trigger implementation

This commit is contained in:
sqshq 2019-03-04 22:25:17 -05:00
parent 0de4d07a02
commit 9b22083af8
6 changed files with 117 additions and 23 deletions

View File

@ -1,7 +1,6 @@
package asset package asset
import ( import (
"fmt"
"github.com/hajimehoshi/go-mp3" "github.com/hajimehoshi/go-mp3"
"github.com/hajimehoshi/oto" "github.com/hajimehoshi/oto"
"io" "io"
@ -31,7 +30,5 @@ func Beep() error {
return err return err
} }
fmt.Print("\a")
return nil return nil
} }

View File

@ -2,6 +2,7 @@ package runchart
import ( import (
"fmt" "fmt"
"github.com/sqshq/sampler/component/trigger"
"github.com/sqshq/sampler/console" "github.com/sqshq/sampler/console"
"github.com/sqshq/sampler/data" "github.com/sqshq/sampler/data"
"image" "image"
@ -36,6 +37,7 @@ const (
type RunChart struct { type RunChart struct {
ui.Block ui.Block
triggers []trigger.Trigger
lines []TimeLine lines []TimeLine
grid ChartGrid grid ChartGrid
timescale time.Duration timescale time.Duration

View File

@ -0,0 +1,99 @@
package trigger
import (
"fmt"
"github.com/sqshq/sampler/asset"
"github.com/sqshq/sampler/config"
"os"
"os/exec"
)
const (
TrueIndicator = "1"
BellCharacter = "\a"
)
type Trigger struct {
title string
condition string
actions Actions
data map[string]Data
}
type Actions struct {
terminalBell bool
sound bool
visual bool
script *string
}
type Data struct {
previousValue interface{}
currentValue interface{}
}
func NewTrigger(config config.TriggerConfig) Trigger {
return Trigger{
title: config.Title,
condition: config.Condition,
actions: Actions{
terminalBell: *config.Actions.TerminalBell,
sound: *config.Actions.Sound,
visual: *config.Actions.Visual,
script: config.Actions.Script,
},
}
}
func (t Trigger) execute(label string, value interface{}) {
go func() {
if data, ok := t.data[label]; ok {
data.previousValue = data.currentValue
data.currentValue = value
} else {
t.data[label] = Data{previousValue: nil, currentValue: value}
}
t.evaluate(label, t.data[label])
}()
}
func (t Trigger) evaluate(label string, data Data) {
output, err := runScript(t.condition, label, data)
if err != nil {
println(err) // TODO visual notification
}
if string(output) != TrueIndicator {
return
}
if t.actions.terminalBell {
fmt.Print(BellCharacter)
}
if t.actions.sound {
_ = asset.Beep()
}
if t.actions.visual {
// TODO visual notification
}
if t.actions.script != nil {
_, _ = runScript(*t.actions.script, label, data)
}
}
func runScript(script, label string, data Data) ([]byte, error) {
cmd := exec.Command("sh", "-c", script)
cmd.Env = os.Environ()
cmd.Env = append(cmd.Env,
fmt.Sprintf("prev=%v", data.previousValue),
fmt.Sprintf("cur=%v", data.currentValue),
fmt.Sprintf("label=%v", label))
return cmd.Output()
}

View File

@ -6,7 +6,6 @@ runcharts:
size: size:
w: 53 w: 53
h: 16 h: 16
scale: 3
triggers: triggers:
- title: PROCESSING STARTED # ${prev} ${cur} ${lavel} echo $(( 3 < 4 && 1 > 2 )) - title: PROCESSING STARTED # ${prev} ${cur} ${lavel} echo $(( 3 < 4 && 1 > 2 ))
condition: ((${prev} == 0 && ${cur} > 0)) condition: ((${prev} == 0 && ${cur} > 0))

View File

@ -7,10 +7,11 @@ import (
) )
type ComponentConfig struct { type ComponentConfig struct {
Title string `yaml:"title"` Title string `yaml:"title"`
RefreshRateMs *int `yaml:"refresh-rate-ms,omitempty"` RefreshRateMs *int `yaml:"refresh-rate-ms,omitempty"`
Position Position `yaml:"position"` Position Position `yaml:"position"`
Size Size `yaml:"size"` Size Size `yaml:"size"`
Triggers []TriggerConfig `yaml:"triggers,omitempty"`
} }
type TriggerConfig struct { type TriggerConfig struct {
@ -28,7 +29,6 @@ type ActionsConfig struct {
type GaugeConfig struct { type GaugeConfig struct {
ComponentConfig `yaml:",inline"` ComponentConfig `yaml:",inline"`
Triggers []TriggerConfig `yaml:"triggers"`
Scale *int `yaml:"scale,omitempty"` Scale *int `yaml:"scale,omitempty"`
Color *ui.Color `yaml:"color,omitempty"` Color *ui.Color `yaml:"color,omitempty"`
Values map[string]string `yaml:"values"` Values map[string]string `yaml:"values"`
@ -37,24 +37,21 @@ type GaugeConfig struct {
type BarChartConfig struct { type BarChartConfig struct {
ComponentConfig `yaml:",inline"` ComponentConfig `yaml:",inline"`
Triggers []TriggerConfig `yaml:"triggers"` Scale *int `yaml:"scale,omitempty"`
Scale *int `yaml:"scale,omitempty"` Items []data.Item `yaml:"items"`
Items []data.Item `yaml:"items"`
} }
type AsciiBoxConfig struct { type AsciiBoxConfig struct {
ComponentConfig `yaml:",inline"` ComponentConfig `yaml:",inline"`
Triggers []TriggerConfig `yaml:"triggers"`
data.Item `yaml:",inline"` data.Item `yaml:",inline"`
Font *asciibox.AsciiFont `yaml:"font,omitempty"` Font *asciibox.AsciiFont `yaml:"font,omitempty"`
} }
type RunChartConfig struct { type RunChartConfig struct {
ComponentConfig `yaml:",inline"` ComponentConfig `yaml:",inline"`
Triggers []TriggerConfig `yaml:"triggers"` Legend *LegendConfig `yaml:"legend,omitempty"`
Legend *LegendConfig `yaml:"legend,omitempty"` Scale *int `yaml:"scale,omitempty"`
Scale *int `yaml:"scale,omitempty"` Items []data.Item `yaml:"items"`
Items []data.Item `yaml:"items"`
} }
type LegendConfig struct { type LegendConfig struct {

View File

@ -24,16 +24,16 @@ type Flags struct {
func Load() (Config, Flags) { func Load() (Config, Flags) {
//if len(os.Args) < 2 { if len(os.Args) < 2 {
// println("Please specify config file location. See www.github.com/sqshq/sampler for the reference") println("Please specify config file location. See www.github.com/sqshq/sampler for the reference")
// os.Exit(0) os.Exit(0)
//} }
cfg := readFile("config.yml") cfg := readFile(os.Args[1])
cfg.validate() cfg.validate()
cfg.setDefaults() cfg.setDefaults()
flg := Flags{ConfigFileName: "config.yml"} flg := Flags{ConfigFileName: os.Args[1]}
return *cfg, flg return *cfg, flg
} }