def plc_get_run(self) -> str: """ :return: 'STOP', 'START', 'RUN' or 'UNKNOWN' :raises: DriverError, ConnectionError """ msg_tx = ibh_const.IBHLinkMSG(rx=ibh_const.MPI_TASK, tx=ibh_const.HOST, nr=self.msg_number, ln=ibh_const.MSG_HEADER_SIZE, b=ibh_const.MPI_GET_OP_STATUS, device_adr=self.mpi_address) self.msg_number += 1 self.sendData( bytes(msg_tx)[:ibh_const.MSG_HEADER_SIZE + ibh_const.TELE_HEADER_SIZE]) raw_bytes = self.receiveData() msg_rx = ibh_const.IBHLinkMSG() msg_rx.receiveSome(raw_bytes) self.received_telegram_check(msg_tx, msg_rx, ibh_const.TELE_HEADER_SIZE + 2) op_status = int.from_bytes(msg_rx.d[:2], byteorder='little') if op_status == 0: return 'STOP' elif op_status == 1: return 'START' elif op_status == 2: return 'RUN' else: return 'UNKNOWN'
def test_write_vals_MB10(self): var = 33 msg_struct = c.IBHLinkMSG(rx=c.MPI_TASK, tx=c.HOST, ln=c.MSG_HEADER_SIZE + 1, nr=0, b=c.MPI_READ_WRITE_M, device_adr=self.mpiAddr, data_adr=10, data_cnt=1, data_type=c.TASK_TDT_UINT8, func_code=c.TASK_TFC_WRITE, d=c.dataArray(var)) raw_bytes_msg_struct = bytes(msg_struct) sent_bytes = raw_bytes_msg_struct[:17] msg_struct.rx, msg_struct.tx = msg_struct.tx, msg_struct.rx msg_struct.a = msg_struct.b msg_struct.ln = 8 raw_bytes_msg_struct = bytes(msg_struct) expected_bytes = raw_bytes_msg_struct[:16] self._instance_socket_class.recv.return_value = expected_bytes self._instance_socket_class.send.return_value = len(sent_bytes) self.driver.connect_plc() self.driver.write_vals(data_type='M', data_address=10, offset=0, size=1, vals=bytes([var])) self._instance_socket_class.send.assert_called_once_with(sent_bytes)
def disconnect_plc(self): """ :raises: DriverError, ConnectionError """ if not self.connected: return msg_tx = ibh_const.IBHLinkMSG(rx=ibh_const.MPI_TASK, tx=ibh_const.HOST, nr=self.msg_number, ln=ibh_const.MSG_HEADER_SIZE, b=ibh_const.MPI_DISCONNECT, device_adr=self.mpi_address) self.msg_number += 1 msg_length = ibh_const.MSG_HEADER_SIZE + ibh_const.TELE_HEADER_SIZE self.sendData(bytes(msg_tx)[:msg_length]) raw_bytes = self.receiveData() msg_rx = ibh_const.IBHLinkMSG() msg_rx.receiveSome(raw_bytes) self.received_telegram_check(msg_tx, msg_rx, ibh_const.TELE_HEADER_SIZE) self.connected = False logger.debug("Disconnected:{}".format(self.ip_address))
def test_plc_get_run(self): raw_bytes_msg_struct = bytes( c.IBHLinkMSG(rx=c.MPI_TASK, tx=c.HOST, nr=0, ln=c.MSG_HEADER_SIZE, b=c.MPI_GET_OP_STATUS, device_adr=self.mpiAddr)) sent_bytes = raw_bytes_msg_struct[:16] self._instance_socket_class.send.return_value = len(sent_bytes) self._instance_socket_class.recv.return_value = bytes([ c.HOST, c.MPI_TASK, 10, self.driver.msg_number, 0x32, 0, 0, 0, self.driver.mpi_address, 0, 0, 0, 0, 0, 0, 0, 2, 0 ]) self.driver.connect_plc() self.assertEqual("RUN", self.driver.plc_get_run(), "PLC state not properly returned") self._instance_socket_class.send.assert_called_once_with(sent_bytes)
def produce_respose(self, data: bytes, disconnect: threading.Event) -> bytes: msg_rx = ibh_const.IBHLinkMSG() msg_rx.receiveSome(data) msg_tx = ibh_const.IBHLinkMSG() msg_tx.rx = msg_rx.tx msg_tx.tx = msg_rx.rx # msg_tx.ln = ? msg_tx.nr = msg_rx.nr msg_tx.a = msg_rx.b msg_tx.f = 0 msg_tx.b = 0 msg_tx.e = 0 msg_tx.device_adr = msg_rx.device_adr msg_tx.data_area = msg_rx.data_area msg_tx.data_adr = msg_rx.data_adr msg_tx.data_idx = msg_rx.data_idx msg_tx.data_cnt = msg_rx.data_cnt msg_tx.data_type = msg_rx.data_type msg_tx.func_code = msg_rx.func_code # msg_tx.data_type = IBHconst.TASK_TDT_UINT8 | IBHconst.TASK_TDT_UINT16 # msg_tx.func_code = IBHconst.TASK_TFC_READ | IBHconst.TASK_TFC_WRITE # msg_tx.d = ? error = self.basic_telegram_check(msg_rx) if error: msg_tx.ln = 8 msg_tx.f = error return bytes(msg_tx)[:ibh_const.MSG_HEADER_SIZE + msg_tx.ln] if msg_rx.b == ibh_const.MPI_READ_WRITE_DB: area = 'D' data_address = msg_rx.data_adr db_offset = (msg_rx.data_area << 8) + msg_rx.data_idx size = msg_rx.data_cnt if msg_rx.func_code == ibh_const.TASK_TFC_READ: return self.fill_message_with_collection_data( msg_tx, area, data_address, db_offset, size) elif msg_rx.func_code == ibh_const.TASK_TFC_WRITE: return self.fill_collection_with_message_data( msg_tx, area, data_address, db_offset, size, msg_rx.d) elif msg_rx.b == ibh_const.MPI_GET_OP_STATUS: msg_tx.ln = ibh_const.TELE_HEADER_SIZE + 2 ctypes.memmove( ctypes.addressof(msg_tx.d), self.collection.plc_state.to_bytes(2, byteorder='little'), 2) return bytes(msg_tx)[:ibh_const.MSG_HEADER_SIZE + msg_tx.ln] elif msg_rx.b == ibh_const.MPI_READ_WRITE_M: area = 'M' data_address = msg_rx.data_adr size = msg_rx.data_cnt if msg_rx.func_code == ibh_const.TASK_TFC_READ: return self.fill_message_with_collection_data( msg_tx, area, data_address, 0, size) elif msg_rx.func_code == ibh_const.TASK_TFC_WRITE: return self.fill_collection_with_message_data( msg_tx, area, data_address, 0, size, msg_rx.d) elif msg_rx.b == ibh_const.MPI_READ_WRITE_IO: if msg_rx.data_area == ibh_const.INPUT_AREA: area = 'I' elif msg_rx.data_area == ibh_const.OUTPUT_AREA: area = 'Q' data_address = msg_rx.data_adr size = msg_rx.data_cnt if msg_rx.func_code == ibh_const.TASK_TFC_READ: return self.fill_message_with_collection_data( msg_tx, area, data_address, 0, size) elif msg_rx.func_code == ibh_const.TASK_TFC_WRITE: return self.fill_collection_with_message_data( msg_tx, area, data_address, 0, size, msg_rx.d) elif msg_rx.b == ibh_const.MPI_READ_WRITE_CNT: area = 'C' data_address = msg_rx.data_adr size = msg_rx.data_cnt if msg_rx.func_code == ibh_const.TASK_TFC_READ: return self.fill_message_with_collection_data( msg_tx, area, data_address, 0, size) elif msg_rx.func_code == ibh_const.TASK_TFC_WRITE: return self.fill_collection_with_message_data( msg_tx, area, data_address, 0, size, msg_rx.d) elif msg_rx.b == ibh_const.MPI_READ_WRITE_TIM: area = 'T' data_address = msg_rx.data_adr size = msg_rx.data_cnt if msg_rx.func_code == ibh_const.TASK_TFC_READ: return self.fill_message_with_collection_data( msg_tx, area, data_address, 0, size) elif msg_rx.func_code == ibh_const.TASK_TFC_WRITE: return self.fill_collection_with_message_data( msg_tx, area, data_address, 0, size, msg_rx.d) elif msg_rx.b == ibh_const.MPI_DISCONNECT: msg_tx.ln = 8 disconnect.set() return bytes(msg_tx)[:ibh_const.MSG_HEADER_SIZE + ibh_const.TELE_HEADER_SIZE]
def write_vals(self, data_type: str, data_address: int, offset: int, size: int, vals: bytes) -> bool: """ :returns: Succeed of operation. :raises: TypeError, ValueError, DriverError, ConnectionError """ if not type(vals) is bytes: raise TypeError("Given 'vals' of type {}, use bytes object".format( type(vals))) if len(vals) != size: raise ValueError( "Length of byte array({}) is not equal to size of write{}". format(len(vals), size)) if size > ibh_const.IBHLINK_WRITE_MAX or size <= 0: raise ValueError( "size > IBHconst.IBHLINK_WRITE_MAX or size <= 0. Given:". format(size)) elif data_type == 'E' or data_type == 'I': msg_tx = ibh_const.IBHLinkMSG(ln=ibh_const.TELE_HEADER_SIZE + size, b=ibh_const.MPI_READ_WRITE_IO, data_area=ibh_const.INPUT_AREA, data_adr=data_address, data_cnt=size, data_type=ibh_const.TASK_TDT_UINT8) ctypes.memmove(ctypes.addressof(msg_tx.d), vals, size) elif data_type == 'A' or data_type == 'O' or data_type == 'Q': msg_tx = ibh_const.IBHLinkMSG(ln=ibh_const.TELE_HEADER_SIZE + size, b=ibh_const.MPI_READ_WRITE_IO, data_area=ibh_const.OUTPUT_AREA, data_adr=data_address, data_cnt=size, data_type=ibh_const.TASK_TDT_UINT8) ctypes.memmove(ctypes.addressof(msg_tx.d), vals, size) elif data_type == 'M': msg_tx = ibh_const.IBHLinkMSG(ln=ibh_const.TELE_HEADER_SIZE + size, b=ibh_const.MPI_READ_WRITE_M, data_adr=data_address, data_cnt=size, data_type=ibh_const.TASK_TDT_UINT8) ctypes.memmove(ctypes.addressof(msg_tx.d), vals, size) elif data_type == 'D': msg_tx = ibh_const.IBHLinkMSG(ln=ibh_const.TELE_HEADER_SIZE + size, b=ibh_const.MPI_READ_WRITE_DB, data_area=offset >> 8, data_idx=offset, data_adr=data_address, data_cnt=size, data_type=ibh_const.TASK_TDT_UINT8) ctypes.memmove(ctypes.addressof(msg_tx.d), vals, size) elif size > ibh_const.IBHLINK_WRITE_MAX / 2: logger.warning("size > IBHconst.IBHLINK_WRITE_MAX/2") return False elif data_type == 'T': # TODO: implementation 'T' return False elif data_type == 'Z' or data_type == 'C': # TODO: implementation 'C' return False else: logger.warning("No valid data type") raise ValueError("No valid data type, given:{}".format(data_type)) msg_tx.rx = ibh_const.MPI_TASK msg_tx.tx = ibh_const.HOST msg_tx.nr = self.msg_number msg_tx.device_adr = self.mpi_address msg_tx.func_code = ibh_const.TASK_TFC_WRITE self.msg_number += 1 msg_length = ibh_const.MSG_HEADER_SIZE + ibh_const.TELE_HEADER_SIZE + size self.sendData(bytes(msg_tx)[:msg_length]) raw_bytes = self.receiveData() msg_rx = ibh_const.IBHLinkMSG() msg_rx.receiveSome(raw_bytes) self.received_telegram_check(msg_tx, msg_rx, ibh_const.TELE_HEADER_SIZE) return True
def read_vals(self, data_type: str, data_address: int, offset: int, size: int) -> [int]: """ :raises: ValueError, DriverError, ConnectionError """ logger.debug('Reading vals:{}, address {}, offset {}, size {}'.format( data_type, data_address, offset, size)) if size > ibh_const.IBHLINK_READ_MAX or size <= 0: raise ValueError("size > IBHconst.IBHLINK_READ_MAX or size <= 0:") elif data_type == 'E' or data_type == 'I': msg_tx = ibh_const.IBHLinkMSG(b=ibh_const.MPI_READ_WRITE_IO, data_area=ibh_const.INPUT_AREA, data_adr=data_address, data_cnt=size, data_type=ibh_const.TASK_TDT_UINT8) elif data_type == 'A' or data_type == 'O' or data_type == 'Q': msg_tx = ibh_const.IBHLinkMSG(b=ibh_const.MPI_READ_WRITE_IO, data_area=ibh_const.OUTPUT_AREA, data_adr=data_address, data_cnt=size, data_type=ibh_const.TASK_TDT_UINT8) elif data_type == 'M': msg_tx = ibh_const.IBHLinkMSG(b=ibh_const.MPI_READ_WRITE_M, data_adr=data_address, data_cnt=size, data_type=ibh_const.TASK_TDT_UINT8) elif data_type == 'D': msg_tx = ibh_const.IBHLinkMSG(b=ibh_const.MPI_READ_WRITE_DB, data_area=offset >> 8, data_idx=offset, data_adr=data_address, data_cnt=size, data_type=ibh_const.TASK_TDT_UINT8) elif size > ibh_const.IBHLINK_READ_MAX / 2: raise ValueError("size > IBHconst.IBHLINK_READ_MAX/2") elif data_type == 'T': # TODO: implementation read 'T' return None elif data_type == 'Z' or data_type == 'C': # TODO: implementation read 'C' return None else: raise ValueError("No valid data type") msg_tx.rx = ibh_const.MPI_TASK msg_tx.tx = ibh_const.HOST msg_tx.ln = ibh_const.TELE_HEADER_SIZE msg_tx.nr = self.msg_number msg_tx.device_adr = self.mpi_address msg_tx.func_code = ibh_const.TASK_TFC_READ self.msg_number += 1 msg_length = ibh_const.MSG_HEADER_SIZE + ibh_const.TELE_HEADER_SIZE self.sendData(bytes(msg_tx)[:msg_length]) raw_bytes = self.receiveData() msg_rx = ibh_const.IBHLinkMSG() msg_rx.receiveSome(raw_bytes) self.received_telegram_check(msg_tx, msg_rx, ibh_const.TELE_HEADER_SIZE + size) if msg_rx.a in [ ibh_const.MPI_READ_WRITE_DB, ibh_const.MPI_READ_WRITE_IO, ibh_const.MPI_READ_WRITE_M ]: list_of_bytes = msg_rx.d[:msg_rx.data_cnt] # type: list return list_of_bytes elif msg_rx.a in [ ibh_const.MPI_READ_WRITE_CNT, ibh_const.MPI_READ_WRITE_TIM ]: list_of_bytes = msg_rx.d[:2 * msg_rx.data_cnt] # type: list return list_of_bytes else: return None