Homeassistant auf Pekaway

Danke für die Antwort - hatte ich vermutet, wollte aber sicher gehen.

Welchen Vorteil verspricht ihr euch von homeassistant gegenüber den VanPios?
Ich habe es selber noch nicht genutzt, nur testweise aufgesetzt um damals ein paar Zigbee Funktionen zu testen, das klappt aber auch direkt im Vanpi.
Die einzige interessante Sache wäre für mich, die Android Auto Funktion.

Ich habe HA schon zu Hause am laufen, dasselbe im Camper wäre für mich logisch.
Plus es hat die größere Community.

Weiß jemand, warum es eigentlich Van Pi gibt, und warum alles nicht direkt auf HA basiert? Also Hardware-Entwicklung der Komponenten wie bisher, und softwareseitig add-ons für HA?

  • Disclaimer: ich kenne Van Pi OS noch nicht :grimacing:

Hi Tristan,

Mal so die Vorteile die mir einfallen würden:

  • Durch Einsatz zuhause evtl schon vertraut
  • unendlich viel Hardware verfügbar die teilweise auch im Campingbereich Sinn macht (z.b. kabellose Schalter via Bluetooth oder Zigbee, Kameras, Sensoren, usw)
  • komplett eigene UIs machbar sowohl für Handy als auch für Tablets, NSPanel usw.
  • Automatisierungen einfacher (wobei das sicher Geschmacksfrage ist)

Aber es gibt sicher auch Nachteile, z.b. schreibt die HA die SD kaputt, sinnvoll ist ein Betrieb eigentlich nur mit SSD. Die Lernkurve für Neulinge ist steiler, bein VanPI Core mit Display hast du sofort ein nutzbares System, bist du im HA ein einfach/sinnvoll nutzbares Dashboard hast, dauert es länger. Ohne es probiert zu haben, das Energie Dashboard funktioniert vermutlich nicht wirklich mit DC Strom. Es gibt kein so stromsparendes Display wie das vom VanPI. Usw.

Insgesamt sehe ich HA nicht als Ersatz für das VanPI OS, sondern eher als Ergänzung. Das setzt aber momentan voraus, dass man 2 PIs betreibt. Evtl gibts da ja in Zukunft mit Proxmox o.ä. die Möglichkeit beides als virtuelle Maschine auf einem PI zu betreiben. Allerdings müsste man an die VanPI VM haufenweise Hardware durchreichen, das würde sicher ziemlich aufwendig und frickelig werden. Ich habe mit den Proxmox Ports auf Raspberrys auch keinerlei Erfahrungen, keine Ahnung ob das stabil läuft.

@moe.camp
Warum genau schreibt HA die SD Kaputt ?

Bezüglich der ganzen Zigbee Geschichte, eben jenes klappt auch (bei mir endlich, verfluchter Sonoff Dongle) problemlos mit VANpi.
Mit dem eigenen UI in der App ist natürlich eine feine Sache.
Leider habe ich noch keine schönen kompakten schalter gefunden, ähnlich der alten Osram oder Ikea Dinger.

Für zuhause werde ich mir HA definitiv noch zulegen.

HA erfasst viele Messwerte bzw. Events und speichert diese auch für einen relativ langen Zeitraum. Weiß gar nicht wie lange, konnte bei meiner Installation gerade bis Januar zurückgehen, ich glaub länger lebt diese Installation noch nicht. Und je mehr Schreiboperationen, desto mehr “altert” die SD bis sie irgendwann stirbt.

Das kann man aber minimieren.
Und mit “guten” SD Karten oder eMMC Speicher ist das kein Problem, wenn viel geloggt wird.

Comworks geht mit CIS 3 den Weg, dass sie ein angepasstes HA benutzen.
Ich finde das irgendwie sinniger, so müssen sie weniger Low-Level implementieren, haben das quasi automatisch durch HA.
Was bleibt ist die Hardware und die entsprechenden Ansteuerungen dafür in HA.
Leider finde ich das keine gute Doku und nichts ist Open source.

