Improve target charging and refactor loadpoint and site apis (#1470)

This commit is contained in:
andig 2021-09-02 14:16:05 +02:00 • committed by GitHub
parent 7f2eddeab1
commit 3986b75b08
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
20 changed files with 204 additions and 180 deletions

View file

@ -24,7 +24,7 @@ import (
"github.com/evcc-io/evcc/api"
"github.com/evcc-io/evcc/charger/easee"
"github.com/evcc-io/evcc/core"
"github.com/evcc-io/evcc/core/loadpoint"
"github.com/evcc-io/evcc/util"
"github.com/evcc-io/evcc/util/request"
"github.com/evcc-io/evcc/util/sponsor"
@ -40,7 +40,7 @@ type Easee struct {
status easee.ChargerStatus
updated time.Time
cache time.Duration
lp core.LoadPointAPI
lp loadpoint.API
//lastSmartCharging bool
//lastChargeMode api.ChargeMode
log *util.Logger
@ -348,9 +348,9 @@ func (c *Easee) Currents() (float64, float64, float64, error) {
err
}
var _ core.LoadpointController = (*Easee)(nil)
var _ loadpoint.Controller = (*Easee)(nil)
// LoadpointControl implements core.LoadpointController
func (c *Easee) LoadpointControl(lp core.LoadPointAPI) {
// LoadpointControl implements loadpoint.Controller
func (c *Easee) LoadpointControl(lp loadpoint.API) {
c.lp = lp
}

View file

@ -11,7 +11,7 @@ import (
"github.com/evcc-io/eebus/ship"
"github.com/evcc-io/eebus/spine"
"github.com/evcc-io/evcc/api"
"github.com/evcc-io/evcc/core"
"github.com/evcc-io/evcc/core/loadpoint"
"github.com/evcc-io/evcc/server"
"github.com/evcc-io/evcc/util"
)
@ -19,7 +19,7 @@ import (
type EEBus struct {
log *util.Logger
cc *communication.ConnectionController
lp core.LoadPointAPI
lp loadpoint.API
forcePVLimits bool
communicationStandard communication.EVCommunicationStandardEnumType
@ -517,10 +517,10 @@ func (c *EEBus) SoC() (float64, error) {
return data.EVData.Measurements.SoC, nil
}
var _ core.LoadpointController = (*EEBus)(nil)
var _ loadpoint.Controller = (*EEBus)(nil)
// LoadpointControl implements core.LoadpointController
func (c *EEBus) LoadpointControl(lp core.LoadPointAPI) {
// LoadpointControl implements loadpoint.Controller
func (c *EEBus) LoadpointControl(lp loadpoint.API) {
c.lp = lp
// set current known min, max current limits

View file

@ -12,6 +12,7 @@ import (
"github.com/evcc-io/evcc/api"
"github.com/evcc-io/evcc/api/proto/pb"
"github.com/evcc-io/evcc/core"
"github.com/evcc-io/evcc/core/loadpoint"
"github.com/evcc-io/evcc/hems"
"github.com/evcc-io/evcc/provider/javascript"
"github.com/evcc-io/evcc/provider/mqtt"
@ -94,8 +95,8 @@ func configureSponsorship(token string) error {
return err
}
// setup influx databases
func configureDatabase(conf server.InfluxConfig, loadPoints []core.LoadPointAPI, in <-chan util.Param) {
// setup influx database
func configureDatabase(conf server.InfluxConfig, loadPoints []loadpoint.API, in <-chan util.Param) {
influx := server.NewInfluxClient(
conf.URL,
conf.Token,

View file

@ -10,6 +10,7 @@ import (
"time"
"github.com/evcc-io/evcc/api"
"github.com/evcc-io/evcc/core/loadpoint"
"github.com/evcc-io/evcc/core/soc"
"github.com/evcc-io/evcc/core/wrapper"
"github.com/evcc-io/evcc/provider"
@ -120,13 +121,13 @@ type LoadPoint struct {
socTimer *soc.Timer
// cached state
status api.ChargeStatus // Charger status
remoteDemand RemoteDemand // External status demand
chargePower float64 // Charging power
chargeCurrents []float64 // Phase currents
connectedTime time.Time // Time when vehicle was connected
pvTimer time.Time // PV enabled/disable timer
phaseTimer time.Time // 1p3p switch timer
status api.ChargeStatus // Charger status
remoteDemand loadpoint.RemoteDemand // External status demand
chargePower float64 // Charging power
chargeCurrents []float64 // Phase currents
connectedTime time.Time // Time when vehicle was connected
pvTimer time.Time // PV enabled/disable timer
phaseTimer time.Time // 1p3p switch timer
vehicleSoc float64 // Vehicle SoC
chargedEnergy float64 // Charged energy while connected in Wh
@ -201,7 +202,7 @@ func NewLoadPointFromConfig(log *util.Logger, cp configProvider, other map[strin
lp.configureChargerType(lp.charger)
// allow target charge handler to access loadpoint
lp.socTimer = soc.NewTimer(lp.log, lp.adapter(), lp.MaxCurrent)
lp.socTimer = soc.NewTimer(lp.log, &adapter{LoadPoint: lp})
if lp.Enable.Threshold > lp.Disable.Threshold {
log.WARN.Printf("PV mode enable threshold (%.0fW) is larger than disable threshold (%.0fW)", lp.Enable.Threshold, lp.Disable.Threshold)
} else if lp.Enable.Threshold > 0 {
@ -454,7 +455,7 @@ func (lp *LoadPoint) Prepare(uiChan chan<- util.Param, pushChan chan<- push.Even
}
// allow charger to access loadpoint
if ctrl, ok := lp.charger.(LoadpointController); ok {
if ctrl, ok := lp.charger.(loadpoint.Controller); ok {
ctrl.LoadpointControl(lp)
}
}
@ -602,7 +603,7 @@ func (lp *LoadPoint) climateActive() bool {
}
// remoteControlled returns true if remote control status is active
func (lp *LoadPoint) remoteControlled(demand RemoteDemand) bool {
func (lp *LoadPoint) remoteControlled(demand loadpoint.RemoteDemand) bool {
lp.Lock()
defer lp.Unlock()
@ -1245,7 +1246,7 @@ func (lp *LoadPoint) Update(sitePower float64, cheap bool) {
var err error
// track if remote disabled is actually active
remoteDisabled := RemoteEnable
remoteDisabled := loadpoint.RemoteEnable
// execute loading strategy
switch {
@ -1265,8 +1266,8 @@ func (lp *LoadPoint) Update(sitePower float64, cheap bool) {
lp.socTimer.Reset() // once SoC is reached, the target charge request is removed
// OCPP has priority over target charging
case lp.remoteControlled(RemoteHardDisable):
remoteDisabled = RemoteHardDisable
case lp.remoteControlled(loadpoint.RemoteHardDisable):
remoteDisabled = loadpoint.RemoteHardDisable
fallthrough
case mode == api.ModeOff:
@ -1286,9 +1287,9 @@ func (lp *LoadPoint) Update(sitePower float64, cheap bool) {
}
// target charging
case lp.socTimer.StartRequired():
case lp.socTimer.DemandActive():
targetCurrent := lp.socTimer.Handle()
err = lp.setLimit(targetCurrent, false)
err = lp.setLimit(targetCurrent, true)
case mode == api.ModeMinPV || mode == api.ModePV:
targetCurrent := lp.pvMaxCurrent(mode, sitePower)
@ -1308,8 +1309,8 @@ func (lp *LoadPoint) Update(sitePower float64, cheap bool) {
}
// Sunny Home Manager
if lp.remoteControlled(RemoteSoftDisable) {
remoteDisabled = RemoteSoftDisable
if lp.remoteControlled(loadpoint.RemoteSoftDisable) {
remoteDisabled = loadpoint.RemoteSoftDisable
targetCurrent = 0
required = true
}
@ -1318,7 +1319,7 @@ func (lp *LoadPoint) Update(sitePower float64, cheap bool) {
}
// effective disabled status
if remoteDisabled != RemoteEnable {
if remoteDisabled != loadpoint.RemoteEnable {
lp.publish("remoteDisabled", remoteDisabled)
}

43
core/loadpoint/api.go Normal file
View file

@ -0,0 +1,43 @@
package loadpoint
import (
"time"
"github.com/evcc-io/evcc/api"
)
// Controller gives access to loadpoint
type Controller interface {
LoadpointControl(API)
}
// API is the external loadpoint API
type API interface {
Name() string
HasChargeMeter() bool
// status
GetStatus() api.ChargeStatus
// settings
GetMode() api.ChargeMode
SetMode(api.ChargeMode)
GetTargetSoC() int
SetTargetSoC(int) error
GetMinSoC() int
SetMinSoC(int) error
GetPhases() int
SetPhases(int) error
SetTargetCharge(time.Time, int)
RemoteControl(string, RemoteDemand)
// energy
GetChargePower() float64
GetMinCurrent() float64
SetMinCurrent(float64)
GetMaxCurrent() float64
SetMaxCurrent(float64)
GetMinPower() float64
GetMaxPower() float64
}

View file

@ -1,4 +1,4 @@
package core
package loadpoint
import "strings"

View file

@ -1,27 +1,19 @@
package core
import "github.com/evcc-io/evcc/core/soc"
import (
"github.com/evcc-io/evcc/core/soc"
)
var _ soc.Adapter = (*adapter)(nil)
type adapter struct {
lp *LoadPoint
}
func (lp *LoadPoint) adapter() soc.Adapter {
return &adapter{lp: lp}
*LoadPoint
}
func (a *adapter) Publish(key string, val interface{}) {
a.lp.publish(key, val)
a.LoadPoint.publish(key, val)
}
func (a *adapter) SocEstimator() *soc.Estimator {
return a.lp.socEstimator
}
func (a *adapter) ActivePhases() int {
return a.lp.activePhases
}
func (a *adapter) Voltage() float64 {
return Voltage
return a.LoadPoint.socEstimator
}

View file

@ -4,43 +4,11 @@ import (
"time"
"github.com/evcc-io/evcc/api"
"github.com/evcc-io/evcc/core/loadpoint"
"github.com/evcc-io/evcc/core/wrapper"
)
// LoadpointController gives access to loadpoint
type LoadpointController interface {
LoadpointControl(LoadPointAPI)
}
// LoadPointAPI is the external loadpoint API
type LoadPointAPI interface {
Name() string
HasChargeMeter() bool
// status
GetStatus() api.ChargeStatus
// settings
GetMode() api.ChargeMode
SetMode(api.ChargeMode)
GetTargetSoC() int
SetTargetSoC(int) error
GetMinSoC() int
SetMinSoC(int) error
GetPhases() int
SetPhases(int) error
SetTargetCharge(time.Time, int)
RemoteControl(string, RemoteDemand)
// energy
GetChargePower() float64
GetMinCurrent() float64
SetMinCurrent(float64)
GetMaxCurrent() float64
SetMaxCurrent(float64)
GetMinPower() float64
GetMaxPower() float64
}
var _ loadpoint.API = (*LoadPoint)(nil)
// GetStatus returns the charging status
func (lp *LoadPoint) GetStatus() api.ChargeStatus {
@ -163,7 +131,7 @@ func (lp *LoadPoint) SetTargetCharge(finishAt time.Time, targetSoC int) {
}
// RemoteControl sets remote status demand
func (lp *LoadPoint) RemoteControl(source string, demand RemoteDemand) {
func (lp *LoadPoint) RemoteControl(source string, demand loadpoint.RemoteDemand) {
lp.Lock()
defer lp.Unlock()

View file

@ -9,6 +9,7 @@ import (
"github.com/avast/retry-go/v3"
"github.com/evcc-io/evcc/api"
"github.com/evcc-io/evcc/core/loadpoint"
"github.com/evcc-io/evcc/push"
"github.com/evcc-io/evcc/util"
)
@ -105,8 +106,8 @@ func NewSite() *Site {
}
// LoadPoints returns the array of associated loadpoints
func (site *Site) LoadPoints() []LoadPointAPI {
res := make([]LoadPointAPI, len(site.loadpoints))
func (site *Site) LoadPoints() []loadpoint.API {
res := make([]loadpoint.API, len(site.loadpoints))
for id, lp := range site.loadpoints {
res[id] = lp
}

10
core/site/api.go Normal file
View file

@ -0,0 +1,10 @@
package site
import "github.com/evcc-io/evcc/core/loadpoint"
// API is the external site API
type API interface {
Healthy() bool
LoadPoints() []loadpoint.API
SetPrioritySoC(float64) error
}

View file

@ -4,14 +4,10 @@ import (
"errors"
"github.com/evcc-io/evcc/api"
"github.com/evcc-io/evcc/core/site"
)
// SiteAPI is the external site API
type SiteAPI interface {
Healthy() bool
LoadPoints() []LoadPointAPI
SetPrioritySoC(float64) error
}
var _ site.API = (*Site)(nil)
// GetPrioritySoC returns the PrioritySoC
func (site *Site) GetPrioritySoC() float64 {

View file

@ -4,10 +4,6 @@ import (
"testing"
)
func TestSiteApi(t *testing.T) {
var _ SiteAPI = NewSite()
}
func TestSitePower(t *testing.T) {
tc := []struct {
grid, battery, site float64

View file

@ -1,9 +1,10 @@
package soc
import "github.com/evcc-io/evcc/core/loadpoint"
// Adapter provides the required methods for interacting with the loadpoint
type Adapter interface {
loadpoint.API
Publish(key string, val interface{})
SocEstimator() *Estimator
ActivePhases() int
Voltage() float64
}

View file

@ -4,6 +4,7 @@ import (
"math"
"time"
"github.com/evcc-io/evcc/api"
"github.com/evcc-io/evcc/util"
)
@ -14,21 +15,19 @@ const (
// Timer is the target charging handler
type Timer struct {
Adapter
log *util.Logger
maxCurrent float64
current float64
SoC int
Time time.Time
finishAt time.Time
chargeRequired bool
log *util.Logger
current float64
SoC int
Time time.Time
finishAt time.Time
active bool
}
// NewTimer creates a Timer
func NewTimer(log *util.Logger, adapter Adapter, maxCurrent float64) *Timer {
func NewTimer(log *util.Logger, api Adapter) *Timer {
lp := &Timer{
log: log,
Adapter: adapter,
maxCurrent: maxCurrent,
log: log,
Adapter: api,
}
return lp
@ -40,62 +39,74 @@ func (lp *Timer) Reset() {
return
}
lp.current = float64(lp.maxCurrent)
lp.current = float64(lp.GetMaxCurrent())
lp.Time = time.Time{}
lp.SoC = 0
}
// StartRequired calculates remaining charge duration and returns true if charge start is required to achieve target soc in time
func (lp *Timer) StartRequired() bool {
// DemandActive calculates remaining charge duration and returns true if charge start is required to achieve target soc in time
func (lp *Timer) DemandActive() bool {
if lp == nil {
return false
}
se := lp.SocEstimator()
if !lp.active() || se == nil {
if se == nil {
lp.log.WARN.Printf("target charging: not possible")
return false
}
power := float64(lp.ActivePhases()) * lp.maxCurrent * lp.Voltage()
defer func() {
lp.Publish("timerSet", lp.Time.After(time.Now()))
lp.Publish("timerActive", lp.active)
lp.Publish("timerProjectedEnd", lp.finishAt)
}()
// power
power := lp.GetMaxPower()
if lp.active {
power *= lp.current / lp.GetMaxCurrent()
}
// time
remainingDuration := se.RemainingChargeDuration(power, lp.SoC)
lp.finishAt = time.Now().Add(remainingDuration).Round(time.Minute)
lp.log.DEBUG.Printf("target charging active for %v: projected %v (%v remaining)", lp.Time, lp.finishAt, remainingDuration.Round(time.Minute))
lp.chargeRequired = lp.finishAt.After(lp.Time)
lp.Publish("timerActive", lp.chargeRequired)
// timer charging is already active- only deactivate once charging has stopped
if lp.active {
if time.Now().After(lp.Time) && lp.GetStatus() != api.StatusC {
lp.log.TRACE.Printf("target charging: deactivating")
lp.active = false
}
return lp.chargeRequired
}
// active returns true if there is an active target charging request
func (lp *Timer) active() bool {
inactive := lp.Time.IsZero() || lp.Time.Before(time.Now())
lp.Publish("timerSet", !inactive)
// reset active
if inactive && lp.chargeRequired {
lp.chargeRequired = false
lp.Publish("timerActive", lp.chargeRequired)
return lp.active
}
return !inactive
// check if charging need be activated
if lp.active = lp.finishAt.After(lp.Time); lp.active {
lp.current = lp.GetMaxCurrent()
lp.log.DEBUG.Printf("target charging active for %v: projected %v (%v remaining)", lp.Time, lp.finishAt, remainingDuration.Round(time.Minute))
}
return lp.active
}
// Handle adjusts current up/down to achieve desired target time taking.
func (lp *Timer) Handle() float64 {
action := "steady"
switch {
case lp.finishAt.Before(lp.Time.Add(-deviation)):
lp.current--
lp.log.DEBUG.Printf("target charging: slowdown")
action = "slowdown"
case lp.finishAt.After(lp.Time):
lp.current++
lp.log.DEBUG.Printf("target charging: speedup")
action = "speedup"
}
lp.current = math.Max(math.Min(lp.current, float64(lp.maxCurrent)), 0)
lp.current = math.Max(math.Min(lp.current, lp.GetMaxCurrent()), lp.GetMinCurrent())
lp.log.DEBUG.Printf("target charging: %s (%.3gA)", action, lp.current)
return lp.current
}

View file

@ -6,12 +6,12 @@ import (
"strings"
"time"
"github.com/denisbrodbeck/machineid"
"github.com/evcc-io/evcc/api"
"github.com/evcc-io/evcc/core"
"github.com/evcc-io/evcc/core/site"
"github.com/evcc-io/evcc/hems/ocpp/profile"
"github.com/evcc-io/evcc/util"
"github.com/denisbrodbeck/machineid"
ocpp16 "github.com/lorenzodonini/ocpp-go/ocpp1.6"
ocppcore "github.com/lorenzodonini/ocpp-go/ocpp1.6/core"
"github.com/lorenzodonini/ocpp-go/ws"
@ -21,14 +21,14 @@ import (
type OCPP struct {
log *util.Logger
cache *util.Cache
site core.SiteAPI
site site.API
cp ocpp16.ChargePoint
}
const retryTimeout = 5 * time.Second
// New generates OCPP chargepoint client
func New(conf map[string]interface{}, site core.SiteAPI, cache *util.Cache) (*OCPP, error) {
func New(conf map[string]interface{}, site site.API, cache *util.Cache) (*OCPP, error) {
cc := struct {
URI string
StationID string

View file

@ -14,7 +14,8 @@ import (
"github.com/denisbrodbeck/machineid"
"github.com/evcc-io/evcc/api"
"github.com/evcc-io/evcc/core"
"github.com/evcc-io/evcc/core/loadpoint"
"github.com/evcc-io/evcc/core/site"
"github.com/evcc-io/evcc/server"
"github.com/evcc-io/evcc/util"
"github.com/google/uuid"
@ -49,11 +50,11 @@ type SEMP struct {
uid string
hostURI string
port int
site core.SiteAPI
site site.API
}
// New generates SEMP Gateway listening at /semp endpoint
func New(conf map[string]interface{}, site core.SiteAPI, cache *util.Cache, httpd *server.HTTPd) (*SEMP, error) {
func New(conf map[string]interface{}, site site.API, cache *util.Cache, httpd *server.HTTPd) (*SEMP, error) {
cc := struct {
VendorID string
DeviceID string
@ -363,7 +364,7 @@ func (s *SEMP) deviceID(id int) string {
return fmt.Sprintf(sempDeviceId, s.vid, ^uint64(0xffff<<48)&(binary.BigEndian.Uint64(did)+uint64(id)))
}
func (s *SEMP) deviceInfo(id int, lp core.LoadPointAPI) DeviceInfo {
func (s *SEMP) deviceInfo(id int, lp loadpoint.API) DeviceInfo {
method := MethodEstimation
if lp.HasChargeMeter() {
method = MethodMeasurement
@ -399,7 +400,7 @@ func (s *SEMP) allDeviceInfo() (res []DeviceInfo) {
return res
}
func (s *SEMP) deviceStatus(id int, lp core.LoadPointAPI) DeviceStatus {
func (s *SEMP) deviceStatus(id int, lp loadpoint.API) DeviceStatus {
chargePower := lp.GetChargePower()
mode := lp.GetMode()
@ -438,7 +439,7 @@ func (s *SEMP) allDeviceStatus() (res []DeviceStatus) {
// TODO remove GetChecked function
func (s *SEMP) planningRequest(id int, lp core.LoadPointAPI) (res PlanningRequest) {
func (s *SEMP) planningRequest(id int, lp loadpoint.API) (res PlanningRequest) {
mode := lp.GetMode()
charging := lp.GetStatus() == api.StatusC
connected := charging || lp.GetStatus() == api.StatusB
@ -531,9 +532,9 @@ func (s *SEMP) deviceControlHandler(w http.ResponseWriter, r *http.Request) {
return
}
demand := core.RemoteSoftDisable
demand := loadpoint.RemoteSoftDisable
if dev.On {
demand = core.RemoteEnable
demand = loadpoint.RemoteEnable
}
lp.RemoteControl(sempController, demand)

View file

@ -11,7 +11,8 @@ import (
"time"
"github.com/evcc-io/evcc/api"
"github.com/evcc-io/evcc/core"
"github.com/evcc-io/evcc/core/loadpoint"
"github.com/evcc-io/evcc/core/site"
"github.com/evcc-io/evcc/util"
"github.com/evcc-io/evcc/util/test"
"github.com/gorilla/handlers"
@ -61,7 +62,7 @@ func routeLogger(inner http.Handler) http.HandlerFunc {
}
}
func indexHandler(site core.SiteAPI) http.HandlerFunc {
func indexHandler(site site.API) http.HandlerFunc {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "text/html; charset=UTF-8")
@ -102,7 +103,7 @@ func jsonResponse(w http.ResponseWriter, r *http.Request, content interface{}) {
}
// HealthHandler returns current charge mode
func HealthHandler(site core.SiteAPI) http.HandlerFunc {
func HealthHandler(site site.API) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
if !site.Healthy() {
w.WriteHeader(http.StatusInternalServerError)
@ -155,15 +156,15 @@ func StateHandler(cache *util.Cache) http.HandlerFunc {
}
// CurrentChargeModeHandler returns current charge mode
func CurrentChargeModeHandler(loadpoint core.LoadPointAPI) http.HandlerFunc {
func CurrentChargeModeHandler(lp loadpoint.API) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
res := chargeModeJSON{Mode: loadpoint.GetMode()}
res := chargeModeJSON{Mode: lp.GetMode()}
jsonResponse(w, r, res)
}
}
// ChargeModeHandler updates charge mode
func ChargeModeHandler(loadpoint core.LoadPointAPI) http.HandlerFunc {
func ChargeModeHandler(lp loadpoint.API) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
@ -176,23 +177,23 @@ func ChargeModeHandler(loadpoint core.LoadPointAPI) http.HandlerFunc {
return
}
loadpoint.SetMode(mode)
lp.SetMode(mode)
res := chargeModeJSON{Mode: loadpoint.GetMode()}
res := chargeModeJSON{Mode: lp.GetMode()}
jsonResponse(w, r, res)
}
}
// CurrentTargetSoCHandler returns current target soc
func CurrentTargetSoCHandler(loadpoint core.LoadPointAPI) http.HandlerFunc {
func CurrentTargetSoCHandler(lp loadpoint.API) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
res := targetSoCJSON{TargetSoC: loadpoint.GetTargetSoC()}
res := targetSoCJSON{TargetSoC: lp.GetTargetSoC()}
jsonResponse(w, r, res)
}
}
// TargetSoCHandler updates target soc
func TargetSoCHandler(loadpoint core.LoadPointAPI) http.HandlerFunc {
func TargetSoCHandler(lp loadpoint.API) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
@ -200,7 +201,7 @@ func TargetSoCHandler(loadpoint core.LoadPointAPI) http.HandlerFunc {
soc, err := strconv.ParseInt(socS, 10, 32)
if err == nil {
err = loadpoint.SetTargetSoC(int(soc))
err = lp.SetTargetSoC(int(soc))
}
if err != nil {
@ -209,21 +210,21 @@ func TargetSoCHandler(loadpoint core.LoadPointAPI) http.HandlerFunc {
return
}
res := targetSoCJSON{TargetSoC: loadpoint.GetTargetSoC()}
res := targetSoCJSON{TargetSoC: lp.GetTargetSoC()}
jsonResponse(w, r, res)
}
}
// CurrentMinSoCHandler returns current minimum soc
func CurrentMinSoCHandler(loadpoint core.LoadPointAPI) http.HandlerFunc {
func CurrentMinSoCHandler(lp loadpoint.API) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
res := minSoCJSON{MinSoC: loadpoint.GetMinSoC()}
res := minSoCJSON{MinSoC: lp.GetMinSoC()}
jsonResponse(w, r, res)
}
}
// MinSoCHandler updates minimum soc
func MinSoCHandler(loadpoint core.LoadPointAPI) http.HandlerFunc {
func MinSoCHandler(lp loadpoint.API) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
@ -231,7 +232,7 @@ func MinSoCHandler(loadpoint core.LoadPointAPI) http.HandlerFunc {
soc, err := strconv.ParseInt(socS, 10, 32)
if err == nil {
err = loadpoint.SetMinSoC(int(soc))
err = lp.SetMinSoC(int(soc))
}
if err != nil {
@ -240,21 +241,21 @@ func MinSoCHandler(loadpoint core.LoadPointAPI) http.HandlerFunc {
return
}
res := minSoCJSON{MinSoC: loadpoint.GetMinSoC()}
res := minSoCJSON{MinSoC: lp.GetMinSoC()}
jsonResponse(w, r, res)
}
}
// CurrentPhasesHandler returns current minimum soc
func CurrentPhasesHandler(loadpoint core.LoadPointAPI) http.HandlerFunc {
func CurrentPhasesHandler(lp loadpoint.API) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
res := phasesJSON{Phases: loadpoint.GetPhases()}
res := phasesJSON{Phases: lp.GetPhases()}
jsonResponse(w, r, res)
}
}
// PhasesHandler updates minimum soc
func PhasesHandler(loadpoint core.LoadPointAPI) http.HandlerFunc {
func PhasesHandler(lp loadpoint.API) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
@ -262,7 +263,7 @@ func PhasesHandler(loadpoint core.LoadPointAPI) http.HandlerFunc {
phases, err := strconv.ParseInt(phasesS, 10, 32)
if err == nil {
err = loadpoint.SetPhases(int(phases))
err = lp.SetPhases(int(phases))
}
if err != nil {
@ -271,13 +272,13 @@ func PhasesHandler(loadpoint core.LoadPointAPI) http.HandlerFunc {
return
}
res := phasesJSON{Phases: loadpoint.GetPhases()}
res := phasesJSON{Phases: lp.GetPhases()}
jsonResponse(w, r, res)
}
}
// RemoteDemandHandler updates minimum soc
func RemoteDemandHandler(loadpoint core.LoadPointAPI) http.HandlerFunc {
func RemoteDemandHandler(lp loadpoint.API) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
@ -288,7 +289,7 @@ func RemoteDemandHandler(loadpoint core.LoadPointAPI) http.HandlerFunc {
source, ok = vars["source"]
}
demand, err := core.RemoteDemandString(demandS)
demand, err := loadpoint.RemoteDemandString(demandS)
if !ok || err != nil {
w.WriteHeader(http.StatusBadRequest)
@ -296,11 +297,11 @@ func RemoteDemandHandler(loadpoint core.LoadPointAPI) http.HandlerFunc {
return
}
loadpoint.RemoteControl(source, demand)
lp.RemoteControl(source, demand)
res := struct {
Demand core.RemoteDemand `json:"demand"`
Source string `json:"source"`
Demand loadpoint.RemoteDemand `json:"demand"`
Source string `json:"source"`
}{
Source: source,
Demand: demand,
@ -321,7 +322,7 @@ func timezone() *time.Location {
}
// TargetChargeHandler updates target soc
func TargetChargeHandler(loadpoint core.LoadPointAPI) http.HandlerFunc {
func TargetChargeHandler(loadpoint loadpoint.API) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
@ -369,7 +370,7 @@ type HTTPd struct {
}
// NewHTTPd creates HTTP server with configured routes for loadpoint
func NewHTTPd(url string, site core.SiteAPI, hub *SocketHub, cache *util.Cache) *HTTPd {
func NewHTTPd(url string, site site.API, hub *SocketHub, cache *util.Cache) *HTTPd {
routes := map[string]route{
"health": {[]string{"GET"}, "/health", HealthHandler(site)},
"state": {[]string{"GET"}, "/state", StateHandler(cache)},

View file

@ -5,7 +5,7 @@ import (
"sync"
"time"
"github.com/evcc-io/evcc/core"
"github.com/evcc-io/evcc/core/loadpoint"
"github.com/evcc-io/evcc/util"
influxdb2 "github.com/influxdata/influxdb-client-go/v2"
influxlog "github.com/influxdata/influxdb-client-go/v2/log"
@ -73,7 +73,7 @@ func (m *Influx) supportedType(p util.Param) bool {
}
// Run Influx publisher
func (m *Influx) Run(loadPoints []core.LoadPointAPI, in <-chan util.Param) {
func (m *Influx) Run(loadPoints []loadpoint.API, in <-chan util.Param) {
writer := m.client.WriteAPI(m.org, m.database)
// log errors

View file

@ -6,7 +6,8 @@ import (
"time"
"github.com/evcc-io/evcc/api"
"github.com/evcc-io/evcc/core"
"github.com/evcc-io/evcc/core/loadpoint"
"github.com/evcc-io/evcc/core/site"
"github.com/evcc-io/evcc/provider/mqtt"
"github.com/evcc-io/evcc/util"
)
@ -64,7 +65,7 @@ func (m *MQTT) publish(topic string, retained bool, payload interface{}) {
m.publishSingleValue(topic, retained, payload)
}
func (m *MQTT) listenSetters(topic string, apiHandler core.LoadPointAPI) {
func (m *MQTT) listenSetters(topic string, apiHandler loadpoint.API) {
m.Handler.Listen(topic+"/mode/set", func(payload string) {
apiHandler.SetMode(api.ChargeMode(payload))
})
@ -89,7 +90,7 @@ func (m *MQTT) listenSetters(topic string, apiHandler core.LoadPointAPI) {
}
// Run starts the MQTT publisher for the MQTT API
func (m *MQTT) Run(site core.SiteAPI, in <-chan util.Param) {
func (m *MQTT) Run(site site.API, in <-chan util.Param) {
// alive
topic := fmt.Sprintf("%s/status", m.root)
m.publish(topic, true, "online")

View file

@ -1,3 +1,4 @@
//go:build !windows
// +build !windows
package server
@ -7,7 +8,7 @@ import (
"net/http"
"os"
"github.com/evcc-io/evcc/core"
"github.com/evcc-io/evcc/core/site"
)
// SocketPath is the unix domain socket path
@ -26,7 +27,7 @@ func remoteIfExists(file string) {
}
// HealthListener attaches listener to unix domain socket and runs listener
func HealthListener(site core.SiteAPI) {
func HealthListener(site site.API) {
remoteIfExists(SocketPath)
l, err := net.Listen("unix", SocketPath)