Files
lippert-onecontrol/docs/HOME_ASSISTANT_INTEGRATION.md
T
wes 718a13c02f Reorganize repository structure into logical folders
Structure:
- src/ - Python implementation (cobs_protocol.py, onecontrol_client.py)
- docs/ - All documentation markdown files
- scripts/ - Extraction scripts (for reference only)

Changes:
- Moved Python files to src/
- Moved all .md docs to docs/
- Moved extraction scripts to scripts/
- Updated README.md with new structure
- Updated import paths in README examples
- Added placeholder for future Quartz documentation URL

Benefits:
- Cleaner repository organization
- Easier to navigate
- Separates code from documentation
- Follows standard project conventions
2025-12-29 09:33:20 -05:00

7.6 KiB

Home Assistant Integration Plan for Lippert OneControl

Overview

This document outlines the plan to create a Home Assistant integration for Lippert OneControl RV systems via Bluetooth.

Integration Architecture

Advantages:

  • No need to reverse engineer full protocol if we can relay commands
  • Use ESP32 as Bluetooth<->WiFi bridge
  • Native Home Assistant integration
  • Reliable and well-supported

Components:

  • ESP32 device with Bluetooth
  • ESPHome firmware
  • Home Assistant ESPHome integration

Implementation:

  1. Configure ESP32 as Bluetooth proxy
  2. Discover OneControl device
  3. Create custom component for command sending

Option 2: Python-Based Custom Integration

Advantages:

  • Direct control from Home Assistant host
  • Can run on Home Assistant server (if it has Bluetooth)
  • Full protocol implementation

Components:

  • Python library using bleak for BLE communication
  • Home Assistant custom component (HACS)
  • Configuration via YAML or UI

Implementation:

# Key libraries needed
- bleak (Python BLE library)
- homeassistant.components (HA integration)

Step-by-Step Implementation

Phase 1: Protocol Discovery (Current Phase)

  • Complete .NET assembly decompilation
  • Capture Bluetooth packets using HCI snoop
  • Document command structure
  • Identify all GATT characteristics and UUIDs

Phase 2: Python Library Development

Create a Python library pylippert_onecontrol:

# pylippert_onecontrol/client.py
from bleak import BleakClient
import struct
from .cobs import encode_packet # Implement COBS + CRC8

# Confirmed UUIDs from Decompiled Code
SERVICE_UUID = "00000030-0200-A58E-E411-AFE28044E62C"
CHAR_READ_UUID = "00000034-0200-A58E-E411-AFE28044E62C"
CHAR_WRITE_UUID = "00000033-0200-A58E-E411-AFE28044E62C"

class OneControlClient:
    def __init__(self, address):
        self.address = address
        self.client = None
        self._seq = 0

    async def connect(self):
        self.client = BleakClient(self.address)
        await self.client.connect()

    def _next_seq(self):
        self._seq = (self._seq + 1) & 0xFFFF
        return self._seq

    async def send_command(self, cmd_type, table_id, payload):
        # 1. Build Packet
        # [Seq (2)] [CmdType (1)] [TableID (1)] [Payload...]
        seq = self._next_seq()
        packet = struct.pack("<HB", seq, cmd_type) + bytes([table_id]) + payload
        
        # 2. Append CRC8 (Init=0x55)
        crc = calculate_crc8(packet, init=0x55)
        packet += bytes([crc])
        
        # 3. COBS Encode
        encoded = cobs_encode(packet)
        
        # 4. Write
        await self.client.write_gatt_char(CHAR_WRITE_UUID, encoded)

    async def turn_on_light(self, light_id):
        # ActionSwitch (0x40), Table 1, On (1)
        # Payload: [State=1] [DeviceID]
        await self.send_command(0x40, 1, bytes([1, light_id]))

    async def turn_off_light(self, light_id):
        await self.send_command(0x40, 1, bytes([0, light_id]))

Phase 3: Home Assistant Integration

Directory Structure:

