Beispiel #1
0
    def handle_data(self, command, msg):
        """Handle changes to the mailbox."""
        from asterisk_mbox.commands import (
            CMD_MESSAGE_LIST, CMD_MESSAGE_CDR_AVAILABLE, CMD_MESSAGE_CDR)

        if command == CMD_MESSAGE_LIST:
            _LOGGER.debug("AsteriskVM sent updated message list: Len %d",
                          len(msg))
            old_messages = self.messages
            self.messages = sorted(
                msg, key=lambda item: item['info']['origtime'], reverse=True)
            if not isinstance(old_messages, list):
                async_dispatcher_send(
                    self.hass, SIGNAL_DISCOVER_PLATFORM, DOMAIN)
            async_dispatcher_send(self.hass, SIGNAL_MESSAGE_UPDATE,
                                  self.messages)
        elif command == CMD_MESSAGE_CDR:
            _LOGGER.debug("AsteriskVM sent updated CDR list: Len %d",
                          len(msg.get('entries', [])))
            self.cdr = msg['entries']
            async_dispatcher_send(self.hass, SIGNAL_CDR_UPDATE, self.cdr)
        elif command == CMD_MESSAGE_CDR_AVAILABLE:
            if not isinstance(self.cdr, list):
                _LOGGER.debug("AsteriskVM adding CDR platform")
                self.cdr = []
                async_dispatcher_send(self.hass, SIGNAL_DISCOVER_PLATFORM,
                                      "asterisk_cdr")
            async_dispatcher_send(self.hass, SIGNAL_CDR_REQUEST)
        else:
            _LOGGER.debug("AsteriskVM sent unknown message '%d' len: %d",
                          command, len(msg))
Beispiel #2
0
def async_fire_mqtt_message(hass, topic, payload, qos=0):
    """Fire the MQTT message."""
    if isinstance(payload, str):
        payload = payload.encode('utf-8')
    dispatcher.async_dispatcher_send(
        hass, mqtt.SIGNAL_MQTT_MESSAGE_RECEIVED, topic,
        payload, qos)
Beispiel #3
0
    async def async_set_climate(self, toggle):
        """Set climate control mode via Nissan servers."""
        climate_result = None
        if toggle:
            _LOGGER.debug("Requesting climate turn on for %s", self.leaf.vin)
            set_function = self.leaf.start_climate_control
            result_function = self.leaf.get_start_climate_control_result
        else:
            _LOGGER.debug("Requesting climate turn off for %s", self.leaf.vin)
            set_function = self.leaf.stop_climate_control
            result_function = self.leaf.get_stop_climate_control_result

        request = await self.hass.async_add_executor_job(set_function)
        for attempt in range(MAX_RESPONSE_ATTEMPTS):
            if attempt > 0:
                _LOGGER.debug("Climate data not in yet (%s) (%s). "
                              "Waiting (%s) seconds", self.leaf.vin,
                              attempt, PYCARWINGS2_SLEEP)
                await asyncio.sleep(PYCARWINGS2_SLEEP)

            climate_result = await self.hass.async_add_executor_job(
                result_function, request)

            if climate_result is not None:
                break

        if climate_result is not None:
            _LOGGER.debug("Climate result: %s", climate_result.__dict__)
            async_dispatcher_send(self.hass, SIGNAL_UPDATE_LEAF)
            return climate_result.is_hvac_running == toggle

        _LOGGER.debug("Climate result not returned by Nissan servers")
        return False
Beispiel #4
0
 async def set_control_setpoint(call):
     """Set the control setpoint on the OpenTherm Gateway."""
     gw_var = gw_vars.DATA_CONTROL_SETPOINT
     value = await gateway.set_control_setpoint(call.data[ATTR_TEMPERATURE])
     status = hass.data[DATA_OPENTHERM_GW][DATA_LATEST_STATUS]
     status.update({gw_var: value})
     async_dispatcher_send(hass, SIGNAL_OPENTHERM_GW_UPDATE, status)
Beispiel #5
0
async def async_handle_temp_update(hass, context, msg):
    """Handle a temperature sensor state update."""
    _LOGGER.debug("[temp handler] context: %s  msg: %s", context, msg)
    entity_id, temp = context.get(DEVICE_CLASS_TEMPERATURE), msg.get('temp')
    if entity_id:
        async_dispatcher_send(
            hass, SIGNAL_SENSOR_UPDATE.format(entity_id), temp)
Beispiel #6
0
    async def _sync(self):
        """Update local list of devices."""
        if not await self._hass.async_add_executor_job(
                self._client.update) and self._is_available:
            self._is_available = False
            _LOGGER.warning("Device is unavailable")
            return

        async def new_device(device_id, component):
            """Load new device."""
            config_entries_key = '{}.{}'.format(component, DOMAIN)
            async with self._hass.data[DATA_CONFIG_ENTRY_LOCK]:
                if config_entries_key not in self._hass.data[
                        CONFIG_ENTRY_IS_SETUP]:
                    await self._hass.config_entries.async_forward_entry_setup(
                        self._config_entry, component)
                    self._hass.data[CONFIG_ENTRY_IS_SETUP].add(
                        config_entries_key)

            async_dispatcher_send(
                self._hass, POINT_DISCOVERY_NEW.format(component, DOMAIN),
                device_id)

        self._is_available = True
        for home_id in self._client.homes:
            if home_id not in self._known_homes:
                await new_device(home_id, 'alarm_control_panel')
                self._known_homes.add(home_id)
        for device in self._client.devices:
            if device.device_id not in self._known_devices:
                for component in ('sensor', 'binary_sensor'):
                    await new_device(device.device_id, component)
                self._known_devices.add(device.device_id)
        async_dispatcher_send(self._hass, SIGNAL_UPDATE_ENTITY)
Beispiel #7
0
 async def _async_handle_conversation_event(self, event):
     from hangups import ChatMessageEvent
     if isinstance(event, ChatMessageEvent):
         dispatcher.async_dispatcher_send(self.hass,
                                          EVENT_HANGOUTS_MESSAGE_RECEIVED,
                                          event.conversation_id,
                                          event.user_id, event)
