· 6 years ago · Apr 26, 2020, 07:20 PM
1#include <Arduino.h>
2
3#include <ESP8266WiFi.h>
4
5#include <ESP8266WiFiMulti.h>
6
7#include <WebSocketsClient.h> // https://github.com/kakopappa/sinric/wiki/How-to-add-dependency-libraries
8
9#include <ArduinoJson.h> // https://github.com/kakopappa/sinric/wiki/How-to-add-dependency-libraries
10
11#include <StreamString.h>
12
13
14
15
16ESP8266WiFiMulti WiFiMulti;
17
18WebSocketsClient webSocket;
19
20WiFiClient client;
21
22
23
24#define MyApiKey "" // TODO: Change to your sinric API Key. Your API Key is displayed on sinric.com dashboard
25
26#define MySSID "" // TODO: Change to your Wifi network SSID
27
28#define MyWifiPassword "" // TODO: Change to your Wifi network password
29
30bool timerStarted = false;
31unsigned long previousMillis = 0;
32
33#define HEARTBEAT_INTERVAL 300000 // 5 Minutes
34
35
36
37const int relayPin1 = D2;
38const int relayPin2 = D3;
39
40
41uint64_t heartbeatTimestamp = 0;
42
43bool isConnected = false;
44
45
46
47void setPowerStateOnServer(String deviceId, String value);
48
49void setTargetTemperatureOnServer(String deviceId, String value, String scale);
50
51
52
53// deviceId is the ID assgined to your smart-home-device in sinric.com dashboard. Copy it from dashboard and paste it here
54
55
56
57void turnOn(String deviceId) {
58 if (deviceId == "5xxxxxxxxxxxxxxxxxx") // Device ID of first device
59 {
60 Serial.print("Turn on device id: ");
61 Serial.println(deviceId);
62 timerStarted = true; // Set a new flag indicating that the timer was started
63 previousMillis = millis(); // Get the initial time the appliance was turned on
64
65 Serial.println("D2 low");
66 digitalWrite(relayPin1, LOW);
67
68 Serial.println("D3 low");
69 digitalWrite(relayPin2, LOW);
70
71 Serial.flush();
72
73 Serial.println("D2 HIGH");
74 digitalWrite(relayPin1, HIGH);
75
76
77 Serial.println("Lift1 moving up.");
78 }
79}
80
81void turnOff(String deviceId) {
82 if (deviceId == "5xxxxxxxx") // Device ID of first device
83 {
84 Serial.print("Turn off Device ID: ");
85 Serial.println(deviceId);
86 }
87 timerStarted = true; // Set a new flag indicating that the timer was started
88 previousMillis = millis(); // Get the initial time the appliance was turned on
89
90 Serial.println("D2 low");
91 digitalWrite(relayPin1, LOW);
92
93 Serial.println("D3 low");
94 digitalWrite(relayPin2, LOW);
95
96 Serial.flush();
97
98 Serial.println("D3 HIGH");
99 digitalWrite(relayPin2, HIGH);
100
101 Serial.println("Lift1 moving down.");
102}
103
104
105
106void webSocketEvent(WStype_t type, uint8_t * payload, size_t length) {
107
108 switch(type) {
109
110 case WStype_DISCONNECTED:
111
112 isConnected = false;
113
114 Serial.printf("[WSc] Webservice disconnected from sinric.com!\n");
115
116 break;
117
118 case WStype_CONNECTED: {
119
120 isConnected = true;
121
122 Serial.printf("[WSc] Service connected to sinric.com at url: %s\n", payload);
123
124 Serial.printf("Waiting for commands from sinric.com ...\n");
125
126 }
127
128 break;
129
130 case WStype_TEXT: {
131
132 Serial.printf("[WSc] get text: %s\n", payload);
133
134 // Example payloads
135
136
137
138 // For Switch or Light device types
139
140 // {"deviceId": xxxx, "action": "setPowerState", value: "ON"} // https://developer.amazon.com/docs/device-apis/alexa-powercontroller.html
141
142
143
144 // For Light device type
145
146 // Look at the light example in github
147
148
149
150#if ARDUINOJSON_VERSION_MAJOR == 5
151
152 DynamicJsonBuffer jsonBuffer;
153
154 JsonObject& json = jsonBuffer.parseObject((char*)payload);
155
156#endif
157
158#if ARDUINOJSON_VERSION_MAJOR == 6
159
160 DynamicJsonDocument json(1024);
161
162 deserializeJson(json, (char*) payload);
163
164#endif
165
166 String deviceId = json ["deviceId"];
167
168 String action = json ["action"];
169
170
171
172 if(action == "setPowerState") { // Switch or Light
173
174 String value = json ["value"];
175
176 if(value == "ON") {
177
178 turnOn(deviceId);
179
180 } else {
181
182 turnOff(deviceId);
183
184 }
185
186 }
187
188 else if (action == "SetTargetTemperature") {
189
190 String deviceId = json ["deviceId"];
191
192 String action = json ["action"];
193
194 String value = json ["value"];
195
196 }
197
198 else if (action == "test") {
199
200 Serial.println("[WSc] received test command from sinric.com");
201
202 }
203
204 }
205
206 break;
207
208 case WStype_BIN:
209
210 Serial.printf("[WSc] get binary length: %u\n", length);
211
212 break;
213
214 }
215
216}
217
218
219
220void setup() {
221
222 Serial.begin(115200);
223
224
225
226 // Relay PIN eg: https://github.com/wemos/D1_mini_Examples/blob/master/examples/04.Shields/Relay_Shield/Blink/Blink.ino
227
228 pinMode(relayPin1, OUTPUT);
229 pinMode(relayPin2, OUTPUT);
230
231
232 WiFiMulti.addAP(MySSID, MyWifiPassword);
233
234 Serial.println();
235
236 Serial.print("Connecting to Wifi: ");
237
238 Serial.println(MySSID);
239
240
241
242 // Waiting for Wifi connect
243
244 while(WiFiMulti.run() != WL_CONNECTED) {
245
246 delay(500);
247
248 Serial.print(".");
249
250 }
251
252 if(WiFiMulti.run() == WL_CONNECTED) {
253
254 Serial.println("");
255
256 Serial.print("WiFi connected. ");
257
258 Serial.print("IP address: ");
259
260 Serial.println(WiFi.localIP());
261
262 }
263
264
265
266 // server address, port and URL
267
268 webSocket.begin("iot.sinric.com", 80, "/");
269
270
271
272 // event handler
273
274 webSocket.onEvent(webSocketEvent);
275
276 webSocket.setAuthorization("apikey", MyApiKey);
277
278
279
280 // try again every 5000ms if connection has failed
281
282 webSocket.setReconnectInterval(5000); // If you see 'class WebSocketsClient' has no member named 'setReconnectInterval' error update arduinoWebSockets
283
284}
285
286
287
288void loop() {
289
290 if (timerStarted && millis() - previousMillis > 45000) { // Check if appliance was turned on for 5s
291 digitalWrite(relayPin1, LOW); // Turn off the relay after 5 seconds
292 digitalWrite(relayPin2, LOW); // Turn off the relay after 5 seconds
293 Serial.println("Turning off relays");
294 timerStarted = false; // Reset flag so it won't keep checking this if statement
295 }
296 webSocket.loop();
297
298 if(isConnected) {
299 uint64_t now = millis();
300
301 // Send heartbeat in order to avoid disconnections during ISP resetting IPs over night. Thanks @MacSass
302 if((now - heartbeatTimestamp) > HEARTBEAT_INTERVAL) {
303 heartbeatTimestamp = now;
304 webSocket.sendTXT("H");
305 }
306 }
307
308}
309
310
311
312// If you are going to use a push button to on/off the switch manually, use this function to update the status on the server
313
314// so it will reflect on Alexa app.
315
316// eg: setPowerStateOnServer("deviceid", "ON")
317
318
319
320// Call ONLY If status changed. DO NOT CALL THIS IN loop() and overload the server.
321
322void setPowerStateOnServer(String deviceId, String value) {
323
324#if ARDUINOJSON_VERSION_MAJOR == 5
325
326 DynamicJsonBuffer jsonBuffer;
327
328 JsonObject& root = jsonBuffer.createObject();
329
330#endif
331
332#if ARDUINOJSON_VERSION_MAJOR == 6
333
334 DynamicJsonDocument root(1024);
335
336#endif
337
338 root["deviceId"] = deviceId;
339
340 root["action"] = "setPowerState";
341
342 root["value"] = value;
343
344 StreamString databuf;
345
346#if ARDUINOJSON_VERSION_MAJOR == 5
347
348 root.printTo(databuf);
349
350#endif
351
352#if ARDUINOJSON_VERSION_MAJOR == 6
353
354 serializeJson(root, databuf);
355
356#endif
357
358
359
360 webSocket.sendTXT(databuf);
361
362}
363
364
365
366//eg: setPowerStateOnServer("deviceid", "CELSIUS", "25.0")
367
368
369
370// Call ONLY If status changed. DO NOT CALL THIS IN loop() and overload the server.
371
372void setTargetTemperatureOnServer(String deviceId, String value, String scale) {
373
374#if ARDUINOJSON_VERSION_MAJOR == 5
375
376 DynamicJsonBuffer jsonBuffer;
377
378 JsonObject& root = jsonBuffer.createObject();
379
380#endif
381
382#if ARDUINOJSON_VERSION_MAJOR == 6
383
384 DynamicJsonDocument root(1024);
385
386#endif
387
388 root["action"] = "SetTargetTemperature";
389
390 root["deviceId"] = deviceId;
391
392
393
394#if ARDUINOJSON_VERSION_MAJOR == 5
395
396 JsonObject& valueObj = root.createNestedObject("value");
397
398 JsonObject& targetSetpoint = valueObj.createNestedObject("targetSetpoint");
399
400#endif
401
402#if ARDUINOJSON_VERSION_MAJOR == 6
403
404 JsonObject valueObj = root.createNestedObject("value");
405
406 JsonObject targetSetpoint = valueObj.createNestedObject("targetSetpoint");
407
408#endif
409
410 targetSetpoint["value"] = value;
411
412 targetSetpoint["scale"] = scale;
413
414
415
416 StreamString databuf;
417
418#if ARDUINOJSON_VERSION_MAJOR == 5
419
420 root.printTo(databuf);
421
422#endif
423
424#if ARDUINOJSON_VERSION_MAJOR == 6
425
426 serializeJson(root, databuf);
427
428#endif
429
430
431
432 webSocket.sendTXT(databuf);
433
434}