Skip to content

Commit

Permalink
Merge pull request #121 from custom-components/custom_names
Browse files Browse the repository at this point in the history
Sensor names option
  • Loading branch information
Ernst79 authored Oct 17, 2020
2 parents 0783c15 + 281cdfc commit 48725ec
Show file tree
Hide file tree
Showing 4 changed files with 115 additions and 48 deletions.
18 changes: 16 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,8 @@ sensor:
batt_entities: False
encryptors:
'A4:C1:38:2F:86:6C': '217C568CF5D22808DA20181502D84C1B'
sensor_names:
'A4:C1:38:2F:86:6C': 'Livingroom'
report_unknown: False
whitelist: False
```
Expand Down Expand Up @@ -230,6 +232,18 @@ Note: The encryptors parameter is only needed for sensors, for which it is [poin
'A4:C1:38:D1:61:7D': 'C99D2313182473B38001086FEBF781BD'
```
#### sensor_names
(dictionary)(Optional) Use this option to link a sensor name to the mac-address of the sensor. Using this option (or changing a name) will create new entities after restarting Home Assistant. These sensors are named with the following convention: `sensor.mi_sensortype_sensor_name` (e.g. `sensor.mi_temperature_livingroom`) in stead of the default `mi_sensortype_mac` (e.g. `sensor.mi_temperature_A4C1382F86C`). You will have to update your lovelace cards, automation and scripts after each change. Note that you can still override the entity_id from the UI. After the change, you can manually delete the old entities from the Developer Tools section. The old data won't be transfered to the new sensor. Default value: Empty

```yaml
sensor:
- platform: mitemp_bt
sensor_names:
'A4:C1:38:2F:86:6C': 'Livingroom'
'A4:C1:38:D1:61:7D': 'Bedroom'
```

#### report_unknown

(boolean)(Optional) This option is needed primarily for those who want to request an implementation of device support that is not in the list of [supported sensors](#supported-sensors). If you set this parameter to `True`, then the component will log all messages from unknown Xiaomi ecosystem devices to the Home Assitant log. **Attention!** Enabling this option can lead to huge output to the Home Assistant log, do not enable it if you do not need it! Details in the [FAQ](https://github.com/custom-components/sensor.mitemp_bt/blob/master/faq.md#my-sensor-from-the-xiaomi-ecosystem-is-not-in-the-list-of-supported-ones-how-to-request-implementation). Default value: False
Expand All @@ -247,8 +261,8 @@ Note: The encryptors parameter is only needed for sensors, for which it is [poin
```

Data from sensors with other addresses will be ignored.
In addition, all addresses listed in the `encryptors` option will be automatically whitelisted.
If you have no sensors other than those listed in `encryptors`, then just set `whitelist` to `True`:
In addition, all addresses listed in the `encryptors` and `sensor_names` option will be automatically whitelisted.
If you have no sensors other than those listed in `encryptors` and/or `sensor_names`, then just set `whitelist` to `True`:

```yaml
sensor:
Expand Down
1 change: 1 addition & 0 deletions custom_components/mitemp_bt/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
CONF_ENCRYPTORS = "encryptors"
CONF_REPORT_UNKNOWN = "report_unknown"
CONF_WHITELIST = "whitelist"
CONF_SENSOR_NAMES = "sensor_names"

# Default values for configuration options
DEFAULT_ROUNDING = True
Expand Down
112 changes: 72 additions & 40 deletions custom_components/mitemp_bt/sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@
CONF_ENCRYPTORS,
CONF_REPORT_UNKNOWN,
CONF_WHITELIST,
CONF_SENSOR_NAMES,
CONF_TMIN,
CONF_TMAX,
CONF_HMIN,
Expand All @@ -70,6 +71,12 @@
MAC_REGEX = "(?i)^(?:[0-9A-F]{2}[:]){5}(?:[0-9A-F]{2})$"
AES128KEY_REGEX = "(?i)^[A-F0-9]{32}$"

SENSOR_NAMES_LIST_SCHEMA = vol.Schema(
{
cv.matches_regex(MAC_REGEX): cv.string
}
)

ENCRYPTORS_LIST_SCHEMA = vol.Schema(
{
cv.matches_regex(MAC_REGEX): cv.matches_regex(AES128KEY_REGEX)
Expand All @@ -93,6 +100,7 @@
vol.Optional(
CONF_WHITELIST, default=DEFAULT_WHITELIST
): vol.Any(vol.All(cv.ensure_list, [cv.matches_regex(MAC_REGEX)]), cv.boolean),
vol.Optional(CONF_SENSOR_NAMES, default={}): SENSOR_NAMES_LIST_SCHEMA,
}
)

Expand Down Expand Up @@ -363,6 +371,16 @@ def parse_raw_message(data, aeskeyslist, whitelist, report_unknown=False):
return result


def sensor_name(config, mac):
"""Set sensor name."""
fmac = ':'.join(mac[i:i+2] for i in range(0, len(mac), 2))
if fmac in config[CONF_SENSOR_NAMES]:
custom_name = config[CONF_SENSOR_NAMES].get(fmac)
_LOGGER.debug("Name of sensor with mac adress %s is set to: %s", fmac, custom_name)
return custom_name
return mac


class BLEScanner:
"""BLE scanner."""

Expand Down Expand Up @@ -450,11 +468,15 @@ def lpacket(mac, packet=None):
if config[CONF_WHITELIST] is True:
for mac in config[CONF_ENCRYPTORS]:
whitelist.append(mac)
for mac in config[CONF_SENSOR_NAMES]:
whitelist.append(mac)
if isinstance(config[CONF_WHITELIST], list):
for mac in config[CONF_WHITELIST]:
whitelist.append(mac)
for mac in config[CONF_ENCRYPTORS]:
whitelist.append(mac)
for mac in config[CONF_SENSOR_NAMES]:
whitelist.append(mac)
for i, mac in enumerate(whitelist):
whitelist[i] = bytes.fromhex(reverse_mac(mac.replace(":", "")).lower())
_LOGGER.debug("%s whitelist item(s) loaded.", len(whitelist))
Expand Down Expand Up @@ -625,31 +647,31 @@ def discover_ble_devices(config, aeskeyslist, whitelist):
else:
sensors = []
if t_i != 9:
sensors.insert(t_i, TemperatureSensor(mac))
sensors.insert(t_i, TemperatureSensor(config, mac))
if h_i != 9:
sensors.insert(h_i, HumiditySensor(mac))
sensors.insert(h_i, HumiditySensor(config, mac))
if m_i != 9:
sensors.insert(m_i, MoistureSensor(mac))
sensors.insert(m_i, MoistureSensor(config, mac))
if c_i != 9:
sensors.insert(c_i, ConductivitySensor(mac))
sensors.insert(c_i, ConductivitySensor(config, mac))
if i_i != 9:
sensors.insert(i_i, IlluminanceSensor(mac))
sensors.insert(i_i, IlluminanceSensor(config, mac))
if f_i != 9:
sensors.insert(f_i, FormaldehydeSensor(mac))
sensors.insert(f_i, FormaldehydeSensor(confing, mac))
if cn_i != 9:
sensors.insert(cn_i, ConsumableSensor(mac))
sensors.insert(cn_i, ConsumableSensor(config, mac))
try:
setattr(sensors[cn_i], "_cn_name", CN_NAME_DICT[stype[mac]])
except KeyError:
pass
if sw_i != 9:
sensors.insert(sw_i, SwitchBinarySensor(mac))
sensors.insert(sw_i, SwitchBinarySensor(config, mac))
try:
setattr(sensors[sw_i], "_swclass", SW_CLASS_DICT[stype[mac]])
except KeyError:
pass
if config[CONF_BATT_ENTITIES] and (b_i != 9):
sensors.insert(b_i, BatterySensor(mac))
sensors.insert(b_i, BatterySensor(config, mac))
sensors_by_mac[mac] = sensors
add_entities(sensors)
# append joint attributes
Expand All @@ -661,6 +683,9 @@ def discover_ble_devices(config, aeskeyslist, whitelist):
sts.mean(rssi[mac])
)
getattr(sensor, "_device_state_attributes")["sensor type"] = stype[mac]
getattr(sensor, "_device_state_attributes")["mac address"] = (
':'.join(mac[i:i+2] for i in range(0, len(mac), 2))
)
if not isinstance(sensor, BatterySensor) and mac in batt:
getattr(sensor, "_device_state_attributes")[
ATTR_BATTERY_LEVEL
Expand Down Expand Up @@ -791,18 +816,18 @@ def update_ble(now):

class TemperatureSensor(Entity):
"""Representation of a sensor."""

def __init__(self, mac):
"""Initialize the sensor."""
def __init__(self, config, mac):
"Initialize the sensor."""
self._state = None
self._battery = None
self._unique_id = "t_" + mac
self._sensor_name = sensor_name(config, mac)
self._unique_id = "t_" + sensor_name(config, mac)
self._device_state_attributes = {}

@property
def name(self):
"""Return the name of the sensor."""
return "mi {}".format(self._unique_id)
return "mi temperature {}".format(self._sensor_name)

@property
def state(self):
Expand Down Expand Up @@ -843,17 +868,18 @@ def force_update(self):
class HumiditySensor(Entity):
"""Representation of a Sensor."""

def __init__(self, mac):
def __init__(self, config, mac):
"""Initialize the sensor."""
self._state = None
self._battery = None
self._unique_id = "h_" + mac
self._sensor_name = sensor_name(config, mac)
self._unique_id = "h_" + sensor_name(config, mac)
self._device_state_attributes = {}

@property
def name(self):
"""Return the name of the sensor."""
return "mi {}".format(self._unique_id)
return "mi humidity {}".format(self._sensor_name)

@property
def state(self):
Expand Down Expand Up @@ -894,17 +920,18 @@ def force_update(self):
class MoistureSensor(Entity):
"""Representation of a Sensor."""

def __init__(self, mac):
def __init__(self, config, mac):
"""Initialize the sensor."""
self._state = None
self._battery = None
self._unique_id = "m_" + mac
self._sensor_name = sensor_name(config, mac)
self._unique_id = "m_" + sensor_name(config, mac)
self._device_state_attributes = {}

@property
def name(self):
"""Return the name of the sensor."""
return "mi {}".format(self._unique_id)
return "mi moisture {}".format(self._sensor_name)

@property
def state(self):
Expand Down Expand Up @@ -945,17 +972,18 @@ def force_update(self):
class ConductivitySensor(Entity):
"""Representation of a Sensor."""

def __init__(self, mac):
def __init__(self, config, mac):
"""Initialize the sensor."""
self._state = None
self._battery = None
self._unique_id = "c_" + mac
self._sensor_name = sensor_name(config, mac)
self._unique_id = "c_" + sensor_name(config, mac)
self._device_state_attributes = {}

@property
def name(self):
"""Return the name of the sensor."""
return "mi {}".format(self._unique_id)
return "mi conductivity {}".format(self._sensor_name)

@property
def state(self):
Expand Down Expand Up @@ -996,17 +1024,18 @@ def force_update(self):
class IlluminanceSensor(Entity):
"""Representation of a Sensor."""

def __init__(self, mac):
def __init__(self, config, mac):
"""Initialize the sensor."""
self._state = None
self._battery = None
self._unique_id = "l_" + mac
self._sensor_name = sensor_name(config, mac)
self._unique_id = "l_" + sensor_name(config, mac)
self._device_state_attributes = {}

@property
def name(self):
"""Return the name of the sensor."""
return "mi {}".format(self._unique_id)
return "mi llluminance {}".format(self._sensor_name)

@property
def state(self):
Expand Down Expand Up @@ -1046,17 +1075,18 @@ def force_update(self):
class FormaldehydeSensor(Entity):
"""Representation of a Sensor."""

def __init__(self, mac):
def __init__(self, config, mac):
"""Initialize the sensor."""
self._state = None
self._battery = None
self._unique_id = "f_" + mac
self._sensor_name = sensor_name(config, mac)
self._unique_id = "f_" + sensor_name(config, mac)
self._device_state_attributes = {}

@property
def name(self):
"""Return the name of the sensor."""
return "mi {}".format(self._unique_id)
return "mi formaldehyde {}".format(self._sensor_name)

@property
def state(self):
Expand Down Expand Up @@ -1096,16 +1126,17 @@ def force_update(self):
class BatterySensor(Entity):
"""Representation of a Sensor."""

def __init__(self, mac):
def __init__(self, config, mac):
"""Initialize the sensor."""
self._state = None
self._unique_id = "batt_" + mac
self._sensor_name = sensor_name(config, mac)
self._unique_id = "batt_" + sensor_name(config, mac)
self._device_state_attributes = {}

@property
def name(self):
"""Return the name of the sensor."""
return "mi {}".format(self._unique_id)
return "mi battery {}".format(self._sensor_name)

@property
def state(self):
Expand Down Expand Up @@ -1145,18 +1176,18 @@ def force_update(self):
class ConsumableSensor(Entity):
"""Representation of a Sensor."""

def __init__(self, mac):
def __init__(self, config, mac):
"""Initialize the sensor."""
self._state = None
self._battery = None
self._cn_name = "cn_"
self._nmac = mac
self._sensor_name = sensor_name(config, mac)
self._unique_id = "cn_" + sensor_name(config, mac)
self._device_state_attributes = {}

@property
def name(self):
"""Return the name of the sensor."""
return "mi {}".format(self._cn_name + self._nmac)
return "mi consumable {}".format(self._sensor_name)

@property
def state(self):
Expand Down Expand Up @@ -1186,7 +1217,7 @@ def device_state_attributes(self):
@property
def unique_id(self) -> str:
"""Return a unique ID."""
return self._cn_name + self._nmac
return self._unique_id

@property
def force_update(self):
Expand All @@ -1196,12 +1227,13 @@ def force_update(self):
class SwitchBinarySensor(BinarySensorEntity):
"""Representation of a Sensor."""

def __init__(self, mac):
def __init__(self, config, mac):
"""Initialize the sensor."""
self._state = None
self._swclass = None
self._battery = None
self._unique_id = "sw_" + mac
self._sensor_name = sensor_name(config, mac)
self._unique_id = "sw_" + sensor_name(config, mac)
self._device_state_attributes = {}

@property
Expand All @@ -1212,7 +1244,7 @@ def is_on(self):
@property
def name(self):
"""Return the name of the sensor."""
return "mi {}".format(self._unique_id)
return "mi switch {}".format(self._sensor_name)

@property
def state(self):
Expand Down
Loading

0 comments on commit 48725ec

Please sign in to comment.