You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

280 lines
7.3 KiB

package hue2
import (
"encoding/json"
"encoding/xml"
"fmt"
"git.aiterp.net/lucifer/new-server/internal/color"
"strings"
"time"
)
type DeviceData struct {
ID string `json:"id"`
LegacyID string `json:"id_v1"`
Metadata DeviceMetadata `json:"metadata"`
Type string `json:"type"`
ProductData DeviceProductData `json:"product_data"`
Services []ResourceLink `json:"services"`
}
type DeviceMetadata struct {
Archetype string `json:"archetype"`
Name string `json:"name"`
}
type DeviceProductData struct {
Certified bool `json:"certified"`
ManufacturerName string `json:"manufacturer_name"`
ModelID string `json:"model_id"`
ProductArchetype string `json:"product_archetype"`
ProductName string `json:"product_name"`
SoftwareVersion string `json:"software_version"`
}
type SSEUpdate struct {
CreationTime time.Time `json:"creationTime"`
ID string `json:"id"`
Type string `json:"type"`
Data []ResourceData `json:"data"`
}
type ResourceData struct {
ID string `json:"id"`
LegacyID string `json:"id_v1"`
Metadata DeviceMetadata `json:"metadata"`
Type string `json:"type"`
Mode *string `json:"mode"`
Owner *ResourceLink `json:"owner"`
ProductData *DeviceProductData `json:"product_data"`
Services []ResourceLink `json:"services"`
Button *SensorButton `json:"button"`
Power *LightPower `json:"on"`
Color *LightColor `json:"color"`
ColorTemperature *LightCT `json:"color_temperature"`
Dimming *LightDimming `json:"dimming"`
Dynamics *LightDynamics `json:"dynamics"`
Alert *LightAlert `json:"alert"`
PowerState *PowerState `json:"power_state"`
Temperature *SensorTemperature `json:"temperature"`
Motion *SensorMotion `json:"motion"`
Status *string `json:"status"`
}
func (res *ResourceData) ServiceID(kind string) *string {
for _, ptr := range res.Services {
if ptr.Kind == kind {
return &ptr.ID
}
}
return nil
}
func (res *ResourceData) ServiceIndex(kind string, id string) int {
idx := 0
for _, link := range res.Services {
if link.ID == id {
return idx
} else if link.Kind == kind {
idx += 1
}
}
return -1
}
func (res *ResourceData) WithUpdate(update ResourceUpdate) *ResourceData {
resCopy := *res
if update.Name != nil {
resCopy.Metadata.Name = *update.Name
}
if update.Power != nil {
cp := *resCopy.Power
resCopy.Power = &cp
resCopy.Power.On = *update.Power
}
if update.ColorXY != nil {
cp := *resCopy.Color
resCopy.Color = &cp
resCopy.Color.XY = *update.ColorXY
if resCopy.ColorTemperature != nil {
cp := *resCopy.ColorTemperature
resCopy.ColorTemperature = &cp
resCopy.ColorTemperature.Mirek = nil
}
}
if update.Mirek != nil {
cp := *resCopy.ColorTemperature
resCopy.ColorTemperature = &cp
mirek := *update.Mirek
resCopy.ColorTemperature.Mirek = &mirek
}
if update.Brightness != nil {
cp := *resCopy.Dimming
resCopy.Dimming = &cp
resCopy.Dimming.Brightness = *update.Brightness
}
return &resCopy
}
type SensorButton struct {
LastEvent string `json:"last_event"`
}
type SensorMotion struct {
Motion bool `json:"motion"`
Valid bool `json:"motion_valid"`
}
type SensorTemperature struct {
Temperature float64 `json:"temperature"`
Valid bool `json:"temperature_valid"`
}
type PowerState struct {
BatteryState string `json:"battery_state"`
BatteryLevel float64 `json:"battery_level"`
}
type LightPower struct {
On bool `json:"on"`
}
type LightDimming struct {
Brightness float64 `json:"brightness"`
}
type LightColor struct {
Gamut color.Gamut `json:"gamut"`
GamutType string `json:"gamut_type"`
XY color.XY `json:"xy"`
}
type LightCT struct {
Mirek *int `json:"mirek"`
MirekSchema LightCTMirekSchema `json:"mirek_schema"`
MirekValid bool `json:"mirek_valid"`
}
type LightCTMirekSchema struct {
MirekMaximum int `json:"mirek_maximum"`
MirekMinimum int `json:"mirek_minimum"`
}
type LightDynamics struct {
Speed float64 `json:"speed"`
SpeedValid bool `json:"speed_valid"`
Status string `json:"status"`
StatusValues []string `json:"status_values"`
}
type LightAlert struct {
ActionValues []string `json:"action_values"`
}
type ResourceUpdate struct {
Name *string
Power *bool
ColorXY *color.XY
Brightness *float64
Mirek *int
TransitionDuration *time.Duration
}
func (r ResourceUpdate) MarshalJSON() ([]byte, error) {
chunks := make([]string, 0, 4)
if r.Name != nil {
s, _ := json.Marshal(*r.Name)
chunks = append(chunks, fmt.Sprintf(`"metadata":{"name":%s}`, string(s)))
}
if r.Power != nil {
chunks = append(chunks, fmt.Sprintf(`"on":{"on":%v}`, *r.Power))
}
if r.ColorXY != nil {
chunks = append(chunks, fmt.Sprintf(`"color":{"xy":{"x":%f,"y":%f}}`, r.ColorXY.X, r.ColorXY.Y))
}
if r.Brightness != nil {
chunks = append(chunks, fmt.Sprintf(`"dimming":{"brightness":%f}`, *r.Brightness))
}
if r.Mirek != nil {
chunks = append(chunks, fmt.Sprintf(`"color_temperature":{"mirek":%d}`, *r.Mirek))
}
if r.TransitionDuration != nil {
chunks = append(chunks, fmt.Sprintf(`"dynamics":{"duration":%d}`, r.TransitionDuration.Truncate(time.Millisecond*100).Milliseconds()))
}
return []byte(fmt.Sprintf("{%s}", strings.Join(chunks, ","))), nil
}
type ResourceLink struct {
ID string `json:"rid"`
Kind string `json:"rtype"`
}
func (rl *ResourceLink) Path() string {
return fmt.Sprintf("/clip/v2/resource/%s/%s", rl.Kind, rl.ID)
}
type CreateUserInput struct {
DeviceType string `json:"devicetype"`
}
type CreateUserResponse struct {
Success *struct {
Username string `json:"username"`
} `json:"success"`
Error *struct {
Type int `json:"type"`
Address string `json:"address"`
Description string `json:"description"`
} `json:"error"`
}
type DiscoveryEntry struct {
Id string `json:"id"`
InternalIPAddress string `json:"internalipaddress"`
}
type BridgeDeviceInfo struct {
XMLName xml.Name `xml:"root"`
Text string `xml:",chardata"`
Xmlns string `xml:"xmlns,attr"`
SpecVersion struct {
Text string `xml:",chardata"`
Major string `xml:"major"`
Minor string `xml:"minor"`
} `xml:"specVersion"`
URLBase string `xml:"URLBase"`
Device struct {
Text string `xml:",chardata"`
DeviceType string `xml:"deviceType"`
FriendlyName string `xml:"friendlyName"`
Manufacturer string `xml:"manufacturer"`
ManufacturerURL string `xml:"manufacturerURL"`
ModelDescription string `xml:"modelDescription"`
ModelName string `xml:"modelName"`
ModelNumber string `xml:"modelNumber"`
ModelURL string `xml:"modelURL"`
SerialNumber string `xml:"serialNumber"`
UDN string `xml:"UDN"`
PresentationURL string `xml:"presentationURL"`
IconList struct {
Text string `xml:",chardata"`
Icon struct {
Text string `xml:",chardata"`
Mimetype string `xml:"mimetype"`
Height string `xml:"height"`
Width string `xml:"width"`
Depth string `xml:"depth"`
URL string `xml:"url"`
} `xml:"icon"`
} `xml:"iconList"`
} `xml:"device"`
}