Skip to content

Commit

Permalink
Added last bit of code
Browse files Browse the repository at this point in the history
  • Loading branch information
LarsK1 committed Mar 31, 2024
1 parent 5969c21 commit e52dda2
Show file tree
Hide file tree
Showing 4 changed files with 770 additions and 189 deletions.
10 changes: 7 additions & 3 deletions custom_components/solvis_control/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,16 @@
"""
"""Solvis integration."""

from datetime import timedelta
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import CONF_IP_ADDRESS, Platform
from homeassistant.core import HomeAssistant

from .const import (
DATA_COORDINATOR,
DOMAIN,
CONF_HOST, CONF_PORT

)
from .coordinator import SolvisModbusCoordinator

Expand All @@ -20,17 +23,18 @@
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
"""Set up Solvis device from a config entry."""

address = entry.data.get(CONF_IP_ADDRESS)
conf_host = entry.data.get(CONF_HOST)
conf_port = entry.data.get(CONF_PORT)

if address is None:
if conf_host is None or conf_port is None:
return False

# Create data structure
hass.data.setdefault(DOMAIN, {})
hass.data[DOMAIN].setdefault(entry.entry_id, {})

# Create coordinator for polling
coordinator = SolvisModbusCoordinator(hass, address)
coordinator = SolvisModbusCoordinator(hass, conf_host, conf_port)
await coordinator.async_config_entry_first_refresh()
hass.data[DOMAIN][entry.entry_id].setdefault(DATA_COORDINATOR, coordinator)

Expand Down
127 changes: 127 additions & 0 deletions custom_components/solvis_control/const.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,134 @@
DOMAIN = "solvis_control"

from dataclasses import dataclass

CONF_NAME = "name"
CONF_HOST = "host"
CONF_PORT = "port"

DATA_COORDINATOR = "coordinator"
MANUFACTURER = "Solvis"

@dataclass(frozen=True)
class ModbusFieldConfig:
name: str
address: int
unit: str
device_class: str
state_class: str
multiplier: float = 0.1

PORT = 502
REGISTERS = [
ModbusFieldConfig(
name="gas_power",
address=33539,
unit="kW",
device_class="power",
state_class="measurement",
),

ModbusFieldConfig(
name="outdoor_air_temp",
address=33033,
unit="°C",
device_class="temperature",
state_class="measurement",
),
ModbusFieldConfig(
name="roof_air_temp",
address=33031,
unit="°C",
device_class="temperature",
state_class="measurement",
),

ModbusFieldConfig(
name="cold_water_temp",
address=33034,
unit="°C",
device_class="temperature",
state_class="measurement",
multiplier=0.01,
),
ModbusFieldConfig(
name="flow_water_temp",
address=33035,
unit="°C",
device_class="temperature",
state_class="measurement",
),
ModbusFieldConfig(
name="domestic_water_temp",
address=33025,
unit="°C",
device_class="temperature",
state_class="measurement",
),

ModbusFieldConfig(
name="solar_water_temp",
address=33030,
unit="°C",
device_class="temperature",
state_class="measurement",
),
ModbusFieldConfig(
name="solar_heat_exchanger_in_water_temp",
address=33029,
unit="°C",
device_class="temperature",
state_class="measurement",
),
ModbusFieldConfig(
name="solar_heat_exchanger_out_water_temp",
address=33028,
unit="°C",
device_class="temperature",
state_class="measurement",
),

ModbusFieldConfig(
name="tank_layer1_water_temp",
address=33026,
unit="°C",
device_class="temperature",
state_class="measurement",
),
ModbusFieldConfig(
name="tank_layer2_water_temp",
address=33032,
unit="°C",
device_class="temperature",
state_class="measurement",
),
ModbusFieldConfig(
name="tank_layer3_water_temp",
address=33027,
unit="°C",
device_class="temperature",
state_class="measurement",
),
ModbusFieldConfig(
name="tank_layer4_water_temp",
address=33024,
unit="°C",
device_class="temperature",
state_class="measurement",
),

ModbusFieldConfig(
name="solar_water_flow",
address=33040,
unit="l/min",
device_class="speed",
state_class="measurement",
),
ModbusFieldConfig(
name="domestic_water_flow",
address=33041,
unit="l/min",
device_class="speed",
state_class="measurement",
),
]
28 changes: 25 additions & 3 deletions custom_components/solvis_control/coordinator.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,20 @@

from homeassistant.helpers.update_coordinator import DataUpdateCoordinator

from .const import DOMAIN
from pymodbus import ModbusException
import pymodbus.client as ModbusClient
from pymodbus.exceptions import ConnectionException
from pymodbus.payload import BinaryPayloadDecoder, Endian

from .const import DOMAIN, REGISTERS

_LOGGER = logging.getLogger(__name__)


class SolvisModbusCoordinator(DataUpdateCoordinator):
"""My custom coordinator."""

def __init__(self, hass, my_api):
def __init__(self, hass, conf_host, conf_port):
"""Initialize my coordinator."""
super().__init__(
hass,
Expand All @@ -23,11 +28,28 @@ def __init__(self, hass, my_api):
# Polling interval. Will only be polled if there are subscribers.
update_interval=timedelta(seconds=5),
)
self.my_api = my_api
self.logger.debug("Creating client")
self.modbus = ModbusClient.AsyncModbusTcpClient(conf_host, conf_port)

async def _async_update_data(self):
"""Fetch data from API endpoint.
This is the place to pre-process the data to lookup tables
so entities can quickly look up their data.
"""
self.logger.debug("Polling data")

parsed_data: dict = {}
try:
await self.modbus.connect()
except ConnectionException:
self.logger.warning("Couldn't connect to device")
if self.modbus.connected:
for register in REGISTERS:
result = await self.modbus.read_holding_registers(register, 1, 1)
d = BinaryPayloadDecoder.fromRegisters(result.registers, byteorder=Endian.BIG)
parsed_data[register.name] = round(d.decode_16bit_int() * register.multiplier, 2)
await self.modbus.close()

# Pass data back to sensors
return parsed_data
Loading

0 comments on commit e52dda2

Please sign in to comment.