Python Plugin - how to replicate a curl statement in a plugin

Python and python framework

Moderator: leecollings

Post Reply
malarcy
Posts: 50
Joined: Sunday 15 November 2015 13:36
Target OS: Linux
Domoticz version:
Contact:

Python Plugin - how to replicate a curl statement in a plugin

Post by malarcy »

Hi - looking at the possibility of developing a plugin for the Blink Home Monitoring Camera's - there's a couple of libraries out there (a python one - unfortunately it depends heavily on the requests module so I can't just use that) There is also good docs on driving Blink via curl, so between the two sources I think I have enough info.

For now, my needs are simple - I just want to be able to ARM/DISARM the motion sense on a camera - I could do this via a separate python script - calling the library / requests - but I am sure I will want to build on it so am tempted to go down the plugin route.

I am however struggling with the Domoticz.Connection and subsequent sends - I can't get the syntax correct to produce the required "packet"

The curl command to emulate is (for authentication - you get an auth token returned to use in the next calls)

curl -H "Host: prod.immedia-semi.com" -H "Content-Type: application/json" --data-binary '{ "password" : "your blink password", "client_specifier" : "iPhone 9.2 | 2.2 | 222", "email" : "your blink login/email" }' --compressed https://rest.prod.immedia-semi.com/login

I have tried both an HTTPS and JSON protocol

Any suggestions?

For reference on the work done so far by others:

https://github.com/MattTW/BlinkMonitorProtocol
https://github.com/fronzbot/blinkpy
febalci
Posts: 331
Joined: Monday 03 July 2017 19:58
Target OS: NAS (Synology & others)
Domoticz version:
Contact:

Re: Python Plugin - how to replicate a curl statement in a plugin

Post by febalci »

hi @malarcy,

in Plugin Framework you can always use urrlib; but that means not using the native plugin framework connections. It will work anyway.

If you are using native TCP-IP/HTTP connection, you have to send a header; check https://github.com/domoticz/domoticz/bl ... es/HTTP.py for an example.

Or if you are using TCP-IP/JSON or TCP-IP/None connection, you have to deal with raw incoming HTTP messages. What i did for a connection in the plugin is like:

Code: Select all

    wsHeader = "GET /standing_order/websocket HTTP/1.1\r\n" \
                "Host: www.seismicportal.eu\r\n" \
                "User-Agent: Domoticz/1.0\r\n" \
                "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n" \
                "Accept-Language: en-US,en;q=0.5\r\n" \
                "Accept-Encoding: gzip, deflate\r\n" \
                "Sec-WebSocket-Version: 13\r\n" \
                "Origin: http://www.seismicportal.eu\r\n" \
                "Sec-WebSocket-Extensions: permessage-deflate\r\n" \
                "Sec-WebSocket-Key: qqMLBxy==\r\n" \
                "DNT: 1\r\n" \
                "Connection: keep-alive, Upgrade\r\n" \
                "Pragma: no-cache\r\n" \
                "Cache-Control: no-cache\r\n" \
"Upgrade: websocket\r\n\r\n"
and use 'Connection.Send(self.wsHeader)' in onconnect. Please be aware that this header is for a websocket connection, you have to correct it according to your needs. You have to convert '{ "password" : "your blink password", "client_specifier" : "iPhone 9.2 | 2.2 | 222", "email" : "your blink login/email" }' to binary before putting it in to your header. Also i believe it should be POST, not GET on your situation.

"Accept-Encoding: gzip, deflate\r\n" \ wll handle the compressed option.
malarcy
Posts: 50
Joined: Sunday 15 November 2015 13:36
Target OS: Linux
Domoticz version:
Contact:

Re: Python Plugin - how to replicate a curl statement in a plugin

Post by malarcy »

Thanks for the quick response and the pointers - some more options there - if I can use the framework I will - if not - will fall back to urllib (or probably urllib2 for the flexibility)

In the case of the HTTP.py example - I see the header getting constructed - thats useful.

The auth sequence is a POST (you are correct), its JSON, I would need to specify that as a "body" section of the send (assuming that can be done).

More playing later on today

Malarcy
febalci
Posts: 331
Joined: Monday 03 July 2017 19:58
Target OS: NAS (Synology & others)
Domoticz version:
Contact:

Re: Python Plugin - how to replicate a curl statement in a plugin

Post by febalci »

@malarcy:

Check https://github.com/domoticz/domoticz/bl ... istener.py for a POST example; which uses:

Code: Select all

self.httpClientConn.Send({"Status":"200 OK", "Headers": {"Connection": "keep-alive", "Accept": "Content-Type: text/html; charset=UTF-8"}, "Data": data})
, so you can send body section in 'Data'
malarcy
Posts: 50
Joined: Sunday 15 November 2015 13:36
Target OS: Linux
Domoticz version:
Contact:

Re: Python Plugin - how to replicate a curl statement in a plugin

Post by malarcy »

OK - got it authenticating and I can read back the token etc. via the framework - thanks for the help on that - found that if I didn't tell the server I would accept gzipped content then it returns uncompressed - how very civil of it - will need to deal with gzip'ed content if I got as far as retrieving thumbnails or videos from the cloud service.

Now looking at the logic in the onMessage section - there's a fair amount of "discovery" that needs to go on at startup - and I would kind of like to handle all that in the onConnect - is there anyway of specifying a different call back handler for a given "send" - if not I guess I just need to parse out the setup and discovery (enumeration of cameras, etc.) - just makes that piece of code heavier than I would like.

In normal running the onMessage handler will be perfect for dealing with periodic status refreshes and response to commands.

More experimentation later.

Malarcy
User avatar
Dnpwwo
Posts: 819
Joined: Sunday 23 March 2014 9:00
Target OS: Raspberry Pi / ODroid
Domoticz version: Beta
Location: Melbourne, Australia
Contact:

Re: Python Plugin - how to replicate a curl statement in a plugin

Post by Dnpwwo »

@malarcy,

Most devices have an element of 'discovery' to them, previously I have triggered the discovery in the onConnect then used the responses as a 'state machine' to drive next steps.

Have a look at: its an easy approach an quite robust to handle cases where remote devices become unavailable and disconnect followed by reconnection.
The reasonable man adapts himself to the world; the unreasonable one persists to adapt the world to himself. Therefore all progress depends on the unreasonable man. George Bernard Shaw
Post Reply

Who is online

Users browsing this forum: Bing [Bot] and 1 guest