Skip to content

feat: real Home Assistant integration over Wear Engine P2P (3 platforms) - #2

Open
gentslava wants to merge 26 commits into
masterfrom
feat/real-ha-integration
Open

feat: real Home Assistant integration over Wear Engine P2P (3 platforms)#2
gentslava wants to merge 26 commits into
masterfrom
feat/real-ha-integration

Conversation

@gentslava

@gentslava gentslava commented Jun 15, 2026

Copy link
Copy Markdown
Owner

What this is

The first working version of the HA assistant for Huawei wearables: an Android companion (HA REST ↔ Wear Engine P2P bridge) + two watch apps (lite-JS for GT, ArkTS for Watch 4/5), plus the AIDD scaffolding for the monorepo.

Architecture: the watch has no direct path to HA — it talks to the phone over Wear Engine P2P, and the phone holds the REST connection to Home Assistant.

Contents

Companion (apps/phone-android) — Kotlin / Compose

  • HA REST client (OkHttp), transport-agnostic HaBridge, EntityMapper (light / switch / lock)
  • Wear Engine P2P transport (HMS SDK); for Android 11+ — <queries> (package visibility) + AGC app_id via meta-data
  • HA-style UI (dark + light theme), secure config (EncryptedSharedPreferences)
  • Tests: mapper + protocol parsing

watch-lite (apps/watch-lite) — JS / HML / CSS (FA model, Watch GT)

  • Wear Engine P2P client, HA repository, sync/action with optimistic update + rollback
  • UI states (loading / empty / offline), mock fallback

watch-arkts (apps/watch-arkts) — ArkTS (Watch 4/5)

  • Real P2P enabled + empty/offline UI states

Docs / AIDD

  • ADR-0007, per-app AGENTS.md (root is a router), platform-aware subagents
  • MVP spec, HA integration notes, P2P protocol (v:1, correlate by id, 8s timeout)

Status

  • Companion connects to a real HA (56 entities), UI done (dark + light)
  • ✅ Both watch apps build; watch-lite installed on a GT 6
  • ✅ Wear Engine bind verified on device: error progressed 12 → 8 (app recognized by AGC)
  • ⏳ Real E2E P2P is gated on Wear Engine approval in AGC (applied 2026-06-15)
  • The mock path works as a dev/offline fallback on both watches

Verification

  • companion: ./gradlew test green; installed on device, status "Connected — 56 entities"
  • watch-lite: hvigor assembleHap successful; HAP installed on a GT 6 via DevEco Assistant
  • Line endings normalized to LF (.gitattributes)

🤖 Generated with Claude Code

gentslava and others added 26 commits June 14, 2026 23:49
Spec 01 defines the real-HA-integration MVP (both watches + Android companion over one P2P contract). ha-integration-notes.md captures verified Home Assistant REST/WS API facts and the direct HA->P2P mapping (CALL_SERVICE = POST /api/services/<domain>/<service>), so the companion is built against the real API, not assumptions.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
settings/build/version-catalog, app module (compileSdk 35, minSdk 26), manifest with INTERNET, and .gitignore (excludes agconnect-services.json). Huawei repo + Wear Engine deps present but commented until AGC setup (Phase 1e).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
HaClient (checkApi/getStates/getState/callService over OkHttp, Bearer auth, Result-based), HaState model, and HaConfig (URL+token in EncryptedSharedPreferences). Built per docs/ha-integration-notes.md.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
p2p/Messages.kt mirrors the v1 contract (parseIncoming + outgoing DTOs). EntityMapper maps HA states to EntityCard for light/switch/lock (lock action is state-dependent). HaBridge turns an inbound JSON request into HA calls and a reply JSON — no transport dependency, so it is unit-testable.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Compose screen to enter HA URL + long-lived token, run Connect & test (checkApi -> getStates), and list mapped entities. Proves the HA layer end-to-end on the phone before the watch transport exists.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
EntityMapperTest (domain filtering, lock state-dependent action, friendly_name fallback) and MessagesTest (parseIncoming for all request types, ACK serialization). Run with ./gradlew test.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Replace the placeholder README with current status (HA layer + bridge + UI + tests done; Wear Engine transport next) and the AGC steps to enable Phase 1e.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
WearEngineP2pService (HMS SDK) requests DEVICE_MANAGER permission, finds the connected watch, registers a receiver, and on each inbound JSON request calls HaBridge.handle(...) and sends the reply. MainActivity starts it when HA is configured. Enabled the wearengine dependency + manifest permissions. Real credentials (PEER_FINGERPRINT, AGC fingerprint) are explicit placeholders.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The repo has three platforms (ArkTS, lite-JS ES5.1, Kotlin) but the AIDD layer was ArkTS-centric. Add nested apps/<app>/AGENTS.md with platform-specific rules (agents.md standard) and turn the root AGENTS.md into a router: shared context + a map to per-app rules, ArkTS specifics moved down. Prevents agents applying ArkTS rules to Kotlin/JS.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
arkts-architect -> architect (plans across all three apps + the contract). code-reviewer and test-writer now read the file's per-app AGENTS.md and apply that platform's rules/framework (strict ArkTS / ES5.1 / Kotlin; hypium / JUnit / on-device).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…tform

