2020-12-22 18:24:23 +01:00
|
|
|
package hue
|
|
|
|
|
|
|
|
import (
|
2020-12-28 17:29:44 +01:00
|
|
|
"encoding/json"
|
2020-12-22 18:24:23 +01:00
|
|
|
"fmt"
|
2020-12-28 17:29:44 +01:00
|
|
|
"io/ioutil"
|
2020-12-22 18:24:23 +01:00
|
|
|
|
|
|
|
"github.com/aexel90/hue_exporter/metric"
|
2020-12-28 17:29:44 +01:00
|
|
|
hueAPI "github.com/amimof/huego"
|
2020-12-22 18:24:23 +01:00
|
|
|
)
|
|
|
|
|
|
|
|
// Exporter data
|
|
|
|
type Exporter struct {
|
|
|
|
BaseURL string
|
|
|
|
Username string
|
|
|
|
}
|
|
|
|
|
2020-12-28 17:29:44 +01:00
|
|
|
type collectEntry struct {
|
|
|
|
Type string `json:"type"`
|
|
|
|
Result map[string]interface{} `json:"result"`
|
|
|
|
}
|
|
|
|
|
2020-12-22 18:24:23 +01:00
|
|
|
const (
|
2020-12-29 14:10:47 +01:00
|
|
|
typeLight = "light"
|
|
|
|
typeSensor = "sensor"
|
2020-12-29 14:24:09 +01:00
|
|
|
typeBridge = "bridge"
|
2020-12-29 14:10:47 +01:00
|
|
|
|
|
|
|
labelName = "name"
|
|
|
|
labelType = "type"
|
|
|
|
labelID = "id"
|
|
|
|
labelModelID = "model_id"
|
|
|
|
labelManufacturerName = "manufacturer_name"
|
|
|
|
labelSwVersion = "sw_version"
|
|
|
|
labelSwConfigID = "sw_config_id"
|
|
|
|
labelUniqueID = "unique_id"
|
|
|
|
|
|
|
|
labelStateOn = "state_on"
|
|
|
|
labelStateAlert = "state_alert"
|
|
|
|
labelStateBri = "state_bri"
|
|
|
|
labelStateColorMode = "state_color_mode"
|
|
|
|
labelStateCT = "state_ct"
|
|
|
|
labelStateReachable = "state_reachable"
|
|
|
|
labelStateSaturation = "state_saturation"
|
|
|
|
labelStateButtonEvent = "state_buttonevent"
|
|
|
|
labelStateDaylight = "state_daylight"
|
|
|
|
labelStateLastUpdated = "state_lastupdated"
|
|
|
|
labelStateTemperature = "state_temperature"
|
|
|
|
labelStateLightLevel = "state_lightlevel"
|
|
|
|
|
|
|
|
labelConfigBattery = "config_battery"
|
|
|
|
labelConfigOn = "config_on"
|
|
|
|
labelConfigReachable = "config_reachable"
|
|
|
|
|
|
|
|
labelAPIVersion = "api_version"
|
|
|
|
labelBridgeID = "bridge_id"
|
|
|
|
labelIPAddress = "ip_address"
|
|
|
|
labelInternetServiceInternet = "internetservice_internet"
|
|
|
|
labelInternetServiceRemoteAccess = "internetservice_remoteaccess"
|
|
|
|
labelInternetServiceSwUpdate = "internetservice_swupdate"
|
|
|
|
labelInternetServiceTime = "internetservice_time"
|
|
|
|
labelLocalTime = "local_time"
|
|
|
|
labelSwUpdate2LastChange = "sw_update_last_change"
|
|
|
|
labelZigbeeChannel = "zigbee_channel"
|
2020-12-22 18:24:23 +01:00
|
|
|
)
|
|
|
|
|
2020-12-28 17:29:44 +01:00
|
|
|
// CollectAll available hue metrics
|
|
|
|
func CollectAll(url string, username string, fileName string) {
|
|
|
|
|
|
|
|
bridge := hueAPI.New(url, username)
|
|
|
|
|
|
|
|
jsonContent := []collectEntry{}
|
2020-12-22 18:24:23 +01:00
|
|
|
|
2020-12-28 17:29:44 +01:00
|
|
|
sensorData, err := collectSensors(bridge)
|
|
|
|
if err != nil {
|
|
|
|
fmt.Sprintln(err)
|
|
|
|
return
|
|
|
|
}
|
2020-12-22 18:24:23 +01:00
|
|
|
|
2020-12-28 17:29:44 +01:00
|
|
|
lightData, err := collectLights(bridge)
|
2020-12-22 18:24:23 +01:00
|
|
|
if err != nil {
|
2020-12-28 17:29:44 +01:00
|
|
|
fmt.Sprintln(err)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2020-12-29 14:10:47 +01:00
|
|
|
bridgeData, err := collectBridgeInfo(bridge)
|
|
|
|
if err != nil {
|
|
|
|
fmt.Sprintln(err)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2020-12-28 17:29:44 +01:00
|
|
|
for _, sensor := range sensorData {
|
2020-12-29 14:10:47 +01:00
|
|
|
jsonContent = append(jsonContent, collectEntry{Type: "sensor", Result: sensor})
|
2020-12-28 17:29:44 +01:00
|
|
|
}
|
|
|
|
for _, light := range lightData {
|
2020-12-29 14:10:47 +01:00
|
|
|
jsonContent = append(jsonContent, collectEntry{Type: "light", Result: light})
|
|
|
|
}
|
|
|
|
for _, bridge := range bridgeData {
|
|
|
|
jsonContent = append(jsonContent, collectEntry{Type: "bridge", Result: bridge})
|
2020-12-22 18:24:23 +01:00
|
|
|
}
|
|
|
|
|
2020-12-28 17:29:44 +01:00
|
|
|
jsonString, err := json.MarshalIndent(jsonContent, "", "\t")
|
|
|
|
if err != nil {
|
|
|
|
fmt.Println(err)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
fmt.Println(string(jsonString))
|
|
|
|
if fileName != "" {
|
|
|
|
err = ioutil.WriteFile(fileName, jsonString, 0644)
|
|
|
|
if err != nil {
|
|
|
|
fmt.Printf("Failed writing JSON file '%s': %s\n", fileName, err.Error())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Collect metrics
|
|
|
|
func (exporter *Exporter) Collect(metrics []*metric.Metric) (err error) {
|
|
|
|
|
|
|
|
bridge := hueAPI.New(exporter.BaseURL, exporter.Username)
|
|
|
|
|
2020-12-28 08:49:18 +01:00
|
|
|
sensorData, err := collectSensors(bridge)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2020-12-22 18:24:23 +01:00
|
|
|
|
2020-12-28 08:49:18 +01:00
|
|
|
lightData, err := collectLights(bridge)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2020-12-22 18:24:23 +01:00
|
|
|
|
2020-12-29 14:24:09 +01:00
|
|
|
bridgeData, err := collectBridgeInfo(bridge)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2020-12-28 08:49:18 +01:00
|
|
|
for _, metric := range metrics {
|
2020-12-22 18:24:23 +01:00
|
|
|
switch metric.HueType {
|
2020-12-29 14:10:47 +01:00
|
|
|
case typeLight:
|
2020-12-28 08:49:18 +01:00
|
|
|
metric.MetricResult = lightData
|
2020-12-29 14:10:47 +01:00
|
|
|
case typeSensor:
|
2020-12-28 08:49:18 +01:00
|
|
|
metric.MetricResult = sensorData
|
2020-12-29 14:24:09 +01:00
|
|
|
case typeBridge:
|
|
|
|
metric.MetricResult = bridgeData
|
2020-12-29 14:10:47 +01:00
|
|
|
default:
|
|
|
|
return fmt.Errorf("Type '%v' currently not supported", metric.HueType)
|
2020-12-22 18:24:23 +01:00
|
|
|
}
|
2020-12-29 14:10:47 +01:00
|
|
|
|
2020-12-22 18:24:23 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2020-12-28 17:29:44 +01:00
|
|
|
func collectSensors(bridge *hueAPI.Bridge) (sensorData []map[string]interface{}, err error) {
|
2020-12-27 14:58:21 +01:00
|
|
|
|
2020-12-28 17:29:44 +01:00
|
|
|
sensors, err := bridge.GetSensors()
|
2020-12-27 14:58:21 +01:00
|
|
|
if err != nil {
|
2020-12-29 14:10:47 +01:00
|
|
|
return nil, fmt.Errorf("[GetAllSensors()] '%v'", err)
|
2020-12-27 14:58:21 +01:00
|
|
|
}
|
|
|
|
for _, sensor := range sensors {
|
|
|
|
result := make(map[string]interface{})
|
2020-12-29 14:10:47 +01:00
|
|
|
result[labelName] = sensor.Name
|
|
|
|
result[labelID] = sensor.ID
|
|
|
|
result[labelType] = sensor.Type
|
|
|
|
result[labelModelID] = sensor.ModelID
|
|
|
|
result[labelManufacturerName] = sensor.ManufacturerName
|
|
|
|
result[labelSwVersion] = sensor.SwVersion
|
|
|
|
result[labelUniqueID] = sensor.UniqueID
|
2020-12-28 17:29:44 +01:00
|
|
|
|
|
|
|
//State
|
|
|
|
for stateKey, stateValue := range sensor.State {
|
|
|
|
result["state_"+stateKey] = stateValue
|
|
|
|
}
|
|
|
|
|
|
|
|
//Config
|
|
|
|
for stateKey, stateValue := range sensor.Config {
|
|
|
|
result["config_"+stateKey] = stateValue
|
2020-12-27 14:58:21 +01:00
|
|
|
}
|
|
|
|
|
2020-12-28 08:49:18 +01:00
|
|
|
sensorData = append(sensorData, result)
|
2020-12-27 14:58:21 +01:00
|
|
|
}
|
2020-12-28 08:49:18 +01:00
|
|
|
return sensorData, nil
|
2020-12-27 14:58:21 +01:00
|
|
|
}
|
|
|
|
|
2020-12-28 17:29:44 +01:00
|
|
|
func collectLights(bridge *hueAPI.Bridge) (lightData []map[string]interface{}, err error) {
|
2020-12-22 18:24:23 +01:00
|
|
|
|
2020-12-28 17:29:44 +01:00
|
|
|
lights, err := bridge.GetLights()
|
2020-12-22 18:24:23 +01:00
|
|
|
if err != nil {
|
2020-12-29 14:10:47 +01:00
|
|
|
return nil, fmt.Errorf("[GetAllLights()] '%v'", err)
|
2020-12-22 18:24:23 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
for _, light := range lights {
|
|
|
|
|
|
|
|
result := make(map[string]interface{})
|
2020-12-29 14:10:47 +01:00
|
|
|
result[labelName] = light.Name
|
|
|
|
result[labelID] = light.ID
|
|
|
|
result[labelType] = light.Type
|
|
|
|
result[labelModelID] = light.ModelID
|
|
|
|
result[labelManufacturerName] = light.ManufacturerName
|
|
|
|
result[labelSwVersion] = light.SwVersion
|
|
|
|
result[labelSwConfigID] = light.SwConfigID
|
|
|
|
result[labelUniqueID] = light.UniqueID
|
2020-12-28 17:29:44 +01:00
|
|
|
|
|
|
|
// State
|
2020-12-29 14:10:47 +01:00
|
|
|
result[labelStateOn] = light.State.On
|
|
|
|
result[labelStateAlert] = light.State.Alert
|
|
|
|
result[labelStateBri] = light.State.Bri
|
|
|
|
result[labelStateColorMode] = light.State.ColorMode
|
|
|
|
result[labelStateCT] = light.State.Ct
|
|
|
|
result[labelStateReachable] = light.State.Reachable
|
|
|
|
result[labelStateSaturation] = light.State.Sat
|
2020-12-28 08:49:18 +01:00
|
|
|
|
|
|
|
lightData = append(lightData, result)
|
2020-12-22 18:24:23 +01:00
|
|
|
}
|
2020-12-28 08:49:18 +01:00
|
|
|
return lightData, nil
|
2020-12-22 18:24:23 +01:00
|
|
|
}
|
2020-12-29 14:10:47 +01:00
|
|
|
|
|
|
|
func collectBridgeInfo(bridge *hueAPI.Bridge) (bridgeData []map[string]interface{}, err error) {
|
|
|
|
|
|
|
|
config, err := bridge.GetConfig()
|
|
|
|
if err != nil {
|
|
|
|
return nil, fmt.Errorf("[GetConfig] '%v'", err)
|
|
|
|
}
|
|
|
|
result := make(map[string]interface{})
|
|
|
|
result[labelName] = config.Name
|
|
|
|
result[labelAPIVersion] = config.APIVersion
|
|
|
|
result[labelBridgeID] = config.BridgeID
|
|
|
|
result[labelIPAddress] = config.IPAddress
|
|
|
|
result[labelInternetServiceInternet] = config.InternetService.Internet
|
|
|
|
result[labelInternetServiceRemoteAccess] = config.InternetService.RemoteAccess
|
|
|
|
result[labelInternetServiceSwUpdate] = config.InternetService.SwUpdate
|
|
|
|
result[labelInternetServiceTime] = config.InternetService.Time
|
|
|
|
result[labelLocalTime] = config.LocalTime
|
|
|
|
result[labelModelID] = config.ModelID
|
|
|
|
result[labelSwVersion] = config.SwVersion
|
|
|
|
result[labelSwUpdate2LastChange] = config.SwUpdate2.LastChange
|
|
|
|
result[labelZigbeeChannel] = config.ZigbeeChannel
|
|
|
|
|
|
|
|
bridgeData = append(bridgeData, result)
|
|
|
|
return bridgeData, nil
|
|
|
|
}
|