Parcourir la source

Implement MQTT device alias support

Christopher Mullins il y a 6 ans
Parent
commit
d4a1d6e9cc
4 fichiers modifiés avec 55 ajouts et 18 suppressions
  1. 41 17
      lib/MQTT/MqttClient.cpp
  2. 1 1
      lib/MQTT/MqttClient.h
  3. 12 0
      lib/Settings/Settings.cpp
  4. 1 0
      lib/Settings/Settings.h

+ 41 - 17
lib/MQTT/MqttClient.cpp

@@ -135,6 +135,7 @@ void MqttClient::subscribe() {
   topic.replace(":dec_device_id", "+");
   topic.replace(":group_id", "+");
   topic.replace(":device_type", "+");
+  topic.replace(":device_alias", "+");
 
 #ifdef MQTT_DEBUG
   printf_P(PSTR("MqttClient - subscribing to topic: %s\n"), topic.c_str());
@@ -184,27 +185,43 @@ void MqttClient::publishCallback(char* topic, byte* payload, int length) {
   TokenIterator topicIterator(topic, strlen(topic), '/');
   UrlTokenBindings tokenBindings(patternIterator, topicIterator);
 
-  if (tokenBindings.hasBinding("device_id")) {
-    deviceId = parseInt<uint16_t>(tokenBindings.get("device_id"));
-  } else if (tokenBindings.hasBinding("hex_device_id")) {
-    deviceId = parseInt<uint16_t>(tokenBindings.get("hex_device_id"));
-  } else if (tokenBindings.hasBinding("dec_device_id")) {
-    deviceId = parseInt<uint16_t>(tokenBindings.get("dec_device_id"));
-  }
-
-  if (tokenBindings.hasBinding("group_id")) {
-    groupId = parseInt<uint16_t>(tokenBindings.get("group_id"));
-  }
+  if (tokenBindings.hasBinding("device_alias")) {
+    String alias = tokenBindings.get("device_alias");
+    auto itr = settings.groupIdAliases.find(alias);
 
-  if (tokenBindings.hasBinding("device_type")) {
-    config = MiLightRemoteConfig::fromType(tokenBindings.get("device_type"));
-
-    if (config == NULL) {
-      Serial.println(F("MqttClient - ERROR: could not extract device_type from topic"));
+    if (itr == settings.groupIdAliases.end()) {
+      Serial.printf_P(PSTR("MqttClient - WARNING: could not find device alias: `%s'. Ignoring packet.\n"), alias.c_str());
       return;
+    } else {
+      BulbId bulbId = itr->second;
+
+      deviceId = bulbId.deviceId;
+      config = MiLightRemoteConfig::fromType(bulbId.deviceType);
+      groupId = bulbId.groupId;
     }
   } else {
-    Serial.println(F("MqttClient - WARNING: could not find device_type token.  Defaulting to FUT092.\n"));
+    if (tokenBindings.hasBinding("device_id")) {
+      deviceId = parseInt<uint16_t>(tokenBindings.get("device_id"));
+    } else if (tokenBindings.hasBinding("hex_device_id")) {
+      deviceId = parseInt<uint16_t>(tokenBindings.get("hex_device_id"));
+    } else if (tokenBindings.hasBinding("dec_device_id")) {
+      deviceId = parseInt<uint16_t>(tokenBindings.get("dec_device_id"));
+    }
+
+    if (tokenBindings.hasBinding("group_id")) {
+      groupId = parseInt<uint16_t>(tokenBindings.get("group_id"));
+    }
+
+    if (tokenBindings.hasBinding("device_type")) {
+      config = MiLightRemoteConfig::fromType(tokenBindings.get("device_type"));
+    } else {
+      Serial.println(F("MqttClient - WARNING: could not find device_type token.  Defaulting to FUT092.\n"));
+    }
+  }
+
+  if (config == NULL) {
+    Serial.println(F("MqttClient - ERROR: unknown device_type specified"));
+    return;
   }
 
   StaticJsonDocument<400> buffer;
@@ -234,6 +251,13 @@ inline void MqttClient::bindTopicString(
   topicPattern.replace(":dec_device_id", String(deviceId));
   topicPattern.replace(":group_id", String(groupId));
   topicPattern.replace(":device_type", remoteConfig.name);
+
+  auto it = settings.findAlias(remoteConfig.type, deviceId, groupId);
+  if (it != settings.groupIdAliases.end()) {
+    topicPattern.replace(":device_alias", it->first);
+  } else {
+    topicPattern.replace(":device_alias", "__unnamed_group");
+  }
 }
 
 String MqttClient::generateConnectionStatusMessage(const char* connectionStatus) {

+ 1 - 1
lib/MQTT/MqttClient.h

@@ -43,7 +43,7 @@ private:
     const bool retain = false
   );
 
-  inline static void bindTopicString(
+  inline void bindTopicString(
     String& topicPattern,
     const MiLightRemoteConfig& remoteConfig,
     const uint16_t deviceId,

+ 12 - 0
lib/Settings/Settings.cpp

@@ -150,6 +150,18 @@ void Settings::patch(JsonObject parsedSettings) {
   }
 }
 
+std::map<String, BulbId>::const_iterator Settings::findAlias(MiLightRemoteType deviceType, uint16_t deviceId, uint8_t groupId) {
+  BulbId searchId{ deviceId, groupId, deviceType };
+
+  for (auto it = groupIdAliases.begin(); it != groupIdAliases.end(); ++it) {
+    if (searchId == it->second) {
+      return it;
+    }
+  }
+
+  return groupIdAliases.end();
+}
+
 void Settings::parseGroupIdAliases(JsonObject json) {
   JsonObject aliases = json["group_id_aliases"];
   groupIdAliases.clear();

+ 1 - 0
lib/Settings/Settings.h

@@ -139,6 +139,7 @@ public:
   void patch(JsonObject obj);
   String mqttServer();
   uint16_t mqttPort();
+  std::map<String, BulbId>::const_iterator findAlias(MiLightRemoteType deviceType, uint16_t deviceId, uint8_t groupId);
 
   String adminUsername;
   String adminPassword;