Remove the vehicle climater feature (#1003)
This commit is contained in:
parent
96a0d4bdfc
commit
c7ff9087a6
11 changed files with 4 additions and 211 deletions
|
|
@ -115,11 +115,6 @@ type VehicleRange interface {
|
|||
Range() (int64, error)
|
||||
}
|
||||
|
||||
// VehicleClimater provides climatisation data
|
||||
type VehicleClimater interface {
|
||||
Climater() (active bool, outsideTemp float64, targetTemp float64, err error)
|
||||
}
|
||||
|
||||
// VehicleStartCharge starts the charging session on the vehicle side
|
||||
type VehicleStartCharge interface {
|
||||
StartCharge() error
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@ package cmd
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
"os"
|
||||
"strings"
|
||||
"text/tabwriter"
|
||||
|
|
@ -127,20 +126,6 @@ func (d *dumper) Dump(name string, v interface{}) {
|
|||
}
|
||||
}
|
||||
|
||||
if v, ok := v.(api.VehicleClimater); ok {
|
||||
if active, ot, tt, err := v.Climater(); err != nil {
|
||||
fmt.Fprintf(w, "Climater:\t%v\n", err)
|
||||
} else {
|
||||
fmt.Fprintf(w, "Climate active:\t%v\n", active)
|
||||
if !math.IsNaN(ot) {
|
||||
fmt.Fprintf(w, "Outside temp:\t%.1f°C\n", ot)
|
||||
}
|
||||
if !math.IsNaN(tt) {
|
||||
fmt.Fprintf(w, "Target temp:\t%.1f°C\n", tt)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Identity
|
||||
|
||||
if v, ok := v.(api.Identifier); ok {
|
||||
|
|
|
|||
|
|
@ -525,37 +525,6 @@ func (lp *LoadPoint) minSocNotReached() bool {
|
|||
lp.socCharge < float64(lp.SoC.Min)
|
||||
}
|
||||
|
||||
// climateActive checks if vehicle has active climate request
|
||||
func (lp *LoadPoint) climateActive() bool {
|
||||
if cl, ok := lp.vehicle.(api.VehicleClimater); ok {
|
||||
active, outsideTemp, targetTemp, err := cl.Climater()
|
||||
if err == nil {
|
||||
lp.log.DEBUG.Printf("climater active: %v, target temp: %.1f°C, outside temp: %.1f°C", active, targetTemp, outsideTemp)
|
||||
|
||||
status := "off"
|
||||
if active {
|
||||
status = "on"
|
||||
|
||||
switch {
|
||||
case outsideTemp < targetTemp:
|
||||
status = "heating"
|
||||
case outsideTemp > targetTemp:
|
||||
status = "cooling"
|
||||
}
|
||||
}
|
||||
|
||||
lp.publish("climater", status)
|
||||
return active
|
||||
}
|
||||
|
||||
if !errors.Is(err, api.ErrNotAvailable) {
|
||||
lp.log.ERROR.Printf("climater: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// remoteControlled returns true if remote control status is active
|
||||
func (lp *LoadPoint) remoteControlled(demand RemoteDemand) bool {
|
||||
lp.Lock()
|
||||
|
|
@ -974,12 +943,7 @@ func (lp *LoadPoint) Update(sitePower float64) {
|
|||
|
||||
case lp.targetSocReached():
|
||||
lp.log.DEBUG.Printf("targetSoC reached: %.1f > %d", lp.socCharge, lp.SoC.Target)
|
||||
var targetCurrent float64 // zero disables
|
||||
if lp.climateActive() {
|
||||
lp.log.DEBUG.Println("climater active")
|
||||
targetCurrent = float64(lp.MinCurrent)
|
||||
}
|
||||
err = lp.setLimit(targetCurrent, true)
|
||||
err = lp.setLimit(0, true)
|
||||
lp.socTimer.Reset() // once SoC is reached, the target charge request is removed
|
||||
|
||||
// OCPP has priority over target charging
|
||||
|
|
@ -1006,13 +970,8 @@ func (lp *LoadPoint) Update(sitePower float64) {
|
|||
targetCurrent := lp.pvMaxCurrent(mode, sitePower)
|
||||
lp.log.DEBUG.Printf("pv max charge current: %.2gA", targetCurrent)
|
||||
|
||||
var required bool // false
|
||||
if targetCurrent == 0 && lp.climateActive() {
|
||||
targetCurrent = float64(lp.MinCurrent)
|
||||
required = true
|
||||
}
|
||||
|
||||
// Sunny Home Manager
|
||||
var required bool // false
|
||||
if lp.remoteControlled(RemoteSoftDisable) {
|
||||
remoteDisabled = RemoteSoftDisable
|
||||
targetCurrent = 0
|
||||
|
|
|
|||
|
|
@ -190,9 +190,8 @@ func (site *Site) DumpConfig() {
|
|||
_, rng := v.(api.VehicleRange)
|
||||
_, finish := v.(api.VehicleFinishTimer)
|
||||
_, status := v.(api.ChargeState)
|
||||
_, climate := v.(api.VehicleClimater)
|
||||
lp.log.INFO.Printf(" car %d: range %s finish %s status %s climate %s",
|
||||
i, presence[rng], presence[finish], presence[status], presence[climate],
|
||||
lp.log.INFO.Printf(" car %d: range %s finish %s status %s",
|
||||
i, presence[rng], presence[finish], presence[status],
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -88,21 +88,3 @@ func (v *CarWings) hvacAPI() (interface{}, error) {
|
|||
func (v *CarWings) SoC() (float64, error) {
|
||||
return v.chargeStateG()
|
||||
}
|
||||
|
||||
var _ api.VehicleClimater = (*CarWings)(nil)
|
||||
|
||||
// Climater implements the api.Vehicle.Climater interface
|
||||
func (v *CarWings) Climater() (active bool, outsideTemp float64, targetTemp float64, err error) {
|
||||
res, err := v.hvacG()
|
||||
if res, ok := res.(carwings.ClimateStatus); err == nil && ok {
|
||||
active = res.Running
|
||||
|
||||
targetTemp = float64(res.Temperature)
|
||||
|
||||
outsideTemp = 0 //fixed value
|
||||
|
||||
return active, outsideTemp, targetTemp, nil
|
||||
}
|
||||
|
||||
return false, 0, 0, api.ErrNotAvailable
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
package id
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/andig/evcc/api"
|
||||
|
|
@ -84,31 +83,6 @@ func (v *Provider) Range() (int64, error) {
|
|||
return 0, err
|
||||
}
|
||||
|
||||
var _ api.VehicleClimater = (*Provider)(nil)
|
||||
|
||||
// Climater implements the api.VehicleClimater interface
|
||||
func (v *Provider) Climater() (active bool, outsideTemp float64, targetTemp float64, err error) {
|
||||
res, err := v.statusG()
|
||||
if res, ok := res.(Status); err == nil && ok {
|
||||
state := strings.ToLower(res.Data.ClimatisationStatus.ClimatisationState)
|
||||
|
||||
if state == "" {
|
||||
return false, 0, 0, api.ErrNotAvailable
|
||||
}
|
||||
|
||||
active := state != "off" && state != "invalid" && state != "error"
|
||||
|
||||
targetTemp = res.Data.ClimatisationSettings.TargetTemperatureC
|
||||
|
||||
// TODO not available; use target temp to avoid wrong heating/cooling display
|
||||
outsideTemp = targetTemp
|
||||
|
||||
return active, outsideTemp, targetTemp, nil
|
||||
}
|
||||
|
||||
return active, outsideTemp, targetTemp, err
|
||||
}
|
||||
|
||||
var _ api.VehicleStartCharge = (*Provider)(nil)
|
||||
|
||||
// StartCharge implements the api.VehicleStartCharge interface
|
||||
|
|
|
|||
|
|
@ -162,20 +162,3 @@ func (v *EMobilityProvider) Status() (api.ChargeStatus, error) {
|
|||
|
||||
return api.StatusNone, err
|
||||
}
|
||||
|
||||
var _ api.VehicleClimater = (*EMobilityProvider)(nil)
|
||||
|
||||
// Climater implements the api.VehicleClimater interface
|
||||
func (v *EMobilityProvider) Climater() (active bool, outsideTemp float64, targetTemp float64, err error) {
|
||||
res, err := v.statusG()
|
||||
if res, ok := res.(EmobilityResponse); err == nil && ok {
|
||||
switch res.DirectClimatisation.ClimatisationState {
|
||||
case "OFF":
|
||||
return false, 0, 0, nil
|
||||
case "ON":
|
||||
return true, 0, 0, nil
|
||||
}
|
||||
}
|
||||
|
||||
return active, outsideTemp, targetTemp, err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -98,16 +98,3 @@ func (v *Provider) Status() (api.ChargeStatus, error) {
|
|||
|
||||
return api.StatusNone, err
|
||||
}
|
||||
|
||||
var _ api.VehicleClimater = (*Provider)(nil)
|
||||
|
||||
// Climater implements the api.VehicleClimater interface
|
||||
func (v *Provider) Climater() (active bool, outsideTemp float64, targetTemp float64, err error) {
|
||||
res, err := v.statusG()
|
||||
if res, ok := res.(Status); err == nil && ok {
|
||||
active := strings.ToLower(res.Preconditionning.AirConditioning.Status) != "disabled"
|
||||
return active, 20, 20, nil
|
||||
}
|
||||
|
||||
return active, outsideTemp, targetTemp, err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,7 +12,6 @@ import (
|
|||
"github.com/andig/evcc/provider"
|
||||
"github.com/andig/evcc/util"
|
||||
"github.com/andig/evcc/util/request"
|
||||
"github.com/thoas/go-funk"
|
||||
)
|
||||
|
||||
// Credits to
|
||||
|
|
@ -398,29 +397,3 @@ func (v *Renault) FinishTime() (time.Time, error) {
|
|||
|
||||
return time.Time{}, err
|
||||
}
|
||||
|
||||
var _ api.VehicleClimater = (*Renault)(nil)
|
||||
|
||||
// Climater implements the api.VehicleClimater interface
|
||||
func (v *Renault) Climater() (active bool, outsideTemp float64, targetTemp float64, err error) {
|
||||
res, err := v.hvacG()
|
||||
|
||||
// Zoe Ph2
|
||||
if err, ok := err.(request.StatusError); ok && err.HasStatus(http.StatusForbidden) {
|
||||
return false, 0, 0, api.ErrNotAvailable
|
||||
}
|
||||
|
||||
if res, ok := res.(kamereonResponse); err == nil && ok {
|
||||
state := strings.ToLower(res.Data.Attributes.HvacStatus)
|
||||
|
||||
if state == "" {
|
||||
return false, 0, 0, api.ErrNotAvailable
|
||||
}
|
||||
|
||||
active := !funk.ContainsString([]string{"off", "false", "invalid", "error"}, state)
|
||||
|
||||
return active, res.Data.Attributes.ExternalTemperature, 20, nil
|
||||
}
|
||||
|
||||
return false, 0, 0, err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -182,23 +182,6 @@ func (v *Tesla) FinishTime() (time.Time, error) {
|
|||
return time.Time{}, err
|
||||
}
|
||||
|
||||
var _ api.VehicleClimater = (*Tesla)(nil)
|
||||
|
||||
// Climater implements the api.VehicleClimater interface
|
||||
func (v *Tesla) Climater() (active bool, outsideTemp float64, targetTemp float64, err error) {
|
||||
res, err := v.climateStateG()
|
||||
|
||||
if res, ok := res.(*tesla.ClimateState); err == nil && ok {
|
||||
active = res.IsPreconditioning
|
||||
outsideTemp = res.OutsideTemp
|
||||
targetTemp = res.PassengerTempSetting
|
||||
|
||||
return active, outsideTemp, targetTemp, nil
|
||||
}
|
||||
|
||||
return false, 0, 0, api.ErrNotAvailable
|
||||
}
|
||||
|
||||
var _ api.VehicleStartCharge = (*Tesla)(nil)
|
||||
|
||||
// StartCharge implements the api.VehicleStartCharge interface
|
||||
|
|
|
|||
|
|
@ -1,8 +1,6 @@
|
|||
package vw
|
||||
|
||||
import (
|
||||
"math"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/andig/evcc/api"
|
||||
|
|
@ -12,7 +10,6 @@ import (
|
|||
// Provider implements the evcc vehicle api
|
||||
type Provider struct {
|
||||
chargerG func() (interface{}, error)
|
||||
climateG func() (interface{}, error)
|
||||
action func(action, value string) error
|
||||
}
|
||||
|
||||
|
|
@ -22,9 +19,6 @@ func NewProvider(api *API, vin string, cache time.Duration) *Provider {
|
|||
chargerG: provider.NewCached(func() (interface{}, error) {
|
||||
return api.Charger(vin)
|
||||
}, cache).InterfaceGetter(),
|
||||
climateG: provider.NewCached(func() (interface{}, error) {
|
||||
return api.Climater(vin)
|
||||
}, cache).InterfaceGetter(),
|
||||
action: func(action, value string) error {
|
||||
return api.Action(vin, action, value)
|
||||
},
|
||||
|
|
@ -100,27 +94,6 @@ func (v *Provider) Range() (rng int64, err error) {
|
|||
return rng, err
|
||||
}
|
||||
|
||||
var _ api.VehicleClimater = (*Provider)(nil)
|
||||
|
||||
// Climater implements the api.VehicleClimater interface
|
||||
func (v *Provider) Climater() (active bool, outsideTemp float64, targetTemp float64, err error) {
|
||||
res, err := v.climateG()
|
||||
if res, ok := res.(ClimaterResponse); err == nil && ok {
|
||||
state := strings.ToLower(res.Climater.Status.ClimatisationStatusData.ClimatisationState.Content)
|
||||
active := state != "off" && state != "invalid" && state != "error"
|
||||
|
||||
targetTemp = res.Climater.Settings.TargetTemperature.Content
|
||||
outsideTemp = res.Climater.Status.TemperatureStatusData.OutdoorTemperature.Content
|
||||
if math.IsNaN(outsideTemp) {
|
||||
outsideTemp = targetTemp // cover "invalid"
|
||||
}
|
||||
|
||||
return active, outsideTemp, targetTemp, nil
|
||||
}
|
||||
|
||||
return active, outsideTemp, targetTemp, err
|
||||
}
|
||||
|
||||
var _ api.VehicleStartCharge = (*Provider)(nil)
|
||||
|
||||
// StartCharge implements the api.VehicleStartCharge interface
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue