Christopher Mullins 7 роки тому
батько
коміт
df3e8da438

+ 4 - 4
lib/MQTT/BulbStateUpdater.cpp

@@ -28,11 +28,11 @@ void BulbStateUpdater::enqueueUpdate(BulbId bulbId, GroupState& groupState) {
 void BulbStateUpdater::loop() {
   while (canFlush() && staleGroups.size() > 0) {
     BulbId bulbId = staleGroups.shift();
-    GroupState& groupState = stateStore.get(bulbId);
+    GroupState* groupState = stateStore.get(bulbId);
 
-    if (groupState.isMqttDirty()) {
-      flushGroup(bulbId, groupState);
-      groupState.clearMqttDirty();
+    if (groupState->isMqttDirty()) {
+      flushGroup(bulbId, *groupState);
+      groupState->clearMqttDirty();
     }
   }
 }

+ 4 - 4
lib/MiLight/CctPacketFormatter.cpp

@@ -48,8 +48,8 @@ void CctPacketFormatter::finalizePacket(uint8_t* packet) {
 }
 
 void CctPacketFormatter::updateBrightness(uint8_t value) {
-  const GroupState& state = this->stateStore->get(deviceId, groupId, MiLightRemoteType::REMOTE_TYPE_CCT);
-  int8_t knownValue = state.isSetBrightness() ? state.getBrightness() : -1;
+  const GroupState* state = this->stateStore->get(deviceId, groupId, MiLightRemoteType::REMOTE_TYPE_CCT);
+  int8_t knownValue = state->isSetBrightness() ? state->getBrightness() : -1;
 
   valueByStepFunction(
     &PacketFormatter::increaseBrightness,
@@ -61,8 +61,8 @@ void CctPacketFormatter::updateBrightness(uint8_t value) {
 }
 
 void CctPacketFormatter::updateTemperature(uint8_t value) {
-  const GroupState& state = this->stateStore->get(deviceId, groupId, MiLightRemoteType::REMOTE_TYPE_CCT);
-  int8_t knownValue = state.isSetKelvin() ? state.getKelvin() : -1;
+  const GroupState* state = this->stateStore->get(deviceId, groupId, MiLightRemoteType::REMOTE_TYPE_CCT);
+  int8_t knownValue = state->isSetKelvin() ? state->getKelvin() : -1;
 
   valueByStepFunction(
     &PacketFormatter::increaseTemperature,

+ 9 - 9
lib/MiLight/FUT089PacketFormatter.cpp

@@ -34,8 +34,8 @@ void FUT089PacketFormatter::updateColorRaw(uint8_t value) {
 // back to the original mode.
 void FUT089PacketFormatter::updateTemperature(uint8_t value) {
   // look up our current mode 
-  GroupState ourState = this->stateStore->get(this->deviceId, this->groupId, REMOTE_TYPE_FUT089);
-  BulbMode originalBulbMode = ourState.getBulbMode();
+  const GroupState* ourState = this->stateStore->get(this->deviceId, this->groupId, REMOTE_TYPE_FUT089);
+  BulbMode originalBulbMode = ourState->getBulbMode();
 
   // are we already in white?  If not, change to white
   if (originalBulbMode != BulbMode::BULB_MODE_WHITE) {
@@ -47,7 +47,7 @@ void FUT089PacketFormatter::updateTemperature(uint8_t value) {
 
   // and return to our original mode
   if ((settings->enableAutomaticModeSwitching) && (originalBulbMode != BulbMode::BULB_MODE_WHITE)) {
-    switchMode(ourState, originalBulbMode);
+    switchMode(*ourState, originalBulbMode);
   }
 }
 
@@ -57,12 +57,12 @@ void FUT089PacketFormatter::updateTemperature(uint8_t value) {
 // and switch back to the original mode.
 void FUT089PacketFormatter::updateSaturation(uint8_t value) {
   // look up our current mode 
-  GroupState ourState = this->stateStore->get(this->deviceId, this->groupId, REMOTE_TYPE_FUT089);
-  BulbMode originalBulbMode = ourState.getBulbMode();
+  const GroupState* ourState = this->stateStore->get(this->deviceId, this->groupId, REMOTE_TYPE_FUT089);
+  BulbMode originalBulbMode = ourState->getBulbMode();
 
   // are we already in color?  If not, we need to flip modes
   if ((settings->enableAutomaticModeSwitching) && (originalBulbMode != BulbMode::BULB_MODE_COLOR)) {
-    updateHue(ourState.getHue());
+    updateHue(ourState->getHue());
   }
 
   // now make the saturation change
@@ -70,7 +70,7 @@ void FUT089PacketFormatter::updateSaturation(uint8_t value) {
 
   // and revert back if necessary
   if ((settings->enableAutomaticModeSwitching) && (originalBulbMode != BulbMode::BULB_MODE_COLOR)) {
-    switchMode(ourState, originalBulbMode);
+    switchMode(*ourState, originalBulbMode);
   }
 }
 
@@ -129,9 +129,9 @@ BulbId FUT089PacketFormatter::parsePacket(const uint8_t *packet, JsonObject& res
   // saturation == kelvin. arg ranges are the same, so can't distinguish
   // without using state
   } else if (command == FUT089_SATURATION) {
-    GroupState& state = stateStore->get(bulbId);
+    const GroupState* state = stateStore->get(bulbId);
 
-    if (state.getBulbMode() == BULB_MODE_COLOR) {
+    if (state != NULL && state->getBulbMode() == BULB_MODE_COLOR) {
       result["saturation"] = 100 - constrain(arg, 0, 100);
     } else {
       result["color_temp"] = Units::whiteValToMireds(100 - arg, 100);

+ 9 - 9
lib/MiLight/RgbCctPacketFormatter.cpp

@@ -46,15 +46,15 @@ void RgbCctPacketFormatter::updateTemperature(uint8_t value) {
   // in white mode, that makes changing temperature annoying because the current hue/mode
   // is lost.  So lookup our current bulb mode, and if needed, reset the hue/mode after
   // changing the temperature
-  GroupState ourState = this->stateStore->get(this->deviceId, this->groupId, REMOTE_TYPE_RGB_CCT);
-  BulbMode originalBulbMode = ourState.getBulbMode();
+  const GroupState* ourState = this->stateStore->get(this->deviceId, this->groupId, REMOTE_TYPE_RGB_CCT);
+  BulbMode originalBulbMode = ourState->getBulbMode();
 
   // now make the temperature change
   command(RGB_CCT_KELVIN, cmdValue);
 
   // and return to our original mode
   if ((settings->enableAutomaticModeSwitching) && (originalBulbMode != BulbMode::BULB_MODE_WHITE)) {
-    switchMode(ourState, originalBulbMode);
+    switchMode(*ourState, originalBulbMode);
   }
 }
 
@@ -62,12 +62,12 @@ void RgbCctPacketFormatter::updateTemperature(uint8_t value) {
 // make the change, and switch back again.
 void RgbCctPacketFormatter::updateSaturation(uint8_t value) {
    // look up our current mode 
-  GroupState ourState = this->stateStore->get(this->deviceId, this->groupId, REMOTE_TYPE_RGB_CCT);
-  BulbMode originalBulbMode = ourState.getBulbMode();
+  const GroupState* ourState = this->stateStore->get(this->deviceId, this->groupId, REMOTE_TYPE_RGB_CCT);
+  BulbMode originalBulbMode = ourState->getBulbMode();
 
   // are we already in white?  If not, change to white
   if ((settings->enableAutomaticModeSwitching) && (originalBulbMode != BulbMode::BULB_MODE_COLOR)) {
-    updateHue(ourState.getHue());
+    updateHue(ourState->getHue());
   }
 
   // now make the saturation change
@@ -75,15 +75,15 @@ void RgbCctPacketFormatter::updateSaturation(uint8_t value) {
   command(RGB_CCT_SATURATION, remapped);
 
   if ((settings->enableAutomaticModeSwitching) && (originalBulbMode != BulbMode::BULB_MODE_COLOR)) {
-    switchMode(ourState, originalBulbMode);
+    switchMode(*ourState, originalBulbMode);
   }
 }
 
 void RgbCctPacketFormatter::updateColorWhite() {
   // there is no direct white command, so let's look up our prior temperature and set that, which
   // causes the bulb to go white 
-  GroupState ourState = this->stateStore->get(this->deviceId, this->groupId, REMOTE_TYPE_RGB_CCT);
-  uint8_t value = V2PacketFormatter::tov2scale(ourState.getKelvin(), RGB_CCT_KELVIN_REMOTE_END, 2);
+  const GroupState* ourState = this->stateStore->get(this->deviceId, this->groupId, REMOTE_TYPE_RGB_CCT);
+  uint8_t value = V2PacketFormatter::tov2scale(ourState->getKelvin(), RGB_CCT_KELVIN_REMOTE_END, 2);
 
   // issue command to set kelvin to prior value, which will drive to white
   command(RGB_CCT_KELVIN, value);

+ 2 - 2
lib/MiLight/RgbPacketFormatter.cpp

@@ -47,8 +47,8 @@ void RgbPacketFormatter::updateColorRaw(uint8_t value) {
 }
 
 void RgbPacketFormatter::updateBrightness(uint8_t value) {
-  const GroupState& state = this->stateStore->get(deviceId, groupId, MiLightRemoteType::REMOTE_TYPE_RGB);
-  int8_t knownValue = state.isSetBrightness() ? state.getBrightness() : -1;
+  const GroupState* state = this->stateStore->get(deviceId, groupId, MiLightRemoteType::REMOTE_TYPE_RGB);
+  int8_t knownValue = state->isSetBrightness() ? state->getBrightness() : -1;
 
   valueByStepFunction(
     &PacketFormatter::increaseBrightness,

+ 2 - 2
lib/MiLight/RgbwPacketFormatter.cpp

@@ -43,8 +43,8 @@ void RgbwPacketFormatter::previousMode() {
 }
 
 uint8_t RgbwPacketFormatter::currentMode() {
-  GroupState& state = stateStore->get(deviceId, groupId, REMOTE_TYPE_RGBW);
-  return state.getMode();
+  const GroupState* state = stateStore->get(deviceId, groupId, REMOTE_TYPE_RGBW);
+  return state->getMode();
 }
 
 void RgbwPacketFormatter::updateMode(uint8_t mode) {

+ 1 - 1
lib/MiLight/V2PacketFormatter.cpp

@@ -82,7 +82,7 @@ uint8_t V2PacketFormatter::groupCommandArg(MiLightStatus status, uint8_t groupId
 }
 
 // helper method to return a bulb to the prior state
-void V2PacketFormatter::switchMode(GroupState currentState, BulbMode desiredMode) {
+void V2PacketFormatter::switchMode(const GroupState& currentState, BulbMode desiredMode) {
   // revert back to the prior mode
   switch (desiredMode) {
     case BulbMode::BULB_MODE_COLOR:

+ 1 - 1
lib/MiLight/V2PacketFormatter.h

@@ -49,7 +49,7 @@ public:
 protected:
   const uint8_t protocolId;
   const uint8_t numGroups;
-  void switchMode(GroupState currentState, BulbMode desiredMode);
+  void switchMode(const GroupState& currentState, BulbMode desiredMode);
 };
 
 #endif

+ 10 - 10
lib/MiLightState/GroupStateStore.cpp

@@ -7,7 +7,7 @@ GroupStateStore::GroupStateStore(const size_t maxSize, const size_t flushRate)
     lastFlush(0)
 { }
 
-GroupState& GroupStateStore::get(const BulbId& id) {
+GroupState* GroupStateStore::get(const BulbId& id) {
   GroupState* state = cache.get(id);
 
   if (state == NULL) {
@@ -25,23 +25,23 @@ GroupState& GroupStateStore::get(const BulbId& id) {
       persistence.get(id, loadedState);
       state = cache.set(id, loadedState);
     } else {
-      state = &loadedState;
+      return NULL;
     }
   }
 
-  return *state;
+  return state;
 }
 
-GroupState& GroupStateStore::get(const uint16_t deviceId, const uint8_t groupId, const MiLightRemoteType deviceType) {
+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.  If id.groupId == 0, will iterate across all groups
 // and individually save each group (recursively)
-GroupState& GroupStateStore::set(const BulbId &id, const GroupState& state) {
-  GroupState& storedState = get(id);
-  storedState = state;
+GroupState* GroupStateStore::set(const BulbId &id, const GroupState& state) {
+  GroupState* storedState = get(id);
+  *storedState = state;
 
   if (id.groupId == 0) {
     const MiLightRemoteConfig* remote = MiLightRemoteConfig::fromType(id.deviceType);
@@ -50,15 +50,15 @@ GroupState& GroupStateStore::set(const BulbId &id, const GroupState& state) {
     for (size_t i = 1; i <= remote->numGroups; i++) {
       individualBulb.groupId = i;
 
-      GroupState& individualState = get(individualBulb);
-      individualState.patch(state);
+      GroupState* individualState = get(individualBulb);
+      individualState->patch(state);
     }
   }
   
   return storedState;
 }
 
-GroupState& GroupStateStore::set(const uint16_t deviceId, const uint8_t groupId, const MiLightRemoteType deviceType, const GroupState& state) {
+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);
 }

+ 9 - 6
lib/MiLightState/GroupStateStore.h

@@ -10,18 +10,21 @@ public:
   GroupStateStore(const size_t maxSize, const size_t flushRate);
 
   /*
-   * Returns the state for the given BulbId.  If no state exists, a suitable
-   * default state will be returned.
+   * Returns the state for the given BulbId.  If accessing state for a valid device
+   * (i.e., NOT group 0) and no state exists, its state will be initialized with a 
+   * default.
+   * 
+   * Otherwise, we return NULL.
    */
-  GroupState& get(const BulbId& id);
-  GroupState& get(const uint16_t deviceId, const uint8_t groupId, const MiLightRemoteType deviceType);
+  GroupState* get(const BulbId& id);
+  GroupState* get(const uint16_t deviceId, const uint8_t groupId, const MiLightRemoteType deviceType);
 
   /*
    * Sets the state for the given BulbId.  State will be marked as dirty and
    * flushed to persistent storage.
    */
-  GroupState& set(const BulbId& id, const GroupState& state);
-  GroupState& set(const uint16_t deviceId, const uint8_t groupId, const MiLightRemoteType deviceType, const GroupState& state);
+  GroupState* set(const BulbId& id, const GroupState& state);
+  GroupState* set(const uint16_t deviceId, const uint8_t groupId, const MiLightRemoteType deviceType, const GroupState& state);
 
   /*
    * Flushes all states to persistent storage.  Returns true iff anything was

+ 7 - 3
lib/WebServer/MiLightHttpServer.cpp

@@ -315,11 +315,15 @@ void MiLightHttpServer::handleListenGateway(const UrlTokenBindings* bindings) {
   server.send(200, "text/plain", response);
 }
 
-void MiLightHttpServer::sendGroupState(BulbId& bulbId, GroupState &state) {
+void MiLightHttpServer::sendGroupState(BulbId& bulbId, GroupState* state) {
   String body;
   StaticJsonBuffer<200> jsonBuffer;
   JsonObject& obj = jsonBuffer.createObject();
-  state.applyState(obj, bulbId, settings.groupStateFields, settings.numGroupStateFields);
+
+  if (state != NULL) {
+    state->applyState(obj, bulbId, settings.groupStateFields, settings.numGroupStateFields);
+  }
+
   obj.printTo(body);
 
   server.send(200, APPLICATION_JSON, body);
@@ -338,7 +342,7 @@ void MiLightHttpServer::handleGetGroup(const UrlTokenBindings* urlBindings) {
   }
 
   BulbId bulbId(parseInt<uint16_t>(_deviceId), _groupId, _remoteType->type);
-  GroupState& state = stateStore->get(bulbId);
+  GroupState* state = stateStore->get(bulbId);
   sendGroupState(bulbId, stateStore->get(bulbId));
 }
 

+ 1 - 1
lib/WebServer/MiLightHttpServer.h

@@ -45,7 +45,7 @@ protected:
   ESP8266WebServer::THandlerFunction handleUpdateFile(const char* filename);
   ESP8266WebServer::THandlerFunction handleServe_P(const char* data, size_t length);
   void applySettings(Settings& settings);
-  void sendGroupState(BulbId& bulbId, GroupState& state);
+  void sendGroupState(BulbId& bulbId, GroupState* state);
 
   void handleUpdateSettings();
   void handleUpdateSettingsPost();

+ 9 - 4
src/main.cpp

@@ -104,9 +104,12 @@ void onPacketSentHandler(uint8_t* packet, const MiLightRemoteConfig& config) {
     *MiLightRemoteConfig::fromType(bulbId.deviceType);
 
   // update state to reflect changes from this packet
-  GroupState& groupState = stateStore->get(bulbId);
-  groupState.patch(result);
-  stateStore->set(bulbId, groupState);
+  GroupState* groupState = stateStore->get(bulbId);
+
+  if (groupState != NULL) {
+    groupState->patch(result);
+    stateStore->set(bulbId, *groupState);
+  }
 
   if (mqttClient) {
     // Sends the state delta derived from the raw packet
@@ -115,7 +118,9 @@ void onPacketSentHandler(uint8_t* packet, const MiLightRemoteConfig& config) {
     mqttClient->sendUpdate(remoteConfig, bulbId.deviceId, bulbId.groupId, output);
 
     // Sends the entire state
-    bulbStateUpdater->enqueueUpdate(bulbId, groupState);
+    if (groupState != NULL) {
+      bulbStateUpdater->enqueueUpdate(bulbId, *groupState);
+    }
   }
 
   httpServer->handlePacketSent(packet, remoteConfig);