def SetRegistersInt(self, addr, data): """Write registers to the host (command 14). addr (integer) = Modbus discrete inputs address. data (string) = Packed binary string with the data to write. """ bindata = SBusMsg.signedint32list2bin([data]) self._SBusRequest(14, addr, 1, bindata)
def GetRegistersIntList(self, addr, qty): """Read registers from the host (command 6). addr (integer) = SBus registers address. qty (integer) = Number of registers. """ return SBusMsg.signedbin2int32list( self._SBusRequest(6, addr, qty, None))
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 GetRegistersInt(self, addr): """Read registers from the host (command 6). addr (integer) = SBus registers address. """ return SBusMsg.signedbin2int32list(self._SBusRequest(6, addr, 1, None))[0]
def _handle(self): ReceivedData = self.rfile.read() if ReceivedData: # Decode message. try: (TelegramAttr, MsgSequence, StnAddr, CmdCode, DataAddr, DataCount, MsgData, MsgResult) = SBServerMsg.SBRequest(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 SBusMsg.MessageLengthError: print('Server %d - Invalid message length. %s' % (CmdOpts.GetPort(), time.ctime())) MsgResult = False MsgSequence = 0 # Message had a CRC error. except SBusMsg.CRCError: print('Server %d - Bad CRC. %s' % (CmdOpts.GetPort(), time.ctime())) MsgResult = False MsgSequence = 0 # All other errors. except: print('Server %d - Request could not be decoded. %s' % (CmdOpts.GetPort(), time.ctime())) MsgResult = False MsgSequence = 0 ReplyData = '' # Handle the command, but only if know the parameters are valid. if (MsgResult): # Decode messages. If we get an error in reading/writing memory or # in constructing messages, we will consider this to be an SBus error. try: # Read Flags. if CmdCode == 2: MemData = MemMap.GetFlags(DataAddr, DataCount) MsgData = ModbusDataStrLib.boollist2bin(MemData) ReplyData = SBServerMsg.SBResponse( MsgSequence, CmdCode, 0, MsgData) # Read Inputs elif CmdCode == 3: MemData = MemMap.GetInputs(DataAddr, DataCount) MsgData = ModbusDataStrLib.boollist2bin(MemData) ReplyData = SBServerMsg.SBResponse( MsgSequence, CmdCode, 0, MsgData) # Read Outputs elif CmdCode == 5: MemData = MemMap.GetOutputs(DataAddr, DataCount) MsgData = ModbusDataStrLib.boollist2bin(MemData) ReplyData = SBServerMsg.SBResponse( MsgSequence, CmdCode, 0, MsgData) # Read Registers elif CmdCode == 6: MemData = MemMap.GetRegisters(DataAddr, DataCount) MsgData = SBusMsg.signedint32list2bin(MemData) ReplyData = SBServerMsg.SBResponse( MsgSequence, CmdCode, 0, MsgData) # Write flags elif CmdCode == 11: MemData = ModbusDataStrLib.bin2boollist(MsgData) MemMap.SetFlags(DataAddr, DataCount, MemData) ReplyData = SBServerMsg.SBResponse( MsgSequence, CmdCode, 0, '') # Write outputs elif CmdCode == 13: MemData = ModbusDataStrLib.bin2boollist(MsgData) MemMap.SetOutputs(DataAddr, DataCount, MemData) ReplyData = SBServerMsg.SBResponse( MsgSequence, CmdCode, 0, '') # Write Registers elif CmdCode == 14: MemData = SBusMsg.signedbin2int32list(MsgData) MemMap.SetRegisters(DataAddr, DataCount, MemData) ReplyData = SBServerMsg.SBResponse( MsgSequence, CmdCode, 0, '') # We don't understand this command code. else: print('Server %d - Unsupported command code' % CmdOpts.GetPort()) ReplyData = SBServerMsg.SBErrorResponse(MsgSequence) # We don't understand this message. except: ReplyData = SBServerMsg.SBErrorResponse(MsgSequence) # The message was bad, so we return a NAK response. else: ReplyData = SBServerMsg.SBErrorResponse(MsgSequence) # Send the reply. try: self.wfile.write(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. %s' % (CmdOpts.GetPort(), time.ctime()))
# Signal handler. def _SigHandler(signum, frame): print('Operator terminated server at %s' % time.ctime()) sys.exit() # Initialise the signal handler. signal.signal(signal.SIGINT, _SigHandler) # Get the command line parameter options. CmdOpts = GetOptions() # Initialise the data table. MemMap = SBusMemTable() # Initialise the server protcol library. We will use a large data # table for all addresses. SBServerMsg = SBusMsg.SBusServerMessages(65535, 65535, 65535, 65535) ############################################################ # Print the start up greetings. print('\n\nSBusServer version %s' % SoftwareVersion) print('Starting server on port %d. %s' % (CmdOpts.GetPort(), time.ctime())) # # Initialise the main server using the selected port and start it up. This runs forever. socketserver.UDPServer(('', CmdOpts.GetPort()), MsgHandler).serve_forever() ############################################################
def Request(self, cmdcode, dataaddr, data=None): """Read data from an address. Parameters: cmdcode (integer) = SBus command code. dataaddr (integer) = SBus address. data (integer) = Data to be written (optional). Returns: (tuple) = If OK, returns True plus the received data. If error, returns False plus an error message. """ # Increment the transaction id. self._IncMsgSeq() # Only request one at a time. datacount = 1 sendata = None # Only the following command codes are supported. if (cmdcode not in [2, 3, 5, 6, 11, 13, 14]): return False, _ErrorMsgs['badcmdcode'] # Check if the SBus address is legal. This does not guaranty though # that it will be supported in the field device. if (dataaddr < 0) or (dataaddr > 65535): return False, _ErrorMsgs['invalidaddress'] # If we are writing data, make sure it is valid. if cmdcode in [11, 13, 14]: try: dataint = int(data) except: return False, _ErrorMsgs['dataerr'] # For writing data, convert the data to a binary string, # and check if it is within range for that function. if (cmdcode in (11, 13)): if (dataint == 0): sendata = self._bitoff elif (dataint == 1): sendata = self._biton else: return False, _ErrorMsgs['dataerr'] elif (cmdcode == 14): if ((dataint >= -2147483648) and (dataint <= 2147483647)): sendata = SBusMsg.signedint32list2bin([data]) else: return False, _ErrorMsgs['dataerr'] # Send the request. try: self._msg.SendRequest(self._msgsequence, self._stnaddr, cmdcode, datacount, dataaddr, sendata) # Something was wrong with the parameters we gave it to send. # This should have been caught earlier. except SBusMsg.ParamError: return False, _ErrorMsgs['invalidparam'] # Some other error occured while sending. except: return False, _ErrorMsgs['connnecterror'] # Receive the response. try: telegramattr, recv_msgsequence, recv_msgdata = self._msg.ReceiveResponse( ) # The message length did not match any valid message type. except SBusMsg.MessageLengthError: return False, _ErrorMsgs['responselength'] # The message CRC was bad. except SBusMsg.CRCError: return False, _ErrorMsgs['crcerr'] # Some other error occured while receiving. except: return False, _ErrorMsgs['connnecterror'] # Look at the telegrapm attribute to see what sort of response # it was, and compare that to the command code. # If it was a 1, we expect some data from a read operation. if (telegramattr == 1): # Decode the data by command code. if (cmdcode in (2, 3, 5)): rdata = int(ModbusDataStrLib.bin2boollist(recv_msgdata)[0]) elif (cmdcode == 6): rdata = SBusMsg.signedbin2int32list(recv_msgdata)[0] # This was an ack from a write operation, or it was a NAK. elif (telegramattr == 2): acknak = ModbusDataStrLib.signedbin2intlist(recv_msgdata)[0] # This is an ACK from a write operation if (acknak == 0) and (cmdcode in (11, 13, 14)): return True, '' else: return False, _ErrorMsgs['deviceerror'] # We have an invalid telegram. else: return False, _ErrorMsgs['badmessage'] return True, rdata
def handle(self): ReceivedData = self.rfile.read() if ReceivedData: # Decode message. try: (TelegramAttr, MsgSequence, StnAddr, CmdCode, DataAddr, DataCount, MsgData, MsgResult) = SBServerMsg.SBRequest(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 SBusMsg.MessageLengthError: print('Server %d - Invalid message length. %s' % (CmdOpts.GetPort(), time.ctime())) MsgResult = False MsgSequence = 0 # Message had a CRC error. except SBusMsg.CRCError: print('Server %d - Bad CRC. %s' % (CmdOpts.GetPort(), time.ctime())) MsgResult = False MsgSequence = 0 # All other errors. except: print('Server %d - Request could not be decoded. %s' % (CmdOpts.GetPort(), time.ctime())) MsgResult = False MsgSequence = 0 ReplyData = '' # Handle the command, but only if know the parameters are valid. if (MsgResult): # Decode messages. If we get an error in reading/writing memory or # in constructing messages, we will consider this to be an SBus error. try: # Read Flags. if CmdCode == 2: MemData = MemMap.GetFlags(DataAddr, DataCount) MsgData = ModbusDataStrLib.boollist2bin(MemData) ReplyData = SBServerMsg.SBResponse(MsgSequence, CmdCode, 0, MsgData) # Read Inputs elif CmdCode == 3: MemData = MemMap.GetInputs(DataAddr, DataCount) MsgData = ModbusDataStrLib.boollist2bin(MemData) ReplyData = SBServerMsg.SBResponse(MsgSequence, CmdCode, 0, MsgData) # Read Outputs elif CmdCode == 5: MemData = MemMap.GetOutputs(DataAddr, DataCount) MsgData = ModbusDataStrLib.boollist2bin(MemData) ReplyData = SBServerMsg.SBResponse(MsgSequence, CmdCode, 0, MsgData) # Read Registers elif CmdCode == 6: MemData = MemMap.GetRegisters(DataAddr, DataCount) MsgData = SBusMsg.signedint32list2bin(MemData) ReplyData = SBServerMsg.SBResponse(MsgSequence, CmdCode, 0, MsgData) # Write flags elif CmdCode == 11: MemData = ModbusDataStrLib.bin2boollist(MsgData) MemMap.SetFlags(DataAddr, DataCount, MemData) ReplyData = SBServerMsg.SBResponse(MsgSequence, CmdCode, 0, '') # Write outputs elif CmdCode == 13: MemData = ModbusDataStrLib.bin2boollist(MsgData) MemMap.SetOutputs(DataAddr, DataCount, MemData) ReplyData = SBServerMsg.SBResponse(MsgSequence, CmdCode, 0, '') # Write Registers elif CmdCode == 14: MemData = SBusMsg.signedbin2int32list(MsgData) MemMap.SetRegisters(DataAddr, DataCount, MemData) ReplyData = SBServerMsg.SBResponse(MsgSequence, CmdCode, 0, '') # We don't understand this command code. else: print('Server %d - Unsupported command code' % CmdOpts.GetPort()) ReplyData = SBServerMsg.SBErrorResponse(MsgSequence) # We don't understand this message. except: ReplyData = SBServerMsg.SBErrorResponse(MsgSequence) # The message was bad, so we return a NAK response. else: ReplyData = SBServerMsg.SBErrorResponse(MsgSequence) # Send the reply. try: self.wfile.write(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. %s' % (CmdOpts.GetPort(), time.ctime()))
def GetRegistersIntList(self, addr, qty): """Read registers from the host (command 6). addr (integer) = SBus registers address. qty (integer) = Number of registers. """ return SBusMsg.signedbin2int32list(self._SBusRequest(6, addr, qty, None))