In my setup I have an 'i3 button' as the input and 'o9 bargraph' as the output:
In the v2 documentation, there was no specific documentation on input, just output.
After opening a case with LittleBits, I was given the pre-release v3 API documentation (Thanks! Theodore from LittleBits):
Following the example on the page, the input and output sample are below (note the different v3 endpoint than v2):
- Output
$ curl -i -XPOST -H "Authorization: Bearer <token>" https://api-http.littlebitscloud.cc/v3/devices/<id>/output -d percent=50 -d duration_ms=5000
HTTP/1.1 200 OK
access-control-allow-headers: Authorization, Content-Type, If-None-Match
access-control-allow-methods: GET, HEAD, POST, PUT, PATCH, DELETE, OPTIONS
access-control-allow-origin: *
access-control-expose-headers: WWW-Authenticate, Server-Authorization
access-control-max-age: 86400
cache-control: no-cache
content-type: application/json; charset=utf-8
Date: Mon, 20 Jul 2015 04:47:37 GMT
Content-Length: 16
Connection: keep-alive
{"success":true}
- Input (stream)
$ curl -i -H "Authorization: Bearer <token>" https://api-http.littlebitscloud.cc/v3/devices/<id>/input
HTTP/1.1 200 OK
access-control-allow-headers: Authorization, Content-Type, If-None-Match
access-control-allow-methods: GET, HEAD, POST, PUT, PATCH, DELETE, OPTIONS
access-control-allow-origin: *
access-control-expose-headers: WWW-Authenticate, Server-Authorization
access-control-max-age: 86400
cache-control: no-cache
content-encoding: identity
content-type: text/event-stream; charset=utf-8
Date: Mon, 20 Jul 2015 04:49:44 GMT
transfer-encoding: chunked
Connection: keep-alive
data:{"type":"input","timestamp":1437367785035,"from":{"socket":{"remotePort":<port>,"remoteAddress":"<id>","localAddress":"<addr>","localPort":<port>,"id":"<id>"},"server":{"id":"<id>"},"user":{"id":<id>},"device":{"id":"<id>","device":"littlebits-module-cloud","setup_version":"1.0.0","protocol_version":"1.1.0","firmware_version":"1.0.140820b","mac":"<mad>","hash":"<hash>","ap":{"ssid":"<ssid>","mac":"<mac>","strength":<strength>},"settings":{"label":"<label>","input_interval_ms":750}},"is_identified":true},"percent":0,"absolute":0,"name":"amplitude","payload":{"percent":0,"absolute":0}}
Of which, when press the button, the payload percent and absolute value changes accordingly.
Converting the two Input and Output Curl to Python were not too difficult, thanks again to the awesome Request package:
- Output Script
#!/usr/env/bin python
import json
import requests
deviceId = "<id>"
littleBitsOutputUrl = "https://api-http.littlebitscloud.cc/v3/devices/" + deviceId + "/output"
authToken = "<token>"
headers = {"Authorization": "Bearer "+authToken, "Content-type": "application/x-www-form-urlencoded"}
body = "percent=50&duration_ms=5000"
r = requests.post(littleBitsOutputUrl, headers=headers, data=body)
print r.status_code
- Execution
$ python CloudbitOputput.py
200
- Input Script
#!/usr/env/bin python
import json
import requests, time
deviceId = "<id>"
littleBitsInputUrl = "https://api-http.littlebitscloud.cc/v3/devices/" + deviceId + "/input"
authToken = "<token>"
headers = {"Authorization": "Bearer "+authToken}
r = requests.get(littleBitsInputUrl, headers=headers, stream=True)
for line in r.iter_lines():
if line:
result = json.loads(line.split('data:')[1])
print result['payload']
- Execution
$ python CloudbitInput.py
{u'percent': 0, u'absolute': 0}
{u'percent': 0, u'absolute': 0}
{u'percent': 0, u'absolute': 0}
{u'percent': 100, u'absolute': 1023}
{u'percent': 100, u'absolute': 1023}
{u'percent': 100, u'absolute': 1023}
{u'percent': 100, u'absolute': 1023}
{u'percent': 100, u'absolute': 1023}
{u'percent': 100, u'absolute': 1023}
{u'percent': 0, u'absolute': 0}
{u'percent': 0, u'absolute': 0}
{u'percent': 0, u'absolute': 0}
Happy Coding!
Thanks! It worked just as advertised when I ran the script in python 2 but I wanted to alert you and your readers that when I tried it in python3 I got the following error reading the input :
ReplyDelete---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
in ()
6 for line in r.iter_lines():
7 if line:
----> 8 result = json.loads(line.split('data:')[1])
9 print(result['payload'])
TypeError: 'str' does not support the buffer interface
According to [this stackoverflow answer](http://stackoverflow.com/questions/26945613/str-does-not-support-the-buffer-interface-python3-from-python2) it is because "Python 2, bare literal strings (e.g. 'string') are bytes, whereas in Python 3 they are unicode.". I haven't figured out how to fix that problem quite yet but I'll stick to python2 in the meantime..
One more question. Suppose you don't want a constant stream but you just want to poll the device to just find out the value of the current input (say a temperature, or light sensor reading at just 4pm daily). I can think of ways to adapt your code to break out of the for loop, but is there a more elegant way? On the request call you set the parameter stream=True. Do you know if there is a 'non-stream' options?
Thanks again!
Unfortunately my cloudBit is not working at this time, just open a case with LittleBits, so I can't test this out. But I think you just need to specify the encoding for line, i.e. line.encode("utf-8") then Python 3 should work as well. Like a lot of people, I have not transition to Python 3 yet.
ReplyDeleteFor the second question about current input, since the data is not stored anywhere, the easiest way I would do is just to cron (set execution of the script at specific time) if you are no Mac or Linux or the equivalent on Windows to execute the script at 4pm daily. Or you can continue to stream the data and write the output to a simple text file (along with timestamp) or simple database.
Hope it helps.
That helps me understand better. Thanks again.
ReplyDeleteRe my question about a single (non-streaming) poll response on the current input value, Turns out the issue has been discussed on github with the littlebits team
https://github.com/littlebits/cloud-platform/issues/1
but from what I can follow there was, as of that time, still no easy non-streaming option (at least one that works with available python wrappers).
Hi Jonathan, the nice folks at LittleBits is RMA'ing the old cloudBit. The new one should arrive soon and I will try it out with some IoT streaming and display solutions like Xively or Push.
ReplyDeleteHi, what if I don't want the stream mode but I only want to read the value once? Like temperature? Ty! this was very helpful
ReplyDelete