Skip to content

Commit f9f90ce

Browse files
authored
Merge Carglglz/develop for upydevice 0.3.7 release
Merge develop branch for upydevice 0.3.7 release
2 parents ceaf4d7 + fdfe090 commit f9f90ce

File tree

14 files changed

+527
-219
lines changed

14 files changed

+527
-219
lines changed

README.md

Lines changed: 100 additions & 192 deletions
Original file line numberDiff line numberDiff line change
@@ -2,102 +2,93 @@
22

33
[![PyPI version](https://badge.fury.io/py/upydevice.svg)](https://badge.fury.io/py/upydevice)[![PyPI license](https://img.shields.io/pypi/l/ansicolortags.svg)](https://pypi.python.org/pypi/ansicolortags/)
44

5-
Python library to interface with MicroPython devices through REPL:
5+
Python library to interface with MicroPython devices through REPL*:
66

7-
- Websockets/WebREPL (WiFi)
8-
- BleREPL (Bluetooth Low Energy)
9-
- Serial REPL (USB)
7+
- Websockets/WebREPL (WiFi)
8+
- BleREPL (Bluetooth Low Energy)
9+
- Serial REPL (USB)
10+
11+
\* *Device REPL must be accesible.*
12+
13+
Upydevice allows to integrate device interaction from simple scripts to automated services, test suites, command line interfaces or even GUI applications.
1014

1115
### Install
16+
1217
`pip install upydevice` or `pip install --upgrade upydevice`
1318

1419
#### Example usage:
1520

16-
### ANY DEVICE: `Device`
21+
### DEVICE: `Device`
22+
23+
```python
24+
>>> from upydevice import Device
25+
```
1726

1827
This will return a Device based on address (first argument) type.
1928

2029
e.g.
2130

22-
```
23-
>>> from upydevice import Device
24-
>>> esp32_ws = Device('192.168.1.56', 'mypass', init=True, autodetect=True)
25-
>>> esp32_ws
26-
WebSocketDevice @ ws://192.168.1.53:8266, Type: esp32, Class: WebSocketDevice
27-
Firmware: MicroPython v1.16 on 2021-06-19; ESP32 module with ESP32
28-
(MAC: 30:ae:a4:23:35:64, RSSI: -43 dBm)
29-
>>> esp32_sr = Device('/dev/tty.SLAB_USBtoUART', init=True)
30-
>>> esp32_sr
31-
SerialDevice @ /dev/tty.SLAB_USBtoUART, Type: esp32, Class: SerialDevice
32-
Firmware: MicroPython v1.16 on 2021-06-19; ESP32 module with ESP32
31+
### Serial (USB)
32+
33+
```python
34+
>>> esp32 = Device('/dev/cu.usbserial-016418E3', init=True)
35+
>>> esp32
36+
SerialDevice @ /dev/cu.usbserial-016418E3, Type: esp32, Class: SerialDevice
37+
Firmware: MicroPython v1.19.1-285-gc4e3ed964-dirty on 2022-08-12; ESP32 module with ESP32
3338
CP2104 USB to UART Bridge Controller, Manufacturer: Silicon Labs
3439
(MAC: 30:ae:a4:23:35:64)
35-
>>> esp32_ble = Device('F53EDB2E-25A2-45A7-95A5-4D775DFE51D2', init=True)
36-
>>> esp32_ble
37-
BleDevice @ F53EDB2E-25A2-45A7-95A5-4D775DFE51D2, Type: esp32 , Class: BleDevice
38-
Firmware: MicroPython v1.16 on 2021-06-19; ESP32 module with ESP32
39-
(MAC: 30:ae:a4:23:35:64, Local Name: esp_ble, RSSI: -70 dBm)
4040
```
4141

42-
### WIRELESS DEVICE (WebREPL Protocol): `WebSocketDevice`
43-
44-
This requires [WebREPL](http://docs.micropython.org/en/latest/esp8266/tutorial/repl.html#webrepl-a-prompt-over-wifi) to be enabled in the device.
42+
### WiFi (WebSockets/WebREPL)
4543

46-
```
47-
>>> from upydevice import WebSocketDevice
48-
>>> esp32 = WebSocketDevice('192.168.1.56', 'mypass', init=True, autodetect=True)
49-
>>> esp32.wr_cmd('led.on()')
50-
>>> esp32.wr_cmd("uos.listdir()")
51-
['boot.py', 'webrepl_cfg.py', 'main.py'] # this output is stored in [upydevice].output
44+
This requires [WebREPL](http://docs.micropython.org/en/latest/esp8266/tutorial/repl.html#webrepl-a-prompt-over-wifi) to be enabled in the device.
5245

53-
>>> esp32.output
54-
['boot.py', 'webrepl_cfg.py', 'main.py']
55-
>>>> esp32.wr_cmd('x = [1,2,3];my_var = len(x);print(my_var)')
56-
3
57-
# Soft Reset:
58-
>>> esp32.reset()
59-
Rebooting device...
60-
Done!
46+
```python
47+
>>> esp32 = Device('192.168.1.53', 'mypass', init=True)
48+
>>> esp32
49+
WebSocketDevice @ ws://192.168.1.53:8266, Type: esp32, Class: WebSocketDevice
50+
Firmware: MicroPython v1.19.1-285-gc4e3ed964-dirty on 2022-08-12; ESP32 module with ESP32
51+
(MAC: 30:ae:a4:23:35:64, Host Name: espdev, RSSI: -45 dBm)
6152
```
6253

63-
### BLE DEVICE (BleREPL Protocol): `BleDevice`
64-
65-
This requires [BleREPL](https://upydev.readthedocs.io/en/latest/gettingstarted.html) to be enabled in the device. (This is still experimental and performance may be platform and device dependent)
54+
If device hostname name is set e.g. (in device `main.py`)
6655

56+
```python
57+
....
58+
wlan = network.WLAN(network.STA_IF)
59+
wlan.active(True)
60+
wlan.config(hostname='espdev')
61+
wlan.connect('your-ssid', 'your-key')
62+
...
6763
```
68-
>>> from upydevice import BleDevice
69-
>>> esp32 = BleDevice("9998175F-9A91-4CA2-B5EA-482AFC3453B9", init=True)
70-
Device with address 9998175F-9A91-4CA2-B5EA-482AFC3453B9 was not found
71-
Trying again...
72-
Device with address 9998175F-9A91-4CA2-B5EA-482AFC3453B9 was not found
73-
Trying again...
74-
Connected to: 9998175F-9A91-4CA2-B5EA-482AFC3453B9
75-
>>> esp32.wr_cmd('led.on()')
76-
>>> esp32.wr_cmd("uos.listdir()")
77-
['boot.py', 'webrepl_cfg.py', 'main.py', 'lib'] # this output is stored in [upydevice].output
7864

79-
>>> esp32.output
80-
['boot.py', 'webrepl_cfg.py', 'main.py', 'lib']
81-
>>> esp32.wr_cmd('x = [1,2,3];my_var = len(x);print(my_var)')
82-
3
65+
Now the device can be connected with mDNS name.
8366

84-
# Soft Reset:
85-
>>> esp32.reset()
86-
Rebooting device...
87-
Done!
67+
```python
68+
>>> esp32 = Device('espdev.local', 'mypass', init=True)
69+
>>> esp32
70+
WebSocketDevice @ ws://192.168.1.53:8266, Type: esp32, Class: WebSocketDevice
71+
Firmware: MicroPython v1.19.1-285-gc4e3ed964-dirty on 2022-08-12; ESP32 module with ESP32
72+
(MAC: 30:ae:a4:23:35:64, Host Name: espdev, RSSI: -45 dBm)
8873
```
8974

75+
### BLE (BleREPL)
9076

77+
This requires [BleREPL](https://upydev.readthedocs.io/en/latest/gettingstarted.html) to be enabled in the device. (This is still experimental and performance may be platform and device dependent)
9178

92-
### SERIAL DEVICE (USB) : `SerialDevice`
79+
```python
80+
>>> esp32 = Device('00FEFE2D-5983-4D6C-9679-01F732CBA9D9', init=True)
81+
>>> esp32
82+
BleDevice @ 00FEFE2D-5983-4D6C-9679-01F732CBA9D9, Type: esp32 , Class: BleDevice
83+
Firmware: MicroPython v1.18-128-g2ea21abae-dirty on 2022-02-19; 4MB/OTA BLE module with ESP32
84+
(MAC: ec:94:cb:54:8e:14, Local Name: espble, RSSI: -38 dBm)
85+
```
9386

94-
Works for any serial device (esp, pyboard, circuitplayground...)
87+
Now the device can recive commands and send back the output. e.g.
9588

96-
```
97-
from upydevice import SerialDevice
98-
>>> esp32 = SerialDevice('/dev/tty.SLAB_USBtoUART', autodetect=True) # baudrate default is 115200
89+
```python
9990
>>> esp32.wr_cmd('led.on()')
100-
>>> esp32.wr_cmd("uos.listdir()")
91+
>>> esp32.wr_cmd("os.listdir()")
10192
['boot.py', 'webrepl_cfg.py', 'main.py'] # this output is stored in [upydevice].output
10293

10394
>>> esp32.output
@@ -111,141 +102,58 @@ from upydevice import SerialDevice
111102
```
112103

113104
### Testing devices with Pytest:
105+
114106
Under `test` directory there are example tests to run with devices. This allows to test MicroPython code in devices interactively, e.g. button press, screen swipes, sensor calibration, actuators, servo/stepper/dc motors ...
115107
e.g.
116-
```
108+
109+
```python
117110
$ pytest test_esp_serial.py -s
111+
112+
=========================================== test session starts ===========================================
113+
platform darwin -- Python 3.7.9, pytest-7.1.2, pluggy-1.0.0
114+
benchmark: 3.4.1 (defaults: timer=time.perf_counter disable_gc=False min_rounds=5 min_time=0.000005 max_time=1.0 calibration_precision=10 warmup=False warmup_iterations=100000)
115+
rootdir: /Users/carlosgilgonzalez/Desktop/IBM_PROJECTS/MICROPYTHON/TOOLS/upydevice_.nosync/test, configfile: pytest.ini
116+
plugins: benchmark-3.4.1
117+
collected 7 items
118+
119+
test_esp_serial.py::test_devname PASSED [ 14%]
120+
test_esp_serial.py::test_platform
121+
---------------------------------------------- live log call ----------------------------------------------
122+
00:13:26 [pytest] [sdev] [ESP32] : Running SerialDevice test...
123+
00:13:26 [pytest] [sdev] [ESP32] : DEV PLATFORM: esp32
124+
00:13:26 [pytest] [sdev] [ESP32] : DEV PLATFORM TEST: [✔]
125+
PASSED [ 28%]
126+
test_esp_serial.py::test_blink_led
127+
---------------------------------------------- live log call ----------------------------------------------
128+
00:13:28 [pytest] [sdev] [ESP32] : BLINK LED TEST: [✔]
129+
PASSED [ 42%]
130+
test_esp_serial.py::test_run_script
131+
---------------------------------------------- live log call ----------------------------------------------
132+
00:13:28 [pytest] [sdev] [ESP32] : RUN SCRIPT TEST: test_code.py
133+
00:13:31 [pytest] [sdev] [ESP32] : RUN SCRIPT TEST: [✔]
134+
PASSED [ 57%]
135+
test_esp_serial.py::test_raise_device_exception
136+
---------------------------------------------- live log call ----------------------------------------------
137+
00:13:31 [pytest] [sdev] [ESP32] : DEVICE EXCEPTION TEST: b = 1/0
138+
00:13:31 [pytest] [sdev] [ESP32] : DEVICE EXCEPTION TEST: [✔]
139+
PASSED [ 71%]
140+
test_esp_serial.py::test_reset
141+
---------------------------------------------- live log call ----------------------------------------------
142+
00:13:31 [pytest] [sdev] [ESP32] : DEVICE RESET TEST
143+
00:13:32 [pytest] [sdev] [ESP32] : DEVICE RESET TEST: [✔]
144+
PASSED [ 85%]
145+
test_esp_serial.py::test_disconnect
146+
---------------------------------------------- live log call ----------------------------------------------
147+
00:13:32 [pytest] [sdev] [ESP32] : DEVICE DISCONNECT TEST
148+
00:13:32 [pytest] [sdev] [ESP32] : DEVICE DISCONNECT TEST: [✔]
149+
PASSED [100%]
150+
151+
============================================ 7 passed in 6.74s ============================================
118152
```
119153

120154
### Made with upydevice:
121155

122156
- [upydev](https://github.com/Carglglz/upydev)
123157
- [Jupyter_upydevice_kernel](https://github.com/Carglglz/jupyter_upydevice_kernel)
124158

125-
## More advanced examples:
126-
127-
### Phantom module
128-
129-
This module has some python 'phantom' classes to make easier the interaction with the same classes in the upydevice.
130-
131-
Available classes:
132-
133-
* MicroPython classes:
134-
* **MACHINE** (just unique_id() method)
135-
* **Pin**
136-
* **I2C**
137-
* **UOS**
138-
* **pyb_LED**
139-
* **pyb_Timer**
140-
* **pyb_Servo**
141-
* **machine_Timer**
142-
* **WLAN**
143-
* **AP**
144-
* Sensor classes:
145-
* **LSM9DS1**
146-
* **BME280**
147-
* **ADS1115**
148-
* Custom classes:
149-
* **IRQ_MG** (This needs *IRQ_util.py in the micropython device*)
150-
* **STREAMER** (to use as a super class, and this needs *STREAMER_util.py in the micropython device*)
151-
* **IMU_STREAMER** (This needs *IMU_util.py in the micropython device*)
152-
* **BME_STREAMER** (This needs *BME_util.py in the micropython device*)
153-
* **ADS_STREAMER** (This needs *ADS_util.py in the micropython device*)
154-
155-
Examples:
156-
157-
**UOS**
158-
159-
```
160-
from upydevice import WebSocketDevice
161-
from upydevice.phantom import UOS
162-
esp32 = WebSocketDevice('192.168.1.73', 'mypass')
163-
uos = UOS(esp32)
164-
uos.listdir('/')
165-
['boot.py', 'webrepl_cfg.py', 'main.py']
166-
uos.uname()
167-
(sysname='esp32', nodename='esp32', release='1.11.0', version='v1.11-530-g25946d1ef on 2019-10-29', machine='ESP32 module with ESP32')
168-
```
169-
170-
171-
172-
## Upydevice_utils
173-
174-
These are some useful modules to put in the micropython device:
175-
176-
* **IRQ_util.py** : A module to test/setup hardware interrupts easily
177-
* **STREAMER_util.py**: A module with U_STREAMER 'super' class to make streaming sensor data in real time easily.
178-
* **IMU_util.py**: A module with U_IMU_IRQ and U_IMU_STREAMER example classes.
179-
* **BME_util.py**: A module with U_BME_IRQ and U_BME_STREAMER example classes.
180-
* **ADS_util.py**: A module with U_ADS_IRQ and U_ADS_STREAMER example classes.
181-
182-
183-
184-
Example: *phantom IMU_STREAMER + U_IMU_STREAMER classes*
185-
186-
*In MicroPython*
187-
188-
```
189-
from IMU_util import i2c, U_IMU_STREAMER
190-
from lsm9ds1 import LSM9DS1
191-
imu_st = U_IMU_STREAMER(LSM9DS1, i2c)
192-
```
193-
194-
*Now the device is ready to be controlled from Python3*
195-
196-
*In Python3*
197-
198-
```
199-
from upydevice import WebSocketDevice
200-
esp32 = WebSocketDevice('192.168.1.73', 'mypass')
201-
from upydevice.phantom import IMU_STREAMER
202-
imu_st = IMU_STREAMER(esp32, name='imu_st', init_soc=True)
203-
192.168.1.43 # (This prints host ip)
204-
205-
# SIMPLE SAMPLE (this uses upydevice.cmd)
206-
imu_st.read_data()
207-
array('f', [-0.4462279975414276, -0.12023930251598358, -0.9497069716453552])
208-
imu_st.setup_mode('gyro')
209-
imu_st.read_data()
210-
array('f', [-0.007476807106286287, 0.9719849824905396, -0.0971985012292862])
211-
imu_st.setup_mode('mag')
212-
imu_st.read_data()
213-
array('f', [0.4848633110523224, 0.1734618991613388, 0.2396239936351776])
214-
imu_st.setup_mode('acc')
215-
imu_st.read_data()
216-
array('f', [-0.4470824897289276, -0.12023930251598358, -0.9493408203125])
217-
218-
# SOCKETS
219-
imu_st.start_server()
220-
Server listening...
221-
Connection received from: 192.168.1.73:50185
222-
imu_st.shot_read(imu_st.data_print, timeout=1)
223-
X: -0.44537353515625, Y: -0.12030029296875, Z: -0.94879150390625 (g=-9.8m/s^2)
224-
225-
# CONTINUOUS STREAMING THROUGH SOCKETS + TEST
226-
227-
imu_st.continuous_stream(imu_st.data_print_static, timeout=10, static=True, test=True)
228-
Streaming IMU ACCELEROMETER: X, Y, Z (g=-9.8m/s^2),fq=100.0Hz
229-
230-
231-
X Y Z
232-
^C -0.4431 -0.1184 -0.9482
233-
234-
Flushed!
235-
Done!
236-
237-
imu_st.get_stream_test()
238-
STREAM TEST RESULTS ARE:
239-
TEST DURATION : 11.31895899772644 (s)
240-
DATA PACKETS : 1077 packets
241-
SAMPLES PER PACKET : 1
242-
VARIABLES PER SAMPLE : 3; ['X', 'Y', 'Z']
243-
SIZE OF PACKETS: 12 bytes
244-
Period: 10 ms ; Fs:100.0 Hz, Data send rate: 95 packets/s of 1 samples
245-
DATA TRANSFER RATE (kBps): 1.11328125 kB/s
246-
DATA TRANSFER RATE (Mbps): 0.00890625 Mbps
247-
248-
imu_st.stop_server()
249-
```
250-
251159
## [Examples (scripts, GUI ...)](https://github.com/Carglglz/upydevice/tree/develop/examples)

changelog.md

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,18 @@ All notable changes to this project will be documented in this file.
44
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
55
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html)
66

7-
## [0.3.7] Unreleased Github Repo [develop]
7+
## [0.3.8] Unreleased Github Repo [develop]
8+
## [0.3.7] - 2022-08-23
9+
### Fix
10+
- paste_buff method in BleDevice
11+
- fix data feeding pipe missing blank lines in follow callback for BleDevice
12+
- deprecate self-signed certs in favor of ROOT CA signed certs for WebSocketDevices using SSL/TLS
13+
### Added
14+
- @device.code decorator for Device classes to declare and call functions in devices
15+
- @device.code_follow for Device classes to declare and call functions in devices whose output need to be followed.
16+
- @devicegroup.code for DeviceGroup class to declare and call functions in group of devices
17+
@devicegroup.code_follow for Device classes to declare and call functions in a group of devices whose output need to be followed.
18+
- decorator examples
819
## [0.3.6] - 2022-03-25
920
### Fix
1021
- fixed missing dependencies in `setup.py` (@BradenM)

0 commit comments

Comments
 (0)