staromeste / homebridge-http-advanced-accessory

Supports all devices on HomeBridge Platform / Bridges devices to http
Apache License 2.0
65 stars 22 forks source link

Cannot setOn with POST #21

Open skytoastar opened 4 years ago

skytoastar commented 4 years ago

I have a "light bulb" I'm hoping to control through Homebridge. It's an ESP8266 running a basic web server to control a light strip. It's running code found in this project. It exposes URLs to POST data to to be able to control it.

I can control it from the ESP8266's built-in web app. I can even control it from this basic python script running on my computer:

import requests
url = "http://10.54.236.84/power"
data = {'value':1}  # 1:on, 0:off
r = requests.post(url = url, data = data) 

For the life of me I can't seem to find the right mapping value to get it to work from this plugin. I stepped through the python code to see the body of the request is 'value=1'. I've tried the following:

"setOn": {
    "url" : "http://10.54.236.84/power",
    "httpMethod" : "POST",
    "body" : "{value}",
    "mappers": [{
        "type": "static",
        "parameters": {
            "mapping": {
                "true": {"value":"1"},
                "false": {"value":"0"}
            }
        }
    }]
}
"setOn": {
    "url" : "http://10.54.236.84/power",
    "httpMethod" : "POST",
    "body" : "{value}",
    "mappers": [{
        "type": "static",
        "parameters": {
            "mapping": {
                "true": "1",
                "false": "0"
            }
        }
    }]
}
"setOn": {
    "url" : "http://10.54.236.84/power",
    "httpMethod" : "POST",
    "body" : "{value}",
    "mappers": [{
        "type": "static",
        "parameters": {
            "mapping": {
                "true": "value=1",
                "false": "value=0"
            }
        }
    }]
}

I added some debugging prints to index.js to know that the mapping is actually working and adding the mapped value to body before calling httpRequest.

But none successfully turn the light on. Also unusual is that when the light actually is on, whatever mapping value I send to turn it off will turn it off. I just can't turn it on.

staromeste commented 4 years ago

Can you try this?

"setOn": { "url" : "http://10.54.236.84/power", "httpMethod" : "POST", "body" : "{\"value\":${value==true?1:0}}" }

On Mon, 27 Apr 2020 at 21:50, skytoastar notifications@github.com wrote:

I have a "light bulb" I'm hoping to control through Homebridge. It's an ESP8266 running a basic web server to control a light strip. It's running code found in this project https://github.com/jasoncoon/esp8266-fastled-webserver. It exposes URLs to POST data to to be able to control it.

I can control it from the ESP8266's built-in web app. I can even control it from this basic python script running on my computer:

import requests url = "http://10.54.236.84/power" data = {'value':1} # 1:on, 0:off r = requests.post(url = url, data = data)

For the life of me I can't seem to find the right mapping value to get it to work from this plugin. I stepped through the python code to see the body of the request is 'value=1'. I've tried the following:

"setOn": { "url" : "http://10.54.236.84/power", "httpMethod" : "POST", "body" : "{value}", "mappers": [{ "type": "static", "parameters": { "mapping": { "true": {"value":"1"}, "false": {"value":"0"} } } }] }

"setOn": { "url" : "http://10.54.236.84/power", "httpMethod" : "POST", "body" : "{value}", "mappers": [{ "type": "static", "parameters": { "mapping": { "true": "1", "false": "0" } } }] }

"setOn": { "url" : "http://10.54.236.84/power", "httpMethod" : "POST", "body" : "{value}", "mappers": [{ "type": "static", "parameters": { "mapping": { "true": "value=1", "false": "value=0" } } }] }

I added some debugging prints to index.js to know that the mapping is actually working and adding the mapped value to body before calling httpRequest.

But none successfully turn the light on. Also unusual is that when the light actually is on, whatever mapping value I send to turn it off will turn it off. I just can't turn it on.

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/staromeste/homebridge-http-advanced-accessory/issues/21, or unsubscribe https://github.com/notifications/unsubscribe-auth/ABBP2MLHCIY23L3OOQDM5ADROXOZLANCNFSM4MSGY2GQ .

staromeste commented 4 years ago

Sorry, value is already 0 or 1. So this should work for you:

