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
1827This will return a Device based on address (first argument) type.
1928
2029e.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
3338CP2104 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+
114106Under ` 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 ...
115107e.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 )
0 commit comments