factory command
This commit is contained in:
@@ -0,0 +1,42 @@
|
|||||||
|
package handlerfactory
|
||||||
|
|
||||||
|
import (
|
||||||
|
"gopkg.in/yaml.v2"
|
||||||
|
"io"
|
||||||
|
"io/ioutil"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
type FactoryConfig struct {
|
||||||
|
Mode FCMOde `yaml:"mode"`
|
||||||
|
Target string `yaml:"target"`
|
||||||
|
SceneNames []string `yaml:"scenes"`
|
||||||
|
TriggerDeviceID string `yaml:"trigger_device_id"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type FCMOde string
|
||||||
|
|
||||||
|
var (
|
||||||
|
SceneDimmer FCMOde = "SceneDimmer"
|
||||||
|
)
|
||||||
|
|
||||||
|
func ParseConfigs(reader io.Reader) ([]FactoryConfig, error) {
|
||||||
|
readAll, err := ioutil.ReadAll(reader)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
splits := strings.Split(string(readAll), "\n---\n")
|
||||||
|
configs := make([]FactoryConfig, 0, 8)
|
||||||
|
for _, split := range splits {
|
||||||
|
var factoryConfig FactoryConfig
|
||||||
|
err := yaml.NewDecoder(strings.NewReader(split)).Decode(&factoryConfig)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
configs = append(configs, factoryConfig)
|
||||||
|
}
|
||||||
|
|
||||||
|
return configs, nil
|
||||||
|
}
|
||||||
@@ -0,0 +1,169 @@
|
|||||||
|
package handlerfactory
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"git.aiterp.net/lucifer/new-server/models"
|
||||||
|
)
|
||||||
|
|
||||||
|
func CreateHandlers(
|
||||||
|
config FactoryConfig,
|
||||||
|
scenes []models.Scene,
|
||||||
|
existing []models.EventHandler,
|
||||||
|
) ([]models.EventHandler, []models.EventHandler) {
|
||||||
|
switch config.Mode {
|
||||||
|
case SceneDimmer:
|
||||||
|
return sceneDimmer(config, scenes, existing)
|
||||||
|
default:
|
||||||
|
return []models.EventHandler{}, []models.EventHandler{}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func sceneDimmer(
|
||||||
|
config FactoryConfig,
|
||||||
|
scenes []models.Scene,
|
||||||
|
existing []models.EventHandler,
|
||||||
|
) ([]models.EventHandler, []models.EventHandler) {
|
||||||
|
kind, refValue := models.ParseFetchString(config.Target)
|
||||||
|
|
||||||
|
toRemove := make([]models.EventHandler, 0, 8)
|
||||||
|
for _, old := range existing {
|
||||||
|
if old.Conditions["deviceId"].EQ == config.TriggerDeviceID {
|
||||||
|
toRemove = append(toRemove, old)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
resolvedScenes := make([]models.Scene, 0, len(config.SceneNames))
|
||||||
|
for _, name := range config.SceneNames {
|
||||||
|
for _, scene := range scenes {
|
||||||
|
if name == scene.Name {
|
||||||
|
resolvedScenes = append(resolvedScenes, scene)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(scenes) < 2 {
|
||||||
|
return []models.EventHandler{}, []models.EventHandler{}
|
||||||
|
}
|
||||||
|
|
||||||
|
handlers := make([]models.EventHandler, 0, len(scenes)+4)
|
||||||
|
|
||||||
|
handlers = append(handlers, models.EventHandler{
|
||||||
|
EventName: "ButtonPressed",
|
||||||
|
Conditions: map[string]models.EventCondition{
|
||||||
|
"deviceId": {EQ: config.TriggerDeviceID},
|
||||||
|
"buttonName": {EQ: "On"},
|
||||||
|
},
|
||||||
|
OneShot: false,
|
||||||
|
Priority: 100,
|
||||||
|
TargetKind: kind,
|
||||||
|
TargetValue: refValue,
|
||||||
|
Actions: models.EventAction{SetPower: &myTrue},
|
||||||
|
From: -1,
|
||||||
|
To: -1,
|
||||||
|
})
|
||||||
|
|
||||||
|
handlers = append(handlers, models.EventHandler{
|
||||||
|
EventName: "ButtonPressed",
|
||||||
|
Conditions: map[string]models.EventCondition{
|
||||||
|
"deviceId": {EQ: config.TriggerDeviceID},
|
||||||
|
"buttonName": {EQ: "Off"},
|
||||||
|
},
|
||||||
|
OneShot: false,
|
||||||
|
Priority: 100,
|
||||||
|
TargetKind: kind,
|
||||||
|
TargetValue: refValue,
|
||||||
|
Actions: models.EventAction{SetPower: &myFalse},
|
||||||
|
From: -1,
|
||||||
|
To: -1,
|
||||||
|
})
|
||||||
|
|
||||||
|
for i, scene := range resolvedScenes {
|
||||||
|
if i > 0 {
|
||||||
|
handlers = append(handlers, models.EventHandler{
|
||||||
|
EventName: "ButtonPressed",
|
||||||
|
Conditions: map[string]models.EventCondition{
|
||||||
|
"deviceId": {EQ: config.TriggerDeviceID},
|
||||||
|
"buttonName": {EQ: "DimDown"},
|
||||||
|
"any.scene": {EQ: fmt.Sprintf("%d", scene.ID)},
|
||||||
|
},
|
||||||
|
OneShot: false,
|
||||||
|
Priority: 100,
|
||||||
|
TargetKind: kind,
|
||||||
|
TargetValue: refValue,
|
||||||
|
Actions: models.EventAction{SetScene: &models.DeviceSceneAssignment{
|
||||||
|
SceneID: resolvedScenes[i-1].ID,
|
||||||
|
Group: refValue,
|
||||||
|
DurationMS: 0,
|
||||||
|
}},
|
||||||
|
From: -1,
|
||||||
|
To: -1,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
if i < len(resolvedScenes)-1 {
|
||||||
|
handlers = append(handlers, models.EventHandler{
|
||||||
|
EventName: "ButtonPressed",
|
||||||
|
Conditions: map[string]models.EventCondition{
|
||||||
|
"deviceId": {EQ: config.TriggerDeviceID},
|
||||||
|
"buttonName": {EQ: "DimUp"},
|
||||||
|
"any.scene": {EQ: fmt.Sprintf("%d", scene.ID)},
|
||||||
|
},
|
||||||
|
OneShot: false,
|
||||||
|
Priority: 100,
|
||||||
|
TargetKind: kind,
|
||||||
|
TargetValue: refValue,
|
||||||
|
Actions: models.EventAction{SetScene: &models.DeviceSceneAssignment{
|
||||||
|
SceneID: resolvedScenes[i+1].ID,
|
||||||
|
Group: refValue,
|
||||||
|
DurationMS: 0,
|
||||||
|
}},
|
||||||
|
From: -1,
|
||||||
|
To: -1,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
handlers = append(handlers, models.EventHandler{
|
||||||
|
EventName: "ButtonPressed",
|
||||||
|
Conditions: map[string]models.EventCondition{
|
||||||
|
"deviceId": {EQ: config.TriggerDeviceID},
|
||||||
|
"buttonName": {EQ: "DimDown"},
|
||||||
|
},
|
||||||
|
OneShot: false,
|
||||||
|
Priority: 90,
|
||||||
|
TargetKind: kind,
|
||||||
|
TargetValue: refValue,
|
||||||
|
Actions: models.EventAction{SetScene: &models.DeviceSceneAssignment{
|
||||||
|
SceneID: scenes[len(scenes)-1].ID,
|
||||||
|
Group: refValue,
|
||||||
|
DurationMS: 0,
|
||||||
|
}},
|
||||||
|
From: -1,
|
||||||
|
To: -1,
|
||||||
|
})
|
||||||
|
|
||||||
|
handlers = append(handlers, models.EventHandler{
|
||||||
|
EventName: "ButtonPressed",
|
||||||
|
Conditions: map[string]models.EventCondition{
|
||||||
|
"deviceId": {EQ: config.TriggerDeviceID},
|
||||||
|
"buttonName": {EQ: "DimUp"},
|
||||||
|
},
|
||||||
|
OneShot: false,
|
||||||
|
Priority: 90,
|
||||||
|
TargetKind: kind,
|
||||||
|
TargetValue: refValue,
|
||||||
|
Actions: models.EventAction{SetScene: &models.DeviceSceneAssignment{
|
||||||
|
SceneID: scenes[0].ID,
|
||||||
|
Group: refValue,
|
||||||
|
DurationMS: 0,
|
||||||
|
}},
|
||||||
|
From: -1,
|
||||||
|
To: -1,
|
||||||
|
})
|
||||||
|
|
||||||
|
return handlers, toRemove
|
||||||
|
}
|
||||||
|
|
||||||
|
var myTrue = true
|
||||||
|
var myFalse = false
|
||||||
@@ -0,0 +1,71 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"git.aiterp.net/lucifer/new-server/app/client"
|
||||||
|
"git.aiterp.net/lucifer/new-server/app/services/handlerfactory"
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
|
)
|
||||||
|
|
||||||
|
func factoryCmd(
|
||||||
|
ctx context.Context,
|
||||||
|
c client.Client,
|
||||||
|
) {
|
||||||
|
cmd := parseCommand(os.Args[2:])
|
||||||
|
|
||||||
|
switch cmd.Name {
|
||||||
|
case "run":
|
||||||
|
fileName := cmd.Params.Get(0).String()
|
||||||
|
if fileName == nil {
|
||||||
|
log.Fatalln("Missing filename")
|
||||||
|
}
|
||||||
|
|
||||||
|
scenes, err := c.GetScenes(ctx)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalln(err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
handlers, err := c.GetHandlers(ctx)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalln(err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
file, err := os.Open(*fileName)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalln("Failed to open file:", err)
|
||||||
|
}
|
||||||
|
defer file.Close()
|
||||||
|
|
||||||
|
configs, err := handlerfactory.ParseConfigs(file)
|
||||||
|
for _, config := range configs {
|
||||||
|
toAdd, toRemove := handlerfactory.CreateHandlers(config, scenes, handlers)
|
||||||
|
|
||||||
|
for _, removing := range toRemove {
|
||||||
|
_, err := c.DeleteHandler(ctx, removing.ID)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalln(err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Printf("Removed handler %d", removing.ID)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, adding := range toAdd {
|
||||||
|
res, err := c.AddHandler(ctx, adding)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalln(err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Printf("Added handler %d", res.ID)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
if cmd.Name != "help" {
|
||||||
|
log.Println("Unknown command:", cmd.Name)
|
||||||
|
}
|
||||||
|
|
||||||
|
_, _ = fmt.Fprintln(os.Stderr, helpString[1:])
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -32,6 +32,23 @@ EVENT HANDLER COMMANDS
|
|||||||
<-fire> <-fire.payload.*>
|
<-fire> <-fire.payload.*>
|
||||||
handler delete <id>
|
handler delete <id>
|
||||||
|
|
||||||
|
EVENT HANDLER FACTORY COMMANDS
|
||||||
|
|
||||||
|
factory run <file.yaml>
|
||||||
|
|
||||||
|
File example (use '---' to delimit multiple configs in one file):
|
||||||
|
mode: SceneDimmer
|
||||||
|
target: tag:Soverom
|
||||||
|
scenes:
|
||||||
|
- kveldslys
|
||||||
|
- landskap
|
||||||
|
- vasking
|
||||||
|
trigger_device_id: 14
|
||||||
|
---
|
||||||
|
(more modes coming soon)
|
||||||
|
|
||||||
|
WARNING: Similar event handlers will be removed!
|
||||||
|
|
||||||
EVENT COMMANDS
|
EVENT COMMANDS
|
||||||
run <event name> <*=S>
|
run <event name> <*=S>
|
||||||
|
|
||||||
|
|||||||
+5
-3
@@ -82,8 +82,8 @@ func main() {
|
|||||||
case "update":
|
case "update":
|
||||||
{
|
{
|
||||||
devices, err := c.PutDevice(ctx, cmd.Params.Get(0).StringOr("all"), models.DeviceUpdate{
|
devices, err := c.PutDevice(ctx, cmd.Params.Get(0).StringOr("all"), models.DeviceUpdate{
|
||||||
Name: cmd.Params.Get("name").String(),
|
Name: cmd.Params.Get("name").String(),
|
||||||
Icon: cmd.Params.Get("icon").String(),
|
Icon: cmd.Params.Get("icon").String(),
|
||||||
UserProperties: cmd.Params.Subset("prop.").StringPtrMap(),
|
UserProperties: cmd.Params.Subset("prop.").StringPtrMap(),
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -93,6 +93,9 @@ func main() {
|
|||||||
WriteDeviceInfoTable(os.Stdout, devices)
|
WriteDeviceInfoTable(os.Stdout, devices)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case "factory":
|
||||||
|
factoryCmd(ctx, c)
|
||||||
|
|
||||||
case "handler":
|
case "handler":
|
||||||
handlerCmd(ctx, c)
|
handlerCmd(ctx, c)
|
||||||
|
|
||||||
@@ -126,4 +129,3 @@ func main() {
|
|||||||
_, _ = fmt.Fprintln(os.Stderr, helpString[1:])
|
_, _ = fmt.Fprintln(os.Stderr, helpString[1:])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user