kakopappa / sinric

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

setPowerStateOnServer not working #303

Closed MarGiang closed 5 years ago

MarGiang commented 5 years ago

Hello, I'm playing with Sinric to actuate a lamp using Alexa, and it seems wonderfull! The only issue I'm finding is that when I use the function setPowerStateOnServer(DEVICE1), it does not update the Alexa app. I'm calling the function when I call the turnon or turnoff funcion.

This is the sketch snipped: `#include //this needs to be first, or it all crashes and burns...

include //https://github.com/esp8266/Arduino

include

//needed for library

include

include

include //https://github.com/tzapu/WiFiManager

//Sinric Alexa stuff

include //

include //https://github.com/bblanchon/ArduinoJson

include

//OTA

include

define BUTTON_PIN D3

define LED D4

define RelVpin V1 //virtual pin assigned to the relay status

const int RELAY_PIN = D1;

include // https://github.com/bxparks/AceButton

using namespace ace_button;

AceButton button(BUTTON_PIN);

define HOSTNAME "WEMOS_Alexa"

int blynk_value = 0; //value of switch status coming from Blynk app int buttonState = 0; // current state of the button int lastButtonState = 0; // previous state of the button

//define your default values here, if there are different values in config.json, they are overwritten. char blynk_token[34] = "";

//flag for saving data bool shouldSaveConfig = false; WebSocketsClient webSocket; //WiFiClient client;

define HEARTBEAT_INTERVAL 300000 // 5 Minutes

uint64_t heartbeatTimestamp = 0;

define MyApiKey "" // TODO: Change to your sinric API Key. Your API Key is displayed on sinric.com dashboard

define DEVICE1 "" //TODO: Device ID of first device

bool isConnected = false;

include

Ticker ticker;

BlynkTimer timer; volatile bool state; int timer01; //timer variable for heartbeat

void handleEvent(AceButton*, uint8_t, uint8_t); void setPowerStateOnServer(String deviceId, String value);

//callback notifying us of the need to save config void saveConfigCallback () { Serial.println("Should save config"); shouldSaveConfig = true; }

void tick() { //toggle state int state = digitalRead(LED); // get the current state of GPIO1 pin digitalWrite(LED, !state); // set pin to the opposite state }

BLYNK_CONNECTED() { Blynk.syncAll(); }

//Read virtual pin 0 and turn on/off relay and led BLYNK_WRITE(RelVpin){ blynk_value = param.asInt(); digitalWrite(LED, blynk_value); if(blynk_value == 0){ turnOff(DEVICE1); } else if(blynk_value == 1){ turnOn(DEVICE1); } } void turnOn(String deviceId) {

blynk_value = 1;
Serial.print("Turn on device id: ");
Serial.println(deviceId);
Serial.println(blynk_value);  
Blynk.virtualWrite(RelVpin, blynk_value);
digitalWrite(RELAY_PIN, HIGH);
digitalWrite(LED, LOW);
setPowerStateOnServer(deviceId, "ON");   

}

void turnOff(String deviceId) {

 blynk_value = 0;
 Serial.print("Turn off Device ID: ");
 Serial.println(deviceId); 
 Serial.println(blynk_value);  
 Blynk.virtualWrite(RelVpin, blynk_value);
 digitalWrite(RELAY_PIN, LOW);
 digitalWrite(LED, HIGH);   
 setPowerStateOnServer(deviceId, "OFF");

}

void toggle(String deviceId){ blynk_value = !blynk_value; if(blynk_value == 0){ turnOff(deviceId); } else if(blynk_value == 1){ turnOn(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");
    }
  }
  break;
case WStype_BIN:
  Serial.printf("[WSc] get binary length: %u\n", length);
  break;

} } void heart(){ webSocket.sendTXT("H"); } void setup() { // put your setup code here, to run once: Serial.begin(115200); //set led pin as output pinMode(LED, OUTPUT); pinMode(RELAY_PIN, OUTPUT); ticker.attach(0.2, tick); const char *hostname = HOSTNAME; //clean FS, for testing //SPIFFS.format();

//read configuration from FS json Serial.println("mounting FS...");

if (SPIFFS.begin()) { Serial.println("mounted file system"); if (SPIFFS.exists("/config.json")) { ticker.attach(0.6, tick); //file exists, reading and loading Serial.println("reading config file"); File configFile = SPIFFS.open("/config.json", "r"); if (configFile) { Serial.println("opened config file"); size_t size = configFile.size(); // Allocate a buffer to store contents of the file. std::unique_ptr<char[]> buf(new char[size]);

    configFile.readBytes(buf.get(), size);
    DynamicJsonBuffer jsonBuffer;
    JsonObject& json = jsonBuffer.parseObject(buf.get());
    json.printTo(Serial);
    if (json.success()) {
      Serial.println("\nparsed json");

      strcpy(blynk_token, json["blynk_token"]);

    } else {
      Serial.println("failed to load json config");
    }
  }
}

} else { Serial.println("failed to mount FS"); } //end read

WiFiManagerParameter custom_blynk_token("blynk", "blynk token", blynk_token, 32);

//WiFiManager //Local intialization. Once its business is done, there is no need to keep it around WiFiManager wifiManager;

//set config save notify callback wifiManager.setSaveConfigCallback(saveConfigCallback);

wifiManager.addParameter(&custom_blynk_token);

if (!wifiManager.autoConnect("Alexa_Living_switch", "1234")) { Serial.println("failed to connect and hit timeout"); delay(3000); //reset and try again, or maybe put it to deep sleep ESP.reset(); delay(5000); }

//if you get here you have connected to the WiFi Serial.println("connected...yeey :)");

//read updated parameters strcpy(blynk_token, custom_blynk_token.getValue());

//save the custom parameters to FS if (shouldSaveConfig) { Serial.println("saving config"); DynamicJsonBuffer jsonBuffer; JsonObject& json = jsonBuffer.createObject(); json["blynk_token"] = blynk_token;

File configFile = SPIFFS.open("/config.json", "w");
if (!configFile) {
  Serial.println("failed to open config file for writing");
}

json.printTo(Serial);
json.printTo(configFile);
configFile.close();
//end save

}

//OTA ArduinoOTA.onStart([]() { Serial.println("Start OTA"); }); ArduinoOTA.onEnd([]() { Serial.println("\nEnd"); }); ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) { Serial.printf("Progress: %u%%\r", (progress / (total / 100))); }); ArduinoOTA.onError([](ota_error_t error) { Serial.printf("Error[%u]: ", error); if (error == OTA_AUTH_ERROR) Serial.println("Auth Failed"); else if (error == OTA_BEGIN_ERROR) Serial.println("Begin Failed"); else if (error == OTA_CONNECT_ERROR) Serial.println("Connect Failed"); else if (error == OTA_RECEIVE_ERROR) Serial.println("Receive Failed"); else if (error == OTA_END_ERROR) Serial.println("End Failed"); }); ArduinoOTA.setHostname(hostname); ArduinoOTA.begin(); Serial.println("local ip"); Serial.println(WiFi.localIP()); Blynk.config(blynk_token); /* while (Blynk.connect() == false) {

}*/ ticker.detach(); digitalWrite(LED, HIGH);

// Setup button // Button uses the built-in pull up register. pinMode(BUTTON_PIN, INPUT_PULLUP); // INPUT_PULLUP so no need a 10K resistor

button.init(BUTTON_PIN); button.setEventHandler(handleEvent);

//*SINRIC Stuff*****// // 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 timer01 = timer.setInterval(HEARTBEAT_INTERVAL, heart);

}

void loop() { // put your main code here, to run repeatedly: ArduinoOTA.handle(); Blynk.run(); timer.run(); webSocket.loop(); button.check(); }

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); }

void handleEvent(AceButton / button /, uint8_t eventType, uint8_t / buttonState */) { switch (eventType) { case AceButton::kEventPressed: Serial.println("kEventPressed"); toggle(DEVICE1); break; case AceButton::kEventReleased: Serial.println("kEventReleased"); break; } }`

kakopappa commented 5 years ago

duplicate