some more stuffs.

This commit is contained in:
2023-09-06 18:00:18 +02:00
parent 64bb737569
commit 07c9398414
23 changed files with 337 additions and 234 deletions
+50 -58
View File
@@ -443,68 +443,60 @@ func (b *Bridge) makeCongruentLoop(ctx context.Context) {
continue
}
// Handle power first
if desired.Power != nil && active.Power != nil && *desired.Power != *active.Power {
updates["light/"+*lightID] = ResourceUpdate{
Power: gentools.Ptr(*desired.Power),
TransitionDuration: gentools.Ptr(time.Millisecond * 101),
}
newActiveState := activeStates[id]
newActiveState.Power = gentools.Ptr(*desired.Power)
continue
}
if active.Power != nil && !*active.Power {
// Don't do more with shut-off-light.
continue
}
updated := false
update := ResourceUpdate{}
if active.Color != nil && desired.Color != nil {
ac := *active.Color
dc := *desired.Color
if !dc.IsKelvin() || !colorFlags[id].IsWarmWhite() {
dc, _ = dc.ToXY()
dc.XY = gentools.Ptr(light.Color.Gamut.Conform(*dc.XY))
}
if dc.XY != nil {
if ac.K != nil {
ac.K = gentools.Ptr(1000000 / (1000000 / *ac.K))
}
acXY, _ := ac.ToXY()
dist := dc.XY.DistanceTo(*acXY.XY)
if dist > 0.0002 {
update.ColorXY = gentools.Ptr(*dc.XY)
updated = true
}
} else {
dcMirek := 1000000 / *dc.K
if dcMirek < light.ColorTemperature.MirekSchema.MirekMinimum {
dcMirek = light.ColorTemperature.MirekSchema.MirekMinimum
} else if dcMirek > light.ColorTemperature.MirekSchema.MirekMaximum {
dcMirek = light.ColorTemperature.MirekSchema.MirekMaximum
}
acMirek := 0
if ac.K != nil {
acMirek = 1000000 / *ac.K
}
if acMirek != dcMirek {
update.Mirek = &dcMirek
updated = true
}
}
// Handle power first
if desired.Power != nil && active.Power != nil && *desired.Power != *active.Power {
update.Power = gentools.Ptr(*desired.Power)
updated = true
}
if active.Intensity != nil && desired.Intensity != nil {
if math.Abs(*active.Intensity-*desired.Intensity) >= 0.01 {
update.Brightness = gentools.Ptr(*desired.Intensity * 100)
updated = true
// Only do the rest if there's power.
if desired.Power == nil || *desired.Power {
if active.Color != nil && desired.Color != nil {
ac := *active.Color
dc := *desired.Color
if !dc.IsKelvin() || !colorFlags[id].IsWarmWhite() {
dc, _ = dc.ToXY()
dc.XY = gentools.Ptr(light.Color.Gamut.Conform(*dc.XY))
}
if dc.XY != nil {
if ac.K != nil {
ac.K = gentools.Ptr(1000000 / (1000000 / *ac.K))
}
acXY, _ := ac.ToXY()
dist := dc.XY.DistanceTo(*acXY.XY)
if dist > 0.0002 {
update.ColorXY = gentools.Ptr(*dc.XY)
updated = true
}
} else {
dcMirek := 1000000 / *dc.K
if dcMirek < light.ColorTemperature.MirekSchema.MirekMinimum {
dcMirek = light.ColorTemperature.MirekSchema.MirekMinimum
} else if dcMirek > light.ColorTemperature.MirekSchema.MirekMaximum {
dcMirek = light.ColorTemperature.MirekSchema.MirekMaximum
}
acMirek := 0
if ac.K != nil {
acMirek = 1000000 / *ac.K
}
if acMirek != dcMirek {
update.Mirek = &dcMirek
updated = true
}
}
}
if active.Intensity != nil && desired.Intensity != nil {
if math.Abs(*active.Intensity-*desired.Intensity) >= 0.01 {
update.Brightness = gentools.Ptr(*desired.Intensity * 100)
updated = true
}
}
}
@@ -515,7 +507,7 @@ func (b *Bridge) makeCongruentLoop(ctx context.Context) {
}
if len(updates) > 0 {
timeout, cancel := context.WithTimeout(ctx, time.Second)
timeout, cancel := context.WithTimeout(ctx, time.Millisecond*500*time.Duration(len(updates)))
eg, ctx := errgroup.WithContext(timeout)
for key := range updates {
+4 -2
View File
@@ -210,8 +210,10 @@ func (res *ResourceData) GenerateEvent(hostname string, resources map[string]*Re
hwMeta.Icon = "hue_lightbulb_e14"
case "sultan_bulb":
hwMeta.Icon = "hue_lightbulb_e27"
case "hue_signe":
hwMeta.Icon = "hue_signe"
case "hue_play":
hwMeta.Icon = "hue_playbar"
case "hue_signe", "hue_go":
hwMeta.Icon = res.ProductData.ProductArchetype
case "unknown_archetype":
switch res.ProductData.ProductName {
case "Hue motion sensor":
+13 -10
View File
@@ -3,6 +3,7 @@ package nanoleaf
import (
"encoding/binary"
"git.aiterp.net/lucifer3/server/device"
"git.aiterp.net/lucifer3/server/internal/color"
"time"
)
@@ -141,13 +142,13 @@ var shapeTypeMap = map[int]string{
var shapeIconMap = map[int]string{
0: "triangle",
1: "rhythm",
2: "Square",
1: "triangle",
2: "square",
3: "square",
4: "square",
7: "hexagon",
8: "triangle",
9: "triangle-small",
9: "triangle",
12: "hexagon",
}
@@ -218,14 +219,16 @@ func (p *panel) apply(change device.State, transitionTime time.Time) {
p.Intensity = *change.Intensity
}
if change.Color != nil {
if !p.On {
newColor := [4]byte{0, 0, 0, 0}
if newColor != p.ColorRGBA {
p.update(newColor, transitionTime)
}
}
if change.Color == nil {
change.Color = &color.Color{RGB: &color.RGB{Red: 255, Green: 255, Blue: 255}}
}
if !p.On {
newColor := [4]byte{0, 0, 0, 0}
if newColor != p.ColorRGBA {
p.update(newColor, transitionTime)
}
} else {
rgbColor, ok := change.Color.ToRGB()
if !ok {
newColor := [4]byte{255, 255, 255, 255}
+6
View File
@@ -13,6 +13,7 @@ type Line struct {
If *LineIf `json:"if,omitempty"`
Assign *LineAssign `json:"assign,omitempty"`
Set *LineSet `json:"set,omitempty"`
Select *LineSelect `json:"select,omitempty"`
}
type LineSet struct {
@@ -31,3 +32,8 @@ type LineIf struct {
Then []Line `json:"then,omitempty"`
Else []Line `json:"else,omitempty"`
}
type LineSelect struct {
Match string `json:"match"`
Then []Line `json:"then"`
}
+38 -24
View File
@@ -1,6 +1,7 @@
package script
import (
"fmt"
lucifer3 "git.aiterp.net/lucifer3/server"
"git.aiterp.net/lucifer3/server/commands"
"git.aiterp.net/lucifer3/server/device"
@@ -37,7 +38,9 @@ func (s *service) HandleEvent(bus *lucifer3.EventBus, event lucifer3.Event) {
return devices[i].ID < devices[j].ID
})
s.runScript(bus, script.Lines, trig.ScriptTarget, map[string]bool{}, devices, variables)
fmt.Println("[TRIGGER] Running", trig.ID, "for", len(devices), "devices:", event.EventDescription())
s.runScript(bus, lines, trig.ScriptTarget, map[string]bool{}, devices, variables)
}
}
}
@@ -97,7 +100,7 @@ func (s *service) runScript(bus *lucifer3.EventBus, lines []Line, match string,
continue
}
if dev.Matches(matcher) {
if line.Assign.Match == "*" || dev.Matches(matcher) {
matchedDevices[dev.ID] = true
matched = append(matched, dev.ID)
}
@@ -109,30 +112,41 @@ func (s *service) runScript(bus *lucifer3.EventBus, lines []Line, match string,
Effect: line.Assign.Effect.Effect,
})
}
} else {
if line.Set != nil {
switch line.Set.Scope {
case "devices":
bus.RunCommand(SetVariable{
Devices: gentools.Map(devices, func(d device.Pointer) string {
return d.ID
}),
Key: line.Set.Key,
Value: line.Set.Value,
})
case "match":
bus.RunCommand(SetVariable{
Match: gentools.Ptr(match),
Key: line.Set.Key,
Value: line.Set.Value,
})
case "global":
bus.RunCommand(SetVariable{
Key: line.Set.Key,
Value: line.Set.Value,
})
} else if line.Set != nil {
switch line.Set.Scope {
case "devices":
bus.RunCommand(SetVariable{
Devices: gentools.Map(devices, func(d device.Pointer) string {
return d.ID
}),
Key: line.Set.Key,
Value: line.Set.Value,
})
case "match":
bus.RunCommand(SetVariable{
Match: gentools.Ptr(match),
Key: line.Set.Key,
Value: line.Set.Value,
})
case "global":
bus.RunCommand(SetVariable{
Key: line.Set.Key,
Value: line.Set.Value,
})
}
} else if line.Select != nil {
matcher := s.resolver.CompileMatcher(line.Select.Match)
matched := make([]device.Pointer, 0)
for _, dev := range devices {
if dev.Matches(matcher) {
matched = append(matched, dev)
}
}
if len(matched) > 0 {
s.runScript(bus, line.Select.Then, match, matchedDevices, matched, variables)
}
}
}
}
+6 -4
View File
@@ -60,10 +60,12 @@ func (s *service) HandleCommand(bus *lucifer3.EventBus, command lucifer3.Command
})
}
case commands.SearchDevices:
bus.RunEvent(events.DeviceFailed{
ID: command.ID,
Error: "Please follow instructions in IKEA app; they will appear here after pairing.",
})
if _, ok := command.Matches("tradfri"); ok {
bus.RunEvent(events.DeviceFailed{
ID: command.ID,
Error: "Please follow instructions in IKEA app; they will appear here after pairing.",
})
}
case commands.SetState:
if _, ok := command.Matches("tradfri"); ok {
bridge, ok := s.findBridge(command.ID)
+19 -5
View File
@@ -8,6 +8,7 @@ import (
"git.aiterp.net/lucifer3/server/internal/gentools"
"git.aiterp.net/lucifer3/server/services/script"
"github.com/google/uuid"
"strings"
)
type Data struct {
@@ -22,7 +23,6 @@ func (d *Data) WithPatch(patches ...Patch) Data {
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)
@@ -32,18 +32,31 @@ func (d *Data) WithPatch(patches ...Patch) Data {
gentools.ApplyUpdatePtr(&pd.DesiredColorRGB, patch.Device.DesiredColorRGB)
if patch.Device.AddAlias != nil {
pd.Aliases = append(pd.Aliases[:0:0], pd.Aliases...)
pd.Aliases = append(pd.Aliases, *patch.Device.AddAlias)
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[:0:0], pd.Aliases...)
pd.Aliases = append(pd.Aliases[:i], pd.Aliases[i+1:]...)
break
}
}
}
if patch.Device.HWMetadata != nil {
if pd.Icon == "" {
pd.Icon = patch.Device.HWMetadata.Icon
}
}
if patch.Device.ClearAssignment {
pd.Assignment = nil
}
@@ -136,6 +149,7 @@ type Device struct {
Aliases []string `json:"aliases"`
Assignment *uuid.UUID `json:"assignment"`
Sensors DeviceSensors `json:"sensors"`
Icon string `json:"icon"`
}
type DeviceSensors struct {
+2 -3
View File
@@ -32,9 +32,9 @@ func (e Patch) EventDescription() string {
case e.Device.HWMetadata != nil:
return fmt.Sprintf("uistate.Patch(device=%s, hwMetadata)", e.Device.ID)
case e.Device.AddAlias != nil:
return fmt.Sprintf("uistate.Patch(device=%s, addAlias=%s)", e.Device.ID, *e.Device.AddAlias)
return fmt.Sprintf("uistate.Patch(device=%s, addAlias)", e.Device.ID)
case e.Device.RemoveAlias != nil:
return fmt.Sprintf("uistate.Patch(device=%s, removeAlias=%s)", e.Device.ID, *e.Device.RemoveAlias)
return fmt.Sprintf("uistate.Patch(device=%s, removeAlias)", e.Device.ID)
case e.Device.ActiveColorRGB != nil:
col := color.Color{RGB: e.Device.ActiveColorRGB}
return fmt.Sprintf("uistate.Patch(device=%s, activeColorRgb=%s)", e.Device.ID, col.String())
@@ -59,7 +59,6 @@ type DevicePatch struct {
HWMetadata *events.HardwareMetadata `json:"hwMetadata,omitempty"`
HWState *events.HardwareState `json:"hwState,omitempty"`
DesiredState *device.State `json:"desiredState,omitempty"`
SetAliases []string `json:"setAliases,omitempty"`
AddAlias *string `json:"addAlias,omitempty"`
RemoveAlias *string `json:"removeAlias,omitempty"`
Assignment *uuid.UUID `json:"assignment,omitempty"`