"setOn": { "url" : "http://10.54.236.84/power", "httpMethod" : "POST", "body" : "{\"value\":{value}}" }

On Tue, 28 Apr 2020 at 14:38, Guido Moscarella staromeste@gmail.com wrote:

Can you try this?

"setOn": { "url" : "http://10.54.236.84/power", "httpMethod" : "POST", "body" : "{\"value\":${value==true?1:0}}" }

On Mon, 27 Apr 2020 at 21:50, skytoastar notifications@github.com wrote:

I have a "light bulb" I'm hoping to control through Homebridge. It's an ESP8266 running a basic web server to control a light strip. It's running code found in this project https://github.com/jasoncoon/esp8266-fastled-webserver. It exposes URLs to POST data to to be able to control it.

I can control it from the ESP8266's built-in web app. I can even control it from this basic python script running on my computer:

import requests url = "http://10.54.236.84/power" data = {'value':1} # 1:on, 0:off r = requests.post(url = url, data = data)

For the life of me I can't seem to find the right mapping value to get it to work from this plugin. I stepped through the python code to see the body of the request is 'value=1'. I've tried the following:

"setOn": { "url" : "http://10.54.236.84/power", "httpMethod" : "POST", "body" : "{value}", "mappers": [{ "type": "static", "parameters": { "mapping": { "true": {"value":"1"}, "false": {"value":"0"} } } }] }

"setOn": { "url" : "http://10.54.236.84/power", "httpMethod" : "POST", "body" : "{value}", "mappers": [{ "type": "static", "parameters": { "mapping": { "true": "1", "false": "0" } } }] }

"setOn": { "url" : "http://10.54.236.84/power", "httpMethod" : "POST", "body" : "{value}", "mappers": [{ "type": "static", "parameters": { "mapping": { "true": "value=1", "false": "value=0" } } }] }

I added some debugging prints to index.js to know that the mapping is actually working and adding the mapped value to body before calling httpRequest.

But none successfully turn the light on. Also unusual is that when the light actually is on, whatever mapping value I send to turn it off will turn it off. I just can't turn it on.

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/staromeste/homebridge-http-advanced-accessory/issues/21, or unsubscribe https://github.com/notifications/unsubscribe-auth/ABBP2MLHCIY23L3OOQDM5ADROXOZLANCNFSM4MSGY2GQ .

skytoastar commented 4 years ago

Neither of the above worked.

So I decided to compare payloads using Wireshark and I found that I could correctly construct the 7-byte payload using Python or this plugin. Those seven bytes are 'value=1'. But only in the python case did it turn the light on. The python-sent payload was specifying the payload as a form of type application/x-www-form-urlencoded whereas the plugin was not.

So I hacked this into the index.js file of this plugin to make request send the data as form data:

    httpRequest : function(url, body, httpMethod, callback) {
        if (httpMethod == 'POST')
        {
            this.debugLog("entering POST");
            request.post({url: url,
                          form: {'value':body}}, // hard coded key of 'value' :(
                         function(error, response, body) {
                             callback(error, response, body)
                         });
        }
        else
        {
        // rest of the original httpRequest body
        }

Then I used the following for "setOn" in the config file:

"setOn": {
    "url" : "http://10.54.236.84/power",
    "httpMethod" : "POST",
    "body" : "{value}",
    "mappers": [{
        "type": "static",
        "parameters": {
            "mapping": {
                "true": "1",
                "false": "0"
            }
        }
    }]
}

And it worked!

That being said, my code probably isn't the right way to specify form key/val pairs in the config file given my hard-coded key.

shanemcw commented 3 years ago

@skytoastar I had a similar issue using non-form POST, as outlined here with PHP as an example:

If you want to receive application/json post data in your script you can not use $_POST. $_POST does only handle form data. Read from php://input instead. You can use fopen or file_get_contents.

Example:

<?php
// Get the JSON contents
$json = file_get_contents('php://input');

// decode the json data
$data = json_decode($json);
?>

which would explain your success with your "form" code.

I solved it by the above technique (reading the received POST raw and decoding manually) that works with non-form POST (I am able to as I am author of the code that gets and processes the received POST).