def pubcomp(self, messageId): # LOG.warn('Sending pubcomp packet') header = bytearray() varHeader = bytearray() header.append(0x07 << 4) varHeader.extend(EncodeDecode._encodeValue(messageId)) header.extend(EncodeDecode._encodeLength(len(varHeader))) self.transport.write(header) self.transport.write(varHeader)
def unsuback(self, messageId): # LOG.info("Sending unsuback packet") header = bytearray() varHeader = bytearray() header.append(0x0B << 4) varHeader.extend(EncodeDecode._encodeValue(messageId)) header.extend(EncodeDecode._encodeLength(len(varHeader))) self.transport.write(header) self.transport.write(varHeader)
def _event_unsubscribe(self, packet, _qos, _dup, _retain): LOG.info('Event Unsubscribe received: {} {}'.format( len(packet), packet)) messageId = EncodeDecode._decodeValue(packet[:2]) packet = packet[2:] # Extract the unsubscribing topics topics = [] while len(packet): topic = EncodeDecode._decodeString(packet) packet = packet[len(topic) + 2:] topics.append(topic) LOG.info('Mqtt UnSubscribe: {}'.format(topics)) self.unsubscribeReceived(topics, messageId)
def suback(self, grantedQos, messageId): # LOG.info("Sending suback packet") header = bytearray() varHeader = bytearray() payload = bytearray() header.append(0x09 << 4) varHeader.extend(EncodeDecode._encodeValue(messageId)) for i in grantedQos: payload.append(i) header.extend( EncodeDecode._encodeLength(len(varHeader) + len(payload))) self.transport.write(header) self.transport.write(varHeader) self.transport.write(payload)
def _event_subscribe(self, packet, qos, _dup, _retain): LOG.info('ProtocolEvent "Subscribe Packet" received: {} {}'.format( len(packet), packet)) messageId = EncodeDecode._decodeValue(packet[:2]) packet = packet[2:] topics = [] while len(packet): topic = EncodeDecode._decodeString(packet) packet = packet[len(topic) + 2:] qos = packet[0] packet = packet[1:] # Add them to the list of (topic, qos)s topics.append((topic, qos)) LOG.info('Mqtt Subscribe: {}'.format(topics)) self.subscribeReceived(topics, messageId)
def _event_puback(self, packet, _qos, _dup, _retain): LOG.info( 'ProtocolEvent "PubAck Packet" received: {} {}\n\tAddr:{}'.format( len(packet), packet, self.m_broker.Host.Name)) # Extract the message ID messageId = EncodeDecode._decodeValue(packet[:2]) self.pubackReceived(messageId)
def unsubscribe(self, topic, messageId=None): # LOG.info("Sending unsubscribe packet") header = bytearray() varHeader = bytearray() payload = bytearray() header.append(0x0A << 4 | 0x01 << 1) if messageId is not None: varHeader.extend(EncodeDecode._encodeValue(self.messageID)) else: varHeader.extend( EncodeDecode._encodeValue(random.randint(1, 0xFFFF))) payload.extend(EncodeDecode._encodeString(topic)) header.extend( EncodeDecode._encodeLength(len(payload) + len(varHeader))) self.transport.write(header) self.transport.write(varHeader) self.transport.write(payload)
def _event_suback(self, packet, _qos, _dup, _retain): messageId = EncodeDecode._decodeValue(packet[:2]) packet = packet[2:] # LOG.info('Event SubAck received - MsgID:{} Acks: {} {}\n\tAddr:{}'.format(messageId, len(packet), packet, self.m_broker.Host.Name)) # Extract the granted QoS levels grantedQos = [] while len(packet): grantedQos.append(packet[0]) packet = packet[1:] self.subackReceived(grantedQos, messageId)
def _build_fixed_header(self, p_packet_type, p_remaining_length, dup=0, qosLevel=0, retain=0): l_header = bytearray() l_header.append((p_packet_type & 0x0f) << 4 | (dup & 0x01) << 3 | (qosLevel & 0x03) << 1 | (retain & 0x01)) l_header.extend(EncodeDecode._encodeLength(p_remaining_length)) return l_header
def subscribe(self, p_topic, requestedQoS=0, messageId=None): """ Only supports QoS = 0 subscribes Only supports one subscription per message """ # LOG.info("Sending subscribe packet - Topic: {}\n\tAddr: {}".format(p_topic, self.m_broker.Host.Name)) l_varHeader = bytearray() l_payload = bytearray() # Type = subscribe, QoS = 1 if messageId is None: l_varHeader.extend( EncodeDecode._encodeValue(random.randint(1, 0xFFFF))) else: l_varHeader.extend(EncodeDecode._encodeValue(messageId)) l_payload.extend(EncodeDecode._encodeString(p_topic)) l_payload.append(requestedQoS) l_fixHeader = self._build_fixed_header(0x08, len(l_varHeader) + len(l_payload), qosLevel=1) self._send_transport(l_fixHeader, l_varHeader, l_payload)
def _event_publish(self, packet, qos, dup, retain): """ Receive a "Published" message Here we get a published message from the broker. Extract the parts of the packet. @param packet: is a bytearray containing the variable header and payload combined. """ # Extract the topic portion of the packet. l_topic = EncodeDecode._decodeString(packet) packet = packet[len(l_topic) + 2:] # Extract the message ID if appropriate messageId = None if qos > 0: messageId = EncodeDecode._decodeValue(packet[:2]) packet = packet[2:] LOG.debug('Publish MsgID:{}'.format(messageId)) # Extract whatever remains as the message l_json = EncodeDecode._get_string(packet) # l_json = packet.decode('utf-8') l_message = json_tools.decode_json_unicode(l_json) # l_topic is a string # l_message is a string self.publishReceived(l_topic, l_message, qos, dup, retain, messageId)
def publish(self, p_topic, p_message, qosLevel=0, retain=False, dup=False, messageId=None): # LOG.info("Sending publish packet\n\tTopic: {};\n\tHost: {};".format(p_topic, self.m_broker.Host.Name)) l_varHeader = bytearray() l_payload = bytearray() # Type = publish l_varHeader.extend(EncodeDecode._encodeString(p_topic)) if qosLevel > 0: if messageId is not None: l_varHeader.extend(EncodeDecode._encodeValue(messageId)) else: l_varHeader.extend( EncodeDecode._encodeValue(random.randint(1, 0xFFFF))) l_payload.extend(EncodeDecode._put_string(p_message)) # l_payload.extend(p_message) l_fixHeader = self._build_fixed_header( 0x03, len(l_varHeader) + len(l_payload), dup, qosLevel, retain) self._send_transport(l_fixHeader, l_varHeader, l_payload)
def _accumulatePacket(self, p_data): """ Get 1 packet. Packet format: Fixed Header(2 - 5 bytes) Variable Header (0 - 268,435,455 bytes) Fixed Header: Various Flags: 1 Byte RemainingLength = 1-4 Bytes Variable Header: : """ self.m_buffer.extend(p_data) l_RemainingLength = None while len(self.m_buffer): if l_RemainingLength is None: # Start on a new packet if len(self.m_buffer) < 2: break # Haven't got enough data to start a new packet, wait for some more l_rl_len = 1 # Initial length of the RemainingLength field. # get the variable length RemainingLength field while l_rl_len < len( self.m_buffer ): # Find the bytes in the RemainingLength field. if not self.m_buffer[l_rl_len] & 0x80: break # We have the full RemainingLength field l_rl_len += 1 # Field is longer - get another byte # Get the variable part - We still haven't got all of the remaining length field so quit and wait for another chunk if l_rl_len < len(self.m_buffer) and self.m_buffer[ l_rl_len] & 0x80: # Is there more to to come of the RemainingLength field? LOG.debug( '### Early return - Another chunk is needed {}'.format( FormatBytes(self.m_buffer))) return l_RemainingLength = EncodeDecode._decodeLength( self.m_buffer[1:]) l_FixedHeaderLength = l_rl_len + 1 # Length of the fixed Header portion of the packet l_PacketLength = l_FixedHeaderLength + +l_RemainingLength if len(self.m_buffer) >= l_PacketLength: l_one_message_packet = self.m_buffer[:l_PacketLength] self._processPacket(l_one_message_packet) self.m_buffer = self.m_buffer[l_PacketLength:] l_RemainingLength = None else: # LOG.debug('### exit without processing\n\t{}'.format(FormatBytes(self.m_buffer))) break
def _event_connect(self, packet, _qos, _dup, _retain): """This will decode a received 'connect' packet. """ LOG.info('ProtocolEvent "Connect Packet" received.') # Strip variable header packet = packet[10:] # Extract the connect flags f_username = packet[0] & 0x80 == 0x80 f_password = packet[0] & 0x40 == 0x40 f_willRetain = packet[0] & 0x20 == 0x20 l_willQos = packet[0] & 0x18 >> 3 f_willFlag = packet[0] & 0x04 == 0x04 f_cleanStart = packet[0] & 0x02 == 0x02 packet = packet[1:] keepalive = EncodeDecode._decodeValue( packet[:2]) # Extract the keepalive period packet = packet[2:] clientID = EncodeDecode._decodeString( packet) # Extract the client id_event_connect packet = packet[len(clientID) + 2:] # Extract the will topic and message, if applicable l_willTopic = None l_willMessage = None if f_willFlag: # Extract the will topic l_willTopic = EncodeDecode._decodeString(packet) packet = packet[len(l_willTopic) + 2:] # Extract the will message # Whatever remains is the will message # ## l_willMessage = packet l_willMessage = EncodeDecode._decodeString(packet) packet = packet[len(l_willMessage) + 2:] l_username = None if f_username: # Extract user name if one is present. l_username = EncodeDecode._decodeString(packet) packet = packet[len(l_username) + 2:] l_password = None if f_password: # Extract password if one is present. l_password = EncodeDecode._decodeString(packet) packet = packet[len(l_password) + 2:] LOG.info('Mqtt Connected.') self.connectReceived(clientID, keepalive, l_willTopic, l_willMessage, l_willQos, f_willRetain, f_cleanStart, l_username, l_password)
def _build_connect(self, p_broker, p_mqtt): """ Build a Mqtt "Connect" Packet. This is the first packet sent after the TCP handshake establishing the network connection. This is used to establish the Mqtt Protocol connection and login. """ l_varHeader = bytearray() l_payload = bytearray() l_varHeader.extend(EncodeDecode._encodeString("MQTT")) l_varHeader.append(4) varLogin = 0 if p_broker.UserName is not None: varLogin += 2 if p_broker.Password is not None: varLogin += 1 if p_broker.WillMessage is None or p_broker.WillMessage == '' or p_broker.WillTopic is None: # Clean start, no will message l_varHeader.append(varLogin << 6 | 0 << 2 | 1 << 1) else: l_varHeader.append(varLogin << 6 | p_broker.WillRetain << 5 | p_broker.WillQoS << 3 | 1 << 2 | 1 << 1) l_varHeader.extend( EncodeDecode._encodeValue(int(p_broker.Keepalive / 1000))) l_payload.extend(EncodeDecode._encodeString(p_mqtt.ClientID)) if (p_broker.WillMessage is not None or p_broker.WillMessage != '') and p_broker.WillTopic is not None: # LOG.debug('Adding last will testiment {}'.format(p_broker.WillMessage + p_broker.WillTopic)) l_payload.extend(EncodeDecode._encodeString(p_broker.WillTopic)) l_payload.extend(EncodeDecode._encodeString(p_broker.WillMessage)) if p_broker.UserName is not None and len(p_broker.UserName) > 0: LOG.debug('Adding username "{}"'.format(p_broker.UserName)) l_payload.extend(EncodeDecode._encodeString(p_broker.UserName)) if p_broker.Password is not None and len(p_broker.Password) > 0: LOG.debug('Adding password "{}"'.format(p_broker.Password)) l_payload.extend(EncodeDecode._encodeString(p_broker.Password)) l_fixHeader = self._build_fixed_header( 0x01, len(l_varHeader) + len(l_payload)) return (l_fixHeader, l_varHeader, l_payload)
def disconnect(self): LOG.info("Sending disconnect packet") header = bytearray() header.append(0x0E << 4) header.extend(EncodeDecode._encodeLength(0)) self.transport.write(header)
def _event_pubcomp(self, packet, _qos, _dup, _retain): LOG.info('Event PubComp received: {} {}'.format(len(packet), packet)) messageId = EncodeDecode._decodeValue(packet[:2]) self.pubcompReceived(messageId)
def pingresp(self): LOG.warn('Got ping ack packet') header = bytearray() header.append(0x0D << 4) header.extend(EncodeDecode._encodeLength(0)) self.transport.write(header)
def _event_unsuback(self, packet, _qos, _dup, _retain): LOG.info('Event UnsubAck received: {} {}'.format(len(packet), packet)) messageId = EncodeDecode._decodeValue(packet[:2]) self.unsubackReceived(messageId)