Context for developing and debugging Hubitat Elevation apps, drivers, and hub environment — sandbox constraints, lifecycle idioms, capability contracts, plus grounded deploy/log-tail/lint mechanisms.
74
93%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
View guide
Low
Low-risk findings worth noting
Hubitat has two distinct persistence mechanisms. Choosing the wrong one is a design bug that surfaces later as "my automation never fires" or "my data vanished".
sendEvent(name: "switch", value: "on", descriptionText: "${device.displayName} switch is on").isStateChange: true. type is "physical" (user acted on the device) or "digital" (hub commanded it).createEvent(...) builds an event map without sending — used when returning events from parse().currentState(attr).date dates the last change to the value, never the last report from the source. A healthy source reporting a steady value emits nothing and is indistinguishable from a dead one.temperature, humidity, thermostatOperatingState). Its staleness measures the world's volatility, not the path's health. Raising the threshold trades detection window against false alerts; no threshold makes the wrong signal right.thermostatTime, runtimeUpdated, sensorsUpdated). Strongest form: stamp your own clock on each verified read, monotonic by construction.lastPoll whose value is a constant string like Succeeded is change-filtered like any value, and goes arbitrarily stale on a healthy integration.isStateChange: true is the writer-side counterpart: set it when a consumer must see every report, not only changes.GET /device/eventsJson/<deviceId> (skills/_reference/endpoints.md) is how you measure an attribute's real gap distribution before trusting it.GET /device/fullJson/<id> and are easy to read backwards: Groovy state is top-level deviceState, attributes are nested device.currentStates (skills/_reference/endpoints.md).currentStates[attr].date in that payload is this trap made concrete — it sits beside value, reads like a freshness stamp, and is the last change, not the last report.0xFF, and drivers flatten it into the same battery attribute the percentage uses.[BatteryCCReport] level: N via skills/_scripts/hub_radiolog.py --ip <addr> --radio zwave.BatteryCCGet on wake and the report lands within ~200 ms.state is a Map-like store for the app/driver's own data between wakes, serialized to/from JSON. state.foo = "bar".DeviceWrapper, a closure, or other live objects in state breaks — keep device references out of state.state writes just before the instance sleeps. atomicState commits immediately — use it only when overlapping executions can race, and prefer singleThreaded: true in definition as the cheaper alternative.state is serialized every execution; don't store large blobs there.sendEvent.state.