Skip to content

Commit

Permalink
refactor: add param mqtt_topic_prefix to internal function _run
Browse files Browse the repository at this point in the history
  • Loading branch information
fphammerle committed Apr 3, 2022
1 parent 680dc5e commit dce4e56
Show file tree
Hide file tree
Showing 6 changed files with 91 additions and 48 deletions.
4 changes: 3 additions & 1 deletion switchbot_mqtt/__init__.py
Expand Up @@ -46,9 +46,10 @@ def _run(
*,
mqtt_host: str,
mqtt_port: int,
mqtt_disable_tls: bool,
mqtt_username: typing.Optional[str],
mqtt_password: typing.Optional[str],
mqtt_disable_tls: bool,
mqtt_topic_prefix: str,
retry_count: int,
device_passwords: typing.Dict[str, str],
fetch_device_info: bool,
Expand All @@ -59,6 +60,7 @@ def _run(
retry_count=retry_count,
device_passwords=device_passwords,
fetch_device_info=fetch_device_info,
mqtt_topic_prefix=mqtt_topic_prefix,
)
)
mqtt_client.on_connect = _mqtt_on_connect
Expand Down
4 changes: 1 addition & 3 deletions switchbot_mqtt/_actors/base.py
Expand Up @@ -52,9 +52,7 @@ class _MQTTCallbackUserdata:
retry_count: int
device_passwords: typing.Dict[str, str]
fetch_device_info: bool
# "homeassistant/" for historic reasons.
# will be parametrized via command-line argument in the future.
mqtt_topic_prefix: str = "homeassistant/"
mqtt_topic_prefix: str


class _MQTTControlledActor(abc.ABC):
Expand Down
15 changes: 8 additions & 7 deletions switchbot_mqtt/_cli.py
Expand Up @@ -27,10 +27,10 @@

import switchbot_mqtt
from switchbot_mqtt._actors import _ButtonAutomator, _CurtainMotor
from switchbot_mqtt._actors.base import _MQTTCallbackUserdata

_MQTT_DEFAULT_PORT = 1883
_MQTT_DEFAULT_TLS_PORT = 8883
_MQTT_TOPIC_PREFIX = "homeassistant/" # for historic reasons

_LOGGER = logging.getLogger(__name__)

