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/variables" "github.com/google/uuid" ) type Data struct { Devices map[string]Device `json:"devices"` Assignments map[uuid.UUID]Assignment `json:"assignments"` Variables variables.Variables `json:"variables"` } 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.ApplyUpdateSlice(&pd.Aliases, patch.Device.SetAliases) 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) if patch.Device.AddAlias != nil { pd.Aliases = append(pd.Aliases[:0:0], pd.Aliases...) pd.Aliases = append(pd.Aliases, *patch.Device.AddAlias) } if patch.Device.RemoveAlias != nil { for i, alias := range pd.Aliases { if alias == *patch.Device.RemoveAlias { pd.Aliases = append(pd.Aliases[:0:0], pd.Aliases...) pd.Aliases = append(pd.Aliases[:i], pd.Aliases[i+1:]...) break } } } 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.Delete { delete(newData.Assignments, pa.ID) } else { newData.Assignments[pa.ID] = pa } } if patch.VariableProperty != nil { newData.Variables = newData.Variables.WithPropertyPatch(*patch.VariableProperty) } } return newData } func (d *Data) Copy() Data { return Data{ Devices: gentools.CopyMap(d.Devices), Assignments: gentools.CopyMap(d.Assignments), Variables: d.Variables, } } 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"` ActiveColorRGB *color.RGB `json:"activeColorRgb"` DesiredState *device.State `json:"desiredState"` Aliases []string `json:"aliases"` Assignment *uuid.UUID `json:"assignment"` Sensors DeviceSensors `json:"sensors"` } 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"` }