Sfoglia il codice sorgente

Merge pull request #50 from sidoh/multi_protocol

Support for sending RF packets to multiple device IDs/RF configs/groups
Chris Mullins 8 anni fa
parent
commit
8a3ebf1419

+ 45 - 14
lib/WebServer/MiLightHttpServer.cpp

@@ -5,6 +5,8 @@
 #include <MiLightHttpServer.h>
 #include <MiLightRadioConfig.h>
 #include <GithubClient.h>
+#include <string.h>
+#include <TokenIterator.h>
 
 void MiLightHttpServer::begin() {
   applySettings(settings);
@@ -315,22 +317,53 @@ void MiLightHttpServer::handleUpdateGroup(const UrlTokenBindings* urlBindings) {
     return;
   }
 
-  const uint16_t deviceId = parseInt<uint16_t>(urlBindings->get("device_id"));
-  const uint8_t groupId = urlBindings->get("group_id").toInt();
-  MiLightRadioConfig* config = MiLightRadioConfig::fromString(urlBindings->get("type"));
-
-  if (config == NULL) {
-    String body = "Unknown device type: ";
-    body += urlBindings->get("type");
-    server.send(400, "text/plain", body);
-    return;
-  }
-
   milightClient->setResendCount(
     settings.httpRepeatFactor * settings.packetRepeats
   );
-  milightClient->prepare(*config, deviceId, groupId);
 
+  String _deviceIds = urlBindings->get("device_id");
+  String _groupIds = urlBindings->get("group_id");
+  String _radioTypes = urlBindings->get("type");
+  char deviceIds[_deviceIds.length()];
+  char groupIds[_groupIds.length()];
+  char radioTypes[_radioTypes.length()];
+  strcpy(radioTypes, _radioTypes.c_str());
+  strcpy(groupIds, _groupIds.c_str());
+  strcpy(deviceIds, _deviceIds.c_str());
+
+  TokenIterator deviceIdItr(deviceIds, _deviceIds.length());
+  TokenIterator groupIdItr(groupIds, _groupIds.length());
+  TokenIterator radioTypesItr(radioTypes, _radioTypes.length());
+
+  while (radioTypesItr.hasNext()) {
+    const char* _radioType = radioTypesItr.nextToken();
+    MiLightRadioConfig* config = MiLightRadioConfig::fromString(_radioType);
+
+    if (config == NULL) {
+      String body = "Unknown device type: ";
+      body += String(_radioType);
+      server.send(400, "text/plain", body);
+      return;
+    }
+
+    deviceIdItr.reset();
+    while (deviceIdItr.hasNext()) {
+      const uint16_t deviceId = parseInt<uint16_t>(deviceIdItr.nextToken());
+
+      groupIdItr.reset();
+      while (groupIdItr.hasNext()) {
+        const uint8_t groupId = atoi(groupIdItr.nextToken());
+
+        milightClient->prepare(*config, deviceId, groupId);
+        handleRequest(request);
+      }
+    }
+  }
+
+  server.send(200, "application/json", "true");
+}
+
+void MiLightHttpServer::handleRequest(const JsonObject& request) {
   if (request.containsKey("status")) {
     const String& statusStr = request.get<String>("status");
     MiLightStatus status = (statusStr == "on" || statusStr == "true") ? ON : OFF;
@@ -404,8 +437,6 @@ void MiLightHttpServer::handleUpdateGroup(const UrlTokenBindings* urlBindings) {
   }
 
   milightClient->setResendCount(settings.packetRepeats);
-
-  server.send(200, "application/json", "true");
 }
 
 void MiLightHttpServer::handleSendRaw(const UrlTokenBindings* bindings) {

+ 15 - 13
lib/WebServer/MiLightHttpServer.h

@@ -3,7 +3,7 @@
 #include <Settings.h>
 
 #ifndef _MILIGHT_HTTP_SERVER
-#define _MILIGHT_HTTP_SERVER 
+#define _MILIGHT_HTTP_SERVER
 
 #define MAX_DOWNLOAD_ATTEMPTS 3
 
@@ -18,24 +18,24 @@ public:
     : server(WebServer(80)),
       milightClient(milightClient),
       settings(settings)
-  { 
+  {
     this->applySettings(settings);
   }
-  
+
   void begin();
   void handleClient();
   void onSettingsSaved(SettingsSavedHandler handler);
-  
+
 protected:
   ESP8266WebServer::THandlerFunction handleServeFile(
-    const char* filename, 
-    const char* contentType, 
-    const char* defaultText = NULL); 
-    
+    const char* filename,
+    const char* contentType,
+    const char* defaultText = NULL);
+
   bool serveFile(const char* file, const char* contentType = "text/html");
   ESP8266WebServer::THandlerFunction handleUpdateFile(const char* filename);
   void applySettings(Settings& settings);
-  
+
   void handleUpdateSettings();
   void handleGetRadioConfigs();
   void handleAbout();
@@ -45,14 +45,16 @@ protected:
   void handleSendRaw(const UrlTokenBindings* urlBindings);
   void handleUpdateGroup(const UrlTokenBindings* urlBindings);
   void handleDownloadUpdate(const UrlTokenBindings* urlBindings);
-  
+
+  void handleRequest(const JsonObject& request);
+
   File updateFile;
-  
+
   WebServer server;
   Settings& settings;
   MiLightClient*& milightClient;
   SettingsSavedHandler settingsSavedHandler;
-  
+
 };
 
-#endif
+#endif

+ 51 - 0
lib/WebServer/TokenIterator.cpp

@@ -0,0 +1,51 @@
+#include <TokenIterator.h>
+
+TokenIterator::TokenIterator(char* data, size_t length, const char sep)
+  : data(data),
+    current(data),
+    length(length),
+    sep(sep),
+    i(0)
+{
+  for (size_t i = 0; i < length; i++) {
+    if (data[i] == sep) {
+      data[i] = 0;
+    }
+  }
+}
+
+const char* TokenIterator::nextToken() {
+  if (i >= length) {
+    return NULL;
+  }
+
+  char* token = current;
+  char* nextToken = current;
+
+  for (; i < length && *nextToken != 0; i++, nextToken++);
+
+  if (i == length) {
+    nextToken = NULL;
+  } else {
+    i = (nextToken - data);
+
+    if (i < length) {
+      nextToken++;
+    } else {
+      nextToken = NULL;
+    }
+  }
+
+  current = nextToken;
+
+  return token;
+}
+
+void TokenIterator::reset() {
+  current = data;
+  i = 0;
+}
+
+bool TokenIterator::hasNext() {
+  return i < length;
+}

+ 20 - 0
lib/WebServer/TokenIterator.h

@@ -0,0 +1,20 @@
+#include <Arduino.h>
+
+#ifndef _TOKEN_ITERATOR_H
+#define _TOKEN_ITERATOR_H value
+class TokenIterator {
+public:
+  TokenIterator(char* data, size_t length, char sep = ',');
+
+  bool hasNext();
+  const char* nextToken();
+  void reset();
+
+private:
+  char* data;
+  char* current;
+  size_t length;
+  char sep;
+  int i;
+};
+#endif