Open eddcaton opened 6 years ago
I have got this code, but i cannot control the relay... now
/*
Version 0.3 - March 06 2018
*/
#include "EmonLib.h"
EnergyMonitor emon1;
#include <Arduino.h>
#include <ESP8266WiFi.h>
#include <ESP8266WiFiMulti.h>
#include <WebSocketsClient.h> // https://github.com/kakopappa/sinric/wiki/How-to-add-dependency-libraries
#include <ArduinoJson.h> // https://github.com/kakopappa/sinric/wiki/How-to-add-dependency-libraries
#include <StreamString.h>
ESP8266WiFiMulti WiFiMulti;
WebSocketsClient webSocket;
WiFiClient client;
const int ledPin = D1;
#define MyApiKey "******" // TODO: Change to your sinric API Key. Your API Key is displayed on sinric.com dashboard
#define MySSID "*****" // TODO: Change to your Wifi network SSID
#define MyWifiPassword "****" // TODO: Change to your Wifi network password
#define HEARTBEAT_INTERVAL 300000 // 5 Minutes
uint64_t heartbeatTimestamp = 0;
bool isConnected = false;
void setPowerStateOnServer(String deviceId, String value);
//void setTargetTemperatureOnServer(String deviceId, String value, String scale);
// deviceId is the ID assgined to your smart-home-device in sinric.com dashboard. Copy it from dashboard and paste it here
void turnOn(String deviceId) {
if (deviceId == "****") // Device ID of first device
{
Serial.print("Turn on device id: ");
Serial.println(deviceId);
digitalWrite(ledPin, LOW);
}
else
{
Serial.print("Turn on for unknown device id: ");
Serial.println(deviceId);
}
}
void turnOff(String deviceId) {
if (deviceId == "***") // Device ID of first device
{
Serial.print("Turn off Device ID: ");
Serial.println(deviceId);
digitalWrite(ledPin, HIGH);
}
else
{
Serial.print("Turn off for unknown device id: ");
Serial.println(deviceId);
}
}
void webSocketEvent(WStype_t type, uint8_t * payload, size_t length) {
switch(type) {
case WStype_DISCONNECTED:
isConnected = false;
Serial.printf("[WSc] Webservice disconnected from sinric.com!\n");
break;
case WStype_CONNECTED: {
isConnected = true;
Serial.printf("[WSc] Service connected to sinric.com at url: %s\n", payload);
Serial.printf("Waiting for commands from sinric.com ...\n");
}
break;
case WStype_TEXT: {
Serial.printf("[WSc] get text: %s\n", payload);
// Example payloads
// For Switch or Light device types
// {"deviceId": xxxx, "action": "setPowerState", value: "ON"} // https://developer.amazon.com/docs/device-apis/alexa-powercontroller.html
// For Light device type
// Look at the light example in github
DynamicJsonBuffer jsonBuffer;
JsonObject& json = jsonBuffer.parseObject((char*)payload);
String deviceId = json ["deviceId"];
String action = json ["action"];
if(action == "setPowerState") { // Switch or Light
String value = json ["value"];
if(value == "ON") {
turnOn(deviceId);
} else {
turnOff(deviceId);
}
}
else if (action == "SetTargetTemperature") {
String deviceId = json ["deviceId"];
String action = json ["action"];
String value = json ["value"];
}
else if (action == "test") {
Serial.println("[WSc] received test command from sinric.com");
}
}
break;
case WStype_BIN:
Serial.printf("[WSc] get binary length: %u\n", length);
break;
}
}
void setup() {
Serial.begin(115200);
emon1.current(A0, 111.1); // Current: input pin, calibration.
WiFiMulti.addAP(MySSID, MyWifiPassword);
Serial.println();
Serial.print("Connecting to Wifi: ");
Serial.println(MySSID);
// Waiting for Wifi connect
while(WiFiMulti.run() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
if(WiFiMulti.run() == WL_CONNECTED) {
Serial.println("");
Serial.print("WiFi connected. ");
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
}
pinMode(ledPin, OUTPUT); // initialize digital ledPin as an output.
delay(10);
digitalWrite(ledPin, HIGH); // Wemos BUILTIN_LED is active Low, so high is off
// server address, port and URL
webSocket.begin("iot.sinric.com", 80, "/");
// event handler
webSocket.onEvent(webSocketEvent);
webSocket.setAuthorization("apikey", MyApiKey);
// try again every 5000ms if connection has failed
webSocket.setReconnectInterval(5000); // If you see 'class WebSocketsClient' has no member named 'setReconnectInterval' error update arduinoWebSockets
}
void loop() {
webSocket.loop();
int volts = 1;
int Irms = emon1.calcIrms(1480); // Calculate Irms only
Serial.println(Irms);
if (Irms > volts)
{
setPowerStateOnServer("***", "ON");
}
else if (Irms < volts)
{
setPowerStateOnServer("***", "OFF");
}
if(isConnected) {
uint64_t now = millis();
// Send heartbeat in order to avoid disconnections during ISP resetting IPs over night. Thanks @MacSass
if((now - heartbeatTimestamp) > HEARTBEAT_INTERVAL) {
heartbeatTimestamp = now;
webSocket.sendTXT("H");
}
}
}
// 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
// so it will reflect on Alexa app.
// eg: setPowerStateOnServer("deviceid", "ON")
void setPowerStateOnServer(String deviceId, String value) {
DynamicJsonBuffer jsonBuffer;
JsonObject& root = jsonBuffer.createObject();
root["deviceId"] = deviceId;
root["action"] = "setPowerState";
root["value"] = value;
StreamString databuf;
root.printTo(databuf);
webSocket.sendTXT(databuf);
}
use the setPowerStateOnServer function in the above sketch to update the on/off status in the server.
I think i am having issues with this piece of code as sinric is not getting updated
`int volts = 1;
int Irms = emon1.calcIrms(1480); // Calculate Irms only
Serial.println(Irms);
if (Irms > volts)
{
setPowerStateOnServer("", "ON");
}
else if (Irms < volts)
{
setPowerStateOnServer("", "OFF");
}`
Hey i have changed some of the coding: `void loop() { webSocket.loop(); float volts = 1.0; float Irms = emon1.calcIrms(1480); // Calculate Irms only Serial.println(Irms, 2); // print 2 decimal places if (Irms >= volts) { setPowerStateOnServer("", "ON"); } else { setPowerStateOnServer("", "OFF");
}
`
But for some reason Sinric does not seem to update.
I have checked alexa app and it has not changed the status of the light.
as you know, loop() gets executed in a loop very fast. You are sending either on or off status to server too often. This is bad. very bad. This will slow down the server a lot. Please fix this
Okay, this is fixed. Here is my current code, it seems to update the server on power up only. can you advise? `/ Version 0.3 - March 06 2018 /
EnergyMonitor emon1;
ESP8266WiFiMulti WiFiMulti; WebSocketsClient webSocket; WiFiClient client; const int ledPin = D1;
uint64_t heartbeatTimestamp = 0; bool isConnected = false;
void setPowerStateOnServer(String deviceId, String value); //void setTargetTemperatureOnServer(String deviceId, String value, String scale);
// deviceId is the ID assgined to your smart-home-device in sinric.com dashboard. Copy it from dashboard and paste it here
void turnOn(String deviceId) {
if (deviceId == "") // Device ID of first device
{
Serial.print("Turn on device id: ");
Serial.println(deviceId);
digitalWrite(ledPin, LOW);
}
else
{
Serial.print("Turn on for unknown device id: ");
Serial.println(deviceId);
}
}
void turnOff(String deviceId) {
if (deviceId == "") // Device ID of first device
{
Serial.print("Turn off Device ID: ");
Serial.println(deviceId);
digitalWrite(ledPin, HIGH);
}
else
{
Serial.print("Turn off for unknown device id: ");
Serial.println(deviceId);
}
}
void webSocketEvent(WStype_t type, uint8_t * payload, size_t length) {
switch(type) {
case WStype_DISCONNECTED:
isConnected = false;
Serial.printf("[WSc] Webservice disconnected from sinric.com!\n");
break;
case WStype_CONNECTED: {
isConnected = true;
Serial.printf("[WSc] Service connected to sinric.com at url: %s\n", payload);
Serial.printf("Waiting for commands from sinric.com ...\n");
}
break;
case WStype_TEXT: {
Serial.printf("[WSc] get text: %s\n", payload);
// Example payloads
// For Switch or Light device types
// {"deviceId": xxxx, "action": "setPowerState", value: "ON"} // https://developer.amazon.com/docs/device-apis/alexa-powercontroller.html
// For Light device type
// Look at the light example in github
DynamicJsonBuffer jsonBuffer;
JsonObject& json = jsonBuffer.parseObject((char*)payload);
String deviceId = json ["deviceId"];
String action = json ["action"];
if(action == "setPowerState") { // Switch or Light
String value = json ["value"];
if(value == "ON") {
turnOn(deviceId);
} else {
turnOff(deviceId);
}
}
else if (action == "test") {
Serial.println("[WSc] received test command from sinric.com");
}
//setPowerStateOnServer("", "ON");
float volts = 1.0; float Irms = emon1.calcIrms(1480); // Calculate Irms only // //Serial.println(Irms, 2); // print 2 decimal places if (Irms >= volts) {
setPowerStateOnServer("", "ON");
Serial.print("Light Is On");
} else { setPowerStateOnServer("", "OFF"); Serial.print("Light Is Off");
}
}
break;
case WStype_BIN:
Serial.printf("[WSc] get binary length: %u\n", length);
break;
} }
void setup() { Serial.begin(115200); emon1.current(A0, 111.1); WiFiMulti.addAP(MySSID, MyWifiPassword); Serial.println(); Serial.print("Connecting to Wifi: "); Serial.println(MySSID);
// Waiting for Wifi connect while(WiFiMulti.run() != WL_CONNECTED) { delay(500); Serial.print("."); } if(WiFiMulti.run() == WL_CONNECTED) { Serial.println(""); Serial.print("WiFi connected. "); Serial.print("IP address: "); Serial.println(WiFi.localIP()); }
pinMode(ledPin, OUTPUT); // initialize digital ledPin as an output. delay(10); digitalWrite(ledPin, HIGH); // Wemos BUILTIN_LED is active Low, so high is off
// server address, port and URL webSocket.begin("iot.sinric.com", 80, "/");
// event handler webSocket.onEvent(webSocketEvent); webSocket.setAuthorization("apikey", MyApiKey);
// try again every 5000ms if connection has failed webSocket.setReconnectInterval(5000); // If you see 'class WebSocketsClient' has no member named 'setReconnectInterval' error update arduinoWebSockets
} void loop() { webSocket.loop();
if(isConnected) { uint64_t now = millis();
// Send heartbeat in order to avoid disconnections during ISP resetting IPs over night. Thanks @MacSass
if((now - heartbeatTimestamp) > HEARTBEAT_INTERVAL) {
heartbeatTimestamp = now;
webSocket.sendTXT("H");
}
}
}
// 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 // so it will reflect on Alexa app.
void setPowerStateOnServer(String deviceId, String value) { DynamicJsonBuffer jsonBuffer; JsonObject& root = jsonBuffer.createObject(); root["deviceId"] = deviceId; root["action"] = "setPowerState"; root["value"] = value; StreamString databuf; root.printTo(databuf);
webSocket.sendTXT(databuf); } `
Dear @eddcaton, good work done. However, the use of variable name volts is confusing (e.g. float volts = 1.0;). You are measuring/ comparing current and not voltage. By the way, What is the CT coil specification?
Hi, @eddcaton I would like to know if you had it working. I'm trying to build an Alexa switch with an esp8266 with a physical switch to update Sinric by sending 5V to an input of the esp8266. I've been looking everywhere and your code is the closest of what I'm trying to build. Where did you connect your coil?
Hey @philb1192, I couldn't get the CT Coil to work, it constantly gave false reading back. I have however got the system working with a 240v Relay which is switched on when the light is on. Then i have connected the NO and Common on the relay to the node MCU which updates Sinric if the light is on or off ever 5 minutes.
Thx @eddcaton I have my project working! Im using a GPIO as an input to receive the signal from a physical switch and compare it to the device. After I did a small truth table to turn on a relay that will activate my light when one or another is on.
void loop() { if (digitalRead(device_1) == LOW && digitalRead(threeway_IN) == LOW) { digitalWrite(relay_OUT, LOW); setPowerStateOnServer("", "OFF"); Serial.print("Light Is Off"); }
if (digitalRead(device_1) == HIGH && digitalRead(threeway_IN) == LOW) { digitalWrite(relay_OUT, HIGH); setPowerStateOnServer("", "ON"); Serial.print("Light Is On"); }
if (digitalRead(device_1) == LOW && digitalRead(threeway_IN) == HIGH) { digitalWrite(relay_OUT, HIGH); setPowerStateOnServer("", "ON"); Serial.print("Light Is On"); }
if (digitalRead(device_1) == HIGH && digitalRead(threeway_IN) == HIGH) { digitalWrite(relay_OUT, LOW); setPowerStateOnServer("", "OFF"); Serial.print("Light Is Off"); }
Hi,
I am not sure about you setup but please make sure you don’t send the status update to server on every loop. This will slow the server and relay responding to other 900 devices connected
On Sat, 13 Apr 2019 at 8:05 PM philb1192 notifications@github.com wrote:
Thx @eddcaton https://github.com/eddcaton I have my project working! Im using a GPIO as an input to receive the signal from a physical switch and compare it to the device. After I did a small truth table to turn on a relay that will activate my light when one or another is on.
void loop() { if (digitalRead(device_1) == LOW && digitalRead(threeway_IN) == LOW) { digitalWrite(relay_OUT, LOW); setPowerStateOnServer("", "OFF"); Serial.print("Light Is Off"); }
if (digitalRead(device_1) == HIGH && digitalRead(threeway_IN) == LOW) { digitalWrite(relay_OUT, HIGH); setPowerStateOnServer("", "ON"); Serial.print("Light Is On"); }
if (digitalRead(device_1) == LOW && digitalRead(threeway_IN) == HIGH) { digitalWrite(relay_OUT, HIGH); setPowerStateOnServer("", "ON"); Serial.print("Light Is On"); }
if (digitalRead(device_1) == HIGH && digitalRead(threeway_IN) == HIGH) { digitalWrite(relay_OUT, LOW); setPowerStateOnServer("", "OFF"); Serial.print("Light Is Off"); }
— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/kakopappa/sinric/issues/131#issuecomment-482807537, or mute the thread https://github.com/notifications/unsubscribe-auth/AHIM5g_1gR2QHBKTmXUDQyNIaPMnCM-bks5vgdYIgaJpZM4XLgBh .
Hi kakopappa, in a nutshell, what I'm trying to do is to have an external switch connected to the esp8266. When I press it, the light turns on, but the status in sinric doesn't change. Consequently, I have to tell Alexa to turn on the light to turn it off.
I'm fairly new in coding and I don't get what you mean by ''don’t send the status update to server on every loop''. Could you look my code and point me in the right direction? Thx.
void loop() {
if (digitalRead(device_1) == LOW && digitalRead(threeway_IN) == LOW) { digitalWrite(relay_OUT, LOW); Serial.print("Light Is Off / D0,T0"); Serial.print('\n'); }
if (digitalRead(device_1) == HIGH && digitalRead(threeway_IN) == LOW) { digitalWrite(relay_OUT, HIGH); Serial.print("Light Is On / D1,T0"); Serial.print('\n'); }
if (digitalRead(device_1) == LOW && digitalRead(threeway_IN) == HIGH) { digitalWrite(relay_OUT, HIGH); Serial.print("Light Is On / D0,T1"); Serial.print('\n'); }
if (digitalRead(device_1) == HIGH && digitalRead(threeway_IN) == HIGH) { digitalWrite(relay_OUT, LOW); Serial.print("Light Is Off / D1,T1"); Serial.print('\n'); }
if (digitalRead(relay_OUT) == HIGH) { setPowerStateOnServer("", "ON"); Serial.print("Server On"); Serial.print('\n'); }
else { setPowerStateOnServer("", "OFF"); Serial.print("Server Off"); Serial.print('\n'); }
if (digitalRead(relay_OUT) == HIGH) { setPowerStateOnServer("", "ON"); Serial.print("Server On"); Serial.print('\n'); }
else
{ setPowerStateOnServer("", "OFF"); Serial.print("Server Off"); Serial.print('\n'); }
If you look at this logic you are sending OFF to the server regardless whether user pushed the button or not. Arduino loop sends about 1000 messages to the server per second and the server cpu goes high updating your status on the database. That’s what I mean by don’t send it in the loop
Take a look at the push button example code in the repo
On Tue, 25 Jun 2019 at 9:04 AM philb1192 notifications@github.com wrote:
Hi kakopappa, in a nutshell, what I'm trying to do is to have an external switch connected to the esp8266. When I press it, the light turns on, but the status in sinric doesn't change. Consequently, I have to tell Alexa to turn on the light to turn it off.
I'm fairly new in coding and I don't get what you mean by ''don’t send the status update to server on every loop''. Could you look my code and point me in the right direction? Thx.
void loop() {
if (digitalRead(device_1) == LOW && digitalRead(threeway_IN) == LOW) { digitalWrite(relay_OUT, LOW); Serial.print("Light Is Off / D0,T0"); Serial.print('\n'); }
if (digitalRead(device_1) == HIGH && digitalRead(threeway_IN) == LOW) { digitalWrite(relay_OUT, HIGH); Serial.print("Light Is On / D1,T0"); Serial.print('\n'); }
if (digitalRead(device_1) == LOW && digitalRead(threeway_IN) == HIGH) { digitalWrite(relay_OUT, HIGH); Serial.print("Light Is On / D0,T1"); Serial.print('\n'); }
if (digitalRead(device_1) == HIGH && digitalRead(threeway_IN) == HIGH) { digitalWrite(relay_OUT, LOW); Serial.print("Light Is Off / D1,T1"); Serial.print('\n'); }
if (digitalRead(relay_OUT) == HIGH) { setPowerStateOnServer("", "ON"); Serial.print("Server On"); Serial.print('\n'); }
else { setPowerStateOnServer("", "OFF"); Serial.print("Server Off"); Serial.print('\n'); }
— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/kakopappa/sinric/issues/131?email_source=notifications&email_token=ABZAZZTFOUHYGPKMXGMSVIDP4F4MNA5CNFSM4FZOABQ2YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGODYOXRVI#issuecomment-505247957, or mute the thread https://github.com/notifications/unsubscribe-auth/ABZAZZQBDSL5YBGH7VYFH3LP4F4MNANCNFSM4FZOABQQ .
Hey,
Is there a way to update sinric from the node MCU to change the state of a light switch?
I have a manual override on my lighting for ease of use, and when you turn the lights off manually, sinric thinks that the light is still on. So you have to ask Alexa to turn the light off to actually turn it on.
I have managed to connect a CT Coil to the manual switch line, which i would like to report back to sinric if there is current over 1amp then the light is on and if it is under 1amp then the light is off.
I hope that makes sense...
Any assistance would be very helpful.
Edd