9393
9494
9595class MMQTTException (Exception ):
96- """MiniMQTT Exception class."""
96+ """
97+ MiniMQTT Exception class.
98+
99+ Raised for various mostly protocol or network/system level errors.
100+ In general, the robust way to recover is to call reconnect().
101+ """
97102
98103 def __init__ (self , error , code = None ):
99104 super ().__init__ (error , code )
100105 self .code = code
101106
102107
108+ class MMQTTStateError (MMQTTException ):
109+ """
110+ MiniMQTT invalid state error.
111+
112+ Raised e.g. if a function is called in unexpected state.
113+ """
114+
115+
103116class NullLogger :
104117 """Fake logger class that does not do anything"""
105118
@@ -163,7 +176,7 @@ def __init__( # noqa: PLR0915, PLR0913, Too many statements, Too many arguments
163176 self ._use_binary_mode = use_binary_mode
164177
165178 if recv_timeout <= socket_timeout :
166- raise MMQTTException ("recv_timeout must be strictly greater than socket_timeout" )
179+ raise ValueError ("recv_timeout must be strictly greater than socket_timeout" )
167180 self ._socket_timeout = socket_timeout
168181 self ._recv_timeout = recv_timeout
169182
@@ -181,7 +194,7 @@ def __init__( # noqa: PLR0915, PLR0913, Too many statements, Too many arguments
181194 self ._reconnect_timeout = float (0 )
182195 self ._reconnect_maximum_backoff = 32
183196 if connect_retries <= 0 :
184- raise MMQTTException ("connect_retries must be positive" )
197+ raise ValueError ("connect_retries must be positive" )
185198 self ._reconnect_attempts_max = connect_retries
186199
187200 self .broker = broker
@@ -190,7 +203,7 @@ def __init__( # noqa: PLR0915, PLR0913, Too many statements, Too many arguments
190203 if (
191204 self ._password and len (password .encode ("utf-8" )) > MQTT_TOPIC_LENGTH_LIMIT
192205 ): # [MQTT-3.1.3.5]
193- raise MMQTTException ("Password length is too large." )
206+ raise ValueError ("Password length is too large." )
194207
195208 # The connection will be insecure unless is_ssl is set to True.
196209 # If the port is not specified, the security will be set based on the is_ssl parameter.
@@ -286,28 +299,27 @@ def will_set(
286299 """
287300 self .logger .debug ("Setting last will properties" )
288301 if self ._is_connected :
289- raise MMQTTException ("Last Will should only be called before connect()." )
302+ raise MMQTTStateError ("Last Will should only be called before connect()." )
290303
291304 # check topic/msg/qos kwargs
292305 self ._valid_topic (topic )
293306 if "+" in topic or "#" in topic :
294- raise MMQTTException ("Publish topic can not contain wildcards." )
307+ raise ValueError ("Publish topic can not contain wildcards." )
295308
296309 if msg is None :
297- raise MMQTTException ("Message can not be None." )
310+ raise ValueError ("Message can not be None." )
298311 if isinstance (msg , (int , float )):
299312 msg = str (msg ).encode ("ascii" )
300313 elif isinstance (msg , str ):
301314 msg = str (msg ).encode ("utf-8" )
302315 elif isinstance (msg , bytes ):
303316 pass
304317 else :
305- raise MMQTTException ("Invalid message data type." )
318+ raise ValueError ("Invalid message data type." )
306319 if len (msg ) > MQTT_MSG_MAX_SZ :
307- raise MMQTTException (f"Message size larger than { MQTT_MSG_MAX_SZ } bytes." )
320+ raise ValueError (f"Message size larger than { MQTT_MSG_MAX_SZ } bytes." )
308321
309322 self ._valid_qos (qos )
310- assert 0 <= qos <= 1 , "Quality of Service Level 2 is unsupported by this library."
311323
312324 # fixed header. [3.3.1.2], [3.3.1.3]
313325 pub_hdr_fixed = bytearray ([MQTT_PUBLISH | retain | qos << 1 ])
@@ -390,7 +402,7 @@ def username_pw_set(self, username: str, password: Optional[str] = None) -> None
390402
391403 """
392404 if self ._is_connected :
393- raise MMQTTException ("This method must be called before connect()." )
405+ raise MMQTTStateError ("This method must be called before connect()." )
394406 self ._username = username
395407 if password is not None :
396408 self ._password = password
@@ -670,21 +682,22 @@ def publish( # noqa: PLR0912, Too many branches
670682 self ._connected ()
671683 self ._valid_topic (topic )
672684 if "+" in topic or "#" in topic :
673- raise MMQTTException ("Publish topic can not contain wildcards." )
685+ raise ValueError ("Publish topic can not contain wildcards." )
674686 # check msg/qos kwargs
675687 if msg is None :
676- raise MMQTTException ("Message can not be None." )
688+ raise ValueError ("Message can not be None." )
677689 if isinstance (msg , (int , float )):
678690 msg = str (msg ).encode ("ascii" )
679691 elif isinstance (msg , str ):
680692 msg = str (msg ).encode ("utf-8" )
681693 elif isinstance (msg , bytes ):
682694 pass
683695 else :
684- raise MMQTTException ("Invalid message data type." )
696+ raise ValueError ("Invalid message data type." )
685697 if len (msg ) > MQTT_MSG_MAX_SZ :
686- raise MMQTTException (f"Message size larger than { MQTT_MSG_MAX_SZ } bytes." )
687- assert 0 <= qos <= 1 , "Quality of Service Level 2 is unsupported by this library."
698+ raise ValueError (f"Message size larger than { MQTT_MSG_MAX_SZ } bytes." )
699+
700+ self ._valid_qos (qos )
688701
689702 # fixed header. [3.3.1.2], [3.3.1.3]
690703 pub_hdr_fixed = bytearray ([MQTT_PUBLISH | retain | qos << 1 ])
@@ -849,7 +862,7 @@ def unsubscribe( # noqa: PLR0912, Too many branches
849862 topics .append (t )
850863 for t in topics :
851864 if t not in self ._subscribed_topics :
852- raise MMQTTException ("Topic must be subscribed to before attempting unsubscribe." )
865+ raise MMQTTStateError ("Topic must be subscribed to before attempting unsubscribe." )
853866 # Assemble packet
854867 self .logger .debug ("Sending UNSUBSCRIBE to broker..." )
855868 fixed_header = bytearray ([MQTT_UNSUB ])
@@ -959,7 +972,7 @@ def loop(self, timeout: float = 1.0) -> Optional[list[int]]:
959972
960973 """
961974 if timeout < self ._socket_timeout :
962- raise MMQTTException (
975+ raise ValueError (
963976 f"loop timeout ({ timeout } ) must be >= "
964977 + f"socket timeout ({ self ._socket_timeout } ))"
965978 )
@@ -1153,13 +1166,13 @@ def _valid_topic(topic: str) -> None:
11531166
11541167 """
11551168 if topic is None :
1156- raise MMQTTException ("Topic may not be NoneType" )
1169+ raise ValueError ("Topic may not be NoneType" )
11571170 # [MQTT-4.7.3-1]
11581171 if not topic :
1159- raise MMQTTException ("Topic may not be empty." )
1172+ raise ValueError ("Topic may not be empty." )
11601173 # [MQTT-4.7.3-3]
11611174 if len (topic .encode ("utf-8" )) > MQTT_TOPIC_LENGTH_LIMIT :
1162- raise MMQTTException ( "Topic length is too large. " )
1175+ raise ValueError ( f"Encoded topic length is larger than { MQTT_TOPIC_LENGTH_LIMIT } " )
11631176
11641177 @staticmethod
11651178 def _valid_qos (qos_level : int ) -> None :
@@ -1170,16 +1183,16 @@ def _valid_qos(qos_level: int) -> None:
11701183 """
11711184 if isinstance (qos_level , int ):
11721185 if qos_level < 0 or qos_level > 2 :
1173- raise MMQTTException ("QoS must be between 1 and 2." )
1186+ raise NotImplementedError ("QoS must be between 1 and 2." )
11741187 else :
1175- raise MMQTTException ("QoS must be an integer." )
1188+ raise ValueError ("QoS must be an integer." )
11761189
11771190 def _connected (self ) -> None :
11781191 """Returns MQTT client session status as True if connected, raises
1179- a `MMQTTException ` if `False`.
1192+ a `MMQTTStateError exception ` if `False`.
11801193 """
11811194 if not self .is_connected ():
1182- raise MMQTTException ("MiniMQTT is not connected" )
1195+ raise MMQTTStateError ("MiniMQTT is not connected" )
11831196
11841197 def is_connected (self ) -> bool :
11851198 """Returns MQTT client session status as True if connected, False
0 commit comments