원클릭으로
async-http-canonical-error-handling
Standard guard pattern for async HTTP response callbacks in Hubitat drivers
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
메뉴
Standard guard pattern for async HTTP response callbacks in Hubitat drivers
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
SOC 직업 분류 기준
Pattern for keeping a rolling temperature-trend sample buffer in Hubitat state, computing slope over a configurable window, and classifying rising/falling/steady/unknown.
Implement Tuya Local v3.3 Groovy drivers on Hubitat using rawSocket, AES-128-ECB, queued retries, and defensive frame parsing.
Use Hubitat async HTTP plus a request queue to authenticate with Cognito, cache tokens in state, refresh proactively, and replay a single 401-failed request.
When two agents produce overlapping skills in one session, consolidate by merging unique content into the highest-confidence existing skill.
Never let cached-state dedup bypass session validity in cloud-backed Hubitat drivers.
Correct formula for converting lat/lng degree differences to miles, with pole clamp for numerical stability
| name | Async HTTP Canonical Error Handling |
| description | Standard guard pattern for async HTTP response callbacks in Hubitat drivers |
| domain | error-handling, http, async |
| confidence | high |
| source | validated in PurpleAir v0.4.0 production release (commit 2d62b05) |
Async HTTP callbacks in Hubitat can fail silently if response handling is incomplete. The standard pattern guards against three categories of errors:
Missing any guard can crash the driver or leave it in an inconsistent state.
void parseHttpResponse(resp) {
// Guard 1: Null response (network/timeout failure)
if (!resp) {
log.warn "No response from API — scheduling retry"
scheduleRetry()
return
}
// Guard 2: HTTP error status
if (resp.hasError()) {
log.warn "HTTP ${resp.getStatus()}: ${resp.getErrorMessage()}"
// Note: if disabled, respect the "don't reschedule" directive
if (settings.updateInterval != "0") {
scheduleRetry()
}
return
}
// Guard 3: JSON parse — empty body or malformed JSON
String body = resp?.getData()?.trim()
if (!body) {
log.warn "Empty response body — no data to parse"
return // Don't retry on empty body (likely a transient condition)
}
try {
def json = parseJson(body)
// ... process json ...
} catch (e) {
log.warn "JSON parse failed: ${e.message}"
return
}
}
When polling is disabled (update interval = "0"), do NOT reschedule even on error:
void scheduleRetry() {
Integer intervalMinutes = settings.updateInterval?.toString()?.isNumber() ?
settings.updateInterval.toString().toInteger() : 60
// Key: respect disabled state even on error paths
if (intervalMinutes != 0) {
Integer backoffSeconds = calculateBackoff()
runIn(backoffSeconds, "refresh")
}
}
Applied in PurpleAir AQI v0.4.0 (commit 2d62b05):
httpResponse() handler checks !resp before accessing resp methodshasError() branch guards HTTP status codes and logs diagnostic statusparseJson() wrapped in try/catch after ?.trim() guardsscheduleRetry() respects disabled polling setting (update_interval == "0")See drivers/purpleair-aqi/purpleair-aqi.groovy lines 160–210 (v0.4.0).
❌ No null-response guard:
def json = parseJson(resp.getData()) // NPE if resp is null
❌ No hasError() check:
def json = parseJson(resp.getData()) // Ignores HTTP 500 errors
❌ No empty-body guard:
parseJson("") // Crashes with JSONException on empty string
❌ Unconditional retry on disabled polling:
if (resp.hasError()) {
runIn(60, "refresh") // Violates disabled-state contract
}
A single guard omission can turn a minor network hiccup into a cascade: driver crashes, manual hub restart required, retry storm if disabled state is ignored.