kakopappa / sinric

Amazon Alexa Smart home skill / Google Home Action for ESP8266 / ESP32 / Arduino
https://sinric.com
285 stars 166 forks source link

Connection issues #350

Open marcosmoura91 opened 4 years ago

marcosmoura91 commented 4 years ago

First I would like to thank you for the amazing service you provide and I would like to ask a question about the connectivity issue that I am experiencing.

I have an nodemcu just for turning an LED On and off. What happens is I often lose connection between sinric to Esp8266 node mcu.

The consequences are the loss of commands during the "blackout"

If during one day I would send 1000 commands, I would say only 600 or less would actually make it to the nodemcu.

I see that many people have a similar kind of issue. I think the connection is really unstable. This happens at my home and at my work.

I know the problem is not with my Alexa because I test the connection using the test buttons in sinric.com.

Steve-Broderick commented 4 years ago

If you have it connected to a P.C. via Arduino IDE and can open a serial screen, put some debug code in the file. You may be dropping the connection which is a problem with the websockets 2.1.4 library, That version will drop the connection and the reboot the 8266, while the 8266 is rebooting your commands will not work. Drop back down to version 2.1.0 and see if the problem goes away.

You can post your code here and I will look at it, remember to remove your SSID and PASSWORD Text before posting.

marcosmoura91 commented 4 years ago

I might have a clue why I have this strange behavior. I have an ESP8266 Turning a LED on and off and this is always working.

My actual problem is on my Nodemcu and I think the problem might be because I am using it also to generate a webpage where I show a graph with temperature values and some buttons for manual turning off/on some outputs.

Can it be that my msdn is interfering with my websockets ? I am not experienced about this topic as I only use examples from the internet and edit them. While my nodemcu webpage always works and never has a problem i guess that it might somehow crash my websockets connection.

Here is my code for the nodemecu, I have many tabs where I organise my code so some of them are unrevelant for the problem and I wont post it completly as not to make the post too long:

I have my code devided in 5 tabs as follows : Main, drawGraph, Switchhandle, UpdateWebpage, websocket

Main :

#include <Arduino.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 <ESP8266WiFiMulti.h>
#include <StreamString.h>
//ESP8266WiFiMulti WiFiMulti;
WebSocketsClient webSocket;
WiFiClient client;
#define MyApiKey "MyApiKey " // TODO: Change to your sinric API Key. Your API Key is displayed on sinric.com dashboard
#define API_ENDPOINT "http://sinric.com"
#define HEARTBEAT_INTERVAL 300000 // 5 Minutes 
uint64_t heartbeatTimestamp = 0;
bool isConnected = false;

#include <ESP8266WiFi.h>
//#include <WiFiClient.h>
#include <ESP8266WebServer.h>
#include <ESP8266mDNS.h>
#include <Ticker.h>
#include <CircularBuffer.h>
#include <ir_Kelvinator.h>

#include <IRrecv.h>
#include <IRsend.h>

#include "DHTesp.h"
#ifdef ESP32
#pragma message(THIS EXAMPLE IS FOR ESP8266 ONLY!)
#error Select ESP8266 board.
#endif

// ############### IR Settings ################ //
uint16_t RECV_PIN = D1;
uint16_t RECV_OUTPIN = D0;
IRsend irsend(RECV_OUTPIN);
IRrecv irrecv(RECV_PIN);
IRKelvinatorAC ac(RECV_OUTPIN);

decode_results results;
DHTesp dht;
Ticker TimerInt;
CircularBuffer<int,80> temperatureHistory;
CircularBuffer<int,80> humidityHistory;

// ############## WIFI Settings ##################### //
MDNSResponder mdns;
const char* ssid = "ssid ";
const char* password = "password ";
ESP8266WebServer server(80);

String webPage = "";
String webPageTop = "";
String webPageEnd = " </body></html>";
String TempH = "";
int i=0;
int TempLog[100];
int HumLog[100];
int readsensor = 1;
int switch_TV = 0;
int intervalo_leitura = 300;// Timer interval for reading sensor values -  Seconds

void setup(void){
  irsend.begin();
  readsensor = 1; //Enable first reading after turning on
  temperatureHistory.clear(); //Clear buffer
  humidityHistory.clear(); //Clear buffer

  TimerInt.attach(intervalo_leitura, ReadSensorValues); // Timer interval for reading sensor values

  webPageTop += "<html><head><meta http-equiv='refresh' content='300'/><title>Cloud</title>";
  webPageTop += "<style>body { background-color: #cccccc; font-family: Arial, Helvetica, Sans-Serif; Color: #000088; }</style></head><body>";
  webPageTop += "<h1>Cloud</h1><p>Light <a href=\"socket1On\"><button>ON</button></a>&nbsp;<a href=\"socket1Off\"><button>OFF</button></a></p>";
  webPageTop += "<p>TV <a href=\"sockettvonoff\"><button>ON/OFF</button></a></p>";

  // preparing GPIOs
  pinMode(D2, OUTPUT);
  digitalWrite(D2, LOW);
  dht.setup(D4, DHTesp::DHT11);

  delay(1000);
  Serial.begin(115200);
  WiFi.begin(ssid, password);
  Serial.println("");

  // Wait for connection
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
  }
  Serial.println("");
  Serial.print("Connected to ");
  Serial.println(ssid);
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());

  if (mdns.begin("esp8266", WiFi.localIP())) {
     Serial.println("MDNS responder started");
  }

  server.on("/", [](){                         // SERVER ROOT
    updatedWebpage();
    server.send(200, "text/html", webPage); 
    }); 

  server.on("/socket1On", [](){               // SERVER  LED ON
    updatedWebpage();
    server.send(200, "text/html", webPage);
    digitalWrite(D2, HIGH);
    delay(1000);
  });
  server.on("/socket1Off", [](){              // SERVER  LED OFF 
    updatedWebpage();
    server.send(200, "text/html", webPage); 
    digitalWrite(D2, LOW);
    delay(1000); 
  });
    server.on("/sockettvonoff", [](){              // SERVER Switch TV 
    switch_TV=1;
    updatedWebpage();
    server.send(200, "text/html", webPage); 
    digitalWrite(D2, LOW);
    delay(1000); 
  });

  server.on("/test.svg", drawGraph);

  server.begin();
  Serial.println("HTTP server started");

  // 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 ###################### //

void loop(void){
  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");          
      }
  } 

  server.handleClient();

  if(switch_TV==1){
    // irsend.sendRaw(PPK_AC_OFF, 74, 38);
    //delay(2000);
    //irsend.sendRaw(PPK_AC_OFF, 74, 38);                  
    switch_TV=0;
  }

  if(readsensor==1){
    temperatureHistory.push(int(dht.getTemperature()));
    humidityHistory.push(int(dht.getHumidity()));
    readsensor=0;
  }
} //END OF LOOP

// ##### ReadSensorValues function called by the timer ############ //
void ReadSensorValues(void){ //Reads every 10 Sec
   readsensor=1;
}

Websocket tab:

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;
  }
}
Steve-Broderick commented 4 years ago

Hi,

I have researched mDNS application with the 8266, I had previously never used it before. I got a few APPS working with a DHT11 and one 'login' example I found. Your test case is too long and is missing several files, mostly .h files. If you want me to help further, please reduce the complexity of the test case to one simple switch being controlled by Sinric. Also let me know what library you are using for websockets.