Expand Down Expand Up @@ -86,25 +86,25 @@ def _main() -> None:
action="store_true",
help="Report devices' battery level on topic "
+ _ButtonAutomator.get_mqtt_battery_percentage_topic(
prefix=_MQTTCallbackUserdata.mqtt_topic_prefix, mac_address="MAC_ADDRESS"
prefix=_MQTT_TOPIC_PREFIX, mac_address="MAC_ADDRESS"
)
+ " or, respectively,"
+ _CurtainMotor.get_mqtt_battery_percentage_topic(
prefix=_MQTTCallbackUserdata.mqtt_topic_prefix, mac_address="MAC_ADDRESS"
prefix=_MQTT_TOPIC_PREFIX, mac_address="MAC_ADDRESS"
)
+ " after every command. Additionally report curtain motors' position on topic "
+ _CurtainMotor.get_mqtt_position_topic(
prefix=_MQTTCallbackUserdata.mqtt_topic_prefix, mac_address="MAC_ADDRESS"
prefix=_MQTT_TOPIC_PREFIX, mac_address="MAC_ADDRESS"
)
+ " after executing stop commands."
" When this option is enabled, the mentioned reports may also be requested"
" by sending a MQTT message to the topic "
+ _ButtonAutomator.get_mqtt_update_device_info_topic(
prefix=_MQTTCallbackUserdata.mqtt_topic_prefix, mac_address="MAC_ADDRESS"
prefix=_MQTT_TOPIC_PREFIX, mac_address="MAC_ADDRESS"
)
+ " or "
+ _CurtainMotor.get_mqtt_update_device_info_topic(
prefix=_MQTTCallbackUserdata.mqtt_topic_prefix, mac_address="MAC_ADDRESS"
prefix=_MQTT_TOPIC_PREFIX, mac_address="MAC_ADDRESS"
)
+ ". This option can also be enabled by assigning a non-empty value to the"
" environment variable FETCH_DEVICE_INFO.",
Expand Down Expand Up @@ -149,9 +149,10 @@ def _main() -> None:
switchbot_mqtt._run( # pylint: disable=protected-access; internal
mqtt_host=args.mqtt_host,
mqtt_port=mqtt_port,
mqtt_disable_tls=not args.mqtt_enable_tls,
mqtt_username=args.mqtt_username,
mqtt_password=mqtt_password,
mqtt_disable_tls=not args.mqtt_enable_tls,
mqtt_topic_prefix=_MQTT_TOPIC_PREFIX,
retry_count=args.retry_count,
device_passwords=device_passwords,
fetch_device_info=args.fetch_device_info
Expand Down
54 changes: 35 additions & 19 deletions tests/test_cli.py
Expand Up @@ -108,9 +108,10 @@ def test__main(
run_mock.assert_called_once_with(
mqtt_host=expected_mqtt_host,
mqtt_port=expected_mqtt_port,
mqtt_disable_tls=True,
mqtt_username=expected_username,
mqtt_password=expected_password,
mqtt_disable_tls=True,
mqtt_topic_prefix="homeassistant/",
retry_count=expected_retry_count,
device_passwords={},
fetch_device_info=False,
Expand Down Expand Up @@ -152,9 +153,10 @@ def test__main_mqtt_password_file(
run_mock.assert_called_once_with(
mqtt_host="localhost",
mqtt_port=1883,
mqtt_disable_tls=True,
mqtt_username="me",
mqtt_password=expected_password,
mqtt_disable_tls=True,
mqtt_topic_prefix="homeassistant/",
retry_count=3,
device_passwords={},
fetch_device_info=False,
Expand Down Expand Up @@ -214,20 +216,23 @@ def test__main_device_password_file(
run_mock.assert_called_once_with(
mqtt_host="localhost",
mqtt_port=1883,
mqtt_disable_tls=True,
mqtt_username=None,
mqtt_password=None,
mqtt_disable_tls=True,
mqtt_topic_prefix="homeassistant/",
retry_count=3,
device_passwords=device_passwords,
fetch_device_info=False,
)


_RUN_DEFAULT_KWARGS: typing.Dict[str, typing.Any] = {
"mqtt_host": "localhost",
"mqtt_port": 1883,
"mqtt_disable_tls": True,
"mqtt_username": None,
"mqtt_password": None,
"mqtt_disable_tls": False,
"mqtt_topic_prefix": "homeassistant/",
"retry_count": 3,
"device_passwords": {},
"fetch_device_info": False,
Expand Down Expand Up @@ -255,7 +260,12 @@ def test__main_mqtt_enable_tls() -> None:
):
switchbot_mqtt._cli._main()
run_mock.assert_called_once_with(
**{**_RUN_DEFAULT_KWARGS, "mqtt_host": "mqtt.local", "mqtt_port": 8883}
**{
**_RUN_DEFAULT_KWARGS,
"mqtt_host": "mqtt.local",
"mqtt_disable_tls": False,
"mqtt_port": 8883,
}
)


Expand All @@ -266,7 +276,12 @@ def test__main_mqtt_enable_tls_overwrite_port() -> None:
):
switchbot_mqtt._cli._main()
run_mock.assert_called_once_with(
**{**_RUN_DEFAULT_KWARGS, "mqtt_host": "mqtt.local", "mqtt_port": 1883}
**{
**_RUN_DEFAULT_KWARGS,
"mqtt_host": "mqtt.local",
"mqtt_disable_tls": False,
"mqtt_port": 1883,
}
)


Expand All @@ -293,40 +308,41 @@ def test__main_fetch_device_info() -> None:
],
):
switchbot_mqtt._cli._main()
default_kwargs = dict(
mqtt_host="localhost",
mqtt_port=1883,
mqtt_username=None,
mqtt_password=None,
mqtt_disable_tls=True,
retry_count=3,
device_passwords={},
run_mock.assert_called_once_with(
**{**_RUN_DEFAULT_KWARGS, "fetch_device_info": False}
)
run_mock.assert_called_once_with(fetch_device_info=False, **default_kwargs)
with unittest.mock.patch("switchbot_mqtt._run") as run_mock, unittest.mock.patch(
"sys.argv",
["", "--mqtt-host", "localhost", "--fetch-device-info"],
):
switchbot_mqtt._cli._main()
run_mock.assert_called_once_with(fetch_device_info=True, **default_kwargs)
run_mock.assert_called_once_with(
**{**_RUN_DEFAULT_KWARGS, "fetch_device_info": True}
)
with unittest.mock.patch("switchbot_mqtt._run") as run_mock, unittest.mock.patch(
"sys.argv",
["", "--mqtt-host", "localhost"],
), unittest.mock.patch.dict("os.environ", {"FETCH_DEVICE_INFO": "21"}):
switchbot_mqtt._cli._main()
run_mock.assert_called_once_with(fetch_device_info=True, **default_kwargs)
run_mock.assert_called_once_with(
**{**_RUN_DEFAULT_KWARGS, "fetch_device_info": True}
)
with unittest.mock.patch("switchbot_mqtt._run") as run_mock, unittest.mock.patch(
"sys.argv",
["", "--mqtt-host", "localhost"],
), unittest.mock.patch.dict("os.environ", {"FETCH_DEVICE_INFO": ""}):
switchbot_mqtt._cli._main()
run_mock.assert_called_once_with(fetch_device_info=False, **default_kwargs)
run_mock.assert_called_once_with(
**{**_RUN_DEFAULT_KWARGS, "fetch_device_info": False}
)
with unittest.mock.patch("switchbot_mqtt._run") as run_mock, unittest.mock.patch(
"sys.argv",
["", "--mqtt-host", "localhost"],
), unittest.mock.patch.dict("os.environ", {"FETCH_DEVICE_INFO": " "}):
switchbot_mqtt._cli._main()
run_mock.assert_called_once_with(fetch_device_info=True, **default_kwargs)
run_mock.assert_called_once_with(
**{**_RUN_DEFAULT_KWARGS, "fetch_device_info": True}
)


@pytest.mark.parametrize(
Expand Down
45 changes: 33 additions & 12 deletions tests/test_mqtt.py
Expand Up @@ -56,9 +56,10 @@ def test__run(
switchbot_mqtt._run(
mqtt_host=mqtt_host,
mqtt_port=mqtt_port,
mqtt_disable_tls=False,
mqtt_username=None,
mqtt_password=None,
mqtt_disable_tls=False,
mqtt_topic_prefix="homeassistant/",
retry_count=retry_count,
device_passwords=device_passwords,
fetch_device_info=fetch_device_info,
Expand All @@ -71,6 +72,7 @@ def test__run(
retry_count=retry_count,
device_passwords=device_passwords,
fetch_device_info=fetch_device_info,
mqtt_topic_prefix="homeassistant/",
)
assert not mqtt_client_mock().username_pw_set.called
mqtt_client_mock().tls_set.assert_called_once_with(ca_certs=None)
Expand Down Expand Up @@ -137,9 +139,10 @@ def test__run_tls(
switchbot_mqtt._run(
mqtt_host="mqtt.local",
mqtt_port=1234,
mqtt_disable_tls=mqtt_disable_tls,
mqtt_username=None,
mqtt_password=None,
mqtt_disable_tls=mqtt_disable_tls,
mqtt_topic_prefix="prfx",
retry_count=21,
device_passwords={},
fetch_device_info=True,
Expand Down Expand Up @@ -168,16 +171,20 @@ def test__run_authentication(
switchbot_mqtt._run(
mqtt_host=mqtt_host,
mqtt_port=mqtt_port,
mqtt_disable_tls=True,
mqtt_username=mqtt_username,
mqtt_password=mqtt_password,
mqtt_disable_tls=True,
mqtt_topic_prefix="prfx",
retry_count=7,
device_passwords={},
fetch_device_info=True,
)
mqtt_client_mock.assert_called_once_with(
userdata=_MQTTCallbackUserdata(
retry_count=7, device_passwords={}, fetch_device_info=True
retry_count=7,
device_passwords={},
fetch_device_info=True,
mqtt_topic_prefix="prfx",
)
)
mqtt_client_mock().username_pw_set.assert_called_once_with(
Expand All @@ -196,9 +203,10 @@ def test__run_authentication_missing_username(
switchbot_mqtt._run(
mqtt_host=mqtt_host,
mqtt_port=mqtt_port,
mqtt_disable_tls=True,
mqtt_username=None,
mqtt_password=mqtt_password,
mqtt_disable_tls=True,
mqtt_topic_prefix="whatever",
retry_count=3,
device_passwords={},
fetch_device_info=True,
Expand Down Expand Up @@ -242,7 +250,7 @@ def _get_device(self) -> None:
[
(
switchbot_mqtt._actors._ButtonAutomator._MQTT_UPDATE_DEVICE_INFO_TOPIC_LEVELS,
b"homeassistant/switch/switchbot/aa:bb:cc:dd:ee:ff/request-device-info",
b"prfx/switch/switchbot/aa:bb:cc:dd:ee:ff/request-device-info",
"aa:bb:cc:dd:ee:ff",
),
],
Expand All @@ -262,6 +270,7 @@ def test__mqtt_update_device_info_callback(
retry_count=21, # tested in test__mqtt_command_callback
device_passwords={},
fetch_device_info=True,
mqtt_topic_prefix="prfx/",
)
with unittest.mock.patch.object(
ActorMock, "__init__", return_value=None
Expand All @@ -277,7 +286,7 @@ def test__mqtt_update_device_info_callback(
mac_address=expected_mac_address, retry_count=21, password=None
)
update_mock.assert_called_once_with(
mqtt_client="client_dummy", mqtt_topic_prefix="homeassistant/"
mqtt_client="client_dummy", mqtt_topic_prefix="prfx/"
)
assert caplog.record_tuples == [
(
Expand Down Expand Up @@ -307,7 +316,10 @@ def test__mqtt_update_device_info_callback_ignore_retained(
ActorMock._mqtt_update_device_info_callback(
"client_dummy",
_MQTTCallbackUserdata(
retry_count=21, device_passwords={}, fetch_device_info=True
retry_count=21,
device_passwords={},
fetch_device_info=True,
mqtt_topic_prefix="ignored",
),
message,
)
Expand Down Expand Up @@ -499,7 +511,10 @@ def test__mqtt_command_callback_unexpected_topic(
ActorMock._mqtt_command_callback(
"client_dummy",
_MQTTCallbackUserdata(
retry_count=3, device_passwords={}, fetch_device_info=True
retry_count=3,
device_passwords={},
fetch_device_info=True,
mqtt_topic_prefix="homeassistant/",
),
message,
)
Expand All @@ -526,7 +541,7 @@ def test__mqtt_command_callback_invalid_mac_address(
ActorMock = _mock_actor_class(
command_topic_levels=_ButtonAutomator.MQTT_COMMAND_TOPIC_LEVELS
)
topic = f"homeassistant/switch/switchbot/{mac_address}/set".encode()
topic = f"mqttprefix-switch/switchbot/{mac_address}/set".encode()
message = MQTTMessage(topic=topic)
message.payload = payload
with unittest.mock.patch.object(
Expand All @@ -539,7 +554,10 @@ def test__mqtt_command_callback_invalid_mac_address(
ActorMock._mqtt_command_callback(
"client_dummy",
_MQTTCallbackUserdata(
retry_count=3, device_passwords={}, fetch_device_info=True
retry_count=3,
device_passwords={},
fetch_device_info=True,
mqtt_topic_prefix="mqttprefix-",
),
message,
)
Expand Down Expand Up @@ -582,7 +600,10 @@ def test__mqtt_command_callback_ignore_retained(
ActorMock._mqtt_command_callback(
"client_dummy",
_MQTTCallbackUserdata(
retry_count=4, device_passwords={}, fetch_device_info=True
retry_count=4,
device_passwords={},
fetch_device_info=True,
mqtt_topic_prefix="homeassistant/",
),
message,
)
Expand Down

0 comments on commit dce4e56

Please sign in to comment.