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
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