Unofficial IBM Watson IoT Platform SDK for Devices Running MicroPython
This is a "SDK" in the loosest sense.
This library is intended to be used with an ESP32-based device, or at least something with connectivity that has more RAM than a ESP8266, and runs MicroPython.
The device you're using should already have been flashed with MicroPython.
Open a serial terminal, e.g.:
$ python3 -m serial.tools.miniterm --raw /dev/your-com-port 115200
Ensure your device has internet connectivity, then:
import upip
upip.install('micropython-watson-iot')
The above will install the latest release of this module (and its dependencies) within lib/
.
If for some reason the above doesn't work, you can try to do this manually through various means.
- Clone this repo, or download a
.zip
. - From your working copy, copy the
watson_iot/
directory to your device - Create a
lib
directory on your device - Create a
lib/umqtt
directory on your device - Clone micropython-lib or download a
.zip
- From the
micropython-lib
working copy, put:-
umqtt.simple/umqtt/simple.py
intolib/umqtt/simple.py
-
umqtt.robust/umqtt/robust.py
intolib/umqtt/robust.py
-
A tool you can use to copy files is adafruit-ampy, which can be installed via pip3 install adafruit-ampy
.
This oughtta do it:
$ PORT=/dev/tty.SLAB_USBtoUART && \
ampy --port "${PORT}" put /path/to/micropython-watson-iot/watson_iot && \
ampy --port "${PORT}" mkdir lib && \
ampy --port "${PORT}" mkdir lib/umqtt && \
ampy --port "${PORT}" put \
/path/to/micropython-lib/umqtt.simple/umqtt/simple.py lib/umqtt/simple.py && \
ampy --port "${PORT}" put \
/path/to/micropython-lib/umqtt.robust/umqtt/robust.py lib/umqtt/robust.py
(Replace the working copy paths and the value of PORT
with your device path.)
You have a couple options here.
- To experiment, you can use Watson IoT Platform Quickstart, or
- Sign up for a (free) IBM Cloud account, then create an Watson IoT Platform service from the catalog
In lieu of proper API documentation, here are a bunch of examples:
from watson_iot import Device
my_device = Device(
device_id='my-device-id', # required
device_type='my-device-type', # required
token='my-device-token', # required
# optional parameters shown with defaults below
org='quickstart',
username='use-token-auth',
port=8883, # this is 1883 if default `org` used
clean_session=True,
domain='internetofthings.ibmcloud.com',
ssl_params=None,
log_level='info'
)
my_device.connect()
When finished, you can disconnect:
my_device.disconnect()
Assuming the Device is connected, this example will publish a single event with ID my_event_id
.
my_device.publishEvent(
'my_event_id', # event name
{'ok': True}, # message payload
message_format='json', # 'text' is also built-in
qos=0 # QoS 0 or QoS 1
)
The following will execute the my_handler
function when command my-command
is received by the Device.
def my_handler(message):
"""
does something with `message`
"""
pass
my_device.set_command('my-command', my_handler)
# blocking wait for command
while my_device.is_connected:
my_device.sync_loop()
Alternatively, a non-blocking approach:
import utime as time
# non-blocking wait for command
while my_device.is_connected:
my_device.loop()
# do other stuff like sleep
time.sleep(1)
To stop handling the command my-command
:
my_device.unset_command('my-command')
micropython-watson-iot
comes with built-in encoders and decoders for JSON (json
) and plain text (text
) message formats.
All incoming messages (via commands, for example) are byte literals!
You can add a custom encoder and decoder:
def to_csv(my_list):
"""
`my_list` is likely a list or tuple; returns a str
"""
return ','.join(my_list)
def from_csv(data):
"""
`data` is a byte literal and must be coerced to a str first
"""
return str(data).split(',')
my_device.set_encoder('csv', to_csv)
my_device.set_decoder('csv', from_csv)
Now, whenever an event is published with message_format='csv'
, the encoder will modify the outbound message. Likewise, whenever a command is received in the csv
format, the incoming message will be run through the decoder before it's given to the command handler.
You can also remove them, if you wish:
my_device.unset_encoder('csv')
my_device.unset_decoder('csv')
-
is_connected
-bool
, whether or not the Device is currently connected -
is_secure
-bool
, whether or not the active or inactive connection is encrypted
If your use case falls outside of the limitations listed below, take a look at the official Python SDK instead.
That being said, I'm open to collaboration on the following items, whether they make sense within this project, or others.
micropython-watson-iot
supports "unmanaged" devices only. A "device" in the context of Watson IoT Platform is:
A device is anything that has a connection to the internet and has data to send to or receive from the cloud. You can use devices to send event information such as sensor readings to the cloud, and to accept commands from applications in the cloud.
That means you cannot create an application or gateway with micropython-watson-iot
.
micropython-watson-iot
(as of this writing) does not support managed devices.
This may or may not be feasible.
micropython-watson-iot
does not (and likely will not) parse commands received as XML; nor does it provide any "helpers" to publish events as XML.
As of Sep 20, 2017, the official MicroPython MQTT client module does not support QoS 2, so neither does micropython-watson-iot
.
I'd be cool with using a non-official MQTT client module which did support QoS 2, if such a thing existed!
MicroPython is not CPython. While MicroPython is based on Python 3, micropython-watson-iot
is not targeting Python 3, nor is it targeting any forks of MicroPython (e.g., CircuitPython).
$ ./setup.py sdist upload
Enter your PyPi pizassword at the pizrompt.
© 2017-2018 Christopher Hiller. Licensed Apache-2.0