Skip to content

Commit

Permalink
Merge branch '1.9.0' of github.com:sidoh/esp8266_milight_hub into 1.9.0
Browse files Browse the repository at this point in the history
  • Loading branch information
sidoh committed Apr 22, 2019
2 parents 954fe6c + 0e63c2d commit 3e2a151
Show file tree
Hide file tree
Showing 5 changed files with 102 additions and 40 deletions.
11 changes: 7 additions & 4 deletions lib/MiLightState/GroupState.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,13 @@ static const char* BULB_MODE_NAMES[] = {

const BulbId DEFAULT_BULB_ID;
static const GroupStateField ALL_PHYSICAL_FIELDS[] = {
GroupStateField::BRIGHTNESS,
GroupStateField::BULB_MODE,
GroupStateField::HUE,
GroupStateField::KELVIN,
GroupStateField::MODE,
GroupStateField::SATURATION,
GroupStateField::STATE
GroupStateField::STATE,
GroupStateField::BRIGHTNESS
};

static const GroupStateField ALL_SCRATCH_FIELDS[] = {
Expand Down Expand Up @@ -549,7 +549,9 @@ bool GroupState::setMireds(uint16_t mireds) {
return setKelvin(Units::miredsToWhiteVal(mireds, 100));
}

bool GroupState::isSetBulbMode() const { return state.fields._isSetBulbMode; }
bool GroupState::isSetBulbMode() const {
return (isSetNightMode() && isNightMode()) || state.fields._isSetBulbMode;
}
BulbMode GroupState::getBulbMode() const {
// Night mode is a transient state. When power is toggled, the bulb returns
// to the state it was last in. To handle this case, night mode state is
Expand Down Expand Up @@ -944,7 +946,7 @@ void GroupState::debugState(char const *debugMessage) const {

// define fields to show (if count changes, make sure to update count to applyState below)
GroupStateField fields[] {
GroupStateField::BRIGHTNESS,
GroupStateField::LEVEL,
GroupStateField::BULB_MODE,
GroupStateField::COLOR_TEMP,
GroupStateField::EFFECT,
Expand All @@ -968,6 +970,7 @@ void GroupState::debugState(char const *debugMessage) const {
Serial.printf("%s: ", debugMessage);
jsonState.printTo(Serial);
Serial.println("");
Serial.printf("Raw data: %08X %08X\n", state.rawData[0], state.rawData[1]);
#endif
}

Expand Down
23 changes: 19 additions & 4 deletions lib/MiLightState/GroupStateStore.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,12 @@ GroupState* GroupStateStore::get(const BulbId& id) {

if (state == NULL) {
#if STATE_DEBUG
Serial.println(F("Couldn't fetch state from cache, getting it from persistence"));
printf(
"Couldn't fetch state for 0x%04X / %d / %s in the cache, getting it from persistence\n",
id.deviceId,
id.groupId,
MiLightRemoteConfig::fromType(id.deviceType)->name.c_str()
);
#endif
trackEviction();
GroupState loadedState = GroupState::defaultState(id.deviceType);
Expand All @@ -39,8 +44,8 @@ GroupState* GroupStateStore::get(const uint16_t deviceId, const uint8_t groupId,
//
// Notes:
//
// * For device types with groups, group 0 is a "virtual" group. All devices paired with the same ID will
// respond to group 0. When state for an individual (i.e., != 0) group is changed, the state for
// * For device types with groups, group 0 is a "virtual" group. All devices paired with the same ID will
// respond to group 0. When state for an individual (i.e., != 0) group is changed, the state for
// group 0 becomes out of sync and should be cleared.
//
// * If id.groupId == 0, will iterate across all groups and individually save each group (recursively)
Expand Down Expand Up @@ -70,7 +75,7 @@ GroupState* GroupStateStore::set(const BulbId &id, const GroupState& state) {

group0State->clearNonMatchingFields(state);
}

return storedState;
}

Expand All @@ -90,6 +95,16 @@ void GroupStateStore::clear(const BulbId& bulbId) {
void GroupStateStore::trackEviction() {
if (cache.isFull()) {
evictedIds.add(cache.getLru());

#ifdef STATE_DEBUG
BulbId bulbId = evictedIds.getLast();
printf(
"Evicting from cache: 0x%04X / %d / %s\n",
bulbId.deviceId,
bulbId.groupId,
MiLightRemoteConfig::fromType(bulbId.deviceType)->name.c_str()
);
#endif
}
}

Expand Down
6 changes: 6 additions & 0 deletions platformio.ini
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ lib_deps_external =
CircularBuffer@~1.2.0
extra_scripts =
pre:.build_web.py
test_ignore = remote
build_flags = !python .get_version.py -DMQTT_MAX_PACKET_SIZE=250 -DHTTP_UPLOAD_BUFLEN=128 -D FIRMWARE_NAME=milight-hub -Idist -Ilib/DataStructures
# -D STATE_DEBUG
# -D DEBUG_PRINTF
Expand All @@ -41,6 +42,7 @@ extra_scripts = ${common.extra_scripts}
lib_deps =
${common.lib_deps_builtin}
${common.lib_deps_external}
test_ignore = ${common.test_ignore}

[env:d1_mini]
platform = ${common.platform}
Expand All @@ -51,6 +53,7 @@ extra_scripts = ${common.extra_scripts}
lib_deps =
${common.lib_deps_builtin}
${common.lib_deps_external}
test_ignore = ${common.test_ignore}

[env:esp12]
platform = ${common.platform}
Expand All @@ -61,6 +64,7 @@ extra_scripts = ${common.extra_scripts}
lib_deps =
${common.lib_deps_builtin}
${common.lib_deps_external}
test_ignore = ${common.test_ignore}

[env:esp07]
platform = ${common.platform}
Expand All @@ -71,6 +75,7 @@ extra_scripts = ${common.extra_scripts}
lib_deps =
${common.lib_deps_builtin}
${common.lib_deps_external}
test_ignore = ${common.test_ignore}

[env:huzzah]
platform = ${common.platform}
Expand All @@ -81,3 +86,4 @@ extra_scripts = ${common.extra_scripts}
lib_deps =
${common.lib_deps_builtin}
${common.lib_deps_external}
test_ignore = ${common.test_ignore}
62 changes: 30 additions & 32 deletions test/d1_mini/test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,28 +42,28 @@ void test_fut092_packet_formatter() {

uint8_t onPacket[] = {0x00, 0xDB, 0xE1, 0x24, 0x66, 0xCA, 0x54, 0x66, 0xD2};
run_packet_test(
onPacket,
&packetFormatter,
BulbId(1, 1, REMOTE_TYPE_RGB_CCT),
"state",
onPacket,
&packetFormatter,
BulbId(1, 1, REMOTE_TYPE_RGB_CCT),
"state",
"OFF"
);

uint8_t minColorTempPacket[] = {0x00, 0xDB, 0xE1, 0x24, 0x64, 0x3C, 0x47, 0x66, 0x31};
run_packet_test(
minColorTempPacket,
&packetFormatter,
BulbId(1, 1, REMOTE_TYPE_RGB_CCT),
"color_temp",
minColorTempPacket,
&packetFormatter,
BulbId(1, 1, REMOTE_TYPE_RGB_CCT),
"color_temp",
COLOR_TEMP_MIN_MIREDS
);

uint8_t maxColorTempPacket[] = {0x00, 0xDB, 0xE1, 0x24, 0x64, 0x94, 0x62, 0x66, 0x88};
run_packet_test(
maxColorTempPacket,
&packetFormatter,
BulbId(1, 1, REMOTE_TYPE_RGB_CCT),
"color_temp",
maxColorTempPacket,
&packetFormatter,
BulbId(1, 1, REMOTE_TYPE_RGB_CCT),
"color_temp",
COLOR_TEMP_MAX_MIREDS
);
}
Expand All @@ -73,28 +73,28 @@ void test_fut091_packet_formatter() {

uint8_t onPacket[] = {0x00, 0xDC, 0xE1, 0x24, 0x66, 0xCA, 0xBA, 0x66, 0xB5};
run_packet_test(
onPacket,
&packetFormatter,
BulbId(1, 1, REMOTE_TYPE_FUT091),
"state",
onPacket,
&packetFormatter,
BulbId(1, 1, REMOTE_TYPE_FUT091),
"state",
"OFF"
);

uint8_t minColorTempPacket[] = {0x00, 0xDC, 0xE1, 0x24, 0x64, 0x8D, 0xB9, 0x66, 0x71};
run_packet_test(
minColorTempPacket,
&packetFormatter,
BulbId(1, 1, REMOTE_TYPE_FUT091),
"color_temp",
minColorTempPacket,
&packetFormatter,
BulbId(1, 1, REMOTE_TYPE_FUT091),
"color_temp",
COLOR_TEMP_MIN_MIREDS
);

uint8_t maxColorTempPacket[] = {0x00, 0xDC, 0xE1, 0x24, 0x64, 0x55, 0xB7, 0x66, 0x27};
run_packet_test(
maxColorTempPacket,
&packetFormatter,
BulbId(1, 1, REMOTE_TYPE_FUT091),
"color_temp",
maxColorTempPacket,
&packetFormatter,
BulbId(1, 1, REMOTE_TYPE_FUT091),
"color_temp",
COLOR_TEMP_MAX_MIREDS
);
}
Expand All @@ -108,9 +108,9 @@ GroupState color() {

s.setState(MiLightStatus::ON);
s.setBulbMode(BulbMode::BULB_MODE_COLOR);
s.setBrightness(100);
s.setHue(1);
s.setSaturation(10);
s.setBrightness(100);

return s;
}
Expand Down Expand Up @@ -220,8 +220,7 @@ void test_store() {
BulbId id1(1, 1, REMOTE_TYPE_FUT089);
BulbId id2(1, 2, REMOTE_TYPE_FUT089);

// cache 1 item, flush immediately
GroupStateStore store(1, 0);
GroupStateStore store(4, 0);
GroupStatePersistence persistence;

persistence.clear(id1);
Expand All @@ -230,7 +229,7 @@ void test_store() {
GroupState initState = color();
GroupState initState2 = color();
GroupState defaultState = GroupState::defaultState(REMOTE_TYPE_FUT089);
initState2.setBrightness(255);
initState2.setBrightness(50);

GroupState* storedState;

Expand All @@ -240,7 +239,7 @@ void test_store() {
store.set(id1, initState);
storedState = store.get(id1);

TEST_ASSERT_TRUE_MESSAGE(*storedState == initState, "Should return cached state");
TEST_ASSERT_TRUE_MESSAGE(storedState->isEqualIgnoreDirty(initState), "Should return stored state. Will not be cached because of internal group 0 lookups");

store.flush();
storedState = store.get(id1);
Expand Down Expand Up @@ -269,7 +268,6 @@ void test_group_0() {

GroupState initState = color();
GroupState initState2 = color();
GroupState defaultState = GroupState::defaultState(REMOTE_TYPE_FUT089);
GroupState storedState;
GroupState expectedState;
GroupState group0State;
Expand Down Expand Up @@ -302,9 +300,9 @@ void test_group_0() {
expectedState.setHue(group0State.getHue());
TEST_ASSERT_TRUE_MESSAGE(storedState.isEqualIgnoreDirty(expectedState), "Saving group 0 should only update changed field");

// Test that state for group 0 is not persisted
// Test that state for group 0 is persisted
storedState = *store.get(group0Id);
TEST_ASSERT_TRUE_MESSAGE(storedState.isEqualIgnoreDirty(defaultState), "Group 0 state should not be stored -- should return default state");
TEST_ASSERT_TRUE_MESSAGE(storedState.isEqualIgnoreDirty(group0State), "Group 0 state should not be stored -- should return default state");

// Test that states for constituent groups are properly updated
initState.setHue(0);
Expand Down
40 changes: 40 additions & 0 deletions test/remote/spec/state_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,46 @@
end
end

context 'night mode command' do
it 'should affect state when bulb is off' do
state = @client.patch_state({'command' => 'night_mode'}, @id_params)

expect(state['bulb_mode']).to eq('night')
expect(state['effect']).to eq('night_mode')
end

it 'should affect state when bulb is on' do
@client.patch_state({'status' => 'ON'}, @id_params)
state = @client.patch_state({'command' => 'night_mode'}, @id_params)

expect(state['status']).to eq('ON')
expect(state['bulb_mode']).to eq('night')
expect(state['effect']).to eq('night_mode')
end

it 'should revert to previous mode when status is toggled' do
@client.patch_state({'status' => 'ON', 'kelvin' => 100}, @id_params)
state = @client.patch_state({'command' => 'night_mode'}, @id_params)

expect(state['effect']).to eq('night_mode')

state = @client.patch_state({'status' => 'OFF'}, @id_params)

expect(state['bulb_mode']).to eq('white')
expect(state['kelvin']).to eq(100)

@client.patch_state({'status' => 'ON', 'hue' => 0}, @id_params)
state = @client.patch_state({'command' => 'night_mode'}, @id_params)

expect(state['effect']).to eq('night_mode')

state = @client.patch_state({'status' => 'OFF'}, @id_params)

expect(state['bulb_mode']).to eq('color')
expect(state['hue']).to eq(0)
end
end

context 'deleting' do
it 'should support deleting state' do
desired_state = {
Expand Down

0 comments on commit 3e2a151

Please sign in to comment.