-
Notifications
You must be signed in to change notification settings - Fork 0
3.1 Base packages
(Author: Patrick Pogscheba, date: 12/2023)
The cubes project consists of multiple different components which are developed in different programming languages picked for the right purpose.
Every component deployed on cubes or server needs the right data models to handle and some basic functionality so base packages were introduced for all components so each developer doesnt't has to hassle with implementing all the basic stuff.
The cubes and the server are running background services for handling background processing and data transfer. So a Base package was introduced for the python language which seemed the best way to develop a flexible backend service. Async programming and a flexible wiring of components is used.
Components of the base package:
-
Webserver (Tornado): In the beginning the communication between backend and apps should be done by Websockets (first apps where Unity WebGL apps). The server should run a webserver to to deliver apps and rest API so a webserver was integrated into the base package.
-
Communication:
- MQTTDispatcher (TODO: link to REPO): a flexible MQTT dispatcher with annotation support to provide MQTT support for client and server
- ZMQ: for communication between backends and apps ZMQ is used and included in the main package. Right now it is only used by the client (cubes) but it could replace the MQTT communication some time.
-
ReactiveX: to better decouple components the reactive programming paradigma is used which provides an observer-listener pattern and more
-
Dependency Injection (Kink): for decoupling and better management of component injection the simple DI framework Kink is used.
- provides central constants by DI, e.g. communication host and port or topics
-
Data Validation and Serialization (Pydantic): for setting up the base models used in communication and inner processing pydantic is used which validates the date also does JSON serialzation.
-
App baseclass: the base class for building backend services which incorporates a web app and the MQTT dispatcher.
(TODO: Should be refactored and optimized)
The first simple app frontends and the management frontend were developed in Vue.js. Later on the apps were developed by another team with more experience in react so there are two implementations for base packges for web development. You have to choose the proper implementation which are slighty differing from each other.
Author: Daniel Glomberg/Patrick Pogscheba, date: 02/2024
The React Base Package provides useful components and state management that can be used in a web based gamemaster app.
To handle state in the base package, we use the npm library zustand. We provide two stores to handle mqtt connection and the cube state of all connected cubes.
-
Connector Component: For easy access to the cube state, we provide a component called Connector.The Connector component is the entry point for the puzzlecube-core library. It connects to the MQTT broker and handles the communication for the cube state. It also provides default functions to send and receive messages. The Connector connects to the default broker at 192.168.111.1 on the production server in the puzzlecube network. It can be configured to connect to a different broker by passing the brokerUrl as a prop.
-
MqttStore: The MqttStore stores the client (if connected) and provides the connection status and error informationen.
-
CubeStateStore: The CubeStateStore subscribes to the cubes state topic and stores all information in an array.
Every connected cube send in an 1-second interval his state, which will be added by the first time or updated if the entry all ready exists.
-
NeighbourhoodStore: This store handles the connection of two cube sides which is published on connectionTopic by the cubes backends. A reactive subject (https://rxjs.dev/) can be used to process or validate the connections in a dedicated gamemaster app. Initally connections are just informations on cube connections which should be validated by an app (e.g. a puzzle tile connection is only valid when the right sides of two cubes are connected). This should be checked individually in the gamemaster apps and the publish as valid connections witjh the method publishValidConnection.
For app development a unity base package was developed which analog to the Python package delivers the base functionality to communicate over MQTT and getting Control Events ( moving state, rotational and translational steps and impulses described earlier ) from ZMQ. The main components are using events to deliver there data to the receiver. The wiring of the events is done via Unity Editor.
The central components are:
- EventDispatcher: Handles incoming data from ZMQ and MQTT, transforms JSON to data models (using Newtonsoft JSON library) and offers events for each data type for app specific processing. Also does topic handling and subscription to MQTT. The function Initialize should be overriden and used for app specific subscriptions. Subscriptions are managed by a Dictionary of MqttTopicFilter and MqttActions.Message to deliver incoming filtered topics to the right messagehandler. Just add your Topicfilter along with the target handler and the subscription is done automatically. Th e EventDispatcher should be used as your central data hub so no other components have to hassle about where the data should go. Just use it as a facade for ZMQ or MQTT communication.
- AppController: Each app should manage it's app state with some information eventually useful for the server. The Appstate is sent out on app start to indicate the app is running which can be used by apps to include this cube. Update your app state and it is sent out by MQTT. If you include data with high framerates try to not sent it out at high frame rates so the MQTT channel is not loaded too much. Decide by yourself but keep an eye on data with a high amount of paralell sending tubes. The controller can handle a splash screen on App start and offers a virtual Initialize function which is called at the end of the Awake function. To have an easy access the controller is setup as a Singleton object which can be accessed by all components directly.
- MqttManager: The communication over MQTT (based on MQTTnet) is handled by this controller which should not be altered as subscriptions are managed in EventDispatcher. If bigger changes are needed be careful to not disrupt the other functionality. The Manager offers two Send-functions to send out data into the MQTT network. To keep things clean the EventDispatcher should offer dedicated Publish-functions which uses the Send-functions.
- ZMQManager: Just like the MQTT controller the ZMQController onyl handles communication by ZMQ and offers events which should be consumed by the EventDispatcher.
(TODO: Some Eventdispatcher functionality, e.g. Subscription management, should eventually be refactored to AppController which was introduced later)
For debugging purposes and control testing there is a keyboard controller and a debug UI. A prefab is included wit the basic setup and wiring of events. For your own app all the modules should be derived in app-specific versions and app specific functionality, e.g. extend the app state, add new models and mqtt topics for app-specific commuication between your network components (server or other cubes), extend your keyboard control to new keys for testing your logic without other mqtt participants. The debug UIs can be controller by MQTT messages.