Developing Python Services in microServiceBus.com
Before you read this post you should familiarize yourself with how flows and services in microServiceBus.com works. If you are not familiar with these concepts yet, please visit the Getting started first. If you’re looking at creating JavaScript based services navigate to Developing JavaScript Services in microServiceBus.com
When you as a developer is writing a Python service to use in a flow, you are inheriting the CustomService object. This object has a few methods and properties that could help you develop your code.
Overall architecture
Your service is developed in the microServiceBus.com portal, added to a Flow and assigned a Node name or a Tag. When the Node signs in, it will download all assigned services including your custom services.
Once downloaded, the Orchestrator service will instantiate your service and call the Start method. When the Node is restarted or disabled, the Orchestrator service will call the Stop method. Whatever happens between these two calls is up to you.
The Orchestrator service has a queue, which is passed into the constructor of your service. This queue can be used to pass messages between your service and others. You can also subscribe to messages (events) from other services.
Apart from yours and other custom services, the Python agent also come with some built-in services which you might find useful, such as the Logger service
Create a new Python service
Before we can start writing code, we first need to create our service. Navigate to the Scripts & Services
page and click the CREATE NEW
button.
- Next you have the option of creating a service from scratch, importing from file or copying existing services. Select
CREATE NEW
. - Give your service a name, filename, description and select “Python file” from the Service type list. Notice that the extension of your filename changes to
.py
.Important! Your filename must match the class name of your service. For instance, if you file is “ReadGPIO.py” your class must be named “ReadGPIO”. Since classes are usually named using
PascalCase
, this will also be true for your filename. - If you want to give the user of your service options, such as which GPIO pin to use you can add these dynamic properties in the Static Properties tab. You can later access these properties in your code using the
GetPropertyValue
method. More on this later. - Click
Edit
of the “0.1” version to open the code editor and start coding.
Services are versioned. You can always update the version by selecting “Update minor” or “Update major” in the lower right corner of the code editor.
- Remove the sample code, and paste in the following:
from queue import Queue
from base_service import CustomService
class YOUR_SERVICE_NAME(CustomService):
def __init__(self, id, queue, config):
# Write your code here
super(YOUR_SERVICE_NAME, self).__init__(id, queue, config)
async def Start(self):
try:
await self.Debug("Started")
# Write your code here
except Exception as ex:
await self.Debug(f"Failed to start: {ex}")
async def Stop(self):
try:
# Write your code here
await self.Debug("Stopped")
except Exception as ex:
await self.Debug(f"Failed to stop: {ex}")
- Update the name of your class, and continue coding ;)
Required methods
-
Constructor
This would be a good place to instanciate properties.
-
Start
This method will be called when your node starts and your service has been downloaded. This can be the place to start an interval or set up an event listener. However, it’s important to understand that other services might not be ready yet. For example, if you want to read GPIO events and send them to Azure, the Azure IoT Hub service migh not be ready yet. In such cases, you might be better of to start your GPIO listener in the
StateUpdate
method. More on this later.Tip! Here’s a great place to add all your PIP packages.
-
Stop
This function will be called when you disable or restart your Node. If you for example have a timer event, this would be where to stop it.
Tip! Here it is recommended to stop your timers or clear your processes.
Built in methods on the CustomService object
-
self.get_settings()
Returns all settings received when the Node signed in. This includes name of the Node among many internally used settings.
@parameters
: None@returns
: dictionary@example
self.settings = self.get_settings() # node settings received upon signin self.nodeName = self.settings["nodeName"]
-
self.GetPropertyValue(type, property_name)
Returns all dynamic properties defined in the
Static Properties
tab provided by the user.@parameters
: type (string) either “static” or “security”@returns
: value of dynamic property@example
self.pin = self.GetPropertyValue("static", "gpio_pin")
-
self.SubmitAction(destination, action, message)
SubmitAction is used to send messages between services and puts a message on the queue, managed by the Orchestrator which in turn transmitts the message to the destinated service.
The SubmitAction method requires you to have an understanding of the receiving service, such as which method should receive the message. There are other built-in method which are using the SubmitAction method underneth, but are designed for specific purposes, such as:
- self.Debug
- self.Warning
- self.ThrowError
- self.SubmitMessage
@parameters
:- destination (string) The name of the service to receive the message (lower case name + “_py”). Use wildcard (*) for all services.
- action (string) The name of the method on the destination service
@returns
: None@example
await self.SubmitAction("someService_py", "some_method", {"id": 42}})
-
self.Debug(message)
The Debug method transmits the messsage to the Logger service for Console output
@parameters
: message (string)@returns
: None@example
await self.Debug("Started")
-
self.Warning(message)
Same as
self.Debug
but is shown in yellow@parameters
: message (string)@returns
: None@example
await self.Warning("Started")
-
self.ThrowError(message, fault_code = None, fault_description = None)
Errors are automaticly transmitted to the microServiceBus.com portal where used for alerts. Errors are also shown in the Console, but in red.
@parameters
: message (string), fault_code (string), fault_description (string)@returns
: None@example
await self.ThrowError("Unable to read GPIO", "666", "Some internal error description")
-
self.SubmitMessage(message)
SubmitMessage transmits messages to the Azure IoT Hub Service
@parameters
: message (object)@returns
: None@example
payload = {"id": 42} await self.SubmitMessage(json.dumps(payload))
-
self.AddPipPackage(package, module, name)
Downloads the packages from PIP at run-time and return the type
@parameters
:- package (string) pip package E.g “azure-iot-device”
- module (string) module name E.g “azure.iot.device.aio”
- name (string) name of object E.g “IoTHubDeviceClient”
@returns
: Type@example
MqttClient = self.AddPipPackage("paho-mqtt", "paho.mqtt.client", "Client") # is equivalent to: # pip install paho-mqtt # from paho.mqtt.client import Client
Related content:
- Home
- Common Linux terminal commands
- Get insight using tracking
- Import nodes from CSV files
- Installing microServiceBus-node
- Working with meter configuration
- Migration information
- Node installation scripts
- Work with Node VPN interface and peers
- Reviewing the Audit log
- Roles, privilages and auditing
- Running microServiceBus-node on a yocto image
- Developing JavaScript Services in microServiceBus.com
- Developing Python Services in microServiceBus.com
- Site verification
- Using the Node terminal
- Using the Console
- Default keyboard shortcuts
- Working with service properties
Report bugs, broken links or missing images.. Create Issue