Architecture version 2.

The project of a microcontroller program for an escape room has the following structure:
  • config.json
  • boot.py
  • main.py
  • mqtt.py
  • app.py

If you don’t use JSON and EscapeRoomMakers server we recommend to use Architecture 1.

These files are necessary for making a device for an escape room.

The config.json file contains the configuration of the device.

Key Description
topic The topic that MQTT client will subscribe
mqtt_host The address of MQTT broker
mqtt_user The login for MQTT broker
mqtt_password The password for MQTT broker
ssid The SSID of the wireless network
psk The Wi-Fi access password

For exapmle:

{
    "topic": "TOPIC",
    "mqtt_host": "HOST",
    "mqtt_user": "USER",
    "mqtt_password": "PASS",
    "ssid": "SSID",
    "psk": "PSK"
}

The microcontroller executes boot.py when it starts. It connects the device to the network using “ssid” and “psk” from config.json. Usually, you should not modify it.

The microcontroller executes main.py when boot.py terminates. It checks a network connection then it tries to connect to the MQTT broker using credentials (“mqtt_host”, “mqtt_user”, “mqtt_password”) from config.json.

If the attempt fails the microcontroller sleeps for a minute, then restarts.

Otherwise, it subscribes on device topic, 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 mqtt.py file contains custom mqtt client class. Usually, you should not modify it.

class MQTTClient(topic, client_id, server, port=0, user=None, password=None, keepalive=0, ssl=False, ssl_params=dict)

MQTT client class.

The arguments are:
  • topic is a MQTT topic that microcontroller will be subscribed.
  • client_id is some unique client_id. We recommend to use nic.config('mac')
  • server is a MQTT server address. main.py file passes mqtt_host here.
  • port is a MQTT server port. Default MQTT port used by EscapeRoomMakers server is 1883.
  • user is a MQTT username. main.py file passes mqtt_user here.
  • password is a MQTT password. main.py file passes mqtt_password here.
  • keepalive is a MQTT keepalive.
  • ssl is MQTT require SSL.
  • ssl_params SSL parameters.
MQTTClient.set_callback(callback)

Set callback that handles parsed package.

The arguments is:
  • callback function that handles parsed package.

Returns None.

MQTTClient.subscribe(topic, qos=0)

Subscribe on topic.

The arguments are:
  • topic is a MQTT topic to subscribe.
  • qos is a MQTT QoS.

Returns None.

MQTTClient.publish(topic, msg, retain=False, qos=0)

Publish message to topic.

The arguments are:
  • topic is a MQTT topic to publish message.
  • msg is message to publish.
  • retain is a MQTT message retain parameter.
  • qos is a MQTT QoS.

Returns None.

MQTTClient.publish_event(call, args=None)

Publish event to EscapeRoomMakers server.

The arguments are:
  • call is an event.
  • args is a dict with event arguments.

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 a MQTT client wrapper.

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