package uistate import ( "git.aiterp.net/lucifer3/server/device" "git.aiterp.net/lucifer3/server/effects" "git.aiterp.net/lucifer3/server/events" "git.aiterp.net/lucifer3/server/internal/color" "git.aiterp.net/lucifer3/server/internal/gentools" "git.aiterp.net/lucifer3/server/services/script" "github.com/google/uuid" "strings" ) type Data struct { Devices map[string]Device `json:"devices"` Assignments map[uuid.UUID]Assignment `json:"assignments"` Scripts map[string][]script.Line `json:"scripts"` } func (d *Data) WithPatch(patches ...Patch) Data { newData := d.Copy() for _, patch := range patches { if patch.Device != nil { pd := d.ensureDevice(patch.Device.ID) gentools.ApplyUpdate(&pd.Name, patch.Device.Name) gentools.ApplyUpdatePtr(&pd.HWState, patch.Device.HWState) gentools.ApplyUpdatePtr(&pd.HWMetadata, patch.Device.HWMetadata) gentools.ApplyUpdatePtr(&pd.DesiredState, patch.Device.DesiredState) gentools.ApplyUpdatePtr(&pd.Assignment, patch.Device.Assignment) gentools.ApplyUpdatePtr(&pd.ActiveColorRGB, patch.Device.ActiveColorRGB) gentools.ApplyUpdatePtr(&pd.DesiredColorRGB, patch.Device.DesiredColorRGB) if patch.Device.AddAlias != nil { ptr := device.Pointer{ID: "dummy", Aliases: pd.Aliases} ptr.AddAlias(*patch.Device.AddAlias) if strings.HasPrefix(*patch.Device.AddAlias, "lucifer:name:") { pd.Name = (*patch.Device.AddAlias)[len("lucifer:name:"):] } if strings.HasPrefix(*patch.Device.AddAlias, "lucifer:icon:") { pd.Icon = (*patch.Device.AddAlias)[len("lucifer:icon:"):] } pd.Aliases = ptr.Aliases } if patch.Device.RemoveAlias != nil { for i, alias := range pd.Aliases { if alias == *patch.Device.RemoveAlias { pd.Aliases = append(pd.Aliases[:i], pd.Aliases[i+1:]...) } } } if patch.Device.HWMetadata != nil { hasIconAlias := false for _, a := range pd.Aliases { if strings.HasPrefix(a, "lucifer:icon") { hasIconAlias = true break } } if !hasIconAlias { pd.Icon = patch.Device.HWMetadata.Icon } } if patch.Device.ClearAssignment { pd.Assignment = nil } if patch.Device.ClearActiveColorRGB { pd.ActiveColorRGB = nil } if patch.Device.Sensors != nil { if patch.Device.Sensors.LastMotion != nil { pd.Sensors.LastMotion = gentools.ShallowCopy(patch.Device.Sensors.LastMotion) } if patch.Device.Sensors.Temperature != nil { pd.Sensors.Temperature = gentools.ShallowCopy(patch.Device.Sensors.Temperature) } } if patch.Device.Delete { delete(newData.Devices, pd.ID) } else { newData.Devices[pd.ID] = pd } } if patch.Assignment != nil { pa := d.ensureAssignment(patch.Assignment.ID) gentools.ApplyUpdatePtr(&pa.Effect, patch.Assignment.Effect) if patch.Assignment.AddDeviceID != nil { pa.DeviceIDs = append(pa.DeviceIDs[:0:0], pa.DeviceIDs...) pa.DeviceIDs = append(pa.DeviceIDs, *patch.Assignment.AddDeviceID) } if patch.Assignment.RemoveDeviceID != nil { for i, id := range pa.DeviceIDs { if id == *patch.Assignment.RemoveDeviceID { pa.DeviceIDs = append(pa.DeviceIDs[:0:0], pa.DeviceIDs...) pa.DeviceIDs[i] = "" break } } } if patch.Assignment.Variables != nil { pa.Variables = gentools.CopyMap(patch.Assignment.Variables) } if patch.Assignment.Delete { delete(newData.Assignments, pa.ID) } else { newData.Assignments[pa.ID] = pa } } if patch.Script != nil { newData.Scripts[patch.Script.Name] = patch.Script.Lines } } return newData } func (d *Data) Copy() Data { return Data{ Devices: gentools.CopyMap(d.Devices), Assignments: gentools.CopyMap(d.Assignments), Scripts: gentools.CopyMap(d.Scripts), } } func (d *Data) ensureDevice(id string) Device { if device, ok := d.Devices[id]; ok { return device } else { return Device{ID: id} } } func (d *Data) ensureAssignment(id uuid.UUID) Assignment { if assignment, ok := d.Assignments[id]; ok { return assignment } else { return Assignment{ID: id} } } type Device struct { ID string `json:"id"` Name string `json:"name"` HWMetadata *events.HardwareMetadata `json:"hwMetadata"` HWState *events.HardwareState `json:"hwState"` DesiredColorRGB *color.RGB `json:"desiredColorRgb"` ActiveColorRGB *color.RGB `json:"activeColorRgb"` DesiredState *device.State `json:"desiredState"` Aliases []string `json:"aliases"` Assignment *uuid.UUID `json:"assignment"` Sensors DeviceSensors `json:"sensors"` Icon string `json:"icon"` } type DeviceSensors struct { LastMotion *float64 `json:"lastMotion,omitempty"` Temperature *float64 `json:"temperature,omitempty"` } type Assignment struct { ID uuid.UUID `json:"id"` DeviceIDs []string `json:"deviceIds"` Effect *effects.Serializable `json:"effect"` Variables map[string]float64 `json:"variables"` }