Meine Traumkombi wäre Van Pi Core mit HA nativ… :slight_smile:

Gibt Leute die da dran sind.

Ja, ich habe das installiert und bin auch schon in Kontakt mit @Max, da ein paar Sachen für den Raspberry PI 5 angepasst werden mussten. Jetzt geht es aber soweit.

Was ich eigentlich (auch) meinte, ist, dass es cool wäre, wenn der Software-Entwicklungsaufwand statt in Van PI OS einfach in HA Integrationen gesteckt wird, so dass die Hardware hier aus dem Shop optimal über HA unterstützt ist :wink:

Naja, “die Hardware” ist ja nicht nur der VanPI. Ich hab bei mir z.B. noch den Dimmy und das Display. So wie ich das Readme bei Git deute, wird beides nicht unterstützt. Beim Display würde man bestimmt Alternativen finden, die mit HA funktionieren. Aber der Dimmy wäre schon ein Verlust..

Ich mag auch HA, aber ich würde eine Lösung vorziehen wo der HA parallel zum VanPI mit VanPI OS existiert. Quasi “nur” ein bisschen MQTT Api vom VanPI anzapfen und in HA integrieren.

Ich verwende nun schon seit längerer Zeit HA exklusiv, also ohne VanPi und hame bisher alles einbinden können. Das Dimmy, konnte ich recht einfach mit ESPHome einbinden. ESPHome lässt dich mit relativ einfacher yaml-Konfiguration eine Firmware für den ESP-Chip im Dimmy erstellen. Hier findest du meine Konfiguration, welche fürs Dimmy funktionieren sollte: dimmy.yaml · GitHub

Danke für den Tipp. Dann würde der Dimmy also auch gehen. Aber nur mit ESP Chip, nicht die nackte Version die via i2c angeschlossen ist, richtig?

Ja, da hast du natürlich recht. Die Option mit ESPHome bedingt, dass du das Dimmy mit dem ESP Chip hast. Falls du die PCA9685 Dimmer jedoch direkt über I2C ansteuerst, könntest du dies vermutlich mit dieser Home-Assistant-Integration realisieren: GitHub - domectrl/ha-pca9685: Home Assistant Raspberry Pi GPIO PWM Integration

Habe ich aber selber nicht ausprobiert.

Krass, was es nicht alles gibt. Nochmal Danke! Klingt gut, werde ich mal ausprobieren. Aber ich hab derzeit noch so viele Baustellen, Bis ich dazu komme ist bestimmt VanPI OS schon in der neuen Version mit der neuen UI draussen. :grinning_face:

Hallo zusammen,

hat von euch jemand resistive Tanksensoren unter HA ans laufen gebracht?

Ich versuche mich gerade an HA als System auf dem Core und dank der tollen Vorarbeit einiger hier im Forum läuft das auch sehr gut.

Schalter, Temp Sensoren, Eingänge, Lagesensor, Dimmy über i2c läuft alles und ich habe es auch geschafft ein HDMI Touchdisplay am Core mit einem HA Dashboard zu nutzen.

Nur die Tanksensoren wollen nicht. Die Eingänge sind über das original vanpi image auf resistent umgestellt und dort funktionieren sie auch.
Anzeige zeigt bei eingestecktem Sensor Imme 0V an. Wenn ich ihn abziehe zeigt er einen fiktiven wert …

vielleicht hat das ja schon jemand umgesetzt und kann einen tipp geben?

Frank

Hallo Frank,

mit meiner Integration GitHub - maxlin1/PekawayVANPICORE_homeassistant: Diese benutzerdefinierte Komponente integriert das VAN PI CORE Board mit Home Assistant und ermöglicht es dir, die Systeme deines Vans über die Home Assistant zu überwachen und zu steuern. · GitHub sollte es funktionieren ich habe einen Supersense Tanksensor und einmal den Camper Typischen mit den 4 Stäben in den Tank (umgebaut mit einem Spannungsteiler Anleitung auch hier im Forum) und ich kann die Werte in HA anzeigen.

Moin Frank
Hier sind 2 Versionen ohne HA beschrieben, einmal mit Spannungsteiler nicht so toll, aber funktioniert.
Und einmal mit digitalen Eingängen, da ich keinen Core oder pro habe sind das externe Eingänge, funktioniert super.

Gruß Arno

Danke für eure Antworten,

Die von dir getesteten Tanksensoren arbeiten allerdings Kapazitiv und über Spannung.

Meiner über Widerstand. Das wird ja auch vom Core unterstützt und funktioniert ja mit dem Vani Image auch aber leider nicht über die HA integration.

Ich habe deine Integration über HACS installiert und die Tanksensoren über die Oberfläche konfiguriert. Es wird dann auch eine Entität für Widerstand hinzugefügt aber die zeigt immer 0Ohm an wenn der sensor aufgesteckt ist.

Frank

Versuche es bitte mal mit dem Code unter Customer Componets:

init_.py

from homeassistant.core import HomeAssistant

from homeassistant.helpers.discovery import load_platform


DOMAIN = "ads_waterlevel"


def setup(hass: HomeAssistant, config: dict):

# Plattform-basierte Einrichtung

return True

manifest.json

{

  "domain": "ads_waterlevel",

"name": "ADS Water Level",

"version": "1.2.0",

"documentation": "https://github.com/maxlin1/homeassistant_PekawayVANPICORE",

"issue_tracker": "https://github.com/maxlin1/homeassistant_PekawayVANPICORE/issues",

"codeowners": ["@maxlin1"],

"iot_class": "local_polling",

"dependencies": [],

"requirements": ["smbus2>=0.4.2", "aiofiles>=23.1.0"]

}

sensor.py

from _future_ import annotations

from datetime import timedelta

import logging

import time

from typing import List, Tuple, Optional, Dict, Any

from homeassistant.components.sensor import SensorEntity

from homeassistant.const import UnitOfElectricPotential, UnitOfVolume

from homeassistant.helpers.entity import DeviceInfo

from smbus2 import SMBus

_LOGGER = logging.getLogger(_name_)

SCAN_INTERVAL = timedelta(seconds=5)

# ---- ADS1115 ---------------------------------------------------------------

ADS_ADDR_DEFAULT = 0x48

REG_CONV = 0x00

REG_CONFIG = 0x01

MUX_MAP = {0: 0x4000, 1: 0x5000, 2: 0x6000, 3: 0x7000}

PGA_BITS = 0x0200

PGA_RANGE_V = 4.096

OS_START = 0x8000

MODE_SINGLE = 0x0100

DR_128SPS = 0x0080

COMP_DISABLE = 0x0003

def _build_cfg(channel: int) → int:

return OS_START | MUX_MAP[channel] | PGA_BITS | MODE_SINGLE | DR_128SPS | COMP_DISABLE

# ---- Hilfen ----------------------------------------------------------------

def ch_human_to_ain(ch: int) → int:

ch = int(ch)

if 1 <= ch <= 4:

return ch - 1

if 0 <= ch <= 3:

return ch

raise ValueError(f"Ungültiger channel: {ch}")

def build_linear_mapping(v_max: float, invert: bool, steps: int = 10) → List[Tuple[float, float]]:

pts: List\[Tuple\[float, float\]\] = \[\]

for i in range(steps + 1):

    v = round(v_max \* i / steps, 3)

    l = round(100.0 \* i / steps, 1)

if invert:

        l = round(100.0 - l, 1)

    pts.append((v, l))

return pts

def normalize_mapping_points(items: List[Dict[str, Any]], v_max: float, invert: bool) → List[Tuple[float, float]]:

pts = \[\]

for it in items:

    v = float(it\["v"\]); l = float(it\["l"\])

    pts.append((v, l))

pts.sort(key=lambda x: x\[0\])



have0 = any(abs(v) < 1e-6 for v, \_ in pts)

haveMax = any(abs(v - v_max) < 1e-6 for v, \_ in pts)

if not have0:

    pts = \[ (0.0, 100.0 if invert else 0.0) \] + pts

if not haveMax:

    pts = pts + \[ (v_max, 0.0 if invert else 100.0) \]

return pts

def interp(points: List[Tuple[float, float]], x: float) → float:

if not points:

return 0.0

if x <= points[0][0]:

return points[0][1]

if x >= points[-1][0]:

return points[-1][1]

for i in range(1, len(points)):

    x0, y0 = points\[i-1\]; x1, y1 = points\[i\]

if x0 <= x <= x1:

if x1 == x0:

return y0

        t = (x - x0) / (x1 - x0)

return y0 + t * (y1 - y0)

return points[-1][1]

# ---- Sensor-Entitäten ------------------------------------------------------

class ADSVoltageSensor(SensorEntity):

\_attr_device_class = "voltage"

\_attr_native_unit_of_measurement = UnitOfElectricPotential.VOLT

\_attr_state_class = "measurement"

\_attr_should_poll = True

def _init_(self, base_name: str, ain: int, divider_ratio: float):

self._base = base_name

self._ain = ain

self._ratio = float(divider_ratio or 1.0)

self._bus = SMBus(1)

self._addr = ADS_ADDR_DEFAULT

self._last_vin: Optional[float] = None

self._attr_name = f"{base_name} Voltage"

self._attr_unique_id = f"ads_wl_v_{ain}_{base_name}"

self._attr_device_info = DeviceInfo(

identifiers={(“ads_waterlevel”, “ads1115”)},

name=“ADS1115 Water Level”,

manufacturer=“Custom”,

model=“ADS1115”

    )

def update(self) → None:

try:

        cfg = \_build_cfg(self.\_ain)

self._bus.write_i2c_block_data(self._addr, REG_CONFIG, [(cfg >> 8) & 0xFF, cfg & 0xFF])

        time.sleep(0.009)

        raw = self.\_bus.read_i2c_block_data(self.\_addr, REG_CONV, 2)

        val = (raw\[0\] << 8) | raw\[1\]

if val > 0x7FFF:

            val -= 0x10000



        v_adc = (val \* PGA_RANGE_V) / 32768.0

if v_adc < 0: v_adc = 0.0

        v_in = round(v_adc \* self.\_ratio, 3)

self._last_vin = v_in

self._attr_native_value = round(v_in, 2)

except Exception as e:

_LOGGER.error(“ADS1115 Read AIN%s fehlgeschlagen: %s”, self._ain, e)

self._attr_native_value = None

self._last_vin = None

def get_last_voltage(self) → Optional[float]:

return self._last_vin

class ADSLevelSensor(SensorEntity):

\_attr_native_unit_of_measurement = UnitOfVolume.LITERS

\_attr_state_class = "measurement"

\_attr_should_poll = True

def _init_(self, base_name: str, voltage_sensor: ADSVoltageSensor,

mapping_points: List[Tuple[float, float]]):

self._base = base_name

self._vs = voltage_sensor

self._map = mapping_points

self._attr_name = f"{base_name} Level"

self._attr_unique_id = f"ads_wl_l_{base_name}"

def update(self) → None:

    v = self.\_vs.get_last_voltage()

if v is None:

self._vs.update()

        v = self.\_vs.get_last_voltage()

if v is None:

self._attr_native_value = None

return

    liters = interp(self.\_map, v)

self._attr_native_value = round(liters, 1)

class ADSResistanceSensor(SensorEntity):

\_attr_native_unit_of_measurement = "Ω"

\_attr_state_class = "measurement"

\_attr_should_poll = True

def _init_(self, base_name: str, voltage_sensor: ADSVoltageSensor, r_pullup: float, v_ref: float):

self._base = base_name

self._vs = voltage_sensor

self._rpu = float(r_pullup or 47000.0)

self._vref = float(v_ref or 3.3)

self._attr_name = f"{base_name} Resistance"

self._attr_unique_id = f"ads_wl_r_{base_name}"

