Files
adminandClaude Opus 5 79843aa2ae SolarManager unter Versionsverwaltung
Erster Stand der Hintergrundprozesse, die auf der Synology unter
/volume1/homes/wagner/SolarManager laufen: der Manager selbst, die Sammler
je Geraet, die MQTT-Bruecke, der Wecker und - neu hinzugezogen - der
AutoAction-Runner, der als Hintergrundprozess hierher gehoert und nicht ins
Web-Verzeichnis.

Zugangsdaten stehen nicht mehr im Quelltext, sondern in config.ini, die
nicht mit eingecheckt wird. Vorlage ist config.ini.example, gelesen wird sie
von konfig.py. Betroffen waren solarManager.py (Datenbank und Wattpilot),
zeit.py, gatherWaterData.py, wecker.py und skoda_testdaten.py, das sich das
Passwort bisher aus dem Quelltext eines anderen Moduls herausgesucht hat.

Die Kia-Anbindung ist mit dem Fahrzeug entfallen: kiaTest.py,
gatherCarData.py und hyundai_kia_connect_api sind nicht mehr dabei, ebenso
gatherInverterData.py, auf das nur noch eine auskommentierte Zeile zeigte.

Die mitgelieferten Bibliotheken bleiben im Repository - die NAS hat kein
pip, sie muessen neben den Skripten liegen.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-02 20:46:59 +02:00

1022 lines
36 KiB
Python

