Skip to content

Commit 8627493

Browse files
committed
examples: Add separate example for MicroPython.
1 parent 7e73472 commit 8627493

File tree

4 files changed

+187
-139
lines changed

4 files changed

+187
-139
lines changed

README.md

Lines changed: 7 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -43,34 +43,27 @@ softhsm2-util --delete-token --token "arduino"
4343
```
4444

4545
### Run the example script
46-
* Set `KEY_URI`, `CERT_URI`, `DEVICE_ID`, `THING_ID` in `example.py`.
46+
* Set `KEY_PATH`, `CERT_PATH`, `DEVICE_ID`, `THING_ID` in `example.py`.
4747
* Provide a CA certificate in a `ca-root.pem` file or set `CA_PATH` to `None` if it's not used.
4848
* Override the default `pin` and provide `ENGINE_PATH` and `MODULE_PATH` in `ssl_params` if needed.
4949
* Clone this repository and run the following:
5050
```bash
51-
python example.py
51+
python examples/example.py
5252
```
5353

5454
## Testing on MicroPython
55-
The following changes to the example code are required, because MicroPython does Not support secure elements yet:
55+
MicroPython currently does Not support secure elements, the key and cert files must be stored in DER format on the filesystem.
56+
Convert the key and certificate to DER, using the following commands, and copy to the filesystem storage.
5657

5758
#### Convert key and certificate to `.DER`
5859
```bash
5960
openssl ec -in key.pem -out key.der -outform DER
6061
openssl x509 -in cert.pem -out cert.der -outform DER
6162
```
6263

63-
#### Load key and certificate from filesystem storage
64-
```python
65-
KEY_PATH = "key.der"
66-
CERT_PATH = "cert.der"
67-
....
68-
69-
async def main():
70-
with open(KEY_PATH, "rb") as fin: key = fin.read()
71-
with open(CERT_PATH, "rb") as fin: cert = fin.read()
72-
client = AIOTClient(device_id=DEVICE_ID, keepalive=10, ssl_params = {"key":key, "cert":cert})
73-
....
64+
### Run the MicroPython example script
65+
* Set `KEY_PATH`, `CERT_PATH`, to key and certificate DER paths respectively.
66+
* run `examples/micropython.py`
7467
```
7568
7669
## Useful links

example.py

Lines changed: 0 additions & 125 deletions
This file was deleted.

examples/example.py

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
# This file is part of the Python Arduino IoT Cloud.
2+
# The MIT License (MIT)
3+
# Copyright (c) 2022 Arduino SA
4+
import time
5+
import asyncio
6+
import logging
7+
from time import strftime
8+
from arduino_iot_cloud import AIOTClient
9+
from arduino_iot_cloud import Location
10+
from arduino_iot_cloud import Schedule
11+
from arduino_iot_cloud import ColoredLight
12+
from random import randint
13+
import argparse
14+
15+
KEY_PATH = "pkcs11:token=arduino"
16+
CERT_PATH = "pkcs11:token=arduino"
17+
CA_PATH = "ca-root.pem"
18+
DEVICE_ID = b"25deeda1-3fda-4d06-9c3c-dd31be382cd2"
19+
20+
async def user_main(client):
21+
# Add your code here. Note to allow other tasks to run, this function
22+
# must yield execution periodically by calling asyncio.sleep(seconds).
23+
while True:
24+
# The composite cloud object's fields can be assigned to individually:
25+
client["clight"].hue = randint(0, 100)
26+
client["clight"].bri = randint(0, 100)
27+
await asyncio.sleep(1.0)
28+
29+
30+
def on_switch_changed(client, value):
31+
# This is a write callback for the switch that toggles the LED variable. The LED
32+
# variable can be accessed via the client object passed in the first argument.
33+
client["led"] = value
34+
35+
36+
def on_clight_changed(client, clight):
37+
logging.info(f"ColoredLight changed. Swi: {clight.swi} Bri: {clight.bri} Sat: {clight.sat} Hue: {clight.hue}")
38+
39+
40+
async def main():
41+
# Create a client to connect to the Arduino IoT cloud. To use a secure element, set the token "pin"
42+
# and URI in "keyfile" and "certfile, and CA certificate (if used), in ssl_params. Alternatively,
43+
# a username and a password can be used for authentication, for example:
44+
# client = AIOTClient(device_id, username="username", password="password")
45+
client = AIOTClient(
46+
device_id=DEVICE_ID,
47+
ssl_params={"pin": "1234", "keyfile": KEY_PATH, "certfile": CERT_PATH, "ca_certs": CA_PATH},
48+
)
49+
50+
# Register cloud objects. Note these objects must be created first in the dashboard.
51+
# This cloud object is initialized with its last known value from the cloud. When this object is updated
52+
# from the dashboard, the on_switch_changed function is called with the client object and the new value.
53+
client.register("sw1", value=None, on_write=on_switch_changed, interval=0.250)
54+
55+
# This cloud object is updated manually in the switch's on_write_change callback.
56+
client.register("led", value=None)
57+
58+
# This is a periodic cloud object that gets updated at fixed intervals (in this case 1 seconed) with the
59+
# value returned from its on_read function (a formatted string of the current time). Note this object's
60+
# initial value is None, it will be initialized by calling the on_read function.
61+
client.register("clk", value=None, on_read=lambda x: strftime("%H:%M:%S", time.localtime()), interval=1.0)
62+
63+
# This is an example of a composite cloud object (a cloud object with multiple variables). In this case
64+
# a colored light with switch, hue, saturation and brightness attributes. Once initialized, the object's
65+
# attributes can be accessed using dot notation. For example: client["clight"].swi = False.
66+
client.register(ColoredLight("clight", swi=True, on_write=on_clight_changed))
67+
68+
# This is another example of a composite cloud object, a map location with lat and long attributes.
69+
client.register(Location("treasureisland", lat=31.264694, lon=29.979987))
70+
71+
# This object allows scheduling recurring events from the cloud UI. On activation of the event, if the
72+
# on_active callback is provided, it gets called with the client object and the schedule object value.
73+
# Note: The activation status of the object can also be polled using client["schedule"].active.
74+
client.register(Schedule("schedule", on_active=lambda client, value: logging.info(f"Schedule activated {value}!")))
75+
76+
# Start the Arduino IoT cloud client. Note a co-routine can be passed to client.run(coro), in this case it will
77+
# scheduled to run along with the other cloud objects.
78+
await client.run(user_main)
79+
80+
81+
if __name__ == "__main__":
82+
# Parse command line args.
83+
parser = argparse.ArgumentParser(description='arduino_iot_cloud.py')
84+
parser.add_argument("-d", "--debug", action = "store_true", help = "Enable debugging messages")
85+
args = parser.parse_args()
86+
87+
# Assume the host has an active Internet connection.
88+
89+
# Configure the logger.
90+
# All message equal or higher to the logger level are printed.
91+
# To see more debugging messages, pass --debug on the command line.
92+
logging.basicConfig(
93+
datefmt="%H:%M:%S",
94+
format="%(asctime)s.%(msecs)03d %(message)s",
95+
level=logging.DEBUG if args.debug else logging.INFO,
96+
)
97+
asyncio.run(main())

examples/micropython.py

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
# This file is part of the Python Arduino IoT Cloud.
2+
# The MIT License (MIT)
3+
# Copyright (c) 2022 Arduino SA
4+
import time
5+
import uasyncio as asyncio
6+
import ulogging as logging
7+
from ulogging.ustrftime import strftime
8+
from arduino_iot_cloud import AIOTClient, Location, Schedule, ColoredLight
9+
from random import randint
10+
11+
KEY_PATH = "key.der"
12+
CERT_PATH = "cert.der"
13+
DEVICE_ID = b"25deeda1-3fda-4d06-9c3c-dd31be382cd2"
14+
15+
async def user_main(client):
16+
# Add your code here. Note to allow other tasks to run, this function
17+
# must yield execution periodically by calling asyncio.sleep(seconds).
18+
while True:
19+
# The composite cloud object's fields can be assigned to individually:
20+
client["clight"].hue = randint(0, 100)
21+
client["clight"].bri = randint(0, 100)
22+
await asyncio.sleep(1.0)
23+
24+
25+
def on_switch_changed(client, value):
26+
# This is a write callback for the switch that toggles the LED variable. The LED
27+
# variable can be accessed via the client object passed in the first argument.
28+
client["led"] = value
29+
30+
31+
def on_clight_changed(client, clight):
32+
logging.info(f"ColoredLight changed. Swi: {clight.swi} Bri: {clight.bri} Sat: {clight.sat} Hue: {clight.hue}")
33+
34+
35+
async def main():
36+
# Create a client to connect to the Arduino IoT cloud. For MicroPython, the key and cert files must be stored
37+
# in DER format on the filesystem. Alternatively, a username and a password can be used for authentication:
38+
# client = AIOTClient(device_id, username="username", password="password")
39+
client = AIOTClient(device_id=DEVICE_ID, ssl_params={"keyfile": KEY_PATH, "certfile": CERT_PATH})
40+
41+
# Register cloud objects. Note these objects must be created first in the dashboard.
42+
# This cloud object is initialized with its last known value from the cloud. When this object is updated
43+
# from the dashboard, the on_switch_changed function is called with the client object and the new value.
44+
client.register("sw1", value=None, on_write=on_switch_changed, interval=0.250)
45+
46+
# This cloud object is updated manually in the switch's on_write_change callback.
47+
client.register("led", value=None)
48+
49+
# This is a periodic cloud object that gets updated at fixed intervals (in this case 1 seconed) with the
50+
# value returned from its on_read function (a formatted string of the current time). Note this object's
51+
# initial value is None, it will be initialized by calling the on_read function.
52+
client.register("clk", value=None, on_read=lambda x: strftime("%H:%M:%S", time.localtime()), interval=1.0)
53+
54+
# This is an example of a composite cloud object (a cloud object with multiple variables). In this case
55+
# a colored light with switch, hue, saturation and brightness attributes. Once initialized, the object's
56+
# attributes can be accessed using dot notation. For example: client["clight"].swi = False.
57+
client.register(ColoredLight("clight", swi=True, on_write=on_clight_changed))
58+
59+
# This is another example of a composite cloud object, a map location with lat and long attributes.
60+
client.register(Location("treasureisland", lat=31.264694, lon=29.979987))
61+
62+
# This object allows scheduling recurring events from the cloud UI. On activation of the event, if the
63+
# on_active callback is provided, it gets called with the client object and the schedule object value.
64+
# Note: The activation status of the object can also be polled using client["schedule"].active.
65+
client.register(Schedule("schedule", on_active=lambda client, value: logging.info(f"Schedule activated {value}!")))
66+
67+
# Start the Arduino IoT cloud client. Note a co-routine can be passed to client.run(coro), in this case it will
68+
# scheduled to run along with the other cloud objects.
69+
await client.run(user_main)
70+
71+
72+
if __name__ == "__main__":
73+
#NOTE: Add networking code here or in boot.py
74+
75+
# Configure the logger.
76+
# All message equal or higher to the logger level are printed.
77+
# To see more debugging messages, set level=logging.DEBUG.
78+
logging.basicConfig(
79+
datefmt="%H:%M:%S",
80+
format="%(asctime)s.%(msecs)03d %(message)s",
81+
level=logging.INFO,
82+
)
83+
asyncio.run(main())

0 commit comments

Comments
 (0)