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.')
예제 #2
0
	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)
예제 #3
0
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.')
예제 #5
0
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 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 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.')
예제 #8
0
    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 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 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.')
예제 #11
0
    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)
예제 #12
0
    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)
예제 #13
0
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()
예제 #14
0
    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 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)
예제 #16
0
    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)
예제 #17
0
	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
예제 #18
0
    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 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)
예제 #20
0
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
예제 #21
0
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()
예제 #22
0
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
예제 #23
0
    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]
예제 #24
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]
예제 #29
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]
예제 #30
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]
예제 #31
0
	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]
예제 #32
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
예제 #33
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]
예제 #34
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]
예제 #35
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]
예제 #36
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