def deserialize(api_data): # type: (Dict[str,Any]) -> VentilationStatusDTO status_dto = VentilationStatusDTO(id=api_data['id'], mode=api_data['mode']) if 'level' in api_data: status_dto.level = Toolbox.nonify(api_data['level'], 0) if 'timer' in api_data: status_dto.timer = Toolbox.nonify(api_data['timer'], 0) if 'remaining_time' in api_data: status_dto.remaining_time = Toolbox.nonify( api_data['remaining_time'], 0) return status_dto
def test_ventilation_controller_inactive_status(self): plugin = Plugin(id=2, name='dummy', version='0.0.1') def get_ventilation(id): return Ventilation(id=id, amount_of_levels=4, source='plugin', plugin=plugin) with mock.patch.object(Select, 'count', return_value=1), \ mock.patch.object(Ventilation, 'get', side_effect=get_ventilation), \ mock.patch.object(Ventilation, 'select', return_value=[get_ventilation(43)]): events = [] def callback(event): events.append(event) self.pubsub.subscribe_gateway_events(PubSub.GatewayTopics.STATE, callback) self.controller.set_status( VentilationStatusDTO(43, 'manual', level=2, timer=60.0, last_seen=(time.time() - 600))) self.pubsub._publish_all_events() self.assertEqual(1, len(events)) self.assertEqual(1, len(self.controller._status)) self.controller._check_connected_timeout() self.pubsub._publish_all_events() self.assertEqual(2, len(events)) self.assertEqual(1, len(self.controller._status)) # Check that the last event that has been send is Null last_event = events[-1] self.assertEqual(None, last_event.data['mode']) self.assertEqual(None, last_event.data['level']) self.controller.set_status( VentilationStatusDTO(43, 'manual', level=2, timer=60.0)) self.pubsub._publish_all_events() self.assertEqual(3, len(events)) self.assertEqual(1, len(self.controller._status)) self.controller._check_connected_timeout() self.pubsub._publish_all_events() # Now there would no timeout occur self.assertEqual(3, len(events)) self.assertEqual(1, len(self.controller._status))
def deserialize(api_data): # type: (Dict[str,Any]) -> Tuple[VentilationStatusDTO, List[str]] loaded_fields = ['id', 'mode'] status_dto = VentilationStatusDTO(api_data['id'], api_data['mode']) if 'level' in api_data: loaded_fields.append('level') status_dto.level = Toolbox.nonify(api_data['level'], 0) if 'timer' in api_data: loaded_fields.append('timer') status_dto.timer = Toolbox.nonify(api_data['timer'], 0) if 'remaining_time' in api_data: loaded_fields.append('remaining_time') status_dto.remaining_time = Toolbox.nonify( api_data['remaining_time'], 0) return status_dto, loaded_fields
def test_set_ventilation_status(self): with mock.patch.object(self.ventilation_controller, 'set_status', return_value=VentilationStatusDTO( id=1, mode='manual', level=2, remaining_time=60.0)) as set_status: status = { 'id': 1, 'mode': 'manual', 'level': 2, 'remaining_time': 60.0 } response = self.web.set_ventilation_status(status=status) self.assertEqual( { 'id': 1, 'connected': True, 'mode': 'manual', 'level': 2, 'remaining_time': 60.0, 'timer': None }, json.loads(response)['status']) set_status.assert_called()
def test_ventilation_status_equal_evaluation(self): status_dto_1 = VentilationStatusDTO(1, 'automatic', level=1, timer=None, remaining_time=None, last_seen=time.time()) status_dto_2 = VentilationStatusDTO(1, 'manual', level=1, timer=30, remaining_time=None, last_seen=time.time()) status_dto_3 = VentilationStatusDTO(1, 'manual', level=1, timer=None, remaining_time=15, last_seen=time.time()) status_dto_4 = VentilationStatusDTO(1, 'manual', level=1, timer=None, remaining_time=None, last_seen=time.time()) status_dto_5 = VentilationStatusDTO(1, 'automatic', level=1, timer=None, remaining_time=None, last_seen=time.time()) self.assertEqual(True, (status_dto_1 == status_dto_5)) self.assertEqual(False, (status_dto_1 == status_dto_2)) self.assertNotEqual( status_dto_1, status_dto_2) # Difference between no timer and setup timer self.assertNotEqual( status_dto_1, status_dto_3) # difference between no timer and running timer self.assertNotEqual( status_dto_2, status_dto_3) # Difference between status and start timer status self.assertNotEqual(status_dto_1, status_dto_4) # difference in mode self.assertEqual(status_dto_1, status_dto_5) # Equal values, but different objects
def set_mode_auto(self, ventilation_id): # type: (int) -> None _ = self.load_ventilation(ventilation_id) status_dto = VentilationStatusDTO(ventilation_id, mode=VentilationStatusDTO.Mode.AUTO) if not (status_dto == self._status.get(ventilation_id)): self._save_status_cache(status_dto) self._publish_state(status_dto)
def set_mode_auto(self, ventilation_id): # type: (int) -> None _ = self.load_ventilation(ventilation_id) status_dto = VentilationStatusDTO(ventilation_id, mode=VentilationStatusDTO.Mode.AUTO) if status_dto != self._status.get(ventilation_id): self._status[ventilation_id] = status_dto self._publish_state(status_dto)
def test_set_status(self): plugin = Plugin(id=2, name='dummy', version='0.0.1') with mock.patch.object(Select, 'count', return_value=1), \ mock.patch.object(Ventilation, 'get', side_effect=[Ventilation(id=42, amount_of_levels=4, source='plugin', plugin=plugin), Ventilation(id=43, amount_of_levels=4, source='plugin', plugin=plugin)]), \ mock.patch.object(Ventilation, 'select', return_value=[Ventilation(id=42, amount_of_levels=4, source='plugin', plugin=plugin), Ventilation(id=43, amount_of_levels=4, source='plugin', plugin=plugin)]): self.controller.set_status( VentilationStatusDTO(42, 'manual', level=0)) self.controller.set_status( VentilationStatusDTO(43, 'manual', level=2, timer=60.0)) status = self.controller.get_status() assert {'manual'} == set(x.mode for x in status) assert {42, 43} == set(x.id for x in status) assert {0, 2} == set(x.level for x in status) assert {None, 60.0} == set(x.timer for x in status)
def test_ventilation_change_events(self): plugin = Plugin(id=2, name='dummy', version='0.0.1') def get_ventilation(id): return Ventilation(id=id, amount_of_levels=4, source='plugin', plugin=plugin) with mock.patch.object(Select, 'count', return_value=1), \ mock.patch.object(Ventilation, 'get', side_effect=get_ventilation), \ mock.patch.object(Ventilation, 'select', return_value=[get_ventilation(42), get_ventilation(43)]): self.controller.set_status( VentilationStatusDTO(42, 'manual', level=0)) self.controller.set_status( VentilationStatusDTO(43, 'manual', level=2, timer=60.0)) self.pubsub._publish_all_events() events = [] def callback(event): events.append(event) self.pubsub.subscribe_gateway_events(PubSub.GatewayTopics.STATE, callback) self.controller.set_status( VentilationStatusDTO(42, 'manual', level=0)) self.controller.set_status( VentilationStatusDTO(43, 'manual', level=2, timer=60.0)) self.pubsub._publish_all_events() assert GatewayEvent( GatewayEvent.Types.VENTILATION_CHANGE, { 'id': 43, 'mode': 'manual', 'level': 2, 'timer': 60.0, 'remaining_time': None, 'is_connected': True }) in events assert len(events) == 1, events
def set_level(self, ventilation_id, level, timer=None): # type: (int, int, Optional[float]) -> None ventilation_dto = self.load_ventilation(ventilation_id) status_dto = VentilationStatusDTO( ventilation_id, mode=VentilationStatusDTO.Mode.MANUAL, level=level, timer=timer) self._validate_state(ventilation_dto, status_dto) if not (status_dto == self._status.get(ventilation_id)): self._save_status_cache(status_dto) self._publish_state(status_dto)
def callback(event, self=self): events.append(event) if len(events) > 20: self.fail( 'There should never be more than 20 events due to ventilation in this test' ) # resend the same event to mock the plugin who will send an event back with the same status # id, mode, level=None, timer=None, remaining_time=None, last_seen=None status_dto = VentilationStatusDTO( id=event.data['id'], mode=event.data['mode'], level=event.data['level'], remaining_time=event.data['timer'], ) self.controller.set_status(status_dto) self.pubsub._publish_all_events()
def test_ventilation_plugin_anti_ping_pong(self): # This test will see if the gateway will not keep sending events back and forth when an event change happens # This can be caused by ping-ponging back and forth between the plugin and gateway when sending updates plugin = Plugin(id=2, name='dummy', version='0.0.1') def get_ventilation(id): return Ventilation(id=id, amount_of_levels=4, source='plugin', plugin=plugin) with mock.patch.object(Ventilation, 'get', side_effect=get_ventilation), \ mock.patch.object(Ventilation, 'select', return_value=[get_ventilation(43)]): events = [] def callback(event, self=self): events.append(event) if len(events) > 20: self.fail( 'There should never be more than 20 events due to ventilation in this test' ) # resend the same event to mock the plugin who will send an event back with the same status # id, mode, level=None, timer=None, remaining_time=None, last_seen=None status_dto = VentilationStatusDTO( id=event.data['id'], mode=event.data['mode'], level=event.data['level'], remaining_time=event.data['timer'], ) self.controller.set_status(status_dto) self.pubsub._publish_all_events() self.pubsub.subscribe_gateway_events(PubSub.GatewayTopics.STATE, callback) # event that ventilation box is running in automatic mode self.controller.set_status( VentilationStatusDTO(43, 'automatic', level=1, timer=None, remaining_time=None, last_seen=time.time())) self.pubsub._publish_all_events() self.assertEqual(1, len(events)) # Clear all current events events = [] # event that timer has been started self.controller.set_status( VentilationStatusDTO(43, 'manual', level=1, timer=30, remaining_time=None, last_seen=time.time())) self.pubsub._publish_all_events() self.assertGreaterEqual(10, len(events)) # event that timer is running self.controller.set_status( VentilationStatusDTO(43, 'manual', level=1, timer=None, remaining_time=15, last_seen=time.time())) self.pubsub._publish_all_events() self.assertGreaterEqual(10, len(events)) # event that timer is done self.controller.set_status( VentilationStatusDTO(43, 'automatic', level=1, timer=None, remaining_time=None, last_seen=time.time())) self.pubsub._publish_all_events() self.assertGreaterEqual(10, len(events))
def test_ventilation_timer_expire_automatic(self): plugin = Plugin(id=2, name='dummy', version='0.0.1') def get_ventilation(id): return Ventilation(id=id, amount_of_levels=4, source='plugin', plugin=plugin) with mock.patch.object(Select, 'count', return_value=1), \ mock.patch.object(Ventilation, 'get', side_effect=get_ventilation), \ mock.patch.object(Ventilation, 'select', return_value=[get_ventilation(43)]): events = [] def callback(event): events.append(event) self.pubsub.subscribe_gateway_events(PubSub.GatewayTopics.STATE, callback) # event that ventilation box is running in automatic mode self.controller.set_status( VentilationStatusDTO(43, 'automatic', level=1, timer=None, remaining_time=None, last_seen=time.time())) self.pubsub._publish_all_events() self.assertEqual(1, len(events)) self.assertEqual(1, len(self.controller._status)) self.assertEqual( None, events[-1].data['remaining_time']) # no timers running self.assertEqual(None, events[-1].data['timer']) # no timers running # Clear all current events events = [] # event that timer has been started self.controller.set_status( VentilationStatusDTO(43, 'automatic', level=1, timer=30, remaining_time=None, last_seen=time.time())) self.pubsub._publish_all_events() self.assertEqual(1, len(events)) self.assertEqual(1, len(self.controller._status)) self.assertEqual( None, events[-1].data['remaining_time'] ) # There has not been an update from the ventilation box or plugin self.assertEqual(30, events[-1].data['timer']) for i in range(30, 0, -1): # Clear all current events events = [] # event from ventilation plugin mode = 'automatic' if i % 2 == 0 else 'manual' self.controller.set_status( VentilationStatusDTO(43, mode, level=1, timer=None, remaining_time=i, last_seen=time.time())) self.pubsub._publish_all_events() print(events) self.assertEqual(1, len(events)) self.assertEqual(1, len(self.controller._status)) self.assertEqual(i, events[-1].data['remaining_time']) self.assertEqual(30, events[-1].data['timer'] ) # this value should be kept in cache # Clear all current events events = [] # event from ventilation plugin -> Timer has expired, and has switched to automatic mode self.controller.set_status( VentilationStatusDTO(43, 'automatic', level=1, timer=None, remaining_time=None, last_seen=time.time())) self.pubsub._publish_all_events() self.assertEqual(1, len(events)) self.assertEqual(1, len(self.controller._status)) self.assertEqual(None, events[-1].data['remaining_time']) self.assertEqual( None, events[-1].data['timer'] ) # this value should now be cleared when timer has done
def test_ventilation_timer_expire_manual(self): plugin = Plugin(id=2, name='dummy', version='0.0.1') def get_ventilation(id): return Ventilation(id=id, amount_of_levels=4, source='plugin', plugin=plugin) with mock.patch.object(Select, 'count', return_value=1), \ mock.patch.object(Ventilation, 'get', side_effect=get_ventilation), \ mock.patch.object(Ventilation, 'select', return_value=[get_ventilation(43)]): events = [] def callback(event): events.append(event) self.pubsub.subscribe_gateway_events(PubSub.GatewayTopics.STATE, callback) # first timer is running self.controller.set_status( VentilationStatusDTO(43, 'manual', level=2, timer=60.0, remaining_time=5.0, last_seen=(time.time() - 10))) self.pubsub._publish_all_events() self.assertEqual(1, len(events)) self.assertEqual(1, len(self.controller._status)) # This should not trigger an event self.controller._check_connected_timeout() # This should trigger an update event. self.controller._periodic_event_update() self.pubsub._publish_all_events() self.assertEqual(2, len(events)) self.assertEqual(1, len(self.controller._status)) # Clear all current events events = [] # event that timer has been done self.controller.set_status( VentilationStatusDTO(43, 'automatic', level=1, timer=None, remaining_time=None, last_seen=time.time())) self.pubsub._publish_all_events() self.assertEqual(1, len(events)) self.assertEqual(1, len(self.controller._status)) self.assertEqual(None, events[-1].data['remaining_time']) self.assertEqual(None, events[-1].data['timer']) # Clear all current events events = [] # event that timer has been started self.controller.set_status( VentilationStatusDTO(43, 'automatic', level=1, timer=30, remaining_time=None, last_seen=time.time())) self.pubsub._publish_all_events() self.assertEqual(1, len(events)) self.assertEqual(1, len(self.controller._status)) self.assertEqual(None, events[-1].data['remaining_time']) self.assertEqual(30, events[-1].data['timer']) # Clear all current events events = [] # event from ventilation plugin self.controller.set_status( VentilationStatusDTO(43, 'manual', level=1, timer=None, remaining_time=29, last_seen=time.time())) self.pubsub._publish_all_events() self.assertEqual(1, len(events)) self.assertEqual(1, len(self.controller._status)) self.assertEqual(29, events[-1].data['remaining_time']) self.assertEqual( 30, events[-1].data['timer']) # this value should be kept in cache # Clear all current events events = [] # event from ventilation plugin self.controller.set_status( VentilationStatusDTO(43, 'automatic', level=1, timer=None, remaining_time=15, last_seen=time.time())) self.pubsub._publish_all_events() self.assertEqual(1, len(events)) self.assertEqual(1, len(self.controller._status)) self.assertEqual(15, events[-1].data['remaining_time'] ) # this value should update from the event self.assertEqual( 30, events[-1].data['timer']) # this value should be kept in cache # Clear all current events events = [] # event from ventilation plugin (same value) self.controller.set_status( VentilationStatusDTO(43, 'automatic', level=1, timer=None, remaining_time=15, last_seen=time.time())) self.pubsub._publish_all_events() self.assertEqual(0, len(events)) self.assertEqual(1, len(self.controller._status)) # event from ventilation plugin self.controller.set_status( VentilationStatusDTO(43, 'automatic', level=1, timer=None, remaining_time=14, last_seen=time.time())) self.pubsub._publish_all_events() self.assertEqual(1, len(events)) self.assertEqual(1, len(self.controller._status)) self.assertEqual(14, events[-1].data['remaining_time'] ) # this value should update from the event self.assertEqual( 30, events[-1].data['timer']) # this value should be kept in cache # Clear all current events events = [] # event from ventilation plugin -> Timer has expired, but is still in manual mode self.controller.set_status( VentilationStatusDTO(43, 'manual', level=1, timer=None, remaining_time=None, last_seen=time.time())) self.pubsub._publish_all_events() self.assertEqual(1, len(events)) self.assertEqual(1, len(self.controller._status)) self.assertEqual(None, events[-1].data['remaining_time']) self.assertEqual( None, events[-1].data['timer'] ) # this value should now be cleared when timer has done