Skip to content

fix(device): restore Clone WINC flag + surface health telemetry (closes #331, #335) - #348

Merged
tylerkron merged 3 commits into
mainfrom
fix/caps-clone-health-telemetry
Jul 18, 2026
Merged

fix(device): restore Clone WINC flag + surface health telemetry (closes #331, #335)#348
tylerkron merged 3 commits into
mainfrom
fix/caps-clone-health-telemetry

Conversation

@tylerkron

Copy link
Copy Markdown
Contributor

Summary

Two related metadata/capabilities fixes that share the Clone/CopyFrom round-trip path.

#331DeviceCapabilities.Clone() silently dropped HasWincWifiModule

Clone() copied 8 of 9 properties, so every clone (and therefore DeviceMetadata.CopyFrom) reset the WINC flag to false — a false negative that steers consumers away from required WINC-specific handling (power-on-before-probe, WINC flash tool, bridge-mode activation).

  • Added the missing HasWincWifiModule copy.
  • Replaced the hand-listed Clone test with a reflection-based round-trip that fails if any future property is dropped from Clone(), closing the bug class.

#335 — surface device health telemetry (battery %, board temp, power/device status)

The protobuf status message carries BattStatus, TempStatus, PwrStatus, DeviceStatus; Core decoded the message but threw these away (only discovery read PwrStatus).

  • New DeviceHealth type exposed as DeviceMetadata.Health.
  • Populated in UpdateFromProtobuf, which runs before the classified StatusMessageReceived event fires — so consumers reading device.Metadata.Health in that handler see current values.
  • Battery/temp are int? and only assigned when the message carries the field (proto3 has no presence → 0 == not reported); raw power/device codes exposed as-is.
  • Round-trips through CopyFrom/Clone (deep-copied, per fix: DeviceCapabilities.Clone() silently drops HasWincWifiModule #331).

Testing

  • dotnet test — 1590 pass, 0 fail.
  • Bench-tested on real hardware (Nyquist 1, FW 3.7.2): Clone round-trips HasWincWifiModule=True; live status messages populate Battery%=100, Pwr=1, DevStatus=3. (Board temp reported as absent on this USB-powered unit — correctly surfaced as null.)

Closes #331, closes #335.

#331, #335)

#331: DeviceCapabilities.Clone() omitted HasWincWifiModule, so every clone
(including DeviceMetadata.CopyFrom) silently reset the WINC flag to false,
steering consumers away from required WINC handling. Add the missing copy and
replace the hand-listed Clone test with a reflection-based round-trip that fails
if any future property is dropped from Clone().

#335: The protobuf status message carries device health (battery %, board temp,
power/device status) but Core decoded and discarded it. Add a DeviceHealth type
on DeviceMetadata, populate it in UpdateFromProtobuf (which runs before the
classified StatusMessageReceived event fires), and round-trip it through CopyFrom.
Battery/temp are nullable and only set when the message carries the field (proto3
has no presence, so 0 == not-reported); the raw power/device codes are exposed
as-is. Verified on real hardware (Nq1, FW 3.7.2): battery=100%, power/device
status populate from live status messages.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@tylerkron
tylerkron requested a review from a team as a code owner July 18, 2026 21:12
@qodo-code-review

Copy link
Copy Markdown

PR Summary by Qodo

Fix Clone WINC capability and expose device health telemetry

🐞 Bug fix ✨ Enhancement 🧪 Tests 🕐 20-40 Minutes

Grey Divider

AI Description

• Fix DeviceCapabilities.Clone() to preserve HasWincWifiModule across Clone/CopyFrom.
• Expose status-message health telemetry (battery, board temp, power/device codes) via
 DeviceMetadata.Health.
• Add/strengthen tests for reflection-based Clone round-trip and health update/deep-copy semantics.
Diagram

graph TD
  StatusMsg["DaqifiOutMessage"] --> Update["DeviceMetadata.UpdateFromProtobuf"] --> Meta["DeviceMetadata"] --> Consumer["StatusMessageReceived handler"]
  Meta --> Health["DeviceHealth"]
  Meta --> Copy["DeviceMetadata.CopyFrom"] --> Clone["Clone() deep copies"]
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Add proto presence (optional/wrapper types)
  • ➕ Removes the ambiguity between 0 and "not reported" for BattStatus/TempStatus/PwrStatus/DeviceStatus
  • ➕ Allows legitimate 0 values to be represented without special-casing
  • ➖ Requires protobuf schema change and regeneration; may be constrained by firmware/protocol compatibility
  • ➖ Potentially larger rollout surface than a Core-only change
2. Track explicit timestamps/validity flags in DeviceHealth
  • ➕ Preserves existing proto contract while making "unknown vs known" explicit
  • ➕ Can support staleness detection (e.g., last updated at)
  • ➖ Adds more API surface and bookkeeping than needed for the immediate fix
  • ➖ Still can’t distinguish a real 0 reading from absent without protocol support
3. Surface health telemetry only on events (not stored on metadata)
  • ➕ Avoids mutable shared state; consumers get per-message payloads
  • ➕ Clearer semantics around partial messages
  • ➖ Harder for consumers that want "latest snapshot" semantics
  • ➖ Requires broader event API changes and more refactoring

Recommendation: The current approach is a good Core-only fix: it preserves last-known values for absent proto3 scalars and makes telemetry available via DeviceMetadata before status handlers run. If the protocol can evolve, consider adding protobuf presence (optional/wrappers) later to eliminate the 0-vs-absent ambiguity entirely.

Files changed (5) +182 / -11

Enhancement (2) +87 / -0
DeviceHealth.csIntroduce DeviceHealth model with Clone() +56/-0

Introduce DeviceHealth model with Clone()

• Adds a new DeviceHealth type to represent decoded health telemetry (battery %, board temp, raw power/device status codes). Uses nullable ints for battery/temp and provides a Clone() method for deep-copy behavior.

src/Daqifi.Core/Device/DeviceHealth.cs

DeviceMetadata.csExpose and populate DeviceMetadata.Health from status messages +31/-0

Expose and populate DeviceMetadata.Health from status messages

• Adds a Health property on DeviceMetadata and ensures it is deep-copied in CopyFrom. Updates UpdateFromProtobuf to populate telemetry fields when non-zero values are present, avoiding clobbering last-known readings on partial status messages.

src/Daqifi.Core/Device/DeviceMetadata.cs

Bug fix (1) +1 / -0
DeviceCapabilities.csFix Clone() to copy HasWincWifiModule +1/-0

Fix Clone() to copy HasWincWifiModule

• Adds the missing HasWincWifiModule assignment in DeviceCapabilities.Clone(), preventing WINC capability from being lost across Clone/CopyFrom round-trips.

src/Daqifi.Core/Device/DeviceCapabilities.cs

Tests (2) +94 / -11
DeviceCapabilitiesTests.csMake Clone test reflection-based and cover HasWincWifiModule +19/-11

Make Clone test reflection-based and cover HasWincWifiModule

• Renames the Clone test to a reflection-driven round-trip that asserts every readable public property is copied. Sets HasWincWifiModule to a non-default value and adds a guard to prevent new properties from silently being left at defaults in the test.

src/Daqifi.Core.Tests/Device/DeviceCapabilitiesTests.cs

DeviceMetadataTests.csAdd health telemetry and deep-copy tests for DeviceMetadata +75/-0

Add health telemetry and deep-copy tests for DeviceMetadata

• Adds tests verifying UpdateFromProtobuf populates battery/temp/power/device status, preserves negative temperatures, and does not clobber prior values when health fields are absent/zero. Extends CopyFrom tests to include Health fields and adds a deep-copy (non-shared reference) assertion.

src/Daqifi.Core.Tests/Device/DeviceMetadataTests.cs

@qodo-code-review

qodo-code-review Bot commented Jul 18, 2026

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (0) 📘 Rule violations (0) 📎 Requirement gaps (0) 📜 Skill insights (0)

Context used

Grey Divider


Action required

1. Null Health crashes status ✓ Resolved 🐞 Bug ☼ Reliability
Description
DeviceMetadata.UpdateFromProtobuf dereferences Health without ensuring it is non-null; since
DeviceMetadata.Health is publicly settable, consumers can set it to null and the next status frame
with any non-zero health field will throw NullReferenceException. This exception occurs on the main
status-message processing path (DaqifiDevice.OnStatusMessageReceived), potentially breaking status
handling for that device.
Code

src/Daqifi.Core/Device/DeviceMetadata.cs[R202-220]

+        if (message.BattStatus != 0)
+        {
+            Health.BatteryPercent = (int)message.BattStatus;
+        }
+
+        if (message.TempStatus != 0)
+        {
+            Health.BoardTemperatureCelsius = message.TempStatus;
+        }
+
+        if (message.PwrStatus != 0)
+        {
+            Health.PowerStatus = message.PwrStatus;
+        }
+
+        if (message.DeviceStatus != 0)
+        {
+            Health.DeviceStatus = message.DeviceStatus;
+        }
Relevance

⭐⭐⭐ High

Defensive null-safety on public APIs is commonly accepted (e.g., null-guarding CopyFrom and event
invocations in #319, #323).

PR-#319
PR-#323

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
Health is publicly settable (can be assigned null), yet UpdateFromProtobuf dereferences it when any
of the health fields are non-zero; this method is called for every status frame by DaqifiDevice, so
a null Health breaks the status pipeline.

src/Daqifi.Core/Device/DeviceMetadata.cs[35-46]
src/Daqifi.Core/Device/DeviceMetadata.cs[117-221]
src/Daqifi.Core/Device/DaqifiDevice.cs[1189-1207]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`DeviceMetadata.UpdateFromProtobuf` writes `Health.BatteryPercent`, `Health.BoardTemperatureCelsius`, etc. without first ensuring `Health` is non-null. Because `DeviceMetadata.Health` has a public setter, external code (or deserialization) can set it to `null`, and status processing will throw a `NullReferenceException` as soon as a non-zero health field arrives.

## Issue Context
- `DaqifiDevice.OnStatusMessageReceived` calls `Metadata.UpdateFromProtobuf(message)` for every status frame, so the null dereference is reachable during normal device operation.
- `Capabilities` has similar assumptions; consider hardening both.

## Fix Focus Areas
- src/Daqifi.Core/Device/DeviceMetadata.cs[117-221]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended

2. Battery docs contradict semantics ✓ Resolved 🐞 Bug ⚙ Maintainability ⭐ New
Description
DeviceHealth.BatteryPercent is documented as becoming null when the most recent status message
doesn't report it, but DeviceMetadata.UpdateFromProtobuf preserves the last-known value when
BattStatus is absent/0/out-of-range. This makes the public API documentation inaccurate and can
cause consumers to misinterpret a non-null value as coming from the latest status message rather
than being stale.
Code

src/Daqifi.Core/Device/DeviceHealth.cs[R19-21]

+    /// Gets or sets the battery charge as a percentage (1-100), or <c>null</c> if the most
+    /// recent status message did not report it. Populated only from in-contract readings; an
+    /// out-of-range value from the device is ignored rather than surfaced.
Relevance

⭐⭐⭐ High

Team often fixes XML doc/behavior mismatches (accepted in PRs #321, #98, #288); likely update
BatteryPercent docs/semantics.

PR-#321
PR-#98
PR-#288

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The property doc claims presence-on-latest-message (null when not reported), but the update path
only assigns when BattStatus is within 1..100 and otherwise leaves the existing value untouched;
the tests also lock in that “partial status message” behavior (no clobbering).

src/Daqifi.Core/Device/DeviceHealth.cs[18-23]
src/Daqifi.Core/Device/DeviceMetadata.cs[212-223]
src/Daqifi.Core.Tests/Device/DeviceMetadataTests.cs[265-276]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`DeviceHealth.BatteryPercent` XML documentation currently states it is `null` if the *most recent* status message did not report it. However, `DeviceMetadata.UpdateFromProtobuf` intentionally keeps the last-known value when the field is not reported (proto3 scalar default/0) or out of range.

## Issue Context
This PR’s implementation (and tests) establish “last-known value” semantics for health telemetry; documentation should reflect that to avoid misleading API consumers.

## Fix Focus Areas
- src/Daqifi.Core/Device/DeviceHealth.cs[18-22]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


3. Health test not captured payload ✓ Resolved 📎 Requirement gap ☼ Reliability
Description
The new health telemetry test constructs a DaqifiOutMessage directly instead of using a
captured/serialized status payload, so it doesn’t verify real payload decoding/population
end-to-end. This can miss regressions in the wire-level frame/field decoding path that the
compliance item explicitly targets.
Code

src/Daqifi.Core.Tests/Device/DeviceMetadataTests.cs[R169-190]

+    [Fact]
+    public void UpdateFromProtobuf_UpdatesHealthTelemetry()
+    {
+        // Arrange
+        var metadata = new DeviceMetadata();
+        var message = new DaqifiOutMessage
+        {
+            BattStatus = 87,
+            TempStatus = 42,
+            PwrStatus = 2,
+            DeviceStatus = 5
+        };
+
+        // Act
+        metadata.UpdateFromProtobuf(message);
+
+        // Assert
+        Assert.Equal(87, metadata.Health.BatteryPercent);
+        Assert.Equal(42, metadata.Health.BoardTemperatureCelsius);
+        Assert.Equal(2u, metadata.Health.PowerStatus);
+        Assert.Equal(5u, metadata.Health.DeviceStatus);
+    }
Relevance

⭐⭐⭐ High

Team often strengthens tests with real serialized/captured protobuf frames (accepted in PRs #325,
#197).

PR-#325
PR-#197

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
PR Compliance ID 4 requires a test using a captured status payload; the added test sets
BattStatus/TempStatus/PwrStatus/DeviceStatus directly on a new DaqifiOutMessage, which
bypasses validating decoding from a captured payload.

Add test using captured status payload to assert device health telemetry decoding/population
src/Daqifi.Core.Tests/Device/DeviceMetadataTests.cs[169-190]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The device health telemetry tests do not use a captured (serialized) status payload, so they validate `UpdateFromProtobuf` only after a `DaqifiOutMessage` is already constructed.

## Issue Context
PR Compliance ID 4 requires an automated test that uses a real/captured status payload and asserts decoded/populated battery %, board temperature, power status, and device status.

## Fix Focus Areas
- src/Daqifi.Core.Tests/Device/DeviceMetadataTests.cs[169-215]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


4. Invalid battery percent accepted ✓ Resolved 🐞 Bug ≡ Correctness
Description
UpdateFromProtobuf assigns Health.BatteryPercent = (int)message.BattStatus without validating the
documented 0–100 range; out-of-contract values (e.g., 500, or very large uints) will be published to
consumers. Because BattStatus is uint, very large values can also wrap negative when cast to int
in the default unchecked context.
Code

src/Daqifi.Core/Device/DeviceMetadata.cs[R202-205]

+        if (message.BattStatus != 0)
+        {
+            Health.BatteryPercent = (int)message.BattStatus;
+        }
Relevance

⭐⭐ Medium

Range/overflow validation is mixed: accepted for some sanitization (#328) but similar cast/bounds
checks were rejected (#117).

PR-#328
PR-#117

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The protobuf field is a uint documented as a percentage; the code casts it directly to int? without
validation, so values outside 0–100 are not filtered and very large uints can wrap when cast to int.

src/Daqifi.Core/Communication/Messages/DaqifiOutMessage.cs[337-352]
src/Daqifi.Core/Device/DeviceMetadata.cs[199-206]
src/Daqifi.Core/Device/DeviceHealth.cs[16-29]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`BattStatus` is documented as a battery percent but is accepted without range validation and cast from `uint` to `int`. This can publish nonsensical values (>100) and, for very large `uint` values, can wrap to negative due to unchecked conversion.

## Issue Context
- `DaqifiOutMessage.BattStatus` is `uint`.
- `DeviceHealth.BatteryPercent` is `int?`.
- The code treats `0` as "not reported", so the practical valid range here is typically `1..100`.

## Fix Focus Areas
- src/Daqifi.Core/Device/DeviceMetadata.cs[199-206]
- src/Daqifi.Core/Communication/Messages/DaqifiOutMessage.cs[337-352]
- src/Daqifi.Core/Device/DeviceHealth.cs[16-29]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Previous review results

Review updated until commit 44b4ff0

Results up to commit 85b0303


🐞 Bugs (0) 📘 Rule violations (0) 📎 Requirement gaps (0) 🎨 UX issues (0) 🔗 Cross-repo conflicts (0) 📜 Skill insights (0)


Action required
1. Null Health crashes status ✓ Resolved 🐞 Bug ☼ Reliability
Description
DeviceMetadata.UpdateFromProtobuf dereferences Health without ensuring it is non-null; since
DeviceMetadata.Health is publicly settable, consumers can set it to null and the next status frame
with any non-zero health field will throw NullReferenceException. This exception occurs on the main
status-message processing path (DaqifiDevice.OnStatusMessageReceived), potentially breaking status
handling for that device.
Code

src/Daqifi.Core/Device/DeviceMetadata.cs[R202-220]

+        if (message.BattStatus != 0)
+        {
+            Health.BatteryPercent = (int)message.BattStatus;
+        }
+
+        if (message.TempStatus != 0)
+        {
+            Health.BoardTemperatureCelsius = message.TempStatus;
+        }
+
+        if (message.PwrStatus != 0)
+        {
+            Health.PowerStatus = message.PwrStatus;
+        }
+
+        if (message.DeviceStatus != 0)
+        {
+            Health.DeviceStatus = message.DeviceStatus;
+        }
Relevance

⭐⭐⭐ High

Defensive null-safety on public APIs is commonly accepted (e.g., null-guarding CopyFrom and event
invocations in #319, #323).

PR-#319
PR-#323

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
Health is publicly settable (can be assigned null), yet UpdateFromProtobuf dereferences it when any
of the health fields are non-zero; this method is called for every status frame by DaqifiDevice, so
a null Health breaks the status pipeline.

src/Daqifi.Core/Device/DeviceMetadata.cs[35-46]
src/Daqifi.Core/Device/DeviceMetadata.cs[117-221]
src/Daqifi.Core/Device/DaqifiDevice.cs[1189-1207]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`DeviceMetadata.UpdateFromProtobuf` writes `Health.BatteryPercent`, `Health.BoardTemperatureCelsius`, etc. without first ensuring `Health` is non-null. Because `DeviceMetadata.Health` has a public setter, external code (or deserialization) can set it to `null`, and status processing will throw a `NullReferenceException` as soon as a non-zero health field arrives.

## Issue Context
- `DaqifiDevice.OnStatusMessageReceived` calls `Metadata.UpdateFromProtobuf(message)` for every status frame, so the null dereference is reachable during normal device operation.
- `Capabilities` has similar assumptions; consider hardening both.

## Fix Focus Areas
- src/Daqifi.Core/Device/DeviceMetadata.cs[117-221]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended
2. Health test not captured payload ✓ Resolved 📎 Requirement gap ☼ Reliability
Description
The new health telemetry test constructs a DaqifiOutMessage directly instead of using a
captured/serialized status payload, so it doesn’t verify real payload decoding/population
end-to-end. This can miss regressions in the wire-level frame/field decoding path that the
compliance item explicitly targets.
Code

src/Daqifi.Core.Tests/Device/DeviceMetadataTests.cs[R169-190]

+    [Fact]
+    public void UpdateFromProtobuf_UpdatesHealthTelemetry()
+    {
+        // Arrange
+        var metadata = new DeviceMetadata();
+        var message = new DaqifiOutMessage
+        {
+            BattStatus = 87,
+            TempStatus = 42,
+            PwrStatus = 2,
+            DeviceStatus = 5
+        };
+
+        // Act
+        metadata.UpdateFromProtobuf(message);
+
+        // Assert
+        Assert.Equal(87, metadata.Health.BatteryPercent);
+        Assert.Equal(42, metadata.Health.BoardTemperatureCelsius);
+        Assert.Equal(2u, metadata.Health.PowerStatus);
+        Assert.Equal(5u, metadata.Health.DeviceStatus);
+    }
Relevance

⭐⭐⭐ High

Team often strengthens tests with real serialized/captured protobuf frames (accepted in PRs #325,
#197).

PR-#325
PR-#197

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
PR Compliance ID 4 requires a test using a captured status payload; the added test sets
BattStatus/TempStatus/PwrStatus/DeviceStatus directly on a new DaqifiOutMessage, which
bypasses validating decoding from a captured payload.

Add test using captured status payload to assert device health telemetry decoding/population
src/Daqifi.Core.Tests/Device/DeviceMetadataTests.cs[169-190]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The device health telemetry tests do not use a captured (serialized) status payload, so they validate `UpdateFromProtobuf` only after a `DaqifiOutMessage` is already constructed.

## Issue Context
PR Compliance ID 4 requires an automated test that uses a real/captured status payload and asserts decoded/populated battery %, board temperature, power status, and device status.

## Fix Focus Areas
- src/Daqifi.Core.Tests/Device/DeviceMetadataTests.cs[169-215]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


3. Invalid battery percent accepted ✓ Resolved 🐞 Bug ≡ Correctness
Description
UpdateFromProtobuf assigns Health.BatteryPercent = (int)message.BattStatus without validating the
documented 0–100 range; out-of-contract values (e.g., 500, or very large uints) will be published to
consumers. Because BattStatus is uint, very large values can also wrap negative when cast to int
in the default unchecked context.
Code

src/Daqifi.Core/Device/DeviceMetadata.cs[R202-205]

+        if (message.BattStatus != 0)
+        {
+            Health.BatteryPercent = (int)message.BattStatus;
+        }
Relevance

⭐⭐ Medium

Range/overflow validation is mixed: accepted for some sanitization (#328) but similar cast/bounds
checks were rejected (#117).

PR-#328
PR-#117

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The protobuf field is a uint documented as a percentage; the code casts it directly to int? without
validation, so values outside 0–100 are not filtered and very large uints can wrap when cast to int.

src/Daqifi.Core/Communication/Messages/DaqifiOutMessage.cs[337-352]
src/Daqifi.Core/Device/DeviceMetadata.cs[199-206]
src/Daqifi.Core/Device/DeviceHealth.cs[16-29]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`BattStatus` is documented as a battery percent but is accepted without range validation and cast from `uint` to `int`. This can publish nonsensical values (>100) and, for very large `uint` values, can wrap to negative due to unchecked conversion.

## Issue Context
- `DaqifiOutMessage.BattStatus` is `uint`.
- `DeviceHealth.BatteryPercent` is `int?`.
- The code treats `0` as "not reported", so the practical valid range here is typically `1..100`.

## Fix Focus Areas
- src/Daqifi.Core/Device/DeviceMetadata.cs[199-206]
- src/Daqifi.Core/Communication/Messages/DaqifiOutMessage.cs[337-352]
- src/Daqifi.Core/Device/DeviceHealth.cs[16-29]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Qodo Logo

Comment thread src/Daqifi.Core.Tests/Device/DeviceMetadataTests.cs
Comment thread src/Daqifi.Core/Device/DeviceMetadata.cs Outdated
Comment thread src/Daqifi.Core/Device/DeviceMetadata.cs Outdated
…nded battery, captured-payload test

- Coerce DeviceMetadata.Health and .Capabilities setters to a fresh instance on null,
  so a consumer assigning null can't NRE the status-processing path (Qodo #1).
- Accept BattStatus only when in the documented 1..100 range; ignore out-of-range
  readings, which also avoids the uint->int wrap-to-negative for very large values (Qodo #3).
- Add a health test that serializes a status message to wire bytes and decodes it back
  through the protobuf parser (captured-payload path per #335), plus out-of-range-battery
  and null-Health tests (Qodo #2).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@tylerkron

Copy link
Copy Markdown
Contributor Author

agentic_review

@tylerkron

Copy link
Copy Markdown
Contributor Author

/agentic_review

Comment thread src/Daqifi.Core/Device/DeviceHealth.cs Outdated
@qodo-code-review

Copy link
Copy Markdown

Code review by qodo was updated up to the latest commit 0d94a63

… round 2)

BatteryPercent/BoardTemperatureCelsius docs claimed null when "the most recent
status message did not report it", but UpdateFromProtobuf intentionally preserves
the last-known reading across partial frames. Reworded to state the sticky
semantics: a value is the last one the device actually reported (may predate the
latest frame), and null means "never reported since construction".

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@tylerkron

Copy link
Copy Markdown
Contributor Author

/agentic_review

@qodo-code-review

Copy link
Copy Markdown

Code review by qodo was updated up to the latest commit 44b4ff0

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant