rudders / homebridge-http

HTTP Plugin for Homebridge
Apache License 2.0
178 stars 109 forks source link

Struggling with Status Update #31

Open andrewdutoit1978 opened 8 years ago

andrewdutoit1978 commented 8 years ago

Hi,

I have built a test.html that returns the following body (see below) (1 for on, 0 for off) but it does not seem to work any ideas, could it be the spaces in the body that causes it to fail?

Thanks Andrew

--snip---snip----

1

--snip---snip----

NovaGL commented 8 years ago

I would imagine that would be the case, how are you getting that value? If you are using PHP try trimming the result.

andrewdutoit1978 commented 8 years ago

Hi,

Ok created simple HTML Body with hardcoded value "1" and still doesnt work, I still get the message in the console: "Light Received power http://192.168.2.151/test.html state is currently NaN

I dont even see this in the code for the status check,

any ideas?

NovaGL commented 8 years ago

What are you putting in your config json file?

JoseNag commented 8 years ago

Hello, I have a problem too.

when I told siri to turn on the light the light turns on but siri told me "sorry I couldn't" (in Japanese) the same when turning off the light.

hope you can help me Thank you.

[ライト] Setting power state to on [ライト] HTTP set power function failed: Parse Error [ライト] Setting power state to on [ライト] HTTP set power function failed: Parse Error

here is the source for ESP-01

wifi.setmode(wifi.STATION) wifi.sta.config("xxx","xxx") print(wifi.sta.getip()) led1 = 3 led2 = 4 gpio.mode(led1, gpio.OUTPUT) gpio.mode(led2, gpio.OUTPUT) buf1 = "0" srv=net.createServer(net.TCP) srv:listen(80,function(conn) conn:on("receive", function(client,request) local buf = "" local , , method, path, vars = string.find(request, "([A-Z]+) (.+)?(.+) HTTP"); if(method == nil)then , , method, path = string.find(request, "([A-Z]+) (.+) HTTP"); end local _GET = {} if (vars ~= nil)then for k, v in string.gmatch(vars, "(%w+)=(%w+)&*") do _GET[k] = v end end buf = ''; local _on,_off = "","" if(_GET.pin == "ON1")then gpio.write(led1, gpio.HIGH); elseif(_GET.pin == "OFF1")then gpio.write(led1, gpio.LOW); elseif(_GET.pin == "ON2")then gpio.write(led2, gpio.HIGH); buf1 = "1"; buf = buf..buf1..""; elseif(_GET.pin == "OFF2")then gpio.write(led2, gpio.LOW); buf1 = "0"; buf = buf..buf1..""; elseif(_GET.pin == "STA1")then buf = buf..buf1..""; end client:send(buf); client:close(); collectgarbage(); end) end)

here is the json file

{ "bridge": { "name": "Homebridge", "username": "XX:XX:XX:XX:XX:XX", "port": 51826, "pin": "031-45-154" },

"description": "HomeBridge HTTP Status Control",

"accessories": [

    {       "accessory": "Http",
            "name": "ライト",
            "switchHandling": "realtime",
            "http_method": "GET",
            "on_url": "http://192.168.1.63/?pin=ON2",
            "off_url": "http://192.168.1.63/?pin=OFF2",
            "status_url":  "http://192.168.1.63/?pin=STA1",
            "service": "Light",
            "sendimmediately": "",
            "username" : "",
            "password" : ""
    }
]

}

deadbone commented 8 years ago

same problem here I write a php page giving 1 but homebridge sees NaN

cybertza commented 8 years ago

http reply e.g.

What we expect for an HTTP Status request Here is how i render it from an arduino. so its presented exactly, 2 many headers cause issues, padding, even 1 will give you an issue, just basically create a file as flat as possible, one of the forks are using regexp to read statuses and this may in the long run be easier to implement, the documentation for that fork isnt complete so its not that easy to see how to use it if you dont have regexp knowledge, reading the comments are helpful, i havent looked to deep into it thou,

here are my findings:
What we expect for an HTTP Status request Here is how i render it from an arduino:

EthernetClient client = server.available(); client.println("HTTP/1.1 200 OK"); client.println("Content-Type: text/html"); client.println("Connnection: close"); client.println(); client.println(1)); // for on and 0 for off. delay(1) client.stop(); Opening a web browser for the url should return the status, and just the status. [[ this may change if i read the reg ex fork]]

0 It will not parse if there in no proper http 200 status, and it will return NaN if it is not 0 or 1

JoseNag commented 8 years ago

Hello! it works now thank you very much!

micheld93 commented 7 years ago

Hi,

I have a problem with status update for my rd-sockets, too. In general it works but the Apple Home app always needs ca.1 min to update the status (on startup). The socket control is not possible until this time delay.

What can I tell you about the setup:

I give the whole code for NodeMCU but I reduced the config.json. I validated the json on the web. I can't explain why it don't work properly. If I delete the stays part in the json it works without any problems.

Can you help me?

What code is on the NodeMCU:

#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <ESP8266WebServer.h>
#include <ESP8266mDNS.h>
#include <RCSwitch.h>
#ifdef ESP8266
extern "C" {
#include "user_interface.h"
}
#endif

RCSwitch mySwitch = RCSwitch();
MDNSResponder mdns;

// Replace with your network credentials
const char* ssid = "SSID";
const char* password = "password";
char* myHostname = "hostname";

ESP8266WebServer server(80);

// (1) replace with your values
char* housecodeeins = "01101";
char* socketcodeseins[] = {"10000", "01000", "00100", "00010","00001"};
char* socketnameseins[] = {"Speaker", "Lamp", "TV", "Test-S01-D", "Test-S01-E"};
// (1) Status
boolean stateseins[] = {false, false, false, false, false};
int numofsocketseins = sizeof(socketcodeseins)/4;

// (2) replace with your values
char* housecodezwei = "01010";
char* socketcodeszwei[] = {"10000", "01000", "00100", "00010","00001"};
char* socketnameszwei[] = {"HiFi", "Receiver", "Player", "Ventillator", "Heating"};
// (2) Status
boolean stateszwei[] = {false, false, false, false, false};
int numofsocketszwei = sizeof(socketcodeszwei)/4;

// you can write your own css and html code (head) here
String css = "body {background-color:#ffffff; color: #000000; font-family: 'Century Gothic', CenturyGothic, AppleGothic, sans-serif;}h1 {font-size: 2em;}a{font-family: Century Gothic, CenturyGothic, AppleGothic, sans-serif; font-size: 2em; text-decoration: none; background-color: #EEEEEE; color: #333333; padding: 2px 6px 2px 6px; border-top: 1px solid #CCCCCC; border-right: 1px solid #333333; border-bottom: 1px solid #333333; border-left: 1px solid #CCCCCC;} p{ font-family: Century Gothic, CenturyGothic, AppleGothic, sans-serif; font-size: 2em;}";
String head1 = "<!DOCTYPE html> <html> <head> <meta name=\"viewport\" content=\"initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no\"> <title>Steckdosensteuerung</title> <style>";
String head2 = "</style></head><body><center>";
String header = head1 + css + head2;
String body = "";
String website(String h, String b){
  String complete = h+b;
  return complete;
}

void setup(void){
  // if you want to modify body part of html start here
  body = "<h1>Steckdosensteuerung</h1>";
  // (1) socket names and buttons are created dynamical
  for(int i = 0; i < numofsocketseins; i++){
    String namesocket = socketnameseins[i];
    body = body + "<p>" + namesocket + " </p> <a href=\"socketEINS" + String(i) + "On\">AN</a>&nbsp;<a href=\"socketEINS" + String(i) + "Off\">AUS</a>";
  }
  // (2) socket names and buttons are created dynamical
  for(int i = 0; i < numofsocketszwei; i++){
    String namesocket = socketnameszwei[i];
    body = body + "<p>" + namesocket + " </p> <a href=\"socketZWEI" + String(i) + "On\">AN</a>&nbsp;<a href=\"socketZWEI" + String(i) + "Off\">AUS</a>";
  }
  body += "</center></body>";

  mySwitch.enableTransmit(2);
  delay(1000);
  Serial.begin(115200);
  wifi_station_set_hostname(myHostname);
  WiFi.begin(ssid, password);
  Serial.println("");

  // Wait for connection
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }

  // serial output of connection details
  Serial.println("");
  Serial.print("Connected to ");
  Serial.println(ssid);
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());
  #ifdef ESP8266
  Serial.print("wifi_station_get_hostname: ");
  Serial.println(wifi_station_get_hostname());
  #endif
  if (mdns.begin("esp8266", WiFi.localIP())) {
    Serial.println("MDNS responder started");
  }

  // this page is loaded when accessing the root of esp8266´s IP
  server.on("/", [](){
    String webPage = website(header, body);
    server.send(200, "text/html", webPage);
  });

// (1) pages for all your sockets are created dynamical
 for(int i = 0; i < numofsocketseins; i++){
   String pathOn = "/socketEINS"+String(i)+"On";
   const char* pathOnChar = pathOn.c_str();
   String pathOff = "/socketEINS"+String(i)+"Off";
   const char* pathOffChar = pathOff.c_str();
   String pathState = "/socketEINS"+String(i)+"State";
   const char* pathStateChar = pathState.c_str();

   server.on(pathOnChar, [i](){
     String webPage = website(header, body);
     server.send(200, "text/html", webPage);
     mySwitch.switchOn(housecodeeins, socketcodeseins[i]);
     stateseins[i] = true;
     delay(1000);
   });

   server.on(pathOffChar, [i](){
     String webPage = website(header, body);
     server.send(200, "text/html", webPage);
     mySwitch.switchOff(housecodeeins, socketcodeseins[i]);
     stateseins[i] = false;
     delay(1000);
   });

   server.on(pathStateChar, [i](){
     if(stateseins[i] == false) {
       server.send(200, "text/html", "0");
     } 
     if(stateseins[i] == true) { 
       server.send(200, "text/html", "1");
     } 
   });
 }

 // (2) pages for all your sockets are created dynamical
 for(int i = 0; i < numofsocketszwei; i++){
   String pathOn = "/socketZWEI"+String(i)+"On";
   const char* pathOnChar = pathOn.c_str();
   String pathOff = "/socketZWEI"+String(i)+"Off";
   const char* pathOffChar = pathOff.c_str();
   String pathState = "/socketZWEI"+String(i)+"State";
   const char* pathStateChar = pathState.c_str();

   server.on(pathOnChar, [i](){
     String webPage = website(header, body);
     server.send(200, "text/html", webPage);
     mySwitch.switchOn(housecodezwei, socketcodeszwei[i]);
     stateszwei[i] = true;
     delay(1000);
   });

   server.on(pathOffChar, [i](){
     String webPage = website(header, body);
     server.send(200, "text/html", webPage);
     mySwitch.switchOff(housecodezwei, socketcodeszwei[i]);
     stateszwei[i] = false;
     delay(1000);
   });

   server.on(pathStateChar, [i](){
     if(stateszwei[i] == false) {
       server.send(200, "text/html", "0");
     } 
     if(stateszwei[i] == true) { 
       server.send(200, "text/html", "1");
     } 
   });
 }

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

void loop(void){
  server.handleClient();
}

What is the config.json (I deleted the HEX-code and my pin...:-)):

{
    "bridge": {
        "name": "HomeKitPI2",
        "username": "HEX-Code",
        "port": 51826,
        "pin": "XXX-XXX-XXX"
    },
    "description": "Smart Home",
    "platforms": [],
    "accessories": [
        {
        "accessory": "Http",
        "name": "Sonoslampe",
        "switchHandling": "yes",
        "http_method": "GET",
        "on_url": "http://192.168.178.39/socketEINS0On",
        "off_url": "http://192.168.178.39/socketEINS0Off",
        "status_url": "http://192.168.178.39/socketEINS0State",
        "service": "Switch",
        "brightnessHandling": "no",
        "brightness_url": "",
        "brightnesslvl_url": "",
        "sendimmediately": "",
        "username": "",
        "password": ""
        },
        {
        "accessory": "Http",
        "name": "Lautsprecher",
        "switchHandling": "yes",
        "http_method": "GET",
        "on_url": "http://192.168.178.39/socketEINS1On",
        "off_url": "http://192.168.178.39/socketEINS1Off",
        "status_url": "http://192.168.178.39/socketEINS1State",
        "service": "Switch",
        "brightnessHandling": "no",
        "brightness_url": "",
        "brightnesslvl_url": "",
        "sendimmediately": "",
        "username": "",
        "password": ""
        }
    ]
}
baghero86 commented 7 years ago

Hi, help as I can create multiple pages for status on Arduino?

` const int buttonPin = 5; // the pin that the pushbutton is attached to int buttonState = 2; // current state of the button const int ledPin = 13; // the pin that the LED is attached to

include

include

// Enter a MAC address and IP address for your controller below. // The IP address will be dependent on your local network: byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; IPAddress ip(192, 168, 1, 177);

// Initialize the Ethernet server library // with the IP address and port you want to use // (port 80 is default for HTTP): EthernetServer server(80);

void setup() { pinMode(buttonPin, INPUT); pinMode(ledPin, OUTPUT); // Open serial communications and wait for port to open: Serial.begin(9600); while (!Serial) { ; // wait for serial port to connect. Needed for native USB port only }

// start the Ethernet connection and the server: Ethernet.begin(mac, ip); server.begin(); Serial.print("server is at "); Serial.println(Ethernet.localIP()); }

void loop() { buttonState = digitalRead(buttonPin); // listen for incoming clients EthernetClient client = server.available(); client.println("HTTP/1.1 200 OK"); client.println("Content-Type: html"); client.println("Connnection: close"); client.println("Refresh: 2"); // refresh the page automatically every 2 sec client.println(); if (buttonState == LOW) { client.println(0);// for on and 0 for off. digitalWrite(ledPin, LOW); }

if (buttonState == HIGH) { client.println(1);// for on and 0 for off. digitalWrite(ledPin, HIGH); }

delay(1); client.stop(); }

`

DeetAus commented 7 years ago

I am also having issue with getting the status to update

