|
|
package script
import ( lucifer3 "git.aiterp.net/lucifer3/server" "git.aiterp.net/lucifer3/server/commands" "git.aiterp.net/lucifer3/server/device" "git.aiterp.net/lucifer3/server/internal/formattools" "git.aiterp.net/lucifer3/server/internal/gentools" "sort" "sync" )
type service struct { mu sync.Mutex resolver device.Resolver variables *Variables scripts map[string]*Script }
func (s *service) Active() bool { return true }
func (s *service) HandleEvent(_ *lucifer3.EventBus, _ lucifer3.Event) {}
func (s *service) HandleCommand(bus *lucifer3.EventBus, command lucifer3.Command) { switch command := command.(type) { case UpdateScript: s.mu.Lock() s.scripts[command.Name] = &Script{ Name: command.Name, Lines: command.Lines, } s.mu.Unlock() case ExecuteScript: s.mu.Lock() script := s.scripts[command.Name] s.mu.Unlock() if script == nil { break }
variables := s.variables.Get()
devices := s.resolver.Resolve(command.Match) sort.Slice(devices, func(i, j int) bool { return devices[i].ID < devices[j].ID })
s.runScript(bus, script.Lines, command.Match, map[string]bool{}, devices, variables) } }
func NewService(resolver device.Resolver, variables *Variables) lucifer3.Service { return &service{ resolver: resolver, variables: variables, scripts: map[string]*Script{}, } }
func (s *service) runScript(bus *lucifer3.EventBus, lines []Line, match string, matchedDevices map[string]bool, devices []device.Pointer, variables VariableSet) { for _, line := range lines { if line.If != nil { devicesIDs := gentools.Map(devices, func(d device.Pointer) string { return d.ID }) if line.If.Condition.Check(variables, match, devicesIDs) { s.runScript(bus, line.If.Then, match, matchedDevices, devices, variables) } else { s.runScript(bus, line.If.Else, match, matchedDevices, devices, variables) } } else if line.Assign != nil { matcher := s.resolver.CompileMatcher(line.Assign.Match)
matched := make([]string, 0) for _, dev := range devices { if matchedDevices[dev.ID] { continue }
if dev.Matches(matcher) { matchedDevices[dev.ID] = true matched = append(matched, dev.ID) } }
if len(matched) > 0 { bus.RunCommand(commands.Assign{ Match: formattools.CompactMatch(matched), 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, }) } } } } }
|