fix(iobroker): reconcile rejected vehicle/energy writes instead of leaving state looking applied - #124
Conversation
…aving state looking applied handleStateChange() in VehicleHandler/EnergyHandler used to catch and log its own write failures, so the onStateChange() caller in main.ts never saw the rejection and the object state kept showing the requested value as if it had applied. Writes now go through a writeAndReconcile() helper that acks the requested value on success and restores the last confirmed value on failure, letting the failure propagate to onStateChange() as the single place that logs it.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 7c5ccba2eb
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| * shows a requested value that was never actually applied. | ||
| */ | ||
| private async writeAndReconcile(id: string, value: any, write: () => Promise<any>): Promise<void> { | ||
| const prior = await this.adapter.getStateAsync(id); |
There was a problem hiding this comment.
Cache the confirmed state before the user overwrites it
When a user changes any directly writable state, ioBroker has already stored the incoming ack: false value before onStateChange() invokes this helper, so getStateAsync(id) returns the requested value rather than the previously acknowledged one. If setTemps, setChargeLimit, setSentryMode, or an energy operation write rejects, the catch therefore re-writes that rejected value with ack: true, still making it look applied; the identical helper in EnergyHandler has the same problem. Preserve confirmed values separately instead of reading the current state here—the new tests miss this because they invoke the handler while the fake store still contains the old value.
AGENTS.md reference: AGENTS.md:L171-L171
Useful? React with 👍 / 👎.
Intent
VehicleHandler/EnergyHandler'shandleStateChange()caught and logged their own write failures, somain.ts'sonStateChange()caller never saw the rejection - after a rejected lock/temperature/charge-limit/energy write, the ioBroker object state kept showing the requested value as if it had applied.handleStateChange()toonStateChange(), the single place that logs and reconciles - no more double logging.writeAndReconcile(id, value, write)helper (colocated in each handler): it acks the requested value on success, and on failure re-acks the last confirmed value so the state never lies about what applied.Test plan
pnpm --filter iobroker.teslemetry test- new coverage for a rejected lock command and a rejected temperature write (vehicle) and a rejected backup-reserve write (energy), each restoring the prior value and propagating exactly once with no handler-level log; plus matching successful-write ack casespnpm --filter iobroker.teslemetry check(tsc)pnpm --filter iobroker.teslemetry buildpnpm lint