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.
 
 
 
 
 
 

187 lines
5.4 KiB

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"`
Triggers map[uuid.UUID]script.Trigger `json:"triggers"`
}
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 {
if len(patch.Script.Lines) > 0 {
newData.Scripts[patch.Script.Name] = patch.Script.Lines
} else {
delete(newData.Scripts, patch.Script.Name)
}
}
if patch.Trigger != nil {
if !patch.Trigger.Delete {
newData.Triggers[patch.Trigger.ID] = patch.Trigger.Trigger
} else {
delete(newData.Triggers, patch.Trigger.ID)
}
}
}
return newData
}
func (d *Data) Copy() Data {
return Data{
Devices: gentools.CopyMap(d.Devices),
Assignments: gentools.CopyMap(d.Assignments),
Scripts: gentools.CopyMap(d.Scripts),
Triggers: gentools.CopyMap(d.Triggers),
}
}
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"`
}