IoT sensor/controller using STM32, W5500 ethernet, MQTT

Dependencies:   mbed WIZnet_Library Watchdog DHT MQTT DS1820

Revision:
4:ebaf1973d008
Parent:
3:de9611d75590
Child:
5:b2ae1ed8a30e
--- a/main.cpp	Sun Feb 23 10:17:06 2020 +0000
+++ b/main.cpp	Sun Feb 23 18:36:18 2020 +0000
@@ -1,15 +1,16 @@
 #include "mbed.h"
 //#include "rtos.h"
 //#include "pins.h"
-#include "networking.h"
-
+#include "WIZnetInterface.h"
+#include "MQTTSocket.h"
+#include "MQTTClient.h"
 
 // ========== PIN DEFINITIONS ============
 #define NUM_OF_OUTPUTS 11
 #define NUM_OF_INPUTS 12
 
-#define GREENLEDPIN PA5
-#define ORANGELEDPIN PA_1
+#define LED_GREEN PA_5
+#define LED_ORANGE PA_1 // Don't use! Shared with D3
 #define BUTTON PC_9
 
 #define ANALOGPIN0 PC_0  // Analogue Input 0
@@ -53,48 +54,162 @@
 // ================= *************** ==================
 #define USART3_TX PC_10
 // ================= *************** ==================
+#define NODE_NAME "controller03" // TODO just define node number
 
+uint8_t mac_addr[6]={0x00, 0x00, 0x00, 0xBE, 0xEF, 0x03}; // TODO make last byte dynamic
+const char* mqtt_broker = "192.168.1.99";
+const int mqtt_port = 1883;
+static Timer g_timer;   // TODO remove me
+
+WIZnetInterface wiz(PA_7, PA_6, PA_5, PA_4, PB_10); // SPI1 with D29 (reset)
+typedef MQTT::Client<MQTTSocket,Countdown> MClient;
+
+const char* ONOFF[] = {"OFF", "ON"};
+const char* OPENCLOSED[] = {"CLOSED", "OPEN"};
+
+Serial pc(USART3_TX, NC); // serial debug output on D26 (pin 4 of Extension)
 
-Serial pc(USART3_TX, NC); // serial output on D26
-DigitalIn BTN(BUTTON);
-DigitalOut LED(LED_GREEN);
+DigitalIn button(BUTTON);
+DigitalOut led(LED_GREEN);
+DigitalOut output0(OUTPUTPIN0);
+
+const char* inputs[2] = {
+    "button",
+    NULL
+};
+
+const char* outputs[2] = {
+    "output0",
+    NULL
+};
+
 
 void on_control_cmd(const char* actuator_name, const char* control_value)
 {
+    int new_state = 0;
     pc.printf("Received CMD %s %s\r\n", actuator_name, control_value);
-    if(strcmp(actuator_name, "led") == 0)
-        LED = atoi(control_value);
+    if(strcmp(control_value, "ON") == 0) {
+        pc.printf("ON value requested!\r\n");
+        new_state = 1;
+    }
+    else if(strcmp(control_value, "OFF") == 0) {
+        pc.printf("OFF value requested!\r\n");
+        new_state = 0;
+    }
+    else {
+        pc.printf("No value specified! In future return the current value...\r\n");
+        return;
+    }
+    
+    if(strcmp(actuator_name, "output0") == 0) {
+        pc.printf("Output: %s updated to %d\r\n", actuator_name, new_state);
+        led = new_state;
+        output0 = new_state;
+    }
+}
+
+void read_inputs()
+{
+}
+
+
+void set_outputs()
+{
+}
+
+
+int publish(MClient& client, const char* msg_type, const char* point, 
+                    const char* payload = NULL, size_t payload_len = 0, 
+                    bool retain = false, MQTT::QoS qos = MQTT::QOS1){
+    char topic[64];
+    sprintf(topic, "%s/" NODE_NAME "/%s", msg_type, point);
+    int ret = client.publish(topic, (void*)payload, payload_len, qos, retain);
+    if(ret == -1) {
+        pc.printf("ERROR during client.publish() = %d\r\n",ret);
+    }
+    return ret;
 }
 
