Ejemplo n.º 1
0
async def _make_sensor(device_class, discovery_info):
    """Create ZHA sensors factory."""
    from zigpy.zcl.clusters.general import OnOff
    from zigpy.zcl.clusters.measurement import OccupancySensing

    in_clusters = discovery_info['in_clusters']
    out_clusters = discovery_info['out_clusters']
    endpoint = discovery_info['endpoint']
    if endpoint.device_type in (0x0800, 0x0810, 0x0820, 0x0830, 0x0000, 0x0001,
                                0x0006):
        sensor = RemoteSensor('remote', **discovery_info)
    elif (OnOff.cluster_id in in_clusters or OnOff.cluster_id in out_clusters):
        sensor = OnOffSensor('opening',
                             **discovery_info,
                             cluster_key=OnOff.ep_attribute)
    elif (OccupancySensing.cluster_id in in_clusters
          or OccupancySensing.cluster_id in out_clusters):
        sensor = OccupancySensor('motion',
                                 **discovery_info,
                                 cluster_key=OccupancySensing.ep_attribute)

#       try:
#           result = await zha_new.get_attributes(
#                           endpoint,
#                           OccupancySensing.cluster_id,
#                           ['occupancy', 'occupancy_sensor_type'])
#           sensor._device_state_attributes['occupancy_sensor_type'] = result[1]
#           sensor._state = result[0]
#       except:
#           _LOGGER.debug("get attributes: failed")
    elif device_class == 'moisture':
        sensor = MoistureSensor('moisture', **discovery_info)
    else:
        sensor = BinarySensor(device_class, **discovery_info)

    if discovery_info['new_join']:
        for cluster in in_clusters.values():
            v = await cluster.bind()
            if v[0]:
                _LOGGER.error("[0x%04x:%s] bind input-cluster failed %s",
                              endpoint._device.nwk, endpoint.endpoint_id,
                              Status(v[0]).name)
            _LOGGER.debug("[0x%04x:%s] bind input-cluster %s: %s",
                          endpoint._device.nwk, endpoint.endpoint_id,
                          cluster.cluster_id, v)
        for cluster in out_clusters.values():
            v = await cluster.bind()
            if v[0]:
                _LOGGER.error("[0x%04x:%s] bind output-cluster failed %s",
                              endpoint._device.nwk, endpoint.endpoint_id,
                              Status(v[0]).name)
            _LOGGER.debug("[0x%04x:%s] bind output-cluster %s: %s",
                          endpoint._device.nwk, endpoint.endpoint_id,
                          cluster.cluster_id, v)

    _LOGGER.debug("[0x%04x:%s] exit make binary-sensor ", endpoint._device.nwk,
                  endpoint.endpoint_id)
    return sensor
Ejemplo n.º 2
0
async def _make_sensor(device_class, discovery_info):
    """Create ZHA sensors factory."""

    in_clusters = discovery_info['in_clusters']
    out_clusters = discovery_info['out_clusters']
    endpoint = discovery_info['endpoint']
    if endpoint.device_type in (
            0x0800,
            0x0810,
            0x0820,
            0x0830,
            0x0000,
            0x0001,
            0x0006,
    ):
        sensor = RemoteSensor('remote', **discovery_info)
    elif device_class == 'moisture':
        sensor = MoistureSensor('moisture', **discovery_info)
    elif device_class == 'motion':
        sensor = OccupancySensor('motion', **discovery_info)
    elif (OnOff.cluster_id in in_clusters or OnOff.cluster_id in out_clusters):
        sensor = OnOffSensor('opening',
                             **discovery_info,
                             cluster_key=OnOff.ep_attribute)
    elif (OccupancySensing.cluster_id in in_clusters
          or OccupancySensing.cluster_id in out_clusters):
        sensor = OccupancySensor('motion',
                                 **discovery_info,
                                 cluster_key=OccupancySensing.ep_attribute)
    else:
        sensor = BinarySensor(device_class, **discovery_info)

    if discovery_info['new_join']:
        for cluster in in_clusters.values():
            try:
                v = await cluster.bind()
            except Exception:
                v = [Status.TIMEOUT]
            if v[0]:
                _LOGGER.error("[0x%04x:%s] bind input-cluster failed %s",
                              endpoint._device.nwk, endpoint.endpoint_id,
                              Status(v[0]).name)
            _LOGGER.debug("[0x%04x:%s] bind input-cluster %s: %s",
                          endpoint._device.nwk, endpoint.endpoint_id,
                          cluster.cluster_id, v)

    _LOGGER.debug("[0x%04x:%s] exit make binary-sensor ", endpoint._device.nwk,
                  endpoint.endpoint_id)
    return sensor
Ejemplo n.º 3
0
    async def async_device_initialized(self, device, join):
        """Handle device joined and basic information discovered (async)."""
        from zigpy.zdo.types import Status
        import zigpy.profiles
        populate_data()
        discovered_info = {}
        out_clusters = []
        model = None
        # loop over endpoints
        _LOGGER.debug("[0x%04x] device init for %s -> Endpoints: %s",
                      device.nwk, device.ieee, list(device.endpoints.keys()))
        for endpoint_id, endpoint in device.endpoints.items():
            _LOGGER.debug(
                "[0x%04x:%s] endpoint init",
                device.nwk,
                endpoint_id,
            )
            if endpoint_id == 0:  # ZDO
                continue

            component = None
            profile_clusters = [set(), set()]
            device_key = '%s-%s' % (str(device.ieee), endpoint_id)
            node_config = self._config[DOMAIN][CONF_DEVICE_CONFIG].get(
                device_key, {})
            _LOGGER.debug("[0x%04x:%s] node config for %s: %s", device.nwk,
                          endpoint_id, device_key, node_config)

            if CONF_TEMPLATE in node_config:
                device_model = model = node_config.get(CONF_TEMPLATE,
                                                       "default")
                if device_model not in self.custom_devices:
                    self.custom_devices[
                        device_model] = custom_module = get_custom_device_info(
                            device_model)
                else:
                    custom_module = self.custom_devices[device_model]
                if '_custom_endpoint_init' in custom_module:
                    custom_module['_custom_endpoint_init'](endpoint,
                                                           node_config,
                                                           device_model)

            if CONF_MANUFACTURER in node_config:
                discovered_info[CONF_MANUFACTURER] = node_config[
                    CONF_MANUFACTURER]
            if CONF_MODEL in node_config:
                discovered_info[CONF_MODEL] = node_config[CONF_MODEL]
            elif 0 in endpoint.in_clusters:
                # just get device_info if cluster 0 exists
                #                if join:
                #                    v = await discover_cluster_values(endpoint, endpoint.in_clusters[0])
                discovered_info = await _discover_endpoint_info(endpoint)
            if model is not None and discovered_info[CONF_MODEL] is None:
                discovered_info[CONF_MODEL] = model

            # when a model name is available and not the template already applied,
            # use it to do custom init
            if (discovered_info[CONF_MODEL] is not None
                    and CONF_TEMPLATE not in node_config):
                device_model = model = discovered_info[CONF_MODEL]
                if device_model not in self.custom_devices:
                    self.custom_devices[
                        device_model] = custom_module = get_custom_device_info(
                            device_model)
                else:
                    custom_module = self.custom_devices[device_model]
                _LOGGER.debug('[0x%04x:%s] pre call _custom_endpoint_init: %s',
                              device.nwk, endpoint_id, custom_module)

                if custom_module.get('_custom_endpoint_init',
                                     None) is not None:
                    _LOGGER.debug('[0x%04x:%s] call _custom_endpoint_init: %s',
                                  device.nwk, endpoint_id, device_model)
                    custom_module['_custom_endpoint_init'](endpoint,
                                                           node_config,
                                                           device_model)
                else:
                    _LOGGER.debug(
                        '[0x%04x:%s] no call _custom_endpoint_init: %s',
                        device.nwk, endpoint_id, device_model)

            _LOGGER.debug("[0x%04x:%s] node config for %s: %s", device.nwk,
                          endpoint_id, device_key, node_config)

            if endpoint.profile_id in zigpy.profiles.PROFILES:
                profile = zigpy.profiles.PROFILES[endpoint.profile_id]
                if DEVICE_CLASS.get(endpoint.profile_id,
                                    {}).get(endpoint.device_type, None):
                    profile_clusters[0].update(
                        profile.CLUSTERS[endpoint.device_type][0])
                    profile_clusters[1].update(
                        profile.CLUSTERS[endpoint.device_type][1])
                    profile_info = DEVICE_CLASS[endpoint.profile_id]
                    component = profile_info[endpoint.device_type]
#            _LOGGER.debug("profile for %s: %s", device_key, profile_info)
# Override type (switch,light,sensor, binary_sensor,...) from config
            if ha_const.CONF_TYPE in node_config:
                component = node_config[ha_const.CONF_TYPE]
            if component in COMPONENT_CLUSTERS:
                profile_clusters = list(COMPONENT_CLUSTERS[component])

            # Add allowed In_Clusters from config
            if CONF_IN_CLUSTER in node_config:
                a = set(node_config.get(CONF_IN_CLUSTER))

                #                _LOGGER.debug('%s', type(profile_clusters))
                profile_clusters[0] = a
            # Add allowed Out_Clusters from config
            if CONF_OUT_CLUSTER in node_config:
                profile_clusters[1] = set(node_config.get(CONF_OUT_CLUSTER))

            async def req_conf_report(report_cls, report_attr, report_min,
                                      report_max, report_change):
                try:
                    await report_cls.bind()
                    v = await report_cls.configure_reporting(
                        report_attr, int(report_min), int(report_max),
                        report_change)
                    _LOGGER.debug(
                        "[0x%04x:%s] %s: set config report %s status: %s",
                        device.nwk, endpoint_id, device_key,
                        report_cls.cluster_id, v[0])
                except:
                    _LOGGER.error(
                        "[0x%04x:%s] %s:set config report failed: %s",
                        device.nwk, endpoint_id, device_key,
                        report_cls.cluster_id)

            # if reporting is configured in yaml,
            # then create cluster if needed and setup reporting
            if join and CONF_CONFIG_REPORT in node_config:
                for report in node_config.get(CONF_CONFIG_REPORT):
                    report_cls, report_attr, report_min, report_max, report_change = report
                    if report_cls in endpoint.in_clusters:
                        cluster = endpoint.in_clusters[report_cls]
                        await req_conf_report(cluster, report_attr, report_min,
                                              report_max, report_change)
#                        elif report_cls in endpoint.out_clusters:
#                            cluster = endpoint.out_clusters[report_cls]
#                            await req_conf_report(
#                                cluster,
#                                report_attr,
#                                report_min,
#                                report_max,
#                                report_change)
            else:
                _LOGGER.debug(
                    "[0x%04x:%s] config reports skipped, already joined %s",
                    device.nwk, endpoint_id, device._ieee)

            _LOGGER.debug("[0x%04x:%s] 2:profile %s, component: %s cluster:%s",
                          device.nwk, endpoint_id, endpoint.profile_id,
                          component, profile_clusters)
            if component:
                # only discovered clusters that are in the profile or configuration listed
                in_clusters = [
                    endpoint.in_clusters[c] for c in profile_clusters[0]
                    if c in endpoint.in_clusters
                ]
                out_clusters = [
                    endpoint.out_clusters[c] for c in profile_clusters[1]
                    if c in endpoint.out_clusters
                ]

                if in_clusters != [] or out_clusters != []:

                    # create  discovery info
                    discovery_info = {
                        'endpoint': endpoint,
                        'in_clusters': {c.cluster_id: c
                                        for c in in_clusters},
                        'out_clusters':
                        {c.cluster_id: c
                         for c in out_clusters},
                        'component': component,
                        'device': device,
                        'domain': DOMAIN,
                        'discovery_key': device_key,
                        'new_join': join,
                        'application': self
                    }

                    discovery_info.update(discovered_info)
                    self._hass.data[DISCOVERY_KEY][device_key] = discovery_info
                    """ goto to the specific code for switch,
                    light sensor or binary_sensor """
                    await discovery.async_load_platform(
                        self._hass,
                        component,
                        DOMAIN,
                        {'discovery_key': device_key},
                        self._config,
                    )
                    _LOGGER.debug(
                        "[0x%04x:%s] Return from component general entity:%s",
                        device.nwk, endpoint_id, device._ieee)

            # initialize single clusters
            for cluster_id, cluster in endpoint.in_clusters.items():
                cluster_type = type(cluster)
                #                _LOGGER.debug("[0x%04x:%s] Start single-cluster entity: %s",
                #                              device.nwk,
                #                              endpoint_id,
                #                              cluster_id)
                if cluster_id in profile_clusters[0]:
                    continue
                if cluster_type not in SINGLE_CLUSTER_DEVICE_CLASS:
                    continue
                if ha_const.CONF_TYPE in node_config:
                    component = node_config[ha_const.CONF_TYPE]
                else:
                    component = SINGLE_CLUSTER_DEVICE_CLASS[cluster_type]

                cluster_key = '%s-%s' % (device_key, cluster_id)
                # cluster key -> single cluster
                discovery_info = {
                    'discovery_key': cluster_key,
                    'endpoint': endpoint,
                    'in_clusters': {
                        cluster.cluster_id: cluster
                    },
                    'out_clusters': {},
                    'new_join': join,
                    'domain': DOMAIN,
                    'component': component,
                    'application': self
                }
                discovery_info.update(discovered_info)

                self._hass.data[DISCOVERY_KEY][cluster_key] = discovery_info
                _LOGGER.debug("[0x%04x:%s] Call single-cluster entity: %s",
                              device.nwk, endpoint_id, cluster_id)
                await discovery.async_load_platform(
                    self._hass,
                    component,
                    DOMAIN,
                    {'discovery_key': cluster_key},
                    self._config,
                )
#                in_clusters.append(cluster)
#                _LOGGER.debug("[0x%04x] Return from single-cluster entity:%s",
#                              device.nwk,
#                              discovery_info)

#            _LOGGER.debug("[0x%04x:%s] Start bind clusters",
#                          device.nwk,
#                          endpoint_id)
            if join:
                for cluster in out_clusters:
                    try:
                        v = await cluster.bind()
                        if v[0]:
                            _LOGGER.error(
                                "[0x%04x:%s] bind output-cluster failed %s : %s",
                                device.nwk, endpoint_id, cluster.cluster_id,
                                Status(v[0]).name)
                    except Exception:
                        _LOGGER.error(
                            "[0x%04x:%s] bind output-cluster exception %s ",
                            device.nwk, endpoint_id, cluster.cluster_id)


#                    _LOGGER.debug("[0x%04x:%s] bind output-cluster %s: %s",
#                                  device.nwk,
#                                  endpoint_id,
#                                  cluster.cluster_id,
#                                  v)

#                _LOGGER.debug("[0x%04x] Exit endpoint init: Input:%s Output:%s",
#                              device.nwk,
#                              list(endpoint.in_clusters.keys()),
#                              list(endpoint.out_clusters.keys())
#                              )
        device._application.listener_event('device_updated', device)
        self.controller._state = 'Run'
        self.controller._device_state_attributes['no_of_entities'] = len(
            self._entity_list)
        self.controller.async_schedule_update_ha_state()
        _LOGGER.debug(
            "[0x%04x] Exit device init %s",
            device.nwk,
            device.ieee,
        )