No description
  • Python 99%
  • JavaScript 1%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
2026-11-06 17:18:13 -05:00
custom_components/blueberry_velux Publish dist/repo/blueberry_velux 2026-11-06 17:18:13 -05:00
hacs.json Publish dist/repo/blueberry_velux 2026-11-06 17:18:13 -05:00
PUBLISHING.md Publish dist/repo/blueberry_velux 2026-11-06 17:18:13 -05:00
README.md Another annoying attempt for gateway imitation 2026-11-06 11:19:36 -05:00

VELUX ACTIVE initial reverse engineering

Simplified Home Assistant setup

Version 0.3 opens directly on the VELUX account email/password form. Homes, modules, names, covers, and available sensors are discovered from the account. New covers are added on later account refreshes without recreating the entry. Expired credentials produce a Home Assistant reauthentication prompt.

Enable advanced setup to enter paired roof-window signing material or choose BlueberryProxy diagnostics. Without paired signing material, roof windows are state-only. This change automates account inventory and supported cloud controls; it does not complete local Netcom authentication.

Home Assistant integration

The custom_components/blueberry_velux integration offers two setup modes. Account mode accepts VELUX credentials, refreshes OAuth tokens, polls home and module state, creates Home Assistant devices, and controls shutters and blinds through the VELUX API. Roof-window movement is exposed when the paired HashSignKey and signing key ID are supplied. Proxy mode retains LAN mDNS discovery, BlueberryProxy diagnostics, and transformer registration without account authentication. Account mode uses VELUX's cloud API, it is not local control. The app's separate local Netcom secure-auth sequence uses a PIN and user password with SPAKE2+, and is not yet implemented in this integration.

For a VELUX KIG 300 or KIX 300, use Home Assistant's built-in HomeKit Device integration for local control. Add the gateway while it is available for pairing, using its HomeKit code. If HomeKit pairing is unavailable or you prefer the vendor service, choose BlueberryVelux account mode for VELUX cloud control. Proxy mode is diagnostic only. Home Assistant's built-in Velux integration supports the separate KLF 200 gateway, not the KIG 300.

Target APK archive is VELUX-ACTIVE-with-NETATMO_3.4.2.0_apkcube.apks, package com.velux.active, version code 791304200. The base APK has been decoded with apktool. Its network discovery code confirms three DNS-SD types. It browses _mfi-config._tcp., _hap._tcp., and _netcom._tcp.. When an _mfi-config._tcp. advertisement has TXT property na_ver=2, the app switches discovery to _hap._tcp.. This ties the MFi setup advertisement to a HomeKit service discovery path. The local _netcom._tcp. service is handled separately.

The _hap._tcp. resolution path requires TXT key na_cfg. It extracts a device ID from na_tkn after validating the token, from id after validating that value, or from na_cfg=1 when an account ID is already available. For a positive advertised port, the app substitutes port 25050. A resolved address and a positive final port are required before the service is delivered to the app. For _netcom._tcp., the app checks TXT discriminator or mac_address against its Netatmo identity filters. These checks suggest discovery is tied to account registration and device identity, not generic unauthenticated control.

The app uses service resolution and TXT data, so the first live probe should record PTR, SRV, TXT and address records for all three service types. Preserve token values locally and redact them from notes, since they may identify or authorize an account or device.

The bundled discovery fixtures under the APK's assets/json/discover/en describe a VELUX home with an NXG gateway and NXO products. The sample gateway has a colon separated ID and sample actuators carry current_position, target_position, reachable, manufacturer, and bridge properties. These files are sample API data and do not establish a local protocol. The app's network security configuration explicitly permits cleartext to fw.netatmo.net; pinning is configured but not enforced in this build. These facts suggest cloud and firmware traffic and do not prove local registration or control.

The APK discovery branches have now been transcribed into the integration scanner. The integration also exposes a VELUX network-candidate sensor that correlates mDNS service addresses with BlueberryProxy's active LAN scan. A service advertisement is labeled as vendor-specific evidence. Other live or ARP hosts are retained as unclassified candidates, not identified as VELUX devices.

Purely local motor and shade control remains unverified. The APK contains cloud-oriented NetFlux action models such as SetTargetPositionAction, while the local Netcom path uses a secure preamble and SPAKE2+ authentication. The inspected local path does not show a validated actuator command exchange. HomeKit remains the only established local-control route in this implementation. A gateway capture, including pairing state and command traffic, is needed to determine whether a separate local actuator protocol exists.

The bundled Netcom library also defines JsonTunnelRequestFrame(method, paramsAsJson), but the VELUX app's Netcom package contains no call sites constructing that frame. This suggests a generic tunnel capability in the shared library, but it does not identify an actuator method or prove the gateway accepts one. It is a concrete next RE lead after the authenticated connection sequence, not a usable command API yet.

The APK's authenticated firmware lookup, download, checksum, and local OTA transfer sequence is documented in firmware-update-path.md, with the relevant decompiled classes preserved in decompiled/relevant-smali/. The downloaded firmware URL is returned dynamically by getfirmwareinfo; no image or live gateway response was present to retrieve it.

The arm64 APK split also includes the Netcom native serializers. The firmware OTA data frame, init frame, and firmware-version query bytes are recorded in firmware-update-path.md. These recover OTA transport framing, not the encrypted or authenticated actuator command layer.

Integration behavior and limits

custom_components/blueberry_velux/mdns.py sends PTR questions for _mfi-config._tcp.local, _hap._tcp.local, and _netcom._tcp.local, then joins PTR, SRV, TXT, A, and AAAA records into discovered services. It retains TXT values for inspection. The APK checks na_ver=2 before switching from MFi to HAP, requires na_cfg on HAP results, and uses port 25050 when its resolver receives a positive advertised HAP port. The component reports these values without manufacturing pairing state or issuing actuator commands. HAP pairing remains optional for discovery. Pair a discovered gateway with Home Assistant's HomeKit Controller to enable local controls.

The Netcom resolver and secure-auth artifacts are preserved under decompiled/relevant-smali/. android/fz0.smali contains the MFi-to-HAP na_ver=2 branch. android/or9.smali contains HAP na_cfg filtering and the 0x61da port substitution, which is decimal 25050. com/netatmo/netcom/n.smali checks Netcom TXT identity fields. The separate Netcom auth frames include a secure preamble and SPAKE2+ setup. These are provisioning and account authorization flows, not enough evidence to implement gateway actuator commands. No live gateway trace is available.

Local Netcom authentication status

The VELUX ACTIVE 3.4.2.0 APK identifies the negotiated SPAKE2+ suite as P256_SHA256_HKDFSHA256_HMACSHA256, with PBKDF2 parameters supplied by the gateway preamble. The app performs proof generation, point operations, frame encoding, and encrypted transport through libnacrypto.so and libjnetcom.so. The integration in this repository does not yet implement that local authenticated session. Its account mode uses VELUX's cloud API, and proxy mode only registers transforms and provides proxy diagnostics. Neither mode should be mistaken for local SPAKE2+ control.

The APK's JNI libraries and frame definitions are preserved under decompiled/relevant-smali as reverse-engineering evidence. Local control is not enabled until an independently implemented exchange can be checked against a real gateway capture and complete an authenticated session.