dafit/moyoung framing (pairs only, no decode) - #46
Conversation
no signal decode yet, just the framing to hold a session open and bank raw bytes.
Reviewer's GuideIntroduces an experimental, publicly exported DaFit/MOYOUNG-V2 framing layer that can parse and construct data/ACK frames, pack handshake date-time data, and generate the required initialization sequence, with tests covering the wire-format behavior; it intentionally performs no signal decoding or transport integration. Sequence diagram for the DaFit handshake and framed exchangesequenceDiagram
participant Edge
participant Band
Edge->>Band: buildDafitFrame Init1
Edge->>Band: buildDafitFrame SetDateTime
Edge->>Band: buildDafitFrame Init1
Edge->>Band: buildDafitFrame Init2
Edge->>Band: buildDafitFrame SetLanguage
Edge->>Band: buildDafitFrame Init3
Edge->>Band: buildDafitFrame GetHwInfo
Edge->>Band: buildDafitFrame GetBandInfo
Band-->>Edge: Data notification
Edge->>Edge: parseDafitFrame
Edge->>Band: buildDafitAck
Band-->>Edge: ACK notification
Edge->>Edge: isDafitAckFrame
File-Level Changes
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
|
Warning Review limit reachedNext included review available in 51 minutes. View limit detailsLimit details: You’ve used the included review currently available. You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository. Review configuration: ⚙️ Run configurationConfiguration used: Organization UI Review profile: ASSERTIVE Plan: Team Run ID: 📒 Files selected for processing (3)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Hey - I've found 3 issues
Prompt for AI Agents
Please address the comments from this code review:
## Individual Comments
### Comment 1
<location path="lib/src/dafit.dart" line_range="129-130" />
<code_context>
+/// this family also uses band-to-app, interspersed with data frames during
+/// the same exchange. Not decoded further: nothing downstream needs more
+/// than "this notification was an ack, not data".
+bool isDafitAckFrame(List<int> value) =>
+ value.length == 8 && value[0] == kDafitAckHeader;
+
+/// Pack a local date/time into this family's bit-packed SET_DATE_TIME field:
</code_context>
<issue_to_address>
**issue (bug_risk):** isDafitAckFrame classifies any 8-byte packet beginning with 0xDC as a valid ACK, even when the fixed bytes at [1..2], [4], or [7] are wrong. A malformed or unrelated notification is therefore routed as an ACK instead of being rejected.
**Triggers:** When an 8-byte 0xDC-headed notification has invalid ACK fields.
**Suggested fix:** Validate the complete fixed ACK shape, including `value[1] == 0`, `value[2] == 0x05`, `value[4] == 0x01`, and `value[7] == 0x01`.
```suggestion
bool isDafitAckFrame(List<int> value) =>
value.length == 8 &&
value[0] == kDafitAckHeader &&
value[1] == 0 &&
value[2] == 0x05 &&
value[4] == 0x01 &&
value[7] == 0x01;
```
</issue_to_address>
### Comment 2
<location path="lib/src/dafit.dart" line_range="82" />
<code_context>
+/// delivered.
+DafitFrame? parseDafitFrame(List<int> value) {
+ if (value.length < 8 || value[0] != kDafitDataHeader) return null;
+ final outerLen = (value[1] << 8) | value[2];
+ final payloadLen = (value[6] << 8) | value[7];
+ if (value.length - 8 < payloadLen) return null;
+ return DafitFrame(
+ value[3],
</code_context>
<issue_to_address>
**issue (bug_risk):** parseDafitFrame reads and preserves outerLen but never verifies that it matches the declared payload length (`outerLen == 5 + payloadLen`). A malformed frame with inconsistent length fields is returned as valid, and buildDafitAck then echoes the invalid outer length and produces an incorrect ACK.
**Triggers:** When the band sends a data frame whose outer and payload length fields disagree.
**Suggested fix:** Reject the frame when `outerLen != 5 + payloadLen` before constructing DafitFrame.
```suggestion
if (value.length - 8 < payloadLen || outerLen != 5 + payloadLen) return null;
```
</issue_to_address>
### Comment 3
<location path="lib/src/dafit.dart" line_range="136-141" />
<code_context>
+/// seconds, then (year-2000), month, day, hour, minute each shifted into
+/// their own bit range of one big-endian u32.
+int packDafitDateTime(DateTime t) {
+ return t.second |
+ ((t.year - 2000) << 26) |
+ (t.month << 22) |
+ (t.day << 17) |
+ (t.hour << 12) |
+ (t.minute << 6);
+}
+
</code_context>
<issue_to_address>
**nitpick (bug_risk):** packDafitDateTime does not constrain `t.year - 2000` to the documented six-bit field. Dates at or after 2064, or before 2000, spill outside the field and are truncated by the later 32-bit encoding, so the watch receives a different year.
**Triggers:** When the supplied DateTime is outside the protocol's representable year range 2000 through 2063.
**Suggested fix:** Reject unsupported years or mask and document an explicit wrapping policy before packing.
</issue_to_address>Sourcery assessment
Needs a human reviewer. 2 findings to address first, and if the framing or ACK arithmetic is wrong, the watch may reject subsequent requests, stall the exchange, or drain its battery, and the initialization sequence can write an incorrect clock or language setting to the device. Reverting prevents future writes, while the device state and any battery drain already caused require a reconnect or corrective command to repair.
Blocking findings: lib/src/dafit.dart:130, lib/src/dafit.dart:82
length-mismatched frames were accepted and echoed back into acks; a year outside 2000-2063 silently truncated in the clock write. sourcery
not just the header byte. sourcery
adds the frame/ack/handshake bytes for the dafit/moyoung-v2 clone-watch family (m4/m6/lh716/sunset6/watch7/fit1900 style boards, sold under a pile of storefront names). pure dart, no crypto, no crc.
no signal decode here, just enough framing for edge to hold a session open and bank raw bytes.
Summary by Sourcery
Add experimental DaFit/MOYOUNG-V2 framing support to keep compatible watch sessions active while preserving raw protocol data.
New Features:
Enhancements:
Tests: