Skip to content

Navigation Menu

Sign in
Sign up

fix: return a device status from getState(), not the device itself - #1404

Open
JanzenMark wants to merge 1 commit into
OpenWonderLabs:latest from
JanzenMark:pr/getstate-returns-status
Open

fix: return a device status from getState(), not the device itself #1404
JanzenMark wants to merge 1 commit into
OpenWonderLabs:latest from
JanzenMark:pr/getstate-returns-status

Conversation

@JanzenMark

@JanzenMark JanzenMark commented Aug 19, 2026

Copy link
Copy Markdown

Fixes #1403

getState() returned the node-switchbot device instance rather than that
device's status, so every characteristic getter read a field that is not on it
and fell back to a default. HomeKit received a plausible 0, or 100% battery,
with nothing logged.

What changed

  • src/devices/genericDevice.ts — when the object from client.getDevice() can
    report status, await device.getStatus() and return that. Objects that are
    already a plain status, and { body } responses, behave as before. A device
    that reports no status falls back to the existing minimal { id, type }
    rather than the instance, since the instance looks like a state whose every
    field happens to be missing.
  • src/deviceFactory.ts — drop the getState override. It set an instance
    property that shadowed the class implementation, so fixing the class alone had
    no effect at runtime. The class already prefers the client-backed lookup.

Tests

test/device/getstate-returns-status.spec.ts covers: a status is returned
rather than the instance; plain status objects and { body } responses still
pass through; a failing or empty getStatus() yields minimal info instead of the
instance; createDevice() no longer replaces the method; and a meter reports a
real temperature through createHAPAccessory().

Full suite, lint, typecheck and build pass.

Verified on hardware

Meter Pro (CO2), values pushed to HomeKit before:

CurrentTemperature=23.7, CurrentRelativeHumidity=0, BatteryLevel=100,
StatusLowBattery=0, CarbonDioxideLevel=0

after:

CurrentTemperature=23.7, CurrentRelativeHumidity=59, BatteryLevel=100,
StatusLowBattery=0, CarbonDioxideLevel=403

Scope

Deliberately limited to the one defect. I found several adjacent issues while
tracking this down — including CO2 never being exposed for the Meter Pro (CO2),
polled values being fetched then discarded, and two node-switchbot problems —
and I would rather offer those separately than bundle them here.

Every characteristic getter reads fields off getState(), for example:
 const s = await this.getState()
 return typeof s.temperature === 'number' ? s.temperature : 0
getState() returned whatever client.getDevice() handed back, which is a
node-switchbot device instance. That instance exposes id, name, deviceType and
mac; the readings live behind await device.getStatus(). So s.temperature was
always undefined and the getter returned 0.
createDevice() then replaced the method with a delegator that returned the
client device directly:
 device.getState = async () => {
 try {
 const dev = await client.getDevice(opts.id)
 if (dev) {
 return dev
 }
 } catch (e) { /* ignore */ }
 return originalGetState()
 }
Being an instance property, that shadowed the class implementation, so even
fixing the class alone had no effect at runtime.
One getState() serves every device class in genericDevice.ts and none override
it, so this affects all readings on all devices. It fails silently: HomeKit is
handed a plausible 0, or 100 percent battery, rather than an error.
Ask the device for its status, and drop the override. A device that reports no
status falls back to the existing minimal info rather than the instance, since
the instance looks like a state whose every field is missing.
Verified on a Meter Pro (CO2). Before, every value pushed to HomeKit was a
default except one:
 CurrentTemperature=23.7, CurrentRelativeHumidity=0, BatteryLevel=100,
 CarbonDioxideLevel=0
After, each value is a measurement:
 CurrentTemperature=23.7, CurrentRelativeHumidity=59, BatteryLevel=100,
 CarbonDioxideLevel=403
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Reviewers

No reviews

Assignees

No one assigned

Labels

None yet

Projects

None yet

Milestone

No milestone

Development

Successfully merging this pull request may close these issues.

Bug: getState() returns the device object, so every reading falls back to 0

1 participant

AltStyle によって変換されたページ (->オリジナル) /