def SBusClientFieldResponse(cmdcode, telegramattr, msgsequence, msgdata): """Construct the report for a SBus field message response. cmdcode (integer) = Command code. telegramattr (integer) = Telegram attribute. msgsequence (integer) = Message sequence. msgdata (string) = The response data as a binary string. """ try: if cmdcode in [2, 3, 5, 11, 13]: reportreqdata = _BoolList2Str(ModbusDataLib.bin2boollist(msgdata)) elif cmdcode in [6, 14]: reportreqdata = binascii.hexlify(msgdata) else: reportreqdata = 'No data.' # This splits the string up into groups separated by # spaces to allow line breaks on the report web page. reportstr = BreakString(reportreqdata) return _sbsclientrespreportstr % (telegramattr, msgsequence, reportstr) # If there was an error, we just ignore it and log some default data. except: return _sbsclientrespreportstr % (0, 0, 0, 'Response data error.')
def SetOutputsBool(self, addr, data): """Write outputs to the host (command 13). addr (integer) = SBus outputs address. data (string) = Packed binary string with the data to write. """ bindata = ModbusDataLib.boollist2bin([data]) self._SBusRequest(13, addr, 1, bindata)
def ModbusClientFieldRequest(transid, uid, functioncode, start, qty, msgdata): """Construct the report for a Modbus/TCP field message request. transid (integer) = The transaction id. uid (integer) = The unit id. functioncode (integer) = The function code. start (integer) = The starting data table address. qty (integer) = The number of items requested. msgdata (string) = The raw binary string containing the message data. """ try: if functioncode in [1, 2, 3, 4]: reportreqdata = '' elif functioncode in [5, 6, 16]: reportreqdata = binascii.hexlify(msgdata) elif (functioncode == 15): reportreqdata = _BoolList2Str(ModbusDataLib.bin2boollist(msgdata)) else: reportreqdata = 'No data.' # This splits the string up into groups separated by # spaces to allow line breaks on the report web page. reportstr = BreakString(reportreqdata) return _reqreportstr % (transid, uid, functioncode, start, qty, reportstr) # If there was an error, we just ignore it and log some default data. except: return _reqreportstr % (0, 0, 0, 0, 0, 'Request data error.')
def SBusClientFieldRequest(msgsequence, stnaddr, cmdcode, dataaddr, datacount, msgdata): """Construct the report for a SBus field message request. msgsequence (integer) = Message sequence. stnaddr (integer) = Station address. cmdcode (integer) = Command code. dataaddr (integer) = Starting data table address. datacount (integer) = Number of data elements. msgdata (string) = The raw binary string containing the message data. """ try: if cmdcode in [2, 3, 5, 6]: reportreqdata = '' elif cmdcode in [11, 13]: reportreqdata = _BoolList2Str(ModbusDataLib.bin2boollist(msgdata)) elif cmdcode == 14: reportreqdata = binascii.hexlify(msgdata) else: reportreqdata = 'No data.' # This splits the string up into groups separated by # spaces to allow line breaks on the report web page. reportstr = BreakString(reportreqdata) return _sbsclientreqreportstr % (msgsequence, stnaddr, cmdcode, dataaddr, datacount, reportstr) # If there was an error, we just ignore it and log some default data. except: return _sbsclientreqreportstr % (0, 0, 0, 0, 0, 'Request data error.')
def ModbusClientFieldResponse(transid, functioncode, msgdata): """Construct the report for a Modbus/TCP field message request. transid (integer) = The transaction id. functioncode (integer) = The function code. msgdata (string) = The response data as a binary string. """ try: if functioncode in [1, 2]: reportrespdata = _BoolList2Str(ModbusDataLib.bin2boollist(msgdata)) elif functioncode in [3, 4, 5, 6, 15, 16]: reportrespdata = binascii.hexlify(msgdata) elif functioncode > 127: reportrespdata = binascii.hexlify(msgdata) else: reportrespdata = 'No data.' # This splits the string up into groups separated by # spaces to allow line breaks on the report web page. reportstr = BreakString(reportrespdata) return _respreportstr % (transid, functioncode, reportstr) # If there was an error, we just ignore it and log some default data. except: return _respreportstr % (0, 0, 'Response data error.')
def GetInputRegistersIntList(self, addr, qty): """Read input registers from the host (function 4). addr (integer) = Modbus discrete inputs address. qty (integer) = Number of registers. """ return ModbusDataLib.signedbin2intlist( self._ModbusRequest(4, addr, qty, None))
def SetHoldingRegistersIntList(self, addr, qty, data): """Write holding registers from the host (function 16). addr (integer) = Modbus discrete inputs address. qty (integer) = Number of registers. data (string) = Packed binary string with the data to write. """ bindata = ModbusDataLib.signedintlist2bin(data) self._ModbusRequest(16, addr, qty, bindata)
def WriteServerData(func, adr, qty, data): if (func == 15): msgdata = ModbusDataLib.boollist2bin(data) elif (func == 16): msgdata = ModbusDataLib.signedintlist2bin(data) else: print('Demosim - Bad function code %s when writing data.' % func) return try: # Send the request. client.SendRequest(1, 1, func, adr, qty, msgdata) # Get the reply. TransID, rfunct, Address, Qty, MsgData, Excode = client.ReceiveResponse() except: print('Demosim - lost contact with server - exiting') sys.exit()
def NextRequest(self): """Increment the command list and execute the next command. This includes constructing the next message. """ # Transaction ID is incremented for each request to check message integrity. # It must not exceed the maximum for an 16 bit unsigned int though. self._TransID += 1 if (self._TransID > 65535): self._TransID = 1 # Get the parameters for this command. self._CmdName, self._FunctionCode, self._AddrRequested, self._QuantityRequested, \ self._MemAddr, self._UnitID, EndofList = self._ConnectionInfo.NextCommand() # Get message data appropriate for the function being executed. if self._FunctionCode in (1, 2, 3, 4): MsgData = '' # No message data is sent for a read. elif (self._FunctionCode == 5): CoilData = MBDataTable.MemMap.GetCoilsBool(self._MemAddr) if CoilData: MsgData = ModbusDataLib.coilvalue( 1) # Special format for function 5 else: MsgData = ModbusDataLib.coilvalue( 0) # Special format for function 5 elif self._FunctionCode in (6, 16): MsgData = MBDataTable.MemMap.GetHoldingRegisters( self._MemAddr, self._QuantityRequested) elif (self._FunctionCode == 15): MsgData = MBDataTable.MemMap.GetCoils(self._MemAddr, self._QuantityRequested) else: return '', True # Invalid function code. # Create and return message. try: Message = self._MBClientMsg.MBRequest(self._TransID, self._UnitID, self._FunctionCode, self._AddrRequested, self._QuantityRequested, MsgData) except: Message = '' return Message, EndofList
def SetHoldingRegistersInt(self, addr, data): #Function changed to 6 """Write holding registers from the host (function 16). addr (integer) = Modbus discrete inputs address. data (string) = Packed binary string with the data to write. """ # bindata = ModbusDataLib.signedintlist2bin([data]) bindata = ModbusDataLib.SignedInt2BinStr(data) # self._ModbusRequest(16, addr, 1, bindata) self._ModbusRequest(6, addr, 1, bindata)
def NextRequest(self): """Increment the command list and execute the next command. This includes constructing the next message. """ # Transaction ID is incremented for each request to check message integrity. # It must not exceed the maximum for an 16 bit unsigned int though. self._TransID += 1 if (self._TransID > 65535): self._TransID = 1 # Get the parameters for this command. self._CmdName, self._FunctionCode, self._AddrRequested, self._QuantityRequested, \ self._MemAddr, self._UnitID, EndofList = self._ConnectionInfo.NextCommand() # Get message data appropriate for the function being executed. if self._FunctionCode in (1, 2, 3, 4): MsgData = '' # No message data is sent for a read. elif (self._FunctionCode == 5): CoilData = MBDataTable.MemMap.GetCoilsBool(self._MemAddr) if CoilData: MsgData = ModbusDataLib.coilvalue(1) # Special format for function 5 else: MsgData = ModbusDataLib.coilvalue(0) # Special format for function 5 elif self._FunctionCode in (6, 16): MsgData = MBDataTable.MemMap.GetHoldingRegisters(self._MemAddr, self._QuantityRequested) elif (self._FunctionCode == 15): MsgData = MBDataTable.MemMap.GetCoils(self._MemAddr, self._QuantityRequested) else: return '', True # Invalid function code. # Create and return message. try: Message = self._MBClientMsg.MBRequest(self._TransID, self._UnitID, self._FunctionCode, self._AddrRequested, self._QuantityRequested, MsgData) except: Message = '' return Message, EndofList
def SetCoilsBool(self, addr, data): """Write coils to the host (function 15). #######Changed to 5 addr (integer) = Modbus discrete inputs address. data (string) = Packed binary string with the data to write. """ ## print "data", data # bindata = ModbusDataLib.boollist2bin([data]) bindata = ModbusDataLib.coilvalue(data) ## print bindata # self._ModbusRequest(15, addr, 1, bindata) ## print "Size", len(bindata) self._ModbusRequest(5, addr, 1, bindata)
def GetServerData(func, adr, qty): try: # Send the request. client.SendRequest(1, 1, func, adr, qty) # Get the reply. TransID, rfunct, Address, Qty, MsgData, Excode = client.ReceiveResponse() except: print('Demosim - lost contact with server - exiting') sys.exit() # Decode the data. if (rfunct in [1, 2]): values = ModbusDataLib.bin2boollist(MsgData) elif (rfunct in [3, 4]): values = ModbusDataLib.signedbin2intlist(MsgData) else: print('Demosim - Bad function code %s when reading data.' % rfunct) # Provide a default based on the sending function. if (func in [1, 2]): values = [False] * 8 elif (funct in [3, 4]): values = [0] * 8 return values
def WriteServerData(cmd, adr, qty, data): if (cmd == 11): msgdata = ModbusDataLib.boollist2bin(data) elif (cmd == 14): msgdata = SBusMsg.signedint32list2bin(data) else: print('Bad command code %s when writing data.' % cmd) return MsgSeqCounter.incseq() # Send the request. client.SendRequest(MsgSeqCounter.getseq(), 1, cmd, qty, adr, msgdata) # Get the reply. TeleAttr, MsgSeq, MsgData = client.ReceiveResponse()
def GetServerData(cmd, adr, qty): MsgSeqCounter.incseq() # Send the request. client.SendRequest(MsgSeqCounter.getseq(), 1, cmd, qty, adr) # Get the reply. TeleAttr, MsgSeq, MsgData = client.ReceiveResponse() # Decode the data. if (cmd in (2, 3, 5)): try: values = ModbusDataLib.bin2boollist(MsgData) except: return [] elif (cmd == 6): try: values = SBusMsg.signedbin2int32list(MsgData) except: return [] else: print('Bad command code %s when reading data.' % cmd) return [] return values
def GetFlagsBool(self, addr): """Read flags from the host (command 2). addr (integer) = SBus flags address. """ return ModbusDataLib.bin2boollist(self._SBusRequest(2, addr, 1, None))[0]
def handle_read(self): try: ReceivedData = self.recv(8192) except: ReceivedData = None if ReceivedData: # Decode message. 'RequestData' may mean either number of coils or sent data, depending # upon the function code being received. For functions 15 and 16, it is a tuple containing # data and quantity. try: TransID, UnitID, FunctionCode, Start, Qty, RequestData, ExceptionCode = \ MBServerMSg.MBRequest(ReceivedData) # We can't decode this message at all, so just drop the request and stop here. # Can't decode the message, because the length is invalid. except ModbusTCPLib.MessageLengthError: print('Server %d - Invalid message length. %s' % (CmdOpts.GetFieldPort(), time.ctime())) TransID, UnitID, FunctionCode, Start, Qty, RequestData, ExceptionCode = self._GetDefaultData( ) except: TransID, UnitID, FunctionCode, Start, Qty, RequestData, ExceptionCode = self._GetDefaultData( ) # Log the incoming messages for reporting purposes. StatusReporter.Report.AddFieldRequest(ModbusStatusReportMsg.ModbusServerFieldRequest(TransID, \ UnitID, FunctionCode, Start, Qty, RequestData)) ReplyData = '' MsgData = [0] # Decode messages. If we get an error in reading/writing memory or in constructing messages, # we will consider this to be a Modbus exception. try: if FunctionCode == 1: # Read coils. MsgData = MemMap.GetCoils(Start, Qty) ReplyData = MBServerMSg.MBResponse(TransID, UnitID, FunctionCode, Start, MsgData) elif FunctionCode == 2: # Read discrete inputs. MsgData = MemMap.GetDiscreteInputs(Start, Qty) ReplyData = MBServerMSg.MBResponse(TransID, UnitID, FunctionCode, Start, MsgData) elif FunctionCode == 3: # Read holding registers. MsgData = MemMap.GetHoldingRegisters(Start, Qty) ReplyData = MBServerMSg.MBResponse(TransID, UnitID, FunctionCode, Start, MsgData) elif FunctionCode == 4: # Read input registers. MsgData = MemMap.GetInputRegisters(Start, Qty) ReplyData = MBServerMSg.MBResponse(TransID, UnitID, FunctionCode, Start, MsgData) elif FunctionCode == 5: # Write single coil. RequestData contains data. MemMap.SetCoils(Start, 1, RequestData) ReplyData = MBServerMSg.MBResponse(TransID, UnitID, FunctionCode, Start, RequestData) elif FunctionCode == 6: # Write single holding register. RequestData contains data. MemMap.SetHoldingRegisters(Start, 1, RequestData) ReplyData = MBServerMSg.MBResponse(TransID, UnitID, FunctionCode, Start, RequestData) elif FunctionCode == 15: # Write multiple coils. MemMap.SetCoils(Start, Qty, RequestData) ReplyData = MBServerMSg.MBResponse(TransID, UnitID, FunctionCode, \ Start, ModbusDataLib.Int2BinStr(Qty)) elif FunctionCode == 16: # Write multiple holding registers. MemMap.SetHoldingRegisters(Start, Qty, RequestData) ReplyData = MBServerMSg.MBResponse(TransID, UnitID, FunctionCode, \ Start, ModbusDataLib.Int2BinStr(Qty)) elif FunctionCode > 127: # Modbus exception. ReplyData = MBServerMSg.MBErrorResponse( TransID, UnitID, FunctionCode, ExceptionCode) else: print('Server %d - Unsupported function call' % CmdOpts.GetFieldPort()) ReplyData = MBServerMSg.MBErrorResponse( TransID, UnitID, FunctionCode + 128, 1) except: # Modbus exception 4. An error has occured in reading or writing a memory location. ReplyData = MBServerMSg.MBErrorResponse( TransID, UnitID, FunctionCode + 128, 4) # Send the reply. try: self.send(ReplyData) except: # If we have an error here, there's not much we can do about it. print('Server %d - Could not reply to request.' % CmdOpts.GetFieldPort()) # Log the response messages for reporting purposes. StatusReporter.Report.AddFieldResponse(ModbusStatusReportMsg.ModbusServerFieldResponse(TransID, \ FunctionCode, MsgData, RequestData, Qty, ExceptionCode)) else: self.close()
def GetInputRegistersIntList(self, addr, qty): """Read input registers from the host (function 4). addr (integer) = Modbus discrete inputs address. qty (integer) = Number of registers. """ return ModbusDataLib.signedbin2intlist(self._ModbusRequest(4, addr, qty, None))
def GetHoldingRegistersInt(self, addr): """Read holding registers from the host (function 3). addr (integer) = Modbus discrete inputs address. """ return ModbusDataLib.signedbin2intlist(self._ModbusRequest(3, addr, 1, None))[0]
def GetDiscreteInputsBool(self, addr): """Read discrete inputs from the host (function 2). addr (integer) = Modbus discrete inputs address. """ return ModbusDataLib.bin2boollist(self._ModbusRequest(2, addr, 1, None))[0]
def GetCoilsBool(self, addr): """Read coils from the host (function 1). addr (integer) = Modbus coil address. """ return ModbusDataLib.bin2boollist(self._ModbusRequest(1, addr, 1, None))[0]
def GetHoldingRegistersInt(self, addr): """Read holding registers from the host (function 3). addr (integer) = Modbus discrete inputs address. """ return ModbusDataLib.signedbin2intlist( self._ModbusRequest(3, addr, 1, None))[0]
def GetOutputsBool(self, addr): """Read outputs from the host (command 5). addr (integer) = SBus outputs address. """ return ModbusDataLib.bin2boollist(self._SBusRequest(5, addr, 1, None))[0]
def HandleRequest(self, ReceivedData): """ Convert a Modbus server request message into a Modbus server reply message. ReceivedData - Binary string with raw request message. Returns - Binary string with completed raw reply message. If a server error occurs, an empty string will be returned instead. This method handles Modbus protocol functions 1, 2, 3, 4, 5, 6, 15, and 16. """ # Decode message. 'RequestData' may mean either number of coils or sent data, depending # upon the function code being received. For functions 15 and 16, it is a tuple containing # data and quantity. try: TransID, UnitID, FunctionCode, Start, Qty, RequestData, ExceptionCode = \ self._MBServerMsg.MBRequest(ReceivedData) except: # Something is wrong with the message, and we can't decode it. TransID = 0 UnitID = 0 FunctionCode = 0 Start = 0 Qty = 0 RequestData = 0 ExceptionCode = 0 try: # Read coils. RequestData = quantity. if FunctionCode == 1: MsgData = MBDataTable.MemMap.GetCoils(Start, Qty) ReplyData = self._MBServerMsg.MBResponse(TransID, UnitID, FunctionCode, Start, MsgData) # Read discrete inputs. RequestData = quantity. elif FunctionCode == 2: MsgData = MBDataTable.MemMap.GetDiscreteInputs(Start, Qty) ReplyData = self._MBServerMsg.MBResponse(TransID, UnitID, FunctionCode, Start, MsgData) # Read holding registers. RequestData = quantity. elif FunctionCode == 3: # Get the expanded address. if self._ExpAddressing: try: dtstart = self._DTOffsets[UnitID] + Start except: raise ExpDTError, self._ExpDTError else: dtstart = Start MsgData = MBDataTable.MemMap.GetHoldingRegisters(dtstart, Qty) ReplyData = self._MBServerMsg.MBResponse(TransID, UnitID, FunctionCode, Start, MsgData) # Read input registers. RequestData = quantity. elif FunctionCode == 4: MsgData = MBDataTable.MemMap.GetInputRegisters(Start, Qty) ReplyData = self._MBServerMsg.MBResponse(TransID, UnitID, FunctionCode, Start, MsgData) # Write single coil. RequestData contains data. elif FunctionCode == 5: MBDataTable.MemMap.SetCoils(Start, 1, RequestData) ReplyData = self._MBServerMsg.MBResponse(TransID, UnitID, FunctionCode, Start, RequestData) # Write single holding register. RequestData contains data. elif FunctionCode == 6: # Get the expanded register maps. if self._ExpAddressing: try: dtstart = self._DTOffsets[UnitID] + Start except: raise ExpDTError, self._ExpDTError else: dtstart = Start MBDataTable.MemMap.SetHoldingRegisters(dtstart, 1, RequestData) ReplyData = self._MBServerMsg.MBResponse(TransID, UnitID, FunctionCode, Start, RequestData) # Write multiple coils. RequestData is a tuple. elif FunctionCode == 15: MBDataTable.MemMap.SetCoils(Start, Qty, RequestData) ReplyData = self._MBServerMsg.MBResponse(TransID, UnitID, FunctionCode, \ Start, ModbusDataLib.Int2BinStr(Qty)) # Write multiple holding registers. RequestData is a tuple. elif FunctionCode == 16: # Get the expanded register maps. if self._ExpAddressing: try: dtstart = self._DTOffsets[UnitID] + Start except: raise ExpDTError, self._ExpDTError else: dtstart = Start MBDataTable.MemMap.SetHoldingRegisters(dtstart, Qty, RequestData) ReplyData = self._MBServerMsg.MBResponse(TransID, UnitID, FunctionCode, \ Start, ModbusDataLib.Int2BinStr(Qty)) # Modbus exception. elif FunctionCode > 127: ReplyData = self._MBServerMsg.MBErrorResponse(TransID, UnitID, FunctionCode, ExceptionCode) # Something is wrong here and we don't understand the message. else: ReplyData = self._MBServerMsg.MBErrorResponse(TransID, UnitID, FunctionCode + 128, 1) # Extended addressing errors. except ExpDTError: # Modbus exception 2. The extended UID is not known. ReplyData = self._MBServerMsg.MBErrorResponse(TransID, UnitID, FunctionCode + 128, 2) except: # Modbus exception 4. An error has occured in reading or writing a memory location. ReplyData = self._MBServerMsg.MBErrorResponse(TransID, UnitID, FunctionCode + 128, 4) # Return the result. return ReplyData
def GetDiscreteInputsBool(self, addr): """Read discrete inputs from the host (function 2). addr (integer) = Modbus discrete inputs address. """ return ModbusDataLib.bin2boollist(self._ModbusRequest( 2, addr, 1, None))[0]
def GetCoilsBool(self, addr): """Read coils from the host (function 1). addr (integer) = Modbus coil address. """ return ModbusDataLib.bin2boollist(self._ModbusRequest( 1, addr, 1, None))[0]
def NextCommand(self, readtable, servercmd): """This should execute the next command, whatever it is. This is called regularly by GenClient. Parameters: readtable (dict) = A dictionary containing a mirror of the requested portion of the server data table. E.g. {'coil' : [True, False, True, True], 'inp' : [True, False, True, True], 'inpreg' : [], 'holdingreg' : [1234, 5678]} servercmd (string) = A command from the server. This will consist of one of the following: 'run' = Run normally. 'pause' = Pause operation. 'restart' = A restart is requested. The restart request will remain in effect until new parameters are loaded. Returns: dict, float = - A dictionary in the same format as the "readtable" input parameter. This will contain the data to be written to the server. - The time in seconds to wait before running this function again. Data table items in excess of those configured for transfer will be ignored. """ # First check if we've got a good parameter set. if not self._ConfigOK: # Set the connection status. self._ConnectStatus = 'stopped' nextpoll = 1.0 return self._WriteTable, nextpoll # Get the next command. try: cmdname, cmdvalue = self._CommandIter.next() nextpoll = self._CommandTime except StopIteration: self._CommandIter = iter(self._CommandList) cmdname, cmdvalue = self._CommandIter.next() nextpoll = self._RepeatTime # See what the command says we should do. A typical command looks like this: # [('action', 'poll'), ('stn', 1), ('cmd', 3), ('remoteaddr', 0), # ('qty', 10), ('datatype', 'coil'), ('dataoffset', 0)] cmdexp = dict(cmdvalue) cmd = cmdexp['cmd'] datatype = cmdexp['datatype'] dataoffset = cmdexp['dataoffset'] qty = cmdexp['qty'] # This is a write command, so we need data. # Write flags or outputs. if cmd in (11, 13): msgdata = ModbusDataLib.boollist2bin(readtable[datatype][dataoffset:dataoffset + qty]) # Write registers. SBus registers are 32 bit, so we need 2 Modbus # registers for each SBus register. elif cmd == 14: msgdata = ModbusDataLib.signedintlist2bin(readtable[datatype][dataoffset:dataoffset + (qty * 2)]) else: msgdata = '' # ##################################### # If we have an error, then bail out, close the socket and set an error # code. Set the client to None so we will re-initialise on the next round. # Create the client if necessary. if self._SBusClient == None: self._SBusClient = SBusSimpleClient.SBusSimpleClient(self._Host, self._Port, self._TimeOut) self._MsgSeq += 1 try: # Send the request. self._SBusClient.SendRequest(self._MsgSeq, cmdexp['stn'], cmd, qty, cmdexp['remoteaddr'], msgdata) # Get the response. telegramattr, recvmsgseq, recvdata = self._SBusClient.ReceiveResponse() # If we have an error, bail out here. except: self._SBusClient = None self._ConnectStatus = 'faulted' self._AddCmdStatus(cmdname, 'connection') # Exit here if error. return {}, 0.5 # ##################################### # This is a read command, so we need to save the data. # Read flags, inputs, or outputs. if (cmd in (2, 3, 5)) and (telegramattr == 1): booldata = ModbusDataLib.bin2boollist(recvdata) self._WriteTable[datatype][dataoffset:dataoffset + qty] = booldata[:qty] # Set the connection status. self._ConnectStatus = 'running' self._AddCmdStatus(cmdname, 'ok') # Read registers. elif (cmd == 6) and (telegramattr == 1): regdata = ModbusDataLib.signedbin2intlist(recvdata) # SBus registers are twice the size of Modbus registers. self._WriteTable[datatype][dataoffset:dataoffset + (qty * 2)] = regdata[:qty * 2] # Set the connection status. self._ConnectStatus = 'running' self._AddCmdStatus(cmdname, 'ok') # This was a write and the response was an ack or nak. elif (cmd in (11, 13, 14)) and (telegramattr == 2): # Decode the ack/nak acknak = ModbusDataLib.BinStr2SignedInt(recvdata) # The Ack was OK. if acknak != 0: self._ConnectStatus = 'faulted' self._AddCmdStatus(cmdname, 'deviceerr') else: # Set the connection status. self._ConnectStatus = 'running' self._AddCmdStatus(cmdname, 'ok') else: self._ConnectStatus = 'faulted' self._AddCmdStatus(cmdname, 'deviceerr') return self._WriteTable, nextpoll