diff --git a/api/api.go b/api/api.go
index aa299e34b..c6f5f8827 100644
--- a/api/api.go
+++ b/api/api.go
@@ -221,3 +221,9 @@ type AuthProvider interface {
LoginHandler() http.HandlerFunc
LogoutHandler() http.HandlerFunc
}
+
+// FeatureDescriber optionally provides a list of supported non-api features
+type FeatureDescriber interface {
+ Features() []Feature
+ Has(Feature) bool
+}
diff --git a/api/feature.go b/api/feature.go
new file mode 100644
index 000000000..9d615d73a
--- /dev/null
+++ b/api/feature.go
@@ -0,0 +1,17 @@
+package api
+
+type Feature int
+
+func (f *Feature) UnmarshalText(text []byte) error {
+ feat, err := FeatureString(string(text))
+ if err == nil {
+ *f = feat
+ }
+ return err
+}
+
+//go:generate enumer -type Feature
+const (
+ _ Feature = iota
+ Offline
+)
diff --git a/api/feature_enumer.go b/api/feature_enumer.go
new file mode 100644
index 000000000..55293ab84
--- /dev/null
+++ b/api/feature_enumer.go
@@ -0,0 +1,75 @@
+// Code generated by "enumer -type Feature"; DO NOT EDIT.
+
+package api
+
+import (
+ "fmt"
+ "strings"
+)
+
+const _FeatureName = "Offline"
+
+var _FeatureIndex = [...]uint8{0, 7}
+
+const _FeatureLowerName = "offline"
+
+func (i Feature) String() string {
+ i -= 1
+ if i < 0 || i >= Feature(len(_FeatureIndex)-1) {
+ return fmt.Sprintf("Feature(%d)", i+1)
+ }
+ return _FeatureName[_FeatureIndex[i]:_FeatureIndex[i+1]]
+}
+
+// An "invalid array index" compiler error signifies that the constant values have changed.
+// Re-run the stringer command to generate them again.
+func _FeatureNoOp() {
+ var x [1]struct{}
+ _ = x[Offline-(1)]
+}
+
+var _FeatureValues = []Feature{Offline}
+
+var _FeatureNameToValueMap = map[string]Feature{
+ _FeatureName[0:7]: Offline,
+ _FeatureLowerName[0:7]: Offline,
+}
+
+var _FeatureNames = []string{
+ _FeatureName[0:7],
+}
+
+// FeatureString retrieves an enum value from the enum constants string name.
+// Throws an error if the param is not part of the enum.
+func FeatureString(s string) (Feature, error) {
+ if val, ok := _FeatureNameToValueMap[s]; ok {
+ return val, nil
+ }
+
+ if val, ok := _FeatureNameToValueMap[strings.ToLower(s)]; ok {
+ return val, nil
+ }
+ return 0, fmt.Errorf("%s does not belong to Feature values", s)
+}
+
+// FeatureValues returns all values of the enum
+func FeatureValues() []Feature {
+ return _FeatureValues
+}
+
+// FeatureStrings returns a slice of all String values of the enum
+func FeatureStrings() []string {
+ strs := make([]string, len(_FeatureNames))
+ copy(strs, _FeatureNames)
+ return strs
+}
+
+// IsAFeature returns "true" if the value is listed in the enum definition. "false" otherwise
+func (i Feature) IsAFeature() bool {
+ for _, v := range _FeatureValues {
+ if i == v {
+ return true
+ }
+ }
+ return false
+}
diff --git a/assets/js/components/AnimatedNumber.vue b/assets/js/components/AnimatedNumber.vue
index 96f7e4242..3879062da 100644
--- a/assets/js/components/AnimatedNumber.vue
+++ b/assets/js/components/AnimatedNumber.vue
@@ -1,5 +1,5 @@
-
+
+
+
diff --git a/assets/js/components/Vehicle.stories.js b/assets/js/components/Vehicle.stories.js
index e9613d93f..0cf6fc77b 100644
--- a/assets/js/components/Vehicle.stories.js
+++ b/assets/js/components/Vehicle.stories.js
@@ -24,6 +24,7 @@ Base.args = {
vehicleSoC: 42,
vehicleRange: 231,
targetSoC: 90,
+ socBasedCharging: true,
id: 0,
};
@@ -36,6 +37,7 @@ Connected.args = {
charging: false,
vehicleSoC: 66,
targetSoC: 90,
+ socBasedCharging: true,
id: 0,
};
@@ -48,6 +50,7 @@ ReadyToCharge.args = {
charging: false,
vehicleSoC: 66,
targetSoC: 90,
+ socBasedCharging: true,
id: 0,
};
@@ -60,6 +63,7 @@ Charging.args = {
charging: true,
vehicleSoC: 66,
targetSoC: 90,
+ socBasedCharging: true,
id: 0,
};
@@ -81,6 +85,7 @@ TargetChargePlanned.args = {
targetTimeActive: false,
targetSoC: 45,
targetTime: hoursFromNow(14),
+ socBasedCharging: true,
id: 0,
};
@@ -96,6 +101,7 @@ TargetChargeActive.args = {
targetTimeActive: true,
targetSoC: 80,
targetTime: hoursFromNow(2),
+ socBasedCharging: true,
id: 0,
};
@@ -109,6 +115,21 @@ MinCharge.args = {
minSoC: 20,
charging: true,
targetSoC: 90,
+ socBasedCharging: true,
+ id: 0,
+};
+
+export const VehicleTargetSoc = Template.bind({});
+VehicleTargetSoc.args = {
+ vehicleTitle: "Mein Auto",
+ enabled: true,
+ connected: true,
+ vehiclePresent: true,
+ vehicleTargetSoC: 80,
+ vehicleSoC: 66,
+ charging: true,
+ targetSoC: 90,
+ socBasedCharging: true,
id: 0,
};
@@ -125,6 +146,7 @@ TimerPvEnable.args = {
phaseRemainingInterpolated: 0,
pvAction: "enable",
pvRemainingInterpolated: 32,
+ socBasedCharging: true,
id: 0,
};
@@ -141,16 +163,17 @@ TimerPvDisable.args = {
phaseRemainingInterpolated: 0,
pvAction: "disable",
pvRemainingInterpolated: 155,
+ socBasedCharging: true,
id: 0,
};
export const UnknownVehicleConnected = Template.bind({});
UnknownVehicleConnected.args = {
- vehicleTitle: "Mein Auto",
enabled: false,
connected: true,
vehiclePresent: false,
targetSoC: 90,
+ socBasedCharging: false,
id: 0,
};
@@ -162,6 +185,7 @@ UnknownVehicleReadyToCharge.args = {
vehiclePresent: false,
charging: false,
targetSoC: 100,
+ socBasedCharging: false,
id: 0,
};
@@ -173,6 +197,37 @@ UnknownVehicleCharging.args = {
vehiclePresent: false,
charging: true,
targetSoC: 90,
+ socBasedCharging: false,
+ id: 0,
+};
+
+export const OfflineVehicleCharging = Template.bind({});
+OfflineVehicleCharging.args = {
+ vehicleTitle: "Polestar 2",
+ enabled: true,
+ connected: true,
+ vehiclePresent: true,
+ vehicleFeatureOffline: true,
+ vehicleCapacity: 72,
+ chargedEnergy: 14123,
+ charging: true,
+ targetSoC: 90,
+ socBasedCharging: false,
+ id: 0,
+};
+
+export const OfflineVehicleTargetEnergy = Template.bind({});
+OfflineVehicleTargetEnergy.args = {
+ vehicleTitle: "Polestar 2",
+ enabled: true,
+ connected: true,
+ vehiclePresent: true,
+ vehicleFeatureOffline: true,
+ vehicleCapacity: 72,
+ chargedEnergy: 14123,
+ targetEnergy: 30,
+ charging: true,
+ socBasedCharging: false,
id: 0,
};
diff --git a/assets/js/components/Vehicle.vue b/assets/js/components/Vehicle.vue
index f17701b14..d34fbe19e 100644
--- a/assets/js/components/Vehicle.vue
+++ b/assets/js/components/Vehicle.vue
@@ -12,44 +12,65 @@
@target-soc-updated="targetSocUpdated"
@target-soc-drag="targetSocDrag"
/>
-
-
-
-
-
-
-
- vor 5 Stunden
-
+
+
+
+
+
+
+
+
+
+ vor 5 Stunden
-
+
+
diff --git a/package-lock.json b/package-lock.json
index aae1729e0..1a38e7c39 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -78,30 +78,30 @@
}
},
"node_modules/@babel/compat-data": {
- "version": "7.18.13",
- "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.18.13.tgz",
- "integrity": "sha512-5yUzC5LqyTFp2HLmDoxGQelcdYgSpP9xsnMWBphAscOdFrHSAVbLNzWiy32sVNDqJRDiJK6klfDnAgu6PAGSHw==",
+ "version": "7.19.3",
+ "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.19.3.tgz",
+ "integrity": "sha512-prBHMK4JYYK+wDjJF1q99KK4JLL+egWS4nmNqdlMUgCExMZ+iZW0hGhyC3VEbsPjvaN0TBhW//VIFwBrk8sEiw==",
"dev": true,
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/core": {
- "version": "7.18.13",
- "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.18.13.tgz",
- "integrity": "sha512-ZisbOvRRusFktksHSG6pjj1CSvkPkcZq/KHD45LAkVP/oiHJkNBZWfpvlLmX8OtHDG8IuzsFlVRWo08w7Qxn0A==",
+ "version": "7.19.3",
+ "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.19.3.tgz",
+ "integrity": "sha512-WneDJxdsjEvyKtXKsaBGbDeiyOjR5vYq4HcShxnIbG0qixpoHjI3MqeZM9NDvsojNCEBItQE4juOo/bU6e72gQ==",
"dev": true,
"dependencies": {
"@ampproject/remapping": "^2.1.0",
"@babel/code-frame": "^7.18.6",
- "@babel/generator": "^7.18.13",
- "@babel/helper-compilation-targets": "^7.18.9",
- "@babel/helper-module-transforms": "^7.18.9",
- "@babel/helpers": "^7.18.9",
- "@babel/parser": "^7.18.13",
+ "@babel/generator": "^7.19.3",
+ "@babel/helper-compilation-targets": "^7.19.3",
+ "@babel/helper-module-transforms": "^7.19.0",
+ "@babel/helpers": "^7.19.0",
+ "@babel/parser": "^7.19.3",
"@babel/template": "^7.18.10",
- "@babel/traverse": "^7.18.13",
- "@babel/types": "^7.18.13",
+ "@babel/traverse": "^7.19.3",
+ "@babel/types": "^7.19.3",
"convert-source-map": "^1.7.0",
"debug": "^4.1.0",
"gensync": "^1.0.0-beta.2",
@@ -117,12 +117,12 @@
}
},
"node_modules/@babel/generator": {
- "version": "7.18.13",
- "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.18.13.tgz",
- "integrity": "sha512-CkPg8ySSPuHTYPJYo7IRALdqyjM9HCbt/3uOBEFbzyGVP6Mn8bwFPB0jX6982JVNBlYzM1nnPkfjuXSOPtQeEQ==",
+ "version": "7.19.3",
+ "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.19.3.tgz",
+ "integrity": "sha512-fqVZnmp1ncvZU757UzDheKZpfPgatqY59XtW2/j/18H7u76akb8xqvjw82f+i2UKd/ksYsSick/BCLQUUtJ/qQ==",
"dev": true,
"dependencies": {
- "@babel/types": "^7.18.13",
+ "@babel/types": "^7.19.3",
"@jridgewell/gen-mapping": "^0.3.2",
"jsesc": "^2.5.1"
},
@@ -170,14 +170,14 @@
}
},
"node_modules/@babel/helper-compilation-targets": {
- "version": "7.18.9",
- "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.18.9.tgz",
- "integrity": "sha512-tzLCyVmqUiFlcFoAPLA/gL9TeYrF61VLNtb+hvkuVaB5SUjW7jcfrglBIX1vUIoT7CLP3bBlIMeyEsIl2eFQNg==",
+ "version": "7.19.3",
+ "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.19.3.tgz",
+ "integrity": "sha512-65ESqLGyGmLvgR0mst5AdW1FkNlj9rQsCKduzEoEPhBCDFGXvz2jW6bXFG6i0/MrV2s7hhXjjb2yAzcPuQlLwg==",
"dev": true,
"dependencies": {
- "@babel/compat-data": "^7.18.8",
+ "@babel/compat-data": "^7.19.3",
"@babel/helper-validator-option": "^7.18.6",
- "browserslist": "^4.20.2",
+ "browserslist": "^4.21.3",
"semver": "^6.3.0"
},
"engines": {
@@ -263,13 +263,13 @@
}
},
"node_modules/@babel/helper-function-name": {
- "version": "7.18.9",
- "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.18.9.tgz",
- "integrity": "sha512-fJgWlZt7nxGksJS9a0XdSaI4XvpExnNIgRP+rVefWh5U7BL8pPuir6SJUmFKRfjWQ51OtWSzwOxhaH/EBWWc0A==",
+ "version": "7.19.0",
+ "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.19.0.tgz",
+ "integrity": "sha512-WAwHBINyrpqywkUH0nTnNgI5ina5TFn85HKS0pbPDfxFfhyR/aNQEn4hGi1P1JyT//I0t4OgXUlofzWILRvS5w==",
"dev": true,
"dependencies": {
- "@babel/template": "^7.18.6",
- "@babel/types": "^7.18.9"
+ "@babel/template": "^7.18.10",
+ "@babel/types": "^7.19.0"
},
"engines": {
"node": ">=6.9.0"
@@ -312,9 +312,9 @@
}
},
"node_modules/@babel/helper-module-transforms": {
- "version": "7.18.9",
- "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.18.9.tgz",
- "integrity": "sha512-KYNqY0ICwfv19b31XzvmI/mfcylOzbLtowkw+mfvGPAQ3kfCnMLYbED3YecL5tPd8nAYFQFAd6JHp2LxZk/J1g==",
+ "version": "7.19.0",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.19.0.tgz",
+ "integrity": "sha512-3HBZ377Fe14RbLIA+ac3sY4PTgpxHVkFrESaWhoI5PuyXPBBX8+C34qblV9G89ZtycGJCmCI/Ut+VUDK4bltNQ==",
"dev": true,
"dependencies": {
"@babel/helper-environment-visitor": "^7.18.9",
@@ -322,9 +322,9 @@
"@babel/helper-simple-access": "^7.18.6",
"@babel/helper-split-export-declaration": "^7.18.6",
"@babel/helper-validator-identifier": "^7.18.6",
- "@babel/template": "^7.18.6",
- "@babel/traverse": "^7.18.9",
- "@babel/types": "^7.18.9"
+ "@babel/template": "^7.18.10",
+ "@babel/traverse": "^7.19.0",
+ "@babel/types": "^7.19.0"
},
"engines": {
"node": ">=6.9.0"
@@ -431,9 +431,9 @@
}
},
"node_modules/@babel/helper-validator-identifier": {
- "version": "7.18.6",
- "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.18.6.tgz",
- "integrity": "sha512-MmetCkz9ej86nJQV+sFCxoGGrUbU3q02kgLciwkrt9QqEB7cP39oKEY0PakknEO0Gu20SskMRi+AYZ3b1TpN9g==",
+ "version": "7.19.1",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz",
+ "integrity": "sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==",
"dev": true,
"engines": {
"node": ">=6.9.0"
@@ -464,14 +464,14 @@
}
},
"node_modules/@babel/helpers": {
- "version": "7.18.9",
- "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.18.9.tgz",
- "integrity": "sha512-Jf5a+rbrLoR4eNdUmnFu8cN5eNJT6qdTdOg5IHIzq87WwyRw9PwguLFOWYgktN/60IP4fgDUawJvs7PjQIzELQ==",
+ "version": "7.19.0",
+ "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.19.0.tgz",
+ "integrity": "sha512-DRBCKGwIEdqY3+rPJgG/dKfQy9+08rHIAJx8q2p+HSWP87s2HCrQmaAMMyMll2kIXKCW0cO1RdQskx15Xakftg==",
"dev": true,
"dependencies": {
- "@babel/template": "^7.18.6",
- "@babel/traverse": "^7.18.9",
- "@babel/types": "^7.18.9"
+ "@babel/template": "^7.18.10",
+ "@babel/traverse": "^7.19.0",
+ "@babel/types": "^7.19.0"
},
"engines": {
"node": ">=6.9.0"
@@ -492,9 +492,9 @@
}
},
"node_modules/@babel/parser": {
- "version": "7.18.13",
- "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.18.13.tgz",
- "integrity": "sha512-dgXcIfMuQ0kgzLB2b9tRZs7TTFFaGM2AbtA4fJgUUYukzGH4jwsS7hzQHEGs67jdehpm22vkgKwvbU+aEflgwg==",
+ "version": "7.19.3",
+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.19.3.tgz",
+ "integrity": "sha512-pJ9xOlNWHiy9+FuFP09DEAFbAn4JskgRsVcc169w2xRBC3FRGuQEwjeIMMND9L2zc0iEhO/tGv4Zq+km+hxNpQ==",
"bin": {
"parser": "bin/babel-parser.js"
},
@@ -1923,19 +1923,19 @@
}
},
"node_modules/@babel/traverse": {
- "version": "7.18.13",
- "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.18.13.tgz",
- "integrity": "sha512-N6kt9X1jRMLPxxxPYWi7tgvJRH/rtoU+dbKAPDM44RFHiMH8igdsaSBgFeskhSl/kLWLDUvIh1RXCrTmg0/zvA==",
+ "version": "7.19.3",
+ "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.19.3.tgz",
+ "integrity": "sha512-qh5yf6149zhq2sgIXmwjnsvmnNQC2iw70UFjp4olxucKrWd/dvlUsBI88VSLUsnMNF7/vnOiA+nk1+yLoCqROQ==",
"dev": true,
"dependencies": {
"@babel/code-frame": "^7.18.6",
- "@babel/generator": "^7.18.13",
+ "@babel/generator": "^7.19.3",
"@babel/helper-environment-visitor": "^7.18.9",
- "@babel/helper-function-name": "^7.18.9",
+ "@babel/helper-function-name": "^7.19.0",
"@babel/helper-hoist-variables": "^7.18.6",
"@babel/helper-split-export-declaration": "^7.18.6",
- "@babel/parser": "^7.18.13",
- "@babel/types": "^7.18.13",
+ "@babel/parser": "^7.19.3",
+ "@babel/types": "^7.19.3",
"debug": "^4.1.0",
"globals": "^11.1.0"
},
@@ -1944,13 +1944,13 @@
}
},
"node_modules/@babel/types": {
- "version": "7.18.13",
- "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.18.13.tgz",
- "integrity": "sha512-ePqfTihzW0W6XAU+aMw2ykilisStJfDnsejDCXRchCcMJ4O0+8DhPXf2YUbZ6wjBlsEmZwLK/sPweWtu8hcJYQ==",
+ "version": "7.19.3",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.19.3.tgz",
+ "integrity": "sha512-hGCaQzIY22DJlDh9CH7NOxgKkFjBk0Cw9xDO1Xmh2151ti7wiGfQ3LauXzL4HP1fmFlTX6XjpRETTpUcv7wQLw==",
"dev": true,
"dependencies": {
"@babel/helper-string-parser": "^7.18.10",
- "@babel/helper-validator-identifier": "^7.18.6",
+ "@babel/helper-validator-identifier": "^7.19.1",
"to-fast-properties": "^2.0.0"
},
"engines": {
@@ -24603,27 +24603,27 @@
}
},
"@babel/compat-data": {
- "version": "7.18.13",
- "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.18.13.tgz",
- "integrity": "sha512-5yUzC5LqyTFp2HLmDoxGQelcdYgSpP9xsnMWBphAscOdFrHSAVbLNzWiy32sVNDqJRDiJK6klfDnAgu6PAGSHw==",
+ "version": "7.19.3",
+ "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.19.3.tgz",
+ "integrity": "sha512-prBHMK4JYYK+wDjJF1q99KK4JLL+egWS4nmNqdlMUgCExMZ+iZW0hGhyC3VEbsPjvaN0TBhW//VIFwBrk8sEiw==",
"dev": true
},
"@babel/core": {
- "version": "7.18.13",
- "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.18.13.tgz",
- "integrity": "sha512-ZisbOvRRusFktksHSG6pjj1CSvkPkcZq/KHD45LAkVP/oiHJkNBZWfpvlLmX8OtHDG8IuzsFlVRWo08w7Qxn0A==",
+ "version": "7.19.3",
+ "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.19.3.tgz",
+ "integrity": "sha512-WneDJxdsjEvyKtXKsaBGbDeiyOjR5vYq4HcShxnIbG0qixpoHjI3MqeZM9NDvsojNCEBItQE4juOo/bU6e72gQ==",
"dev": true,
"requires": {
"@ampproject/remapping": "^2.1.0",
"@babel/code-frame": "^7.18.6",
- "@babel/generator": "^7.18.13",
- "@babel/helper-compilation-targets": "^7.18.9",
- "@babel/helper-module-transforms": "^7.18.9",
- "@babel/helpers": "^7.18.9",
- "@babel/parser": "^7.18.13",
+ "@babel/generator": "^7.19.3",
+ "@babel/helper-compilation-targets": "^7.19.3",
+ "@babel/helper-module-transforms": "^7.19.0",
+ "@babel/helpers": "^7.19.0",
+ "@babel/parser": "^7.19.3",
"@babel/template": "^7.18.10",
- "@babel/traverse": "^7.18.13",
- "@babel/types": "^7.18.13",
+ "@babel/traverse": "^7.19.3",
+ "@babel/types": "^7.19.3",
"convert-source-map": "^1.7.0",
"debug": "^4.1.0",
"gensync": "^1.0.0-beta.2",
@@ -24632,12 +24632,12 @@
}
},
"@babel/generator": {
- "version": "7.18.13",
- "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.18.13.tgz",
- "integrity": "sha512-CkPg8ySSPuHTYPJYo7IRALdqyjM9HCbt/3uOBEFbzyGVP6Mn8bwFPB0jX6982JVNBlYzM1nnPkfjuXSOPtQeEQ==",
+ "version": "7.19.3",
+ "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.19.3.tgz",
+ "integrity": "sha512-fqVZnmp1ncvZU757UzDheKZpfPgatqY59XtW2/j/18H7u76akb8xqvjw82f+i2UKd/ksYsSick/BCLQUUtJ/qQ==",
"dev": true,
"requires": {
- "@babel/types": "^7.18.13",
+ "@babel/types": "^7.19.3",
"@jridgewell/gen-mapping": "^0.3.2",
"jsesc": "^2.5.1"
},
@@ -24675,14 +24675,14 @@
}
},
"@babel/helper-compilation-targets": {
- "version": "7.18.9",
- "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.18.9.tgz",
- "integrity": "sha512-tzLCyVmqUiFlcFoAPLA/gL9TeYrF61VLNtb+hvkuVaB5SUjW7jcfrglBIX1vUIoT7CLP3bBlIMeyEsIl2eFQNg==",
+ "version": "7.19.3",
+ "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.19.3.tgz",
+ "integrity": "sha512-65ESqLGyGmLvgR0mst5AdW1FkNlj9rQsCKduzEoEPhBCDFGXvz2jW6bXFG6i0/MrV2s7hhXjjb2yAzcPuQlLwg==",
"dev": true,
"requires": {
- "@babel/compat-data": "^7.18.8",
+ "@babel/compat-data": "^7.19.3",
"@babel/helper-validator-option": "^7.18.6",
- "browserslist": "^4.20.2",
+ "browserslist": "^4.21.3",
"semver": "^6.3.0"
}
},
@@ -24741,13 +24741,13 @@
}
},
"@babel/helper-function-name": {
- "version": "7.18.9",
- "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.18.9.tgz",
- "integrity": "sha512-fJgWlZt7nxGksJS9a0XdSaI4XvpExnNIgRP+rVefWh5U7BL8pPuir6SJUmFKRfjWQ51OtWSzwOxhaH/EBWWc0A==",
+ "version": "7.19.0",
+ "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.19.0.tgz",
+ "integrity": "sha512-WAwHBINyrpqywkUH0nTnNgI5ina5TFn85HKS0pbPDfxFfhyR/aNQEn4hGi1P1JyT//I0t4OgXUlofzWILRvS5w==",
"dev": true,
"requires": {
- "@babel/template": "^7.18.6",
- "@babel/types": "^7.18.9"
+ "@babel/template": "^7.18.10",
+ "@babel/types": "^7.19.0"
}
},
"@babel/helper-hoist-variables": {
@@ -24778,9 +24778,9 @@
}
},
"@babel/helper-module-transforms": {
- "version": "7.18.9",
- "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.18.9.tgz",
- "integrity": "sha512-KYNqY0ICwfv19b31XzvmI/mfcylOzbLtowkw+mfvGPAQ3kfCnMLYbED3YecL5tPd8nAYFQFAd6JHp2LxZk/J1g==",
+ "version": "7.19.0",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.19.0.tgz",
+ "integrity": "sha512-3HBZ377Fe14RbLIA+ac3sY4PTgpxHVkFrESaWhoI5PuyXPBBX8+C34qblV9G89ZtycGJCmCI/Ut+VUDK4bltNQ==",
"dev": true,
"requires": {
"@babel/helper-environment-visitor": "^7.18.9",
@@ -24788,9 +24788,9 @@
"@babel/helper-simple-access": "^7.18.6",
"@babel/helper-split-export-declaration": "^7.18.6",
"@babel/helper-validator-identifier": "^7.18.6",
- "@babel/template": "^7.18.6",
- "@babel/traverse": "^7.18.9",
- "@babel/types": "^7.18.9"
+ "@babel/template": "^7.18.10",
+ "@babel/traverse": "^7.19.0",
+ "@babel/types": "^7.19.0"
}
},
"@babel/helper-optimise-call-expression": {
@@ -24867,9 +24867,9 @@
"dev": true
},
"@babel/helper-validator-identifier": {
- "version": "7.18.6",
- "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.18.6.tgz",
- "integrity": "sha512-MmetCkz9ej86nJQV+sFCxoGGrUbU3q02kgLciwkrt9QqEB7cP39oKEY0PakknEO0Gu20SskMRi+AYZ3b1TpN9g==",
+ "version": "7.19.1",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz",
+ "integrity": "sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==",
"dev": true
},
"@babel/helper-validator-option": {
@@ -24891,14 +24891,14 @@
}
},
"@babel/helpers": {
- "version": "7.18.9",
- "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.18.9.tgz",
- "integrity": "sha512-Jf5a+rbrLoR4eNdUmnFu8cN5eNJT6qdTdOg5IHIzq87WwyRw9PwguLFOWYgktN/60IP4fgDUawJvs7PjQIzELQ==",
+ "version": "7.19.0",
+ "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.19.0.tgz",
+ "integrity": "sha512-DRBCKGwIEdqY3+rPJgG/dKfQy9+08rHIAJx8q2p+HSWP87s2HCrQmaAMMyMll2kIXKCW0cO1RdQskx15Xakftg==",
"dev": true,
"requires": {
- "@babel/template": "^7.18.6",
- "@babel/traverse": "^7.18.9",
- "@babel/types": "^7.18.9"
+ "@babel/template": "^7.18.10",
+ "@babel/traverse": "^7.19.0",
+ "@babel/types": "^7.19.0"
}
},
"@babel/highlight": {
@@ -24913,9 +24913,9 @@
}
},
"@babel/parser": {
- "version": "7.18.13",
- "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.18.13.tgz",
- "integrity": "sha512-dgXcIfMuQ0kgzLB2b9tRZs7TTFFaGM2AbtA4fJgUUYukzGH4jwsS7hzQHEGs67jdehpm22vkgKwvbU+aEflgwg=="
+ "version": "7.19.3",
+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.19.3.tgz",
+ "integrity": "sha512-pJ9xOlNWHiy9+FuFP09DEAFbAn4JskgRsVcc169w2xRBC3FRGuQEwjeIMMND9L2zc0iEhO/tGv4Zq+km+hxNpQ=="
},
"@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": {
"version": "7.18.6",
@@ -25861,31 +25861,31 @@
}
},
"@babel/traverse": {
- "version": "7.18.13",
- "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.18.13.tgz",
- "integrity": "sha512-N6kt9X1jRMLPxxxPYWi7tgvJRH/rtoU+dbKAPDM44RFHiMH8igdsaSBgFeskhSl/kLWLDUvIh1RXCrTmg0/zvA==",
+ "version": "7.19.3",
+ "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.19.3.tgz",
+ "integrity": "sha512-qh5yf6149zhq2sgIXmwjnsvmnNQC2iw70UFjp4olxucKrWd/dvlUsBI88VSLUsnMNF7/vnOiA+nk1+yLoCqROQ==",
"dev": true,
"requires": {
"@babel/code-frame": "^7.18.6",
- "@babel/generator": "^7.18.13",
+ "@babel/generator": "^7.19.3",
"@babel/helper-environment-visitor": "^7.18.9",
- "@babel/helper-function-name": "^7.18.9",
+ "@babel/helper-function-name": "^7.19.0",
"@babel/helper-hoist-variables": "^7.18.6",
"@babel/helper-split-export-declaration": "^7.18.6",
- "@babel/parser": "^7.18.13",
- "@babel/types": "^7.18.13",
+ "@babel/parser": "^7.19.3",
+ "@babel/types": "^7.19.3",
"debug": "^4.1.0",
"globals": "^11.1.0"
}
},
"@babel/types": {
- "version": "7.18.13",
- "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.18.13.tgz",
- "integrity": "sha512-ePqfTihzW0W6XAU+aMw2ykilisStJfDnsejDCXRchCcMJ4O0+8DhPXf2YUbZ6wjBlsEmZwLK/sPweWtu8hcJYQ==",
+ "version": "7.19.3",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.19.3.tgz",
+ "integrity": "sha512-hGCaQzIY22DJlDh9CH7NOxgKkFjBk0Cw9xDO1Xmh2151ti7wiGfQ3LauXzL4HP1fmFlTX6XjpRETTpUcv7wQLw==",
"dev": true,
"requires": {
"@babel/helper-string-parser": "^7.18.10",
- "@babel/helper-validator-identifier": "^7.18.6",
+ "@babel/helper-validator-identifier": "^7.19.1",
"to-fast-properties": "^2.0.0"
}
},
diff --git a/server/http.go b/server/http.go
index b40f0f54c..9f65cabc0 100644
--- a/server/http.go
+++ b/server/http.go
@@ -109,6 +109,7 @@ func (s *HTTPd) RegisterSiteHandlers(site site.API, cache *util.Cache) {
routes := map[string]route{
"mode": {[]string{"POST", "OPTIONS"}, "/mode/{value:[a-z]+}", chargeModeHandler(lp)},
+ "targetenergy": {[]string{"POST", "OPTIONS"}, "/targetenergy/{value:[0-9]+}", intHandler(pass(lp.SetTargetEnergy), lp.GetTargetEnergy)},
"targetsoc": {[]string{"POST", "OPTIONS"}, "/targetsoc/{value:[0-9]+}", intHandler(pass(lp.SetTargetSoC), lp.GetTargetSoC)},
"minsoc": {[]string{"POST", "OPTIONS"}, "/minsoc/{value:[0-9]+}", intHandler(pass(lp.SetMinSoC), lp.GetMinSoC)},
"mincurrent": {[]string{"POST", "OPTIONS"}, "/mincurrent/{value:[0-9]+}", floatHandler(pass(lp.SetMinCurrent), lp.GetMinCurrent)},
diff --git a/templates/definition/vehicle/offline.yaml b/templates/definition/vehicle/offline.yaml
index 6e7b5f1e4..6cf099fde 100644
--- a/templates/definition/vehicle/offline.yaml
+++ b/templates/definition/vehicle/offline.yaml
@@ -20,6 +20,7 @@ params:
valuetype: stringlist
render: |
type: custom
+ features: ["offline"]
{{- if ne .title "" }}
title: {{ .title }}
{{- end }}
diff --git a/vehicle/embed.go b/vehicle/embed.go
index 71f9d2a10..633def331 100644
--- a/vehicle/embed.go
+++ b/vehicle/embed.go
@@ -1,12 +1,16 @@
package vehicle
-import "github.com/evcc-io/evcc/api"
+import (
+ "github.com/evcc-io/evcc/api"
+ "golang.org/x/exp/slices"
+)
type embed struct {
Title_ string `mapstructure:"title"`
Capacity_ int64 `mapstructure:"capacity"`
Phases_ int `mapstructure:"phases"`
Identifiers_ []string `mapstructure:"identifiers"`
+ Features_ []api.Feature `mapstructure:"features"`
OnIdentify api.ActionConfig `mapstructure:"onIdentify"`
}
@@ -34,3 +38,15 @@ func (v *embed) Identifiers() []string {
func (v *embed) OnIdentified() api.ActionConfig {
return v.OnIdentify
}
+
+var _ api.FeatureDescriber = (*embed)(nil)
+
+// Features implements the api.Describer interface
+func (v *embed) Features() []api.Feature {
+ return v.Features_
+}
+
+// Features implements the api.Describer interface
+func (v *embed) Has(f api.Feature) bool {
+ return slices.Contains(v.Features_, f)
+}