kakopappa / arduino-esp8266-alexa-wemo-switch

Amazon Alexa + WeMos switch made with Arduino D1 Mini
https://sinric.pro
MIT License
281 stars 249 forks source link

Add a pushbutton switch to toggle relay - NOT Sonos #18

Closed dougstrickland closed 7 years ago

dougstrickland commented 7 years ago

I am trying to add a pushbutton switch on one of the GPIO pins, then toggle the relay between on-off states. This makes it possible to Manually turn the relay on or off with the push of a button, and not having to use Alexa every time.

I am saving the current on/off state, so simply flip it whenever the button is pushed, but I can't get the switch to be read.

Any suggestions are appreciated!

kakopappa commented 7 years ago

Push buttons often generate spurious open close singles when pressed. it's called Debounce. You have to handle it properly to get the push button working.

https://www.youtube.com/watch?v=jYOYgU2vlSE

I like to recommend you to turn on /off a LED light with a push button first and then change the code to turn on /off relay.

https://learn.sparkfun.com/tutorials/sik-experiment-guide-for-arduino---v32/experiment-5-push-buttons

dougstrickland commented 7 years ago

Thanks for the suggestion. I've debounced the switch, and checked it with a scope. The switch is working correctly. I don't think it's getting to my code, seems to be looping through something else. Would you recommend putting it at the top of the loop script, or somewhere in the middle. I currently have it at the bottom.

Svengali86 commented 7 years ago

Hi I did this works well.

'#include

include

include

include

void prepareIds(); boolean connectWifi(); boolean connectUDP(); void startHttpServer(); void turnOnRelay(); void turnOffRelay();

const char* ssid = "**"; const char* password = "*****";

unsigned int localPort = 1900; // local port to listen on

WiFiUDP UDP; boolean udpConnected = false; IPAddress ipMulti(239, 255, 255, 250); unsigned int portMulti = 1900; // local port to listen on

ESP8266WebServer HTTP(80);

boolean wifiConnected = false;

char packetBuffer[UDP_TX_PACKET_MAX_SIZE]; //buffer to hold incoming packet,

String serial; String persistent_uuid; String device_name;

const int relayPin = 2; const int switchPin = 3;

boolean cannotConnectToWifi = false;

int switchState = 0;

void setup() { Serial.begin(115200);

// Setup Relay pinMode(relayPin, OUTPUT);

// Setup Switch pinMode(switchPin, INPUT);

turnOffRelay(); switchState = 0; Serial.println("Setting relay to off - setting value to 0");

prepareIds();

// Initialise wifi connection wifiConnected = connectWifi();

// only proceed if wifi connection successful if(wifiConnected){ udpConnected = connectUDP();

if (udpConnected){
  // initialise pins if needed 
  startHttpServer();
}

}
}

void loop() {

if (digitalRead(switchPin)){ delay(250); if (!digitalRead(switchPin)){ switchState = !switchState; Serial.print("Switch Pressed - Relay now ");

// Show and change Relay State
if (switchState){ Serial.println("ON"); turnOnRelay(); } else { Serial.println("OFF"); turnOffRelay(); } delay(500); } }

HTTP.handleClient(); delay(1);

// if there's data available, read a packet // check if the WiFi and UDP connections were successful if(wifiConnected){ if(udpConnected){
// if there’s data available, read a packet int packetSize = UDP.parsePacket();

  if(packetSize) {
    Serial.println("");
    Serial.print("Received packet of size ");
    Serial.println(packetSize);
    Serial.print("From ");
    IPAddress remote = UDP.remoteIP();

    for (int i =0; i < 4; i++) {
      Serial.print(remote[i], DEC);
      if (i < 3) {
        Serial.print(".");
      }
    }

    Serial.print(", port ");
    Serial.println(UDP.remotePort());

    int len = UDP.read(packetBuffer, 255);

    if (len > 0) {
        packetBuffer[len] = 0;
    }

    String request = packetBuffer;
    //Serial.println("Request:");
    //Serial.println(request);

    if(request.indexOf('M-SEARCH') > 0) {
        if(request.indexOf("urn:Belkin:device:**") > 0) {
            Serial.println("Responding to search request ...");
            respondToSearch();
        }
    }
  }

  delay(10);
}

} else { // Turn on/off to indicate cannot connect ..
} }

void prepareIds() { uint32_t chipId = ESP.getChipId(); char uuid[64]; sprintf_P(uuid, PSTR("38323636-4558-4dda-9188-cda0e6%02x%02x%02x"), (uint16_t) ((chipId >> 16) & 0xff), (uint16_t) ((chipId >> 8) & 0xff), (uint16_t) chipId & 0xff);

serial = String(uuid); persistent_uuid = "Socket-1_0-" + serial; device_name = "Potato"; }

void respondToSearch() { Serial.println(""); Serial.print("Sending response to "); Serial.println(UDP.remoteIP()); Serial.print("Port : "); Serial.println(UDP.remotePort());

IPAddress localIP = WiFi.localIP();
char s[16];
sprintf(s, "%d.%d.%d.%d", localIP[0], localIP[1], localIP[2], localIP[3]);

String response = 
     "HTTP/1.1 200 OK\r\n"
     "CACHE-CONTROL: max-age=86400\r\n"
     "DATE: Fri, 15 Apr 2016 04:56:29 GMT\r\n"
     "EXT:\r\n"
     "LOCATION: http://" + String(s) + ":80/setup.xml\r\n"
     "OPT: \"http://schemas.upnp.org/upnp/1/0/\"; ns=01\r\n"
     "01-NLS: b9200ebb-736d-4b93-bf03-835149d13983\r\n"
     "SERVER: Unspecified, UPnP/1.0, Unspecified\r\n"
     "ST: urn:Belkin:device:**\r\n"
     "USN: uuid:" + persistent_uuid + "::urn:Belkin:device:**\r\n"
     "X-User-Agent: redsonic\r\n\r\n";

UDP.beginPacket(UDP.remoteIP(), UDP.remotePort());
UDP.write(response.c_str());
UDP.endPacket();                    

 Serial.println("Response sent !");

}

void startHttpServer() { HTTP.on("/index.html", HTTP_GET, [](){ Serial.println("Got Request index.html ...\n"); HTTP.send(200, "text/plain", "potato"); });

HTTP.on("/upnp/control/basicevent1", HTTP_POST, []() {
  Serial.println("########## Responding to  /upnp/control/basicevent1 ... ##########");      

  //for (int x=0; x <= HTTP.args(); x++) {
  //  Serial.println(HTTP.arg(x));
  //}

  String request = HTTP.arg(0);      
  Serial.print("request:");
  Serial.println(request);

  if(request.indexOf("<BinaryState>1</BinaryState>") > 0) {
      Serial.println("Got Turn on request");
      turnOnRelay();
  }

  if(request.indexOf("<BinaryState>0</BinaryState>") > 0) {
      Serial.println("Got Turn off request");
      turnOffRelay();
  }

  HTTP.send(200, "text/plain", "");
});

HTTP.on("/eventservice.xml", HTTP_GET, [](){
  Serial.println(" ########## Responding to eventservice.xml ... ########\n");
  String eventservice_xml = "<?scpd xmlns=\"urn:Belkin:service-1-0\"?>"
        "<actionList>"
          "<action>"
            "<name>SetBinaryState</name>"
            "<argumentList>"
              "<argument>"
                "<retval/>"
                "<name>BinaryState</name>"
                "<relatedStateVariable>BinaryState</relatedStateVariable>"
                "<direction>in</direction>"
              "</argument>"
            "</argumentList>"
             "<serviceStateTable>"
              "<stateVariable sendEvents=\"yes\">"
                "<name>BinaryState</name>"
                "<dataType>Boolean</dataType>"
                "<defaultValue>0</defaultValue>"
              "</stateVariable>"
              "<stateVariable sendEvents=\"yes\">"
                "<name>level</name>"
                "<dataType>string</dataType>"
                "<defaultValue>0</defaultValue>"
              "</stateVariable>"
            "</serviceStateTable>"
          "</action>"
        "</scpd>\r\n"
        "\r\n";

  HTTP.send(200, "text/plain", eventservice_xml.c_str());
});

HTTP.on("/setup.xml", HTTP_GET, [](){
  Serial.println(" ########## Responding to setup.xml ... ########\n");

  IPAddress localIP = WiFi.localIP();
  char s[16];
  sprintf(s, "%d.%d.%d.%d", localIP[0], localIP[1], localIP[2], localIP[3]);

  String setup_xml = "<?xml version=\"1.0\"?>"
        "<root>"
         "<device>"
            "<deviceType>urn:Belkin:device:controllee:1</deviceType>"
            "<friendlyName>"+ device_name +"</friendlyName>"
            "<manufacturer>Belkin International Inc.</manufacturer>"
            "<modelName>Emulated Socket</modelName>"
            "<modelNumber>3.1415</modelNumber>"
            "<UDN>uuid:"+ persistent_uuid +"</UDN>"
            "<serialNumber>221517K0101769</serialNumber>"
            "<binaryState>0</binaryState>"
            "<serviceList>"
              "<service>"
                  "<serviceType>urn:Belkin:service:basicevent:1</serviceType>"
                  "<serviceId>urn:Belkin:serviceId:basicevent1</serviceId>"
                  "<controlURL>/upnp/control/basicevent1</controlURL>"
                  "<eventSubURL>/upnp/event/basicevent1</eventSubURL>"
                  "<SCPDURL>/eventservice.xml</SCPDURL>"
              "</service>"
          "</serviceList>" 
          "</device>"
        "</root>\r\n"
        "\r\n";

    HTTP.send(200, "text/xml", setup_xml.c_str());

    Serial.print("Sending :");
    Serial.println(setup_xml);
});

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

}

// connect to wifi – returns true if successful or false if not boolean connectWifi(){ boolean state = true; int i = 0;

WiFi.mode(WIFI_STA); WiFi.begin(ssid, password); Serial.println(""); Serial.println("Connecting to WiFi");

// Wait for connection Serial.print("Connecting ..."); while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); if (i > 10){ state = false; break; } i++; }

if (state){ Serial.println(""); Serial.print("Connected to "); Serial.println(ssid); Serial.print("IP address: "); Serial.println(WiFi.localIP()); } else { Serial.println(""); Serial.println("Connection failed."); }

return state; }

boolean connectUDP(){ boolean state = false;

Serial.println(""); Serial.println("Connecting to UDP");

if(UDP.beginMulticast(WiFi.localIP(), ipMulti, portMulti)) { Serial.println("Connection successful"); state = true; } else{ Serial.println("Connection failed"); }

return state; }

void turnOnRelay() { digitalWrite(relayPin, HIGH); // turn on relay with voltage HIGH switchState = 1; }

void turnOffRelay() { digitalWrite(relayPin, LOW); // turn off relay with voltage LOW switchState = 0; }'

dougstrickland commented 7 years ago

I'm getting a bunch of compile errors, starting with an empty #include on line 4. I've tried working through the syntax errors, but I seem to be making it worse. Can you try compiling my script and see what you get?

include

include

include

// #include

void prepareIds(); boolean connectWifi(); boolean connectUDP(); void startHttpServer(); void turnOnRelay(); void turnOffRelay();

const char ssid = "buddha"; const char password = "0305196001161955";

unsigned int localPort = 1900; // local port to listen on

WiFiUDP UDP; boolean udpConnected = false; IPAddress ipMulti(239, 255, 255, 250); unsigned int portMulti = 1900; // local port to listen on

ESP8266WebServer HTTP(80);

boolean wifiConnected = false;

char packetBuffer[UDP_TX_PACKET_MAX_SIZE]; //buffer to hold incoming packet,

String serial; String persistent_uuid; String device_name;

const int relayPin = 2; const int switchPin = 3;

boolean cannotConnectToWifi = false;

int switchState = 0;

void setup() { Serial.begin(115200);

// Setup Relay pinMode(relayPin, OUTPUT);

// Setup Switch pinMode(switchPin, INPUT);

turnOffRelay(); switchState = 0; Serial.println("Setting relay to off - setting value to 0");

prepareIds();

// Initialise wifi connection wifiConnected = connectWifi();

// only proceed if wifi connection successful if(wifiConnected){ udpConnected = connectUDP();

if (udpConnected){ // initialise pins if needed startHttpServer(); } } }

void loop() {

if (digitalRead(switchPin)){ delay(250); if (!digitalRead(switchPin)){ switchState = !switchState; Serial.print("Switch Pressed - Relay now ");

// Show and change Relay State if (switchState){ Serial.println("ON"); turnOnRelay(); } else { Serial.println("OFF"); turnOffRelay(); } delay(500); } }

HTTP.handleClient(); delay(1);

// if there's data available, read a packet // check if the WiFi and UDP connections were successful if(wifiConnected){ if(udpConnected){ // if there’s data available, read a packet int packetSize = UDP.parsePacket();

if(packetSize) { Serial.println(""); Serial.print("Received packet of size "); Serial.println(packetSize); Serial.print("From "); IPAddress remote = UDP.remoteIP();

for (int i =0; i < 4; i++) {
  Serial.print(remote[i], DEC);
  if (i < 3) {
    Serial.print(".");
  }
}

Serial.print(", port ");
Serial.println(UDP.remotePort());

int len = UDP.read(packetBuffer, 255);

if (len > 0) {
    packetBuffer[len] = 0;
}

String request = packetBuffer;
//Serial.println("Request:");
//Serial.println(request);

if(request.indexOf('M-SEARCH') > 0) {
    if(request.indexOf("urn:Belkin:device:**") > 0) {
        Serial.println("Responding to search request ...");
        respondToSearch();
    }
}

}

delay(10); } } else { // Turn on/off to indicate cannot connect .. } }

void prepareIds() { uint32_t chipId = ESP.getChipId(); char uuid[64]; sprintf_P(uuid, PSTR("38323636-4558-4dda-9188-cda0e6%02x%02x%02x"), (uint16_t) ((chipId >> 16) & 0xff), (uint16_t) ((chipId >> 8) & 0xff), (uint16_t) chipId & 0xff);

serial = String(uuid); persistent_uuid = "Socket-1_0-" + serial; device_name = "Potato"; }

void respondToSearch() { Serial.println(""); Serial.print("Sending response to "); Serial.println(UDP.remoteIP()); Serial.print("Port : "); Serial.println(UDP.remotePort());

IPAddress localIP = WiFi.localIP(); char s[16]; sprintf(s, "%d.%d.%d.%d", localIP[0], localIP[1], localIP[2], localIP[3]);

String response = "HTTP/1.1 200 OK\r\n" "CACHE-CONTROL: max-age=86400\r\n" "DATE: Fri, 15 Apr 2016 04:56:29 GMT\r\n" "EXT:\r\n" "LOCATION: http://" + String(s) + ":80/setup.xml\r\n" "OPT: \"http://schemas.upnp.org/upnp/1/0/\"; ns=01\r\n" "01-NLS: b9200ebb-736d-4b93-bf03-835149d13983\r\n" "SERVER: Unspecified, UPnP/1.0, Unspecified\r\n" "ST: urn:Belkin:device:\r\n" "USN: uuid:" + persistent_uuid + "::urn:Belkin:device:\r\n" "X-User-Agent: redsonic\r\n\r\n";

UDP.beginPacket(UDP.remoteIP(), UDP.remotePort()); UDP.write(response.c_str()); UDP.endPacket();

Serial.println("Response sent !"); }

void startHttpServer() { HTTP.on("/index.html", HTTP_GET, { Serial.println("Got Request index.html ...\n"); HTTP.send(200, "text/plain", "potato"); });

HTTP.on("/upnp/control/basicevent1", HTTP_POST, []() { Serial.println("########## Responding to /upnp/control/basicevent1 ... ##########");

//for (int x=0; x <= HTTP.args(); x++) { // Serial.println(HTTP.arg(x)); //}

String request = HTTP.arg(0);
Serial.print("request:"); Serial.println(request);

if(request.indexOf("1") > 0) { Serial.println("Got Turn on request"); turnOnRelay(); }

if(request.indexOf("0") > 0) { Serial.println("Got Turn off request"); turnOffRelay(); }

HTTP.send(200, "text/plain", ""); });

HTTP.on("/eventservice.xml", HTTP_GET, [](){ Serial.println(" ########## Responding to eventservice.xml ... ########\n"); String eventservice_xml = "<?scpd xmlns=\"urn:Belkin:service-1-0\"?>" "" "" "SetBinaryState" "" "" "" "BinaryState" "BinaryState" "in" "" "" "" "<stateVariable sendEvents=\"yes\">" "BinaryState" "Boolean" "0" "" "<stateVariable sendEvents=\"yes\">" "level" "string" "0" "" "" "" "\r\n" "\r\n";

HTTP.send(200, "text/plain", eventservice_xml.c_str()); });

HTTP.on("/setup.xml", HTTP_GET, [](){ Serial.println(" ########## Responding to setup.xml ... ########\n");

IPAddress localIP = WiFi.localIP(); char s[16]; sprintf(s, "%d.%d.%d.%d", localIP[0], localIP[1], localIP[2], localIP[3]);

String setup_xml = "<?xml version=\"1.0\"?>" "" "" "urn:Belkin:device:controllee:1" ""+ device_name +"" "Belkin International Inc." "Emulated Socket" "3.1415" "uuid:"+ persistent_uuid +"" "221517K0101769" "0" "" "" "urn:Belkin:service:basicevent:1" "urn:Belkin:serviceId:basicevent1" "/upnp/control/basicevent1" "/upnp/event/basicevent1" "/eventservice.xml" "" "" "" "\r\n" "\r\n";

HTTP.send(200, "text/xml", setup_xml.c_str());

Serial.print("Sending :");
Serial.println(setup_xml);

});

HTTP.begin();
Serial.println("HTTP Server started .."); }

// connect to wifi – returns true if successful or false if not boolean connectWifi(){ boolean state = true; int i = 0;

WiFi.mode(WIFI_STA); WiFi.begin(ssid, password); Serial.println(""); Serial.println("Connecting to WiFi");

// Wait for connection Serial.print("Connecting ..."); while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); if (i > 10){ state = false; break; } i++; }

if (state){ Serial.println(""); Serial.print("Connected to "); Serial.println(ssid); Serial.print("IP address: "); Serial.println(WiFi.localIP()); } else { Serial.println(""); Serial.println("Connection failed."); }

return state; }

boolean connectUDP(){ boolean state = false;

Serial.println(""); Serial.println("Connecting to UDP");

if(UDP.beginMulticast(WiFi.localIP(), ipMulti, portMulti)) { Serial.println("Connection successful"); state = true; } else{ Serial.println("Connection failed"); }

return state; }

void turnOnRelay() { digitalWrite(relayPin, HIGH); // turn on relay with voltage HIGH switchState = 1; }

void turnOffRelay() { digitalWrite(relayPin, LOW); // turn off relay with voltage LOW switchState = 0; }

Svengali86 commented 7 years ago

Hi Doug sent you my code on email, I think pasting it in here messes it up somehow

cheers