Skip to content

Commit

Permalink
Cleanup. Sort the batteries so I can find missing ones easier.
Browse files Browse the repository at this point in the history
Add the leak sensor as a binary sensor.  Needs testing.
Minor prep work for sensors not initially registered, just a warning for
now.
  • Loading branch information
garbled1 committed Nov 12, 2020
1 parent 51e1409 commit 8989112
Show file tree
Hide file tree
Showing 5 changed files with 172 additions and 53 deletions.
154 changes: 105 additions & 49 deletions custom_components/ecowitt/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@

from homeassistant.const import (
DEGREE,
EVENT_HOMEASSISTANT_STOP,
CONF_PORT,
CONF_UNIT_SYSTEM_METRIC,
CONF_UNIT_SYSTEM_IMPERIAL,
Expand All @@ -48,11 +47,13 @@
DEVICE_CLASS_TEMPERATURE,
DEVICE_CLASS_PRESSURE,
DEVICE_CLASS_TIMESTAMP,
DEVICE_CLASS_MOISTURE,
)

_LOGGER = logging.getLogger(__name__)

TYPE_SENSOR = "sensor"
TYPE_BINARY_SENSOR = "binary_sensor"
DOMAIN = "ecowitt"
DATA_CONFIG = "config"
DATA_ECOWITT = "ecowitt_listener"
Expand Down Expand Up @@ -151,12 +152,16 @@
TYPE_LIGHTNING_NUM = "lightning_num"
TYPE_LIGHTNING_KM = "lightning"
TYPE_LIGHTNING_MI = "lightning_mi"
TYPE_WH68BATT = "wh68batt"
TYPE_WH40BATT = "wh40batt"
TYPE_LEAK_CH1 = "leak_ch1"
TYPE_LEAK_CH2 = "leak_ch2"
TYPE_LEAK_CH3 = "leak_ch3"
TYPE_LEAK_CH4 = "leak_ch4"
TYPE_WH25BATT = "wh25batt"
TYPE_WH26BATT = "wh26batt"
TYPE_WH65BATT = "wh65batt"
TYPE_WH40BATT = "wh40batt"
TYPE_WH57BATT = "wh57batt"
TYPE_WH25BATT = "wh25batt"
TYPE_WH68BATT = "wh68batt"
TYPE_WH65BATT = "wh65batt"
TYPE_WH80BATT = "wh80batt"
TYPE_SOILBATT1 = "soilbatt1"
TYPE_SOILBATT2 = "soilbatt2"
Expand All @@ -182,6 +187,14 @@
TYPE_PM25BATT6 = "pm25batt6"
TYPE_PM25BATT7 = "pm25batt7"
TYPE_PM25BATT8 = "pm25batt8"
TYPE_LEAKBATT1 = "leakbatt1"
TYPE_LEAKBATT2 = "leakbatt2"
TYPE_LEAKBATT3 = "leakbatt3"
TYPE_LEAKBATT4 = "leakbatt4"
TYPE_LEAKBATT5 = "leakbatt5"
TYPE_LEAKBATT6 = "leakbatt6"
TYPE_LEAKBATT7 = "leakbatt7"
TYPE_LEAKBATT8 = "leakbatt8"

S_METRIC = 1
S_IMPERIAL = 2
Expand All @@ -190,6 +203,8 @@
W_TYPE_OLD = "old"
W_TYPE_HYBRID = "hybrid"

LEAK_DETECTED = "Leak Detected"

