To avoid blocking the thread, avoid using the print(...)
function. Instead use the built-in printf
function inherited from base_service:
self.printf("Hello world")
You can also use self.Debug
if you want the logging transmitted to msb.com.
All services inherit from BaseService either directly or through CustomService. Inheriting from BaseService provides a number of functions such as self.Debug(text)
and self.SubmitMessage(message)
. Such methods are predefined to target specific destinations and functions. A service can also call self.SubmitAction(destination, action, message)
when more flexibility is needed.
For instance, if you had a custom service called emailhandler
which would send emails through the Process function you could use the following code:
message = {'to':'[email protected]', 'subject':'Hello', 'body':'...from foo'}
await self.SubmitAction("emailhandler", "Process", message)
Note that the action is set to "Process". All services inheriting from BaseService has a
Start
.Stop
andProccess
function. However, you could have created aSendEmail
function and set the action to "SendEmail".
If, on the other hand, you'd like to send a message to the IoT Hub you would set the destination to "com". However, there is already a simplified function called SubmitMessage predefined with both destination and action:
message = {'ts':'2021-01-01 01:01:01', 'temperature':22}
await self.SubmitMessage(message)
Similarly there is a predefined function to logging:
await self.Debug("Hello from Python")
Internal services are used as any other service but are never stopped.
The Orchestrator is responsible for starting up services and correlate messages between then. All messages on the queue are of type QueueMessage (baseservice) and contains information such as the destination
and action
. When the Orchestrator receives a message on the queue, it will resolve the destination and call the function (_action).
As the name implies the microServiceBusHandler is responsible for all communication with microServiceBus.com. When staring up the service will sign in to msb.com and set up channels for different commands in msb. After successful sign-in, the service will call the Orchestrator to start up the these services.
The Logger service outputs data to the terminal and forward debugging info to microServiceBusHandler if enabled
All custom services inherit from BaseService
and must expose the following functions:
The Start function will be called when the when custom service is started. This is the where the services should start any kind of interval or work to produce readings.
Readings can be submitted using the self.SubmitMessage(message)
function which forwards the message to the Process function of the Com service.
The Stop function is called as the service is getting stopped and can be used for any cleanup.
The Process method can optionally be used for transmitting messages between services using the self.SubmitAction(destination, action, message)
E.g
await self.SubmitAction('MyOtherService', 'Process', message)
State updates received by the Com service are forwarded to all services and accessible through the StateUpdate function
To get started with Docker on Windows, follow the Install Docker Desktop on Windows guideline.
There is a Dockerfile
in the root directory which can be used to build a docker image (from the root of the repo):
docker build -t msb-py .
You can start the image using:
docker run -v ${PWD}:/app -it python bash
This start an instance of the Python agent which you can claim in the portal.
There is also a Docker Compose file you can use to start up multiple instances at once. This creates 5 instances, all mapping /root/msb-py
to [REPO Root]/docker/[container]
. So before you start, create a docker
folder in the repo root with 5 folders inside (p1, p2, p3, p4, p5).
Once you've set up the folder structure, you can start it using:
docker compose up -d
or stop it using
docker compose down
You'll still have to claim the nodes when they come online, but only the first time.