██ ██████ █████ ██████ ███ ███ ██████ ██████ ██ ██ ██ ███████ ███████
██ ██ ██ ██ ██ ██ ██ ████ ████ ██ ██ ██ ██ ██ ██ ██ ██ ██
██ ██ ██ ███████ ██ ██ ██ ████ ██ ██ ██ ██ ██ ██ ██ ██ █████ ███████
██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██
███████ ██████ ██ ██ ██████ ██ ██ ██████ ██████ ██████ ███████ ███████ ███████
- Create python file with the following naming convension:
LM_
your_app.py
- You can create any function in this modul, these will be exposed by micrOS framework over IP so these can be accessable via phone client or web application (webui)
- Drag-n-Drop LM file to micrOS devToolKit GUI
- Select device
- Press upload
██████ ███████ ██████ ██ ███ ██ ███ ██ ███████ ██████
██ ██ ██ ██ ██ ████ ██ ████ ██ ██ ██ ██
██████ █████ ██ ███ ██ ██ ██ ██ ██ ██ ██ █████ ██████
██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██
██████ ███████ ██████ ██ ██ ████ ██ ████ ███████ ██ ██ level
def hello(name="Anonymous"):
return f"Hello {name}!"
def add_two_numbers(a, b):
return f"{a}+{b} = {a+b}"
def help(widgets=False):
return ("hello name='Anonymous'",
"add_two_numbers a b")
from machine import Pin # Import micropython Pin module
LED = None # Cache created Pin instance
def load(pin_number=4):
global LED
if LED is None:
LED = Pin(pin_number, Pin.OUT) # Init PIN 4 as OUTPUT and store (cache) in global var.
return LED
def on():
pin = load()
pin.value(1) # Set pin high - LED ON
return "LED ON"
def off():
pin = load()
pin.value(0) # Set pin low - LED OFF
return "LED OFF"
def toggle():
pin = load()
pin.value(not pin.value())
return "LED ON" if pin.value() else "LED OFF"
def help():
return 'load', 'on', 'off', 'toggle'
For more info: Micropython official Pins
Function naming convesions for Load Modules.
from machine import Pin
from microIO import register_pin, pinmap_search
LED = None # Cache created Pin instance
def load(pin_number=4):
"""
[RECOMMENDED]
Function Naming Convetion for module load/init
"""
global LED
if LED is None:
pin = register_pin('led', pin_number) # Book pin 4 (as "led")
LED = Pin(pin, Pin.OUT) # Init PIN 4 as OUTPUT and store (cache) in global var.
return LED
def on():
pin = load()
pin.value(1) # Set pin high - LED ON
return "LED ON"
def off():
pin = load()
pin.value(0) # Set pin low - LED OFF
return "LED OFF"
def toggle():
pin = load()
pin.value(not pin.value())
return "LED ON" if pin.value() else "LED OFF"
def pinmap():
"""
[OPTIONAL]
pinmap_search - logical pinmap resolver based on IO_<device_tag>.py + Custom pins
return: dict {pinkey: pinvalue, ...}
"""
return pinmap_search(['led'])
def status(lmf=None):
"""
[OPTIONAL]
Function naming convension for
module state-machine return
return: dict
Example:
return {'S': 0/1}
Supported keys: {S, R, G, B, BR, X, Y}
"""
return {'S': LED.value()}
def help(widgets=False):
"""
[i] micrOS LM naming convention - built-in help message
:return tuple:
(widgets=False) list of functions implemented by this application
(widgets=True) list of widget json for UI generation
"""
return 'load', 'on', 'off', 'toggle', 'pinmap', 'status', 'help'
def resolve_pin(tag):
"""
Used in LoadModules
tag - resolve pin name by logical name (like: switch_1)
This function implements IO allocation/booking (with overload protection)
return: integer (pin number)
"""
Note: Used for multi-device pin support (advanced)
def register_pin(tag, number):
"""
Book pin (with overload protection) without IO_platform.py file editing
:param tag: associated pin name for pin number
:param number: pin number as integer
return: pin number
"""
Note: Simple micrOS pin allocation method
def pinmap_info():
"""
Debug info function to get active pinmap and booked IO-s
return: {'map': "platform", 'booked': {}, 'custom': {}}
"""
def pinmap_search(keys):
"""
:param keys: one or list of pin names (like: switch_1) to resolve physical pin number
Gives information where to connect the selected periphery to control WITHOUT PIN BOOKING
"""
██ ███ ██ ████████ ███████ ██████ ███ ███ ███████ ██████ ██ █████ ████████ ███████
██ ████ ██ ██ ██ ██ ██ ████ ████ ██ ██ ██ ██ ██ ██ ██ ██
██ ██ ██ ██ ██ █████ ██████ ██ ████ ██ █████ ██ ██ ██ ███████ ██ █████
██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██
██ ██ ████ ██ ███████ ██ ██ ██ ██ ███████ ██████ ██ ██ ██ ██ ███████ level
Advanced help messages with widget type assignment
Normally in help function you can return a tuple of strings, this can be queried as help message from ShellCli and WebCli.
With Types.resolve
integration you can easily extend normal human readable help messages,
and enable machine readable output for frontend element generation.
Main steps:
- Create
help
function withwidgets
parameter - Wrap help tuple into
resolve
function - Use predefined widget types (tags)
- Check the following example:
Tags:
BUTTON
, requires[0]: no paramCOLOR
, requires[3]: r, g, b function parametersSLIDER
, requires[1]: br function parameters (or any other single param)TEXTBOX
, requires[0]: no paramJOYSTICK
, requires[1]: x and y function parameters- Implementation of TYPES
from machine import Pin
from microIO import register_pin, pinmap_search
from Types import resolve
LED = None # Cache created Pin instance
def load(pin_number=4):
"""
[RECOMMENDED]
Function Naming Convetion for module load/init
"""
global LED
if LED is None:
pin = register_pin('led', pin_number) # Book pin 4 (as "led")
LED = Pin(pin, Pin.OUT) # Init PIN 4 as OUTPUT and store (cache) in global var.
return LED
def on():
pin = load()
pin.value(1) # Set pin high - LED ON
return "LED ON"
def off():
pin = load()
pin.value(0) # Set pin low - LED OFF
return "LED OFF"
def toggle():
pin = load()
pin.value(not pin.value())
return "LED ON" if pin.value() else "LED OFF"
def pinmap():
"""
[OPTIONAL]
pinmap_search - logical pinmap resolver based on IO_<device_tag>.py + Custom pins
return: dict {pinkey: pinvalue, ...}
"""
return pinmap_search(['led'])
def status(lmf=None):
"""
[OPTIONAL]
Function naming convension for
module state-machine return
return: dict
Example:
return {'S': 0/1}
Supported keys: {S, R, G, B, BR, X, Y}
"""
return {'S': LED.value()}
def help(widgets=False):
"""
[i] micrOS LM naming convention - built-in help message
:return tuple:
(widgets=False) list of functions implemented by this application
(widgets=True) list of widget json for UI generation
"""
return resolve(('load',
'BUTTON on',
'BUTTON off',
'BUTTON toggle',
'pinmap',
'status',
'help'), widgets)
Output:
simulator $ types_demo help
load,
on,
off,
toggle,
pinmap,
status,
help,
simulator $ types_demo help True
{"type": "button", "lm_call": "on ", "options": ["None"]},
{"type": "button", "lm_call": "off ", "options": ["None"]},
{"type": "button", "lm_call": "toggle ", "options": ["None"]},
Usage(s): LM_neopixel, etc. in most of the modules :)
TYPE Example sytax:
return resolve(('COLOR color r=<0-255> g b', # range syntax: <min-max-step> step is optional
'SLIDER brightness br=<0-1000-10>', # range syntax: <min-max-step> step is optional
'BUTTON action',
'BUTTON conntrol cmd=<Hello,Bello>', # options syntax: <opt1,opt2,...> list of parameters
'other_function num'), widgets=widgets)
█████ ██████ ██ ██ █████ ███ ██ ██████ ███████ ██████
██ ██ ██ ██ ██ ██ ██ ██ ████ ██ ██ ██ ██ ██
███████ ██ ██ ██ ██ ███████ ██ ██ ██ ██ █████ ██ ██
██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██
██ ██ ██████ ████ ██ ██ ██ ████ ██████ ███████ ██████ level
Module responsible for collecting additional feature definitions dedicated to the micrOS framework and LoadModules. Code: micrOS/source/Common.py
Example: LM_my_module.py
from Common import console
def write_and_light(msg="Hello world!"):
console(msg) # Use console write + built-in LED effect
# When dbg=True in node_config
Usage(s): LM_sound_event LM_demo
Generator for color transitions.
Parameters:
- from_val: Starting value
- to_val: Target value
- step_ms: Step to reach to_val
- interval_sec: Full intervals
Returns:
- A generator that yields the intermediate values between from_val and to_val in steps of step_ms.
Usage(s): LM_rgb LM_cct LM_servo
Create multiple transition generators.
Parameters:
- args: Pairs of from_val and to_val values for each channel
- interval_sec: Interval in seconds to calculate the optimal fade/transition effect
Returns:
- If only one transition generator is created, it returns the generator and the step size in milliseconds (gen, step_ms). If multiple transition generators are created, it returns a list of generators and the step size in milliseconds ([gen1, gen2, ...], step_ms).
Usage(s): LM_rgb LM_cct LM_servo
ADC wrapper class for reading analog values.
Methods:
- __init__(self, pin): Initializes the ADC object with the specified pin.
- get(self): Reads the analog value from the ADC and returns a dictionary with the raw value, percentage, and voltage.
- get_singleton(pin): Returns a singleton SmartADC object for the specified pin.
Async task creation from LoadModules.
Parameters:
- tag: If None, returns the task generator object. If a taskID is provided, returns the existing task object by tag.
- task: Coroutine to execute.
Returns:
- If tag is None, returns the task generator object. If a taskID is provided, returns the existing task object by tag. If task is provided, returns the task creation state: True for success, False for failure.
Example: LM_my_task.py
import uasyncio as asyncio
from Common import micro_task
async def __task(period_ms):
counter = 0
with micro_task(tag="mytask") as my_task:
while True:
# DO something here in the async loop...
counter += 1
# Store data in task cache (task show mytask)
my_task.out = f'MyTask Counter: {counter}'
# Async sleep - feed event loop
await asyncio.sleep_ms(period_ms)
def create_task():
# [!] ASYNC TASK CREATION [1*] with async task callback + taskID (TAG) handling
state = micro_task(tag="mytask", task=__task(period_ms=5))
return "Starting" if state else "Already running"
Usage(s): LM_presence LM_buzzer LM_cct LM_dimmer LM_neopixel LM_neopixel LM_rgb LM_roboarm etc.
Async task management from LoadModules.: show
, isbusy
, kill
Parameters:
tag
: Task string identifier. Used for task creation, or can be get astask list
command output.operation
: Opeartionshow
,isbusy
,kill
ontag
-ed task.
def manage_task(tag, operation):
"""
[LM] Async task management - user interface
:param tag: task tag
:param operation: kill / show / isbusy
"""
Usage(s): LM_oled_ui LM_i2s_mic
Run sync task from LoadModules by string list.
Parameters:
cmd
: String list for Load Module execution
Example:
cmd = ["system", "info"]
state, output = exec_cmd(cmd)
Where "system"
is the module name and "info"
is the function name, and it not requires any paramater.
Note:
cmd
can contain only one command with its optional paramater. So this method not supports multi command execution.
def exec_cmd(cmd):
"""
Single (sync) LM execution - user interface
:param cmd: command string list
return state, output
"""
Usage(s): LM_oled_ui
micrOS Common Data logger solution.
Parameters:
- f_name: Log name (without extension, automatically appends .dat)
- data: Data to append to the log. If None, reads the log and returns it as a message stream.
- limit: Line limit for the log (default: 12)
- msgobj: Socket stream object (automatically set)
Returns:
- If data is None, returns the log as a message stream. If data is provided, returns True if the write operation was successful, False otherwise.
Example: LM_my_logger.py
from Common import data_logger
def log_data(data):
if not data_logger(f_name="mylog", data=data, limit=20):
return "data_logger, error... check system alarms"
return "data saved."
def get_data():
return data_logger(f_name="mylog")
def help(widgets=False):
"""
[i] micrOS LM naming convention - built-in help message
:return tuple:
(widgets=False) list of functions implemented by this application
(widgets=True) list of widget json for UI generation
"""
return 'log_data data="value"', 'get_data'
Usage(s): LM_dht22
Adds an extra msgobj
to the wrapped function's argument list. The msgobj
provides a socket message interface for the open connection.
Example: LM_my_module.py
from Common import socket_stream
@socket_stream
def function_name(arg1, arg2, ..., msgobj=None):
# function body
msgobj("Reply from Load Module to shellCli :)")
Usage(s): LM_system
micrOS common notification handler (Telegram).
Prerequisite
Set Telegram API KEY in node config: telegram key
conf
telegram <API KEY>
noconf
my_notification "hello"
notify, msg was sent.
Parameters:
- text: Notification text
Returns:
- True if the notification was sent successfully, False otherwise.
Example: LM_my_notification.py
from Common import notify
def send_notification(msg="Hello from micrOS board"):
if not notify(msg):
return "notify, error... check system alarms"
return "notify, msg was sent."
Usage(s): LM_presence
Custom endpoint creation in order to receive GET requests. <localhost.local>/endpoint
from Load Modules to WebCli web server.
Prerequisite
Enable
webui True
in node config.
Parameters:
-
endpoint: name of the http endpoint after the main address, like
localhost.local/my_endpoint
, in this case themy_endpoint
is the input paramater here. -
Simple function return: callback function, this will be called when endpoint is called, it must return 2 values: html type and data for example
html/text, data
data for example:hello world
. Supported data types:text/html
,text/plain
,image/jpeg
. In short:
return "image/jpeg" | "text/html" | "text/plain", <data>
# <data>: binary | string
select one from between | signs
- Stream function return:
return "multipart/x-mixed-replace" | "multipart/form-data", <data>
# <data>: {'callback':<func>, 'content-type': 'image/jpeg' | 'audio/l16;...'}
select one from between | signs
Returns:
- True if function successfuly registered on the endpoint
Example: LM_my_endpoint.py
from Common import web_endpoint
def load():
...
web_endpoint('my_endpoint', _response)
return "Endpoint was created: http://localhost/my_endpoint"
def _response():
reply = "hello world"
return 'text/plain', reply
Usage(s): LM_OV2640