Standalone architecture. ======================== The project of a microcontroller program for an escape room has the following structure: * boot.py * main.py * dispatcher.py * message_queue.py * app.py These files are necessary for making a standalone device for an escape room. The microcontroller executes ``boot.py`` when it starts. It's empty in this architecture. **Usually, you should not modify it.** The microcontroller executes ``main.py`` when ``boot.py`` terminates. It creates internal message queue that allows to communicate between subapplications. Then it creates an ``App`` instance, calls instance ``start()`` method for a time, and executes the infinite loop that periodically checks income messages and calls ``loop()`` method of ``App`` instance. **Usually, you should not modify it.** The ``message_queue.py`` contains ``InternalMessageQueue`` class, that provides MQTT interface from Architecture v2. **Usually, you should not modify it.** .. class:: InternalMessageQueue() Internal message queue that allows to communicate between applications. It creates ``Dispatcher`` instance to dispatch messages. There are no arguments. .. method:: InternalMessageQueue.set_callback(callback) Set callback that handles package. The arguments is: * ``callback`` function that handles package. Returns ``None``. .. method:: InternalMessageQueue.publish(topic, msg, retain=False, qos=0) Publish message to dispatcher. The arguments are: * ``topic`` is a fake MQTT topic to publish message. * ``msg`` is a message to publish. * ``retain`` is a fake MQTT message retain parameter. * ``qos`` is a fake MQTT QoS. Returns ``None``. .. method:: InternalMessageQueue.publish_event(call, args=None) Publish event dispatcher. The arguments are: * ``call`` is an event. * ``args`` is a dict with event arguments. Returns ``None``. .. method:: InternalMessageQueue.check_msg() Send messages from queue to application, if queue contains them. Send one message per call. There are no arguments. Returns ``None``. The ``dispatcher.py`` contains ``Dispatcher`` class, that contains events and messages handlers. You need to place your logic in it's methods. .. class:: Dispatcher(message_queue) Dispatcher handles messages and events. The argument is: * ``message_queue`` is internal message_queue that allows to communicate between applications. .. method:: Dispatcher.dispatch_event(package) Dispatch event published by ``MessageQueue.publish_event()``. **You need to place your dispatching logic here.** The argument is: * ``package`` is a dict that contains ``call`` and ``args`` keys. Returns ``None``. .. method:: Dispatcher.dispatch_message(topic, msg, retain, qos) Dispatch message published by ``MessageQueue.publish_message()``. **You need to place your dispatching logic here.** The arguments are: * ``topic`` is a fake MQTT topic to publish message. * ``msg`` is a message to publish. * ``retain`` is a fake MQTT message retain parameter. * ``qos`` is a fake MQTT QoS. Returns ``None``. .. method:: Dispatcher.publish(package) Publish package to message queue. The argument is: * ``package`` is a dict that will be passed to ``App.on_message``. Returns ``None``. The ``App.py`` file contains the main class of microcontroller escape room application. .. class:: App(client) :noindex: App is the main class of microcontroller escape room application. **You need to implement it's methods to make an application.** The arguments are: * ``client`` is an internal message queue. The ``__init__`` should make this arguments members. .. method:: App.on_message(package) :noindex: The MQTT messages handler. The ``main.py`` calls this method when any MQTT message is received. The arguments are: * ``package`` is a parsed JSON as dict. Returns ``None``. .. method:: App.start() :noindex: Make some things after connection to internal message queue. Usually this method sends greating message. **You should not initialize peripheral devices here. Do it in** ``__init__`` **instead.** Returns ``None``. .. method:: App.loop() :noindex: Make main periodically logic. Returns ``None``. File template:: import gc import utime class App: def __init__(self, client, topic): self.client = client self.topic = topic def on_message(self, package): print(package) self.client.publish('micropython', 'hello') def start(self): pass def loop(self): time.sleep_ms(1000) print(gc.mem_free())