The Instrument Driver is responsible to handle the communication to the devices that are attached to the OneIoT Gateway. There are two possible communication modes.
Command Mode
Stream Mode
Command Mode
In command mode the OneIoT Gateway serves as a master device. It sends commands to the slave devices attached to the gateway, handles their responses and communicates with the OneIoT Cloud. The basic skeleton for a command basedInstrument Driver looks like the following (Modbus example).
import structimport uasyncio as asyncioimport loggingfrom serial_communication import Serialfrom queue import MESSAGE_BUS, Event, EVENT_TO_CLOUD_FOR_MQTT, EVENT_ERRORimport message_utilfrom libs.modbus_facade import ModbusFacadeclassCustomHandler:def__init__(self,serial:Serial):# Every 30sec self.fire_every =30 self.modbus =ModbusFacade(serial)asyncdefloop(self):# Read every x secondswhileTrue:await asyncio.sleep_ms(self.fire_every*1000)# SEND COMMANDS OR READ VALUES HERE# PROCESS RESPONSES FROM DEVICE# EXAMPLE: answer_double =await self.modbus.read_holding_registers(0x10, 0x01, 0x02, double_valued=True)[0]await self.send_double(1, answer_double)asyncdefhandle_incoming(self,message):# Messages from the cloud are send to the driver and can be handled hereif message_util.get_state_content_for_payload(message)isnotNone: item_number, state_str = message_util.get_state_content_for_payload(message) item_number =int(item_number)# DO SOMETHING WITH THE ITEM AND STATE, FOR EXAMPLE, SEND COMMAND TO DEVICES# EXAMPLE: state =int(state_str)ifnotawait self.modbus.write_single_coil(0x10, 0x01, state): logging.log("Writing register failed.")else: logging.log(str("Cannot handle message %s."%str(message)))asyncdefsend_double(self,item,value): value =str(value)await self.send_message(item, value, "DOUBLE")asyncdefsend_message(self,item,value_string,type="DOUBLE"): message =Noneif value_string: message ="S:"+str(item)+":20:"+type+":"+ value_stringelse: message ="S:"+str(item)+":50" logging.log("No answer received for command...")await self.finalize_serial_to_cloud(message)# YOU CAN ALSO SEND SOME LOGS TO THE CLOUD HERE''' This finalizes a serial message given the OneIoT protocol. Timestamp is added and message is checked. Then it is sent to the cloud. '''asyncdeffinalize_serial_to_cloud(self,message): message = message_util.add_timestamp(message) correct = message_util.check_serial_message(message)ifnot correct:await MESSAGE_BUS.send(Event(EVENT_ERROR, "Incorrect handled serial: "+ message))else:# just forward to devicecloud via MQTTawait MESSAGE_BUS.send(Event(EVENT_TO_CLOUD_FOR_MQTT, [message]))
Stream Mode
In Stream Mode, the device proactively sends messages to the OneIoT Gateway. For this, the OneIoT Communication Protocol can be used and no further driver is used. If your device sends serial messages in other formats, a driver needs to be used.
classCustomHandler:def__init__(self):asyncdefhandle_message(self,message):# PARSE MESSAGE; EXAMPLE: item, value =parse_message(message)# SEND TO CLOUD; EXAMPLE:awaitsend_double(item, value)defparse_message(message):# Semikolon separated data (example only) data = message.split(';') item =int(data[0]) value = data[1]return item, valueasyncdefsend_double(self,item,value):await self.send_message(item, value, "DOUBLE")asyncdefsend_message(self,item,value_string,type="DOUBLE"): message =Noneif value_string: message ="S:"+str(item)+":20:"+type+":"+ value_stringelse: message ="S:"+str(item)+":50" logging.log("No answer received for command...")await self.finalize_serial_to_cloud(message)# YOU CAN ALSO SEND SOME LOGS TO THE CLOUD HERE''' This finalizes a serial message given the OneIoT protocol. Timestamp is added and message is checked. Then it is sent to the cloud. '''asyncdeffinalize_serial_to_cloud(self,message): message = message_util.add_timestamp(message) correct = message_util.check_serial_message(message)ifnot correct:await MESSAGE_BUS.send(Event(EVENT_ERROR, "Incorrect handled serial: "+ message))else:# just forward to devicecloud via MQTTawait MESSAGE_BUS.send(Event(EVENT_TO_CLOUD_FOR_MQTT, [message]))