diff --git a/pysnoo/pubnub.py b/pysnoo/pubnub.py index 12f08c7..790a853 100644 --- a/pysnoo/pubnub.py +++ b/pysnoo/pubnub.py @@ -1,7 +1,7 @@ """PySnoo PubNub Interface.""" import asyncio import logging -from typing import Callable, Optional +from typing import Callable, Optional, List from pubnub.callbacks import SubscribeCallback from pubnub.pnconfiguration import PNConfiguration @@ -53,18 +53,17 @@ class SnooPubNub: def __init__(self, access_token: str, - snoo_serial: str, + serial_number: str, uuid: str, - callback: Callable[[ActivityState], None], custom_event_loop=None): """Initialize the Snoo PubNub object.""" - # self._access_token = access_token - # self._snoo_serial = snoo_serial - self._activiy_channel = 'ActivityState.{}'.format(snoo_serial) - self._controlcommand_channel = 'ControlCommand.{}'.format(snoo_serial) - self._pnconfig = self._setup_pnconfig(access_token, uuid) - self._pubnub = PubNubAsyncio(self._pnconfig, custom_event_loop=custom_event_loop) - self._listener = SnooSubscribeListener(callback) + self.config = self._setup_pnconfig(access_token, uuid) + self.serial_number = serial_number + self._activiy_channel = 'ActivityState.{}'.format(serial_number) + self._controlcommand_channel = 'ControlCommand.{}'.format(serial_number) + self._pubnub = PubNubAsyncio(self.config, custom_event_loop=custom_event_loop) + self._listener = SnooSubscribeListener(self._activy_state_callback) + self._external_listeners: List[Callable[[ActivityState], None]] = [] @staticmethod def _setup_pnconfig(access_token, uuid): @@ -77,6 +76,25 @@ def _setup_pnconfig(access_token, uuid): pnconfig.ssl = True return pnconfig + def add_listener(self, update_callback: Callable[[ActivityState], None]) -> Callable[[], None]: + """Add a AcitivyState Listener to the SnooPubNub Entity and returns a remove_listener CB for that listener""" + self._external_listeners.append(update_callback) + + def remove_listener_cb() -> None: + """Remove listener.""" + self.remove_listener(update_callback) + + return remove_listener_cb + + def remove_listener(self, update_callback: Callable[[ActivityState], None]) -> None: + """Remove data update.""" + self._external_listeners.remove(update_callback) + + def _activy_state_callback(self, state: ActivityState): + """Internal Callback of SnooSubscribeListener""" + for update_callback in self._external_listeners: + update_callback(state) + async def subscribe(self): """Subscribe to Snoo Activity Channel""" self._pubnub.add_listener(self._listener) diff --git a/scripts/snoo b/scripts/snoo index f5e4f65..665d15c 100755 --- a/scripts/snoo +++ b/scripts/snoo @@ -13,7 +13,7 @@ from pysnoo.models import dt_str_to_dt # pylint: disable=unused-argument -async def _setup_pubnub(snoo: Snoo, callback): +async def _setup_pubnub(snoo: Snoo): """Utility Function to setup SnooPubNub""" # Also checks for valid token devices = await snoo.get_devices() @@ -24,8 +24,7 @@ async def _setup_pubnub(snoo: Snoo, callback): return SnooPubNub(snoo.auth.access_token, devices[0].serial_number, - f'pn-pysnoo-{devices[0].serial_number}', - callback) + f'pn-pysnoo-{devices[0].serial_number}') async def user(snoo: Snoo, args): @@ -84,7 +83,8 @@ async def monitor(snoo: Snoo, args): def as_callback(activity_state): pprint(activity_state.to_dict()) - pubnub = await _setup_pubnub(snoo, as_callback) + pubnub = await _setup_pubnub(snoo) + pubnub.add_listener(as_callback) for activity_state in await pubnub.history(): as_callback(activity_state) @@ -103,7 +103,7 @@ async def monitor(snoo: Snoo, args): async def history(snoo: Snoo, args): """history command""" - pubnub = await _setup_pubnub(snoo, None) + pubnub = await _setup_pubnub(snoo) for activity_state in await pubnub.history(100): pprint(activity_state.to_dict()) @@ -113,7 +113,7 @@ async def history(snoo: Snoo, args): async def toggle(snoo: Snoo, args): """toggle command""" - pubnub = await _setup_pubnub(snoo, None) + pubnub = await _setup_pubnub(snoo) last_activity_state = (await pubnub.history())[0] if last_activity_state.state_machine.state == SessionLevel.ONLINE: @@ -128,7 +128,7 @@ async def toggle(snoo: Snoo, args): async def toggle_hold(snoo: Snoo, args): """toggleHold command""" - pubnub = await _setup_pubnub(snoo, None) + pubnub = await _setup_pubnub(snoo) last_activity_state = (await pubnub.history())[0] current_state = last_activity_state.state_machine.state @@ -144,7 +144,7 @@ async def toggle_hold(snoo: Snoo, args): async def level_up(snoo: Snoo, args): """up command""" - pubnub = await _setup_pubnub(snoo, None) + pubnub = await _setup_pubnub(snoo) last_activity_state = (await pubnub.history())[0] up_transition = last_activity_state.state_machine.up_transition @@ -159,7 +159,7 @@ async def level_up(snoo: Snoo, args): async def level_down(snoo: Snoo, args): """down command""" - pubnub = await _setup_pubnub(snoo, None) + pubnub = await _setup_pubnub(snoo) last_activity_state = (await pubnub.history())[0] down_transition = last_activity_state.state_machine.down_transition diff --git a/setup.py b/setup.py index 4a96017..5f874ba 100644 --- a/setup.py +++ b/setup.py @@ -1,7 +1,7 @@ """PySnoo setup script.""" from setuptools import setup -_VERSION = '0.1.0' +_VERSION = '0.1.1' def readme(): diff --git a/tests/test_snoo_pubnub.py b/tests/test_snoo_pubnub.py index f22862a..7d06c29 100644 --- a/tests/test_snoo_pubnub.py +++ b/tests/test_snoo_pubnub.py @@ -20,7 +20,6 @@ def setUp(self): self.pubnub = SnooPubNub('ACCESS_TOKEN', 'SERIAL_NUMBER', 'UUID', - MagicMock(), custom_event_loop=self.loop) async def tearDown(self): @@ -163,9 +162,18 @@ async def test_message_callback(self): load_fixture('', 'pubnub_message_ActivityState.json')) activity_state = ActivityState.from_dict(activity_state_msg_payload) - callback = self.pubnub._listener._callback + # Add callback + callback = MagicMock() + remove_cb = self.pubnub.add_listener(callback) + self.assertEqual(self.pubnub._external_listeners, [callback]) + + # Trigger callback self.pubnub._listener.message(self.pubnub._pubnub, PNMessageResult( activity_state_msg_payload, None, None, 0)) callback.assert_called_once_with(activity_state) + + # Remove callback + remove_cb() + self.assertEqual(self.pubnub._external_listeners, [])