Beispiel #8
0
async def async_handle_humi_update(hass, context, msg):
    """Handle a humidity sensor state update."""
    _LOGGER.debug("[humi handler] context: %s  msg: %s", context, msg)
    entity_id, humi = context.get(DEVICE_CLASS_HUMIDITY), msg.get('humi')
    if entity_id:
        async_dispatcher_send(
            hass, SIGNAL_SENSOR_UPDATE.format(entity_id), humi)
Beispiel #9
0
 def on_data(data):
     """Define a handler to fire when the data is received."""
     mac_address = data['macAddress']
     if data != self.stations[mac_address][ATTR_LAST_DATA]:
         _LOGGER.debug('New data received: %s', data)
         self.stations[mac_address][ATTR_LAST_DATA] = data
         async_dispatcher_send(self._hass, TOPIC_UPDATE)
Beispiel #10
0
 async def set_outside_temp(call):
     """Provide the outside temperature to the OpenTherm Gateway."""
     gw_var = gw_vars.DATA_OUTSIDE_TEMP
     value = await gateway.set_outside_temp(call.data[ATTR_TEMPERATURE])
     status = hass.data[DATA_OPENTHERM_GW][DATA_LATEST_STATUS]
     status.update({gw_var: value})
     async_dispatcher_send(hass, SIGNAL_OPENTHERM_GW_UPDATE, status)
        def async_update_data(now):
            """Update data from IP camera in SCAN_INTERVAL."""
            yield from cam.update()
            async_dispatcher_send(hass, SIGNAL_UPDATE_DATA, host)

            async_track_point_in_utc_time(
                hass, async_update_data, utcnow() + interval)
async def handle_webhook(hass, webhook_id, request):
    """Handle incoming webhook with GPSLogger request."""
    try:
        data = WEBHOOK_SCHEMA(dict(await request.post()))
    except vol.MultipleInvalid as error:
        return web.Response(
            text=error.error_message,
            status=HTTP_UNPROCESSABLE_ENTITY
        )

    attrs = {
        ATTR_SPEED: data.get(ATTR_SPEED),
        ATTR_DIRECTION: data.get(ATTR_DIRECTION),
        ATTR_ALTITUDE: data.get(ATTR_ALTITUDE),
        ATTR_PROVIDER: data.get(ATTR_PROVIDER),
        ATTR_ACTIVITY: data.get(ATTR_ACTIVITY)
    }

    device = data[ATTR_DEVICE]

    async_dispatcher_send(
        hass, TRACKER_UPDATE, device,
        (data[ATTR_LATITUDE], data[ATTR_LONGITUDE]),
        data[ATTR_BATTERY], data[ATTR_ACCURACY], attrs)

    return web.Response(
        text='Setting location for {}'.format(device),
        status=HTTP_OK
    )
    def async_update_heat_data(now):
        """Update heat data from eight in HEAT_SCAN_INTERVAL."""
        yield from eight.update_device_data()
        async_dispatcher_send(hass, SIGNAL_UPDATE_HEAT)

        async_track_point_in_utc_time(
            hass, async_update_heat_data, utcnow() + HEAT_SCAN_INTERVAL)
    def async_update_user_data(now):
        """Update user data from eight in USER_SCAN_INTERVAL."""
        yield from eight.update_user_data()
        async_dispatcher_send(hass, SIGNAL_UPDATE_USER)

        async_track_point_in_utc_time(
            hass, async_update_user_data, utcnow() + USER_SCAN_INTERVAL)
Beispiel #15
0
    def axis_device_discovered(service, discovery_info):
        """Called when axis devices has been found."""
        host = discovery_info[CONF_HOST]
        name = discovery_info['hostname']
        serialnumber = discovery_info['properties']['macaddress']

        if serialnumber not in AXIS_DEVICES:
            config_file = _read_config(hass)
            if serialnumber in config_file:
                # Device config saved to file
                try:
                    device_config = DEVICE_SCHEMA(config_file[serialnumber])
                    device_config[CONF_HOST] = host
                except vol.Invalid as err:
                    _LOGGER.error("Bad data from %s. %s", CONFIG_FILE, err)
                    return False
                if not setup_device(hass, config, device_config):
                    _LOGGER.error("Couldn\'t set up %s",
                                  device_config[CONF_NAME])
            else:
                # New device, create configuration request for UI
                request_configuration(hass, config, name, host, serialnumber)
        else:
            # Device already registered, but on a different IP
            device = AXIS_DEVICES[serialnumber]
            device.url = host
            async_dispatcher_send(hass,
                                  DOMAIN + '_' + device.name + '_new_ip',
                                  host)
Beispiel #16
0
    async def handle_remove_tracking(call):
        """Call when a user removes an Aftership tracking from HASS."""
        slug = call.data[CONF_SLUG]
        tracking_number = call.data[CONF_TRACKING_NUMBER]

        await aftership.remove_package_tracking(slug, tracking_number)
        async_dispatcher_send(hass, UPDATE_TOPIC)
def test_run_camera_setup(hass, test_client):
    """Test that it fetches the given dispatcher data."""
    yield from async_setup_component(hass, 'camera', {
        'camera': {
            'platform': 'dispatcher',
            'name': 'dispatcher',
            'signal': 'test_camera',
        }})

    client = yield from test_client(hass.http.app)

    async_dispatcher_send(hass, 'test_camera', b'test')
    yield from hass.async_block_till_done()

    resp = yield from client.get('/api/camera_proxy/camera.dispatcher')

    assert resp.status == 200
    body = yield from resp.text()
    assert body == 'test'

    async_dispatcher_send(hass, 'test_camera', b'test2')
    yield from hass.async_block_till_done()

    resp = yield from client.get('/api/camera_proxy/camera.dispatcher')

    assert resp.status == 200
    body = yield from resp.text()
    assert body == 'test2'
Beispiel #18
0
 async def set_setback_temp(call):
     """Set the OpenTherm Gateway SetBack temperature."""
     gw_var = gw_vars.OTGW_SB_TEMP
     value = await gateway.set_setback_temp(call.data[ATTR_TEMPERATURE])
     status = hass.data[DATA_OPENTHERM_GW][DATA_LATEST_STATUS]
     status.update({gw_var: value})
     async_dispatcher_send(hass, SIGNAL_OPENTHERM_GW_UPDATE, status)
Beispiel #19
0
 def dispatch_level_change(self, command, level):
     """Dispatch level change."""
     async_dispatcher_send(
         self._zha_device.hass,
         "{}_{}".format(self.unique_id, command),
         level
     )
