hass-cozylife
hass-cozylife copied to clipboard
2-gang switch fixed
UPDATED, CHECK POST BELOW!!
took me a whole day and some help of AI. But I finally made it to control a two gang switch with two seperate entities!
Split your configuration.yaml in two parts: "switches" for sockets etc. "switches2" for 2-gang wall switches
switch:
- platform: cozylife
switches:
- ip: 192.168.178.10
did: 51039349083a8d53f900 #Sekretär
pid: esEM1c
dmn: Metering Socket
dpid: [1, 2, 3, 18, 19, 20, 21, 26, 27, 28, 29, 30, 31, 32]
switches2:
- ip: 192.168.178.12
did: 4324820980646f4c6700 #Wohnzimmer
pid: e5aHVS
dmn: Smart switch
dpid: [1, 2, 3, 4, 5]
_replace your custom_components/cozylife/switch.py with this:
"""Platform for sensor integration."""
from __future__ import annotations
import logging
from .tcp_client import tcp_client
from datetime import timedelta
import asyncio
from homeassistant.components.sensor import SensorEntity
from homeassistant.components.switch import SwitchEntity
from homeassistant.const import TEMP_CELSIUS
from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
from homeassistant.helpers.event import async_track_time_interval
from typing import Any, Final, Literal, TypedDict, final
from .const import (
DOMAIN,
SWITCH_TYPE_CODE,
LIGHT_TYPE_CODE,
LIGHT_DPID,
SWITCH,
WORK_MODE,
TEMP,
BRIGHT,
HUE,
SAT,
)
SCAN_INTERVAL = timedelta(seconds=20)
_LOGGER = logging.getLogger(__name__)
_LOGGER.info(__name__)
SCAN_INTERVAL = timedelta(seconds=1)
async def async_setup_platform(
hass: HomeAssistant,
config: ConfigType,
async_add_devices: AddEntitiesCallback,
discovery_info: DiscoveryInfoType | None = None
) -> None:
"""Set up the sensor platform."""
# We only want this platform to be set up via discovery.
# logging.info('setup_platform', hass, config, add_entities, discovery_info)
_LOGGER.info('setup_platform')
#_LOGGER.info(f'ip={hass.data[DOMAIN]}')
#if discovery_info is None:
# return
switches = []
for item in config.get('switches') or []:
client = tcp_client(item.get('ip'))
client._device_id = item.get('did')
client._pid = item.get('pid')
client._dpid = item.get('dpid')
client._device_model_name = item.get('dmn')
switches.append(CozyLifeSwitch(client, hass, 'wippe1'))
for item in config.get('switches2') or []:
client = tcp_client(item.get('ip'))
client._device_id = item.get('did')
client._pid = item.get('pid')
client._dpid = item.get('dpid')
client._device_model_name = item.get('dmn')
# Create two entities for each switch, one for each rocker
switches.append(CozyLifeSwitch(client, hass, 'wippe1'))
switches.append(CozyLifeSwitch(client, hass, 'wippe2'))
async_add_devices(switches)
for switch in switches:
await hass.async_add_executor_job(switch._tcp_client._initSocket)
await asyncio.sleep(0.01)
async def async_update(now=None):
for switch in switches:
await hass.async_add_executor_job(switch._refresh_state)
await asyncio.sleep(0.01)
async_track_time_interval(hass, async_update, SCAN_INTERVAL)
class CozyLifeSwitch(SwitchEntity):
_tcp_client = None
_attr_is_on = True
_wippe = None # Add a new attribute to track the rocker
def __init__(self, tcp_client: tcp_client, hass, wippe: str) -> None:
"""Initialize the sensor."""
_LOGGER.info('__init__')
self.hass = hass
self._tcp_client = tcp_client
self._unique_id = tcp_client.device_id + '_' + wippe
self._name = tcp_client.device_id[-4:] + ' ' + wippe
self._wippe = wippe # Set the rocker attribute
self._refresh_state()
@property
def unique_id(self) -> str | None:
"""Return a unique ID."""
return self._unique_id
async def async_update(self):
await self.hass.async_add_executor_job(self._refresh_state)
def _refresh_state(self):
self._state = self._tcp_client.query()
_LOGGER.info(f'_name={self._name},_state={self._state}')
if self._state:
if self._wippe == 'wippe1':
self._attr_is_on = (self._state['1'] & 0x01) == 0x01
elif self._wippe == 'wippe2':
self._attr_is_on = (self._state['1'] & 0x02) == 0x02
@property
def name(self) -> str:
return 'cozylife:' + self._name
@property
def available(self) -> bool:
"""Return if the device is available."""
if self._tcp_client._connect:
return True
else:
return False
@property
def is_on(self) -> bool:
"""Return True if entity is on."""
return self._attr_is_on
async def async_turn_on(self, **kwargs: Any) -> None:
"""Turn the entity on."""
self._attr_is_on = True
_LOGGER.info(f'turn_on:{kwargs}')
if self._wippe == 'wippe1':
await self.hass.async_add_executor_job(self._tcp_client.control, {
'1': self._state['1'] | 0x01
})
elif self._wippe == 'wippe2':
await self.hass.async_add_executor_job(self._tcp_client.control, {
'1': self._state['1'] | 0x02
})
return None
async def async_turn_off(self, **kwargs: Any) -> None:
"""Turn the entity off."""
self._attr_is_on = False
_LOGGER.info('turn_off')
if self._wippe == 'wippe1':
await self.hass.async_add_executor_job(self._tcp_client.control, {
'1': self._state['1'] & ~0x01
})
elif self._wippe == 'wippe2':
await self.hass.async_add_executor_job(self._tcp_client.control, {
'1': self._state['1'] & ~0x02
})
return None
```````_
adjust SCAN_INTERVAL = timedelta(seconds=1) (in my case 1 second) to improve status response speed of the switch. Going below 1 sec. could maybe decrease your homeassistant's performance.
"wippe" stands for rocker
I found information about how to control certain rockers here:
https://github.com/cozylife/dpid_document/blob/main/electrician_zh.md