Skip to content

Add T8501 (Eufy Solo Smart Lock D20) lock/unlock support (V12 protocol)#928

Open
dastorie wants to merge 1 commit into
bropat:developfrom
dastorie:t8501-d20-lock-v12
Open

Add T8501 (Eufy Solo Smart Lock D20) lock/unlock support (V12 protocol)#928
dastorie wants to merge 1 commit into
bropat:developfrom
dastorie:t8501-d20-lock-v12

Conversation

@dastorie

Copy link
Copy Markdown

Summary

The Eufy Solo Smart Lock D20 (T8501) is already detected as a lock and its state reads correctly, but lock/unlock commands are silently ignored. Root cause: it's routed to the legacy wifi-lock P2P protocol, but the T8501 only responds to the "V12" lock protocol (getLockV12P2PCommand, the same family as the R10/R20 retrofit locks). Routing it through V12 makes lock/unlock work. No new DeviceType/DeviceProperties entries are needed.

Closes #226.

Device facts (captured from a live unit)

Field Value
device_type 53 (LOCK_WIFI_NO_FINGER)
device_model T8501
serial prefix T8501… (it is its own station)
hardwareVersion P0
softwareVersion 1.0.4.0
Device.isLock(53) already true
state (locked / lockStatus / battery) reads fine

State arrives over MQTT (smart-lock message, eventType 770 lockState / 261 unlock / 264 lock), which is why state has always worked even though every command was being dropped.

Root cause

Station.lockDevice() dispatched device_type 53 via isLockWifiNoFinger() into the legacy branch (getLockP2PCommand, P2P_ON_OFF_LOCK). The "P0" hardware superficially resembles the modern smart-lock family, but neither the legacy nor the smart-lock (getSmartLockP2PCommand) protocol gets any response from this device — only getLockV12P2PCommand does.

Evidence (redacted P2P traces)

# legacy (as shipped):  no response
getLockP2PCommand cmd 1961 (P2P_ON_OFF_LOCK)          -> lock does not move
P2P_QUERY_STATUS_IN_LOCK (1955)                       -> return_code -133 (ERROR_COMMAND_TIMEOUT)

# smart-lock:  no response
getSmartLockP2PCommand cmd 6018 / handshake 6016,6012 -> no P2P response

# V12:  WORKS
getLockV12P2PCommand handshake 6016,6012              -> return_code 0 (ERROR_PPCS_SUCCESSFUL), command_type 1930
  UNLOCK -> locked=false, lockStatus 4->3, MQTT unlock event (261)
  LOCK   -> locked=true,  lockStatus 3->4, MQTT lock  event (264)

Both directions physically actuate the bolt and the state reflects back.

What changed

  • src/http/device.ts — add Device.isLockWifiT8501(type, serial) (device_type 53 and serial starts with T8501, so other type-53 devices are unaffected — mirrors the existing T8510P/T8520P serial-prefix split), plus the instance wrapper.
  • src/http/station.ts — route T8501 through the V12 branch in lockDevice, getLockParameters and getLockStatus; exclude it from the legacy isLockWifi()/isLockWifiNoFinger() branch. The RSA lock public key is still fetched (V12 needs it), so the public-key gate is unchanged.

Builds clean (tsc); the change follows the existing file style.

Known-incomplete (not needed for lock/unlock): calibrateLock() and a few other per-feature dispatch sites still route device_type 53 down the legacy path. Only lock/unlock + connect-time params/status were changed here; the rest can follow the same isLockWifiT8501() routing if desired.

Verification

  • Library standalone: UNLOCK then LOCK both return return_code 0, the bolt physically moves, locked/lockStatus update, and MQTT lock/unlock events fire.
  • End-to-end via Home Assistant (fuatakgun/eufy_securityeufy-security-ws 3.0.1 → patched client): lock.unlock / lock.lock actuate the real D20 and Home Assistant reflects the state.

🤖 Generated with Claude Code

…V12 protocol

The Eufy Solo Smart Lock D20 (T8501) reports device_type 53 (LOCK_WIFI_NO_FINGER)
and is already detected as a lock with working state, but lock/unlock commands were
silently dropped: lockDevice() routed it to the legacy wifi-lock P2P protocol, while
the device only responds to the "V12" lock protocol (getLockV12P2PCommand, same
family as the R10/R20 retrofit locks).

Add an isLockWifiT8501 detector (device_type 53 + serial prefix "T8501", so other
type-53 devices are unaffected, mirroring the T8510P/T8520P serial-prefix split) and
route it through the V12 path in lockDevice, getLockParameters and getLockStatus;
exclude it from the legacy branch. No DeviceType/DeviceProperties changes needed.

Verified on real hardware: UNLOCK/LOCK return code 0, the bolt actuates, state
reflects back; also end-to-end via eufy-security-ws + Home Assistant.

Closes bropat#226

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