Beispiel #20
0
 def attribute_updated(self, attrid, value):
     """Handle attribute updates on this cluster."""
     if attrid == self._value_attribute:
         async_dispatcher_send(
             self._zha_device.hass,
             "{}_{}".format(self.unique_id, SIGNAL_ATTR_UPDATED),
             value
         )
Beispiel #21
0
    async def handle_add_tracking(call):
        """Call when a user adds a new Aftership tracking from HASS."""
        title = call.data.get(CONF_TITLE)
        slug = call.data.get(CONF_SLUG)
        tracking_number = call.data[CONF_TRACKING_NUMBER]

        await aftership.add_package_tracking(tracking_number, title, slug)
        async_dispatcher_send(hass, UPDATE_TOPIC)
Beispiel #22
0
 async def async_update_sabnzbd(now):
     """Refresh SABnzbd queue data."""
     from pysabnzbd import SabnzbdApiException
     try:
         await sab_api.refresh_data()
         async_dispatcher_send(hass, SIGNAL_SABNZBD_UPDATED, None)
     except SabnzbdApiException as err:
         _LOGGER.error(err)
Beispiel #23
0
 async def _on_disconnect(self):
     """Handle disconnecting."""
     if self._connected:
         _LOGGER.debug('Connection lost! Reconnect...')
         await self.async_connect()
     else:
         dispatcher.async_dispatcher_send(self.hass,
                                          EVENT_HANGOUTS_DISCONNECTED)
Beispiel #24
0
    async def async_new_address_callback(hass, entry):
        """Handle signals of device getting new address.

        This is a static method because a class method (bound method),
        can not be used with weak references.
        """
        device = hass.data[DOMAIN][entry.data[CONF_MAC]]
        device.api.config.host = device.host
        async_dispatcher_send(hass, device.event_new_address)
Beispiel #25
0
async def test_add_new_group(hass):
    """Test successful creation of group entities."""
    await setup_gateway(hass, {})
    group = Mock()
    group.name = 'name'
    group.register_async_callback = Mock()
    async_dispatcher_send(hass, 'deconz_new_group', [group])
    await hass.async_block_till_done()
    assert "light.name" in hass.data[deconz.DOMAIN].deconz_ids
Beispiel #26
0
async def test_do_not_add_deconz_groups(hass):
    """Test that clip sensors can be ignored."""
    await setup_gateway(hass, {}, allow_deconz_groups=False)
    group = Mock()
    group.name = 'name'
    group.register_async_callback = Mock()
    async_dispatcher_send(hass, 'deconz_new_group', [group])
    await hass.async_block_till_done()
    assert len(hass.data[deconz.DOMAIN].deconz_ids) == 0
Beispiel #27
0
    async def async_update(self):
        """Retrieve latest state."""
        result = await self.get_attribute_value('fan_mode', from_cache=True)

        async_dispatcher_send(
            self._zha_device.hass,
            "{}_{}".format(self.unique_id, SIGNAL_ATTR_UPDATED),
            result
        )
Beispiel #28
0
 async def set_gpio_mode(call):
     """Set the OpenTherm Gateway GPIO modes."""
     gpio_id = call.data[ATTR_ID]
     gpio_mode = call.data[ATTR_MODE]
     mode = await gateway.set_gpio_mode(gpio_id, gpio_mode)
     gpio_var = getattr(gw_vars, 'OTGW_GPIO_{}'.format(gpio_id))
     status = hass.data[DATA_OPENTHERM_GW][DATA_LATEST_STATUS]
     status.update({gpio_var: mode})
     async_dispatcher_send(hass, SIGNAL_OPENTHERM_GW_UPDATE, status)
Beispiel #29
0
 async def set_led_mode(call):
     """Set the OpenTherm Gateway LED modes."""
     led_id = call.data[ATTR_ID]
     led_mode = call.data[ATTR_MODE]
     mode = await gateway.set_led_mode(led_id, led_mode)
     led_var = getattr(gw_vars, 'OTGW_LED_{}'.format(led_id))
     status = hass.data[DATA_OPENTHERM_GW][DATA_LATEST_STATUS]
     status.update({led_var: mode})
     async_dispatcher_send(hass, SIGNAL_OPENTHERM_GW_UPDATE, status)
    async def async_device_message_received(topic, payload, qos):
        """Process the received message."""
        match = TOPIC_MATCHER.match(topic)

        if not match:
            return

        _prefix_topic, component, node_id, object_id = match.groups()

        if component not in SUPPORTED_COMPONENTS:
            _LOGGER.warning("Component %s is not supported", component)
            return

        # If present, the node_id will be included in the discovered object id
        discovery_id = '_'.join((node_id, object_id)) if node_id else object_id

        if ALREADY_DISCOVERED not in hass.data:
            hass.data[ALREADY_DISCOVERED] = {}

        discovery_hash = (component, discovery_id)

        if discovery_hash in hass.data[ALREADY_DISCOVERED]:
            _LOGGER.info(
                "Component has already been discovered: %s %s, sending update",
                component, discovery_id)
            async_dispatcher_send(
                hass, MQTT_DISCOVERY_UPDATED.format(discovery_hash), payload)
        elif payload:
            # Add component
            try:
                payload = json.loads(payload)
            except ValueError:
                _LOGGER.warning("Unable to parse JSON %s: '%s'",
                                object_id, payload)
                return

            payload = dict(payload)
            platform = payload.get(CONF_PLATFORM, 'mqtt')
            if platform not in ALLOWED_PLATFORMS.get(component, []):
                _LOGGER.warning("Platform %s (component %s) is not allowed",
                                platform, component)
                return

            payload[CONF_PLATFORM] = platform
            if CONF_STATE_TOPIC not in payload:
                payload[CONF_STATE_TOPIC] = '{}/{}/{}{}/state'.format(
                    discovery_topic, component,
                    '%s/' % node_id if node_id else '', object_id)

            hass.data[ALREADY_DISCOVERED][discovery_hash] = None
            payload[ATTR_DISCOVERY_HASH] = discovery_hash

            _LOGGER.info("Found new component: %s %s", component, discovery_id)

            await async_load_platform(
                hass, component, platform, payload, hass_config)
