micrOSDevToolKit 2.13.0__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.0.dist-info → microsdevtoolkit-2.17.0.dist-info}/METADATA +30 -37
- {microsdevtoolkit-2.13.0.dist-info → microsdevtoolkit-2.17.0.dist-info}/RECORD +201 -191
- 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/lib/pip_package_installer.py +5 -2
- 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.0.data → microsdevtoolkit-2.17.0.data}/scripts/devToolKit.py +0 -0
- {microsdevtoolkit-2.13.0.dist-info → microsdevtoolkit-2.17.0.dist-info}/WHEEL +0 -0
- {microsdevtoolkit-2.13.0.dist-info → microsdevtoolkit-2.17.0.dist-info}/licenses/LICENSE +0 -0
- {microsdevtoolkit-2.13.0.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
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
import json
|
|
2
|
+
import time
|
|
3
|
+
from mqtt_as import MQTTClient, config
|
|
4
|
+
from Config import cfgget
|
|
5
|
+
from Common import micro_task, console, syslog, exec_cmd
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class MQTT:
|
|
9
|
+
CLIENT:MQTTClient = None # MQTT Client (broker) instance
|
|
10
|
+
QOS: int = None
|
|
11
|
+
DEBUG: bool = True
|
|
12
|
+
DEFAULT_TOPIC: str = f"{cfgget('devfid')}/#"
|
|
13
|
+
|
|
14
|
+
# Micro Task TGS
|
|
15
|
+
SUB_TASK = 'mqtt.subscribe'
|
|
16
|
+
UNSUB_TASK = 'mqtt.unsubscribe'
|
|
17
|
+
CLIENT_TASK = 'mqtt.client'
|
|
18
|
+
UP_TASK = 'mqtt.up'
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
######################
|
|
22
|
+
# CORE MQTT HANDLERS #
|
|
23
|
+
######################
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
async def _receiver():
|
|
27
|
+
"""
|
|
28
|
+
Asynchronous loop that listens for incoming MQTT messages from the subscribed topics.
|
|
29
|
+
- Decodes topic and message.
|
|
30
|
+
- Validates JSON payload, runs commands via exec_cmd, and publishes a JSON-formatted response.
|
|
31
|
+
"""
|
|
32
|
+
async for topic, msg, retained in MQTT.CLIENT.queue:
|
|
33
|
+
incoming_topic, msg = topic.decode(), msg.decode()
|
|
34
|
+
console(f'Topic: "{incoming_topic}" Message: "{msg}" Retained: {retained}')
|
|
35
|
+
|
|
36
|
+
topic_parts = incoming_topic.split('/')
|
|
37
|
+
if len(topic_parts) == 3:
|
|
38
|
+
payload = {}
|
|
39
|
+
if msg.strip():
|
|
40
|
+
try:
|
|
41
|
+
payload = json.loads(msg)
|
|
42
|
+
except ValueError:
|
|
43
|
+
_publish_error(incoming_topic, f"Invalid payload JSON on topic {incoming_topic}: {msg}")
|
|
44
|
+
continue
|
|
45
|
+
|
|
46
|
+
args = [f'{k}="{v}"' if isinstance(v, str) else f'{k}={v}' for k, v in payload.items()]
|
|
47
|
+
|
|
48
|
+
cmd_parts = topic_parts[1:] + args
|
|
49
|
+
|
|
50
|
+
state, output_json = exec_cmd(cmd=cmd_parts, jsonify=True)
|
|
51
|
+
try:
|
|
52
|
+
output = json.loads(output_json)
|
|
53
|
+
except ValueError:
|
|
54
|
+
output = output_json
|
|
55
|
+
|
|
56
|
+
resp_payload = json.dumps({"state": state, "result": output})
|
|
57
|
+
publish(topic=f"{incoming_topic}/response", message=resp_payload)
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def _publish_error(topic: str, error_msg: str):
|
|
61
|
+
"""
|
|
62
|
+
Publish an error message to the <topic>/response MQTT topic and log it to the console.
|
|
63
|
+
:param topic: The original MQTT topic where the error occurred.
|
|
64
|
+
:param error_msg: The error message string.
|
|
65
|
+
"""
|
|
66
|
+
publish(topic=f"{topic}/response", message=error_msg)
|
|
67
|
+
console(error_msg)
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
#############################
|
|
71
|
+
# SUBSCRIPTION \ PUBLISHING #
|
|
72
|
+
#############################
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
async def _unsubscribe(topic: str):
|
|
76
|
+
"""
|
|
77
|
+
Unsubscribe from the specified MQTT topic.
|
|
78
|
+
:param topic: Topic string to unsubscribe from.
|
|
79
|
+
"""
|
|
80
|
+
with micro_task(tag=MQTT.UNSUB_TASK) as my_task:
|
|
81
|
+
my_task.out = "Started"
|
|
82
|
+
try:
|
|
83
|
+
console(f"Unsubscribe topic: {topic}")
|
|
84
|
+
await MQTT.CLIENT.unsubscribe(topic)
|
|
85
|
+
my_task.out = "Done"
|
|
86
|
+
except Exception as e:
|
|
87
|
+
my_task.out = f"Error: {e}"
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
async def _subscribe(topic: str):
|
|
91
|
+
"""
|
|
92
|
+
Subscribe to the specified MQTT topic with the global QoS.
|
|
93
|
+
:param topic: Topic string to subscribe to.
|
|
94
|
+
"""
|
|
95
|
+
with micro_task(tag=MQTT.SUB_TASK) as my_task:
|
|
96
|
+
my_task.out = "Started"
|
|
97
|
+
try:
|
|
98
|
+
console(f"Subscribe topic: {topic}")
|
|
99
|
+
await MQTT.CLIENT.subscribe(topic, qos=MQTT.QOS)
|
|
100
|
+
my_task.out = "Done"
|
|
101
|
+
except Exception as e:
|
|
102
|
+
my_task.out = f"Error: {e}"
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
async def _publish(tag, message: str, topic: str, retain: bool):
|
|
106
|
+
"""
|
|
107
|
+
Asynchronously publish a message to the given MQTT topic.
|
|
108
|
+
:param message: The message payload as a string.
|
|
109
|
+
:param topic: The MQTT topic string.
|
|
110
|
+
:param retain: Whether the message should be retained on the broker.
|
|
111
|
+
"""
|
|
112
|
+
with micro_task(tag) as my_task:
|
|
113
|
+
await MQTT.CLIENT.publish(topic, message, qos=MQTT.QOS, retain=retain)
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
def publish(topic: str, message: str, retain: bool = False):
|
|
117
|
+
"""
|
|
118
|
+
Wrapper to publish a message to the specified topic.
|
|
119
|
+
Creates a micro_task for asynchronous publishing.
|
|
120
|
+
:param topic: MQTT topic string.
|
|
121
|
+
:param message: Message string.
|
|
122
|
+
:param retain: Whether to retain the message on the broker (default False).
|
|
123
|
+
:return: Status message string.
|
|
124
|
+
"""
|
|
125
|
+
unique_tag = f'mqtt.publish.{topic}.{time.ticks_ms()}'
|
|
126
|
+
state = micro_task(tag=unique_tag, task=_publish(unique_tag, message, topic, retain))
|
|
127
|
+
return f"Message was sent {state}"
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
####################
|
|
131
|
+
# CLIENT LIFECYCLE #
|
|
132
|
+
####################
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
async def _up():
|
|
136
|
+
"""
|
|
137
|
+
UP Listener task that waits for an MQTT 'up' event (reconnection) and re-subscribes to the default topic.
|
|
138
|
+
"""
|
|
139
|
+
with micro_task(tag=MQTT.UP_TASK) as my_task:
|
|
140
|
+
while True:
|
|
141
|
+
# Wait for UP Event - (re)subscribe
|
|
142
|
+
my_task.out = "Wait"
|
|
143
|
+
await MQTT.CLIENT.up.wait()
|
|
144
|
+
MQTT.CLIENT.up.clear()
|
|
145
|
+
state = micro_task(tag=MQTT.SUB_TASK, task=_subscribe(MQTT.DEFAULT_TOPIC))
|
|
146
|
+
my_task.out = f"Re-Subscription {state}"
|
|
147
|
+
my_task.feed()
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
async def _init_client():
|
|
151
|
+
"""
|
|
152
|
+
Initialize and connect the MQTT client, subscribe to default topics,
|
|
153
|
+
start up-listener, and begin receiving messages.
|
|
154
|
+
"""
|
|
155
|
+
with micro_task(tag=MQTT.CLIENT_TASK) as my_task:
|
|
156
|
+
try:
|
|
157
|
+
await MQTT.CLIENT.connect()
|
|
158
|
+
my_task.out = "Connection successful."
|
|
159
|
+
except OSError:
|
|
160
|
+
my_task.out = "Connection failed."
|
|
161
|
+
return
|
|
162
|
+
|
|
163
|
+
# Wait for mqtt client connected successfully
|
|
164
|
+
await MQTT.CLIENT.up.wait()
|
|
165
|
+
MQTT.CLIENT.up.clear()
|
|
166
|
+
|
|
167
|
+
# Initialize mqtt topics
|
|
168
|
+
if not micro_task(tag=MQTT.SUB_TASK, task=_subscribe(MQTT.DEFAULT_TOPIC)):
|
|
169
|
+
syslog(f"Failed start mqtt subscribe")
|
|
170
|
+
if not micro_task(tag=MQTT.UP_TASK, task=_up()):
|
|
171
|
+
syslog(f"Failed start mqtt up")
|
|
172
|
+
# Async listener loop
|
|
173
|
+
await _receiver()
|
|
174
|
+
my_task.out = "Receiver closed"
|
|
175
|
+
|
|
176
|
+
# Close when listener exits
|
|
177
|
+
MQTT.CLIENT.close()
|
|
178
|
+
|
|
179
|
+
|
|
180
|
+
#################
|
|
181
|
+
# CONFIGURATION #
|
|
182
|
+
#################
|
|
183
|
+
|
|
184
|
+
|
|
185
|
+
def get_config():
|
|
186
|
+
"""
|
|
187
|
+
Get configuration for MQTT client.
|
|
188
|
+
:return: MQTT configuration dict.
|
|
189
|
+
"""
|
|
190
|
+
return config
|
|
191
|
+
|
|
192
|
+
|
|
193
|
+
def _configure(username: str, password: str, server_ip: str, server_port: str):
|
|
194
|
+
"""
|
|
195
|
+
Build the MQTT client configuration.
|
|
196
|
+
:param username: Broker username.
|
|
197
|
+
:param password: Broker password.
|
|
198
|
+
:param server_ip: Broker IP or hostname.
|
|
199
|
+
:param server_port: Broker port.
|
|
200
|
+
:return: Updated configuration dictionary.
|
|
201
|
+
"""
|
|
202
|
+
config.update({
|
|
203
|
+
'client_id': cfgget("devfid"),
|
|
204
|
+
'server': server_ip,
|
|
205
|
+
'port': server_port,
|
|
206
|
+
'user': username,
|
|
207
|
+
'password': password,
|
|
208
|
+
'ssid': cfgget("staessid"), # Only supports a single Wi-Fi connection. Multiple SSIDs not handled.
|
|
209
|
+
'wifi_pw': cfgget("stapwd"),
|
|
210
|
+
'keepalive': 120,
|
|
211
|
+
'queue_len': 1, # Use event interface with default queue
|
|
212
|
+
'will': (f'{cfgget("devfid")}/status', '{"status": "offline"}', True, 1)
|
|
213
|
+
})
|
|
214
|
+
return config
|
|
215
|
+
|
|
216
|
+
|
|
217
|
+
def load(username: str, password: str, server_ip: str, server_port: str='1883', qos: str=1):
|
|
218
|
+
"""
|
|
219
|
+
Configure, initialize, and start the MQTT client.
|
|
220
|
+
Requires that the micropython-mqtt package is installed. You can install it with:
|
|
221
|
+
mpremote mip install github:peterhinch/micropython-mqtt
|
|
222
|
+
:param username: Broker username.
|
|
223
|
+
:param password: Broker password.
|
|
224
|
+
:param server_ip: Broker IP or hostname.
|
|
225
|
+
:param server_port: MQTT port (default 1883).
|
|
226
|
+
:param qos: MQTT Quality of Service level (0, 1, or 2). Controls delivery guarantee.
|
|
227
|
+
:return: Status dict showing whether the client is starting or already running.
|
|
228
|
+
"""
|
|
229
|
+
MQTTClient.DEBUG = MQTT.DEBUG
|
|
230
|
+
MQTT.CLIENT = MQTTClient(_configure(username, password, server_ip, server_port))
|
|
231
|
+
MQTT.QOS = qos
|
|
232
|
+
|
|
233
|
+
state = micro_task(tag=MQTT.CLIENT_TASK, task=_init_client())
|
|
234
|
+
return {MQTT.CLIENT_TASK: "Starting"} if state else {MQTT.CLIENT_TASK: "Already running"}
|
|
235
|
+
|
|
236
|
+
|
|
237
|
+
def help(widgets=False):
|
|
238
|
+
"""
|
|
239
|
+
Show public functions. Return a tuple of public function usage strings for the MQTT module.
|
|
240
|
+
:param widgets: Unused, reserved for extra help formatting.
|
|
241
|
+
:return: Tuple of help strings.
|
|
242
|
+
"""
|
|
243
|
+
return ('load username:str password:str server_ip:str server_port:str="1883"',
|
|
244
|
+
'get_config',
|
|
245
|
+
'publish topic:str message:str retain=False')
|
|
246
|
+
|
|
@@ -100,7 +100,13 @@ def cycle(speed_ms:int=60, shift:bool=True, batch:bool=True):
|
|
|
100
100
|
return load().play(effect_cycle, speed_ms=speed_ms, bt_draw=batch, bt_size=4)
|
|
101
101
|
|
|
102
102
|
|
|
103
|
-
def rainbow(speed_ms=
|
|
103
|
+
def rainbow(speed_ms=50, br=15, batch=True):
|
|
104
|
+
"""
|
|
105
|
+
Rainbow effect animation
|
|
106
|
+
:param speed_ms: animation speed in milliseconds
|
|
107
|
+
:param br: Brightness of the pixels (0-100)
|
|
108
|
+
:param batch: Batch drawing of pixels (True/False)
|
|
109
|
+
"""
|
|
104
110
|
def _wheel(pos):
|
|
105
111
|
# Input a value 0 to 255 to get a color value.
|
|
106
112
|
# The colours are a transition r - g - b - back to r.
|
|
@@ -121,8 +127,7 @@ def rainbow(speed_ms=20, br=15, batch=True):
|
|
|
121
127
|
:param step: step size
|
|
122
128
|
"""
|
|
123
129
|
nonlocal pix_cnt, br
|
|
124
|
-
|
|
125
|
-
for color_wheel in range(0, 255, color_step):
|
|
130
|
+
for color_wheel in range(0, 255):
|
|
126
131
|
for index in range(0, pix_cnt):
|
|
127
132
|
rc_index = (index * 256 // pix_cnt) + color_wheel
|
|
128
133
|
r, g, b = _wheel(rc_index & 255)
|
|
@@ -157,6 +162,11 @@ def fire(speed_ms:int=150, br:int=30, batch:bool=True):
|
|
|
157
162
|
|
|
158
163
|
|
|
159
164
|
def shader(offset=0, size=6):
|
|
165
|
+
"""
|
|
166
|
+
Shader effect on neopixel ring.
|
|
167
|
+
:param offset: start pixel index
|
|
168
|
+
:param size: shader size (number of pixels)
|
|
169
|
+
"""
|
|
160
170
|
def effect_shader():
|
|
161
171
|
nonlocal size, offset, neoeffect
|
|
162
172
|
pix_cnt = Data.NEOPIXEL_OBJ.n
|
|
@@ -261,7 +271,7 @@ def help(widgets=False):
|
|
|
261
271
|
'BUTTON meteor speed_ms=60',
|
|
262
272
|
'cycle speed_ms=60 shift=True batch=True',
|
|
263
273
|
'BUTTON cycle speed_ms=60',
|
|
264
|
-
'rainbow speed_ms=
|
|
274
|
+
'rainbow speed_ms=50 br=15 batch=True',
|
|
265
275
|
'BUTTON rainbow',
|
|
266
276
|
'fire speed_ms=150 br=30 batch=True',
|
|
267
277
|
'BUTTON fire speed_ms=150',
|
|
@@ -1,10 +1,11 @@
|
|
|
1
|
+
from random import randint
|
|
1
2
|
from neopixel import NeoPixel
|
|
2
3
|
from machine import Pin
|
|
3
4
|
from utime import sleep_ms
|
|
4
5
|
|
|
5
6
|
from microIO import bind_pin
|
|
6
7
|
from Types import resolve
|
|
7
|
-
from Common import manage_task, AnimationPlayer
|
|
8
|
+
from Common import manage_task, AnimationPlayer, web_dir, syslog, web_endpoint
|
|
8
9
|
|
|
9
10
|
|
|
10
11
|
class NeoPixelMatrix(AnimationPlayer):
|
|
@@ -18,7 +19,7 @@ class NeoPixelMatrix(AnimationPlayer):
|
|
|
18
19
|
self.num_pixels = width * height
|
|
19
20
|
self.pixels = NeoPixel(Pin(pin, Pin.OUT), self.num_pixels)
|
|
20
21
|
self._color_buffer = [(0, 0, 0)] * self.num_pixels # Store original RGB values
|
|
21
|
-
self._brightness = 0.
|
|
22
|
+
self._brightness = 0.20 # Brightness level, default 20%
|
|
22
23
|
NeoPixelMatrix.INSTANCE = self
|
|
23
24
|
|
|
24
25
|
def update(self, x:int, y:int, color:tuple[int, int, int]):
|
|
@@ -34,6 +35,7 @@ class NeoPixelMatrix(AnimationPlayer):
|
|
|
34
35
|
for i in range(self.num_pixels):
|
|
35
36
|
# Write pixel buffer before write to ws2812
|
|
36
37
|
self.pixels[i] = (0, 0, 0)
|
|
38
|
+
self._color_buffer[i] = (0, 0, 0)
|
|
37
39
|
# Send buffer to device
|
|
38
40
|
self.draw()
|
|
39
41
|
|
|
@@ -41,9 +43,11 @@ class NeoPixelMatrix(AnimationPlayer):
|
|
|
41
43
|
"""
|
|
42
44
|
Zigzag layout: even rows left-to-right, odd rows right-to-left
|
|
43
45
|
"""
|
|
44
|
-
if
|
|
45
|
-
|
|
46
|
-
|
|
46
|
+
if zigzag is None or zigzag:
|
|
47
|
+
if y % 2 == 0:
|
|
48
|
+
return y * self.width + x
|
|
49
|
+
return y * self.width + (self.width - 1 - x)
|
|
50
|
+
return y * self.width + x
|
|
47
51
|
|
|
48
52
|
def _index_to_coord(self, index: int, zigzag:bool=True) -> tuple[int, int]:
|
|
49
53
|
"""
|
|
@@ -140,9 +144,21 @@ def load(width=8, height=8):
|
|
|
140
144
|
"""
|
|
141
145
|
if NeoPixelMatrix.INSTANCE is None:
|
|
142
146
|
NeoPixelMatrix(width=width, height=height, pin=bind_pin('neop'))
|
|
147
|
+
web_endpoint('matrixDraw', _web_endpoint_clb, auto_enable=False)
|
|
143
148
|
return NeoPixelMatrix.INSTANCE
|
|
144
149
|
|
|
145
150
|
|
|
151
|
+
def _web_endpoint_clb():
|
|
152
|
+
try:
|
|
153
|
+
with open(web_dir('matrix_draw.html'), 'r') as html:
|
|
154
|
+
html_content = html.read()
|
|
155
|
+
return 'text/html', html_content
|
|
156
|
+
except Exception as e:
|
|
157
|
+
syslog(f"[ERR] neomatrix web: {e}")
|
|
158
|
+
html_content = None
|
|
159
|
+
return 'text/plain', f'html_content error: {html_content}'
|
|
160
|
+
|
|
161
|
+
|
|
146
162
|
def pixel(x, y, color=None, show=True):
|
|
147
163
|
"""
|
|
148
164
|
Set pixel at (x,y) to RGB color.
|
|
@@ -205,6 +221,10 @@ def stop():
|
|
|
205
221
|
|
|
206
222
|
|
|
207
223
|
def draw_colormap(bitmap):
|
|
224
|
+
"""
|
|
225
|
+
Draw colors as a color map
|
|
226
|
+
[(x, y, (r, g,b)), ...]
|
|
227
|
+
"""
|
|
208
228
|
try:
|
|
209
229
|
load().draw_colormap(bitmap)
|
|
210
230
|
except Exception as e:
|
|
@@ -215,12 +235,22 @@ def draw_colormap(bitmap):
|
|
|
215
235
|
def get_colormap():
|
|
216
236
|
return load().export_colormap()
|
|
217
237
|
|
|
238
|
+
|
|
239
|
+
def status():
|
|
240
|
+
"""
|
|
241
|
+
Get the current status of the matrix
|
|
242
|
+
"""
|
|
243
|
+
r, g, b = NeoPixelMatrix.DEFAULT_COLOR
|
|
244
|
+
br = NeoPixelMatrix.INSTANCE._brightness
|
|
245
|
+
return {'r': r, 'g': g, 'b': b, 'br': int(br*100)}
|
|
246
|
+
|
|
247
|
+
|
|
218
248
|
# -----------------------------------------------------------------------------
|
|
219
249
|
# -----------------------------------------------------------------------------
|
|
220
250
|
|
|
221
251
|
def rainbow(speed_ms=0):
|
|
222
|
-
def
|
|
223
|
-
def
|
|
252
|
+
def _effect_rainbow():
|
|
253
|
+
def _hsv_to_rgb(h, s, v):
|
|
224
254
|
max_color = 150 #255
|
|
225
255
|
h = float(h)
|
|
226
256
|
s = float(s)
|
|
@@ -254,14 +284,14 @@ def rainbow(speed_ms=0):
|
|
|
254
284
|
for x in range(width):
|
|
255
285
|
index = y * width + x
|
|
256
286
|
hue = ((index + frame) % 64) / 64.0
|
|
257
|
-
r, g, b =
|
|
287
|
+
r, g, b = _hsv_to_rgb(hue, 1.0, 0.7)
|
|
258
288
|
yield x, y, (r, g, b)
|
|
259
289
|
|
|
260
|
-
return load().play(
|
|
290
|
+
return load().play(_effect_rainbow, speed_ms=speed_ms, bt_draw=True, bt_size=8)
|
|
261
291
|
|
|
262
292
|
|
|
263
|
-
def snake(speed_ms:int=30, length:int=
|
|
264
|
-
def
|
|
293
|
+
def snake(speed_ms:int=30, length:int=6):
|
|
294
|
+
def _effect_snake():
|
|
265
295
|
clear_color = (0, 0, 0)
|
|
266
296
|
total_pixels = 8 * 8
|
|
267
297
|
total_steps = total_pixels + length # run just past the end to clear tail
|
|
@@ -283,40 +313,110 @@ def snake(speed_ms:int=30, length:int=5):
|
|
|
283
313
|
color = (int(r * br), int(g * br), int(b * br))
|
|
284
314
|
yield x, y, color
|
|
285
315
|
|
|
286
|
-
return load().play(
|
|
316
|
+
return load().play(_effect_snake, speed_ms=speed_ms, bt_draw=False)
|
|
287
317
|
|
|
288
318
|
|
|
289
|
-
def
|
|
290
|
-
def
|
|
319
|
+
def spiral(speed_ms=40):
|
|
320
|
+
def _effect_spiral(trail=12, hold=6):
|
|
291
321
|
"""
|
|
292
|
-
|
|
293
|
-
|
|
322
|
+
Center-out spiral with row-prewarp so the visual is continuous
|
|
323
|
+
even when set_pixel() applies zigzag=True internally.
|
|
294
324
|
"""
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
325
|
+
try:
|
|
326
|
+
W = NeoPixelMatrix.INSTANCE.width
|
|
327
|
+
H = NeoPixelMatrix.INSTANCE.height
|
|
328
|
+
except:
|
|
329
|
+
W = H = 8
|
|
330
|
+
|
|
331
|
+
# --- build center-out spiral path in true matrix coords (x,y) ---
|
|
332
|
+
# exact center on odd sizes; upper-left of center 2x2 on even sizes
|
|
333
|
+
cx = (W // 2 - 1) if (W % 2 == 0) else (W // 2)
|
|
334
|
+
cy = (H // 2 - 1) if (H % 2 == 0) else (H // 2)
|
|
335
|
+
|
|
336
|
+
x, y = cx, cy
|
|
337
|
+
path, seen = [], set()
|
|
338
|
+
|
|
339
|
+
def _add(ax, ay):
|
|
340
|
+
if 0 <= ax < W and 0 <= ay < H and (ax, ay) not in seen:
|
|
341
|
+
seen.add((ax, ay))
|
|
342
|
+
path.append((ax, ay))
|
|
343
|
+
|
|
344
|
+
_add(x, y)
|
|
345
|
+
dirs = ((1, 0), (0, 1), (-1, 0), (0, -1)) # R, D, L, U
|
|
346
|
+
step_len, d = 1, 0
|
|
347
|
+
while len(path) < W * H:
|
|
348
|
+
for _ in range(2):
|
|
349
|
+
dx, dy = dirs[d & 3]
|
|
350
|
+
for _ in range(step_len):
|
|
351
|
+
x += dx; y += dy
|
|
352
|
+
_add(x, y)
|
|
353
|
+
if len(path) >= W * H: break
|
|
354
|
+
d += 1
|
|
355
|
+
if len(path) >= W * H: break
|
|
356
|
+
step_len += 1
|
|
357
|
+
|
|
358
|
+
# --- PREWARP ---
|
|
359
|
+
# Cancel the internal zigzag mapping: flip x on odd rows so
|
|
360
|
+
# set_pixel(zigzag=True) flips it back -> visually linear.
|
|
361
|
+
def _warp(ax, ay):
|
|
362
|
+
return (W - 1 - ax, ay) if (ay & 1) else (ax, ay)
|
|
363
|
+
|
|
364
|
+
off = (0, 0, 0)
|
|
365
|
+
|
|
366
|
+
def _shade(k):
|
|
367
|
+
r0, g0, b0 = NeoPixelMatrix.DEFAULT_COLOR
|
|
368
|
+
k = max(0.0, min(1.0, k)) ** 0.9
|
|
369
|
+
return int(r0 * k), int(g0 * k), int(b0 * k)
|
|
370
|
+
|
|
307
371
|
try:
|
|
308
372
|
NeoPixelMatrix.INSTANCE.clear()
|
|
309
373
|
except:
|
|
310
374
|
pass
|
|
311
|
-
# Collapse phase: back down, skipping the largest to avoid duplicate
|
|
312
|
-
for r in range(max_radius - 1, -1, -1):
|
|
313
|
-
for dx in range(-r, r + 2):
|
|
314
|
-
for dy in range(-r, r + 2):
|
|
315
|
-
x, y = cx + dx, cy + dy
|
|
316
|
-
if 0 <= x < width and 0 <= y < height:
|
|
317
|
-
yield x, y, NeoPixelMatrix.DEFAULT_COLOR
|
|
318
375
|
|
|
319
|
-
|
|
376
|
+
# expand with tail
|
|
377
|
+
for n in range(len(path)):
|
|
378
|
+
clear_at = n - trail - 1
|
|
379
|
+
if clear_at >= 0:
|
|
380
|
+
cx_, cy_ = _warp(*path[clear_at])
|
|
381
|
+
yield cx_, cy_, off
|
|
382
|
+
|
|
383
|
+
start = 0 if n < trail else (n - trail + 1)
|
|
384
|
+
span = max(1, n - start + 1)
|
|
385
|
+
for i in range(start, n + 1):
|
|
386
|
+
k = (i - start + 1) / span
|
|
387
|
+
px, py = _warp(*path[i])
|
|
388
|
+
yield px, py, _shade(k)
|
|
389
|
+
|
|
390
|
+
# brief hold
|
|
391
|
+
hx, hy = _warp(*path[-1])
|
|
392
|
+
for _ in range(hold):
|
|
393
|
+
yield hx, hy, _shade(1.0)
|
|
394
|
+
|
|
395
|
+
# shrink with fading tail
|
|
396
|
+
for n in range(len(path) - 1, -1, -1):
|
|
397
|
+
px, py = _warp(*path[n])
|
|
398
|
+
yield px, py, off
|
|
399
|
+
start = max(0, n - trail + 1)
|
|
400
|
+
span = max(1, n - start)
|
|
401
|
+
for i in range(start, n):
|
|
402
|
+
k = (i - start + 1) / span
|
|
403
|
+
qx, qy = _warp(*path[i])
|
|
404
|
+
yield qx, qy, _shade(k)
|
|
405
|
+
|
|
406
|
+
return load().play(_effect_spiral, speed_ms=speed_ms, bt_draw=True, bt_size=8)
|
|
407
|
+
|
|
408
|
+
|
|
409
|
+
def noise(speed_ms:int=85):
|
|
410
|
+
def _effect_noise():
|
|
411
|
+
total_steps = 8 * 8
|
|
412
|
+
for step in range(total_steps):
|
|
413
|
+
x, y = step % 8, step // 8
|
|
414
|
+
r, g, b = NeoPixelMatrix.DEFAULT_COLOR
|
|
415
|
+
br = float(randint(0, 100) * 0.01) # Generate random brightness
|
|
416
|
+
color = (int(r * br), int(g * br), int(b * br))
|
|
417
|
+
yield x, y, color
|
|
418
|
+
|
|
419
|
+
return load().play(_effect_noise, speed_ms=speed_ms, bt_draw=True, bt_size=4)
|
|
320
420
|
|
|
321
421
|
|
|
322
422
|
def help(widgets=False):
|
|
@@ -328,8 +428,10 @@ def help(widgets=False):
|
|
|
328
428
|
'BUTTON stop',
|
|
329
429
|
'BUTTON snake speed_ms=50 length=5',
|
|
330
430
|
'BUTTON rainbow',
|
|
331
|
-
'BUTTON
|
|
431
|
+
'BUTTON spiral speed_ms=40',
|
|
432
|
+
'BUTTON noise speed_ms=85',
|
|
332
433
|
'SLIDER control speed_ms=<1-200-2> bt_draw=None',
|
|
333
434
|
'draw_colormap bitmap=[(0,0,(10,2,0)),(x,y,color),...]',
|
|
334
|
-
'get_colormap'
|
|
435
|
+
'get_colormap',
|
|
436
|
+
'status'
|
|
335
437
|
), widgets=widgets)
|
|
@@ -341,7 +341,7 @@ class PageUI:
|
|
|
341
341
|
self.open_intercons.append(host)
|
|
342
342
|
try:
|
|
343
343
|
# Send CMD to other device & show result
|
|
344
|
-
state, data_meta = exec_cmd(cmd + [f">>{host}"], jsonify=True
|
|
344
|
+
state, data_meta = exec_cmd(cmd + [f">>{host}"], jsonify=True)
|
|
345
345
|
if state:
|
|
346
346
|
self.cmd_task_tag = data_meta['tag']
|
|
347
347
|
if "Task is Busy" in data_meta['verdict'] and not run:
|
|
@@ -386,7 +386,7 @@ class PageUI:
|
|
|
386
386
|
try:
|
|
387
387
|
cmd_list = cmd.strip().split()
|
|
388
388
|
# Send CMD to other device & show result
|
|
389
|
-
state, out = exec_cmd(cmd_list
|
|
389
|
+
state, out = exec_cmd(cmd_list)
|
|
390
390
|
try:
|
|
391
391
|
self.cmd_out = ''.join(out.strip().split()).replace(' ', '')
|
|
392
392
|
except Exception:
|
|
@@ -745,7 +745,7 @@ class PageUI:
|
|
|
745
745
|
try:
|
|
746
746
|
cmd_list = cmd.strip().split()
|
|
747
747
|
# Send CMD to other device & show result
|
|
748
|
-
state, out = exec_cmd(cmd_list
|
|
748
|
+
state, out = exec_cmd(cmd_list)
|
|
749
749
|
cmd_out = out.strip()
|
|
750
750
|
except Exception as e:
|
|
751
751
|
cmd_out = str(e)
|
|
@@ -780,7 +780,7 @@ class PageUI:
|
|
|
780
780
|
# Check open host connection
|
|
781
781
|
try:
|
|
782
782
|
# Send CMD to other device & show result
|
|
783
|
-
state, data_meta = exec_cmd(cmd + [f">>{host}"], jsonify=True
|
|
783
|
+
state, data_meta = exec_cmd(cmd + [f">>{host}"], jsonify=True)
|
|
784
784
|
if state:
|
|
785
785
|
self._cmd_task_tag = data_meta['tag']
|
|
786
786
|
if "Task is Busy" in data_meta['verdict'] and not run:
|