IoT sensor/controller using STM32, W5500 ethernet, MQTT

Dependencies:   mbed WIZnet_Library Watchdog DHT MQTT DS1820

Committer:
Geekshow
Date:
Sun Feb 23 18:36:18 2020 +0000
Revision:
4:ebaf1973d008
Parent:
3:de9611d75590
Child:
5:b2ae1ed8a30e
merged networking into main.cpp

Who changed what in which revision?

UserRevisionLine numberNew contents of line
zhangyx 0:1170747a672f 1 #include "mbed.h"
Geekshow 3:de9611d75590 2 //#include "rtos.h"
Geekshow 3:de9611d75590 3 //#include "pins.h"
Geekshow 4:ebaf1973d008 4 #include "WIZnetInterface.h"
Geekshow 4:ebaf1973d008 5 #include "MQTTSocket.h"
Geekshow 4:ebaf1973d008 6 #include "MQTTClient.h"
Geekshow 3:de9611d75590 7
Geekshow 3:de9611d75590 8 // ========== PIN DEFINITIONS ============
Geekshow 3:de9611d75590 9 #define NUM_OF_OUTPUTS 11
Geekshow 3:de9611d75590 10 #define NUM_OF_INPUTS 12
Geekshow 3:de9611d75590 11
Geekshow 4:ebaf1973d008 12 #define LED_GREEN PA_5
Geekshow 4:ebaf1973d008 13 #define LED_ORANGE PA_1 // Don't use! Shared with D3
Geekshow 3:de9611d75590 14 #define BUTTON PC_9
Geekshow 3:de9611d75590 15
Geekshow 3:de9611d75590 16 #define ANALOGPIN0 PC_0 // Analogue Input 0
Geekshow 3:de9611d75590 17 #define ANALOGPIN1 PC_1 // Analogue Input 1
Geekshow 3:de9611d75590 18 #define ANALOGPIN2 PC_2 // Analogue Input 2
Geekshow 3:de9611d75590 19 #define ANALOGPIN3 PC_3 // Analogue Input 3
Geekshow 3:de9611d75590 20 #define ANALOGPIN4 PC_4 // Analogue Input 4
Geekshow 3:de9611d75590 21 #define ANALOGPIN5 PC_5 // Analogue Input 5
Geekshow 3:de9611d75590 22
Geekshow 3:de9611d75590 23 //#define INPUTPINx PC_15 // Don't use D23
Geekshow 3:de9611d75590 24 #define INPUTPIN0 PB_9 // DHT22 digital pin (D24)
Geekshow 3:de9611d75590 25 #define INPUTPIN1 PD_2 // DHT22 digital pin (D25)
Geekshow 3:de9611d75590 26 #define INPUTPIN2 PC_10 // DHT22 digital pin (D26)
Geekshow 3:de9611d75590 27 //#define INPUTPINx PB_0 // Don't use D27
Geekshow 3:de9611d75590 28 //#define INPUTPINx PB_1 // Don't use D28
Geekshow 3:de9611d75590 29 #define INPUTPIN3 PB_10 // digital pin (D29)
Geekshow 3:de9611d75590 30 #define INPUTPIN4 PB_11 // digital pin (D30)
Geekshow 3:de9611d75590 31 #define INPUTPIN5 PB_12 // digital pin (D31)
Geekshow 3:de9611d75590 32 #define INPUTPIN6 PB_13 // digital pin (D32)
Geekshow 3:de9611d75590 33 #define INPUTPIN7 PB_14 // digital pin (D33)
Geekshow 3:de9611d75590 34 #define INPUTPIN8 PB_15 // digital pin (D34)
Geekshow 3:de9611d75590 35 #define INPUTPIN9 PC_6 // digital pin (D35)
Geekshow 3:de9611d75590 36 #define INPUTPIN10 PC_7 // digital pin (D36)
Geekshow 3:de9611d75590 37 #define INPUTPIN11 PC_8 // digital pin (D37)
Geekshow 3:de9611d75590 38
Geekshow 3:de9611d75590 39 #define OUTPUTPIN0 PA_3 // digital output D0
Geekshow 3:de9611d75590 40 #define OUTPUTPIN1 PA_2 // digital output D1
Geekshow 3:de9611d75590 41 #define OUTPUTPIN2 PA_0 // digital output D2
Geekshow 3:de9611d75590 42 #define OUTPUTPIN3 PA_1 // digital output D3
Geekshow 3:de9611d75590 43 #define OUTPUTPIN4 PB_5 // digital output D4
Geekshow 3:de9611d75590 44 #define OUTPUTPIN5 PB_6 // digital output D5
Geekshow 3:de9611d75590 45 #define OUTPUTPIN6 PA_8 // digital output D6
Geekshow 3:de9611d75590 46 #define OUTPUTPIN7 PA_9 // digital output D7
Geekshow 3:de9611d75590 47 #define OUTPUTPIN8 PA_10 // digital output D8
Geekshow 3:de9611d75590 48 #define OUTPUTPIN9 PB_7 // digital output D9
Geekshow 3:de9611d75590 49 //#define OUTPUTPINx PA_4 // digital output D10 - SPI1 SS
Geekshow 3:de9611d75590 50 //#define OUTPUTPINx PA_4 // digital output D11 - SPI1 MOSI
Geekshow 3:de9611d75590 51 //#define OUTPUTPINx PA_4 // digital output D12 - SPI1 MISO
Geekshow 3:de9611d75590 52 //#define OUTPUTPINx PA_4 // digital output D13 - SPI1 CLK
Geekshow 3:de9611d75590 53 #define OUTPUTPIN10 PB_8 // digital output D14
Geekshow 3:de9611d75590 54 // ================= *************** ==================
Geekshow 3:de9611d75590 55 #define USART3_TX PC_10
Geekshow 3:de9611d75590 56 // ================= *************** ==================
Geekshow 4:ebaf1973d008 57 #define NODE_NAME "controller03" // TODO just define node number
Geekshow 3:de9611d75590 58
Geekshow 4:ebaf1973d008 59 uint8_t mac_addr[6]={0x00, 0x00, 0x00, 0xBE, 0xEF, 0x03}; // TODO make last byte dynamic
Geekshow 4:ebaf1973d008 60 const char* mqtt_broker = "192.168.1.99";
Geekshow 4:ebaf1973d008 61 const int mqtt_port = 1883;
Geekshow 4:ebaf1973d008 62 static Timer g_timer; // TODO remove me
Geekshow 4:ebaf1973d008 63
Geekshow 4:ebaf1973d008 64 WIZnetInterface wiz(PA_7, PA_6, PA_5, PA_4, PB_10); // SPI1 with D29 (reset)
Geekshow 4:ebaf1973d008 65 typedef MQTT::Client<MQTTSocket,Countdown> MClient;
Geekshow 4:ebaf1973d008 66
Geekshow 4:ebaf1973d008 67 const char* ONOFF[] = {"OFF", "ON"};
Geekshow 4:ebaf1973d008 68 const char* OPENCLOSED[] = {"CLOSED", "OPEN"};
Geekshow 4:ebaf1973d008 69
Geekshow 4:ebaf1973d008 70 Serial pc(USART3_TX, NC); // serial debug output on D26 (pin 4 of Extension)
Geekshow 3:de9611d75590 71
Geekshow 4:ebaf1973d008 72 DigitalIn button(BUTTON);
Geekshow 4:ebaf1973d008 73 DigitalOut led(LED_GREEN);
Geekshow 4:ebaf1973d008 74 DigitalOut output0(OUTPUTPIN0);
Geekshow 4:ebaf1973d008 75
Geekshow 4:ebaf1973d008 76 const char* inputs[2] = {
Geekshow 4:ebaf1973d008 77 "button",
Geekshow 4:ebaf1973d008 78 NULL
Geekshow 4:ebaf1973d008 79 };
Geekshow 4:ebaf1973d008 80
Geekshow 4:ebaf1973d008 81 const char* outputs[2] = {
Geekshow 4:ebaf1973d008 82 "output0",
Geekshow 4:ebaf1973d008 83 NULL
Geekshow 4:ebaf1973d008 84 };
Geekshow 4:ebaf1973d008 85
zhangyx 0:1170747a672f 86
zhangyx 2:a50b794b8ede 87 void on_control_cmd(const char* actuator_name, const char* control_value)
zhangyx 0:1170747a672f 88 {
Geekshow 4:ebaf1973d008 89 int new_state = 0;
zhangyx 2:a50b794b8ede 90 pc.printf("Received CMD %s %s\r\n", actuator_name, control_value);
Geekshow 4:ebaf1973d008 91 if(strcmp(control_value, "ON") == 0) {
Geekshow 4:ebaf1973d008 92 pc.printf("ON value requested!\r\n");
Geekshow 4:ebaf1973d008 93 new_state = 1;
Geekshow 4:ebaf1973d008 94 }
Geekshow 4:ebaf1973d008 95 else if(strcmp(control_value, "OFF") == 0) {
Geekshow 4:ebaf1973d008 96 pc.printf("OFF value requested!\r\n");
Geekshow 4:ebaf1973d008 97 new_state = 0;
Geekshow 4:ebaf1973d008 98 }
Geekshow 4:ebaf1973d008 99 else {
Geekshow 4:ebaf1973d008 100 pc.printf("No value specified! In future return the current value...\r\n");
Geekshow 4:ebaf1973d008 101 return;
Geekshow 4:ebaf1973d008 102 }
Geekshow 4:ebaf1973d008 103
Geekshow 4:ebaf1973d008 104 if(strcmp(actuator_name, "output0") == 0) {
Geekshow 4:ebaf1973d008 105 pc.printf("Output: %s updated to %d\r\n", actuator_name, new_state);
Geekshow 4:ebaf1973d008 106 led = new_state;
Geekshow 4:ebaf1973d008 107 output0 = new_state;
Geekshow 4:ebaf1973d008 108 }
Geekshow 4:ebaf1973d008 109 }
Geekshow 4:ebaf1973d008 110
Geekshow 4:ebaf1973d008 111 void read_inputs()
Geekshow 4:ebaf1973d008 112 {
Geekshow 4:ebaf1973d008 113 }
Geekshow 4:ebaf1973d008 114
Geekshow 4:ebaf1973d008 115
Geekshow 4:ebaf1973d008 116 void set_outputs()
Geekshow 4:ebaf1973d008 117 {
Geekshow 4:ebaf1973d008 118 }
Geekshow 4:ebaf1973d008 119
Geekshow 4:ebaf1973d008 120
Geekshow 4:ebaf1973d008 121 int publish(MClient& client, const char* msg_type, const char* point,
Geekshow 4:ebaf1973d008 122 const char* payload = NULL, size_t payload_len = 0,
Geekshow 4:ebaf1973d008 123 bool retain = false, MQTT::QoS qos = MQTT::QOS1){
Geekshow 4:ebaf1973d008 124 char topic[64];
Geekshow 4:ebaf1973d008 125 sprintf(topic, "%s/" NODE_NAME "/%s", msg_type, point);
Geekshow 4:ebaf1973d008 126 int ret = client.publish(topic, (void*)payload, payload_len, qos, retain);
Geekshow 4:ebaf1973d008 127 if(ret == -1) {
Geekshow 4:ebaf1973d008 128 pc.printf("ERROR during client.publish() = %d\r\n",ret);
Geekshow 4:ebaf1973d008 129 }
Geekshow 4:ebaf1973d008 130 return ret;
zhangyx 0:1170747a672f 131 }
zhangyx 2:a50b794b8ede 132
Geekshow 4:ebaf1973d008 133
Geekshow 4:ebaf1973d008 134 void messageArrived(MQTT::MessageData& md)
Geekshow 3:de9611d75590 135 {
Geekshow 4:ebaf1973d008 136 MQTT::Message &message = md.message;
Geekshow 4:ebaf1973d008 137
Geekshow 4:ebaf1973d008 138 // copy message payload into local char array IMPROVE ME!
Geekshow 4:ebaf1973d008 139 char* payload = new char[message.payloadlen+1];
Geekshow 4:ebaf1973d008 140 if(!payload)
Geekshow 4:ebaf1973d008 141 return;
Geekshow 4:ebaf1973d008 142 memcpy(payload, message.payload, message.payloadlen);
Geekshow 4:ebaf1973d008 143 payload[message.payloadlen]='\0';
Geekshow 4:ebaf1973d008 144
Geekshow 4:ebaf1973d008 145 // copy topic payload into local char array IMPROVE ME!
Geekshow 4:ebaf1973d008 146 char* topic = new char[md.topicName.lenstring.len+1];
Geekshow 4:ebaf1973d008 147 if(!topic){
Geekshow 4:ebaf1973d008 148 delete[] payload;
Geekshow 4:ebaf1973d008 149 return;
Geekshow 4:ebaf1973d008 150 }
Geekshow 4:ebaf1973d008 151 memcpy(topic, md.topicName.lenstring.data, md.topicName.lenstring.len);
Geekshow 4:ebaf1973d008 152 topic[md.topicName.lenstring.len]='\0';
Geekshow 4:ebaf1973d008 153
Geekshow 4:ebaf1973d008 154 pc.printf("Rcvd: %s : %s\r\n", topic, payload);
Geekshow 4:ebaf1973d008 155
Geekshow 4:ebaf1973d008 156 // split up topic string
Geekshow 4:ebaf1973d008 157 char *topics = strtok (topic,"/");
Geekshow 4:ebaf1973d008 158 for (int tok=0; tok<2 && topics != NULL; tok++) // WARNING! hard coded 2 layer topic!
Geekshow 4:ebaf1973d008 159 {
Geekshow 4:ebaf1973d008 160 // pc.printf ("%s\r\n",topics);
Geekshow 4:ebaf1973d008 161 topics = strtok (NULL, "/");
Geekshow 4:ebaf1973d008 162 }
Geekshow 4:ebaf1973d008 163 on_control_cmd(topics, payload);
Geekshow 4:ebaf1973d008 164 delete[] topic;
Geekshow 4:ebaf1973d008 165 delete[] payload;
Geekshow 3:de9611d75590 166 }
Geekshow 3:de9611d75590 167
Geekshow 4:ebaf1973d008 168
Geekshow 4:ebaf1973d008 169 int publish_value(MClient &client, const char *topic, const char *buf)
Geekshow 3:de9611d75590 170 {
Geekshow 4:ebaf1973d008 171 return publish(client, "stat", topic, buf, strlen(buf), true);
Geekshow 4:ebaf1973d008 172 }
Geekshow 4:ebaf1973d008 173
Geekshow 4:ebaf1973d008 174
Geekshow 4:ebaf1973d008 175 int networking_init(MQTTSocket &sock, MClient &client) {
Geekshow 4:ebaf1973d008 176 int ret = 0;
Geekshow 4:ebaf1973d008 177 g_timer.start();
Geekshow 4:ebaf1973d008 178 pc.printf("\n\nNode: %s\r\n", NODE_NAME);
Geekshow 4:ebaf1973d008 179 pc.printf("%s attempting ethernet connection...\r\n", NODE_NAME);
Geekshow 4:ebaf1973d008 180 wiz.init(mac_addr); // resets the w5500
Geekshow 4:ebaf1973d008 181 if (wiz.connect() == (-1)) {
Geekshow 4:ebaf1973d008 182 pc.printf("Error getting DHCP address!!\r\n");
Geekshow 4:ebaf1973d008 183 }
Geekshow 4:ebaf1973d008 184
Geekshow 4:ebaf1973d008 185 pc.printf("IP: %s\r\n", wiz.getIPAddress());
Geekshow 4:ebaf1973d008 186
Geekshow 4:ebaf1973d008 187 srand(rand()^g_timer.read_us()); // what is this doing?
Geekshow 4:ebaf1973d008 188
Geekshow 4:ebaf1973d008 189 ret = sock.connect((char*)mqtt_broker,mqtt_port);
Geekshow 4:ebaf1973d008 190 if(ret != 0){
Geekshow 4:ebaf1973d008 191 pc.printf("failed to connect to TCP server\r\n");
Geekshow 4:ebaf1973d008 192 return 1;
Geekshow 4:ebaf1973d008 193 }
Geekshow 4:ebaf1973d008 194 pc.printf("sock.connect()=%d\r\n",ret);
Geekshow 4:ebaf1973d008 195
Geekshow 4:ebaf1973d008 196 srand(rand()^g_timer.read_us()); // what is this doing?
Geekshow 4:ebaf1973d008 197
Geekshow 4:ebaf1973d008 198 if(client.connect() != 0){
Geekshow 4:ebaf1973d008 199 pc.printf("MQTT connect failed\r\n");
Geekshow 4:ebaf1973d008 200 return -1;
Geekshow 4:ebaf1973d008 201 }
Geekshow 4:ebaf1973d008 202 pc.printf("client.connect()=%d\r\n",ret);
Geekshow 4:ebaf1973d008 203
Geekshow 4:ebaf1973d008 204
Geekshow 4:ebaf1973d008 205 ret = client.subscribe("cmnd/" NODE_NAME "/+", MQTT::QOS1, messageArrived);
Geekshow 4:ebaf1973d008 206 pc.printf("client.subscribe()=%d\r\n", ret);
Geekshow 4:ebaf1973d008 207
Geekshow 4:ebaf1973d008 208 // Node online message
Geekshow 4:ebaf1973d008 209 publish(client, "stat","online");
Geekshow 4:ebaf1973d008 210 pc.printf("Initialization done.\r\n");
Geekshow 4:ebaf1973d008 211
Geekshow 4:ebaf1973d008 212 return 0;
Geekshow 3:de9611d75590 213 }
Geekshow 3:de9611d75590 214
Geekshow 3:de9611d75590 215
Geekshow 3:de9611d75590 216 int main()
Geekshow 3:de9611d75590 217 {
zhangyx 0:1170747a672f 218 MQTTSocket sock;
zhangyx 0:1170747a672f 219 MClient client(sock);
Geekshow 3:de9611d75590 220
Geekshow 4:ebaf1973d008 221 int connected = networking_init(sock, client);
zhangyx 0:1170747a672f 222
zhangyx 0:1170747a672f 223 bool btn = 0;
Geekshow 3:de9611d75590 224
Geekshow 3:de9611d75590 225 while(1) {
Geekshow 4:ebaf1973d008 226 set_outputs();
Geekshow 4:ebaf1973d008 227 read_inputs();
Geekshow 3:de9611d75590 228
Geekshow 4:ebaf1973d008 229 // replace this hacky mess with read_inputs!
Geekshow 4:ebaf1973d008 230 bool newBTN = button;
Geekshow 3:de9611d75590 231 if(newBTN != btn) {
Geekshow 4:ebaf1973d008 232 publish_value(client,"input0",OPENCLOSED[newBTN]);
zhangyx 0:1170747a672f 233 btn = newBTN;
Geekshow 3:de9611d75590 234 } else {
zhangyx 2:a50b794b8ede 235 client.yield(1000);
Geekshow 3:de9611d75590 236 connected = publish_value(client,"stat","hello world");
Geekshow 3:de9611d75590 237 if(connected != 0) {
Geekshow 3:de9611d75590 238 pc.printf("Restarting network....\r\n");
Geekshow 4:ebaf1973d008 239 networking_init(sock, client);
Geekshow 3:de9611d75590 240 }
zhangyx 0:1170747a672f 241 }
zhangyx 0:1170747a672f 242 }
zhangyx 0:1170747a672f 243 }