Beispiel #31
0
async def test_bandwidth_sensors(hass, aioclient_mock, mock_unifi_websocket):
    """Verify that bandwidth sensors are working as expected."""
    wired_client = {
        "hostname": "Wired client",
        "is_wired": True,
        "mac": "00:00:00:00:00:01",
        "oui": "Producer",
        "wired-rx_bytes": 1234000000,
        "wired-tx_bytes": 5678000000,
    }
    wireless_client = {
        "is_wired": False,
        "mac": "00:00:00:00:00:02",
        "name": "Wireless client",
        "oui": "Producer",
        "rx_bytes": 2345000000,
        "tx_bytes": 6789000000,
    }
    options = {
        CONF_ALLOW_BANDWIDTH_SENSORS: True,
        CONF_ALLOW_UPTIME_SENSORS: False,
        CONF_TRACK_CLIENTS: False,
        CONF_TRACK_DEVICES: False,
    }

    config_entry = await setup_unifi_integration(
        hass,
        aioclient_mock,
        options=options,
        clients_response=[wired_client, wireless_client],
    )

    assert len(hass.states.async_all()) == 5
    assert len(hass.states.async_entity_ids(SENSOR_DOMAIN)) == 4
    assert hass.states.get("sensor.wired_client_rx").state == "1234.0"
    assert hass.states.get("sensor.wired_client_tx").state == "5678.0"
    assert hass.states.get("sensor.wireless_client_rx").state == "2345.0"
    assert hass.states.get("sensor.wireless_client_tx").state == "6789.0"

    ent_reg = er.async_get(hass)
    assert (ent_reg.async_get("sensor.wired_client_rx").entity_category ==
            ENTITY_CATEGORY_DIAGNOSTIC)

    # Verify state update

    wireless_client["rx_bytes"] = 3456000000
    wireless_client["tx_bytes"] = 7891000000

    mock_unifi_websocket(data={
        "meta": {
            "message": MESSAGE_CLIENT
        },
        "data": [wireless_client],
    })
    await hass.async_block_till_done()

    assert hass.states.get("sensor.wireless_client_rx").state == "3456.0"
    assert hass.states.get("sensor.wireless_client_tx").state == "7891.0"

    # Disable option

    options[CONF_ALLOW_BANDWIDTH_SENSORS] = False
    hass.config_entries.async_update_entry(config_entry,
                                           options=options.copy())
    await hass.async_block_till_done()

    assert len(hass.states.async_all()) == 1
    assert len(hass.states.async_entity_ids(SENSOR_DOMAIN)) == 0
    assert hass.states.get("sensor.wireless_client_rx") is None
    assert hass.states.get("sensor.wireless_client_tx") is None
    assert hass.states.get("sensor.wired_client_rx") is None
    assert hass.states.get("sensor.wired_client_tx") is None

    # Enable option

    options[CONF_ALLOW_BANDWIDTH_SENSORS] = True
    hass.config_entries.async_update_entry(config_entry,
                                           options=options.copy())
    await hass.async_block_till_done()

    assert len(hass.states.async_all()) == 5
    assert len(hass.states.async_entity_ids(SENSOR_DOMAIN)) == 4
    assert hass.states.get("sensor.wireless_client_rx")
    assert hass.states.get("sensor.wireless_client_tx")
    assert hass.states.get("sensor.wired_client_rx")
    assert hass.states.get("sensor.wired_client_tx")

    # Try to add the sensors again, using a signal

    clients_connected = {wired_client["mac"], wireless_client["mac"]}
    devices_connected = set()

    controller = hass.data[UNIFI_DOMAIN][config_entry.entry_id]

    async_dispatcher_send(
        hass,
        controller.signal_update,
        clients_connected,
        devices_connected,
    )
    await hass.async_block_till_done()

    assert len(hass.states.async_all()) == 5
    assert len(hass.states.async_entity_ids(SENSOR_DOMAIN)) == 4
Beispiel #32
0
 def zones_update_callback(status):
     """Update zone objects as per notification from the alarm."""
     _LOGGER.debug("Zones callback, status: %s", status)
     async_dispatcher_send(hass, SIGNAL_ZONES_UPDATED, status[ZONES])
Beispiel #33
0
 def alarm_status_update_callback():
     """Send status update received from alarm to Home Assistant."""
     _LOGGER.debug("Sending request to update panel state")
     async_dispatcher_send(hass, SIGNAL_PANEL_MESSAGE)
Beispiel #34
0
 def controller_reconnected(self, ctrl: Controller) -> None:
     """On reconnect to controller."""
     async_dispatcher_send(self.hass, DISPATCH_CONTROLLER_RECONNECTED, ctrl)
Beispiel #35
0
 async def async_reset_meters(self):
     """Reset all sensors of this meter."""
     _LOGGER.debug("reset meter %s", self.entity_id)
     async_dispatcher_send(self.hass, SIGNAL_RESET_METER, self.entity_id)
Beispiel #36
0
 def async_event_callback(self, action, event_id):
     """Call to configure events when initialized on event stream."""
     if action == "add":
         async_dispatcher_send(self.hass, self.event_new_sensor, event_id)
Beispiel #37
0
 def _async_push_update(state: PilotParser) -> None:
     """Receive a push update."""
     _LOGGER.debug("%s: Got push update: %s", bulb.mac, state.pilotResult)
     coordinator.async_set_updated_data(None)
     if state.get_source() == PIR_SOURCE:
         async_dispatcher_send(hass, SIGNAL_WIZ_PIR.format(bulb.mac))
Beispiel #38
0
 def reconnected():
     """Schedule reconnect after connection has been lost."""
     _LOGGER.warning('HLK-SW16 %s connected', device)
     async_dispatcher_send(hass, SIGNAL_AVAILABILITY.format(device),
                           True)
Beispiel #39
0
 def alarm_data_updated_callback(data):
     """Handle non-alarm based info updates."""
     _LOGGER.debug("Envisalink sent new alarm info. Updating alarms...")
     async_dispatcher_send(hass, SIGNAL_KEYPAD_UPDATE, data)
