Add support for electric vehicles

Signed-off-by: Knut Ahlers <knut@ahlers.me>
This commit is contained in:
Knut Ahlers 2022-12-04 00:22:53 +01:00
parent 6d438d912a
commit b51d41f15e
Signed by: luzifer
GPG key ID: D91C3E91E4CAD6F5
8 changed files with 92 additions and 14 deletions

View file

@ -46,5 +46,12 @@ func runFetcher(mc mercedes.Client, vehicleID string) {
} }
enabledExporters.SetLockStatus(vehicleID, s4) enabledExporters.SetLockStatus(vehicleID, s4)
s5, err := mc.GetElectricStatus(cfg.VehicleID[0])
if err != nil {
logger.WithError(err).Error("fetching electric-status data")
return
}
enabledExporters.SetElectricStatus(vehicleID, s5)
logger.Info("data updated successfully") logger.Info("data updated successfully")
} }

View file

@ -12,12 +12,18 @@ const (
labelLight = "light" labelLight = "light"
labelWindow = "window" labelWindow = "window"
subsystemElectricStatus = `electric_status`
subsystemFuelStatus = "fuel_status" subsystemFuelStatus = "fuel_status"
subsystemLockStatus = "lock_status" subsystemLockStatus = "lock_status"
subsystemPayAsYouDrive = "pay_as_you_drive" subsystemPayAsYouDrive = "pay_as_you_drive"
subsystemVehicleStatus = "vehicle_status" subsystemVehicleStatus = "vehicle_status"
) )
func (e *Exporter) SetElectricStatus(vehicleID string, es mercedes.ElectricStatus) {
e.submitValue(es.ElectricRange, mn(subsystemElectricStatus, "electric_range"), labelVehicleID, vehicleID)
e.submitValue(es.StateOfCharge, mn(subsystemElectricStatus, "state_of_charge"), labelVehicleID, vehicleID)
}
func (e *Exporter) SetFuelStatus(vehicleID string, fs mercedes.FuelStatus) { func (e *Exporter) SetFuelStatus(vehicleID string, fs mercedes.FuelStatus) {
e.submitValue(fs.RangeLiquid, mn(subsystemFuelStatus, "range_liquid"), labelVehicleID, vehicleID) e.submitValue(fs.RangeLiquid, mn(subsystemFuelStatus, "range_liquid"), labelVehicleID, vehicleID)
e.submitValue(fs.TanklevelPercent, mn(subsystemFuelStatus, "tanklevel_percent"), labelVehicleID, vehicleID) e.submitValue(fs.TanklevelPercent, mn(subsystemFuelStatus, "tanklevel_percent"), labelVehicleID, vehicleID)

View file

@ -4,6 +4,7 @@ import "github.com/Luzifer/mercedes-byocar-exporter/internal/mercedes"
type ( type (
Exporter interface { Exporter interface {
SetElectricStatus(vehicleID string, es mercedes.ElectricStatus)
SetFuelStatus(vehicleID string, fs mercedes.FuelStatus) SetFuelStatus(vehicleID string, fs mercedes.FuelStatus)
SetLockStatus(vehicleID string, ls mercedes.LockStatus) SetLockStatus(vehicleID string, ls mercedes.LockStatus)
SetPayAsYouGo(vehicleID string, p mercedes.PayAsYouDriveInsurance) SetPayAsYouGo(vehicleID string, p mercedes.PayAsYouDriveInsurance)
@ -15,6 +16,12 @@ type (
var _ Exporter = Set{} var _ Exporter = Set{}
func (s Set) SetElectricStatus(vehicleID string, es mercedes.ElectricStatus) {
for _, e := range s {
e.SetElectricStatus(vehicleID, es)
}
}
func (s Set) SetFuelStatus(vehicleID string, fs mercedes.FuelStatus) { func (s Set) SetFuelStatus(vehicleID string, fs mercedes.FuelStatus) {
for _, e := range s { for _, e := range s {
e.SetFuelStatus(vehicleID, fs) e.SetFuelStatus(vehicleID, fs)

View file

@ -13,6 +13,7 @@ const (
metricsNamespace = "mercedes_byocar" metricsNamespace = "mercedes_byocar"
subsystemElectricStatus = `electric_status`
subsystemFuelStatus = "fuel_status" subsystemFuelStatus = "fuel_status"
subsystemLockStatus = "lock_status" subsystemLockStatus = "lock_status"
subsystemPayAsYouDrive = "pay_as_you_drive" subsystemPayAsYouDrive = "pay_as_you_drive"
@ -20,6 +21,9 @@ const (
) )
var ( var (
electricSOC *prometheus.GaugeVec
electricRange *prometheus.GaugeVec
fuelRangeLiquidVec *prometheus.GaugeVec fuelRangeLiquidVec *prometheus.GaugeVec
fuelTanklevelPercent *prometheus.GaugeVec fuelTanklevelPercent *prometheus.GaugeVec
@ -41,12 +45,29 @@ var (
) )
func init() { func init() {
initElectricStatus()
initFuelStatus() initFuelStatus()
initLockStatus() initLockStatus()
initPAYD() initPAYD()
initVehicleStatus() initVehicleStatus()
} }
func initElectricStatus() {
electricRange = promauto.NewGaugeVec(prometheus.GaugeOpts{
Namespace: metricsNamespace,
Subsystem: subsystemElectricStatus,
Name: "electric_range",
Help: "Electric range - 0..2046 km",
}, []string{labelVehicleID})
electricSOC = promauto.NewGaugeVec(prometheus.GaugeOpts{
Namespace: metricsNamespace,
Subsystem: subsystemElectricStatus,
Name: "state_of_charge",
Help: "Displayed state of charge for the HV battery - 0..100 %",
}, []string{labelVehicleID})
}
func initFuelStatus() { func initFuelStatus() {
fuelRangeLiquidVec = promauto.NewGaugeVec(prometheus.GaugeOpts{ fuelRangeLiquidVec = promauto.NewGaugeVec(prometheus.GaugeOpts{
Namespace: metricsNamespace, Namespace: metricsNamespace,

View file

@ -16,6 +16,11 @@ var (
_ exporters.Exporter = exporter{} _ exporters.Exporter = exporter{}
) )
func (exporter) SetElectricStatus(vehicleID string, es mercedes.ElectricStatus) {
setGaugeVecValue(es.ElectricRange, electricRange, labelVehicleID, vehicleID)
setGaugeVecValue(es.StateOfCharge, electricSOC, labelVehicleID, vehicleID)
}
func (exporter) SetFuelStatus(vehicleID string, fs mercedes.FuelStatus) { func (exporter) SetFuelStatus(vehicleID string, fs mercedes.FuelStatus) {
setGaugeVecValue(fs.RangeLiquid, fuelRangeLiquidVec, labelVehicleID, vehicleID) setGaugeVecValue(fs.RangeLiquid, fuelRangeLiquidVec, labelVehicleID, vehicleID)
setGaugeVecValue(fs.TanklevelPercent, fuelTanklevelPercent, labelVehicleID, vehicleID) setGaugeVecValue(fs.TanklevelPercent, fuelTanklevelPercent, labelVehicleID, vehicleID)

View file

@ -9,6 +9,7 @@ import (
type ( type (
Client interface { Client interface {
GetAuthStartURL(redirectURL string) string GetAuthStartURL(redirectURL string) string
GetElectricStatus(vehicleID string) (ElectricStatus, error)
GetFuelStatus(vehicleID string) (FuelStatus, error) GetFuelStatus(vehicleID string) (FuelStatus, error)
GetLockStatus(vehicleID string) (LockStatus, error) GetLockStatus(vehicleID string) (LockStatus, error)
GetPayAsYouDriveInsurance(vehicleID string) (PayAsYouDriveInsurance, error) GetPayAsYouDriveInsurance(vehicleID string) (PayAsYouDriveInsurance, error)
@ -67,6 +68,7 @@ const (
oAuthScopeOfflineAccess = "offline_access" oAuthScopeOfflineAccess = "offline_access"
oAuthScopeOpenID = "openid" oAuthScopeOpenID = "openid"
oAuthScopePayAsYouDrive = "mb:vehicle:mbdata:payasyoudrive" oAuthScopePayAsYouDrive = "mb:vehicle:mbdata:payasyoudrive"
oAuthScopeVehicleElectricStatus = "mb:vehicle:mbdata:evstatus"
oAuthScopeVehicleFuelStatus = "mb:vehicle:mbdata:fuelstatus" oAuthScopeVehicleFuelStatus = "mb:vehicle:mbdata:fuelstatus"
oAuthScopeVehicleLockStatus = "mb:vehicle:mbdata:vehiclelock" oAuthScopeVehicleLockStatus = "mb:vehicle:mbdata:vehiclelock"
oAuthScopeVehicleStatus = "mb:vehicle:mbdata:vehiclestatus" oAuthScopeVehicleStatus = "mb:vehicle:mbdata:vehiclestatus"

View file

@ -0,0 +1,29 @@
package mercedes
import (
"fmt"
"github.com/pkg/errors"
)
type (
ElectricStatus struct {
// Displayed state of charge for the HV battery 0..100 %
StateOfCharge TimedInt `apiField:"soc"`
// Electric range 0..2046 km
ElectricRange TimedInt `apiField:"rangeelectric"`
}
)
func (a APIClient) GetElectricStatus(vehicleID string) (ElectricStatus, error) {
var (
path = fmt.Sprintf("/vehicles/%s/containers/electricvehicle", vehicleID)
out ElectricStatus
)
if err := a.request(path, &out); err != nil {
return out, errors.Wrap(err, "getting electric status")
}
return out, nil
}

View file

@ -83,6 +83,7 @@ func (a APIClient) getOauth2Config(redirectURL string) *oauth2.Config {
oAuthScopeOfflineAccess, oAuthScopeOfflineAccess,
oAuthScopeOpenID, oAuthScopeOpenID,
oAuthScopePayAsYouDrive, oAuthScopePayAsYouDrive,
oAuthScopeVehicleElectricStatus,
oAuthScopeVehicleFuelStatus, oAuthScopeVehicleFuelStatus,
oAuthScopeVehicleLockStatus, oAuthScopeVehicleLockStatus,
oAuthScopeVehicleStatus, oAuthScopeVehicleStatus,