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
7.6 KiB
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
Option 1: ESPHome Bluetooth Proxy (Recommended)
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:
- Configure ESP32 as Bluetooth proxy
- Discover OneControl device
- 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
bleakfor 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:
-
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 -
Extract .NET Assemblies
- Need to properly extract DLLs from the Xamarin blob
- Decompile with dnSpy or ILSpy
- Document complete command structure
-
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()) -
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:
- Lippert API: Contact Lippert for official API/SDK
- Existing Projects: Search GitHub for "OneControl", "Lippert", "MyRV"
- RV Forums: Check iRV2, Forest River forums for existing integration work
Resources
Python Libraries
bleak- Cross-platform BLE libraryhomeassistant- 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