Example #1
0
    def read_float(self, file_table=8, start=0, total_float=1) -> list():
        """
         Read data from floats file table starting with 'start' offset

         :param file_table: file table used for register, default =8
         :param start: starting address, default =0
         :param total_float: total of floats (32 bits) to read
         :return: list of values if success, otherwise return [] or raise exception
        ;        .data => list of words/status of bits if success or raise exception in case of error
         """
        self.read_ok = False
        command = self.create_command(Command0FA2, bytes_to_read=total_float * 4, table=file_table,
                                      file_type=FileType.FLOAT, start=start, start_sub=0x00)
        try:
            reply = self.send_command(command)

        except Exception as e:
            print('[ERROR] Read float error',e)
            raise SendReceiveError()

        values = reply.get_data(FileType.FLOAT)
        self.read_ok = len(values) > 0 and command.tns == reply.tns
        if self.read_ok:
            self.data = values
        else:
            self.data =[]
        return self.data
Example #2
0
    def read_binary(self, file_table=3, start=0, bit=BIT.ALL, total_int=1) -> list():
        """
         Read data from binary file table starting with 'start' offset

         :param file_table: file table used for binary, default =3
         :param start: starting address, default =0
         :param bit: define which specific bit or all bits want to read from words, e.g: BIT.BIT0, BIT.ALL
         :param total_int: total of words (16 bits) to read
         :return: true if success, otherwise false
        ;        .data => list of words/status of bits if success or raise exception in case of error
         """
        self.read_ok = False
        command = self.create_command(Command0FA2, bytes_to_read=total_int * 2, table=file_table,
                                      file_type=FileType.BIT, start=start, start_sub=0x00)

        try:
            reply = self.send_command(command)
        except Exception as e:
            print('[ERROR] Read binary error',e)
            raise SendReceiveError()

        # Parsing based on the Category
        values = list()
        if bit == BIT.ALL:  # return all integers as shown
            values = reply.get_data(FileType.INTEGER)
        else:  # related individual bits
            for data in reply.get_data(FileType.INTEGER):
                status = data >> bit.value & 1
                values.append(status)
        self.read_ok = len(values) > 0 and command.tns == reply.tns
        if self.read_ok:
            self.data = values
        else:
            self.data = []
        return self.data
Example #3
0
    def read_counter(self, file_table=5, start=0, category=COUNTER.ACC, total_int=1) -> list():
        """
          Read data from counters file table starting with 'start' offset

          :param file_table: file table used for counter, default =5
          :param start: starting address, default =0
          :param category: define category to get, e.g: COUNTER.CU,.CD,.DN,.OV,.UN,.UA,.PRE,.ACC,.STATUS (entire word)
          :param total_int: total of words (16 bits) to read
          :return: list of values if success, otherwise return [] or raise exception
        ;        .data => list of words/status of bits if success or raise exception in case of error
          """
        self.read_ok = False
        # Based on category determine the Sub
        sub = 0  # are bits  (CU,CD,DN,OV,UN,UA) or all of them in Status
        if category == COUNTER.PRE:
            sub = 1
        elif category == COUNTER.ACC:
            sub = 2
        command = self.create_command(Command0FA2, bytes_to_read=total_int * 2, table=file_table,
                                      file_type=FileType.COUNTER, start=start, start_sub=sub)
        try:
            reply = self.send_command(command)
        except Exception as e:
            print('[ERROR] Read counter error',e)
            raise SendReceiveError()

        # Parsing based on the Category
        values = list()
        if category in {COUNTER.PRE, COUNTER.ACC}:  # return all integers as shown
            values = reply.get_data(FileType.INTEGER)
        else:  # related with status or individual bits
            for data in reply.get_data(FileType.INTEGER):
                status = data >> 10  # the result of this are 6 bits on right side EN TI DN XX

                if category == COUNTER.CU:
                    status = status >> 5 & 1
                elif category == COUNTER.CD:
                    status = status >> 4 & 1
                elif category == COUNTER.DN:
                    status = status >> 3 & 1
                elif category == COUNTER.OV:
                    status = status >> 2 & 1
                elif category == COUNTER.UN:
                    status = status >> 1 & 1
                elif category == COUNTER.UA:
                    status = status & 1

                values.append(status)
        self.read_ok = len(values) > 0 and command.tns == reply.tns
        if self.read_ok:
            self.data = values
        else:
            self.data =[]
        return self.data
Example #4
0
    def send_command(self, command):
        """
        Send the command, created by create_command

        :param command: created by created_command
        :return: list of values or raise exception in case of error
        """
        """Doc page 4-6 Transmitter"""
        # print('Sending Command')
        for __ in range(3):  # 3
            # print('retry')
            # wait for any pending command to avoid conflict with other previous commands
            # make sure only one command is processing at a time
            self.wait_no_pending_command()

            # While clear any communication wth PLC hold any send command
            self.wait_while_com_clear()

            self.comm_history.append({'direction': 'out', 'command': command})

            self._command_sent = command  # record the command sent to compare with the tns of the message received

            self._plc.send_bytes(command.get_bytes())

            retry_send = False
            got_ack = False
            i = 0
            while i < 3:  # 3
                reply = self._expect_message()
                # print('reply',reply, type(reply))
                if type(reply) is ReplyAck:
                    got_ack = True
                    # self._send_ack()  # Added - Send Ack to PLC on time, this allow PLC knows we received the data
                    i = 0
                elif type(reply) is ReplyNak:
                    command.tns = self._get_new_tns()
                    retry_send = True
                elif type(reply) is ReplyTimeout or not reply.is_valid():
                    print('[ERROR] Error send command', reply)
                    if got_ack:
                        self._send_nak()
                    else:
                        self._send_enq()
                    break  # exit retry loop
                elif got_ack:
                    # validate if this reply correspond to the command using transaction number (TNS),
                    # otherwise drop it and keep trying
                    if self._command_sent.tns == reply.tns:  # Important to check the transaction #, otherwise drop it
                        return reply
                    else:
                        # This could happened or either bad response from PLC or something happened with the queue
                        # drop this message and Starting all over again
                        self._messages_dropped += 1
                        print(f'[ERROR]**** Message dropped- CMD TNS:{self._command_sent.tns} Reply TNS:{reply.tns} ')
                        # try one more time
                        got_ack = False
                        i=0

                i += 1
                if self._seq_sleep_time>0:
                    time.sleep(self._seq_sleep_time)

            if not retry_send:
                self._plc.clear_buffer() # try to clear any buffer for retrying
                raise SendReceiveError()

        raise SendReceiveError()