diff --git a/charger/abl.go b/charger/abl.go index 9a5953b2e9..c2f0f57c9f 100644 --- a/charger/abl.go +++ b/charger/abl.go @@ -3,7 +3,7 @@ package charger // LICENSE // Copyright (c) 2019-2022 andig -// Copyright (c) 2022 premultiply +// Copyright (c) 2022-2024 premultiply // This module is NOT covered by the MIT license. All rights reserved. @@ -157,15 +157,20 @@ func (wb *ABLeMH) Status() (api.ChargeStatus, error) { return api.StatusNone, err } - r := rune(b[1]>>4-0x0A) + 'A' + s := string(rune((b[1]>>4)-0x0A) + 'A') - switch r { - case 'A', 'B', 'C': - return api.ChargeStatus(r), nil + switch s { + case "A", "B", "C": + return api.ChargeStatusString(s) default: + // ensure Outlet is re-enabled after wake-up + if b[1] == 0xE0 { // Outlet is disabled + return api.StatusB, wb.set(ablRegModifyState, 0xA1A1) + } + status, ok := ablStatus[b[1]] if !ok { - status = string(r) + status = s } return api.StatusNone, fmt.Errorf("invalid status: %s", status) diff --git a/meter/zendure/connection.go b/meter/zendure/connection.go index da81946995..f1c7de9fe3 100644 --- a/meter/zendure/connection.go +++ b/meter/zendure/connection.go @@ -73,12 +73,10 @@ func (c *Connection) handler(data string) { } c.data.SetFunc(func(v Data) Data { - if err := mergo.Merge(&v, res.Data); err != nil { + if err := mergo.Merge(&v, res.Data, mergo.WithOverride); err != nil { c.log.ERROR.Println(err) } - c.log.TRACE.Printf("!! data: %+v", v) - return v }) } diff --git a/meter/zendure/connection_test.go b/meter/zendure/connection_test.go new file mode 100644 index 0000000000..12eb9bfb21 --- /dev/null +++ b/meter/zendure/connection_test.go @@ -0,0 +1,31 @@ +package zendure + +import ( + "testing" + "time" + + "github.com/evcc-io/evcc/util" + "github.com/stretchr/testify/assert" +) + +func TestHandler(t *testing.T) { + conn := &Connection{ + log: util.NewLogger("test"), + data: util.NewMonitor[Data](time.Minute), + } + + { + conn.handler(`{"solarInputPower":113,"sn":"serial"}`) + res, err := conn.data.Get() + assert.NoError(t, err) + + assert.Equal(t, Data{SolarInputPower: 113, Sn: "serial"}, res) + } + { + conn.handler(`{"solarInputPower":125,"sn":"serial"}`) + res, err := conn.data.Get() + assert.NoError(t, err) + + assert.Equal(t, Data{SolarInputPower: 125, Sn: "serial"}, res) + } +} diff --git a/provider/golang/registry.go b/provider/golang/registry.go index 21d024f61c..72f0bcf235 100644 --- a/provider/golang/registry.go +++ b/provider/golang/registry.go @@ -8,13 +8,6 @@ import ( "github.com/traefik/yaegi/interp" ) -const Imports = `import ( - "fmt" - "math" - "strings" - "time" -)` - var ( mu sync.Mutex registry = make(map[string]*interp.Interpreter) @@ -31,14 +24,10 @@ func RegisteredVM(name, init string) (*interp.Interpreter, error) { // create new VM if !ok { vm = interp.New(interp.Options{}) - if err := vm.Use(stdlib.Symbols); err != nil { return nil, err } - - if _, err := vm.Eval(Imports); err != nil { - return nil, err - } + vm.ImportUsed() if init != "" { if _, err := vm.Eval(init); err != nil { diff --git a/tariff/embed.go b/tariff/embed.go index c9c523a39a..effc0213a7 100644 --- a/tariff/embed.go +++ b/tariff/embed.go @@ -5,7 +5,6 @@ import ( "fmt" "time" - "github.com/evcc-io/evcc/provider/golang" "github.com/evcc-io/evcc/provider/golang/stdlib" "github.com/traefik/yaegi/interp" ) @@ -29,35 +28,24 @@ func (t *embed) init() (err error) { return nil } - vm := interp.New(interp.Options{}) - if err := vm.Use(stdlib.Symbols); err != nil { - return err - } - - if _, err := vm.Eval(fmt.Sprintf(`%s - var ( - price float64 - charges float64 = %f - tax float64 = %f - ts time.Time - )`, golang.Imports, t.Charges, t.Tax)); err != nil { - return err - } - - prg, err := vm.Compile(t.Formula) - if err != nil { - return err - } - t.calc = func(price float64, ts time.Time) (float64, error) { + vm := interp.New(interp.Options{}) + if err := vm.Use(stdlib.Symbols); err != nil { + return 0, err + } + vm.ImportUsed() + if _, err := vm.Eval(fmt.Sprintf(` - price = %f + var ( + price float64 = %f + charges float64 = %f + tax float64 = %f ts = time.Unix(%d, 0).Local() - `, price, ts.Unix())); err != nil { + )`, price, t.Charges, t.Tax, ts.Unix())); err != nil { return 0, err } - res, err := vm.Execute(prg) + res, err := vm.Eval(t.Formula) if err != nil { return 0, err } diff --git a/vehicle/bmw/provider.go b/vehicle/bmw/provider.go index 6978347b2b..3c65beee9a 100644 --- a/vehicle/bmw/provider.go +++ b/vehicle/bmw/provider.go @@ -108,6 +108,14 @@ func (v *Provider) GetLimitSoc() (int64, error) { return res.State.ElectricChargingState.ChargingTarget, nil } +var _ api.VehicleClimater = (*Provider)(nil) + +// Climater implements the api.VehicleClimater interface +func (v *Provider) Climater() (bool, error) { + res, err := v.statusG() + return res.State.ClimateControlState.Activity == "HEATING" || res.State.ClimateControlState.Activity == "COOLING", err +} + var _ api.Resurrector = (*Provider)(nil) func (v *Provider) WakeUp() error { diff --git a/vehicle/bmw/types.go b/vehicle/bmw/types.go index 6d2f7aa7ca..5f8f07ec64 100644 --- a/vehicle/bmw/types.go +++ b/vehicle/bmw/types.go @@ -19,5 +19,8 @@ type VehicleStatus struct { ChargingStatus string ChargingTarget int64 } + ClimateControlState struct { + Activity string + } } }