Beispiel #40
0
    async def async_process_queue(self, task_idx = 0):
        """walk through the list of tasks and execute the ones that are ready"""
        if self.queue_busy or not self.is_available():
            return

        self.queue_busy = True

        # verify conditions
        conditions_passed = (
            all(validate_condition(self.hass, item) for item in self._conditions)
            if self._condition_type == const.CONDITION_TYPE_AND
            else any(validate_condition(self.hass, item) for item in self._conditions)
        ) if len(self._conditions) else True

        if not conditions_passed and len(self._queue):
            _LOGGER.debug("[{}]: Conditions have failed, skipping execution of actions".format(self.id))
            if self._track_conditions:
                # postpone tasks
                self.queue_busy = False
                return

            else:
                # abort all items in queue
                while len(self._queue):
                    self._queue.pop()

        while task_idx < len(self._queue):
            action = self._queue[task_idx]

            if action[CONF_SERVICE] == ACTION_WAIT:

                @callback
                async def async_timer_finished(_now):
                    self._timer = None
                    self.queue_busy = False
                    await self.async_process_queue(task_idx + 1)

                self._timer = async_call_later(
                    self.hass,
                    action[CONF_SERVICE_DATA][CONF_DELAY],
                    async_timer_finished
                )
                _LOGGER.debug("[{}]: Postponing next action for {} seconds".format(self.id, action[CONF_SERVICE_DATA][CONF_DELAY]))
                return

            if ATTR_ENTITY_ID in action:
                _LOGGER.debug("[{}]: Executing service {} on entity {}".format(
                    self.id, action[CONF_SERVICE], action[ATTR_ENTITY_ID]
                ))
            else:
                _LOGGER.debug("[{}]: Executing service {}".format(self.id, action[CONF_SERVICE]))

            await async_call_from_config(
                self.hass,
                action,
            )
            task_idx = task_idx+1

        self.queue_busy = False

        if not self._track_conditions or not len(self._conditions):
            while len(self._queue):
                self._queue.pop()

            async_dispatcher_send(self.hass, "action_queue_finished", self.id)
        else:
            _LOGGER.debug("[{}]: Done for now, Waiting for conditions to change".format(self.id))
Beispiel #41
0
async def async_config_entry_updated(hass: HomeAssistant,
                                     entry: ConfigEntry) -> None:
    """Handle signals of config entry being updated."""
    async_dispatcher_send(hass,
                          f"signal-{DOMAIN}-public-update-{entry.entry_id}")
Beispiel #42
0
    async def async_device_message_received(msg):
        """Process the received message."""
        payload = msg.payload
        topic = msg.topic
        topic_trimmed = topic.replace(f"{discovery_topic}/", "", 1)
        match = TOPIC_MATCHER.match(topic_trimmed)

        if not match:
            return

        component, node_id, object_id = match.groups()

        if component not in SUPPORTED_COMPONENTS:
            _LOGGER.warning("Integration %s is not supported", component)
            return

        if payload:
            try:
                payload = json.loads(payload)
            except ValueError:
                _LOGGER.warning("Unable to parse JSON %s: '%s'", object_id, payload)
                return

        payload = MQTTConfig(payload)

        for key in list(payload.keys()):
            abbreviated_key = key
            key = ABBREVIATIONS.get(key, key)
            payload[key] = payload.pop(abbreviated_key)

        if CONF_DEVICE in payload:
            device = payload[CONF_DEVICE]
            for key in list(device.keys()):
                abbreviated_key = key
                key = DEVICE_ABBREVIATIONS.get(key, key)
                device[key] = device.pop(abbreviated_key)

        if TOPIC_BASE in payload:
            base = payload.pop(TOPIC_BASE)
            for key, value in payload.items():
                if isinstance(value, str) and value:
                    if value[0] == TOPIC_BASE and key.endswith("_topic"):
                        payload[key] = f"{base}{value[1:]}"
                    if value[-1] == TOPIC_BASE and key.endswith("_topic"):
                        payload[key] = f"{value[:-1]}{base}"

        # If present, the node_id will be included in the discovered object id
        discovery_id = " ".join((node_id, object_id)) if node_id else object_id
        discovery_hash = (component, discovery_id)

        if payload:
            # Attach MQTT topic to the payload, used for debug prints
            setattr(payload, "__configuration_source__", f"MQTT (topic: '{topic}')")
            discovery_data = {
                ATTR_DISCOVERY_HASH: discovery_hash,
                ATTR_DISCOVERY_PAYLOAD: payload,
                ATTR_DISCOVERY_TOPIC: topic,
            }
            setattr(payload, "discovery_data", discovery_data)

            payload[CONF_PLATFORM] = "mqtt"

        if ALREADY_DISCOVERED not in hass.data:
            hass.data[ALREADY_DISCOVERED] = {}
        if discovery_hash in hass.data[ALREADY_DISCOVERED]:
            # Dispatch update
            _LOGGER.info(
                "Component has already been discovered: %s %s, sending update",
                component,
                discovery_id,
            )
            async_dispatcher_send(
                hass, MQTT_DISCOVERY_UPDATED.format(discovery_hash), payload
            )
        elif payload:
            # Add component
            _LOGGER.info("Found new component: %s %s", component, discovery_id)
            hass.data[ALREADY_DISCOVERED][discovery_hash] = None

            config_entries_key = f"{component}.mqtt"
            async with hass.data[DATA_CONFIG_ENTRY_LOCK]:
                if config_entries_key not in hass.data[CONFIG_ENTRY_IS_SETUP]:
                    if component == "device_automation":
                        # Local import to avoid circular dependencies
                        # pylint: disable=import-outside-toplevel
                        from . import device_automation

                        await device_automation.async_setup_entry(hass, config_entry)
                    else:
                        await hass.config_entries.async_forward_entry_setup(
                            config_entry, component
                        )
                    hass.data[CONFIG_ENTRY_IS_SETUP].add(config_entries_key)

            async_dispatcher_send(
                hass, MQTT_DISCOVERY_NEW.format(component, "mqtt"), payload
            )
Beispiel #43
0
 async def async_refresh_entity(service):
     """Refresh values that specific entity depends on."""
     entity_id = service.data.get(ATTR_ENTITY_ID)
     async_dispatcher_send(hass,
                           SIGNAL_REFRESH_ENTITY_FORMAT.format(entity_id))
