Stian Fredrik Aune
3 years ago
5 changed files with 304 additions and 3 deletions
-
42app/services/handlerfactory/config.go
-
169app/services/handlerfactory/factory.go
-
71cmd/lucy/factorycmd.go
-
17cmd/lucy/help.go
-
8cmd/lucy/main.go
@ -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:]) |
||||
|
} |
||||
|
} |
Write
Preview
Loading…
Cancel
Save
Reference in new issue