コード例 #1
0
 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'
コード例 #2
0
 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)
コード例 #3
0
 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))
コード例 #4
0
 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)
コード例 #5
0
    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]
コード例 #6
0
    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
コード例 #7
0
    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