Beispiel #44
0
    async def ws_handler(message_obj):
        """Handle websocket messages.

        This allows push notifications from Alexa to update last_called
        and media state.
        """

        command = (message_obj.json_payload["command"]
                   if isinstance(message_obj.json_payload, dict)
                   and "command" in message_obj.json_payload else None)
        json_payload = (message_obj.json_payload["payload"]
                        if isinstance(message_obj.json_payload, dict)
                        and "payload" in message_obj.json_payload else None)
        existing_serials = _existing_serials(hass, login_obj)
        seen_commands = hass.data[DATA_ALEXAMEDIA]["accounts"][email][
            "websocket_commands"]
        if command and json_payload:

            _LOGGER.debug(
                "%s: Received websocket command: %s : %s",
                hide_email(email),
                command,
                hide_serial(json_payload),
            )
            serial = None
            command_time = time.time()
            if command not in seen_commands:
                _LOGGER.debug("Adding %s to seen_commands: %s", command,
                              seen_commands)
            seen_commands[command] = command_time

            if ("dopplerId" in json_payload
                    and "deviceSerialNumber" in json_payload["dopplerId"]):
                serial = json_payload["dopplerId"]["deviceSerialNumber"]
            elif ("key" in json_payload and "entryId" in json_payload["key"]
                  and json_payload["key"]["entryId"].find("#") != -1):
                serial = (json_payload["key"]["entryId"]).split("#")[2]
                json_payload["key"]["serialNumber"] = serial
            else:
                serial = None
            if command == "PUSH_ACTIVITY":
                #  Last_Alexa Updated
                last_called = {
                    "serialNumber": serial,
                    "timestamp": json_payload["timestamp"],
                }
                if serial and serial in existing_serials:
                    await update_last_called(login_obj, last_called)
                async_dispatcher_send(
                    hass,
                    f"{DOMAIN}_{hide_email(email)}"[0:32],
                    {"push_activity": json_payload},
                )
            elif command in (
                    "PUSH_AUDIO_PLAYER_STATE",
                    "PUSH_MEDIA_CHANGE",
                    "PUSH_MEDIA_PROGRESS_CHANGE",
            ):
                # Player update/ Push_media from tune_in
                if serial and serial in existing_serials:
                    _LOGGER.debug("Updating media_player: %s",
                                  hide_serial(json_payload))
                    async_dispatcher_send(
                        hass,
                        f"{DOMAIN}_{hide_email(email)}"[0:32],
                        {"player_state": json_payload},
                    )
            elif command == "PUSH_VOLUME_CHANGE":
                # Player volume update
                if serial and serial in existing_serials:
                    _LOGGER.debug("Updating media_player volume: %s",
                                  hide_serial(json_payload))
                    async_dispatcher_send(
                        hass,
                        f"{DOMAIN}_{hide_email(email)}"[0:32],
                        {"player_state": json_payload},
                    )
            elif command in (
                    "PUSH_DOPPLER_CONNECTION_CHANGE",
                    "PUSH_EQUALIZER_STATE_CHANGE",
            ):
                # Player availability update
                if serial and serial in existing_serials:
                    _LOGGER.debug(
                        "Updating media_player availability %s",
                        hide_serial(json_payload),
                    )
                    async_dispatcher_send(
                        hass,
                        f"{DOMAIN}_{hide_email(email)}"[0:32],
                        {"player_state": json_payload},
                    )
            elif command == "PUSH_BLUETOOTH_STATE_CHANGE":
                # Player bluetooth update
                bt_event = json_payload["bluetoothEvent"]
                bt_success = json_payload["bluetoothEventSuccess"]
                if (serial and serial in existing_serials and bt_success
                        and bt_event and bt_event
                        in ["DEVICE_CONNECTED", "DEVICE_DISCONNECTED"]):
                    _LOGGER.debug("Updating media_player bluetooth %s",
                                  hide_serial(json_payload))
                    bluetooth_state = await update_bluetooth_state(
                        login_obj, serial)
                    # _LOGGER.debug("bluetooth_state %s",
                    #               hide_serial(bluetooth_state))
                    if bluetooth_state:
                        async_dispatcher_send(
                            hass,
                            f"{DOMAIN}_{hide_email(email)}"[0:32],
                            {"bluetooth_change": bluetooth_state},
                        )
            elif command == "PUSH_MEDIA_QUEUE_CHANGE":
                # Player availability update
                if serial and serial in existing_serials:
                    _LOGGER.debug("Updating media_player queue %s",
                                  hide_serial(json_payload))
                    async_dispatcher_send(
                        hass,
                        f"{DOMAIN}_{hide_email(email)}"[0:32],
                        {"queue_state": json_payload},
                    )
            elif command == "PUSH_NOTIFICATION_CHANGE":
                # Player update
                await process_notifications(login_obj)
                if serial and serial in existing_serials:
                    _LOGGER.debug(
                        "Updating mediaplayer notifications: %s",
                        hide_serial(json_payload),
                    )
                    async_dispatcher_send(
                        hass,
                        f"{DOMAIN}_{hide_email(email)}"[0:32],
                        {"notification_update": json_payload},
                    )
            elif command in [
                    "PUSH_DELETE_DOPPLER_ACTIVITIES",  # delete Alexa history
                    "PUSH_LIST_ITEM_CHANGE",  # update shopping list
                    "PUSH_CONTENT_FOCUS_CHANGE",  # likely prime related refocus
                    "PUSH_DEVICE_SETUP_STATE_CHANGE",  # likely device changes mid setup
            ]:
                pass
            else:
                _LOGGER.warning(
                    "Unhandled command: %s with data %s. Please report at %s",
                    command,
                    hide_serial(json_payload),
                    ISSUE_URL,
                )
            if serial in existing_serials:
                history = hass.data[DATA_ALEXAMEDIA]["accounts"][email][
                    "websocket_activity"]["serials"].get(serial)
                if history is None or (
                        history
                        and command_time - history[len(history) - 1][1] > 2):
                    history = [(command, command_time)]
                else:
                    history.append([command, command_time])
                hass.data[DATA_ALEXAMEDIA]["accounts"][email][
                    "websocket_activity"]["serials"][serial] = history
                events = []
                for old_command, old_command_time in history:
                    if (old_command in {
                            "PUSH_VOLUME_CHANGE", "PUSH_EQUALIZER_STATE_CHANGE"
                    } and command_time - old_command_time < 0.25):
                        events.append((old_command,
                                       round(command_time - old_command_time,
                                             2)))
                    elif old_command in {"PUSH_AUDIO_PLAYER_STATE"}:
                        # There is a potential false positive generated during this event
                        events = []
                if len(events) >= 4:
                    _LOGGER.debug(
                        "%s: Detected potential DND websocket change with %s events %s",
                        hide_serial(serial),
                        len(events),
                        events,
                    )
                    await update_dnd_state(login_obj)
            if (serial and serial not in existing_serials
                    and serial not in (hass.data[DATA_ALEXAMEDIA]["accounts"]
                                       [email]["excluded"].keys())):
                _LOGGER.debug("Discovered new media_player %s", serial)
                (hass.data[DATA_ALEXAMEDIA]["accounts"][email]["new_devices"]
                 ) = True
                coordinator = hass.data[DATA_ALEXAMEDIA]["accounts"][
                    email].get("coordinator")
                if coordinator:
                    await coordinator.async_request_refresh()