# Name, unit_of_measure, type, device_class, icon, metric=1
# name, uom, kind, device_class, icon, metric = SENSOR_TYPES[x]
SENSOR_TYPES = {
Expand Down Expand Up @@ -399,17 +414,25 @@
TYPE_SENSOR, None, "mdi:ruler", S_METRIC),
TYPE_LIGHTNING_MI: ("Lightning strike distance", LENGTH_MILES,
TYPE_SENSOR, None, "mdi:ruler", S_IMPERIAL),
TYPE_WH68BATT: ("WH68 Battery", "BATT", TYPE_SENSOR,
None, "mdi:battery", 0),
TYPE_WH40BATT: ("WH40 Battery", "BATT", TYPE_SENSOR,
TYPE_LEAK_CH1: ("Leak Detection 1", LEAK_DETECTED, TYPE_BINARY_SENSOR,
DEVICE_CLASS_MOISTURE, "mdi:leak", 0),
TYPE_LEAK_CH2: ("Leak Detection 2", LEAK_DETECTED, TYPE_BINARY_SENSOR,
DEVICE_CLASS_MOISTURE, "mdi:leak", 0),
TYPE_LEAK_CH3: ("Leak Detection 3", LEAK_DETECTED, TYPE_BINARY_SENSOR,
DEVICE_CLASS_MOISTURE, "mdi:leak", 0),
TYPE_LEAK_CH4: ("Leak Detection 4", LEAK_DETECTED, TYPE_BINARY_SENSOR,
DEVICE_CLASS_MOISTURE, "mdi:leak", 0),
TYPE_WH25BATT: ("WH25 Battery", "BATT", TYPE_SENSOR,
None, "mdi:battery", 0),
TYPE_WH26BATT: ("WH26 Battery", "BATT", TYPE_SENSOR,
None, "mdi:battery", 0),
TYPE_WH65BATT: ("WH65 Battery", "BATT", TYPE_SENSOR,
TYPE_WH40BATT: ("WH40 Battery", "BATT", TYPE_SENSOR,
None, "mdi:battery", 0),
TYPE_WH57BATT: ("WH57 Battery", "BATT", TYPE_SENSOR,
None, "mdi:battery", 0),
TYPE_WH25BATT: ("WH25 Battery", "BATT", TYPE_SENSOR,
TYPE_WH65BATT: ("WH65 Battery", "BATT", TYPE_SENSOR,
None, "mdi:battery", 0),
TYPE_WH68BATT: ("WH68 Battery", "BATT", TYPE_SENSOR,
None, "mdi:battery", 0),
TYPE_WH80BATT: ("WH80 Battery", "BATT", TYPE_SENSOR,
None, "mdi:battery", 0),
Expand Down Expand Up @@ -461,6 +484,22 @@
None, "mdi:battery", 0),
TYPE_PM25BATT8: ("PM2.5 8 Battery", "BATT", TYPE_SENSOR,
None, "mdi:battery", 0),
TYPE_LEAKBATT1: ("Leak 1 Battery", "BATT", TYPE_SENSOR,
None, "mdi:battery", 0),
TYPE_LEAKBATT2: ("Leak 2 Battery", "BATT", TYPE_SENSOR,
None, "mdi:battery", 0),
TYPE_LEAKBATT3: ("Leak 3 Battery", "BATT", TYPE_SENSOR,
None, "mdi:battery", 0),
TYPE_LEAKBATT4: ("Leak 4 Battery", "BATT", TYPE_SENSOR,
None, "mdi:battery", 0),
TYPE_LEAKBATT5: ("Leak 5 Battery", "BATT", TYPE_SENSOR,
None, "mdi:battery", 0),
TYPE_LEAKBATT6: ("Leak 6 Battery", "BATT", TYPE_SENSOR,
None, "mdi:battery", 0),
TYPE_LEAKBATT7: ("Leak 7 Battery", "BATT", TYPE_SENSOR,
None, "mdi:battery", 0),
TYPE_LEAKBATT8: ("Leak 8 Battery", "BATT", TYPE_SENSOR,
None, "mdi:battery", 0),
}

IGNORED_SENSORS = [
Expand Down Expand Up @@ -517,7 +556,8 @@ async def async_setup(hass: HomeAssistant, config):
"""Set up the Ecowitt component."""

hass.data[DOMAIN] = {}
all_sensors = []
sensor_sensors = []
binary_sensors = []

if DOMAIN not in config:
return True
Expand Down Expand Up @@ -557,6 +597,42 @@ async def close_server(*args):
# # go to sleep until we get the first report
# await ws.wait_for_valid_data()

def check_and_append_sensor(sensor):
"""Check the sensor for validity, and append to appropriate list."""
if sensor not in SENSOR_TYPES:
if sensor not in IGNORED_SENSORS:
_LOGGER.warning("Unhandled sensor type %s", sensor)
return

# Is this a metric or imperial sensor, lookup and skip
name, uom, kind, device_class, icon, metric = SENSOR_TYPES[sensor]
if "baro" in sensor:
if (conf[CONF_UNIT_BARO] == CONF_UNIT_SYSTEM_IMPERIAL
and metric == S_METRIC):
return
if (conf[CONF_UNIT_BARO] == CONF_UNIT_SYSTEM_METRIC
and metric == S_IMPERIAL):
return
if "rain" in sensor:
if (conf[CONF_UNIT_RAIN] == CONF_UNIT_SYSTEM_IMPERIAL
and metric == S_METRIC):
return
if (conf[CONF_UNIT_RAIN] == CONF_UNIT_SYSTEM_METRIC
and metric == S_IMPERIAL):
return
if "wind" in sensor:
if (conf[CONF_UNIT_WIND] == CONF_UNIT_SYSTEM_IMPERIAL
and metric == S_METRIC):
return
if (conf[CONF_UNIT_WIND] == CONF_UNIT_SYSTEM_METRIC
and metric == S_IMPERIAL):
return

if kind == TYPE_SENSOR:
sensor_sensors.append(sensor)
if kind == TYPE_BINARY_SENSOR:
binary_sensors.append(sensor)

async def _first_data_rec(weather_data):
_LOGGER.info("First ecowitt data recd, setting up sensors.")
# check if we have model info, etc.
Expand All @@ -578,45 +654,22 @@ async def _first_data_rec(weather_data):

# load the sensors we have
for sensor in ws.last_values.keys():
if sensor not in SENSOR_TYPES:
if sensor not in IGNORED_SENSORS:
_LOGGER.warning("Unhandled sensor type %s", sensor)
continue

# Is this a metric or imperial sensor, lookup and skip
name, uom, kind, device_class, icon, metric = SENSOR_TYPES[sensor]
if "baro" in sensor:
if (conf[CONF_UNIT_BARO] == CONF_UNIT_SYSTEM_IMPERIAL and
metric == S_METRIC):
continue
if (conf[CONF_UNIT_BARO] == CONF_UNIT_SYSTEM_METRIC and
metric == S_IMPERIAL):
continue
if "rain" in sensor:
if (conf[CONF_UNIT_RAIN] == CONF_UNIT_SYSTEM_IMPERIAL and
metric == S_METRIC):
continue
if (conf[CONF_UNIT_RAIN] == CONF_UNIT_SYSTEM_METRIC and
metric == S_IMPERIAL):
continue
if "wind" in sensor:
if (conf[CONF_UNIT_WIND] == CONF_UNIT_SYSTEM_IMPERIAL and
metric == S_METRIC):
continue
if (conf[CONF_UNIT_WIND] == CONF_UNIT_SYSTEM_METRIC and
metric == S_IMPERIAL):
continue

all_sensors.append(sensor)

if not all_sensors:
check_and_append_sensor(sensor)

if not sensor_sensors and not binary_sensors:
_LOGGER.error("No sensors found to monitor, check device config.")
return False

hass.async_create_task(
async_load_platform(hass, "sensor", DOMAIN, all_sensors,
config)
)
if sensor_sensors:
hass.async_create_task(
async_load_platform(hass, "sensor", DOMAIN, sensor_sensors,
config)
)
if binary_sensors:
hass.async_create_task(
async_load_platform(hass, "binary_sensor", DOMAIN, binary_sensors,
config)
)
hass.data[DOMAIN][DATA_READY] = True

async def _async_ecowitt_update_cb(weather_data):
Expand All @@ -628,8 +681,11 @@ async def _async_ecowitt_update_cb(weather_data):
for sensor in weather_data.keys():
if sensor not in SENSOR_TYPES:
if sensor not in IGNORED_SENSORS:
_LOGGER.warning("Unhandled sensor type %s value %s, " +
"file a PR.", sensor, weather_data[sensor])
_LOGGER.warning("Unhandled sensor type %s value %s, "
+ "file a PR.", sensor, weather_data[sensor])
if sensor not in sensor_sensors and sensor not in binary_sensors:
_LOGGER.warning("Unregistered sensor type %s value %s received.",
sensor, weather_data[sensor])
async_dispatcher_send(hass, DOMAIN)

ws.register_listener(_async_ecowitt_update_cb)
Expand Down
65 changes: 65 additions & 0 deletions custom_components/ecowitt/binary_sensor.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
"""Support for Ecowitt Weather Stations."""
import logging

from . import (
TYPE_BINARY_SENSOR,
SENSOR_TYPES,
EcowittEntity,
)

_LOGGER = logging.getLogger(__name__)


async def async_setup_platform(hass, config, async_add_entities,
discovery_info=None):
"""Setup a single Ecowitt sensor."""

if not discovery_info:
return

entities = []
for sensor in discovery_info:
name, uom, kind, device_class, icon, metric = SENSOR_TYPES[sensor]
if kind == TYPE_BINARY_SENSOR:
entities.append(
EcowittBinarySensor(
hass,
sensor,
name,
device_class,
uom,
icon,
)
)
async_add_entities(entities, True)


class EcowittBinarySensor(EcowittEntity):

def __init__(self, hass, key, name, dc, uom, icon):
"""Initialize the sensor."""
super().__init__(hass, key, name)
self._icon = icon
self._uom = uom
self._dc = dc

@property
def is_on(self):
"""Return true if the binary sensor is on."""
if self._key in self._ws_last_values:
if self._ws.last_values[self._key] > 0:
return True
else:
_LOGGER.warning("Sensor %s not in last update, check range or battery",
self._key)
return False

@property
def icon(self):
"""Return the icon to use in the fronend."""
return self._icon

@property
def device_class(self):
"""Return the device class."""
return self._dc
2 changes: 1 addition & 1 deletion custom_components/ecowitt/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"config_flow": false,
"documentation": "https://www.home-assistant.io/integrations/ecowitt",
"requirements": [
"pyecowitt==0.9"
"pyecowitt==0.10"
],
"ssdp": [],
"zeroconf": [],
Expand Down
2 changes: 0 additions & 2 deletions custom_components/ecowitt/sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@

from . import (
TYPE_SENSOR,
DOMAIN,
DATA_STATION,
SENSOR_TYPES,
EcowittEntity,
DEVICE_CLASS_TIMESTAMP
Expand Down
2 changes: 1 addition & 1 deletion hacs.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "Ecowitt Weather Station",
"render_readme": true,
"domains": ["sensor"],
"domains": ["sensor", "binary_sensor"],
"iot_class": "Local Push"
}

0 comments on commit 8989112

Please sign in to comment.