-void readInputs()
+
+void messageArrived(MQTT::MessageData& md)
 {
-  inputs[0] = digitalRead(INPUTPIN0);
-  inputs[1] = digitalRead(INPUTPIN1);
-  inputs[2] = digitalRead(INPUTPIN2);
-  inputs[3] = digitalRead(INPUTPIN3);
-  inputs[4] = digitalRead(INPUTPIN4);
-  inputs[5] = digitalRead(INPUTPIN5);
-  inputs[6] = digitalRead(INPUTPIN6);
-  inputs[7] = digitalRead(INPUTPIN7);
-  inputs[8] = digitalRead(INPUTPIN8);
-  inputs[9] = digitalRead(INPUTPIN9);
-  inputs[10] = digitalRead(INPUTPIN10);
-  inputs[11] = digitalRead(INPUTPIN11);
+    MQTT::Message &message = md.message;
+
+    // copy message payload into local char array IMPROVE ME!
+    char* payload = new char[message.payloadlen+1];
+    if(!payload)
+        return;
+    memcpy(payload, message.payload, message.payloadlen);
+    payload[message.payloadlen]='\0';
+    
+    // copy topic payload into local char array IMPROVE ME!
+    char* topic = new char[md.topicName.lenstring.len+1];
+    if(!topic){
+        delete[] payload;
+        return;
+    }
+    memcpy(topic, md.topicName.lenstring.data, md.topicName.lenstring.len);
+    topic[md.topicName.lenstring.len]='\0';
+    
+    pc.printf("Rcvd: %s : %s\r\n", topic, payload);
+    
+    // split up topic string
+    char *topics = strtok (topic,"/");
+    for (int tok=0; tok<2 && topics != NULL; tok++)  // WARNING! hard coded 2 layer topic!
+    {
+//        pc.printf ("%s\r\n",topics);
+        topics = strtok (NULL, "/");
+    }
+    on_control_cmd(topics, payload);
+    delete[] topic;
+    delete[] payload;
 }
 
-void setOutputs()
+
+int publish_value(MClient &client, const char *topic, const char *buf)
 {
-  digitalWrite(OUTPUTPIN0,!outputs[0]);
-  digitalWrite(OUTPUTPIN1,!outputs[1]);
-  digitalWrite(OUTPUTPIN2,!outputs[2]);
-  digitalWrite(OUTPUTPIN3,!outputs[3]);
-  digitalWrite(OUTPUTPIN4,!outputs[4]);
-  digitalWrite(OUTPUTPIN5,!outputs[5]);
-  digitalWrite(OUTPUTPIN6,!outputs[6]);
-  digitalWrite(OUTPUTPIN7,!outputs[7]);
-  digitalWrite(OUTPUTPIN8,!outputs[8]);
-  digitalWrite(OUTPUTPIN9,!outputs[9]);
-  digitalWrite(OUTPUTPIN10,!outputs[10]);
+    return publish(client, "stat", topic, buf, strlen(buf), true);
+}
+
+ 
+int networking_init(MQTTSocket &sock, MClient &client) {
+    int ret = 0;
+    g_timer.start();
+    pc.printf("\n\nNode: %s\r\n", NODE_NAME);
+    pc.printf("%s attempting ethernet connection...\r\n", NODE_NAME);
+    wiz.init(mac_addr); // resets the w5500
+    if (wiz.connect() == (-1)) {
+        pc.printf("Error getting DHCP address!!\r\n");
+    }
+    
+    pc.printf("IP: %s\r\n", wiz.getIPAddress());
+    
+    srand(rand()^g_timer.read_us()); // what is this doing?
+    
+    ret = sock.connect((char*)mqtt_broker,mqtt_port);
+    if(ret != 0){
+        pc.printf("failed to connect to TCP server\r\n");
+        return 1;
+    }
+    pc.printf("sock.connect()=%d\r\n",ret);
+    
+    srand(rand()^g_timer.read_us()); // what is this doing?
+    
+    if(client.connect() != 0){
+        pc.printf("MQTT connect failed\r\n");
+        return -1;
+    }
+    pc.printf("client.connect()=%d\r\n",ret);
+    
+    
+    ret = client.subscribe("cmnd/" NODE_NAME "/+", MQTT::QOS1, messageArrived);    
+    pc.printf("client.subscribe()=%d\r\n", ret);
+
+    // Node online message
+    publish(client, "stat","online");
+    pc.printf("Initialization done.\r\n");
+    
+    return 0;
 }
 
 
@@ -103,43 +218,25 @@
     MQTTSocket sock;
     MClient client(sock);
 
-    // Declare sensors (name, unit)
-    const char* sensors[][8] = {
-        "test", " ",
-        "button", "V",
-        NULL, NULL
-    };
-
-    // Declare all actuators (name and parameter)
-    const char* actuators[][8] = {
-        "led", "int",
-        NULL, NULL
-    };
-
-    int connected = networking_init(sock, client, sensors, actuators, on_control_cmd);
+    int connected = networking_init(sock, client);
 
     bool btn = 0;
 
     while(1) {
-        setOutputs();
-        readInputs();
+        set_outputs();
+        read_inputs();
         
-                
-        bool newBTN = BTN;
+        // replace this hacky mess with read_inputs!
+        bool newBTN = button;
         if(newBTN != btn) {
-            char buf[16];
-            int value = (bool)newBTN;
-
-            sprintf(buf, "%d mV", value);
-            publish_value(client,"button",buf);
-
+            publish_value(client,"input0",OPENCLOSED[newBTN]);
             btn = newBTN;
         } else {
             client.yield(1000);
             connected = publish_value(client,"stat","hello world");
             if(connected != 0) {
                 pc.printf("Restarting network....\r\n");
-                networking_init(sock, client, sensors, actuators, on_control_cmd);
+                networking_init(sock, client);
             }
         }
     }