Skip to content

fix: E340 talkback — streamType, seq counters, command routing#837

Open
CaCEO1 wants to merge 2 commits intobropat:developfrom
CaCEO1:fix/e340-talkback
Open

fix: E340 talkback — streamType, seq counters, command routing#837
CaCEO1 wants to merge 2 commits intobropat:developfrom
CaCEO1:fix/e340-talkback

Conversation

@CaCEO1
Copy link
Copy Markdown

@CaCEO1 CaCEO1 commented Mar 6, 2026

Summary

Talkback (two-way audio) is completely broken on the E340 Dual Cam Doorbell (T8214). Three bugs were identified through packet capture comparison between the official Eufy Security app and homebridge-eufy-security.

This PR fixes all three. Tested on real E340 hardware — talkback confirmed working.

Context: PR #793 fixed livestream routing for E340 but talkback routing was not addressed. These are the remaining talkback-specific bugs. Directed here by @lenoxys in homebridge-plugins/homebridge-eufy-security#822.

Bugs Fixed

1. Wrong streamType in buildTalkbackAudioFrameHeader (src/p2p/utils.ts)

The magic bytes use 0x01 (doorbell microphone stream) instead of 0x02 (talkback speaker stream). The doorbell silently ignores audio frames tagged with the wrong stream direction.

- const magicBuffer = Buffer.from([0x01, 0x00]);
+ const magicBuffer = Buffer.from([0x02, 0x00]);

Pcap evidence — official app always sends 0x02 0x00 in the talkback audio header:

Official app frame:  c0 00 00 00 02 00 00 00 00 00 ...
                                  ^^ stream type = 0x02 (speaker)
homebridge (before): c0 00 00 00 01 00 00 00 00 00 ...
                                  ^^ stream type = 0x01 (mic) — WRONG

2. audioSeq and audioTimestamp always zero (src/p2p/utils.ts, src/p2p/session.ts)

Every talkback audio frame is sent with audioSeq=0 and audioTimestamp=0. The doorbell expects incrementing values — the official app increments seq by 1 per frame and timestamp by 64 per frame (64ms AAC-LC frames at 16kHz).

+ let _talkbackSeq = 0;
+ let _talkbackTimestamp = 0;
+
+ export const resetTalkbackCounters = (): void => {
+   _talkbackSeq = 0;
+   _talkbackTimestamp = 0;
+ };

Inside buildTalkbackAudioFrameHeader:

- const audioSeq = Buffer.alloc(2);
+ const audioSeq = Buffer.allocUnsafe(2);
+ audioSeq.writeUInt16LE(_talkbackSeq & 0xFFFF);
+ _talkbackSeq++;
  const audioTimestamp = Buffer.alloc(8);
+ audioTimestamp.writeBigUInt64LE(BigInt(_talkbackTimestamp));
+ _talkbackTimestamp += 64;

Counters are reset at the start of each startTalkback() call in session.ts.

Pcap evidence — official app increments both fields:

Frame 1: seq=0x0000  timestamp=0x0000000000000000
Frame 2: seq=0x0100  timestamp=0x4000000000000000  (1, 64 in LE)
Frame 3: seq=0x0200  timestamp=0x8000000000000000  (2, 128 in LE)

3. Wrong talkback command routing (src/http/station.ts)

startTalkback() and stopTalkback() route E340 through CMD_START_TALKBACK (command 1005), which the doorbell ignores. The official app uses CMD_DOORBELL_SET_PAYLOAD (1700) with CMD_START_SPEAK / CMD_END_SPEAK — the same path used by wired doorbells and indoor cameras.

This is the same routing pattern already applied for livestream in #793, but was missing for talkback.

  device.isOutdoorPanAndTiltCamera() ||
+ device.isBatteryDoorbellDualE340() ||
  (device.isIndoorPanAndTiltCameraS350() && !this.isDeviceControlledByHomeBase())

Added to both startTalkback() and stopTalkback() Branch A conditions.

ECDH Key Exchange

PR #779 originally included an ECDH P2P key exchange fix for E340 alongside the livestream routing. It was reverted, and #793 re-applied only the livestream routing.

I've been running with the ECDH fix reintegrated on my E340 for weeks and P2P connectivity has been flawless — livestream connects reliably every time with no session failures. Without ECDH, the E340 intermittently fails to establish P2P sessions.

Could you share more context on why ECDH was excluded from the recovery in #793? Was there a specific concern, or was it simply scoped out to keep #793 minimal? I'd be happy to submit a separate PR for ECDH if the approach is acceptable.

Test Plan

  • npm run build:ts compiles without errors
  • Diff matches compiled JS already deployed and confirmed working on real E340 (T8214)
  • Talkback audio confirmed via pcap — doorbell receives and plays back audio
  • No regressions to other device types (changes are scoped to isBatteryDoorbellDualE340() and the shared buildTalkbackAudioFrameHeader)

Related

max246 and others added 2 commits March 1, 2026 11:26
…nd routing

Three bugs prevent talkback (two-way audio) from working on the E340
Dual Cam Doorbell (T8214):

1. streamType 0x01 (doorbell mic) instead of 0x02 (talkback speaker)
   in buildTalkbackAudioFrameHeader — the doorbell silently ignores
   audio frames tagged with the wrong stream direction.

2. audioSeq and audioTimestamp are always zero — the doorbell expects
   incrementing sequence numbers (+1 per frame) and timestamps (+64
   per frame for 64ms AAC-LC at 16kHz). Module-level counters are
   reset on each startTalkback() call.

3. startTalkback/stopTalkback route E340 through CMD_START_TALKBACK
   (1005) instead of CMD_DOORBELL_SET_PAYLOAD (1700) with
   CMD_START_SPEAK/CMD_END_SPEAK. The official Eufy app uses 1700
   for this device — confirmed via pcap analysis.

All three bugs confirmed via packet capture comparison between the
official Eufy Security app and homebridge-eufy-security. Tested on
real E340 hardware (T8214) with all fixes applied — talkback works.

Ref: homebridge-plugins/homebridge-eufy-security#822
@CaCEO1 CaCEO1 force-pushed the fix/e340-talkback branch from 5c101da to 8836c85 Compare March 6, 2026 00:03
@lenoxys
Copy link
Copy Markdown
Contributor

lenoxys commented Mar 6, 2026

@CaCEO1, for ECDH Key Exchange there already a PR for that #795 we need further tests, it has impact on device managed by HB3

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.

3 participants