Beispiel #45
0
async def test_uptime_sensors(
    hass,
    aioclient_mock,
    mock_unifi_websocket,
    initial_uptime,
    event_uptime,
    new_uptime,
):
    """Verify that uptime sensors are working as expected."""
    uptime_client = {
        "mac": "00:00:00:00:00:01",
        "name": "client1",
        "oui": "Producer",
        "uptime": initial_uptime,
    }
    options = {
        CONF_ALLOW_BANDWIDTH_SENSORS: False,
        CONF_ALLOW_UPTIME_SENSORS: True,
        CONF_TRACK_CLIENTS: False,
        CONF_TRACK_DEVICES: False,
    }

    now = datetime(2021, 1, 1, 1, 1, 0, tzinfo=dt_util.UTC)
    with patch("homeassistant.util.dt.now", return_value=now):
        config_entry = await setup_unifi_integration(
            hass,
            aioclient_mock,
            options=options,
            clients_response=[uptime_client],
        )

    assert len(hass.states.async_all()) == 2
    assert len(hass.states.async_entity_ids(SENSOR_DOMAIN)) == 1
    assert hass.states.get(
        "sensor.client1_uptime").state == "2021-01-01T01:00:00+00:00"

    ent_reg = er.async_get(hass)
    assert (ent_reg.async_get("sensor.client1_uptime").entity_category ==
            ENTITY_CATEGORY_DIAGNOSTIC)

    # Verify normal new event doesn't change uptime
    # 4 seconds has passed

    uptime_client["uptime"] = event_uptime
    now = datetime(2021, 1, 1, 1, 1, 4, tzinfo=dt_util.UTC)
    with patch("homeassistant.util.dt.now", return_value=now):
        mock_unifi_websocket(data={
            "meta": {
                "message": MESSAGE_CLIENT
            },
            "data": [uptime_client],
        })
        await hass.async_block_till_done()

    assert hass.states.get(
        "sensor.client1_uptime").state == "2021-01-01T01:00:00+00:00"

    # Verify new event change uptime
    # 1 month has passed

    uptime_client["uptime"] = new_uptime
    now = datetime(2021, 2, 1, 1, 1, 0, tzinfo=dt_util.UTC)
    with patch("homeassistant.util.dt.now", return_value=now):
        mock_unifi_websocket(data={
            "meta": {
                "message": MESSAGE_CLIENT
            },
            "data": [uptime_client],
        })
        await hass.async_block_till_done()

    assert hass.states.get(
        "sensor.client1_uptime").state == "2021-02-01T01:00:00+00:00"

    # Disable option

    options[CONF_ALLOW_UPTIME_SENSORS] = False
    hass.config_entries.async_update_entry(config_entry,
                                           options=options.copy())
    await hass.async_block_till_done()

    assert len(hass.states.async_all()) == 1
    assert len(hass.states.async_entity_ids(SENSOR_DOMAIN)) == 0
    assert hass.states.get("sensor.client1_uptime") is None

    # Enable option

    options[CONF_ALLOW_UPTIME_SENSORS] = True
    with patch("homeassistant.util.dt.now", return_value=now):
        hass.config_entries.async_update_entry(config_entry,
                                               options=options.copy())
        await hass.async_block_till_done()

    assert len(hass.states.async_all()) == 2
    assert len(hass.states.async_entity_ids(SENSOR_DOMAIN)) == 1
    assert hass.states.get("sensor.client1_uptime")

    # Try to add the sensors again, using a signal

    clients_connected = {uptime_client["mac"]}
    devices_connected = set()

    controller = hass.data[UNIFI_DOMAIN][config_entry.entry_id]

    async_dispatcher_send(
        hass,
        controller.signal_update,
        clients_connected,
        devices_connected,
    )
    await hass.async_block_till_done()

    assert len(hass.states.async_all()) == 2
    assert len(hass.states.async_entity_ids(SENSOR_DOMAIN)) == 1
Beispiel #46
0
 async def wrapper(self, *args, **kwargs):
     """Call decorated function and send update signal to all entities."""
     await func(self, *args, **kwargs)
     async_dispatcher_send(self.hass, DOMAIN)
Beispiel #47
0
async def test_switches(hass, aioclient_mock):
    """Test the update_items function with some clients."""
    config_entry = await setup_unifi_integration(
        hass,
        aioclient_mock,
        options={
            CONF_BLOCK_CLIENT: [BLOCKED["mac"], UNBLOCKED["mac"]],
            CONF_TRACK_CLIENTS: False,
            CONF_TRACK_DEVICES: False,
        },
        clients_response=[CLIENT_1, CLIENT_4],
        devices_response=[DEVICE_1],
        clients_all_response=[BLOCKED, UNBLOCKED, CLIENT_1],
        dpigroup_response=DPI_GROUPS,
        dpiapp_response=DPI_APPS,
    )
    controller = hass.data[UNIFI_DOMAIN][config_entry.entry_id]

    assert len(hass.states.async_entity_ids(SWITCH_DOMAIN)) == 4

    switch_1 = hass.states.get("switch.poe_client_1")
    assert switch_1 is not None
    assert switch_1.state == "on"
    assert switch_1.attributes["power"] == "2.56"
    assert switch_1.attributes[SWITCH_DOMAIN] == "00:00:00:00:01:01"
    assert switch_1.attributes["port"] == 1
    assert switch_1.attributes["poe_mode"] == "auto"

    switch_4 = hass.states.get("switch.poe_client_4")
    assert switch_4 is None

    blocked = hass.states.get("switch.block_client_1")
    assert blocked is not None
    assert blocked.state == "off"

    unblocked = hass.states.get("switch.block_client_2")
    assert unblocked is not None
    assert unblocked.state == "on"

    dpi_switch = hass.states.get("switch.block_media_streaming")
    assert dpi_switch is not None
    assert dpi_switch.state == "on"
    assert dpi_switch.attributes["icon"] == "mdi:network"

    ent_reg = er.async_get(hass)
    for entry_id in (
            "switch.poe_client_1",
            "switch.block_client_1",
            "switch.block_media_streaming",
    ):
        assert ent_reg.async_get(
            entry_id).entity_category is EntityCategory.CONFIG

    # Block and unblock client

    aioclient_mock.post(
        f"https://{controller.host}:1234/api/s/{controller.site}/cmd/stamgr", )

    await hass.services.async_call(SWITCH_DOMAIN,
                                   "turn_off",
                                   {"entity_id": "switch.block_client_1"},
                                   blocking=True)
    assert aioclient_mock.call_count == 11
    assert aioclient_mock.mock_calls[10][2] == {
        "mac": "00:00:00:00:01:01",
        "cmd": "block-sta",
    }

    await hass.services.async_call(SWITCH_DOMAIN,
                                   "turn_on",
                                   {"entity_id": "switch.block_client_1"},
                                   blocking=True)
    assert aioclient_mock.call_count == 12
    assert aioclient_mock.mock_calls[11][2] == {
        "mac": "00:00:00:00:01:01",
        "cmd": "unblock-sta",
    }

    # Enable and disable DPI

    aioclient_mock.put(
        f"https://{controller.host}:1234/api/s/{controller.site}/rest/dpiapp/5f976f62e3c58f018ec7e17d",
    )

    await hass.services.async_call(
        SWITCH_DOMAIN,
        "turn_off",
        {"entity_id": "switch.block_media_streaming"},
        blocking=True,
    )
    assert aioclient_mock.call_count == 13
    assert aioclient_mock.mock_calls[12][2] == {"enabled": False}

    await hass.services.async_call(
        SWITCH_DOMAIN,
        "turn_on",
        {"entity_id": "switch.block_media_streaming"},
        blocking=True,
    )
    assert aioclient_mock.call_count == 14
    assert aioclient_mock.mock_calls[13][2] == {"enabled": True}

    # Make sure no duplicates arise on generic signal update
    async_dispatcher_send(hass, controller.signal_update)
    await hass.async_block_till_done()
    assert len(hass.states.async_entity_ids(SWITCH_DOMAIN)) == 4
Beispiel #48
0
 def send_removed_signal():
     async_dispatcher_send(self.hass, SIGNAL_GROUP_ENTITY_REMOVED,
                           self._group_id)
 def _dispatch(signal, entity_ids, *args):
     for entity_id in entity_ids:
         async_dispatcher_send(hass, '{}_{}'.format(signal, entity_id),
                               *args)
Beispiel #50
0
 def controller_disconnected(self, ctrl: Controller, ex: Exception) -> None:
     """On disconnect from controller."""
     async_dispatcher_send(self.hass, DISPATCH_CONTROLLER_DISCONNECTED,
                           ctrl, ex)
Beispiel #51
0
 def partition_updated_callback(data):
     """Handle partition changes thrown by evl (including alarms)."""
     _LOGGER.debug("The envisalink sent a partition update event")
     async_dispatcher_send(hass, SIGNAL_PARTITION_UPDATE, data)
Beispiel #52
0
async def async_signal_options_update(hass: HomeAssistantType,
                                      config_entry: ConfigEntry) -> None:
    """Handle config entry options update."""
    async_dispatcher_send(hass, UPDATE_OPTIONS_SIGNAL, config_entry)
Beispiel #53
0
 def zones_updated_callback(data):
     """Handle zone timer updates."""
     _LOGGER.debug("Envisalink sent a zone update event. Updating zones...")
     async_dispatcher_send(hass, SIGNAL_ZONE_UPDATE, data)
Beispiel #54
0
 def dispatcher_message(self, identifier: str, data: Any = None) -> None:
     """Match cloud notification to dispatcher."""
     if identifier.startswith("remote_"):
         async_dispatcher_send(self._hass, DISPATCHER_REMOTE_UPDATE, data)
Beispiel #55
0
                logger=_LOGGER,
                name="Fjaraskupan Updater",
                update_interval=timedelta(seconds=120),
                update_method=async_update_data,
            )
            coordinator.async_set_updated_data(device.state)

            device_info = DeviceInfo(
                identifiers={(DOMAIN, ble_device.address)},
                manufacturer="Fjäråskupan",
                name="Fjäråskupan",
            )
            device_state = DeviceState(device, coordinator, device_info)
            state.devices[ble_device.address] = device_state
            async_dispatcher_send(hass,
                                  f"{DISPATCH_DETECTION}.{entry.entry_id}",
                                  device_state)

    scanner.register_detection_callback(detection_callback)
    await scanner.start()

    hass.config_entries.async_setup_platforms(entry, PLATFORMS)
    return True


@callback
def async_setup_entry_platform(
    hass: HomeAssistant,
    entry: ConfigEntry,
    async_add_entities: AddEntitiesCallback,
    constructor: Callable[[DeviceState], list[Entity]],
Beispiel #56
0
 def add_device() -> None:
     async_dispatcher_send(
         hass, f"{DOMAIN}_{entry.entry_id}_add_{SENSOR_DOMAIN}", device)
Beispiel #57
0
 def controller_update(self, ctrl: Controller) -> None:
     """System update message is received from the controller."""
     async_dispatcher_send(self.hass, DISPATCH_CONTROLLER_UPDATE, ctrl)
Beispiel #58
0
 def outputs_update_callback(status):
     """Update zone objects as per notification from the alarm."""
     _LOGGER.debug("Outputs updated callback , status: %s", status)
     async_dispatcher_send(hass, SIGNAL_OUTPUTS_UPDATED, status["outputs"])
Beispiel #59
0
 def controller_discovered(self, ctrl: Controller) -> None:
     """Handle new controller discoverery."""
     async_dispatcher_send(self.hass, DISPATCH_CONTROLLER_DISCOVERED, ctrl)
 def _remove_events(self, events):
     """Remove old geo location events."""
     _LOGGER.debug("Going to remove %s", events)
     for event in events:
         async_dispatcher_send(
             self._hass, SIGNAL_DELETE_ENTITY.format(event._strike_id))