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