| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368 |
- // #if defined(ARDUINO) && defined(UNIT_TEST)
- #include <FS.h>
- #include <Arduino.h>
- #include <GroupState.h>
- #include <GroupStateStore.h>
- #include <GroupStateCache.h>
- #include <GroupStatePersistence.h>
- #include <RgbCctPacketFormatter.h>
- #include <FUT091PacketFormatter.h>
- #include <Units.h>
- #include "unity.h"
- //================================================================================
- // Packet formatter
- //================================================================================
- template <typename T>
- void run_packet_test(uint8_t* packet, PacketFormatter* packetFormatter, const BulbId& expectedBulbId, const String& expectedKey, const T expectedValue) {
- GroupStateStore stateStore(10, 0);
- Settings settings;
- RgbCctPacketFormatter formatter;
- DynamicJsonBuffer jsonBuffer;
- JsonObject& result = jsonBuffer.createObject();
- packetFormatter->prepare(0, 0);
- BulbId bulbId = packetFormatter->parsePacket(packet, result);
- TEST_ASSERT_EQUAL_INT_MESSAGE(expectedBulbId.deviceId, bulbId.deviceId, "Should get the expected device ID");
- TEST_ASSERT_EQUAL_INT_MESSAGE(expectedBulbId.groupId, bulbId.groupId, "Should get the expected group ID");
- TEST_ASSERT_EQUAL_INT_MESSAGE(expectedBulbId.deviceType, bulbId.deviceType, "Should get the expected remote type");
- TEST_ASSERT_TRUE_MESSAGE(result.containsKey(expectedKey), "Parsed packet should be for expected command type");
- TEST_ASSERT_TRUE_MESSAGE(result[expectedKey] == expectedValue, "Parsed packet should have expected value");
- }
- void test_fut092_packet_formatter() {
- RgbCctPacketFormatter packetFormatter;
- 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",
- "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",
- 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",
- COLOR_TEMP_MAX_MIREDS
- );
- }
- void test_fut091_packet_formatter() {
- FUT091PacketFormatter packetFormatter;
- uint8_t onPacket[] = {0x00, 0xDC, 0xE1, 0x24, 0x66, 0xCA, 0xBA, 0x66, 0xB5};
- run_packet_test(
- 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",
- 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",
- COLOR_TEMP_MAX_MIREDS
- );
- }
- //================================================================================
- // Group State
- //================================================================================
- GroupState color() {
- GroupState s;
- s.setState(MiLightStatus::ON);
- s.setBulbMode(BulbMode::BULB_MODE_COLOR);
- s.setHue(1);
- s.setSaturation(10);
- s.setBrightness(100);
- return s;
- }
- void test_init_state() {
- GroupState s;
- TEST_ASSERT_EQUAL(s.getBulbMode(), BulbMode::BULB_MODE_WHITE);
- TEST_ASSERT_EQUAL(s.isSetBrightness(), false);
- }
- void test_state_updates() {
- GroupState s = color();
- // Make sure values are packed and unpacked correctly
- TEST_ASSERT_EQUAL(s.getBulbMode(), BulbMode::BULB_MODE_COLOR);
- TEST_ASSERT_EQUAL(s.getBrightness(), 100);
- TEST_ASSERT_EQUAL(s.getHue(), 1);
- TEST_ASSERT_EQUAL(s.getSaturation(), 10);
- // Make sure brightnesses are tied to mode
- s.setBulbMode(BulbMode::BULB_MODE_WHITE);
- s.setBrightness(0);
- TEST_ASSERT_EQUAL(s.getBulbMode(), BulbMode::BULB_MODE_WHITE);
- TEST_ASSERT_EQUAL(s.getBrightness(), 0);
- s.setBulbMode(BulbMode::BULB_MODE_COLOR);
- TEST_ASSERT_EQUAL(s.getBrightness(), 100);
- }
- void test_cache() {
- BulbId id1(1, 1, REMOTE_TYPE_FUT089);
- BulbId id2(1, 2, REMOTE_TYPE_FUT089);
- GroupState s = color();
- s.clearDirty();
- s.clearMqttDirty();
- GroupStateCache cache(1);
- GroupState* storedState = cache.get(id2);
- TEST_ASSERT_NULL_MESSAGE(storedState, "Should not retrieve value which hasn't been stored");
- cache.set(id1, s);
- storedState = cache.get(id1);
- TEST_ASSERT_NOT_NULL_MESSAGE(storedState, "Should retrieve a value");
- TEST_ASSERT_TRUE_MESSAGE(s == *storedState, "State should be the same when retrieved");
- cache.set(id2, s);
- storedState = cache.get(id2);
- TEST_ASSERT_NOT_NULL_MESSAGE(storedState, "Should retrieve a value");
- TEST_ASSERT_TRUE_MESSAGE(s == *storedState, "State should be the same when retrieved");
- storedState = cache.get(id1);
- TEST_ASSERT_NULL_MESSAGE(storedState, "Should evict old entry from cache");
- }
- void test_persistence() {
- BulbId id1(1, 1, REMOTE_TYPE_FUT089);
- BulbId id2(1, 2, REMOTE_TYPE_FUT089);
- GroupStatePersistence persistence;
- persistence.clear(id1);
- persistence.clear(id2);
- GroupState storedState;
- GroupState s = color();
- s.clearDirty();
- s.clearMqttDirty();
- GroupState defaultState = GroupState::defaultState(REMOTE_TYPE_FUT089);
- persistence.get(id1, storedState);
- TEST_ASSERT_TRUE_MESSAGE(storedState.isEqualIgnoreDirty(defaultState), "Should start with clean state");
- persistence.get(id2, storedState);
- TEST_ASSERT_TRUE_MESSAGE(storedState.isEqualIgnoreDirty(defaultState), "Should start with clean state");
- persistence.set(id1, s);
- persistence.get(id2, storedState);
- TEST_ASSERT_TRUE_MESSAGE(storedState.isEqualIgnoreDirty(defaultState), "Should return default for state that hasn't been stored");
- persistence.get(id1, storedState);
- TEST_ASSERT_TRUE_MESSAGE(storedState.isEqualIgnoreDirty(s), "Should retrieve state from flash without modification");
- GroupState newState = s;
- newState.setBulbMode(BulbMode::BULB_MODE_WHITE);
- newState.setBrightness(255);
- persistence.set(id2, newState);
- persistence.get(id1, storedState);
- TEST_ASSERT_TRUE_MESSAGE(storedState.isEqualIgnoreDirty(s), "Should retrieve unmodified state");
- persistence.get(id2, storedState);
- TEST_ASSERT_TRUE_MESSAGE(storedState.isEqualIgnoreDirty(newState), "Should retrieve modified state");
- }
- void test_store() {
- BulbId id1(1, 1, REMOTE_TYPE_FUT089);
- BulbId id2(1, 2, REMOTE_TYPE_FUT089);
- GroupStateStore store(4, 0);
- GroupStatePersistence persistence;
- persistence.clear(id1);
- persistence.clear(id2);
- GroupState initState = color();
- GroupState initState2 = color();
- GroupState defaultState = GroupState::defaultState(REMOTE_TYPE_FUT089);
- initState2.setBrightness(50);
- GroupState* storedState;
- storedState = store.get(id2);
- TEST_ASSERT_TRUE_MESSAGE(*storedState == defaultState, "Should return default for state that hasn't been stored");
- store.set(id1, initState);
- storedState = store.get(id1);
- 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);
- TEST_ASSERT_FALSE_MESSAGE(storedState->isDirty(), "Should not be dirty after flushing");
- TEST_ASSERT_TRUE_MESSAGE(storedState->isEqualIgnoreDirty(initState), "Should return cached state after flushing");
- store.set(id2, defaultState);
- storedState = store.get(id2);
- TEST_ASSERT_TRUE_MESSAGE(storedState->isEqualIgnoreDirty(defaultState), "Should return cached state");
- storedState = store.get(id1);
- TEST_ASSERT_TRUE_MESSAGE(storedState->isEqualIgnoreDirty(initState), "Should return persisted state");
- }
- void test_group_0() {
- BulbId group0Id(1, 0, REMOTE_TYPE_FUT089);
- BulbId id1(1, 1, REMOTE_TYPE_FUT089);
- BulbId id2(1, 2, REMOTE_TYPE_FUT089);
- // cache 1 item, flush immediately
- GroupStateStore store(10, 0);
- GroupStatePersistence persistence;
- persistence.clear(id1);
- persistence.clear(id2);
- GroupState initState = color();
- GroupState initState2 = color();
- GroupState storedState;
- GroupState expectedState;
- GroupState group0State;
- initState2.setBrightness(255);
- group0State.setHue(100);
- store.set(id1, initState);
- store.set(id2, initState2);
- TEST_ASSERT_FALSE_MESSAGE(group0State.isEqualIgnoreDirty(initState), "group0 state should be different than initState");
- TEST_ASSERT_FALSE_MESSAGE(group0State.isEqualIgnoreDirty(initState2), "group0 state should be different than initState2");
- storedState = *store.get(id1);
- TEST_ASSERT_TRUE_MESSAGE(storedState.isEqualIgnoreDirty(initState), "Should fetch persisted state");
- storedState = *store.get(id2);
- TEST_ASSERT_TRUE_MESSAGE(storedState.isEqualIgnoreDirty(initState2), "Should fetch persisted state");
- store.set(group0Id, group0State);
- storedState = *store.get(id1);
- expectedState = initState;
- expectedState.setHue(group0State.getHue());
- TEST_ASSERT_TRUE_MESSAGE(storedState.isEqualIgnoreDirty(expectedState), "Saving group 0 should only update changed field");
- storedState = *store.get(id2);
- expectedState = initState2;
- 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 persisted
- storedState = *store.get(group0Id);
- 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);
- initState2.setHue(100);
- initState.setBrightness(50);
- initState2.setBrightness(70);
- store.set(id1, initState);
- store.set(id2, initState2);
- storedState = *store.get(group0Id);
- storedState.setHue(200);
- TEST_ASSERT_FALSE_MESSAGE(storedState.isSetBrightness(), "Should not have a set field for group 0 brightness");
- store.set(group0Id, storedState);
- storedState = *store.get(id1);
- TEST_ASSERT_TRUE_MESSAGE(storedState.getBrightness() == 50, "UNSET field in group 0 update SHOULD NOT overwrite constituent group field");
- TEST_ASSERT_TRUE_MESSAGE(storedState.getHue() == 200, "SET field in group 0 update SHOULD overwrite constituent group field");
- storedState = *store.get(id2);
- TEST_ASSERT_TRUE_MESSAGE(storedState.getBrightness() == 70, "UNSET field in group 0 update SHOULD NOT overwrite constituent group field");
- TEST_ASSERT_TRUE_MESSAGE(storedState.getHue() == 200, "SET field in group 0 update SHOULD overwrite constituent group field");
- // Should persist group 0 for device types with 0 groups
- BulbId rgbId(1, 0, REMOTE_TYPE_RGB);
- GroupState rgbState = GroupState::defaultState(REMOTE_TYPE_RGB);
- rgbState.setHue(100);
- rgbState.setBrightness(100);
- store.set(rgbId, rgbState);
- store.flush();
- storedState = *store.get(rgbId);
- TEST_ASSERT_TRUE_MESSAGE(storedState.isEqualIgnoreDirty(rgbState), "Should persist group 0 for device type with no groups");
- }
- // setup connects serial, runs test cases (upcoming)
- void setup() {
- delay(2000);
- SPIFFS.begin();
- Serial.begin(9600);
- UNITY_BEGIN();
- RUN_TEST(test_init_state);
- RUN_TEST(test_state_updates);
- RUN_TEST(test_cache);
- RUN_TEST(test_persistence);
- RUN_TEST(test_store);
- RUN_TEST(test_group_0);
- RUN_TEST(test_fut091_packet_formatter);
- RUN_TEST(test_fut092_packet_formatter);
- UNITY_END();
- }
- void loop() {
- // nothing to be done here.
- }
- // #endif
|