I am controlling multiple accessories with a control device I can get them to turn on and off from Siri, but never get the feedback to work, In homebridge I get Parse Errors.

I have to write the feedback string in my controlled accessory to send the feedback to Homebridge. I am sure its just a format error on the string I return

my on URL is http:///frontyard/light/on

status on would be :"frontyard/light/on" status off :"frontyard/light/off"

no matter how i try and format the returned string I just cant get it to work

could anyone do a capture of working feedback json so I can get some idea of how I can get the formatting of my string right

eneski commented 6 years ago

@micheld93 Hallo, ich möchte auch meine Funksteckdosen mit dem WeMos D1 Mini steuern und habe dabei auch an dieses Plugin gedacht. Leider habe ich nicht wirklich viel Erfahrung mit dem Programmieren und habe in meinem kleinen Test auch das mit dem Status nicht gelöst bekommen. Hats bei dir mittlerweile geklappt? Würde mich sehr über eine Antwort freuen, da ich echt etwas Hilfe gebrauchen könnte.

micheld93 commented 6 years ago

@eneski Hi, sorry, nein. Bisher nicht. Ich habe zwar Vermutungen, jedoch hatte ich noch keine Zeit denen nachzugehen.

eneski commented 6 years ago

@micheld93 Hi, danke für deine Antwort. Knnast du mir evtl. dein Sketch schicken, sodass ich nur den "Code" von meiner Funksteckdose einsetzen muss? Habe leider wie gesagt nicht so viel Erfahrung mit dem Programmieren. Würde mir echt weiterhelfen

micheld93 commented 6 years ago

@eneski funktioniert der obige von mir gepostete Code nicht?

eneski commented 6 years ago

@micheld93 doch schon, habe aber irgendwie einen code gefunden um das funksignal auszulesen und da kam das hier raus <--- Beginn Decimal: 262165 (24 Bit) Binary: 000001000000000000010101 Tri-State: 00F000000FFF PulseLength: 351 microseconds Protocol: 1 Raw data: 10891,308,1099,307,1093,309, 1092,313,1095,309,1091, 1028,387,314,1091,311, 1098,307,1095,308,1095, 312,1089,310,1098,312, 1092,308,1099,309,1094, 310,1093,308,1095,315, 1094,303,1100,129,53, 65,6,159,16,266, 47,120,18, <--- End

<--- Beginn Decimal: 262164 (24 Bit) Binary: 000001000000000000010100 Tri-State: 00F000000FF0 PulseLength: 350 microseconds Protocol: 1 Raw data: 10866,311,1094,312,1088,313, 1092,302,1088,318,1085, 1019,390,311,1091,314, 1084,314,1095,304,1095, 306,1094,307,1094,309, 1090,315,1103,291,1103, 302,1094,309,1090,56, 25,185,16,49,5, 85,100,111,112,26, 48,111,12, <--- End welches davon muss ich wo einsetzen? der erste abschnitt ist das signal zum einschalten und der zweite zum ausschalten

micheld93 commented 6 years ago

@eneski Da brauche ich mehr Infos... Hardware etc.

eneski commented 6 years ago

@micheld93 https://draeger-it.blog/arduino-projekt-funksteckdose-steuern/ bin nach dieser Anleitung gegangen, einfach den Code ausgelesen und dann eingesetzt sozusagen. Habe an meiner Deckenleuchte einen Empfänger von Intertechno und dann jeweils ein paar Funktaster. Mit dem D1 mini board will ich sozusagen das ganze auch mit dem Telefon steuern.

micheld93 commented 6 years ago

Dann geht das eh nicht.... nur mit Dip-Schalter

eneski commented 6 years ago

@micheld93 achso ok, habe zwei sone runden regler die ich jeweils verstellen kann. einmal 1-16 und dann noch der andere von A-P

micheld93 commented 6 years ago

Nein, du brauchst Dip-Schalter. Das sind A-E und 1-5. Somit geht das nicht...es gibt aber Anleitungen für die Intertechno und HomeKit.

SenMorgan commented 6 years ago

When homebridge-http is sending the reqest to switch on or off something, you must not only get that reqest, but you must answer on it with 200 code. Here is the part of my code, that helped me to solve this problem:

server.on("/ON", light_on);

void light_on() { server.send(200, "text/plain"); digitalWrite(green_led, 1); Serial.println("LED ON"); } In the server.send(200, "text/plain"); I'm not sending nothing exept code 200.

Answering on status request (really works without "NaN"): if(digitalRead(green_led)) server.send(200, "text/plain", "1"); else server.send(200, "text/plain", "0");

micheld93 commented 6 years ago

@SenMorgan Thanks for the snippet. I already have this structure in my code but unfortunately there is still a time delay (up to 1 minute) between "switch on...new status shown in home app".