def write_multiple_registers(self, starting_address, values):
        """
        Write multiple registers to Master device (Function code 16)
        starting_address: First register to be written
        values:  Register Values [0..quantity-1] to be written
        """
        self.__transactionIdentifier += 1
        if self.__ser is not None:
            if self.__ser.closed:
                raise Exception.SerialPortNotOpenedException(
                    "serial port not opened")
        function_code = 16
        length = 6
        transaction_identifier_lsb = self.__transactionIdentifier & 0xFF
        transaction_identifier_msb = (
            (self.__transactionIdentifier & 0xFF00) >> 8)
        length_lsb = length & 0xFF
        length_msb = (length & 0xFF00) >> 8
        starting_address_lsb = starting_address & 0xFF
        starting_address_msb = (starting_address & 0xFF00) >> 8
        quantityLSB = len(values) & 0xFF
        quantityMSB = (len(values) & 0xFF00) >> 8
        valueToWrite = list()
        for i in range(0, len(values)):
            valueToWrite.append(values[i])
        if self.__ser is not None:
            data = bytearray([
                self.__unitIdentifier, function_code, starting_address_msb,
                starting_address_lsb, quantityMSB, quantityLSB
            ])
            data.append(len(valueToWrite) * 2)  # Bytecount
            for i in range(0, len(valueToWrite)):
                data.append((valueToWrite[i] & 0xFF00) >> 8)
                data.append(valueToWrite[i] & 0xFF)
            crc = self.__calculateCRC(data, len(data), 0)
            crcLSB = crc & 0xFF
            crcMSB = (crc & 0xFF00) >> 8
            data.append(crcLSB)
            data.append(crcMSB)
            self.__ser.write(data)
            bytes_to_read = 8
            data = self.__ser.read(bytes_to_read)
            b = bytearray(data)
            data = b
            if len(data) < bytes_to_read:
                raise Exceptions.TimeoutError('Read timeout Exception')
            if (data[1] == 0x90) & (data[2] == 0x01):
                raise Exceptions.function_codeNotSupportedException(
                    "Function code not supported by master")
            if (data[1] == 0x90) & (data[2] == 0x02):
                raise Exceptions.starting_addressInvalidException(
                    "Starting address invalid or starting address + quantity invalid"
                )
            if (data[1] == 0x90) & (data[2] == 0x03):
                raise Exceptions.QuantityInvalidException("quantity invalid")
            if (data[1] == 0x90) & (data[2] == 0x04):
                raise Exceptions.ModbusException("error reading")
            crc = self.__calculateCRC(data, len(data) - 2, 0)
            crcLSB = crc & 0xFF
            crcMSB = (crc & 0xFF00) >> 8
            if (crcLSB != data[len(data) - 2]) & (crcMSB !=
                                                  data[len(data) - 1]):
                raise Exceptions.CRCCheckFailedException("CRC check failed")
            if data[1] == self.__unitIdentifier:
                return True
            else:
                return False
        else:
            protocolIdentifierLSB = 0x00
            protocolIdentifierMSB = 0x00
            length_lsb = 0x06
            length_msb = 0x00
            data = bytearray([
                transaction_identifier_msb, transaction_identifier_lsb,
                protocolIdentifierMSB, protocolIdentifierLSB, length_msb,
                length_lsb, self.__unitIdentifier, function_code,
                starting_address_msb, starting_address_lsb, quantityMSB,
                quantityLSB
            ])
            data.append(len(valueToWrite) * 2)  # Bytecount
            for i in range(0, len(valueToWrite)):
                data.append((valueToWrite[i] & 0xFF00) >> 8)
                data.append(valueToWrite[i] & 0xFF)

            self.__tcpClientSocket.send(data)
            bytes_to_read = 12
            self.__receivedata = bytearray()
            try:
                while len(self.__receivedata) == 0:
                    pass
            except Exception:
                raise Exception('Read Timeout')
            data = bytearray(self.__receivedata)
            if (data[1] == 0x90) & (data[2] == 0x01):
                raise Exceptions.function_codeNotSupportedException(
                    "Function code not supported by master")
            if (data[1] == 0x90) & (data[2] == 0x02):
                raise Exceptions.starting_addressInvalidException(
                    "Starting address invalid or starting address + quantity invalid"
                )
            if (data[1] == 0x90) & (data[2] == 0x03):
                raise Exceptions.QuantityInvalidException("quantity invalid")
            if (data[1] == 0x90) & (data[2] == 0x04):
                raise Exceptions.ModbusException("error reading")
            return True
    def read_inputregisters(self, starting_address, quantity):
        """
        Read Input Registers from Master device (Function code 4)
        starting_address :  First input register to be read
        quantity:  Number of input registers to be read
        returns:  Int Array [0..quantity-1] which contains the input registers
        """
        self.__transactionIdentifier += 1
        if self.__ser is not None:
            if self.__ser.closed:
                raise Exception.SerialPortNotOpenedException(
                    "serial port not opened")
        if (starting_address > 65535) | (quantity > 125):
            raise ValueError(
                "Starting address must be 0 - 65535 quantity must be 0 - 125")
        function_code = 4
        length = 6
        transaction_identifier_lsb = self.__transactionIdentifier & 0xFF
        transaction_identifier_msb = (
            (self.__transactionIdentifier & 0xFF00) >> 8)
        length_lsb = length & 0xFF
        length_msb = (length & 0xFF00) >> 8
        starting_address_lsb = starting_address & 0xFF
        starting_address_msb = (starting_address & 0xFF00) >> 8
        quantity_lsb = quantity & 0xFF
        quantity_msb = (quantity & 0xFF00) >> 8
        if self.__ser is not None:
            data = bytearray([
                self.__unitIdentifier, function_code, starting_address_msb,
                starting_address_lsb, quantity_msb, quantity_lsb, 0, 0
            ])
            crc = self.__calculateCRC(data, len(data) - 2, 0)
            crcLSB = crc & 0xFF
            crcMSB = (crc & 0xFF00) >> 8
            data[6] = crcLSB
            data[7] = crcMSB

            self.__ser.write(data)
            bytes_to_read = 5 + int(quantity * 2)

            data = self.__ser.read(bytes_to_read)

            b = bytearray(data)
            data = b

            if len(data) < bytes_to_read:
                raise Exceptions.TimeoutError("Read timeout Exception")
            if (data[1] == 0x84) & (data[2] == 0x01):
                raise Exceptions.function_codeNotSupportedException(
                    "Function code not supported by master")
            if (data[1] == 0x84) & (data[2] == 0x02):
                raise Exceptions.starting_addressInvalidException(
                    "Starting address invalid or starting address + quantity invalid"
                )
            if (data[1] == 0x84) & (data[2] == 0x03):
                raise Exceptions.QuantityInvalidException("quantity invalid")
            if (data[1] == 0x84) & (data[2] == 0x04):
                raise Exceptions.ModbusException("error reading")
            crc = self.__calculateCRC(data, len(data) - 2, 0)
            crcLSB = crc & 0xFF
            crcMSB = (crc & 0xFF00) >> 8
            if (crcLSB != data[len(data) - 2]) & (crcMSB !=
                                                  data[len(data) - 1]):
                raise Exceptions.CRCCheckFailedException("CRC check failed")
            myList = list()
            for i in range(0, quantity):
                myList.append((data[i * 2 + 3] << 8) + data[i * 2 + 4])
            return myList
        else:
            protocolIdentifierLSB = 0x00
            protocolIdentifierMSB = 0x00
            length_lsb = 0x06
            length_msb = 0x00
            data = bytearray([
                transaction_identifier_msb, transaction_identifier_lsb,
                protocolIdentifierMSB, protocolIdentifierLSB, length_msb,
                length_lsb, self.__unitIdentifier, function_code,
                starting_address_msb, starting_address_lsb, quantity_msb,
                quantity_lsb
            ])
            self.__tcpClientSocket.send(data)
            bytes_to_read = 9 + int(quantity * 2)
            self.__receivedata = bytearray()
            try:
                while len(self.__receivedata) == 0:
                    pass
            except Exception:
                raise Exception('Read Timeout')
            data = bytearray(self.__receivedata)
            if (data[1 + 6] == 0x84) & (data[2 + 6] == 0x01):
                raise Exceptions.function_codeNotSupportedException(
                    "Function code not supported by master")
            if (data[1 + 6] == 0x84) & (data[2 + 6] == 0x02):
                raise Exceptions.starting_addressInvalidException(
                    "Starting address invalid or starting address + quantity invalid"
                )
            if (data[1 + 6] == 0x84) & (data[2 + 6] == 0x03):
                raise Exceptions.QuantityInvalidException("quantity invalid")
            if (data[1 + 6] == 0x84) & (data[2 + 6] == 0x04):
                raise Exceptions.ModbusException("error reading")
            myList = list()
            for i in range(0, quantity):
                myList.append((data[i * 2 + 3 + 6] << 8) + data[i * 2 + 4 + 6])
            return myList
    def write_single_register(self, starting_address, value):
        """
        Write single Register to Master device (Function code 6)
        starting_address:  Register to be written
        value: Register Value to be written
        """
        self.__transactionIdentifier += 1
        if self.__ser is not None:
            if self.__ser.closed:
                raise Exception.SerialPortNotOpenedException(
                    "serial port not opened")
        function_code = 6
        length = 6
        transaction_identifier_lsb = self.__transactionIdentifier & 0xFF
        transaction_identifier_msb = (
            (self.__transactionIdentifier & 0xFF00) >> 8)
        length_lsb = length & 0xFF
        length_msb = (length & 0xFF00) >> 8
        starting_address_lsb = starting_address & 0xFF
        starting_address_msb = (starting_address & 0xFF00) >> 8
        valueLSB = value & 0xFF
        valueMSB = (value & 0xFF00) >> 8
        if self.__ser is not None:
            data = bytearray([
                self.__unitIdentifier, function_code, starting_address_msb,
                starting_address_lsb, valueMSB, valueLSB, 0, 0
            ])
            crc = self.__calculateCRC(data, len(data) - 2, 0)
            crcLSB = crc & 0xFF
            crcMSB = (crc & 0xFF00) >> 8
            data[6] = crcLSB
            data[7] = crcMSB
            self.__ser.write(data)
            bytes_to_read = 8
            data = self.__ser.read(bytes_to_read)
            b = bytearray(data)
            data = b
            # Check for Exception
            if len(data) < bytes_to_read:
                raise Exceptions.TimeoutError('Read timeout Exception')
            if (data[1] == 0x86) & (data[2] == 0x01):
                raise Exceptions.function_codeNotSupportedException(
                    "Function code not supported by master")
            if (data[1] == 0x86) & (data[2] == 0x02):
                raise Exceptions.starting_addressInvalidException(
                    "Register address invalid")
            if (data[1] == 0x86) & (data[2] == 0x03):
                raise Exceptions.QuantityInvalidException(
                    "Invalid Register Value")
            if (data[1] == 0x86) & (data[2] == 0x04):
                raise Exceptions.ModbusException("error reading")
            crc = self.__calculateCRC(data, len(data) - 2, 0)
            crcLSB = crc & 0xFF
            crcMSB = (crc & 0xFF00) >> 8
            if (crcLSB != data[len(data) - 2]) & (crcMSB !=
                                                  data[len(data) - 1]):
                raise Exceptions.CRCCheckFailedException("CRC check failed")

            if data[1] == self.__unitIdentifier:
                return True
            else:
                return False
        else:
            protocolIdentifierLSB = 0x00
            protocolIdentifierMSB = 0x00
            length_lsb = 0x06
            length_msb = 0x00
            data = bytearray([
                transaction_identifier_msb, transaction_identifier_lsb,
                protocolIdentifierMSB, protocolIdentifierLSB, length_msb,
                length_lsb, self.__unitIdentifier, function_code,
                starting_address_msb, starting_address_lsb, valueMSB, valueLSB
            ])
            self.__tcpClientSocket.send(data)
            bytes_to_read = 12
            self.__receivedata = bytearray()
            try:
                while (len(self.__receivedata) == 0):
                    pass
            except Exception:
                raise Exception('Read Timeout')
            data = bytearray(self.__receivedata)
            if (data[1 + 6] == 0x86) & (data[2 + 6] == 0x01):
                raise Exceptions.function_codeNotSupportedException(
                    "Function code not supported by master")
            if (data[1 + 6] == 0x86) & (data[2 + 6] == 0x02):
                raise Exceptions.starting_addressInvalidException(
                    "Register address invalid")
            if (data[1 + 6] == 0x86) & (data[2 + 6] == 0x03):
                raise Exceptions.QuantityInvalidException(
                    "Invalid Register Value")
            if (data[1 + 6] == 0x86) & (data[2 + 6] == 0x04):
                raise Exceptions.ModbusException("error reading")

                return True
示例#4
0
 def read_coils(self, starting_address, quantity):
     """
     Read Coils from Master device (Function code 1)
     starting_address:  First coil to be read
     quantity: Numer of coils to be read
     returns:  Boolean Array [0..quantity-1] which contains the coils
     """
     self.__transactionIdentifier += 1
     if (self.__ser is not None):
         if (self.__ser.closed):
             raise Exception.SerialPortNotOpenedException(
                 "serial port not opened")
     if ((starting_address > 65535) | (quantity > 2000)):
         raise ValueError(
             "Starting address must be 0 - 65535; quantity must be 0 - 2000"
         )
     function_code = 1
     length = 6
     transaction_identifier_lsb = self.__transactionIdentifier & 0xFF
     transaction_identifier_msb = (
         (self.__transactionIdentifier & 0xFF00) >> 8)
     length_lsb = length & 0xFF
     length_msb = (length & 0xFF00) >> 8
     starting_address_lsb = starting_address & 0xFF
     starting_address_msb = (starting_address & 0xFF00) >> 8
     quantity_lsb = quantity & 0xFF
     quantity_msb = (quantity & 0xFF00) >> 8
     if (self.__ser is not None):
         data = bytearray([
             self.__unitIdentifier, function_code, starting_address_msb,
             starting_address_lsb, quantity_msb, quantity_lsb, 0, 0
         ])
         crc = self.__calculateCRC(data, len(data) - 2, 0)
         crcLSB = crc & 0xFF
         crcMSB = (crc & 0xFF00) >> 8
         data[6] = crcLSB
         data[7] = crcMSB
         self.__ser.write(data)
         if (quantity % 8 != 0):
             bytes_to_read = 6 + int(quantity / 8)
         else:
             bytes_to_read = 5 + int(quantity / 8)
         data = self.__ser.read(bytes_to_read)
         b = bytearray(data)
         data = b
         if (len(data) < bytes_to_read):
             raise Exceptions.TimeoutError('Read timeout Exception')
         if ((data[1] == 0x81) & (data[2] == 0x01)):
             raise Exceptions.function_codeNotSupportedException(
                 "Function code not supported by master")
         if ((data[1] == 0x81) & (data[2] == 0x02)):
             raise Exceptions.starting_addressInvalidException(
                 "Starting address invalid or starting address + quantity invalid"
             )
         if ((data[1] == 0x81) & (data[2] == 0x03)):
             raise Exceptions.QuantityInvalidException("quantity invalid")
         if ((data[1] == 0x81) & (data[2] == 0x04)):
             raise Exceptions.ModbusException("error reading")
         crc = self.__calculateCRC(data, len(data) - 2, 0)
         crcLSB = crc & 0xFF
         crcMSB = (crc & 0xFF00) >> 8
         if ((crcLSB != data[len(data) - 2]) &
             (crcMSB != data[len(data) - 1])):
             raise Exceptions.CRCCheckFailedException("CRC check failed")
         myList = list()
         for i in range(0, quantity):
             myList.append(bool((data[int(i / 8) + 3] >> int(i % 8)) & 0x1))
         return myList
     else:
         protocolIdentifierLSB = 0x00
         protocolIdentifierMSB = 0x00
         length_lsb = 0x06
         length_msb = 0x00
         data = bytearray([
             transaction_identifier_msb, transaction_identifier_lsb,
             protocolIdentifierMSB, protocolIdentifierLSB, length_msb,
             length_lsb, self.__unitIdentifier, function_code,
             starting_address_msb, starting_address_lsb, quantity_msb,
             quantity_lsb
         ])
         self.__tcpClientSocket.send(data)
         self.__receivedata = bytearray()
         if (quantity % 8 != 0):
             bytes_to_read = 10 + int(quantity / 8)
         else:
             bytes_to_read = 9 + int(quantity / 8)
         try:
             while (len(self.__receivedata) == 0):
                 pass
         except Exception:
             raise Exception('Read Timeout')
         data = bytearray(self.__receivedata)
         if ((data[1 + 6] == 0x82) & (data[2 + 6] == 0x01)):
             raise Exceptions.function_codeNotSupportedException(
                 "Function code not supported by master")
         if ((data[1 + 6] == 0x82) & (data[2 + 6] == 0x02)):
             raise Exceptions.starting_addressInvalidException(
                 "Starting address invalid or starting address + quantity invalid"
             )
         if ((data[1 + 6] == 0x82) & (data[2 + 6] == 0x03)):
             raise Exceptions.QuantityInvalidException("quantity invalid")
         if ((data[1 + 6] == 0x82) & (data[2 + 6] == 0x04)):
             raise Exceptions.ModbusException("error reading")
         myList = list()
         for i in range(0, quantity):
             myList.append(
                 bool((data[int(i / 8) + 3 + 6] >> int(i % 8)) & 0x1))
         return myList