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.
202 lines
5.8 KiB
202 lines
5.8 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.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.HWState != nil {
|
|
hasName := false
|
|
for _, alias := range pd.Aliases {
|
|
if strings.HasPrefix(alias, "lucifer:name:") {
|
|
hasName = true
|
|
break
|
|
}
|
|
}
|
|
|
|
if !hasName {
|
|
pd.Aliases = append(pd.Aliases, "lucifer:name:"+patch.Device.HWState.InternalName)
|
|
}
|
|
if pd.Name == "" {
|
|
pd.Name = patch.Device.HWState.InternalName
|
|
}
|
|
}
|
|
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, Aliases: make([]string, 0)}
|
|
}
|
|
}
|
|
|
|
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"`
|
|
}
|