micrOSDevToolKit 2.13.1__py3-none-any.whl → 2.17.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of micrOSDevToolKit might be problematic. Click here for more details.
- micrOS/release_info/micrOS_ReleaseInfo/system_analysis_sum.json +125 -121
- micrOS/source/Common.py +48 -26
- micrOS/source/Config.py +13 -5
- micrOS/source/Espnow.py +100 -58
- micrOS/source/Files.py +77 -41
- micrOS/source/Hooks.py +18 -34
- micrOS/source/Logger.py +2 -7
- micrOS/source/Network.py +36 -16
- micrOS/source/Server.py +22 -8
- micrOS/source/Shell.py +9 -6
- micrOS/source/Tasks.py +34 -13
- micrOS/source/Web.py +69 -31
- micrOS/source/__pycache__/Common.cpython-312.pyc +0 -0
- micrOS/source/__pycache__/Files.cpython-312.pyc +0 -0
- micrOS/source/__pycache__/Logger.cpython-312.pyc +0 -0
- micrOS/source/__pycache__/Server.cpython-312.pyc +0 -0
- micrOS/source/config/_git.keep +0 -0
- micrOS/source/micrOS.py +7 -0
- micrOS/source/micrOSloader.py +2 -10
- micrOS/source/microIO.py +2 -2
- micrOS/source/modules/IO_esp32c6.py +38 -0
- micrOS/source/modules/LM_L298N.py +161 -0
- micrOS/source/modules/LM_cluster.py +250 -0
- {toolkit/workspace/precompiled → micrOS/source/modules}/LM_esp32.py +5 -0
- micrOS/source/modules/LM_espnow.py +36 -0
- micrOS/source/{LM_i2c.py → modules/LM_i2c.py} +1 -1
- micrOS/source/{LM_light_sensor.py → modules/LM_light_sensor.py} +2 -2
- micrOS/source/modules/LM_mqtt_client.py +246 -0
- micrOS/source/{LM_neoeffects.py → modules/LM_neoeffects.py} +14 -4
- micrOS/source/{LM_neomatrix.py → modules/LM_neomatrix.py} +140 -38
- micrOS/source/{LM_oled_ui.py → modules/LM_oled_ui.py} +2 -2
- micrOS/source/{LM_oledui.py → modules/LM_oledui.py} +2 -2
- micrOS/source/{LM_pacman.py → modules/LM_pacman.py} +74 -29
- micrOS/source/{LM_presence.py → modules/LM_presence.py} +2 -2
- micrOS/source/{LM_robustness.py → modules/LM_robustness.py} +49 -2
- micrOS/source/{LM_tcs3472.py → modules/LM_tcs3472.py} +4 -6
- micrOS/source/web/dashboard.html +2 -0
- micrOS/source/web/matrix_draw.html +390 -0
- micrOS/source/web/uapi.js +9 -6
- {microsdevtoolkit-2.13.1.dist-info → microsdevtoolkit-2.17.0.dist-info}/METADATA +30 -37
- {microsdevtoolkit-2.13.1.dist-info → microsdevtoolkit-2.17.0.dist-info}/RECORD +200 -190
- toolkit/DevEnvCompile.py +21 -12
- toolkit/DevEnvOTA.py +27 -16
- toolkit/DevEnvUSB.py +35 -21
- toolkit/LM_to_compile.dat +3 -1
- toolkit/MicrOSDevEnv.py +37 -21
- toolkit/dashboard_apps/QMI8685_GYRO.py +1 -1
- toolkit/dashboard_apps/SystemTest.py +8 -5
- toolkit/{MicrosFiles.py → lib/MicrosFiles.py} +24 -4
- toolkit/micrOSdashboard.py +2 -2
- toolkit/micrOSlint.py +17 -7
- toolkit/simulator_lib/__pycache__/simulator.cpython-312.pyc +0 -0
- toolkit/simulator_lib/__pycache__/uos.cpython-312.pyc +0 -0
- toolkit/simulator_lib/mqtt_as/Note.md +15 -0
- toolkit/simulator_lib/mqtt_as/__init__.py +950 -0
- toolkit/simulator_lib/mqtt_as/__pycache__/__init__.cpython-312.pyc +0 -0
- toolkit/simulator_lib/mqtt_as/clean.py +69 -0
- toolkit/simulator_lib/mqtt_as/mqtt_v5_properties.py +239 -0
- toolkit/simulator_lib/mqtt_as/range.py +90 -0
- toolkit/simulator_lib/mqtt_as/range_ex.py +119 -0
- toolkit/simulator_lib/simulator.py +14 -1
- toolkit/simulator_lib/uos.py +2 -0
- toolkit/workspace/precompiled/Common.mpy +0 -0
- toolkit/workspace/precompiled/Config.mpy +0 -0
- toolkit/workspace/precompiled/Espnow.mpy +0 -0
- toolkit/workspace/precompiled/Files.mpy +0 -0
- toolkit/workspace/precompiled/Hooks.mpy +0 -0
- toolkit/workspace/precompiled/Logger.mpy +0 -0
- toolkit/workspace/precompiled/Network.mpy +0 -0
- toolkit/workspace/precompiled/Server.mpy +0 -0
- toolkit/workspace/precompiled/Shell.mpy +0 -0
- toolkit/workspace/precompiled/Tasks.mpy +0 -0
- toolkit/workspace/precompiled/Web.mpy +0 -0
- toolkit/workspace/precompiled/config/_git.keep +0 -0
- toolkit/workspace/precompiled/micrOS.mpy +0 -0
- toolkit/workspace/precompiled/micrOSloader.mpy +0 -0
- toolkit/workspace/precompiled/microIO.mpy +0 -0
- toolkit/workspace/precompiled/{IO_esp32.mpy → modules/IO_esp32.mpy} +0 -0
- toolkit/workspace/precompiled/{IO_esp32c3.mpy → modules/IO_esp32c3.mpy} +0 -0
- toolkit/workspace/precompiled/modules/IO_esp32c6.mpy +0 -0
- toolkit/workspace/precompiled/{IO_esp32s2.mpy → modules/IO_esp32s2.mpy} +0 -0
- toolkit/workspace/precompiled/{IO_esp32s3.mpy → modules/IO_esp32s3.mpy} +0 -0
- toolkit/workspace/precompiled/{IO_m5stamp.mpy → modules/IO_m5stamp.mpy} +0 -0
- toolkit/workspace/precompiled/{IO_qtpy.mpy → modules/IO_qtpy.mpy} +0 -0
- toolkit/workspace/precompiled/modules/IO_rp2.mpy +0 -0
- toolkit/workspace/precompiled/modules/IO_s3matrix.mpy +0 -0
- toolkit/workspace/precompiled/{IO_tinypico.mpy → modules/IO_tinypico.mpy} +0 -0
- toolkit/workspace/precompiled/modules/LM_L298N.mpy +0 -0
- toolkit/workspace/precompiled/{LM_OV2640.mpy → modules/LM_OV2640.mpy} +0 -0
- toolkit/workspace/precompiled/{LM_aht10.mpy → modules/LM_aht10.mpy} +0 -0
- toolkit/workspace/precompiled/{LM_bme280.mpy → modules/LM_bme280.mpy} +0 -0
- toolkit/workspace/precompiled/{LM_buzzer.mpy → modules/LM_buzzer.mpy} +0 -0
- toolkit/workspace/precompiled/{LM_cct.mpy → modules/LM_cct.mpy} +0 -0
- toolkit/workspace/precompiled/modules/LM_cluster.mpy +0 -0
- toolkit/workspace/precompiled/{LM_co2.mpy → modules/LM_co2.mpy} +0 -0
- toolkit/workspace/precompiled/{LM_dht11.mpy → modules/LM_dht11.mpy} +0 -0
- toolkit/workspace/precompiled/{LM_dht22.mpy → modules/LM_dht22.mpy} +0 -0
- toolkit/workspace/precompiled/{LM_dimmer.mpy → modules/LM_dimmer.mpy} +0 -0
- toolkit/workspace/precompiled/{LM_distance.mpy → modules/LM_distance.mpy} +0 -0
- toolkit/workspace/precompiled/{LM_ds18.mpy → modules/LM_ds18.mpy} +0 -0
- {micrOS/source → toolkit/workspace/precompiled/modules}/LM_esp32.py +5 -0
- toolkit/workspace/precompiled/modules/LM_espnow.py +36 -0
- toolkit/workspace/precompiled/{LM_gameOfLife.mpy → modules/LM_gameOfLife.mpy} +0 -0
- toolkit/workspace/precompiled/{LM_genIO.mpy → modules/LM_genIO.mpy} +0 -0
- toolkit/workspace/precompiled/{LM_haptic.mpy → modules/LM_haptic.mpy} +0 -0
- toolkit/workspace/precompiled/{LM_i2c.py → modules/LM_i2c.py} +1 -1
- toolkit/workspace/precompiled/{LM_i2s_mic.mpy → modules/LM_i2s_mic.mpy} +0 -0
- toolkit/workspace/precompiled/{LM_keychain.mpy → modules/LM_keychain.mpy} +0 -0
- toolkit/workspace/precompiled/{LM_ld2410.mpy → modules/LM_ld2410.mpy} +0 -0
- toolkit/workspace/precompiled/modules/LM_light_sensor.mpy +0 -0
- toolkit/workspace/precompiled/modules/LM_mqtt_client.mpy +0 -0
- toolkit/workspace/precompiled/{LM_neoeffects.mpy → modules/LM_neoeffects.mpy} +0 -0
- toolkit/workspace/precompiled/modules/LM_neomatrix.mpy +0 -0
- toolkit/workspace/precompiled/{LM_neopixel.mpy → modules/LM_neopixel.mpy} +0 -0
- toolkit/workspace/precompiled/{LM_oled.mpy → modules/LM_oled.mpy} +0 -0
- toolkit/workspace/precompiled/{LM_oled_sh1106.mpy → modules/LM_oled_sh1106.mpy} +0 -0
- toolkit/workspace/precompiled/modules/LM_oled_ui.mpy +0 -0
- toolkit/workspace/precompiled/modules/LM_oledui.mpy +0 -0
- toolkit/workspace/precompiled/modules/LM_pacman.mpy +0 -0
- toolkit/workspace/precompiled/modules/LM_presence.mpy +0 -0
- toolkit/workspace/precompiled/{LM_rest.mpy → modules/LM_rest.mpy} +0 -0
- toolkit/workspace/precompiled/{LM_rgb.mpy → modules/LM_rgb.mpy} +0 -0
- toolkit/workspace/precompiled/{LM_rgbcct.mpy → modules/LM_rgbcct.mpy} +0 -0
- toolkit/workspace/precompiled/{LM_roboarm.mpy → modules/LM_roboarm.mpy} +0 -0
- toolkit/workspace/precompiled/{LM_robustness.py → modules/LM_robustness.py} +49 -2
- toolkit/workspace/precompiled/{LM_servo.mpy → modules/LM_servo.mpy} +0 -0
- toolkit/workspace/precompiled/{LM_sound_event.mpy → modules/LM_sound_event.mpy} +0 -0
- toolkit/workspace/precompiled/{LM_stepper.mpy → modules/LM_stepper.mpy} +0 -0
- toolkit/workspace/precompiled/{LM_switch.mpy → modules/LM_switch.mpy} +0 -0
- toolkit/workspace/precompiled/{LM_system.mpy → modules/LM_system.mpy} +0 -0
- toolkit/workspace/precompiled/{LM_tcs3472.py → modules/LM_tcs3472.py} +4 -6
- toolkit/workspace/precompiled/{LM_telegram.mpy → modules/LM_telegram.mpy} +0 -0
- toolkit/workspace/precompiled/{LM_tinyrgb.mpy → modules/LM_tinyrgb.mpy} +0 -0
- toolkit/workspace/precompiled/{LM_trackball.mpy → modules/LM_trackball.mpy} +0 -0
- toolkit/workspace/precompiled/{LM_veml7700.mpy → modules/LM_veml7700.mpy} +0 -0
- toolkit/workspace/precompiled/web/dashboard.html +2 -0
- toolkit/workspace/precompiled/web/matrix_draw.html +390 -0
- toolkit/workspace/precompiled/web/uapi.js +9 -6
- micrOS/source/IO_esp32c6.py +0 -16
- micrOS/source/LM_L298N_DCmotor.py +0 -86
- micrOS/source/LM_espnow.py +0 -57
- micrOS/source/LM_mqtt_pro.py +0 -211
- toolkit/lib/file_extensions.py +0 -22
- toolkit/workspace/precompiled/Common.cpython-312.pyc +0 -0
- toolkit/workspace/precompiled/IO_esp32c6.mpy +0 -0
- toolkit/workspace/precompiled/IO_rp2.mpy +0 -0
- toolkit/workspace/precompiled/IO_s3matrix.mpy +0 -0
- toolkit/workspace/precompiled/LM_L298N_DCmotor.mpy +0 -0
- toolkit/workspace/precompiled/LM_espnow.py +0 -57
- toolkit/workspace/precompiled/LM_light_sensor.mpy +0 -0
- toolkit/workspace/precompiled/LM_mqtt_pro.py +0 -211
- toolkit/workspace/precompiled/LM_neomatrix.mpy +0 -0
- toolkit/workspace/precompiled/LM_oled_ui.mpy +0 -0
- toolkit/workspace/precompiled/LM_oledui.mpy +0 -0
- toolkit/workspace/precompiled/LM_pacman.mpy +0 -0
- toolkit/workspace/precompiled/LM_presence.mpy +0 -0
- toolkit/workspace/precompiled/Logger.cpython-312.pyc +0 -0
- toolkit/workspace/precompiled/Server.cpython-312.pyc +0 -0
- /micrOS/source/{IO_esp32.py → modules/IO_esp32.py} +0 -0
- /micrOS/source/{IO_esp32c3.py → modules/IO_esp32c3.py} +0 -0
- /micrOS/source/{IO_esp32s2.py → modules/IO_esp32s2.py} +0 -0
- /micrOS/source/{IO_esp32s3.py → modules/IO_esp32s3.py} +0 -0
- /micrOS/source/{IO_m5stamp.py → modules/IO_m5stamp.py} +0 -0
- /micrOS/source/{IO_qtpy.py → modules/IO_qtpy.py} +0 -0
- /micrOS/source/{IO_rp2.py → modules/IO_rp2.py} +0 -0
- /micrOS/source/{IO_s3matrix.py → modules/IO_s3matrix.py} +0 -0
- /micrOS/source/{IO_tinypico.py → modules/IO_tinypico.py} +0 -0
- /micrOS/source/{LM_L9110_DCmotor.py → modules/LM_L9110_DCmotor.py} +0 -0
- /micrOS/source/{LM_OV2640.py → modules/LM_OV2640.py} +0 -0
- /micrOS/source/{LM_VL53L0X.py → modules/LM_VL53L0X.py} +0 -0
- /micrOS/source/{LM_aht10.py → modules/LM_aht10.py} +0 -0
- /micrOS/source/{LM_bme280.py → modules/LM_bme280.py} +0 -0
- /micrOS/source/{LM_buzzer.py → modules/LM_buzzer.py} +0 -0
- /micrOS/source/{LM_cct.py → modules/LM_cct.py} +0 -0
- /micrOS/source/{LM_co2.py → modules/LM_co2.py} +0 -0
- /micrOS/source/{LM_dashboard_be.py → modules/LM_dashboard_be.py} +0 -0
- /micrOS/source/{LM_dht11.py → modules/LM_dht11.py} +0 -0
- /micrOS/source/{LM_dht22.py → modules/LM_dht22.py} +0 -0
- /micrOS/source/{LM_dimmer.py → modules/LM_dimmer.py} +0 -0
- /micrOS/source/{LM_distance.py → modules/LM_distance.py} +0 -0
- /micrOS/source/{LM_ds18.py → modules/LM_ds18.py} +0 -0
- /micrOS/source/{LM_gameOfLife.py → modules/LM_gameOfLife.py} +0 -0
- /micrOS/source/{LM_genIO.py → modules/LM_genIO.py} +0 -0
- /micrOS/source/{LM_haptic.py → modules/LM_haptic.py} +0 -0
- /micrOS/source/{LM_i2s_mic.py → modules/LM_i2s_mic.py} +0 -0
- /micrOS/source/{LM_keychain.py → modules/LM_keychain.py} +0 -0
- /micrOS/source/{LM_ld2410.py → modules/LM_ld2410.py} +0 -0
- /micrOS/source/{LM_neopixel.py → modules/LM_neopixel.py} +0 -0
- /micrOS/source/{LM_oled.py → modules/LM_oled.py} +0 -0
- /micrOS/source/{LM_oled_sh1106.py → modules/LM_oled_sh1106.py} +0 -0
- /micrOS/source/{LM_pet_feeder.py → modules/LM_pet_feeder.py} +0 -0
- /micrOS/source/{LM_qmi8658.py → modules/LM_qmi8658.py} +0 -0
- /micrOS/source/{LM_rencoder.py → modules/LM_rencoder.py} +0 -0
- /micrOS/source/{LM_rest.py → modules/LM_rest.py} +0 -0
- /micrOS/source/{LM_rgb.py → modules/LM_rgb.py} +0 -0
- /micrOS/source/{LM_rgbcct.py → modules/LM_rgbcct.py} +0 -0
- /micrOS/source/{LM_roboarm.py → modules/LM_roboarm.py} +0 -0
- /micrOS/source/{LM_rp2w.py → modules/LM_rp2w.py} +0 -0
- /micrOS/source/{LM_sdcard.py → modules/LM_sdcard.py} +0 -0
- /micrOS/source/{LM_servo.py → modules/LM_servo.py} +0 -0
- /micrOS/source/{LM_sound_event.py → modules/LM_sound_event.py} +0 -0
- /micrOS/source/{LM_stepper.py → modules/LM_stepper.py} +0 -0
- /micrOS/source/{LM_switch.py → modules/LM_switch.py} +0 -0
- /micrOS/source/{LM_system.py → modules/LM_system.py} +0 -0
- /micrOS/source/{LM_telegram.py → modules/LM_telegram.py} +0 -0
- /micrOS/source/{LM_tinyrgb.py → modules/LM_tinyrgb.py} +0 -0
- /micrOS/source/{LM_trackball.py → modules/LM_trackball.py} +0 -0
- /micrOS/source/{LM_veml7700.py → modules/LM_veml7700.py} +0 -0
- {microsdevtoolkit-2.13.1.data → microsdevtoolkit-2.17.0.data}/scripts/devToolKit.py +0 -0
- {microsdevtoolkit-2.13.1.dist-info → microsdevtoolkit-2.17.0.dist-info}/WHEEL +0 -0
- {microsdevtoolkit-2.13.1.dist-info → microsdevtoolkit-2.17.0.dist-info}/licenses/LICENSE +0 -0
- {microsdevtoolkit-2.13.1.dist-info → microsdevtoolkit-2.17.0.dist-info}/top_level.txt +0 -0
- /toolkit/workspace/precompiled/{LM_L9110_DCmotor.py → modules/LM_L9110_DCmotor.py} +0 -0
- /toolkit/workspace/precompiled/{LM_VL53L0X.py → modules/LM_VL53L0X.py} +0 -0
- /toolkit/workspace/precompiled/{LM_dashboard_be.py → modules/LM_dashboard_be.py} +0 -0
- /toolkit/workspace/precompiled/{LM_pet_feeder.py → modules/LM_pet_feeder.py} +0 -0
- /toolkit/workspace/precompiled/{LM_qmi8658.py → modules/LM_qmi8658.py} +0 -0
- /toolkit/workspace/precompiled/{LM_rencoder.py → modules/LM_rencoder.py} +0 -0
- /toolkit/workspace/precompiled/{LM_rp2w.py → modules/LM_rp2w.py} +0 -0
- /toolkit/workspace/precompiled/{LM_sdcard.py → modules/LM_sdcard.py} +0 -0
|
Binary file
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
# clean.py Test of asynchronous mqtt client with clean session.
|
|
2
|
+
# (C) Copyright Peter Hinch 2017-2019.
|
|
3
|
+
# Released under the MIT licence.
|
|
4
|
+
|
|
5
|
+
# Public brokers https://github.com/mqtt/mqtt.github.io/wiki/public_brokers
|
|
6
|
+
|
|
7
|
+
# The use of clean_session means that after a connection failure subscriptions
|
|
8
|
+
# must be renewed (MQTT spec 3.1.2.4). This is done by the connect handler.
|
|
9
|
+
# Note that publications issued during the outage will be missed. If this is
|
|
10
|
+
# an issue see unclean.py.
|
|
11
|
+
|
|
12
|
+
# red LED: ON == WiFi fail
|
|
13
|
+
# blue LED heartbeat: demonstrates scheduler is running.
|
|
14
|
+
|
|
15
|
+
from mqtt_as import MQTTClient
|
|
16
|
+
from mqtt_local import wifi_led, blue_led, config
|
|
17
|
+
import uasyncio as asyncio
|
|
18
|
+
|
|
19
|
+
# Subscription callback
|
|
20
|
+
def sub_cb(topic, msg, retained):
|
|
21
|
+
print(f'Topic: "{topic.decode()}" Message: "{msg.decode()}" Retained: {retained}')
|
|
22
|
+
|
|
23
|
+
# Demonstrate scheduler is operational.
|
|
24
|
+
async def heartbeat():
|
|
25
|
+
s = True
|
|
26
|
+
while True:
|
|
27
|
+
await asyncio.sleep_ms(500)
|
|
28
|
+
blue_led(s)
|
|
29
|
+
s = not s
|
|
30
|
+
|
|
31
|
+
async def wifi_han(state):
|
|
32
|
+
wifi_led(not state)
|
|
33
|
+
print('Wifi is ', 'up' if state else 'down')
|
|
34
|
+
await asyncio.sleep(1)
|
|
35
|
+
|
|
36
|
+
# If you connect with clean_session True, must re-subscribe (MQTT spec 3.1.2.4)
|
|
37
|
+
async def conn_han(client):
|
|
38
|
+
await client.subscribe('foo_topic', 1)
|
|
39
|
+
|
|
40
|
+
async def main(client):
|
|
41
|
+
try:
|
|
42
|
+
await client.connect()
|
|
43
|
+
except OSError:
|
|
44
|
+
print('Connection failed.')
|
|
45
|
+
return
|
|
46
|
+
n = 0
|
|
47
|
+
while True:
|
|
48
|
+
await asyncio.sleep(5)
|
|
49
|
+
print('publish', n)
|
|
50
|
+
# If WiFi is down the following will pause for the duration.
|
|
51
|
+
await client.publish('result', '{} {}'.format(n, client.REPUB_COUNT), qos = 1)
|
|
52
|
+
n += 1
|
|
53
|
+
|
|
54
|
+
# Define configuration
|
|
55
|
+
config['subs_cb'] = sub_cb
|
|
56
|
+
config['wifi_coro'] = wifi_han
|
|
57
|
+
config['connect_coro'] = conn_han
|
|
58
|
+
config['clean'] = True
|
|
59
|
+
|
|
60
|
+
# Set up client
|
|
61
|
+
MQTTClient.DEBUG = True # Optional
|
|
62
|
+
client = MQTTClient(config)
|
|
63
|
+
|
|
64
|
+
asyncio.create_task(heartbeat())
|
|
65
|
+
try:
|
|
66
|
+
asyncio.run(main(client))
|
|
67
|
+
finally:
|
|
68
|
+
client.close() # Prevent LmacRxBlk:1 errors
|
|
69
|
+
asyncio.new_event_loop()
|
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
# mqtt_v5_properties.py Add MQTT V5 extensions to mqtt_as
|
|
2
|
+
|
|
3
|
+
# (C) Copyright Bob Veringa 2024-2025.
|
|
4
|
+
# Released under the MIT licence.
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
import struct
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def encode_byte(value):
|
|
11
|
+
# It takes in a byte and returns a byte
|
|
12
|
+
return value
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def encode_two_byte_int(value):
|
|
16
|
+
return struct.pack("!H", value)
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def encode_four_byte_int(value):
|
|
20
|
+
return struct.pack("!I", value)
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def encode_string(value):
|
|
24
|
+
value = value.encode("utf-8")
|
|
25
|
+
return struct.pack("!H", len(value)) + value
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def encode_string_pair(value):
|
|
29
|
+
# just get the first key and value
|
|
30
|
+
key, value = list(value.items())[0]
|
|
31
|
+
return encode_string(key) + encode_string(value)
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def encode_binary(value):
|
|
35
|
+
return struct.pack("!H", len(value)) + value
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def encode_variable_byte_int(value):
|
|
39
|
+
out = bytearray(4)
|
|
40
|
+
i = 0
|
|
41
|
+
for i in range(4):
|
|
42
|
+
b = value & 0x7F
|
|
43
|
+
value >>= 7
|
|
44
|
+
if value > 0:
|
|
45
|
+
b |= 0x80
|
|
46
|
+
out[i] = b
|
|
47
|
+
if value == 0:
|
|
48
|
+
break
|
|
49
|
+
return out[: i + 1]
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
# This table does not contain all properties (unlike the decode table)
|
|
53
|
+
# as not all properties can be sent by the client.
|
|
54
|
+
ENCODE_TABLE = {
|
|
55
|
+
0x01: encode_byte, # Payload Format Indicator
|
|
56
|
+
0x02: encode_four_byte_int, # Message Expiry Interval
|
|
57
|
+
0x03: encode_string, # Content Type
|
|
58
|
+
0x08: encode_string, # Response Topic
|
|
59
|
+
0x09: encode_binary, # Correlation Data
|
|
60
|
+
0x0B: encode_variable_byte_int, # Subscription Identifier
|
|
61
|
+
0x11: encode_four_byte_int, # Session Expiry Interval
|
|
62
|
+
0x15: encode_string, # Authentication Method
|
|
63
|
+
0x16: encode_binary, # Authentication Data
|
|
64
|
+
0x17: encode_byte, # Request Problem Information
|
|
65
|
+
0x18: encode_four_byte_int, # Will Delay Interval
|
|
66
|
+
0x19: encode_byte, # Request Response Information
|
|
67
|
+
0x1C: encode_string, # Server Reference
|
|
68
|
+
0x1F: encode_string, # Reason String
|
|
69
|
+
0x21: encode_two_byte_int, # Receive Maximum
|
|
70
|
+
0x22: encode_two_byte_int, # Topic Alias Maximum
|
|
71
|
+
0x23: encode_two_byte_int, # Topic Alias
|
|
72
|
+
0x26: encode_string_pair, # User Property
|
|
73
|
+
0x27: encode_four_byte_int, # Maximum Packet Size
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
# MQTT_base class. Handles MQTT protocol on the basis of a good connection.
|
|
78
|
+
# Exceptions from connectivity failures are handled by MQTTClient subclass.
|
|
79
|
+
def encode_properties(properties: dict):
|
|
80
|
+
# If properties are empty or None, we can just return a single byte (0)
|
|
81
|
+
if properties in (None, {}):
|
|
82
|
+
return bytes(1)
|
|
83
|
+
|
|
84
|
+
# We can't modify the properties dict, as user might want to use it later
|
|
85
|
+
# So we will create a new dict with the encoded values.
|
|
86
|
+
# This causes a slight increase in memory usage. But this is acceptable.
|
|
87
|
+
pre_encoded_properties = {}
|
|
88
|
+
|
|
89
|
+
# We keep track of the length of the properties
|
|
90
|
+
properties_length = 0
|
|
91
|
+
|
|
92
|
+
# Preprocess properties to encode everything as bytes.
|
|
93
|
+
for key, value in properties.items():
|
|
94
|
+
encode_func = ENCODE_TABLE.get(key)
|
|
95
|
+
if encode_func is None:
|
|
96
|
+
# We can just leave that data as is and assume that it is valid.
|
|
97
|
+
tmp_value = value
|
|
98
|
+
else:
|
|
99
|
+
tmp_value = encode_func(value)
|
|
100
|
+
pre_encoded_properties[key] = tmp_value
|
|
101
|
+
|
|
102
|
+
# Pre-calculate the length of the properties
|
|
103
|
+
properties_length += 1 # key
|
|
104
|
+
properties_length += len(tmp_value)
|
|
105
|
+
|
|
106
|
+
# Mark properties as deleted
|
|
107
|
+
del properties
|
|
108
|
+
|
|
109
|
+
variable_length = 1
|
|
110
|
+
if properties_length > 127:
|
|
111
|
+
variable_length += 1
|
|
112
|
+
if properties_length > 16383:
|
|
113
|
+
variable_length += 1
|
|
114
|
+
if properties_length > 2097151:
|
|
115
|
+
variable_length += 1
|
|
116
|
+
|
|
117
|
+
# Now we can allocate the byte array
|
|
118
|
+
properties_bytes = bytearray(variable_length + properties_length)
|
|
119
|
+
view = memoryview(properties_bytes)
|
|
120
|
+
|
|
121
|
+
i = 0
|
|
122
|
+
while properties_length > 0x7F:
|
|
123
|
+
view[i] = (properties_length & 0x7F) | 0x80
|
|
124
|
+
properties_length >>= 7
|
|
125
|
+
i += 1
|
|
126
|
+
|
|
127
|
+
view[i] = properties_length
|
|
128
|
+
i += 1
|
|
129
|
+
|
|
130
|
+
for key, value in pre_encoded_properties.items():
|
|
131
|
+
view[i] = key
|
|
132
|
+
i += 1
|
|
133
|
+
view[i : i + len(value)] = value
|
|
134
|
+
i += len(value)
|
|
135
|
+
|
|
136
|
+
return properties_bytes
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
def decode_byte(props, offset):
|
|
140
|
+
value = props[offset]
|
|
141
|
+
offset += 1
|
|
142
|
+
return value, offset
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
def decode_two_byte_int(props, offset):
|
|
146
|
+
value = struct.unpack_from("!H", props, offset)[0]
|
|
147
|
+
offset += 2
|
|
148
|
+
return value, offset
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
def decode_four_byte_int(props, offset):
|
|
152
|
+
value = struct.unpack_from("!I", props, offset)[0]
|
|
153
|
+
offset += 4
|
|
154
|
+
return value, offset
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
def decode_string(props, offset):
|
|
158
|
+
str_length = struct.unpack_from("!H", props, offset)[0]
|
|
159
|
+
offset += 2
|
|
160
|
+
value = props[offset : offset + str_length].decode("utf-8")
|
|
161
|
+
offset += str_length
|
|
162
|
+
return value, offset
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
def decode_string_pair(props, offset):
|
|
166
|
+
key, offset = decode_string(props, offset)
|
|
167
|
+
value, offset = decode_string(props, offset)
|
|
168
|
+
item = {key: value}
|
|
169
|
+
return item, offset
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
def decode_binary(props, offset):
|
|
173
|
+
data_length = struct.unpack_from("!H", props, offset)[0]
|
|
174
|
+
offset += 2
|
|
175
|
+
value = props[offset : offset + data_length]
|
|
176
|
+
offset += data_length
|
|
177
|
+
return value, offset
|
|
178
|
+
|
|
179
|
+
|
|
180
|
+
def decode_variable_byte_int(props, offset):
|
|
181
|
+
value = 0
|
|
182
|
+
for i in range(4):
|
|
183
|
+
b = props[offset]
|
|
184
|
+
value |= (b & 0x7F) << (7 * i)
|
|
185
|
+
offset += 1
|
|
186
|
+
if not b & 0x80:
|
|
187
|
+
break
|
|
188
|
+
return value, offset
|
|
189
|
+
|
|
190
|
+
|
|
191
|
+
decode_property_lookup = {
|
|
192
|
+
0x01: decode_byte, # Payload Format Indicator
|
|
193
|
+
0x02: decode_four_byte_int, # Message Expiry Interval
|
|
194
|
+
0x03: decode_string, # Content Type
|
|
195
|
+
0x08: decode_string, # Response Topic
|
|
196
|
+
0x09: decode_binary, # Correlation Data
|
|
197
|
+
0x0B: decode_variable_byte_int, # Subscription Identifier
|
|
198
|
+
0x11: decode_four_byte_int, # Session Expiry Interval
|
|
199
|
+
0x12: decode_string, # Assigned Client Identifier
|
|
200
|
+
0x13: decode_two_byte_int, # Server Keep Alive
|
|
201
|
+
0x15: decode_string, # Authentication Method
|
|
202
|
+
0x16: decode_binary, # Authentication Data
|
|
203
|
+
0x17: decode_byte, # Request Problem Information
|
|
204
|
+
0x18: decode_four_byte_int, # Will Delay Interval
|
|
205
|
+
0x19: decode_byte, # Request Response Information
|
|
206
|
+
0x1A: decode_string, # Response Information
|
|
207
|
+
0x1C: decode_string, # Server Reference
|
|
208
|
+
0x1F: decode_string, # Reason String
|
|
209
|
+
0x21: decode_two_byte_int, # Receive Maximum
|
|
210
|
+
0x22: decode_two_byte_int, # Topic Alias Maximum
|
|
211
|
+
0x23: decode_two_byte_int, # Topic Alias
|
|
212
|
+
0x24: decode_byte, # Maximum QoS
|
|
213
|
+
0x25: decode_byte, # Retain Available
|
|
214
|
+
0x26: decode_string_pair, # User Property
|
|
215
|
+
0x27: decode_four_byte_int, # Maximum Packet Size
|
|
216
|
+
0x28: decode_byte, # Wildcard Subscription Available
|
|
217
|
+
0x29: decode_byte, # Subscription Identifiers Available
|
|
218
|
+
0x2A: decode_byte, # Shared Subscription Available
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
|
|
222
|
+
def decode_properties(props, properties_length):
|
|
223
|
+
if isinstance(props, memoryview):
|
|
224
|
+
props = bytes(props) # If a memoryview is passed, make a copy
|
|
225
|
+
offset = 0
|
|
226
|
+
properties = {}
|
|
227
|
+
|
|
228
|
+
while offset < properties_length:
|
|
229
|
+
property_identifier = props[offset]
|
|
230
|
+
offset += 1
|
|
231
|
+
|
|
232
|
+
if property_identifier in decode_property_lookup:
|
|
233
|
+
decode_function = decode_property_lookup[property_identifier]
|
|
234
|
+
value, offset = decode_function(props, offset)
|
|
235
|
+
properties[property_identifier] = value
|
|
236
|
+
else:
|
|
237
|
+
raise ValueError(f"Unknown property identifier: {property_identifier}")
|
|
238
|
+
|
|
239
|
+
return properties
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
# range.py Test of asynchronous mqtt client with clean session False.
|
|
2
|
+
# (C) Copyright Peter Hinch 2017-2024.
|
|
3
|
+
# Released under the MIT licence.
|
|
4
|
+
|
|
5
|
+
# Now uses the event interface
|
|
6
|
+
|
|
7
|
+
# Public brokers https://github.com/mqtt/mqtt.github.io/wiki/public_brokers
|
|
8
|
+
|
|
9
|
+
# This demo is for wireless range tests. If OOR the red WiFi ON LED will go out.
|
|
10
|
+
# In range the blue LED will pulse for each received message.
|
|
11
|
+
# Uses clean sessions to avoid backlog when OOR.
|
|
12
|
+
|
|
13
|
+
# red LED: ON == WiFi OK
|
|
14
|
+
# blue LED pulse == message received
|
|
15
|
+
# Publishes connection statistics.
|
|
16
|
+
|
|
17
|
+
from mqtt_as import MQTTClient
|
|
18
|
+
from mqtt_local import wifi_led, blue_led, config
|
|
19
|
+
import uasyncio as asyncio
|
|
20
|
+
|
|
21
|
+
TOPIC = "shed" # For demo publication and last will use same topic
|
|
22
|
+
|
|
23
|
+
outages = 0
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
async def pulse(): # This demo pulses blue LED each time a subscribed msg arrives.
|
|
27
|
+
blue_led(True)
|
|
28
|
+
await asyncio.sleep(1)
|
|
29
|
+
blue_led(False)
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
async def messages(client):
|
|
33
|
+
async for topic, msg, retained in client.queue:
|
|
34
|
+
print(f'Topic: "{topic.decode()}" Message: "{msg.decode()}" Retained: {retained}')
|
|
35
|
+
asyncio.create_task(pulse())
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
async def down(client):
|
|
39
|
+
global outages
|
|
40
|
+
while True:
|
|
41
|
+
await client.down.wait() # Pause until connectivity changes
|
|
42
|
+
client.down.clear()
|
|
43
|
+
wifi_led(False)
|
|
44
|
+
outages += 1
|
|
45
|
+
print("WiFi or broker is down.")
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
async def up(client):
|
|
49
|
+
while True:
|
|
50
|
+
await client.up.wait()
|
|
51
|
+
client.up.clear()
|
|
52
|
+
wifi_led(True)
|
|
53
|
+
print("We are connected to broker.")
|
|
54
|
+
await client.subscribe("foo_topic", 1)
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
async def main(client):
|
|
58
|
+
try:
|
|
59
|
+
await client.connect(quick=True)
|
|
60
|
+
except OSError:
|
|
61
|
+
print("Connection failed.")
|
|
62
|
+
return
|
|
63
|
+
for task in (up, down, messages):
|
|
64
|
+
asyncio.create_task(task(client))
|
|
65
|
+
n = 0
|
|
66
|
+
while True:
|
|
67
|
+
await asyncio.sleep(5)
|
|
68
|
+
print("publish", n)
|
|
69
|
+
# If WiFi is down the following will pause for the duration.
|
|
70
|
+
await client.publish(
|
|
71
|
+
TOPIC, "{} repubs: {} outages: {}".format(n, client.REPUB_COUNT, outages), qos=1
|
|
72
|
+
)
|
|
73
|
+
n += 1
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
# Define configuration
|
|
77
|
+
config["will"] = (TOPIC, "Goodbye cruel world!", False, 0)
|
|
78
|
+
config["keepalive"] = 120
|
|
79
|
+
config["queue_len"] = 1 # Use event interface with default queue
|
|
80
|
+
|
|
81
|
+
# Set up client. Enable optional debug statements.
|
|
82
|
+
MQTTClient.DEBUG = True
|
|
83
|
+
client = MQTTClient(config)
|
|
84
|
+
|
|
85
|
+
try:
|
|
86
|
+
asyncio.run(main(client))
|
|
87
|
+
finally: # Prevent LmacRxBlk:1 errors.
|
|
88
|
+
client.close()
|
|
89
|
+
blue_led(True)
|
|
90
|
+
asyncio.new_event_loop()
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
# range_ex.py Test of asynchronous mqtt client with clean session False.
|
|
2
|
+
# Extended version publishes SSID
|
|
3
|
+
# (C) Copyright Peter Hinch 2017-2024.
|
|
4
|
+
# Released under the MIT licence.
|
|
5
|
+
|
|
6
|
+
# Now uses the event interface
|
|
7
|
+
|
|
8
|
+
# Public brokers https://github.com/mqtt/mqtt.github.io/wiki/public_brokers
|
|
9
|
+
|
|
10
|
+
# This demo is for wireless range tests. If OOR the red LED will light.
|
|
11
|
+
# In range the blue LED will pulse for each received message.
|
|
12
|
+
# Uses clean sessions to avoid backlog when OOR.
|
|
13
|
+
|
|
14
|
+
# red LED: ON == WiFi fail
|
|
15
|
+
# blue LED pulse == message received
|
|
16
|
+
# Publishes connection statistics.
|
|
17
|
+
|
|
18
|
+
from mqtt_as import MQTTClient, RP2
|
|
19
|
+
|
|
20
|
+
if RP2:
|
|
21
|
+
from sys import implementation
|
|
22
|
+
from mqtt_local import wifi_led, blue_led, config
|
|
23
|
+
import uasyncio as asyncio
|
|
24
|
+
import network
|
|
25
|
+
import gc
|
|
26
|
+
|
|
27
|
+
TOPIC = "shed" # For demo publication and last will use same topic
|
|
28
|
+
|
|
29
|
+
outages = 0
|
|
30
|
+
rssi = -199 # Effectively zero signal in dB.
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
async def pulse(): # This demo pulses blue LED each time a subscribed msg arrives.
|
|
34
|
+
blue_led(True)
|
|
35
|
+
await asyncio.sleep(1)
|
|
36
|
+
blue_led(False)
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
# The only way to measure RSSI is via scan(). Alas scan() blocks so the code
|
|
40
|
+
# causes the obvious uasyncio issues.
|
|
41
|
+
async def get_rssi():
|
|
42
|
+
global rssi
|
|
43
|
+
s = network.WLAN()
|
|
44
|
+
ssid = config["ssid"].encode("UTF8")
|
|
45
|
+
while True:
|
|
46
|
+
try:
|
|
47
|
+
rssi = [x[3] for x in s.scan() if x[0] == ssid][0]
|
|
48
|
+
except IndexError: # ssid not found.
|
|
49
|
+
rssi = -199
|
|
50
|
+
await asyncio.sleep(30)
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
async def messages(client):
|
|
54
|
+
async for topic, msg, retained in client.queue:
|
|
55
|
+
print(f'Topic: "{topic.decode()}" Message: "{msg.decode()}" Retained: {retained}')
|
|
56
|
+
asyncio.create_task(pulse())
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
async def down(client):
|
|
60
|
+
global outages
|
|
61
|
+
while True:
|
|
62
|
+
await client.down.wait() # Pause until connectivity changes
|
|
63
|
+
client.down.clear()
|
|
64
|
+
wifi_led(False)
|
|
65
|
+
outages += 1
|
|
66
|
+
print("WiFi or broker is down.")
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
async def up(client):
|
|
70
|
+
while True:
|
|
71
|
+
await client.up.wait()
|
|
72
|
+
client.up.clear()
|
|
73
|
+
wifi_led(True)
|
|
74
|
+
print("We are connected to broker.")
|
|
75
|
+
await client.subscribe("foo_topic", 1)
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
async def main(client):
|
|
79
|
+
try:
|
|
80
|
+
await client.connect()
|
|
81
|
+
except OSError:
|
|
82
|
+
print("Connection failed.")
|
|
83
|
+
return
|
|
84
|
+
asyncio.create_task(up(client))
|
|
85
|
+
asyncio.create_task(down(client))
|
|
86
|
+
asyncio.create_task(messages(client))
|
|
87
|
+
n = 0
|
|
88
|
+
s = "{} repubs: {} outages: {} rssi: {}dB free: {}bytes discards: {}"
|
|
89
|
+
while True:
|
|
90
|
+
await asyncio.sleep(5)
|
|
91
|
+
gc.collect()
|
|
92
|
+
m = gc.mem_free()
|
|
93
|
+
print("publish", n)
|
|
94
|
+
# If WiFi is down the following will pause for the duration.
|
|
95
|
+
await client.publish(
|
|
96
|
+
TOPIC, s.format(n, client.REPUB_COUNT, outages, rssi, m, client.queue.discards), qos=1
|
|
97
|
+
)
|
|
98
|
+
n += 1
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
# Define configuration
|
|
102
|
+
config["will"] = (TOPIC, "Goodbye cruel world!", False, 0)
|
|
103
|
+
config["keepalive"] = 120
|
|
104
|
+
config["queue_len"] = 4 # Use event interface
|
|
105
|
+
|
|
106
|
+
# Set up client. Enable optional debug statements.
|
|
107
|
+
MQTTClient.DEBUG = True
|
|
108
|
+
client = MQTTClient(config)
|
|
109
|
+
|
|
110
|
+
# Currently (Apr 22) this task causes connection periodically to be dropped on Arduino Nano Connect
|
|
111
|
+
# It does work on Pico W
|
|
112
|
+
if not RP2 or "Pico W" in implementation._machine:
|
|
113
|
+
asyncio.create_task(get_rssi())
|
|
114
|
+
try:
|
|
115
|
+
asyncio.run(main(client))
|
|
116
|
+
finally: # Prevent LmacRxBlk:1 errors.
|
|
117
|
+
client.close()
|
|
118
|
+
blue_led(True)
|
|
119
|
+
asyncio.new_event_loop()
|
|
@@ -29,6 +29,7 @@ class micrOSIM():
|
|
|
29
29
|
def __init__(self, doc_resolve=False):
|
|
30
30
|
if doc_resolve:
|
|
31
31
|
console("[micrOSIM] Create micrOS LM doc (env proc)")
|
|
32
|
+
self._init_sim_doc_resolve()
|
|
32
33
|
# json_structure, html_structure
|
|
33
34
|
self.doc_output = (None, None)
|
|
34
35
|
else:
|
|
@@ -38,7 +39,19 @@ class micrOSIM():
|
|
|
38
39
|
self.pid = None
|
|
39
40
|
micrOSIM.SIM_PROCESS_LIST.append(self.process)
|
|
40
41
|
|
|
42
|
+
def _init_sim_doc_resolve(self):
|
|
43
|
+
"""
|
|
44
|
+
Init micrOS in simulator - folder structure creation
|
|
45
|
+
"""
|
|
46
|
+
sim_path = LocalMachine.SimplePopPushd()
|
|
47
|
+
sim_path.pushd(SIM_PATH)
|
|
48
|
+
import micrOS # Init micrOS - DO NOT REMOVE
|
|
49
|
+
sim_path.popd()
|
|
50
|
+
|
|
41
51
|
def micrOS_sim_worker(self, trace=False):
|
|
52
|
+
"""
|
|
53
|
+
Start micrOS in python simulator
|
|
54
|
+
"""
|
|
42
55
|
sim_path = LocalMachine.SimplePopPushd()
|
|
43
56
|
sim_path.pushd(SIM_PATH)
|
|
44
57
|
console("[micrOSIM] Start micrOS loader in: {}".format(SIM_PATH))
|
|
@@ -130,7 +143,7 @@ class micrOSIM():
|
|
|
130
143
|
console(f"[micrOSIM][Extract doc-str] LM_{mod}.{func}.__doc__")
|
|
131
144
|
try:
|
|
132
145
|
# Get function doc string
|
|
133
|
-
exec(f"import LM_{mod}")
|
|
146
|
+
exec(f"from modules import LM_{mod}")
|
|
134
147
|
doc_str = eval(f"LM_{mod}.{func}.__doc__")
|
|
135
148
|
# Get function pin map
|
|
136
149
|
if func == 'pinmap':
|
toolkit/simulator_lib/uos.py
CHANGED
|
@@ -68,6 +68,7 @@ def rename(old_path, new_path):
|
|
|
68
68
|
print(f"[uos.SIM] rename: {old_path} -> {new_path}")
|
|
69
69
|
os.rename(old_path, new_path)
|
|
70
70
|
|
|
71
|
+
|
|
71
72
|
def _stat_eval(stat_result):
|
|
72
73
|
"""
|
|
73
74
|
micropython converter
|
|
@@ -82,6 +83,7 @@ def _stat_eval(stat_result):
|
|
|
82
83
|
return (micropython_file_identifier['dir'],)
|
|
83
84
|
return (0x0,)
|
|
84
85
|
|
|
86
|
+
|
|
85
87
|
def stat(path):
|
|
86
88
|
path = __mock_sim_dir(path)
|
|
87
89
|
stat_result = os.stat(path)
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
File without changes
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|