예제 #1
0
    def send_param_command_packet(self, command_tuple, param_tuple=None, param_type_tuple=0,ack=True):
        
        """
        Send a command packet with parameters. Ack channel is optional for future flexibility,
        but currently commands are always send over the Ack channel so it defaults to True.

        Contributed by awm102 on github

        :param: command_tuple: the command tuple derived from command_parser.get_command_tuple()
        :param: param_tuple (optional): the parameter values to be sent (can be found in the XML files)
        :param: param_size_tuple (optional): a tuple of strings representing the data type of the parameters
        e.g. u8, float etc. (can be found in the XML files)
        :param: ack (optional): allows ack to be turned off if required
        :return:
        """
# TODO: This function could potentially be extended to encompass send_noparam_command_packet_ack
# and send_enum_command_packet_ack if desired for more modular code.
# TODO: The function could be improved by looking up the parameter data types in the xml files
# in the same way the send_enum_command_packet_ack does. 

        # Create lists to store the number of bytes and pack chars needed for parameters
        # Default them to zero so that if no params are provided the packet size is correct 
        param_size_list = [0] * len(param_tuple)
        pack_char_list = [0] * len(param_tuple)
        
        if param_tuple is not None:
            # Fetch the parameter sizes. By looping over the param_tuple we only get the data
            # for requested parameters so a mismatch in params and types does not matter
            for i,param in enumerate(param_tuple):
                pack_char_list[i], param_size_list[i] = get_data_format_and_size(param, param_type_tuple[i])
            
        if ack:
            ack_string = 'SEND_WITH_ACK'
            data_ack_string = 'DATA_WITH_ACK'
        else:
            ack_string = 'SEND_NO_ACK'
            data_ack_string = 'DATA_NO_ACK'

        # Construct the base packet
        self.sequence_counter[ack_string] = (self.sequence_counter[ack_string] + 1) % 256

        # Calculate packet size:
        # base packet <BBBIBBH is 11 bytes, param_size_list can be added up
        packet_size = 11 + sum(param_size_list)
        
        packet = struct.pack("<BBBIBBH", self.data_types_by_name[data_ack_string],
                             self.buffer_ids[ack_string],
                             self.sequence_counter[ack_string], packet_size,
                             command_tuple[0], command_tuple[1], command_tuple[2])

        if param_tuple is not None:
            # Add in the parameter values based on their sizes
            for i,param in enumerate(param_tuple):
                packet += struct.pack(pack_char_list[i],param)
        if ack:
            return self.send_command_packet_ack(packet, self.sequence_counter['SEND_WITH_ACK'])
        else:
            return self.send_command_packet_noack(packet)
예제 #2
0
    def send_param_command_packet(self,
                                  command_tuple,
                                  param_tuple=None,
                                  param_type_tuple=0,
                                  ack=True):
        """
        Send a command packet with parameters. Ack channel is optional for future flexibility,
        but currently commands are always send over the Ack channel so it defaults to True.

        Contributed by awm102 on github.  Edited by Amy McGovern to work for BLE commands also.

        :param: command_tuple: the command tuple derived from command_parser.get_command_tuple()
        :param: param_tuple (optional): the parameter values to be sent (can be found in the XML files)
        :param: param_size_tuple (optional): a tuple of strings representing the data type of the parameters
        e.g. u8, float etc. (can be found in the XML files)
        :param: ack (optional): allows ack to be turned off if required
        :return:
        """
        # Create lists to store the number of bytes and pack chars needed for parameters
        # Default them to zero so that if no params are provided the packet size is correct
        param_size_list = [0] * len(param_tuple)
        pack_char_list = [0] * len(param_tuple)

        if param_tuple is not None:
            # Fetch the parameter sizes. By looping over the param_tuple we only get the data
            # for requested parameters so a mismatch in params and types does not matter
            for i, param in enumerate(param_tuple):
                pack_char_list[i], param_size_list[
                    i] = get_data_format_and_size(param, param_type_tuple[i])

        if ack:
            ack_string = 'SEND_WITH_ACK'
            data_ack_string = 'DATA_WITH_ACK'
        else:
            ack_string = 'SEND_NO_ACK'
            data_ack_string = 'DATA_NO_ACK'

        # Construct the base packet
        self.characteristic_send_counter['SEND_WITH_ACK'] = (
            self.characteristic_send_counter['SEND_WITH_ACK'] + 1) % 256

        # TODO:  Amy changed this to match the BLE packet structure but needs to fully test it
        packet = struct.pack("<BBBBH", self.data_types[data_ack_string],
                             self.characteristic_send_counter[ack_string],
                             command_tuple[0], command_tuple[1],
                             command_tuple[2])

        if param_tuple is not None:
            # Add in the parameter values based on their sizes
            for i, param in enumerate(param_tuple):
                packet += struct.pack(pack_char_list[i], param)

        # TODO: Fix this to not go with ack always
        return self.send_command_packet_ack(packet)