import threading
import time
import unicodedata
import paho.mqtt.client as client
import pytest
from paho.mqtt.enums import CallbackAPIVersion, MQTTErrorCode, MQTTProtocolVersion
from paho.mqtt.packettypes import PacketTypes
from paho.mqtt.properties import Properties
from paho.mqtt.reasoncodes import ReasonCode
import tests.paho_test as paho_test
# Import test fixture
from tests.testsupport.broker import FakeBroker, fake_broker # noqa: F401
@pytest.mark.parametrize("proto_ver,callback_version", [
(MQTTProtocolVersion.MQTTv31, CallbackAPIVersion.VERSION1),
(MQTTProtocolVersion.MQTTv31, CallbackAPIVersion.VERSION2),
(MQTTProtocolVersion.MQTTv311, CallbackAPIVersion.VERSION1),
(MQTTProtocolVersion.MQTTv311, CallbackAPIVersion.VERSION2),
])
class Test_connect:
"""
Tests on connect/disconnect behaviour of the client
"""
def test_01_con_discon_success(self, proto_ver, callback_version, fake_broker):
mqttc = client.Client(
callback_version,
"01-con-discon-success",
protocol=proto_ver,
transport=fake_broker.transport,
)
def on_connect(mqttc, obj, flags, rc_or_reason_code, properties_or_none=None):
assert rc_or_reason_code == 0
mqttc.disconnect()
mqttc.on_connect = on_connect
mqttc.connect_async("localhost", fake_broker.port)
mqttc.loop_start()
try:
fake_broker.start()
connect_packet = paho_test.gen_connect(
"01-con-discon-success", keepalive=60,
proto_ver=proto_ver)
packet_in = fake_broker.receive_packet(1000)
assert packet_in # Check connection was not closed
assert packet_in == connect_packet
connack_packet = paho_test.gen_connack(rc=0)
count = fake_broker.send_packet(connack_packet)
assert count # Check connection was not closed
assert count == len(connack_packet)
disconnect_packet = paho_test.gen_disconnect()
packet_in = fake_broker.receive_packet(1000)
assert packet_in # Check connection was not closed
assert packet_in == disconnect_packet
finally:
mqttc.loop_stop()
packet_in = fake_broker.receive_packet(1)
assert not packet_in # Check connection is closed
def test_01_con_failure_rc(self, proto_ver, callback_version, fake_broker):
mqttc = client.Client(
callback_version, "01-con-failure-rc",
protocol=proto_ver, transport=fake_broker.transport)
def on_connect(mqttc, obj, flags, rc_or_reason_code, properties_or_none=None):
assert rc_or_reason_code > 0
assert rc_or_reason_code != 0
if callback_version == CallbackAPIVersion.VERSION1:
assert rc_or_reason_code == 1
else:
assert rc_or_reason_code == ReasonCode(PacketTypes.CONNACK, "Unsupported protocol version")
mqttc.on_connect = on_connect
mqttc.connect_async("localhost", fake_broker.port)
mqttc.loop_start()
try:
fake_broker.start()
connect_packet = paho_test.gen_connect(
"01-con-failure-rc", keepalive=60,
proto_ver=proto_ver)
packet_in = fake_broker.receive_packet(1000)
assert packet_in # Check connection was not closed
assert packet_in == connect_packet
connack_packet = paho_test.gen_connack(rc=1)
count = fake_broker.send_packet(connack_packet)
assert count # Check connection was not closed
assert count == len(connack_packet)
packet_in = fake_broker.receive_packet(1)
assert not packet_in # Check connection is closed
finally:
mqttc.loop_stop()
def test_connection_properties(self, proto_ver, callback_version, fake_broker):
mqttc = client.Client(
CallbackAPIVersion.VERSION2, "client-id",
protocol=proto_ver, transport=fake_broker.transport)
mqttc.enable_logger()
is_connected = threading.Event()
is_disconnected = threading.Event()
def on_connect(mqttc, obj, flags, rc, properties):
assert rc == 0
is_connected.set()
def on_disconnect(*args):
import logging
logging.info("disco")
is_disconnected.set()
mqttc.on_connect = on_connect
mqttc.on_disconnect = on_disconnect
mqttc.host = "localhost"
mqttc.connect_timeout = 7
mqttc.port = fake_broker.port
mqttc.keepalive = 7
mqttc.max_inflight_messages = 7
mqttc.max_queued_messages = 7
mqttc.transport = fake_broker.transport
mqttc.username = "username"
mqttc.password = "password"
mqttc.reconnect()
# As soon as connection try to be established, no longer accept updates
with pytest.raises(RuntimeError):
mqttc.host = "localhost"
mqttc.loop_start()
try:
fake_broker.start()
connect_packet = paho_test.gen_connect(
"client-id",
keepalive=7,
username="username",
password="password",
proto_ver=proto_ver,
)
packet_in = fake_broker.receive_packet(1000)
assert packet_in # Check connection was not closed
assert packet_in == connect_packet
connack_packet = paho_test.gen_connack(rc=0)
count = fake_broker.send_packet(connack_packet)
assert count # Check connection was not closed
assert count == len(connack_packet)
is_connected.wait()
# Check that all connections related properties can't be updated
with pytest.raises(RuntimeError):
mqttc.host = "localhost"
with pytest.raises(RuntimeError):
mqttc.connect_timeout = 7
with pytest.raises(RuntimeError):
mqttc.port = fake_broker.port
with pytest.raises(RuntimeError):
mqttc.keepalive = 7
with pytest.raises(RuntimeError):
mqttc.max_inflight_messages = 7
with pytest.raises(RuntimeError):
mqttc.max_queued_messages = 7
with pytest.raises(RuntimeError):
mqttc.transport = fake_broker.transport
with pytest.raises(RuntimeError):
mqttc.username = "username"
with pytest.raises(RuntimeError):
mqttc.password = "password"
# close the connection, but from broker
fake_broker.finish()
is_disconnected.wait()
assert not mqttc.is_connected()
# still not allowed to update, because client try to reconnect in background
with pytest.raises(RuntimeError):
mqttc.host = "localhost"
mqttc.disconnect()
# Now it's allowed, connection is closing AND not trying to reconnect
mqttc.host = "localhost"
finally:
mqttc.loop_stop()
class Test_connect_v5:
"""
Tests on connect/disconnect behaviour of the client with MQTTv5
"""
def test_01_broker_no_support(self, fake_broker):
mqttc = client.Client(
CallbackAPIVersion.VERSION2, "01-broker-no-support",
protocol=MQTTProtocolVersion.MQTTv5, transport=fake_broker.transport)
def on_connect(mqttc, obj, flags, reason, properties):
assert reason == 132
assert reason == ReasonCode(client.CONNACK >> 4, aName="Unsupported protocol version")
mqttc.disconnect()
mqttc.on_connect = on_connect
mqttc.connect_async("localhost", fake_broker.port)
mqttc.loop_start()
try:
fake_broker.start()
# Can't test the connect_packet, we can't yet generate MQTTv5 packet.
# connect_packet = paho_test.gen_connect(
# "01-con-discon-success", keepalive=60,
# proto_ver=client.MQTTv311)
packet_in = fake_broker.receive_packet(1000)
assert packet_in # Check connection was not closed
# assert packet_in == connect_packet
# The reply packet is a MQTTv3 connack. But that the propose of this test,
# ensure client convert it to a reason code 132 "Unsupported protocol version"
connack_packet = paho_test.gen_connack(rc=1)
count = fake_broker.send_packet(connack_packet)
assert count # Check connection was not closed
assert count == len(connack_packet)
packet_in = fake_broker.receive_packet(1)
assert not packet_in # Check connection is closed
finally:
mqttc.loop_stop()
class TestConnectionLost:
def test_with_loop_start(self, fake_broker: FakeBroker):
mqttc = client.Client(
CallbackAPIVersion.VERSION1,
"test_with_loop_start",
protocol=MQTTProtocolVersion.MQTTv311,
reconnect_on_failure=False,
transport=fake_broker.transport
)
on_connect_reached = threading.Event()
on_disconnect_reached = threading.Event()
def on_connect(mqttc, obj, flags, rc):
assert rc == 0
on_connect_reached.set()
def on_disconnect(*args):
on_disconnect_reached.set()
mqttc.on_connect = on_connect
mqttc.on_disconnect = on_disconnect
mqttc.connect_async("localhost", fake_broker.port)
mqttc.loop_start()
try:
fake_broker.start()
connect_packet = paho_test.gen_connect(
"test_with_loop_start", keepalive=60,
proto_ver=MQTTProtocolVersion.MQTTv311)
packet_in = fake_broker.receive_packet(1000)
assert packet_in # Check connection was not closed
assert packet_in == connect_packet
connack_packet = paho_test.gen_connack(rc=0)
count = fake_broker.send_packet(connack_packet)
assert count # Check connection was not closed
assert count == len(connack_packet)
assert on_connect_reached.wait(1)
assert mqttc.is_connected()
fake_broker.finish()
assert on_disconnect_reached.wait(1)
assert not mqttc.is_connected()
finally:
mqttc.loop_stop()
def test_with_loop(self, fake_broker: FakeBroker):
mqttc = client.Client(
CallbackAPIVersion.VERSION1,
"test_with_loop",
clean_session=True,
transport=fake_broker.transport,
)
on_connect_reached = threading.Event()
on_disconnect_reached = threading.Event()
def on_connect(mqttc, obj, flags, rc):
assert rc == 0
on_connect_reached.set()
def on_disconnect(*args):
on_disconnect_reached.set()
mqttc.on_connect = on_connect
mqttc.on_disconnect = on_disconnect
mqttc.connect("localhost", fake_broker.port)
fake_broker.start()
# not yet connected, packet are not yet processed by loop()
assert not mqttc.is_connected()
# connect packet is sent during connect() call
connect_packet = paho_test.gen_connect(
"test_with_loop", keepalive=60,
proto_ver=MQTTProtocolVersion.MQTTv311)
packet_in = fake_broker.receive_packet(1000)
assert packet_in # Check connection was not closed
assert packet_in == connect_packet
connack_packet = paho_test.gen_connack(rc=0)
count = fake_broker.send_packet(connack_packet)
assert count # Check connection was not closed
assert count == len(connack_packet)
# call loop() to process the connack packet
assert mqttc.loop(timeout=1) == MQTTErrorCode.MQTT_ERR_SUCCESS
assert on_connect_reached.wait(1)
assert mqttc.is_connected()
fake_broker.finish()
# call loop() to detect the connection lost
assert mqttc.loop(timeout=1) == MQTTErrorCode.MQTT_ERR_CONN_LOST
assert on_disconnect_reached.wait(1)
assert not mqttc.is_connected()
class TestPublish:
def test_publish_before_connect(self, fake_broker: FakeBroker) -> None:
mqttc = client.Client(
CallbackAPIVersion.VERSION1,
"test_publish_before_connect",
transport=fake_broker.transport,
)
def on_connect(mqttc, obj, flags, rc):
assert rc == 0
mqttc.on_connect = on_connect
mqttc.loop_start()
mqttc.connect("localhost", fake_broker.port)
mqttc.enable_logger()
try:
mi = mqttc.publish("test", "testing")
fake_broker.start()
packet_in = fake_broker.receive_packet(1)
assert not packet_in # Check connection is closed
# re-call fake_broker.start() to take the 2nd connection done by client
# ... this is probably a bug, when using loop_start/loop_forever
# and doing a connect() before, the TCP connection is opened twice.
fake_broker.start()
connect_packet = paho_test.gen_connect(
"test_publish_before_connect", keepalive=60,
proto_ver=client.MQTTv311)
packet_in = fake_broker.receive_packet(1000)
assert packet_in # Check connection was not closed
assert packet_in == connect_packet
connack_packet = paho_test.gen_connack(rc=0)
count = fake_broker.send_packet(connack_packet)
assert count # Check connection was not closed
assert count == len(connack_packet)
with pytest.raises(RuntimeError):
mi.wait_for_publish(1)
mqttc.disconnect()
disconnect_packet = paho_test.gen_disconnect()
packet_in = fake_broker.receive_packet(1000)
assert packet_in # Check connection was not closed
assert packet_in == disconnect_packet
finally:
mqttc.loop_stop()
packet_in = fake_broker.receive_packet(1)
assert not packet_in # Check connection is closed
@pytest.mark.parametrize("user_payload,sent_payload", [
("string", b"string"),
(b"byte", b"byte"),
(bytearray(b"bytearray"), b"bytearray"),
(42, b"42"),
(4.2, b"4.2"),
(None, b""),
])
def test_publish_various_payload(self, user_payload: client.PayloadType, sent_payload: bytes, fake_broker: FakeBroker) -> None:
mqttc = client.Client(
CallbackAPIVersion.VERSION2,
"test_publish_various_payload",
transport=fake_broker.transport,
)
mqttc.connect("localhost", fake_broker.port)
mqttc.loop_start()
mqttc.enable_logger()
try:
fake_broker.start()
connect_packet = paho_test.gen_connect(
"test_publish_various_payload", keepalive=60,
proto_ver=client.MQTTv311)
fake_broker.expect_packet("connect", connect_packet)
connack_packet = paho_test.gen_connack(rc=0)
count = fake_broker.send_packet(connack_packet)
assert count # Check connection was not closed
assert count == len(connack_packet)
mqttc.publish("test", user_payload)
publish_packet = paho_test.gen_publish(
b"test", payload=sent_payload, qos=0
)
fake_broker.expect_packet("publish", publish_packet)
mqttc.disconnect()
disconnect_packet = paho_test.gen_disconnect()
packet_in = fake_broker.receive_packet(1000)
assert packet_in # Check connection was not closed
assert packet_in == disconnect_packet
finally:
mqttc.loop_stop()
packet_in = fake_broker.receive_packet(1)
assert not packet_in # Check connection is closed
@pytest.mark.parametrize("callback_version", [
(CallbackAPIVersion.VERSION1),
(CallbackAPIVersion.VERSION2),
])
class TestPublishBroker2Client:
def test_invalid_utf8_topic(self, callback_version, fake_broker):
mqttc = client.Client(callback_version, "client-id", transport=fake_broker.transport)
def on_message(client, userdata, msg):
with pytest.raises(UnicodeDecodeError):
assert msg.topic
client.disconnect()
mqttc.on_message = on_message
mqttc.connect_async("localhost", fake_broker.port)
mqttc.loop_start()
try:
fake_broker.start()
connect_packet = paho_test.gen_connect("client-id")
packet_in = fake_broker.receive_packet(len(connect_packet))
assert packet_in # Check connection was not closed
assert packet_in == connect_packet
connack_packet = paho_test.gen_connack(rc=0)
count = fake_broker.send_packet(connack_packet)
assert count # Check connection was not closed
assert count == len(connack_packet)
publish_packet = paho_test.gen_publish(b"\xff", qos=0)
count = fake_broker.send_packet(publish_packet)
assert count # Check connection was not closed
assert count == len(publish_packet)
disconnect_packet = paho_test.gen_disconnect()
packet_in = fake_broker.receive_packet(len(disconnect_packet))
assert packet_in # Check connection was not closed
assert packet_in == disconnect_packet
finally:
mqttc.loop_stop()
packet_in = fake_broker.receive_packet(1)
assert not packet_in # Check connection is closed
def test_valid_utf8_topic_recv(self, callback_version, fake_broker):
mqttc = client.Client(callback_version, "client-id", transport=fake_broker.transport)
# It should be non-ascii multi-bytes character
topic = unicodedata.lookup('SNOWMAN')
def on_message(client, userdata, msg):
assert msg.topic == topic
client.disconnect()
mqttc.on_message = on_message
mqttc.connect_async("localhost", fake_broker.port)
mqttc.loop_start()
try:
fake_broker.start()
connect_packet = paho_test.gen_connect("client-id")
packet_in = fake_broker.receive_packet(len(connect_packet))
assert packet_in # Check connection was not closed
assert packet_in == connect_packet
connack_packet = paho_test.gen_connack(rc=0)
count = fake_broker.send_packet(connack_packet)
assert count # Check connection was not closed
assert count == len(connack_packet)
publish_packet = paho_test.gen_publish(
topic.encode('utf-8'), qos=0
)
count = fake_broker.send_packet(publish_packet)
assert count # Check connection was not closed
assert count == len(publish_packet)
disconnect_packet = paho_test.gen_disconnect()
packet_in = fake_broker.receive_packet(len(disconnect_packet))
assert packet_in # Check connection was not closed
assert packet_in == disconnect_packet
finally:
mqttc.loop_stop()
packet_in = fake_broker.receive_packet(1)
assert not packet_in # Check connection is closed
def test_valid_utf8_topic_publish(self, callback_version, fake_broker):
mqttc = client.Client(callback_version, "client-id", transport=fake_broker.transport)
# It should be non-ascii multi-bytes character
topic = unicodedata.lookup('SNOWMAN')
mqttc.connect_async("localhost", fake_broker.port)
mqttc.loop_start()
try:
fake_broker.start()
connect_packet = paho_test.gen_connect("client-id")
packet_in = fake_broker.receive_packet(len(connect_packet))
assert packet_in # Check connection was not closed
assert packet_in == connect_packet
connack_packet = paho_test.gen_connack(rc=0)
count = fake_broker.send_packet(connack_packet)
assert count # Check connection was not closed
assert count == len(connack_packet)
mqttc.publish(topic, None, 0)
# Small sleep needed to avoid connection reset.
time.sleep(0.3)
publish_packet = paho_test.gen_publish(
topic.encode('utf-8'), qos=0
)
packet_in = fake_broker.receive_packet(len(publish_packet))
assert packet_in # Check connection was not closed
assert packet_in == publish_packet
mqttc.disconnect()
disconnect_packet = paho_test.gen_disconnect()
packet_in = fake_broker.receive_packet(len(disconnect_packet))
assert packet_in # Check connection was not closed
assert packet_in == disconnect_packet
finally:
mqttc.loop_stop()
packet_in = fake_broker.receive_packet(1)
assert not packet_in # Check connection is closed
def test_message_callback(self, callback_version, fake_broker):
mqttc = client.Client(callback_version, "client-id", transport=fake_broker.transport)
userdata = {
'on_message': 0,
'callback1': 0,
'callback2': 0,
}
mqttc.user_data_set(userdata)
def on_message(client, userdata, msg):
assert msg.topic == 'topic/value'
userdata['on_message'] += 1
def callback1(client, userdata, msg):
assert msg.topic == 'topic/callback/1'
userdata['callback1'] += 1
def callback2(client, userdata, msg):
assert msg.topic in ('topic/callback/3', 'topic/callback/1')
userdata['callback2'] += 1
mqttc.on_message = on_message
mqttc.message_callback_add('topic/callback/1', callback1)
mqttc.message_callback_add('topic/callback/+', callback2)
mqttc.connect_async("localhost", fake_broker.port)
mqttc.loop_start()
try:
fake_broker.start()
connect_packet = paho_test.gen_connect("client-id")
packet_in = fake_broker.receive_packet(len(connect_packet))
assert packet_in # Check connection was not closed
assert packet_in == connect_packet
connack_packet = paho_test.gen_connack(rc=0)
count = fake_broker.send_packet(connack_packet)
assert count # Check connection was not closed
assert count == len(connack_packet)
publish_packet = paho_test.gen_publish(b"topic/value", qos=1, mid=1)
count = fake_broker.send_packet(publish_packet)
assert count # Check connection was not closed
assert count == len(publish_packet)
publish_packet = paho_test.gen_publish(b"topic/callback/1", qos=1, mid=2)
count = fake_broker.send_packet(publish_packet)
assert count # Check connection was not closed
assert count == len(publish_packet)
publish_packet = paho_test.gen_publish(b"topic/callback/3", qos=1, mid=3)
count = fake_broker.send_packet(publish_packet)
assert count # Check connection was not closed
assert count == len(publish_packet)
puback_packet = paho_test.gen_puback(mid=1)
packet_in = fake_broker.receive_packet(len(puback_packet))
assert packet_in # Check connection was not closed
assert packet_in == puback_packet
puback_packet = paho_test.gen_puback(mid=2)
packet_in = fake_broker.receive_packet(len(puback_packet))
assert packet_in # Check connection was not closed
assert packet_in == puback_packet
puback_packet = paho_test.gen_puback(mid=3)
packet_in = fake_broker.receive_packet(len(puback_packet))
assert packet_in # Check connection was not closed
assert packet_in == puback_packet
mqttc.disconnect()
disconnect_packet = paho_test.gen_disconnect()
packet_in = fake_broker.receive_packet(len(disconnect_packet))
assert packet_in # Check connection was not closed
assert packet_in == disconnect_packet
finally:
mqttc.loop_stop()
packet_in = fake_broker.receive_packet(1)
assert not packet_in # Check connection is closed
assert userdata['on_message'] == 1
assert userdata['callback1'] == 1
assert userdata['callback2'] == 2
class TestCompatibility:
"""
Some tests for backward compatibility
"""
def test_change_error_code_to_enum(self):
"""Make sure code don't break after MQTTErrorCode enum introduction"""
rc_ok = client.MQTTErrorCode.MQTT_ERR_SUCCESS
rc_again = client.MQTTErrorCode.MQTT_ERR_AGAIN
rc_err = client.MQTTErrorCode.MQTT_ERR_NOMEM
# Access using old name still works
assert rc_ok == client.MQTT_ERR_SUCCESS
# User might compare to 0 to check for success
assert rc_ok == 0
assert not rc_err == 0
assert not rc_again == 0
assert not rc_ok != 0
assert rc_err != 0
assert rc_again != 0
# User might compare to specific code
assert rc_again == -1
assert rc_err == 1
# User might just use "if rc:"
assert not rc_ok
assert rc_err
assert rc_again
# User might do inequality with 0 (like "if rc > 0")
assert not (rc_ok > 0)
assert rc_err > 0
assert rc_again < 0
# This might probably not be done: User might use rc as number in
# operation
assert rc_ok + 1 == 1
def test_migration_callback_version(self):
with pytest.raises(ValueError, match="see docs/migrations.rst"):
_ = client.Client("client-id")
def test_callback_v1_mqtt3(self, fake_broker):
callback_called = []
with pytest.deprecated_call():
mqttc = client.Client(
CallbackAPIVersion.VERSION1,
"client-id",
userdata=callback_called,
transport=fake_broker.transport,
)
def on_connect(cl, userdata, flags, rc):
assert isinstance(cl, client.Client)
assert isinstance(flags, dict)
assert isinstance(flags["session present"], int)
assert isinstance(rc, int)
userdata.append("on_connect")
cl.subscribe([("topic", 0)])
def on_subscribe(cl, userdata, mid, granted_qos):
assert isinstance(cl, client.Client)
assert isinstance(mid, int)
assert isinstance(granted_qos, tuple)
assert isinstance(granted_qos[0], int)
userdata.append("on_subscribe")
cl.publish("topic", "payload", 2)
def on_publish(cl, userdata, mid):
assert isinstance(cl, client.Client)
assert isinstance(mid, int)
userdata.append("on_publish")
def on_message(cl, userdata, message):
assert isinstance(cl, client.Client)
assert isinstance(message, client.MQTTMessage)
userdata.append("on_message")
cl.unsubscribe("topic")
def on_unsubscribe(cl, userdata, mid):
assert isinstance(cl, client.Client)
assert isinstance(mid, int)
userdata.append("on_unsubscribe")
cl.disconnect()
def on_disconnect(cl, userdata, rc):
assert isinstance(cl, client.Client)
assert isinstance(rc, int)
userdata.append("on_disconnect")
mqttc.on_connect = on_connect
mqttc.on_subscribe = on_subscribe
mqttc.on_publish = on_publish
mqttc.on_message = on_message
mqttc.on_unsubscribe = on_unsubscribe
mqttc.on_disconnect = on_disconnect
mqttc.enable_logger()
mqttc.connect_async("localhost", fake_broker.port)
mqttc.loop_start()
try:
fake_broker.start()
connect_packet = paho_test.gen_connect(
"client-id", keepalive=60)
fake_broker.expect_packet("connect", connect_packet)
connack_packet = paho_test.gen_connack(rc=0)
count = fake_broker.send_packet(connack_packet)
assert count # Check connection was not closed
assert count == len(connack_packet)
subscribe_packet = paho_test.gen_subscribe(1, "topic", 0)
fake_broker.expect_packet("subscribe", subscribe_packet)
suback_packet = paho_test.gen_suback(1, 0)
count = fake_broker.send_packet(suback_packet)
assert count # Check connection was not closed
assert count == len(suback_packet)
publish_packet = paho_test.gen_publish("topic", 2, "payload", mid=2)
fake_broker.expect_packet("publish", publish_packet)
pubrec_packet = paho_test.gen_pubrec(mid=2)
count = fake_broker.send_packet(pubrec_packet)
assert count # Check connection was not closed
assert count == len(pubrec_packet)
pubrel_packet = paho_test.gen_pubrel(mid=2)
fake_broker.expect_packet("pubrel", pubrel_packet)
pubcomp_packet = paho_test.gen_pubcomp(mid=2)
count = fake_broker.send_packet(pubcomp_packet)
assert count # Check connection was not closed
assert count == len(pubcomp_packet)
publish_from_broker_packet = paho_test.gen_publish("topic", qos=0, payload="payload", mid=99)
count = fake_broker.send_packet(publish_from_broker_packet)
assert count # Check connection was not closed
assert count == len(publish_from_broker_packet)
unsubscribe_packet = paho_test.gen_unsubscribe(mid=3, topic="topic")
fake_broker.expect_packet("unsubscribe", unsubscribe_packet)
suback_packet = paho_test.gen_unsuback(mid=3)
count = fake_broker.send_packet(suback_packet)
assert count # Check connection was not closed
assert count == len(suback_packet)
disconnect_packet = paho_test.gen_disconnect()
fake_broker.expect_packet("disconnect", disconnect_packet)
assert callback_called == [
"on_connect",
"on_subscribe",
"on_publish",
"on_message",
"on_unsubscribe",
"on_disconnect",
]
finally:
mqttc.disconnect()
mqttc.loop_stop()
packet_in = fake_broker.receive_packet(1)
assert not packet_in # Check connection is closed
def test_callback_v2_mqtt3(self, fake_broker):
callback_called = []
mqttc = client.Client(
CallbackAPIVersion.VERSION2,
"client-id",
userdata=callback_called,
transport=fake_broker.transport,
)
def on_connect(cl, userdata, flags, reason, properties):
assert isinstance(cl, client.Client)
assert isinstance(flags, client.ConnectFlags)
assert isinstance(reason, ReasonCode)
assert isinstance(properties, Properties)
assert reason == 0
assert properties.isEmpty()
userdata.append("on_connect")
cl.subscribe([("topic", 0)])
def on_subscribe(cl, userdata, mid, reason_code_list, properties):
assert isinstance(cl, client.Client)
assert isinstance(mid, int)
assert isinstance(reason_code_list, list)
assert isinstance(reason_code_list[0], ReasonCode)
assert isinstance(properties, Properties)
assert properties.isEmpty()
userdata.append("on_subscribe")
cl.publish("topic", "payload", 2)
def on_publish(cl, userdata, mid, reason_code, properties):
assert isinstance(cl, client.Client)
assert isinstance(mid, int)
assert isinstance(reason_code, ReasonCode)
assert isinstance(properties, Properties)
assert properties.isEmpty()
userdata.append("on_publish")
def on_message(cl, userdata, message):
assert isinstance(cl, client.Client)
assert isinstance(message, client.MQTTMessage)
userdata.append("on_message")
cl.unsubscribe("topic")
def on_unsubscribe(cl, userdata, mid, reason_code_list, properties):
assert isinstance(cl, client.Client)
assert isinstance(mid, int)
assert isinstance(reason_code_list, list)
assert len(reason_code_list) == 0
assert isinstance(properties, Properties)
assert properties.isEmpty()
userdata.append("on_unsubscribe")
cl.disconnect()
def on_disconnect(cl, userdata, flags, reason_code, properties):
assert isinstance(cl, client.Client)
assert isinstance(flags, client.DisconnectFlags)
assert isinstance(reason_code, ReasonCode)
assert isinstance(properties, Properties)
assert properties.isEmpty()
userdata.append("on_disconnect")
mqttc.on_connect = on_connect
mqttc.on_subscribe = on_subscribe
mqttc.on_publish = on_publish
mqttc.on_message = on_message
mqttc.on_unsubscribe = on_unsubscribe
mqttc.on_disconnect = on_disconnect
mqttc.enable_logger()
mqttc.connect_async("localhost", fake_broker.port)
mqttc.loop_start()
try:
fake_broker.start()
connect_packet = paho_test.gen_connect(
"client-id", keepalive=60)
fake_broker.expect_packet("connect", connect_packet)
connack_packet = paho_test.gen_connack(rc=0)
count = fake_broker.send_packet(connack_packet)
assert count # Check connection was not closed
assert count == len(connack_packet)
subscribe_packet = paho_test.gen_subscribe(1, "topic", 0)
fake_broker.expect_packet("subscribe", subscribe_packet)
suback_packet = paho_test.gen_suback(1, 0)
count = fake_broker.send_packet(suback_packet)
assert count # Check connection was not closed
assert count == len(suback_packet)
publish_packet = paho_test.gen_publish("topic", 2, "payload", mid=2)
fake_broker.expect_packet("publish", publish_packet)
pubrec_packet = paho_test.gen_pubrec(mid=2)
count = fake_broker.send_packet(pubrec_packet)
assert count # Check connection was not closed
assert count == len(pubrec_packet)
pubrel_packet = paho_test.gen_pubrel(mid=2)
fake_broker.expect_packet("pubrel", pubrel_packet)
pubcomp_packet = paho_test.gen_pubcomp(mid=2)
count = fake_broker.send_packet(pubcomp_packet)
assert count # Check connection was not closed
assert count == len(pubcomp_packet)
publish_from_broker_packet = paho_test.gen_publish("topic", qos=0, payload="payload", mid=99)
count = fake_broker.send_packet(publish_from_broker_packet)
assert count # Check connection was not closed
assert count == len(publish_from_broker_packet)
unsubscribe_packet = paho_test.gen_unsubscribe(mid=3, topic="topic")
fake_broker.expect_packet("unsubscribe", unsubscribe_packet)
suback_packet = paho_test.gen_unsuback(mid=3)
count = fake_broker.send_packet(suback_packet)
assert count # Check connection was not closed
assert count == len(suback_packet)
disconnect_packet = paho_test.gen_disconnect()
fake_broker.expect_packet("disconnect", disconnect_packet)
assert callback_called == [
"on_connect",
"on_subscribe",
"on_publish",
"on_message",
"on_unsubscribe",
"on_disconnect",
]
finally:
mqttc.disconnect()
mqttc.loop_stop()
packet_in = fake_broker.receive_packet(1)
assert not packet_in # Check connection is closed