Skip to content

Commit a9be5df

Browse files
2 parents 98de07a + 787cec8 commit a9be5df

17 files changed

Lines changed: 1482 additions & 46 deletions

File tree

.gitmodules

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,6 @@
1515
[submodule "micropython-nostr"]
1616
path = micropython-nostr
1717
url = https://github.com/MicroPythonOS/micropython-nostr
18+
[submodule "esp32-component-rvswd"]
19+
path = esp32-component-rvswd
20+
url = https://github.com/Fri3dCamp/esp32-component-rvswd.git

c_mpos/micropython.cmake

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ set(MPOS_C_INCLUDES)
99
set(MPOS_C_INCLUDES
1010
${CMAKE_CURRENT_LIST_DIR}/../lvgl_micropython/lib/micropython/ports/esp32/managed_components/espressif__esp_codec_dev/include/
1111
${CMAKE_CURRENT_LIST_DIR}/../lvgl_micropython/lib/micropython/ports/esp32/managed_components/espressif__esp_codec_dev/interface/
12+
# RVSWD programmer component headers
13+
${CMAKE_CURRENT_LIST_DIR}/../esp32-component-rvswd/include/
1214
)
1315

1416
set(MPOS_C_SOURCES
@@ -20,6 +22,12 @@ set(MPOS_C_SOURCES
2022
${CMAKE_CURRENT_LIST_DIR}/quirc/lib/quirc.c
2123
# ${CMAKE_CURRENT_LIST_DIR}/../lvgl_micropython/lib/micropython/extmod/modwebrepl.c
2224
# ${CMAKE_CURRENT_LIST_DIR}/src/font_Noto_Sans_sat_emojis_compressed.c
25+
# RVSWD programmer component sources
26+
${CMAKE_CURRENT_LIST_DIR}/src/rvswd_module.c
27+
${CMAKE_CURRENT_LIST_DIR}/../esp32-component-rvswd/src/rvswd.c
28+
${CMAKE_CURRENT_LIST_DIR}/../esp32-component-rvswd/src/rvswd_ch32.c
29+
${CMAKE_CURRENT_LIST_DIR}/../esp32-component-rvswd/src/rvswd_ch32v20x.c
30+
${CMAKE_CURRENT_LIST_DIR}/../esp32-component-rvswd/src/rvswd_ch32x03x.c
2331
)
2432

2533
# Add our source files to the lib
@@ -42,4 +50,3 @@ target_compile_options(usermod_c_mpos INTERFACE
4250

4351
# Link our INTERFACE library to the usermod target.
4452
target_link_libraries(usermod INTERFACE usermod_c_mpos)
45-

c_mpos/src/rvswd_module.c

Lines changed: 399 additions & 0 deletions
Large diffs are not rendered by default.

esp32-component-rvswd

Submodule esp32-component-rvswd added at 7474128
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
{
2+
"name": "ESPNowChat",
3+
"publisher": "MicroPythonOS",
4+
"short_description": "ESPNow Chat",
5+
"long_description": "Simple chat app using EspNow protocol for communication between devices.",
6+
"icon_url": "https://apps.micropythonos.com/apps/com.micropythonos.espnow_chat/icons/com.micropythonos.espnow_chat_0.0.1_64x64.png",
7+
"download_url": "https://apps.micropythonos.com/apps/com.micropythonos.espnow_chat/mpks/com.micropythonos.espnow_chat_0.0.1.mpk",
8+
"fullname": "com.micropythonos.espnow_chat",
9+
"version": "0.1.0",
10+
"category": "development",
11+
"activities": [
12+
{
13+
"entrypoint": "assets/espnow_chat.py",
14+
"classname": "EspNowChat",
15+
"intent_filters": [
16+
{
17+
"action": "main",
18+
"category": "launcher"
19+
}
20+
]
21+
}
22+
]
23+
}
24+
Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
"""
2+
https://docs.micropython.org/en/latest/library/espnow.html
3+
"""
4+
5+
from collections import deque
6+
7+
import lvgl as lv
8+
import machine
9+
from micropython import const
10+
from mpos import Activity, MposKeyboard, TaskManager
11+
from mpos.time import localtime
12+
13+
try:
14+
import aioespnow
15+
except ImportError:
16+
aioespnow = None
17+
18+
try:
19+
import network
20+
except ImportError:
21+
network = None
22+
23+
BROADCAST_MAC = const(b"\xbb\xbb\xbb\xbb\xbb\xbb")
24+
25+
26+
def pformat_mac(mac):
27+
if mac:
28+
return ":".join(f"{b:02x}" for b in mac)
29+
else:
30+
return "<no mac>"
31+
32+
33+
class EspNowChat(Activity):
34+
def onCreate(self):
35+
main_content = lv.obj()
36+
main_content.set_flex_flow(lv.FLEX_FLOW.COLUMN)
37+
main_content.set_style_pad_gap(10, 0)
38+
39+
self.input_textarea = lv.textarea(main_content)
40+
self.input_textarea.set_placeholder_text("Message input...")
41+
self.input_textarea.set_one_line(True)
42+
self.input_textarea.set_style_text_font(lv.font_montserrat_16, lv.PART.MAIN)
43+
self.input_textarea.set_width(lv.pct(100))
44+
self.input_textarea.add_event_cb(self.show_keyboard, lv.EVENT.CLICKED, None)
45+
46+
self.keyboard = MposKeyboard(main_content)
47+
self.keyboard.set_textarea(self.input_textarea)
48+
self.keyboard.add_event_cb(self.keyboard_cb, lv.EVENT.READY, None)
49+
self.keyboard.add_flag(lv.obj.FLAG.HIDDEN)
50+
51+
self.messages = lv.label(main_content)
52+
self.messages.set_style_text_font(lv.font_montserrat_14, 0)
53+
54+
# Buffer to store and display the latest 20 messages:
55+
self.messages_buffer = deque((), 20)
56+
57+
self.setContentView(main_content)
58+
59+
if aioespnow and network:
60+
print("Initialize WLAN interface...")
61+
sta = network.WLAN(network.WLAN.IF_STA)
62+
sta.active(True)
63+
64+
self.own_id = pformat_mac(machine.unique_id())
65+
66+
self.info("Initialize ESPNow...")
67+
self.espnow = aioespnow.AIOESPNow()
68+
self.espnow.active(True)
69+
self.espnow.add_peer(BROADCAST_MAC)
70+
71+
if sta.isconnected():
72+
self.info(f"Connected to WiFi: {sta.config('essid')}")
73+
self.info(f"Use WiFi Channel: {sta.config('channel')}")
74+
else:
75+
self.own_id = "<no espnow>"
76+
self.info("ESPNow not available on this platform")
77+
78+
def info(self, text):
79+
now = localtime()
80+
hour, minute, second = now[3], now[4], now[5]
81+
message = f"{hour:02}:{minute:02}:{second:02} {text}"
82+
print(message)
83+
self.messages_buffer.appendleft(message)
84+
self.messages.set_text("\n".join(self.messages_buffer))
85+
86+
def keyboard_cb(self, event):
87+
message = self.input_textarea.get_text()
88+
if not message:
89+
print("Ignore empty input")
90+
else:
91+
self.input_textarea.set_text("")
92+
print(f"Create task to send {message=}...")
93+
TaskManager.create_task(self.send_messages(message))
94+
95+
def show_keyboard(self, event):
96+
print("Show keyboard")
97+
self.keyboard.remove_flag(lv.obj.FLAG.HIDDEN)
98+
99+
async def send_messages(self, message):
100+
self.info(f"Sending: {message} ({self.own_id})")
101+
try:
102+
await self.espnow.asend(BROADCAST_MAC, message.encode())
103+
except OSError as err:
104+
print(f"Error sending message: {err}")
105+
else:
106+
print(f"{message=} sent")
107+
108+
async def receive_messages(self):
109+
await self.send_messages(f"{self.own_id} joins ESPNow chat.")
110+
async for mac, msg in self.espnow:
111+
if not msg:
112+
print("Ignore empty message from", pformat_mac(mac))
113+
continue
114+
try:
115+
msg = msg.decode()
116+
except UnicodeError as err:
117+
msg = f"<invalid message: {err}>"
118+
self.info(f"{msg} ({pformat_mac(mac)})")
119+
raise RuntimeError("ESPNow receive loop exited, which shouldn't happen")
120+
121+
def onResume(self, screen):
122+
super().onResume(screen)
123+
if aioespnow and network:
124+
TaskManager.create_task(self.receive_messages())
125+
126+
def onPause(self, screen):
127+
if aioespnow and network:
128+
self.espnow.send(
129+
BROADCAST_MAC, f"{self.own_id} leaves ESPNow chat.".encode()
130+
)
131+
132+
print("Stop ESPNow...")
133+
self.espnow.active(False)
134+
print("ESPNow deactivated")
135+
136+
super().onPause(screen)
3.02 KB
Loading

internal_filesystem/builtin/apps/com.micropythonos.settings/assets/settings.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import lvgl as lv
22

3-
from mpos import Activity, Intent, AppearanceManager, AppManager, SettingActivity, SettingsActivity, TimeZone
3+
from mpos import Activity, Intent, AppearanceManager, AppManager, NumberFormat, SettingActivity, SettingsActivity, TimeZone
44

55
from bootloader import ResetIntoBootloader
66
from calibrate_imu import CalibrateIMUActivity
@@ -82,6 +82,7 @@ def getIntent(self):
8282
{"title": "Light/Dark Theme", "key": "theme_light_dark", "ui": "radiobuttons", "ui_options": [("Light", "light"), ("Dark", "dark")], "changed_callback": self.theme_changed},
8383
{"title": "Theme Color", "key": "theme_primary_color", "placeholder": "HTML hex color, like: EC048C", "ui": "dropdown", "ui_options": theme_colors, "changed_callback": self.theme_changed, "default_value": AppearanceManager.DEFAULT_PRIMARY_COLOR},
8484
{"title": "Timezone", "key": "timezone", "ui": "dropdown", "ui_options": [(tz, tz) for tz in TimeZone.get_timezones()], "changed_callback": lambda *args: TimeZone.refresh_timezone_preference()},
85+
{"title": "Number Format", "key": "number_format", "ui": "dropdown", "ui_options": NumberFormat.get_format_options(), "changed_callback": lambda *args: NumberFormat.refresh_preference(), "default_value": "comma_dot"},
8586
# Advanced settings, alphabetically:
8687
{"title": "Auto Start App", "key": "auto_start_app", "ui": "radiobuttons", "ui_options": [(app.name, app.fullname) for app in AppManager.get_app_list()]},
8788
{"title": "Check IMU Calibration", "key": "check_imu_calibration", "ui": "activity", "activity_class": CheckIMUCalibrationActivity},

0 commit comments

Comments
 (0)