Legrand adorne LC7001
Local-LAN driver for the Legrand adorne LC7001 whole-house lighting hub. Talks the LC7001 JSON protocol on TCP port 2112 — the same channel the Legrand Home+ Control mobile app uses. Enumerates zones (Room Controllers, Switches, Dimmers, Outlets), sets power / dim level, and folds hub-pushed change events onto the corresponding GEM zone attributes. Scenes stored in RAM on the hub can be triggered by ID.
No cloud round-trip. If the LC7001 and the GEM controller are on the same subnet, control latency is under 100 ms even on large deployments.
Prerequisites
- LC7001 commissioned via the Legrand Home+ Control app and reporting online in the app.
- The LC7001 given a reserved DHCP lease or a static IP — the GEM device row stores an IP, not a hostname.
- Optional: if the installer set a system password in Home+ (Settings → Hub → Password), capture it now. It is the value passed to the driver as
password. Default installs have no password. - TCP 2112 reachable from the GEM controller. On the same subnet by default; if the hub sits behind a subnet boundary, open
2112/tcpon the intervening firewall.
Setup
- Get the LC7001 IP from your router or from the Home+ app → Settings → Hub.
- In GEM, open Admin → Devices → Add Device and pick driver legrand_adorne_lc7001.
- Enter
ip. Leaveporton 2112 unless you have a TCP proxy in front of the hub. - If a system password is set on the hub, paste it into
password. Otherwise leave blank. - On connect the driver runs ListZones, then ReportZoneProperties for every zone id to prime state. Look for the log line
legrand lc7001 discovered zones: <id> <name> <N>. - Run the
list_zonescommand to see every discovered zone. Each row is{address, name, power, power_level}. - Create one GEM zone per LC7001 zone. Use the numeric ZID as the GEM zone address.
Attribute reference
Device (required)
| Attribute | Description |
|---|---|
ip | LAN IP of the LC7001. Reserve a DHCP lease. |
Device (optional)
| Attribute | Default | Description |
|---|---|---|
port | 2112 | LC7001 protocol port. Hardcoded in firmware. |
password | (blank) | Home+ system password. Required only if the installer set one; the driver satisfies the hub's MD5 challenge automatically when present. |
default_ramp_rate | 0 | RampRate value passed on set_level (0 = instant, higher = slower crossfade). Ignored by switch and outlet zones. |
request_timeout | 5000 ms | Per-request timeout on ListZones, ReportZoneProperties, SetZoneProperties. A value that is zero, negative, not a number, or larger than 2147483647 falls back to 5000. |
Zone
| Attribute | Description |
|---|---|
address (required) | LC7001 zone id (ZID) as a small integer, e.g. 1, 2, 17. Run list_zones to enumerate. |
Zone address format
Zone addresses are numeric ZIDs exactly as the hub reports them, as strings — "1", "17". Do not use the hub's user-facing zone name; it is not a stable identifier. A zero-padded address such as "03" is read as ZID 3 for both commands and pushed state. A zone with no address receives no hub state.
Commands
| Command | Args | Notes |
|---|---|---|
on | address | SetZoneProperties with Power=true. |
off | address | SetZoneProperties with Power=false. |
set_level | address, level | PowerLevel 0..100. level==0 implicitly sets Power=false; level>0 implicitly sets Power=true. RampRate is added from default_ramp_rate when > 0. |
get_status | address | ReportZoneProperties for one ZID. The reported power and level are written onto the zone and returned. |
list_zones | Enumerate all zones (returns [{address, name, power, power_level}]). | |
list_scenes | Enumerate RAM scenes on the hub. | |
trigger_scene | scene_id | Fire a RAM scene by numeric ID. |
raw_command | service, body | Escape hatch: send an arbitrary Service with body (JSON object) merged in. The driver adds ID, and an ID inside body is ignored so the reply still reaches the command. A blank body sends none; a JSON array is refused. |
A command missing a value it needs is refused with an error instead of being sent: a zone command whose address is blank, not a number, negative, or an unfilled [@zone.address]; set_level with no numeric level; trigger_scene with a blank, non-numeric or negative scene_id; and raw_command with a blank or unfilled service. Every value that worked before is sent exactly as before.
State surfaced onto the zone
When the hub pushes a ZonePropertiesChanged event (or the driver polls with get_status):
| Zone attribute | Hub property | Notes |
|---|---|---|
state | Power | on / off. Written only once the hub has reported Power for the zone; a push that carries only a name or a level leaves state as it was. |
level | PowerLevel | Integer 0..100. Written even on switch/outlet zones so debugging is easier. |
Device attribute hub_mac | BroadcastMemory.MAC | Captured once on the initial BroadcastMemory hello frame. |
Known limitations
- Single active client — the LC7001 does not gracefully share a session with the Home+ app; state can drift briefly when both are connected. Prefer commissioning in Home+ and delegating day-to-day control to GEM.
- Zone type is not always reported. On older firmware, the hub does not label a zone as switch vs. dimmer vs. outlet. The driver treats
PowerLevel == 0 / 100as switch-like and everything else as dimmer-like; if a zone type matters to your macro, set an integrator-visibledevice_type_hinton the GEM zone. - Scene authoring is out of scope.
trigger_scenefires a RAM-stored scene by ID only. Create and edit scenes in Home+. - RampRate is best-effort. Some dimmer models ignore it, and the hub does not report back which do.
- No mesh discovery. The LC7001 does not auto-discover newly-paired devices without user pairing through Home+.
- Discovery retry. If the zone list cannot be read when the driver connects, it tries again after 30 s, doubling up to every 15 minutes, for as long as the connection stays up. A reconnect starts discovery again from the beginning.
Troubleshooting
| Symptom | Check |
|---|---|
| Socket connect refused | The hub is unreachable on 2112 — check IP, firewall, and hub power. After a power-cycle the hub takes ~60 s to bring up the TCP listener. |
Hub sends a Hello Challenge and nothing works afterwards (log: hub demands password but none configured) | A system password is set on the hub but password is unset (or wrong) on the device. Get the value from Home+ → Settings → Hub → Password. |
list_zones returns an empty list | The hub has no commissioned zones. Add zones in Home+ first — the LC7001 does not auto-discover. |
| Wall-switch presses do not update GEM state | The hub only pushes ZonePropertiesChanged for changes that originated inside the mesh. Switches on directly-wired loads (no adorne network module) are invisible to the hub. |
set_level lands but the zone stays off | Zone was off before the level write and the dimmer requires an explicit Power=true. The driver already includes it when level > 0 — if the behavior persists, the dimmer model is treating PowerLevel as a floor, not a target. Send on first, then set_level. |
A protocol-level Legrand adorne integration overview under Integrations is pending.