custom_components/lippert_onecontrol/
├── __init__.py          # Integration setup
├── manifest.json        # Integration metadata
├── config_flow.py       # Configuration UI
├── const.py            # Constants
├── light.py            # Light entities
├── switch.py           # Switch entities (pumps, etc.)
├── sensor.py           # Sensor entities (tanks)
├── cover.py            # Cover entities (awnings, slides)
└── climate.py          # Climate entities (heating)

Integration Code Skeleton:

# custom_components/lippert_onecontrol/__init__.py
async def async_setup_entry(hass, entry):
    """Set up Lippert OneControl from a config entry."""
    device = OneControlDevice(entry.data["address"])
    await device.connect()

    hass.data[DOMAIN] = device

    # Forward setup to platforms
    await hass.config_entries.async_forward_entry_setups(
        entry, ["light", "switch", "cover", "sensor", "climate"]
    )
    return True

Phase 4: Device Entities

Example: Light Control

# custom_components/lippert_onecontrol/light.py
from homeassistant.components.light import LightEntity

class OneControlLight(LightEntity):
    def __init__(self, device, light_id, name):
        self._device = device
        self._light_id = light_id
        self._name = name
        self._state = False

    @property
    def name(self):
        return self._name

    @property
    def is_on(self):
        return self._state

    async def async_turn_on(self):
        await self._device.control_light(self._light_id, True)
        self._state = True

    async def async_turn_off(self):
        await self._device.control_light(self._light_id, False)
        self._state = False

Example: Awning Control (Cover)

# custom_components/lippert_onecontrol/cover.py
from homeassistant.components.cover import CoverEntity, CoverDeviceClass

class OneControlAwning(CoverEntity):
    _attr_device_class = CoverDeviceClass.AWNING

    async def async_open_cover(self):
        await self._device.control_awning(self._awning_id, "extend")

    async def async_close_cover(self):
        await self._device.control_awning(self._awning_id, "retract")

Next Steps

Immediate Actions Needed:

  1. Bluetooth Packet Capture

    # On Android device with app
    adb shell settings put secure bluetooth_hci_log 1
    # Use the Lippert Connect app to control devices
    adb pull /data/misc/bluetooth/logs/btsnoop_hci.log
    # Analyze with Wireshark
    
  2. Extract .NET Assemblies

    • Need to properly extract DLLs from the Xamarin blob
    • Decompile with dnSpy or ILSpy
    • Document complete command structure
  3. Test BLE Connection

    # Quick test script
    import asyncio
    from bleak import BleakScanner
    
    async def scan():
        devices = await BleakScanner.discover()
        for d in devices:
            print(f"{d.name}: {d.address}")
            if "OneControl" in str(d.name) or "Lippert" in str(d.name):
                print(f"Found potential device: {d}")
    
    asyncio.run(scan())
    
  4. Manual BLE Exploration

    • Use nRF Connect app to explore OneControl device
    • List all services and characteristics
    • Try writing test values to understand command format

Alternative: Existing Solutions

Before building from scratch, check:

  1. Lippert API: Contact Lippert for official API/SDK
  2. Existing Projects: Search GitHub for "OneControl", "Lippert", "MyRV"
  3. RV Forums: Check iRV2, Forest River forums for existing integration work

Resources

Python Libraries

  • bleak - Cross-platform BLE library
  • homeassistant - HA development

Tools

  • nRF Connect - BLE explorer (Android/iOS)
  • Wireshark - Packet analysis
  • dnSpy / ILSpy - .NET decompiler

Documentation

Timeline Estimate

  • Protocol Discovery: 1-2 days
  • Python Library: 2-3 days
  • HA Integration: 3-5 days
  • Testing & Refinement: 2-3 days
  • Total: ~1-2 weeks

Success Criteria

  • Can discover OneControl device via BLE
  • Can connect to device
  • Can send commands (lights, pumps, awnings, etc.)
  • Can read state/status from device
  • Integration works in Home Assistant
  • All RV systems controllable from HA
  • Reliable operation over Bluetooth range