Add shared javascript VMs and demo config
This commit is contained in:
parent
e767cf0fbc
commit
85dbee393f
6 changed files with 153 additions and 12 deletions
|
|
@ -21,6 +21,7 @@ type config struct {
|
|||
Levels map[string]string
|
||||
Interval time.Duration
|
||||
Mqtt mqttConfig
|
||||
Javascript map[string]interface{}
|
||||
Influx server.InfluxConfig
|
||||
HEMS typedConfig
|
||||
Messaging messagingConfig
|
||||
|
|
|
|||
72
cmd/demo.go
72
cmd/demo.go
|
|
@ -8,24 +8,60 @@ import (
|
|||
const demoYaml = `
|
||||
log: info
|
||||
|
||||
javascript:
|
||||
- vm: shared
|
||||
script: |
|
||||
state = {
|
||||
residualpower: 200,
|
||||
pvpower: -3000,
|
||||
batterypower: 200,
|
||||
gridpower: -2000,
|
||||
chargepower: 0,
|
||||
maxcurrent: 0,
|
||||
battery: 63, // car
|
||||
};
|
||||
function get() {
|
||||
console.log("state:", JSON.stringify(state));
|
||||
}
|
||||
function set() {
|
||||
console.log(param+":", val);
|
||||
console.log("state:", JSON.stringify(state));
|
||||
}
|
||||
|
||||
meters:
|
||||
- name: grid
|
||||
type: default
|
||||
power:
|
||||
type: js
|
||||
script: "1200"
|
||||
vm: shared
|
||||
script: state.gridpower = state.pvpower + state.chargepower + state.residualpower + state.batterypower;
|
||||
|
||||
- name: pv
|
||||
type: default
|
||||
power:
|
||||
type: js
|
||||
script: "6400"
|
||||
vm: shared
|
||||
script: state.pvpower += 100*Math.random();
|
||||
|
||||
- name: battery
|
||||
type: default
|
||||
power:
|
||||
type: js
|
||||
script: "200"
|
||||
vm: shared
|
||||
script: state.batterypower;
|
||||
soc:
|
||||
type: js
|
||||
vm: shared
|
||||
script: "30"
|
||||
- name: charge
|
||||
type: default
|
||||
power:
|
||||
type: js
|
||||
vm: shared
|
||||
script: state.chargepower;
|
||||
soc:
|
||||
type: js
|
||||
vm: shared
|
||||
script: "30"
|
||||
|
||||
chargers:
|
||||
|
|
@ -33,16 +69,28 @@ chargers:
|
|||
type: default
|
||||
enable:
|
||||
type: js
|
||||
script: "true"
|
||||
vm: shared
|
||||
script: |
|
||||
set();
|
||||
state.enabled = val;
|
||||
if (state.enabled) state.chargepower = state.maxcurrent * 230; else state.chargepower = 0;
|
||||
enabled:
|
||||
type: js
|
||||
script: "true"
|
||||
vm: shared
|
||||
script: |
|
||||
state.enabled;
|
||||
status:
|
||||
type: js
|
||||
script: "'B'"
|
||||
vm: shared
|
||||
script: |
|
||||
if (state.enabled) "C"; else "B";
|
||||
maxcurrent:
|
||||
type: js
|
||||
script: "6"
|
||||
vm: shared
|
||||
script: |
|
||||
set();
|
||||
state.maxcurrent = val;
|
||||
if (state.enabled) state.chargepower = state.maxcurrent * 230;
|
||||
|
||||
vehicles:
|
||||
- name: demo
|
||||
|
|
@ -50,7 +98,13 @@ vehicles:
|
|||
type: default
|
||||
charge:
|
||||
type: js
|
||||
script: "63"
|
||||
vm: shared
|
||||
script: |
|
||||
if (state.chargepower > 0) state.battery++; else state.battery--;
|
||||
if (state.battery < 15) state.battery = 15;
|
||||
if (state.battery > 100) state.battery = 100;
|
||||
state.battery;
|
||||
cache: 1s
|
||||
|
||||
site:
|
||||
title: Demo
|
||||
|
|
@ -62,6 +116,8 @@ site:
|
|||
loadpoints:
|
||||
- title: Carport
|
||||
charger: demo
|
||||
meters:
|
||||
charge: charge
|
||||
vehicle: demo
|
||||
`
|
||||
|
||||
|
|
|
|||
|
|
@ -158,6 +158,9 @@ func run(cmd *cobra.Command, args []string) {
|
|||
configureMQTT(conf.Mqtt)
|
||||
}
|
||||
|
||||
// setup javascript VMs
|
||||
configureJavascript(conf.Javascript)
|
||||
|
||||
// start broadcasting values
|
||||
tee := &Tee{}
|
||||
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import (
|
|||
|
||||
"github.com/andig/evcc/core"
|
||||
"github.com/andig/evcc/hems"
|
||||
"github.com/andig/evcc/provider/javascript"
|
||||
"github.com/andig/evcc/provider/mqtt"
|
||||
"github.com/andig/evcc/push"
|
||||
"github.com/andig/evcc/server"
|
||||
|
|
@ -57,6 +58,13 @@ func configureMQTT(conf mqttConfig) {
|
|||
}
|
||||
}
|
||||
|
||||
// setup javascript
|
||||
func configureJavascript(conf map[string]interface{}) {
|
||||
if err := javascript.Configure(conf); err != nil {
|
||||
log.FATAL.Fatalf("failed configuring javascript: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// setup HEMS
|
||||
func configureHEMS(conf typedConfig, site *core.Site, cache *util.Cache, httpd *server.HTTPd) hems.HEMS {
|
||||
hems, err := hems.NewFromConfig(conf.Type, conf.Other, site, cache, httpd)
|
||||
|
|
|
|||
|
|
@ -1,6 +1,9 @@
|
|||
package provider
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/andig/evcc/provider/javascript"
|
||||
"github.com/andig/evcc/util"
|
||||
"github.com/robertkrimen/otto"
|
||||
)
|
||||
|
|
@ -19,6 +22,7 @@ func init() {
|
|||
// NewJavascriptProviderFromConfig creates a HTTP provider
|
||||
func NewJavascriptProviderFromConfig(other map[string]interface{}) (IntProvider, error) {
|
||||
cc := struct {
|
||||
VM string
|
||||
Script string
|
||||
}{}
|
||||
|
||||
|
|
@ -28,9 +32,11 @@ func NewJavascriptProviderFromConfig(other map[string]interface{}) (IntProvider,
|
|||
|
||||
log := util.NewLogger("js")
|
||||
|
||||
vm := javascript.RegisteredVM(strings.ToLower(cc.VM))
|
||||
|
||||
p := &Javascript{
|
||||
log: log,
|
||||
vm: otto.New(),
|
||||
vm: vm,
|
||||
script: cc.Script,
|
||||
}
|
||||
|
||||
|
|
@ -85,10 +91,21 @@ func (p *Javascript) BoolGetter() func() (bool, error) {
|
|||
}
|
||||
}
|
||||
|
||||
func (p *Javascript) setParam(param string, val interface{}) error {
|
||||
err := p.vm.Set(param, val)
|
||||
if err == nil {
|
||||
err = p.vm.Set("param", param)
|
||||
}
|
||||
if err == nil {
|
||||
err = p.vm.Set("val", val)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// IntSetter sends int request
|
||||
func (p *Javascript) IntSetter(param string) func(int64) error {
|
||||
return func(val int64) error {
|
||||
err := p.vm.Set(param, val)
|
||||
err := p.setParam(param, val)
|
||||
if err == nil {
|
||||
_, err = p.vm.Eval(p.script)
|
||||
}
|
||||
|
|
@ -99,7 +116,7 @@ func (p *Javascript) IntSetter(param string) func(int64) error {
|
|||
// StringSetter sends string request
|
||||
func (p *Javascript) StringSetter(param string) func(string) error {
|
||||
return func(val string) error {
|
||||
err := p.vm.Set(param, val)
|
||||
err := p.setParam(param, val)
|
||||
if err == nil {
|
||||
_, err = p.vm.Eval(p.script)
|
||||
}
|
||||
|
|
@ -110,7 +127,7 @@ func (p *Javascript) StringSetter(param string) func(string) error {
|
|||
// BoolSetter sends bool request
|
||||
func (p *Javascript) BoolSetter(param string) func(bool) error {
|
||||
return func(val bool) error {
|
||||
err := p.vm.Set(param, val)
|
||||
err := p.setParam(param, val)
|
||||
if err == nil {
|
||||
_, err = p.vm.Eval(p.script)
|
||||
}
|
||||
|
|
|
|||
56
provider/javascript/init.go
Normal file
56
provider/javascript/init.go
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
package javascript
|
||||
|
||||
import (
|
||||
"github.com/andig/evcc/util"
|
||||
"github.com/robertkrimen/otto"
|
||||
)
|
||||
|
||||
// Configure initializes JS VMs
|
||||
func Configure(other map[string]interface{}) error {
|
||||
cc := []struct {
|
||||
VM string
|
||||
Script string
|
||||
}{}
|
||||
|
||||
if err := util.DecodeOther(other, &cc); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// init all VMs that require it
|
||||
for _, conf := range cc {
|
||||
if conf.Script == "" {
|
||||
continue
|
||||
}
|
||||
|
||||
if _, ok := registry[conf.VM]; !ok {
|
||||
vm := otto.New()
|
||||
|
||||
_, err := vm.Run(conf.Script)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
registry[conf.VM] = vm
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
var registry = make(map[string]*otto.Otto)
|
||||
|
||||
// RegisteredVM returns a JS VM. If name is not empty, it will return a shared instance.
|
||||
func RegisteredVM(name string) *otto.Otto {
|
||||
vm, ok := registry[name]
|
||||
|
||||
// create new VM
|
||||
if !ok {
|
||||
vm = otto.New()
|
||||
|
||||
if name != "" {
|
||||
registry[name] = vm
|
||||
}
|
||||
}
|
||||
|
||||
return vm
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue