Super dzięki. Testuję właśnie zmiany i jest tylko jeden problem dla RCM - tam idą cztery kanały i dla każdego jest tworzony sensor baterii. Myślę że to nie ma sensu i wystarczy tworzyć tylko encje sensora baterii dla kanału 1. W tej chwili to wygląda tak:
def push_virtual_sensor_channels(self, virtual_sensor_domain: str, channel_data: dict):
"""Push additional, virtual sensor channels for entity attributes. These should be
processed by all platforms during platform setup and ultimately sensor entities
shouldbe created by the sensor platform"""
virtual_sensors = self._get_virtual_sensors()
_LOGGER.debug("Virtual sensors: %s", virtual_sensors)
for virtual in virtual_sensors:
v_channel_data = channel_data.copy()
v_channel_data.update({VIRT_SENSOR_CHN_FIELD: virtual})
self.core.push_channels(
virtual_sensor_domain, v_channel_data, append=True, custom=True
)
moja propozycja zmiany to takie coś:
def push_virtual_sensor_channels(self, virtual_sensor_domain: str, channel_data: dict):
"""Push additional, virtual sensor channels for entity attributes. These should be
processed by all platforms during platform setup and ultimately sensor entities
shouldbe created by the sensor platform"""
virtual_sensors = self._get_virtual_sensors()
_LOGGER.debug("Virtual sensors: %s", virtual_sensors)
data = self.channel_data
channel = data.get("channel")
for virtual in virtual_sensors:
if channel > 1:
sensor_class = virtual.get(VIRT_SENSOR_DEV_CLS)
if sensor_class == SensorDeviceClass.BATTERY:
continue
v_channel_data = channel_data.copy()
v_channel_data.update({VIRT_SENSOR_CHN_FIELD: virtual})
self.core.push_channels(
virtual_sensor_domain, v_channel_data, append=True, custom=True
)
Wstępnie myślałem, żeby to było zrobione na zasadzie konfiguracji opartej o dictionary - tak jak dla device class sensorów, tylko tutaj byłobyby przyporządkowanie atrybut:config. To byłby dictionary na zasadzie filter, czyli brak wpisu oznacza, że tworzymy sensor bezwarunkowo, a pasujący wpis oznacza, że nie tworzymy jeśli warunki się nie zgodzą..
Na początek byłby tylko filtr oparty o numer kanału, a kiedyś w razie potrzeby możnaby to rozbudować.
Przykładowy konfig wyglądałby tak:
w sensor.py:
VIRTUAL_SENSOR_RESTRICTIONS = {
"battery_status": {"allowed_channels": (1)}
}
Wtedy czytasz dict dla atrybutu, odczytujesz "allowed_channels", sprawdzasz funkcją indexof() czy aktualny channel jest na liście i jeśli jest to ok, a jeśli nie to nie tworzymy. Tylko tą logikę trzebaby zbudować zamiast tutaj to w funkcję _get_virtual_sensors. Wtedy mielibyśmy filtrowanie na poprawnym poziomie bez sytuacji, że liczba zwróconych przez get_virtual_sensors sensorów będzie mniejsza niż liczba utworzonych. Byłoby to trochę mylące, a tak to tego unikniemy.
A jeszcze bardziej zaawansowana wersja zamiast dict "allowed_channels" mogłaby być klasą ze statycznym atrybutem "allowed_channels" - rozwiązanie podobne do SENSOR_TYPES w sensor.py. To rozwiązanie (klasy konfiguracyjne) upowszechnia się w kodzie HA i bardzo mi się podoba z tego względu, że wtedy mamy podpowiadanie kodu i walidację nazw pól już na poziomie pythonowej kompilacji. Nie trzeba także tworzyć constantów dla kolejnych pól dictionary, bo operujemy na statycznych atrybutach, które mają swoje nazwy. Generalnie python jest ciekawym językiem, ale brak typów w nim mnie wkurza. Do większych projektów to bardziej przeszkadza niż pomaga. W kodzie HA praktycznie wszystko jest typowane (tzn. pseudotypowane, bo to działa tylko w edytorze a nie runtime) - i to pomaga szybciej pisać kod i unikać błędów.
Generalnie coraz bardziej podoba mi się logika oparta o dictionary config, czyli unikanie ifów i elsów, a zamiast nich zdefiniowanie co, kiedy i do czego. Wtedy sam kod jest zwięzły i chyba bardziej czytelny. Integracja w większości nie jest tak napisana, bo wtedy jeszcze tej koncepcji nie znałem, ale jak zabrałem się za przebudowę sensora i przenanalizowałem kilka integracji, to już z tego skorzystałem i musze przyznać, że efekt mi się podoba
PS: Możesz podrzucić swoje ustawienia do pylinta ?
Mogę jak mi powiesz skąd je wziąć
W dev container on po prostu jest samoczynnie uaktywniony i ma konfigurację zgodną z developmenem HA. Nie wnikałem skąd się to wzięło i jak go skonfigurować. Dlatego koncepcja dev container mi się tak podoba. Jeśli coś developerzy HA zmienią w ustawieniach to ja też to samoczynnie zobaczę przy najbliższej synchronizacji mojego forka z repo HA Core.