def update(self) → None:

    v = self.\_vs.get_last_voltage()

if v is None:

self._vs.update()

        v = self.\_vs.get_last_voltage()

if v is None or v >= self._vref:

self._attr_native_value = None

return

    r = self.\_rpu \* (v / (self.\_vref - v))

self._attr_native_value = round(r, 0)

# ---- Plattform-Setup -------------------------------------------------------

async def async_setup_platform(hass, config, async_add_entities, discovery_info=None):

entities: List\[SensorEntity\] = \[\]



pair_cfg: Dict\[str, Dict\[str, Any\]\] = config.get("pair_config", {})

def defaults_for_channel_human(ch_human: int) → Dict[str, Any]:

    pair_key = "1-2" if ch_human in (1,2) else "3-4"

    d = {

“mode”: “voltage”,

“v_max”: 3.3,

“invert”: False,

    }

    d.update(pair_cfg.get(pair_key, {}))

return d

for s in config.get(“sensors”, []):

    name = s\["name"\]

    ch_human = int(s\["channel"\])

    ain = ch_human_to_ain(ch_human)



    dfl = defaults_for_channel_human(ch_human)

    mode = s.get("mode", dfl\["mode"\])

    v_max = float(s.get("v_max", dfl.get("v_max", 3.3)))

    invert = bool(s.get("invert", dfl.get("invert", False)))

    divider_ratio = float(s.get("divider_ratio", 1.0))

    r_pullup = float(s.get("r_pullup_ohm", dfl.get("r_pullup_ohm", 47000)))

    v_ref = float(s.get("v_ref", dfl.get("v_ref", 3.3)))



    mp_items = s.get("mapping_points")

if mp_items:

        mapping = normalize_mapping_points(mp_items, v_max=v_max, invert=invert)

else:

        mapping = build_linear_mapping(v_max=v_max, invert=invert, steps=10)



    v_ent = ADSVoltageSensor(name, ain, divider_ratio)

    l_ent = ADSLevelSensor(name, v_ent, mapping)

    entities.extend(\[v_ent, l_ent\])

if mode == “resistive”:

        r_ent = ADSResistanceSensor(name, v_ent, r_pullup, v_ref)

        entities.append(r_ent)

_LOGGER.debug(

“Setup %s (CH%d→AIN%d): mode=%s v_max=%.2f invert=%s ratio=%.3f”,

        name, ch_human, ain, mode, v_max, invert, divider_ratio

    )



async_add_entities(entities)

configurartion,yml

    sensors:
      # CH1 = Abwasser (Eigenbau Spannungsteiler + Dioden)
      - name: "Abwasser Tank"
        channel: 1
        divider_ratio: 1.0
        mode: voltage
        mapping_points:
          - { v: 0.00, l: 0 }
          - { v: 0.39, l: 20 }
          - { v: 0.41, l: 30 }
          - { v: 0.46, l: 40 }
          - { v: 0.47, l: 50 }
          - { v: 0.89, l: 60 }
          - { v: 0.93, l: 70 }
          - { v: 1.33, l: 80 }
          - { v: 1.46, l: 85 }
          - { v: 1.57, l: 90 }
          - { v: 1.59, l: 100 }

      # CH3 = Frischwasser (Votronic kapazitiv, 0–2.55V)
      - name: "Wasser Tank"
        channel: 3
        divider_ratio: 1.0
        mode: voltage
        mapping_points:
          - { v: 0.03, l: 0 }
          - { v: 0.91, l: 10 }
          - { v: 1.46, l: 20 }
          - { v: 1.71, l: 30 }
          - { v: 1.72, l: 40 }
          - { v: 2.04, l: 50 }
          - { v: 2.19, l: 60 }
          - { v: 2.33, l: 70 }
          - { v: 2.40, l: 80 }
          - { v: 2.45, l: 90 }
          - { v: 2.55, l: 100 }

Ich hab leider noch kein Teststetup daher mal nur was angeasst für dich könnte ggf. funktionieren bitte mal testen.