package collector import ( "bytes" "encoding/json" ) // gen1Status is a superset of the optional blocks returned by Gen1 /status // endpoints. Pointers distinguish a missing capability from a valid zero value. type gen1Status struct { WiFiStation *struct { Connected bool `json:"connected"` SSID string `json:"ssid"` IP string `json:"ip"` RSSI int `json:"rssi"` } `json:"wifi_sta"` Cloud *struct { Enabled bool `json:"enabled"` Connected bool `json:"connected"` } `json:"cloud"` MQTT *struct { Connected bool `json:"connected"` } `json:"mqtt"` Serial *uint64 `json:"serial"` HasUpdate *bool `json:"has_update"` MAC string `json:"mac"` Update *struct { Status string `json:"status"` HasUpdate bool `json:"has_update"` NewVersion string `json:"new_version"` OldVersion string `json:"old_version"` } `json:"update"` RAMTotal *uint64 `json:"ram_total"` RAMFree *uint64 `json:"ram_free"` FSSize *uint64 `json:"fs_size"` FSFree *uint64 `json:"fs_free"` Uptime *float64 `json:"uptime"` Relays []gen1Relay `json:"relays"` Meters []gen1Meter `json:"meters"` EMeters []gen1EMeter `json:"emeters"` Inputs []gen1Input `json:"inputs"` Input *float64 `json:"input"` Rollers []gen1Roller `json:"rollers"` Lights []gen1Light `json:"lights"` ADCs []gen1ADC `json:"adcs"` Thermostats []gen1Thermostat `json:"thermostats"` Calibrated *bool `json:"calibrated"` Temperature *float64 `json:"temperature"` Overtemperature *bool `json:"overtemperature"` TemperatureStatus string `json:"temperature_status"` TemperatureSensor *gen1TemperatureSensor `json:"tmp"` Humidity *gen1ValueSensor `json:"hum"` Battery *gen1Battery `json:"bat"` Lux *gen1Lux `json:"lux"` Sensor *gen1MotionSensor `json:"sensor"` Acceleration *gen1Acceleration `json:"accel"` Motion *bool `json:"motion"` Charger *bool `json:"charger"` Smoke *bool `json:"smoke"` Flood *bool `json:"flood"` RainSensor *bool `json:"rain_sensor"` Valid *bool `json:"is_valid"` SensorError *float64 `json:"sensor_error"` ConnectRetries *float64 `json:"connect_retries"` ExternalTemperature map[string]gen1ExternalTemperature `json:"ext_temperature"` ExternalHumidity map[string]gen1ExternalHumidity `json:"ext_humidity"` TotalPower *float64 `json:"total_power"` FSMounted *bool `json:"fs_mounted"` GasSensor *struct { SensorState string `json:"sensor_state"` SelfTestState string `json:"self_test_state"` AlarmState string `json:"alarm_state"` } `json:"gas_sensor"` Concentration *struct { PPM *float64 `json:"ppm"` Valid *bool `json:"is_valid"` } `json:"concentration"` Valves []struct { State string `json:"state"` } `json:"valves"` } type gen1Relay struct { On *bool `json:"ison"` HasTimer *bool `json:"has_timer"` TimerDuration *float64 `json:"timer_duration"` TimerRemaining *float64 `json:"timer_remaining"` Overpower *bool `json:"overpower"` Valid *bool `json:"is_valid"` } type gen1Meter struct { Power *float64 `json:"power"` Overpower *numberOrBool `json:"overpower"` Valid *bool `json:"is_valid"` Timestamp *float64 `json:"timestamp"` Counters []float64 `json:"counters"` Total *float64 `json:"total"` } type gen1EMeter struct { Power *float64 `json:"power"` ReactivePower *float64 `json:"reactive"` PowerFactor *float64 `json:"pf"` Current *float64 `json:"current"` Voltage *float64 `json:"voltage"` Valid *bool `json:"is_valid"` Total *float64 `json:"total"` TotalReturned *float64 `json:"total_returned"` } type gen1Input struct { Input *float64 `json:"input"` Event string `json:"event"` EventCount *float64 `json:"event_cnt"` LastSequence string `json:"last_sequence"` } type gen1Roller struct { State string `json:"state"` Power *float64 `json:"power"` Valid *bool `json:"is_valid"` SafetySwitch *bool `json:"safety_switch"` Overtemperature *bool `json:"overtemperature"` StopReason string `json:"stop_reason"` LastDirection string `json:"last_direction"` CurrentPosition *float64 `json:"current_pos"` Calibrating *bool `json:"calibrating"` Positioning *bool `json:"positioning"` } type gen1Light struct { On *bool `json:"ison"` HasTimer *bool `json:"has_timer"` TimerRemaining *float64 `json:"timer_remaining"` Mode string `json:"mode"` Brightness *float64 `json:"brightness"` Red *float64 `json:"red"` Green *float64 `json:"green"` Blue *float64 `json:"blue"` White *float64 `json:"white"` Gain *float64 `json:"gain"` Temperature *float64 `json:"temp"` Effect *float64 `json:"effect"` } type gen1ADC struct { Voltage *float64 `json:"voltage"` } type gen1Thermostat struct { Position *float64 `json:"pos"` Target *struct { Enabled *bool `json:"enabled"` Value *float64 `json:"value"` Units string `json:"units"` } `json:"target_t"` Temperature *gen1TemperatureSensor `json:"tmp"` Schedule *bool `json:"schedule"` ScheduleProfile *float64 `json:"schedule_profile"` BoostMinutes *float64 `json:"boost_minutes"` WindowOpen *bool `json:"window_open"` } type gen1TemperatureSensor struct { Value *float64 `json:"value"` Units string `json:"units"` C *float64 `json:"tC"` F *float64 `json:"tF"` Valid *bool `json:"is_valid"` } type gen1ValueSensor struct { Value *float64 `json:"value"` Valid *bool `json:"is_valid"` } type gen1Battery struct { Value *float64 `json:"value"` Voltage *float64 `json:"voltage"` } type gen1Lux struct { Value *float64 `json:"value"` Illumination string `json:"illumination"` Valid *bool `json:"is_valid"` } type gen1MotionSensor struct { Motion *bool `json:"motion"` Vibration *bool `json:"vibration"` Timestamp *float64 `json:"timestamp"` Active *bool `json:"active"` Valid *bool `json:"is_valid"` State string `json:"state"` } type gen1Acceleration struct { Tilt *float64 `json:"tilt"` Vibration *float64 `json:"vibration"` VibrationTime *float64 `json:"vibration_time"` } type gen1ExternalTemperature struct { HardwareID string `json:"hwID"` C *float64 `json:"tC"` F *float64 `json:"tF"` } type gen1ExternalHumidity struct { HardwareID string `json:"hwID"` Humidity *float64 `json:"hum"` } // numberOrBool handles the inconsistent Gen1 "overpower" representation: // depending on the product it is either a threshold in watts or a boolean state. type numberOrBool struct { Number *float64 Bool *bool } func (value *numberOrBool) UnmarshalJSON(data []byte) error { data = bytes.TrimSpace(data) if bytes.Equal(data, []byte("null")) { return nil } var boolean bool if err := json.Unmarshal(data, &boolean); err == nil { value.Bool = &boolean return nil } var number float64 if err := json.Unmarshal(data, &number); err == nil { value.Number = &number return nil } // Unknown representations should not make every other metric unavailable. return nil }