62
62
MQTT_PINGRESP = const (0xD0 )
63
63
MQTT_SUB = b"\x82 "
64
64
MQTT_UNSUB = b"\xA2 "
65
- MQTT_PUB = bytearray (b"\x30 \0 " )
66
- # Variable CONNECT header [MQTT 3.1.2]
67
- MQTT_VAR_HEADER = bytearray (b"\x04 MQTT\x04 \x02 \0 \0 " )
65
+ MQTT_PUB = bytearray (b"\x30 " )
68
66
MQTT_DISCONNECT = b"\xe0 \0 "
69
67
68
+ # Variable CONNECT header [MQTT 3.1.2]
69
+ MQTT_HDR_CONNECT = bytearray (b"\x04 MQTT\x04 \x02 \0 \0 " )
70
+
71
+
70
72
CONNACK_ERRORS = {
71
73
const (0x01 ): "Connection Refused - Incorrect Protocol Version" ,
72
74
const (0x02 ): "Connection Refused - ID Rejected" ,
@@ -301,8 +303,11 @@ def connect(self, clean_session=True):
301
303
fixed_header = bytearray ()
302
304
fixed_header .append (0x10 )
303
305
306
+ # NOTE: Variable header is
307
+ # MQTT_HDR_CONNECT = bytearray(b"\x04MQTT\x04\x02\0\0")
308
+ # because final 4 bytes are 4, 2, 0, 0
304
309
# Variable Header
305
- var_header = MQTT_VAR_HEADER
310
+ var_header = MQTT_HDR_CONNECT
306
311
var_header [6 ] = clean_session << 1
307
312
308
313
# Set up variable header and remaining_length
@@ -427,7 +432,6 @@ def publish(self, topic, msg, retain=False, qos=0):
427
432
.. code-block:: python
428
433
429
434
mqtt_client.publish('topics/piVal', 'threepointonefour')
430
-
431
435
"""
432
436
self .is_connected ()
433
437
self ._check_topic (topic )
@@ -443,42 +447,52 @@ def publish(self, topic, msg, retain=False, qos=0):
443
447
else :
444
448
raise MMQTTException ("Invalid message data type." )
445
449
if len (msg ) > MQTT_MSG_MAX_SZ :
446
- raise MMQTTException ("Message size larger than %db." % MQTT_MSG_MAX_SZ )
447
- self ._check_qos (qos )
448
- pkt = MQTT_PUB
449
- pkt [0 ] |= qos << 1 | retain
450
- sz = 2 + len (topic ) + len (msg )
450
+ raise MMQTTException ("Message size larger than %d bytes." % MQTT_MSG_MAX_SZ )
451
+ assert (
452
+ 0 <= qos <= 1
453
+ ), "Quality of Service Level 2 is unsupported by this library."
454
+
455
+ pub_hdr_fixed = bytearray () # fixed header
456
+ pub_hdr_fixed .extend (MQTT_PUB )
457
+ pub_hdr_fixed [0 ] |= retain | qos << 1 # [3.3.1.2], [3.3.1.3]
458
+
459
+ pub_hdr_var = bytearray () # variable header
460
+ pub_hdr_var .append (len (topic ) >> 8 ) # Topic length, MSB
461
+ pub_hdr_var .append (len (topic ) & 0xFF ) # Topic length, LSB
462
+ pub_hdr_var .extend (topic .encode ("utf-8" )) # Topic name
463
+
464
+ remaining_length = 2 + len (msg ) + len (topic )
451
465
if qos > 0 :
452
- sz += 2
453
- assert sz < 2097152
454
- i = 1
455
- while sz > 0x7F :
456
- pkt [i ] = (sz & 0x7F ) | 0x80
457
- sz >>= 7
458
- i += 1
459
- pkt [i ] = sz
466
+ # packet identifier where QoS level is 1 or 2. [3.3.2.2]
467
+ pid = self ._pid
468
+ remaining_length += 2
469
+ pub_hdr_var .append (0x00 )
470
+ pub_hdr_var .append (self ._pid )
471
+ self ._pid += 1
472
+
473
+ # Calculate remaining length [2.2.3]
474
+ if remaining_length > 0x7F :
475
+ while remaining_length > 0 :
476
+ encoded_byte = remaining_length % 0x80
477
+ remaining_length = remaining_length // 0x80
478
+ if remaining_length > 0 :
479
+ encoded_byte |= 0x80
480
+ pub_hdr_fixed .append (encoded_byte )
481
+ else :
482
+ pub_hdr_fixed .append (remaining_length )
483
+
460
484
if self .logger is not None :
461
485
self .logger .debug (
462
486
"Sending PUBLISH\n Topic: {0}\n Msg: {1}\
463
487
\n QoS: {2}\n Retain? {3}" .format (
464
488
topic , msg , qos , retain
465
489
)
466
490
)
467
- self ._sock .send (pkt )
468
- self ._send_str (topic )
469
- if qos == 0 :
470
- if self .on_publish is not None :
471
- self .on_publish (self , self .user_data , topic , self ._pid )
472
- if qos > 0 :
473
- self ._pid += 1
474
- pid = self ._pid
475
- struct .pack_into ("!H" , pkt , 0 , pid )
476
- self ._sock .send (pkt )
477
- if self .on_publish is not None :
478
- self .on_publish (self , self .user_data , topic , pid )
479
- if self .logger is not None :
480
- self .logger .debug ("Sending PUBACK" )
491
+ self ._sock .send (pub_hdr_fixed )
492
+ self ._sock .send (pub_hdr_var )
481
493
self ._sock .send (msg )
494
+ if qos == 0 and self .on_publish is not None :
495
+ self .on_publish (self , self .user_data , topic , self ._pid )
482
496
if qos == 1 :
483
497
while True :
484
498
op = self ._wait_for_msg ()
@@ -491,10 +505,6 @@ def publish(self, topic, msg, retain=False, qos=0):
491
505
if self .on_publish is not None :
492
506
self .on_publish (self , self .user_data , topic , rcv_pid )
493
507
return
494
- elif qos == 2 :
495
- assert 0
496
- if self .on_publish is not None :
497
- self .on_publish (self , self .user_data , topic , rcv_pid )
498
508
499
509
def subscribe (self , topic , qos = 0 ):
500
510
"""Subscribes to a topic on the MQTT Broker.
0 commit comments