| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135 |
- #include <GroupStateStore.h>
- #include <MiLightRemoteConfig.h>
- GroupStateStore::GroupStateStore(const size_t maxSize, const size_t flushRate)
- : cache(GroupStateCache(maxSize)),
- flushRate(flushRate),
- lastFlush(0)
- { }
- GroupState* GroupStateStore::get(const BulbId& id) {
- GroupState* state = cache.get(id);
- if (state == NULL) {
- #if STATE_DEBUG
- Serial.println(F("Couldn't fetch state from cache, getting it from persistence"));
- #endif
- trackEviction();
- GroupState loadedState = GroupState::defaultState(id.deviceType);
- const MiLightRemoteConfig* remoteConfig = MiLightRemoteConfig::fromType(id.deviceType);
- if (remoteConfig == NULL) {
- return NULL;
- }
- persistence.get(id, loadedState);
- state = cache.set(id, loadedState);
- }
- return state;
- }
- GroupState* GroupStateStore::get(const uint16_t deviceId, const uint8_t groupId, const MiLightRemoteType deviceType) {
- BulbId bulbId(deviceId, groupId, deviceType);
- return get(bulbId);
- }
- // Save state for a bulb.
- //
- // 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
- // 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)
- //
- GroupState* GroupStateStore::set(const BulbId &id, const GroupState& state) {
- BulbId otherId(id);
- GroupState* storedState = get(id);
- storedState->patch(state);
- if (id.groupId == 0) {
- const MiLightRemoteConfig* remote = MiLightRemoteConfig::fromType(id.deviceType);
- #ifdef STATE_DEBUG
- Serial.printf_P(PSTR("Fanning out group 0 state for device ID 0x%04X (%d groups in total)\n"), id.deviceId, remote->numGroups);
- state.debugState("group 0 state = ");
- #endif
- for (size_t i = 1; i <= remote->numGroups; i++) {
- otherId.groupId = i;
- GroupState* individualState = get(otherId);
- individualState->patch(state);
- }
- } else {
- otherId.groupId = 0;
- GroupState* group0State = get(otherId);
- group0State->clearNonMatchingFields(state);
- }
-
- return storedState;
- }
- GroupState* GroupStateStore::set(const uint16_t deviceId, const uint8_t groupId, const MiLightRemoteType deviceType, const GroupState& state) {
- BulbId bulbId(deviceId, groupId, deviceType);
- return set(bulbId, state);
- }
- void GroupStateStore::clear(const BulbId& bulbId) {
- GroupState* state = get(bulbId);
- if (state != NULL) {
- state->initFields();
- }
- }
- void GroupStateStore::trackEviction() {
- if (cache.isFull()) {
- evictedIds.add(cache.getLru());
- }
- }
- bool GroupStateStore::flush() {
- ListNode<GroupCacheNode*>* curr = cache.getHead();
- bool anythingFlushed = false;
- while (curr != NULL && curr->data->state.isDirty() && !anythingFlushed) {
- persistence.set(curr->data->id, curr->data->state);
- curr->data->state.clearDirty();
- #ifdef STATE_DEBUG
- BulbId bulbId = curr->data->id;
- printf(
- "Flushing dirty state for 0x%04X / %d / %s\n",
- bulbId.deviceId,
- bulbId.groupId,
- MiLightRemoteConfig::fromType(bulbId.deviceType)->name.c_str()
- );
- #endif
- curr = curr->next;
- anythingFlushed = true;
- }
- while (evictedIds.size() > 0 && !anythingFlushed) {
- persistence.clear(evictedIds.shift());
- anythingFlushed = true;
- }
- return anythingFlushed;
- }
- void GroupStateStore::limitedFlush() {
- unsigned long now = millis();
- if ((lastFlush + flushRate) < now) {
- if (flush()) {
- lastFlush = now;
- }
- }
- }
|