ADR-0007 documents the per-app AGENTS.md decision. CLAUDE.md and DEVELOPMENT.md updated: read the per-app AGENTS.md, architect (not arkts-architect), per-app verification (emulator / device / gradlew test).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
JerryScript on GT supports a fixed ES6 subset (let/const, arrow, destructuring, template strings, for-of, rest), not bare ES5. Only globalThis/Promise/async/spread/?./?? are unsupported. Earlier docs wrongly banned arrow functions.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Index loads real entities via haRepository.sync with loading/empty/offline status (mock kept as a debug fallback). Entity screen runs actions through callAction with optimistic update, syncEntity confirmation, and rollback on failure.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
p2pClient.js (bundled wearengine.js SDK, callbacks, id-correlation, 8s timeout), haRepository.js (sync/syncEntity/callAction over the v1 protocol), domains.js (EntityCard->item mapping), and config.json supportLists for the companion peer (fingerprint placeholder).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Uncomment setRemoteApp with the companion bundle (ru.gentslava.homeassistant.companion) and a fingerprint placeholder, so the real P2P repo is attempted before the Mock fallback. Index shows a status line (Loading / Offline / No entities) when the card list is empty instead of a blank screen.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Match the AGC registration and the watch bundle: companion applicationId becomes ru.gentslava.homeassistant (Kotlin namespace stays .companion). Update the P2P peer references on both watches (p2pClient.js PHONE_PKG, config.json supportLists, Services.ets setRemoteApp). Wear Engine pairs the phone and watch by this shared package + distinct fingerprints.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Use the available Wear Engine artifact (com.huawei.hms:wearengine:5.0.2.306); add the kotlinx.serialization.encodeToString reified import where used (HaBridge, HaClient, MessagesTest); fix AuthCallback.onCancel to return Unit. assembleDebug + unit tests green.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… to watches

applicationId = ru.gentslava.homeassistant.companion (distinct from the watch bundle, cleaner AGC + matches namespace). Set the companion's debug SHA-256 fingerprint as the peer on both watches (p2pClient.js, config.json supportLists, Services.ets). The companion's own peer (watch fingerprint) is still a placeholder until the watch is signed.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Android blocks cleartext (http://) by default since API 28; HA is typically reached over http on the LAN. usesCleartextTraffic=true permits it (same as the official HA Android app).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add HA brand dark theme (HA blue primary). Redesign the screen with systemBarsPadding (fixes the title overlapping the status bar), HA-styled title/fields/button, and entity cards with a domain glyph and state-colored accent (amber/green/blue per domain+state).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Wrapper (gradlew, gradle-wrapper), foojay-resolver in settings, and gradle-daemon-jvm.properties (Daemon JVM toolchain) so the project builds reproducibly from CLI/IDE/any machine with the right JDK auto-resolved.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
HaLightColorScheme + adaptive card/text colors via MaterialTheme.colorScheme; the screen now follows the system theme (isSystemInDarkTheme). HA blue stays the accent in both.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The build-profile carried a machine-specific signing config with absolute Windows paths, which broke builds on other machines. Reset signingConfigs to [] (like watch-arkts) and gitignore signing material. Each machine configures signing locally; signing material stays out of git.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
PEER_FINGERPRINT = the watch signing cert SHA-256 (from Debug.cer). Completes the symmetric Wear Engine pairing: companion knows the watch, watch knows the companion. Fingerprints are public, not secret.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Wear Engine on Android 11+ needs a <queries> block to resolve the Huawei
Health / HMS Core service via implicit intent; without it requestPermission
fails with "implicitIntent List are null". It also needs the AGC app_id to
authorize the app — supplied via the com.huawei.hms.client.appid meta-data —
otherwise requestPermission returns WearEngineException code 12.

Add both, plus a failure listener and diagnostics on the
requestPermission / getBondedDevices chain so errors surface in logcat.

Verified on device: error progressed 12 -> 8 (Scope unauthorized), i.e. the
app is now recognized by AGC; remaining gate is the Wear Engine approval.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Add .gitattributes enforcing LF for text files (Windows .bat/.cmd keep CRLF
on checkout, binaries marked explicitly so they are never touched).
Renormalize existing CRLF files — watch-lite is Windows-origin — to LF so
tools like ohpm no longer produce line-ending diff noise on the lockfile.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant