2019-03-10 04:41:23 +00:00
|
|
|
package data
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"github.com/sqshq/sampler/asset"
|
|
|
|
"github.com/sqshq/sampler/config"
|
|
|
|
"github.com/sqshq/sampler/console"
|
|
|
|
"os"
|
|
|
|
"os/exec"
|
|
|
|
"regexp"
|
|
|
|
)
|
|
|
|
|
|
|
|
const (
|
|
|
|
TrueIndicator = "1"
|
|
|
|
InitialValue = "0"
|
|
|
|
)
|
|
|
|
|
|
|
|
type Trigger struct {
|
|
|
|
title string
|
|
|
|
condition string
|
2019-03-16 23:59:28 +00:00
|
|
|
actions *Actions
|
|
|
|
consumer *Consumer
|
2019-03-10 04:41:23 +00:00
|
|
|
valuesByLabel map[string]Values
|
|
|
|
player *asset.AudioPlayer
|
|
|
|
digitsRegexp *regexp.Regexp
|
|
|
|
}
|
|
|
|
|
|
|
|
type Actions struct {
|
|
|
|
terminalBell bool
|
|
|
|
sound bool
|
|
|
|
visual bool
|
|
|
|
script *string
|
|
|
|
}
|
|
|
|
|
|
|
|
type Values struct {
|
|
|
|
current string
|
|
|
|
previous string
|
|
|
|
}
|
|
|
|
|
2019-03-16 23:59:28 +00:00
|
|
|
func NewTriggers(cfgs []config.TriggerConfig, consumer *Consumer, player *asset.AudioPlayer) []Trigger {
|
2019-03-10 04:41:23 +00:00
|
|
|
|
|
|
|
triggers := make([]Trigger, 0)
|
|
|
|
|
|
|
|
for _, cfg := range cfgs {
|
|
|
|
triggers = append(triggers, NewTrigger(cfg, consumer, player))
|
|
|
|
}
|
|
|
|
|
|
|
|
return triggers
|
|
|
|
}
|
|
|
|
|
2019-03-16 23:59:28 +00:00
|
|
|
func NewTrigger(config config.TriggerConfig, consumer *Consumer, player *asset.AudioPlayer) Trigger {
|
2019-03-10 04:41:23 +00:00
|
|
|
return Trigger{
|
|
|
|
title: config.Title,
|
|
|
|
condition: config.Condition,
|
|
|
|
consumer: consumer,
|
|
|
|
valuesByLabel: make(map[string]Values),
|
|
|
|
player: player,
|
|
|
|
digitsRegexp: regexp.MustCompile("[^0-9]+"),
|
2019-03-16 23:59:28 +00:00
|
|
|
actions: &Actions{
|
2019-03-10 04:41:23 +00:00
|
|
|
terminalBell: *config.Actions.TerminalBell,
|
|
|
|
sound: *config.Actions.Sound,
|
|
|
|
visual: *config.Actions.Visual,
|
|
|
|
script: config.Actions.Script,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-03-16 23:59:28 +00:00
|
|
|
func (t *Trigger) Execute(sample *Sample) {
|
2019-03-10 04:41:23 +00:00
|
|
|
if t.evaluate(sample) {
|
|
|
|
|
|
|
|
if t.actions.terminalBell {
|
|
|
|
fmt.Print(console.BellCharacter)
|
|
|
|
}
|
|
|
|
|
|
|
|
if t.actions.sound {
|
|
|
|
t.player.Beep()
|
|
|
|
}
|
|
|
|
|
|
|
|
if t.actions.visual {
|
2019-03-16 23:59:28 +00:00
|
|
|
t.consumer.AlertChannel <- &Alert{
|
2019-03-13 03:15:55 +00:00
|
|
|
Title: t.title,
|
|
|
|
Text: fmt.Sprintf("%s: %v", sample.Label, sample.Value),
|
|
|
|
Color: sample.Color,
|
2019-03-11 03:43:47 +00:00
|
|
|
}
|
2019-03-10 04:41:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if t.actions.script != nil {
|
|
|
|
_, _ = runScript(*t.actions.script, sample.Label, t.valuesByLabel[sample.Label])
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-03-16 23:59:28 +00:00
|
|
|
func (t *Trigger) evaluate(sample *Sample) bool {
|
2019-03-10 04:41:23 +00:00
|
|
|
|
|
|
|
if values, ok := t.valuesByLabel[sample.Label]; ok {
|
|
|
|
values.previous = values.current
|
|
|
|
values.current = sample.Value
|
|
|
|
t.valuesByLabel[sample.Label] = values
|
|
|
|
} else {
|
|
|
|
t.valuesByLabel[sample.Label] = Values{previous: InitialValue, current: sample.Value}
|
|
|
|
}
|
|
|
|
|
|
|
|
output, err := runScript(t.condition, sample.Label, t.valuesByLabel[sample.Label])
|
|
|
|
|
|
|
|
if err != nil {
|
2019-03-16 23:59:28 +00:00
|
|
|
t.consumer.AlertChannel <- &Alert{Title: "TRIGGER CONDITION FAILURE", Text: err.Error()}
|
2019-03-10 04:41:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return t.digitsRegexp.ReplaceAllString(string(output), "") == TrueIndicator
|
|
|
|
}
|
|
|
|
|
|
|
|
func runScript(script, label string, data Values) ([]byte, error) {
|
|
|
|
|
|
|
|
cmd := exec.Command("sh", "-c", script)
|
|
|
|
cmd.Env = os.Environ()
|
|
|
|
cmd.Env = append(cmd.Env,
|
|
|
|
fmt.Sprintf("prev=%v", data.previous),
|
|
|
|
fmt.Sprintf("cur=%v", data.current),
|
|
|
|
fmt.Sprintf("label=%v", label))
|
|
|
|
|
|
|
|
return cmd.Output()
|
|
|
|
}
|