Include files
parent
72839a82a6
commit
929efdd12c
@ -0,0 +1 @@
|
||||
"""Solareco sensor integration"""
|
@ -0,0 +1,9 @@
|
||||
{
|
||||
"domain": "solareco",
|
||||
"name": "solareco",
|
||||
"version": "1.0.0",
|
||||
"dependencies": [],
|
||||
"requirments": [],
|
||||
"codeowners": [],
|
||||
"iot_class": "cloud_polling"
|
||||
}
|
@ -0,0 +1,138 @@
|
||||
import logging
|
||||
import telnetlib
|
||||
from datetime import timedelta, datetime, time
|
||||
from typing import Callable, Any
|
||||
import re
|
||||
|
||||
from homeassistant.components.sensor import SensorEntity, SensorStateClass, SensorDeviceClass
|
||||
from homeassistant.const import UnitOfTemperature, UnitOfPower, UnitOfElectricPotential, UnitOfElectricCurrent, \
|
||||
UnitOfEnergy, UnitOfFrequency, UnitOfTime
|
||||
from homeassistant.core import callback
|
||||
from homeassistant.helpers.dispatcher import async_dispatcher_connect
|
||||
from homeassistant.helpers.dispatcher import dispatcher_send
|
||||
from homeassistant.helpers.event import async_track_time_interval
|
||||
|
||||
SIGNAL = 'solareco'
|
||||
DOMAIN = 'solareco'
|
||||
|
||||
_LOGGER = logging.getLogger('solareco')
|
||||
|
||||
|
||||
class SolarecoSensorConfig:
|
||||
def __init__(self, name,
|
||||
unit_of_measurement,
|
||||
device_class,
|
||||
data_transformation,
|
||||
icon,
|
||||
state_class=SensorStateClass.MEASUREMENT):
|
||||
self.name = name
|
||||
self.unit_of_measurement = unit_of_measurement
|
||||
self.device_class = device_class
|
||||
self.data_transformation = data_transformation
|
||||
self.icon = icon
|
||||
self.state_class = state_class
|
||||
|
||||
SENSORS = [
|
||||
SolarecoSensorConfig('relay', None, None, lambda data: re.findall('AC+\d', data)[0][2:] if re.search('AC+\d',data) else re.findall('R:+\d', data)[0][2:],""),
|
||||
SolarecoSensorConfig('fan', None, None, lambda data: re.findall('F:+\d', data)[0][2:] if re.search('F:+\d',data) else None,"mdi:fan"),
|
||||
SolarecoSensorConfig('required_voltage', UnitOfElectricPotential.VOLT, None, lambda data: re.findall('\d+U', data)[0][:-1],"mdi:alpha-v-circle-outline"),
|
||||
SolarecoSensorConfig('voltage', UnitOfElectricPotential.VOLT, SensorDeviceClass.VOLTAGE, lambda data: re.findall('\d+V', data)[0][:-1],"mdi:alpha-v-circle-outline"),
|
||||
SolarecoSensorConfig('current', UnitOfElectricCurrent.MILLIAMPERE, SensorDeviceClass.CURRENT, lambda data: re.findall('\d+mA', data)[0][:-2],"mdi:current-dc"),
|
||||
SolarecoSensorConfig('power', UnitOfPower.WATT, SensorDeviceClass.POWER, lambda data: re.findall('\d+W', data)[0][:-1],"mdi:alpha-w-circle-outline"),
|
||||
SolarecoSensorConfig('frequency', UnitOfFrequency.HERTZ, SensorDeviceClass.FREQUENCY, lambda data: re.findall('\d+Hz', data)[0][:-2] if re.search('\d+Hz',data) else None,""),
|
||||
SolarecoSensorConfig('cooler_temperature', UnitOfTemperature.CELSIUS, SensorDeviceClass.TEMPERATURE, lambda data: re.findall('\d+C', data)[0][:-1],""),
|
||||
SolarecoSensorConfig('boiler_temperature', UnitOfTemperature.CELSIUS, SensorDeviceClass.TEMPERATURE, lambda data: re.findall('(\d+):\d+C',data)[0],""),
|
||||
SolarecoSensorConfig('pulse_width', UnitOfTime.MICROSECONDS, None, lambda data: re.findall('\d+us', data)[0][:-2],""),
|
||||
SolarecoSensorConfig('total_energy', UnitOfEnergy.WATT_HOUR, SensorDeviceClass.ENERGY, lambda data: re.findall('\d+kWh\s\d+Wh', data)[0].replace(' ','').replace('kWh','').replace('Wh','') if re.search('\d+kWh\s\d+Wh', data) else None,"mdi:alpha-w-circle-outline"),
|
||||
SolarecoSensorConfig('day_energy', UnitOfEnergy.WATT_HOUR, SensorDeviceClass.ENERGY, lambda data: re.findall('\d+Wh', data)[0][:-2],"mdi:alpha-w-circle-outline" ,SensorStateClass.TOTAL_INCREASING),
|
||||
]
|
||||
|
||||
|
||||
async def async_setup_platform(hass, config, async_add_entities, discovery_info=None) -> True:
|
||||
_LOGGER.info(str(config))
|
||||
sensor_connector = SensorConnector(hass, config['host'], config['port'])
|
||||
# Do first update
|
||||
await hass.async_add_executor_job(sensor_connector.update)
|
||||
# Poll for updates in the background
|
||||
async_track_time_interval(
|
||||
hass,
|
||||
lambda now: sensor_connector.update(),
|
||||
timedelta(seconds=int(config['poll_interval_seconds'])),
|
||||
)
|
||||
|
||||
entities: list[SensorEntity] = []
|
||||
entities.extend([SolarecoSensor(sensor_connector, sensor_config) for sensor_config in SENSORS])
|
||||
async_add_entities(entities, True)
|
||||
|
||||
hass.data.setdefault(DOMAIN, {})
|
||||
|
||||
|
||||
class SolarecoSensor(SensorEntity):
|
||||
def __init__(self, sensor_connector, sensor_config: SolarecoSensorConfig):
|
||||
super().__init__()
|
||||
self.sensor_connector = sensor_connector
|
||||
self.sensor_config = sensor_config
|
||||
|
||||
self._attr_has_entity_name = True
|
||||
self._attr_translation_key = self.sensor_config.name
|
||||
self._state = None
|
||||
self._state_attributes = None
|
||||
self._attr_icon = self.sensor_config.icon
|
||||
|
||||
async def async_added_to_hass(self) -> None:
|
||||
self.async_on_remove(
|
||||
async_dispatcher_connect(self.hass, SIGNAL, self._async_update_callback)
|
||||
)
|
||||
|
||||
@callback
|
||||
def _async_update_callback(self):
|
||||
self._async_update_data()
|
||||
self.async_write_ha_state()
|
||||
|
||||
@property
|
||||
def unique_id(self):
|
||||
return f"{'solareco'} {self.sensor_config.name}"
|
||||
|
||||
# @property
|
||||
# def name(self):
|
||||
# return f"{'solareco'} {self.sensor_config.name}"
|
||||
|
||||
@property
|
||||
def native_value(self):
|
||||
return self._state
|
||||
|
||||
@property
|
||||
def state_class(self):
|
||||
return self.sensor_config.state_class
|
||||
|
||||
@property
|
||||
def device_class(self):
|
||||
return self.sensor_config.device_class
|
||||
|
||||
@property
|
||||
def native_unit_of_measurement(self):
|
||||
return self.sensor_config.unit_of_measurement
|
||||
|
||||
@callback
|
||||
def _async_update_data(self):
|
||||
self._state = self.sensor_connector.data[self.sensor_config.name]
|
||||
|
||||
|
||||
class SensorConnector:
|
||||
def __init__(self, hass, solareco_host, solareco_port):
|
||||
self.hass = hass
|
||||
self.solareco_host = solareco_host
|
||||
self.solareco_port = solareco_port
|
||||
self.data = {SENSORS[i]: None for i in range(0, len(SENSORS))}
|
||||
|
||||
def update(self):
|
||||
try:
|
||||
with telnetlib.Telnet(self.solareco_host, self.solareco_port) as tn:
|
||||
line = tn.read_until(b'\n').decode('ascii')
|
||||
for i in range(0, len(SENSORS)):
|
||||
sensor = SENSORS[i]
|
||||
self.data[sensor.name] = sensor.data_transformation(line)
|
||||
dispatcher_send(self.hass, SIGNAL)
|
||||
except:
|
||||
_LOGGER.error("Can't connect to SolarEco")
|
||||
|
@ -0,0 +1,43 @@
|
||||
{
|
||||
"entity": {
|
||||
"sensor": {
|
||||
"relay": {
|
||||
"name": "relay"
|
||||
},
|
||||
"fan": {
|
||||
"name": "fan"
|
||||
},
|
||||
"required_voltage": {
|
||||
"name": "required_voltage"
|
||||
},
|
||||
"voltage": {
|
||||
"name": "voltage"
|
||||
},
|
||||
"current": {
|
||||
"name": "current"
|
||||
},
|
||||
"power": {
|
||||
"name": "power"
|
||||
},
|
||||
"frequency": {
|
||||
"name": "frequency"
|
||||
},
|
||||
"cooler_temperature": {
|
||||
"name": "cooler_temperature"
|
||||
},
|
||||
"boiler_temperature": {
|
||||
"name": "boiler_temperature"
|
||||
},
|
||||
"pulse_width": {
|
||||
"name": "day_energy"
|
||||
},
|
||||
"total_energy": {
|
||||
"name": "total_energy"
|
||||
},
|
||||
"day_energy": {
|
||||
"name": "day_energy"
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,43 @@
|
||||
{
|
||||
"entity": {
|
||||
"sensor": {
|
||||
"relay": {
|
||||
"name": "relé"
|
||||
},
|
||||
"fan": {
|
||||
"name": "větrák"
|
||||
},
|
||||
"required_voltage": {
|
||||
"name": "požadované_napětí"
|
||||
},
|
||||
"voltage": {
|
||||
"name": "napětí"
|
||||
},
|
||||
"current": {
|
||||
"name": "proud"
|
||||
},
|
||||
"power": {
|
||||
"name": "výkon"
|
||||
},
|
||||
"frequency": {
|
||||
"name": "frekvence"
|
||||
},
|
||||
"cooler_temperature": {
|
||||
"name": "teplota_chladiče"
|
||||
},
|
||||
"boiler_temperature": {
|
||||
"name": "teplota_kotle"
|
||||
},
|
||||
"pulse_width": {
|
||||
"name": "šířka_pulzu"
|
||||
},
|
||||
"total_energy": {
|
||||
"name": "celková_energie"
|
||||
},
|
||||
"day_energy": {
|
||||
"name": "denní_energie"
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,43 @@
|
||||
{
|
||||
"entity": {
|
||||
"sensor": {
|
||||
"relay": {
|
||||
"name": "relay"
|
||||
},
|
||||
"fan": {
|
||||
"name": "fan"
|
||||
},
|
||||
"required_voltage": {
|
||||
"name": "required_voltage"
|
||||
},
|
||||
"voltage": {
|
||||
"name": "voltage"
|
||||
},
|
||||
"current": {
|
||||
"name": "current"
|
||||
},
|
||||
"power": {
|
||||
"name": "power"
|
||||
},
|
||||
"frequency": {
|
||||
"name": "frequency"
|
||||
},
|
||||
"cooler_temperature": {
|
||||
"name": "cooler_temperature"
|
||||
},
|
||||
"boiler_temperature": {
|
||||
"name": "boiler_temperature"
|
||||
},
|
||||
"pulse_width": {
|
||||
"name": "day_energy"
|
||||
},
|
||||
"total_energy": {
|
||||
"name": "total_energy"
|
||||
},
|
||||
"day_energy": {
|
||||
"name": "day_energy"
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue