def handle_modbus_request(mqtt_client, userdata, message): """Process the modbus request""" logging.debug("In handle_modbus_request") logging.debug("Payload = %s", message.payload) #{ # 'ModbusHost': modbus.com:5023 # 'FunctionCode': 5, # 'UnitID': 2, # 'StartAddress': 2, # 'AddressCount': 2, # 'Data': [2, 3, 4] # } logging.debug("message payload = %s", message.payload) payload = json.loads(message.payload.replace("'", '"')) if validate_modbus_request(mqtt_client, payload): modbus_port = payload.get('ModbusPort') if modbus_port is None or modbus_port == "": logging.info("Modbus port not specified. Defaulting port to %s", Defaults.Port) modbus_port = Defaults.Port if payload['FunctionCode'] == ModbusFunctionCodes.ReadCoil or \ payload['FunctionCode'] == ModbusFunctionCodes.ReadDiscreteInput or \ payload['FunctionCode'] == ModbusFunctionCodes.ReadHoldingRegisters or \ payload['FunctionCode'] == ModbusFunctionCodes.ReadInputRegisters or \ payload['FunctionCode'] == ModbusFunctionCodes.WriteSingleCoil or \ payload['FunctionCode'] == ModbusFunctionCodes.WriteSingleHoldingRegister or \ payload['FunctionCode'] == ModbusFunctionCodes.WriteMultipleCoils or \ payload['FunctionCode'] == ModbusFunctionCodes.WriteMultipleHoldingRegisters: #Create a Modbus client and send the modbus request client = ModbusClient(payload['ModbusHost'], modbus_port) client.connect() #Send the modbus request response = send_modbus_request(client, payload) logging.debug("response = %s", response) # close the client client.close() if response is not None and response.get('error') is None: # Publish the modbus response logging.debug("respData = %s", response) mqtt.publish_modbus_response(mqtt_client, CB_CONFIG['adapterTopicRoot'], \ create_modbus_response(payload, response)) else: mqtt.publish_modbus_error(mqtt_client, CB_CONFIG['adapterTopicRoot'], \ create_modbus_error(payload, response.get('error'))) else: mqtt.publish_modbus_error(mqtt_client, CB_CONFIG['adapterTopicRoot'], \ create_modbus_error(payload, \ "Invalid Modbus function code specified. Unable to process Modbus command.")) logging.debug("Exit handle_modbus_request")
def validate_modbus_request(mqtt_client, payload): """Validate the modbus request. Publish any errors if the request is not valid.""" #{ # 'ModbusHost': 'localhost', # 'ModbusPort': 5023, # 'FunctionCode': 5, # 'UnitID': 2, # 'StartAddress': 2, # 'AddressCount': 2, # 'Data': [2, 3, 4] # } logging.debug("In validate_modbus_request") #Validate the ModbusHost value modbus_host = payload.get('ModbusHost') if modbus_host is None or modbus_host == "": logging.debug("Invalid ModbusHost") mqtt.publish_modbus_error(mqtt_client, CB_CONFIG['adapterTopicRoot'], create_modbus_error(\ payload, "Modbus host not specified. Unable to process Modbus command.")) return False #Validate the FunctionCode value func_code = payload.get('FunctionCode') if func_code is None or func_code == "": logging.debug("Invalid Modbus FunctionCode") mqtt.publish_modbus_error(mqtt_client, CB_CONFIG['adapterTopicRoot'], create_modbus_error(\ payload, "Modbus function code not specified. Unable to process Modbus command.")) return False #Validate the UnitID value unit_id = payload.get('UnitID') if unit_id is None or unit_id == "": logging.debug("Invalid Modbus UnitID") mqtt.publish_modbus_error(mqtt_client, CB_CONFIG['adapterTopicRoot'], create_modbus_error(\ payload, "Modbus Unit ID not specified. Unable to process Modbus command.")) return False #Validate the StartAddress value start_addr = payload.get('StartAddress') if start_addr is None or start_addr == "": logging.debug("Invalid Modbus StartAddress") mqtt.publish_modbus_error(mqtt_client, CB_CONFIG['adapterTopicRoot'], create_modbus_error(\ payload, "Modbus StartAddress not specified. Unable to process Modbus command.")) return False #Check if a data parameter was specified for write operations if payload['FunctionCode'] == ModbusFunctionCodes.WriteSingleCoil or \ payload['FunctionCode'] == ModbusFunctionCodes.WriteSingleHoldingRegister or \ payload['FunctionCode'] == ModbusFunctionCodes.WriteMultipleCoils or \ payload['FunctionCode'] == ModbusFunctionCodes.WriteMultipleHoldingRegisters: data = payload.get('Data') if data is None or data == "" or len(data) == 0: logging.debug("Invalid Modbus Data") mqtt.publish_modbus_error(mqtt_client, CB_CONFIG['adapterTopicRoot'], \ create_modbus_error(\ payload, "Modbus Data not specified. Unable to process Modbus command.")) return False else: # Validate the address count length for the write operations # The count length must be specified if the data array length is greater than 1 addr_count = payload.get('AddressCount') if (len(data) > 0 and addr_count != len(data)) or addr_count is None or \ addr_count == "": logging.debug("Invalid Modbus AddressCount") mqtt.publish_modbus_error(mqtt_client, CB_CONFIG['adapterTopicRoot'], \ create_modbus_error(\ payload, "Modbus address count not specified or invalid. \ Unable to process Modbus command." )) return False logging.debug("Exit validate_modbus_request, returning True") return True