Toby Chui 6 tháng trước cách đây
mục cha
commit
b78161b044

+ 2 - 2
hardware/hds_4-way-relay/firmware/4xrelay/4xrelay.ino

@@ -20,7 +20,7 @@
 #include <ESP8266WebServer.h>
 #include "LittleFS.h"
 
-// Device Configs, required by HDSv2
+// Device Configs, required by HDSv3
 #define DEVICE_NAME "hds_4xRelay"    //The name of this IoT device
 #define LISTENING_PORT 12110        //The port where this IoT device listen
 String deviceUUID = ""; //Device UUID is generated base on devcie MAC address
@@ -86,7 +86,7 @@ void setup() {
   digitalWrite(RELAY_4, LOW);
 
   //Start HDSv2 services
-  initHds2Services();
+  initHds3Services();
 }
 
 void loop() {

+ 2 - 2
hardware/hds_4-way-relay/firmware/4xrelay/hdsv3.ino

@@ -16,8 +16,8 @@ void hostProbeResult(String p_pcDomainName, bool p_bProbeResult) {
   MDNS.setDynamicServiceTxtCallback(MDNSDynamicServiceTxtCallback);
 }
 
-//Start all HDSv2 required services
-void initHds2Services() {
+//Start all HDSv3 required services
+void initHds3Services() {
   // Connect to Wi-Fi
   Serial.println("Starting WiFi Manager");
   wifiManager.setClass("invert");

+ 46 - 53
hardware/hds_5-way-switch/firmware/5xswitches/5xswitches.ino

@@ -8,31 +8,21 @@
       Author: tobychui
 */
 
-/*
- * 
- *  DEVICE SETTINGS
- *  
- *  Update the configurations below before flashing the firmware to
- *  your HDSv3 devices
- * 
- */
-
-//Mesh settings (for HDSv3)
-#define   MESH_PREFIX     "homedynamicv3"
-#define   MESH_PASSWORD   "verySecurePassword"
-#define   MESH_PORT       9640
-
-//Change these to fit your needs
-uint32_t TARGET_RELAY = 3664199101;
-
-/*
- * 
- *  END OF DEVICE SETTINGS
- * 
- */
-
-//Mesh networking
-#include "painlessMesh.h"
+#include <WiFiManager.h>
+#include <ArduinoJson.h>
+#include <ESP8266WiFi.h>
+#include <ESP8266mDNS.h>
+#include <ESP8266WebServer.h>
+#include <ESP8266HTTPClient.h>
+#include "TaskScheduler.h"
+#include "LittleFS.h"
+
+// Device Configs, required by HDSv3
+#define DEVICE_NAME "hds_5xSwitch"    //The name of this IoT device
+#define SETUP_WIFI_NAME "hds_5xSwitch"
+#define LISTENING_PORT 12110        //The port where this IoT device listen
+#define DEBUG true
+String deviceUUID = ""; //Device UUID is generated base on devcie MAC address
 
 // Output shift register pints
 const int SRCLK_PIN = D7;
@@ -44,30 +34,33 @@ bool buttonStates[5] = {false, false, false, false, false};
 const int buttonPins[] = {D4, D6, D5, D0, A0};
 const int numButtons = 5;
 
+//Modify these two control other devices
+#define TARGET_DEVICE "hds_4xRelay_48-3F-DA-67-3D-BD.local"
+IPAddress target_ip;
+uint16_t target_port = 0;
+
+
 // Status led
 #define BLINK_DURATION 100
 bool blueLED = false;
 bool yellowLED = false;
 bool redLED = false;
 
-
 //Runtimes
 Scheduler deviceScheduler;
-painlessMesh  mesh;
 
-//System Tasks
-void updateButtonStates();
-void buttonPressCallbacks();
-void sendMessage();
-void handleSignalLEDBlinks();
-Task taskButtons(10, TASK_FOREVER, &buttonPressCallbacks);
-Task taskSendMessage( TASK_SECOND * 1 , TASK_FOREVER, &sendMessage );
-Task taskLEDsBlink( BLINK_DURATION * TASK_MILLISECOND , 2, &handleSignalLEDBlinks );
+//WiFi Related
+WiFiManager wifiManager;
+ESP8266WebServer server(LISTENING_PORT);
 
 void setup() {
   //Enable debug Serial
   Serial.begin(115200);
 
+  //Load device UUID
+  deviceUUID = WiFi.macAddress();
+  deviceUUID.replace(":", "-");
+
   // Initialize shift register pins
   pinMode(SRCLK_PIN, OUTPUT);
   pinMode(RCLK_PIN, OUTPUT);
@@ -81,25 +74,25 @@ void setup() {
   //Reset the state of all LEDs
   resetOutputs();
 
-  //Start mesh networking
-  mesh.setDebugMsgTypes( ERROR | STARTUP );  // set before init() so that you can see startup messages
-  
-  mesh.init( MESH_PREFIX, MESH_PASSWORD, &deviceScheduler, MESH_PORT );
-  mesh.onReceive(&receivedCallback);
-  mesh.onNewConnection(&newConnectionCallback);
-  mesh.onChangedConnections(&changedConnectionCallback);
-  mesh.onNodeTimeAdjusted(&nodeTimeAdjustedCallback);
-  
-  //Add tasks to scheduler
-  deviceScheduler.addTask(taskSendMessage);
-  deviceScheduler.addTask(taskButtons);
-  deviceScheduler.addTask(taskLEDsBlink);
-
-  //Enable tasks
-  taskSendMessage.enable();
-  taskButtons.enable();
+  //Start HDSv3 services
+  initHds3Services();
+
+  //Start discovering the target devices ip
+  resolveTargetRelayIP();
 }
 
 void loop() {
-  mesh.update();
+  //Handle web-ish things
+  server.handleClient();
+  MDNS.update();
+  //Update and Execute Button Events
+  updateButtonStates();
+  updateShiftRegister();
+
+  //Show yellow warning LED if target not found
+  if (target_port == 0){
+    yellowLED = true;
+  }else{
+    yellowLED = false;
+  }
 }

+ 18 - 6
hardware/hds_5-way-switch/firmware/5xswitches/buttons.ino

@@ -1,8 +1,3 @@
-void buttonPressCallbacks() {
-  updateButtonStates();
-  updateShiftRegister();
-}
-
 void updateButtonStates() {
   // Read the state of each button and update the boolean array
   bool pressed = false;
@@ -60,9 +55,26 @@ void resetOutputs() {
 
 //Handle button down and up events, index start from 0
 void handleButtonDown(int index) {
-
+  
 }
 
 void handleButtonUp(int index) {
+  //Generate the base URL from ip and port
+  String baseURL = "http://" + target_ip.toString() + ":" + String(target_port);
+  if (index == 0){
+     baseURL += "/toggle?relay=0";
+  }else if (index == 1){
+    baseURL += "/toggle?relay=1";
+  }else if (index == 2){
+    baseURL += "/toggle?relay=2";
+  }else if (index == 3){
+    baseURL += "/toggle?relay=3";
+  }else if (index == 4){
+    resolveTargetRelayIP();
+    return;
+  }
+
+  Serial.println("Sending request to: " + baseURL);
+  GetRequest(baseURL);
 
 }

+ 47 - 0
hardware/hds_5-way-switch/firmware/5xswitches/data/config.json

@@ -0,0 +1,47 @@
+{
+    "info":{
+      "name":"4 Ways Relay Module",
+      "vendor": "imuslab",
+      "mcu":"esp12F",
+      "firmware":"1.0.0",
+      "author":"tobychui"
+    },
+    "api":[
+    {
+      "id":"relay1",
+      "name": "Channel 1",
+      "actions": {
+        "on":"/on?relay=0",
+        "off":"/off?relay=0",
+        "toggle":"/toggle?relay=0"
+      }
+    },
+    {
+      "id":"relay2",
+      "name": "Channel 2",
+      "actions": {
+        "on":"/on?relay=1",
+        "off":"/off?relay=1",
+        "toggle":"/toggle?relay=1"
+      }
+    },
+    {
+      "id":"relay3",
+      "name": "Channel 3",
+     "actions": {
+        "on":"/on?relay=2",
+        "off":"/off?relay=2",
+        "toggle":"/toggle?relay=2"
+      }
+    },
+    {
+      "id":"relay4",
+      "name": "Channel 4",
+      "actions": {
+        "on":"/on?relay=3",
+        "off":"/off?relay=3",
+        "toggle":"/toggle?relay=3"
+      }
+    }
+  ]
+  }

+ 39 - 0
hardware/hds_5-way-switch/firmware/5xswitches/endpoints.ino

@@ -0,0 +1,39 @@
+//Handlers for Web Server
+void handle_index() {
+  server.send(200, "text/html", "[OK] - hds 4-way relay module");
+}
+
+void handle_status() {
+  DynamicJsonDocument doc(256);
+  //doc["relay1"] = relayStatus[0] ? true : false;
+  //doc["relay2"] = relayStatus[1] ? true : false;
+  //doc["relay3"] = relayStatus[2] ? true : false;
+  //doc["relay4"] = relayStatus[3] ? true : false;
+
+  String json;
+  serializeJson(doc, json);
+  server.send(200, "application/json", json.c_str());
+}
+
+
+void handle_deviceInfo() {
+  // Open the file in read mode
+  File file = LittleFS.open("/config.json", "r");
+
+  if (!file) {
+    // If the file doesn't exist, send a 404 Not Found response
+    server.send(404, "application/json", "{\"error\":\"device config missing from firmware\"}");
+    return;
+  }
+
+  String fileContent = "";
+  while (file.available()) {
+    fileContent += (char)file.read();
+  }
+  file.close();
+  server.send(200, "application/json", fileContent);
+}
+
+void handle_uuid() {
+  server.send(200, "application/json", "\"" + deviceUUID + "\"");
+}

+ 105 - 0
hardware/hds_5-way-switch/firmware/5xswitches/hdsv3.ino

@@ -0,0 +1,105 @@
+/*
+
+   HDSv3 functions require the following library
+   to be included in the main sketch
+
+
+  #include <WiFiManager.h>
+  #include <ArduinoJson.h>
+  #include <ESP8266WiFi.h>
+  #include <ESP8266mDNS.h>
+  #include <ESP8266WebServer.h>
+
+*/
+
+/*
+   mDNS Probing and Broadcast
+*/
+//Inject zeroconf attr into the MDNS respond (For scanning by ArozOS)
+void MDNSDynamicServiceTxtCallback(const MDNSResponder::hMDNSService p_hService) {
+  //Define the domain of the HDSv2 devices
+  MDNS.addDynamicServiceTxt(p_hService, "domain", "hds.imuslab.com");
+  MDNS.addDynamicServiceTxt(p_hService, "protocol", "hdsv3");
+
+  //Define the OEM written values
+  MDNS.addDynamicServiceTxt(p_hService, "uuid", deviceUUID.c_str());
+  MDNS.addDynamicServiceTxt(p_hService, "name", (String(DEVICE_NAME) + "_" + deviceUUID).c_str());
+  MDNS.addDynamicServiceTxt(p_hService, "model", DEVICE_NAME);
+  MDNS.addDynamicServiceTxt(p_hService, "vendor", "imuslab");
+  MDNS.addDynamicServiceTxt(p_hService, "version", "1.00");
+}
+
+void hostProbeResult(String p_pcDomainName, bool p_bProbeResult) {
+  MDNS.setDynamicServiceTxtCallback(MDNSDynamicServiceTxtCallback);
+}
+
+/*
+ *  mDNS Resolver (new in HDSv3)
+ */
+bool resolveMdnsService(char* service_name, char* protocol, char* desired_host, IPAddress* ip_addr, uint16_t *port_number) {
+  Serial.println("Sending mDNS query");
+  int n = MDNS.queryService(service_name, protocol);
+  Serial.printf("mDNS query got %d results\n", n);
+
+  if (n == 0) {
+    Serial.println("no services found");
+  } else {
+    for (int i = 0; i < n; ++i) {
+#ifdef DEBUG
+      Serial.print(i + 1);
+      Serial.print(": ");
+      Serial.print(MDNS.hostname(i));
+      Serial.print(" (");
+      Serial.print(MDNS.IP(i));
+      Serial.print(":");
+      Serial.print(MDNS.port(i));
+      Serial.println(")");
+#endif
+
+      if (strcmp(MDNS.hostname(i).c_str(), desired_host) == 0) {
+        *ip_addr = MDNS.IP(i);
+        *port_number = MDNS.port(i);
+        return true;
+      }
+    }
+  }
+
+  return false;
+}
+
+
+//Start all HDSv2 required services
+void initHds3Services() {
+  // Connect to Wi-Fi
+  Serial.println("Starting WiFi Manager");
+  wifiManager.setClass("invert");
+  wifiManager.autoConnect(SETUP_WIFI_NAME);
+  Serial.print("Connected to ");
+  Serial.println(WiFi.SSID());
+  Serial.print("IP address:\t");
+  Serial.println(WiFi.localIP());
+
+
+  //Startup MDNS Responder
+  MDNS.setHostProbeResultCallback(hostProbeResult);
+  if (!MDNS.begin((String(DEVICE_NAME) + "_" + deviceUUID).c_str())) {
+    Serial.println("Error setting up MDNS responder!");
+  }
+
+  //Advertise the port that you are using
+  MDNS.addService("http", "tcp", LISTENING_PORT);
+  Serial.println("mDNS responder started");
+
+  //Restful API (required)
+  server.on("/", handle_index);
+  server.on("/status", handle_status);
+  server.on("/info", handle_deviceInfo);
+  server.on("/uuid", handle_uuid);
+
+  delay(100);
+  server.begin();
+  Serial.println("Restful API server started");
+  Serial.print("Listening on port: ");
+  Serial.println(LISTENING_PORT);
+
+}

+ 0 - 28
hardware/hds_5-way-switch/firmware/5xswitches/leds.ino

@@ -31,31 +31,3 @@ void updateShiftRegister() {
   delay(1); // Optional: Adjust delay if needed
   digitalWrite(RCLK_PIN, LOW);
 }
-
-void handleSignalLEDBlinks(){
-  updateShiftRegister();
-  taskLEDsBlink.delay(BLINK_DURATION);
-  if (taskLEDsBlink.isLastIteration()) {
-    // Finished blinking. Reset task for next run 
-    taskLEDsBlink.setIterations(2);
-    blueLED = false;
-    yellowLED = false;
-    redLED = false;
-  }
-}
-
-//Blink LED utils to help blink any signal led once
-// 0 => blue LED
-// 1 => yellow LED
-// 2 => red LED
-void blinkLED(int sigLED) {
-  //Turn on the target LED
-  if (sigLED == 0) {
-    blueLED = true;
-  } else if (sigLED == 1) {
-    yellowLED = true;
-  } else if (sigLED == 2) {
-    redLED = true;
-  }
-  taskLEDsBlink.enable();
-}

+ 0 - 43
hardware/hds_5-way-switch/firmware/5xswitches/mesh.ino

@@ -1,43 +0,0 @@
-
-void sendMessage() {
-  String msg = "Hi from node1";
-  msg += mesh.getNodeId();
-  mesh.sendBroadcast( msg );
-  taskSendMessage.setInterval( random( TASK_SECOND * 1, TASK_SECOND * 5 ));
-  blinkLED(0);
-}
-
-void toggleRelay(){
-  
-}
-
-// Painless Mesh callbacks
-void receivedCallback( uint32_t from, String &msg ) {
-  Serial.printf("Received from %u msg=%s\n", from, msg.c_str());
-  if (from == TARGET_RELAY){
-    //This is the relay we are listening to
-    StaticJsonDocument<200> doc;
-    deserializeJson(doc, msg);
-    buttonStates[0] = doc["relay1"];
-    buttonStates[1] = doc["relay2"];
-    buttonStates[2] = doc["relay3"];
-    buttonStates[3] = doc["relay4"];
-    if (buttonStates[0] && buttonStates[1] && buttonStates[2] && buttonStates[3]){
-      buttonStates[4] = true;
-    }else{
-      buttonStates[3] = false;
-    }
-  }
-}
-
-void newConnectionCallback(uint32_t nodeId) {
-  Serial.printf("--> New device discovered: New Connection, nodeId = %u\n", nodeId);
-}
-
-void changedConnectionCallback() {
-  Serial.printf("Changed connections\n");
-}
-
-void nodeTimeAdjustedCallback(int32_t offset) {
-  Serial.printf("Adjusted time %u. Offset = %d\n", mesh.getNodeTime(), offset);
-}

+ 29 - 0
hardware/hds_5-way-switch/firmware/5xswitches/target.ino

@@ -0,0 +1,29 @@
+void resolveTargetRelayIP(){
+  //Resolve the target relay module IP from mDNS broadcast
+   if(resolveMdnsService("http", "tcp", TARGET_DEVICE, &target_ip, &target_port)) {
+    Serial.printf("got an answer for %s.local!\n", TARGET_DEVICE);
+    Serial.println(target_ip);
+    Serial.println(target_port);
+  } else {
+    Serial.printf("Sorry, %s.local not found\n", TARGET_DEVICE);
+  }
+}
+
+void GetRequest(String url) {
+  WiFiClient client;  // Create a WiFiClient object
+
+  HTTPClient http;
+  http.begin(client, url);  // Pass the WiFiClient object and the URL to begin()
+
+  int httpCode = http.GET();  // Make the GET request
+
+  if (httpCode > 0) {
+    String payload = http.getString();  // Get the response payload
+    Serial.println("HTTP Response Code: " + String(httpCode));
+    Serial.println("Response Payload: " + payload);
+  } else {
+    Serial.println("Error on HTTP request");
+  }
+
+  http.end();  // Close connection
+}