arduino-sketches – Blame information for rev 6

Subversion Repositories:
Rev:
Rev Author Line No. Line
5 office 1 /*************************************************************************/
2 /* Copyright (C) 2020 Wizardry and Steamworks - License: GNU GPLv3 */
3 /*************************************************************************/
4  
5 // The AP to connect to via Wifi.
6 #define STA_SSID ""
7 // The AP Wifi password.
8 #define STA_PSK ""
9 // The MQTT broker to connect to.
10 #define MQTT_HOST ""
11 // The MQTT broker username.
12 #define MQTT_USERNAME ""
13 // The MQTT broker password.
14 #define MQTT_PASSWORD ""
15 // The MQTT broker port.
16 #define MQTT_PORT 1883
17 // The default MQTT client ID is "esp-CHIPID" where CHIPID is the ESP8266
18 // or ESP32 chip identifier.
19 #define MQTT_CLIENT_ID() String("esp-" + String(GET_CHIP_ID(), HEX))
20 // The authentication password to use for OTA updates.
21 #define OTA_PASSWORD ""
22 // The OTA port on which updates take place.
23 #define OTA_PORT 8266
24 // The default topic that the sketch subscribes to is "esp/CHIPID" where
25 // CHIPID is the ESP8266 or ESP32 chip identifier.
26 #define MQTT_TOPIC() String("esp/" + String(GET_CHIP_ID(), HEX))
27  
28 // Platform specific defines.
29 #if defined(ARDUINO_ARCH_ESP8266)
30 #define GET_CHIP_ID() (ESP.getChipId())
31 #elif defined(ARDUINO_ARCH_ESP32)
32 #define GET_CHIP_ID() ((uint16_t)(ESP.getEfuseMac()>>32))
33 #endif
34  
35 // Miscellaneous defines.
36 //#define CHIP_ID_HEX (String(GET_CHIP_ID()).c_str())
37 #define HOSTNAME() String("esp-" + String(GET_CHIP_ID(), HEX))
38  
39 // Platform specific libraries.
40 #if defined(ARDUINO_ARCH_ESP8266)
41 #include <ESP8266WiFi.h>
42 #include <ESP8266mDNS.h>
43 #elif defined(ARDUINO_ARCH_ESP32)
44 #include <WiFi.h>
45 #include <ESPmDNS.h>
46 #endif
47 // General libraries.
48 #include <WiFiUdp.h>
49 #include <ArduinoOTA.h>
50 #include <PubSubClient.h>
51 #include <ArduinoJson.h>
52 #if defined(ARDUINO_ARCH_ESP32)
53 #include <FS.h>
54 #include <SPIFFS.h>
55 #endif
56 // DHT11
57 #include <Adafruit_Sensor.h>
58 #include <DHT.h>
59 #include <DHT_U.h>
60  
61 const char *sta_ssid = STA_SSID;
62 const char *sta_psk = STA_PSK;
63 const char *mqtt_host = MQTT_HOST;
64 const char *mqtt_username = MQTT_USERNAME;
65 const char *mqtt_password = MQTT_PASSWORD;
66 const int mqtt_port = MQTT_PORT;
67 const char *ota_password = OTA_PASSWORD;
68 const int ota_port = OTA_PORT;
69  
70 WiFiClient espClient;
71 PubSubClient mqttClient(espClient);
72  
73 // Uncomment the type of sensor in use:
74 #define DHTTYPE DHT11 // DHT 11
75 //#define DHTTYPE DHT22 // DHT 22 (AM2302)
76 //#define DHTTYPE DHT21 // DHT 21 (AM2301)
77  
78 // Define GPIO pins for supported architectures.
79 #if defined(ARDUINO_ARCH_ESP8266)
80 int PINS[] = { D0, D1, D2, D3, D4, D5, D6, D7, D8 };
81 #elif defined(ARDUINO_ARCH_ESP32)
82 int PINS[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
83 12, 13, 14, 15, 16, 17, 18, 19, 21, 22,
84 23, 25, 26, 27, 32, 33, 34, 35, 36, 37,
85 38, 39
86 };
87 #endif
88  
89 const char* mqttSerialize(StaticJsonDocument<256> msg) {
90 char message[256];
91 serializeJson(msg, message);
92 return (const char*) message;
93 }
94  
95 void mqttCallback(char *topic, byte *payload, unsigned int length) {
96 String msgTopic = String(topic);
97 // payload is not null terminated and casting will not work
98 char msgPayload[length + 1];
99 snprintf(msgPayload, length + 1, "%s", payload);
100 Serial.println("Message received on topic: " + String(topic) + " with payload: " + String(msgPayload));
101  
102 // Parse the payload sent to the MQTT topic as a JSON document.
103 StaticJsonDocument<256> doc;
104 Serial.println("Deserializing message....");
105 DeserializationError error = deserializeJson(doc, msgPayload);
106 if (error) {
107 Serial.println("Failed to parse MQTT payload as JSON: " + String(error.c_str()));
108 return;
109 }
110  
111 // Ignore message with no identifier in the payload.
112 if (!doc.containsKey("id")) {
113 return;
114 }
115  
116 // Do not listen to self.
117 String id = (const char *)doc["id"];
118 if (id == String(MQTT_CLIENT_ID().c_str())) {
119 return;
120 }
121  
122 // Reject messages that do not provide a reading pin.
123 if (!doc.containsKey("pin")) {
124 Serial.println("MQTT message received but no pin supplied...");
125 return;
126 }
127  
128 const int pin = (const int)doc["pin"];
129  
130 StaticJsonDocument<256> msg;
6 office 131 msg["id"] = String(MQTT_CLIENT_ID().c_str());
5 office 132 DHT_Unified dht(PINS[pin], DHTTYPE);
133 dht.begin();
134 // Print temperature sensor details.
135 sensors_event_t event;
136 dht.temperature().getEvent(&event);
137 switch (!isnan(event.temperature)) {
138 case true:
139 msg["temperature"] = event.temperature;
140 break;
141 default:
142 Serial.println("Error reading temperature...");
143 break;
144 }
145  
146 dht.humidity().getEvent(&event);
147 switch (!isnan(event.relative_humidity)) {
148 case true:
149 msg["humidity"] = event.relative_humidity;
150 break;
151 default:
152 Serial.println("Error reading humidity...");
153 break;
154 }
155 // Eeek?
156 //dht.end();
157  
158 // Publish the sensor data.
159 mqttClient.publish(MQTT_TOPIC().c_str(), mqttSerialize(msg));
160 }
161  
162 bool mqttConnect() {
163 Serial.println("Attempting to connect to MQTT broker: " + String(mqtt_host));
164 mqttClient.setServer(mqtt_host, mqtt_port);
165  
166 StaticJsonDocument<255> msg;
167 if (mqttClient.connect(MQTT_CLIENT_ID().c_str(), mqtt_username, mqtt_password)) {
168 Serial.println("Established connection with MQTT broker using client ID: " + MQTT_CLIENT_ID());
169 mqttClient.setCallback(mqttCallback);
170 msg["action"] = "connected";
171 mqttClient.publish(MQTT_TOPIC().c_str(), mqttSerialize(msg));
172 Serial.println("Attempting to subscribe to MQTT topic: " + MQTT_TOPIC());
173 if (!mqttClient.subscribe(MQTT_TOPIC().c_str())) {
174 Serial.println("Failed to subscribe to MQTT topic: " + MQTT_TOPIC());
175 return false;
176 }
177 Serial.println("Subscribed to MQTT topic: " + MQTT_TOPIC());
178 msg.clear();
179 msg["action"] = "subscribed";
180 mqttClient.publish(MQTT_TOPIC().c_str(), mqttSerialize(msg));
181 return true;
182 }
183 else {
184 Serial.println("Connection to MQTT broker failed with MQTT client state: " + String(mqttClient.state()));
185 }
186  
187 return false;
188 }
189  
190 bool loopWifiConnected() {
191 // Process OTA loop first since emergency OTA updates might be needed.
192 ArduinoOTA.handle();
193  
194 // Process MQTT client loop.
195 if (!mqttClient.connected()) {
196 // If the connection to the MQTT broker has failed then sleep before carrying on.
197 if (!mqttConnect()) {
198 return false;
199 }
200 }
201 mqttClient.loop();
202  
203 return true;
204 }
205  
206 void setup() {
207 Serial.begin(115200);
208 Serial.println("Booted, setting up Wifi in 10s...");
209 delay(10000);
210  
211 WiFi.mode(WIFI_STA);
212 #if defined(ARDUINO_ARCH_ESP8266)
213 WiFi.hostname(HOSTNAME().c_str());
214 #elif defined(ARDUINO_ARCH_ESP32)
215 WiFi.setHostname(HOSTNAME().c_str());
216 #endif
217 WiFi.begin(sta_ssid, sta_psk);
218 while (WiFi.waitForConnectResult() != WL_CONNECTED) {
219 Serial.println("Failed to connect to Wifi, rebooting in 5s...");
220 delay(5000);
221 ESP.restart();
222 }
223  
224 Serial.print("Connected to Wifi: ");
225 Serial.println(WiFi.localIP());
226  
227 Serial.println("Setting up OTA in 10s...");
228 delay(10000);
229  
230 // Port defaults to 8266
231 ArduinoOTA.setPort(ota_port);
232  
233 // Hostname defaults to esp-[ChipID]
234 ArduinoOTA.setHostname(HOSTNAME().c_str());
235  
236 // Set the OTA password
237 ArduinoOTA.setPassword(ota_password);
238  
239 ArduinoOTA.onStart([]() {
240 switch (ArduinoOTA.getCommand()) {
241 case U_FLASH: // Sketch
242 Serial.println("OTA start updating sketch.");
243 break;
244 #if defined(ARDUINO_ARCH_ESP8266)
245 case U_FS:
246 #elif defined(ARDUINO_ARCH_ESP32)
247 case U_SPIFFS:
248 #endif
249 Serial.println("OTA start updating filesystem.");
250 SPIFFS.end();
251 break;
252 default:
253 Serial.println("Unknown OTA update type.");
254 break;
255 }
256 });
257 ArduinoOTA.onEnd([]() {
258 Serial.println("OTA update complete.");
259 SPIFFS.begin();
260 #if defined(ARDUINO_ARCH_ESP8266)
261 // For what it's worth, check the filesystem on ESP8266.
262 SPIFFS.check();
263 #endif
264 ESP.restart();
265 });
266 ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) {
267 Serial.printf("OTA update progress: %u%%\r", (progress / (total / 100)));
268 });
269 ArduinoOTA.onError([](ota_error_t error) {
270 Serial.printf("OTA update error [%u]: ", error);
271 switch (error) {
272 case OTA_AUTH_ERROR:
273 Serial.println("OTA authentication failed");
274 break;
275 case OTA_BEGIN_ERROR:
276 Serial.println("OTA begin failed");
277 break;
278 case OTA_CONNECT_ERROR:
279 Serial.println("OTA connect failed");
280 break;
281 case OTA_RECEIVE_ERROR:
282 Serial.println("OTA receive failed");
283 break;
284 case OTA_END_ERROR:
285 Serial.println("OTA end failed");
286 break;
287 default:
288 Serial.println("Unknown OTA failure");
289 break;
290 }
291 ESP.restart();
292 });
293 ArduinoOTA.begin();
294  
295 // Set up MQTT client.
296 mqttClient.setServer(mqtt_host, mqtt_port);
297 mqttClient.setCallback(mqttCallback);
298  
299 // Touchdown.
300 Serial.println("Setup complete.");
301 }
302  
303 void loop() {
304 // Check the Wifi connection status.
305 int wifiStatus = WiFi.status();
306 switch (wifiStatus) {
307 case WL_CONNECTED:
308 if (!loopWifiConnected()) {
309 delay(1000);
310 break;
311 }
312 delay(1);
313 break;
314 case WL_NO_SHIELD:
315 Serial.println("No Wifi shield present.");
316 goto DEFAULT_CASE;
317 break;
318 case WL_NO_SSID_AVAIL:
319 Serial.println("Configured SSID not found.");
320 goto DEFAULT_CASE;
321 break;
322 // Temporary statuses indicating transitional states.
323 case WL_IDLE_STATUS:
324 case WL_SCAN_COMPLETED:
325 delay(1000);
326 break;
327 // Fatal Wifi statuses trigger a delayed ESP restart.
328 case WL_CONNECT_FAILED:
329 case WL_CONNECTION_LOST:
330 case WL_DISCONNECTED:
331 default:
332 Serial.println("Wifi connection failed with status: " + String(wifiStatus));
333 DEFAULT_CASE:
334 delay(10000);
335 ESP.restart();
336 break;
337 }
338 }