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.

InternalMessageQueue.set_callback(callback)

Set callback that handles package.

The arguments is:
  • callback function that handles package.

Returns None.

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.

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.

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.
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.

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.

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)

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.

App.on_message(package)

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.

App.start()

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.

App.loop()

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())