IoT sensor/controller using STM32, W5500 ethernet, MQTT
Dependencies: mbed WIZnet_Library Watchdog DHT MQTT DS1820
main.cpp@4:ebaf1973d008, 2020-02-23 (annotated)
- 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?
User | Revision | Line number | New 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 | } |