Gisle Aune
2 years ago
9 changed files with 234 additions and 39 deletions
-
32cmd/bustest/main.go
-
33commands/edit.go
-
4device/flags.go
-
18device/state.go
-
8events/device.go
-
24internal/gentools/slices.go
-
2service.go
-
3services/package.go
-
149services/resolver.go
@ -0,0 +1,33 @@ |
|||||
|
package commands |
||||
|
|
||||
|
import ( |
||||
|
"fmt" |
||||
|
"git.aiterp.net/lucifer3/server/internal/formattools" |
||||
|
) |
||||
|
|
||||
|
type SetName struct { |
||||
|
ID string |
||||
|
Name string |
||||
|
} |
||||
|
|
||||
|
func (c SetName) CommandDescription() string { |
||||
|
return fmt.Sprintf("SetName(%v, %s)", c.ID, c.Name) |
||||
|
} |
||||
|
|
||||
|
type AddTag struct { |
||||
|
IDs []string |
||||
|
Tag string |
||||
|
} |
||||
|
|
||||
|
func (c AddTag) CommandDescription() string { |
||||
|
return fmt.Sprintf("AddTag(%v, %s)", formattools.CompactIDList(c.IDs), c.Tag) |
||||
|
} |
||||
|
|
||||
|
type RemoveTag struct { |
||||
|
IDs []string |
||||
|
Tag string |
||||
|
} |
||||
|
|
||||
|
func (c RemoveTag) CommandDescription() string { |
||||
|
return fmt.Sprintf("RemoveTag(%v, %s)", formattools.CompactIDList(c.IDs), c.Tag) |
||||
|
} |
@ -0,0 +1,24 @@ |
|||||
|
package gentools |
||||
|
|
||||
|
func IndexOf[T comparable](arr []T, value T) int { |
||||
|
for i, v := range arr { |
||||
|
if v == value { |
||||
|
return i |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
return -1 |
||||
|
} |
||||
|
|
||||
|
func AddUniques[T comparable](arr *[]T, values ...T) { |
||||
|
Outer: |
||||
|
for _, v := range values { |
||||
|
for _, v2 := range *arr { |
||||
|
if v2 == v { |
||||
|
continue Outer |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
*arr = append(*arr, v) |
||||
|
} |
||||
|
} |
@ -0,0 +1,3 @@ |
|||||
|
// Package services is for self-contained general services. Things like bridges, databases and such should
|
||||
|
// not be in here.
|
||||
|
package services |
@ -0,0 +1,149 @@ |
|||||
|
package services |
||||
|
|
||||
|
import ( |
||||
|
lucifer3 "git.aiterp.net/lucifer3/server" |
||||
|
"git.aiterp.net/lucifer3/server/commands" |
||||
|
"git.aiterp.net/lucifer3/server/events" |
||||
|
"git.aiterp.net/lucifer3/server/internal/gentools" |
||||
|
"strings" |
||||
|
) |
||||
|
|
||||
|
func Resolver() lucifer3.Service { |
||||
|
return &resolver{ |
||||
|
tags: make(map[string][]string), |
||||
|
names: make(map[string][]string), |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
type resolver struct { |
||||
|
tags map[string][]string |
||||
|
names map[string][]string |
||||
|
} |
||||
|
|
||||
|
func (r *resolver) Active() bool { |
||||
|
return true |
||||
|
} |
||||
|
|
||||
|
func (r *resolver) HandleEvent(_ *lucifer3.EventBus, event lucifer3.Event) { |
||||
|
switch event := event.(type) { |
||||
|
case events.HardwareState: |
||||
|
// On HardwareState, use the internal name if (and only if) it is not already named.
|
||||
|
|
||||
|
if event.InternalName != "" { |
||||
|
found := false |
||||
|
for _, ids := range r.names { |
||||
|
i := gentools.IndexOf(ids, event.ID) |
||||
|
if i != -1 { |
||||
|
found = true |
||||
|
break |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
if !found { |
||||
|
r.names[event.InternalName] = append(r.names[event.InternalName], event.ID) |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
func (r *resolver) HandleCommand(bus *lucifer3.EventBus, command lucifer3.Command) { |
||||
|
var resolveList []string |
||||
|
var resolveCB func(newIDs []string) lucifer3.Command |
||||
|
|
||||
|
switch command := command.(type) { |
||||
|
case commands.Assign: |
||||
|
resolveList = command.IDs |
||||
|
resolveCB = func(newIDs []string) lucifer3.Command { command.IDs = newIDs; return command } |
||||
|
case commands.ReplaceScene: |
||||
|
resolveList = command.IDs |
||||
|
resolveCB = func(newIDs []string) lucifer3.Command { command.IDs = newIDs; return command } |
||||
|
case commands.ClearScene: |
||||
|
resolveList = command.IDs |
||||
|
resolveCB = func(newIDs []string) lucifer3.Command { command.IDs = newIDs; return command } |
||||
|
case commands.SetName: |
||||
|
if !strings.HasPrefix(command.ID, "lucifer:") { |
||||
|
for name := range r.names { |
||||
|
i := gentools.IndexOf(r.names[name], command.ID) |
||||
|
if i != -1 { |
||||
|
r.names[name] = append(r.names[name][:i], r.names[name][i+1:]...) |
||||
|
} |
||||
|
} |
||||
|
r.names[command.Name] = append(r.names[command.Name], command.ID) |
||||
|
} |
||||
|
case commands.AddTag: |
||||
|
for _, id := range command.IDs { |
||||
|
if strings.HasPrefix(id, "lucifer:") { |
||||
|
continue |
||||
|
} |
||||
|
|
||||
|
found := false |
||||
|
for _, id2 := range r.tags[command.Tag] { |
||||
|
if id == id2 { |
||||
|
found = true |
||||
|
break |
||||
|
} |
||||
|
} |
||||
|
if !found { |
||||
|
r.tags[command.Tag] = append(r.tags[command.Tag], id) |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
resolveList = command.IDs |
||||
|
resolveCB = func(newIDs []string) lucifer3.Command { command.IDs = newIDs; return command } |
||||
|
case commands.RemoveTag: |
||||
|
for _, id := range command.IDs { |
||||
|
if strings.HasPrefix(id, "lucifer:") { |
||||
|
continue |
||||
|
} |
||||
|
|
||||
|
for i, id2 := range r.tags[command.Tag] { |
||||
|
if id == id2 { |
||||
|
r.tags[command.Tag] = append(r.tags[command.Tag][:i], r.tags[command.Tag][i+1:]...) |
||||
|
break |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
resolveList = command.IDs |
||||
|
resolveCB = func(newIDs []string) lucifer3.Command { command.IDs = newIDs; return command } |
||||
|
} |
||||
|
|
||||
|
if resolveList != nil && resolveCB != nil { |
||||
|
newList := make([]string, 0, 16) |
||||
|
|
||||
|
for _, id := range resolveList { |
||||
|
switch { |
||||
|
case strings.HasPrefix(id, "lucifer:tag:"): |
||||
|
tag := id[12:] |
||||
|
if len(newList) == 0 { |
||||
|
newList = append(newList, r.tags[tag]...) |
||||
|
} else { |
||||
|
gentools.AddUniques(&newList, r.tags[tag]...) |
||||
|
} |
||||
|
case strings.HasPrefix(id, "lucifer:name:"): |
||||
|
name := id[13:] |
||||
|
if strings.HasSuffix(name, "*") { |
||||
|
prefix := name[:len(name)-1] |
||||
|
for name, ids := range r.names { |
||||
|
if strings.HasPrefix(name, prefix) { |
||||
|
gentools.AddUniques(&newList, ids...) |
||||
|
} |
||||
|
} |
||||
|
} else if strings.HasPrefix(name, "*") { |
||||
|
suffix := name[1:] |
||||
|
for name, ids := range r.names { |
||||
|
if strings.HasSuffix(name, suffix) { |
||||
|
gentools.AddUniques(&newList, ids...) |
||||
|
} |
||||
|
} |
||||
|
} else { |
||||
|
gentools.AddUniques(&newList, r.names[name]...) |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
if len(newList) > 0 { |
||||
|
bus.RunCommand(resolveCB(newList)) |
||||
|
} |
||||
|
} |
||||
|
} |
Write
Preview
Loading…
Cancel
Save
Reference in new issue