Repository: evcc-io/evcc
Pull request #18138 (2025-01-08 20:10:56)

Go-E: re-add session energy for v2
Fix https://github.com/evcc-io/evcc/issues/17681. Follow-up to https://github.com/evcc-io/evcc/issues/13726.


Patch:
diff --git a/assets/js/components/VehicleIcon/Battery.vue b/assets/js/components/VehicleIcon/Battery.vue
new file mode 100644
index 00000000..4ff7f037
--- /dev/null
+++ b/assets/js/components/VehicleIcon/Battery.vue
@@ -0,0 +1,14 @@
+<template>
+	<svg width="1em" height="1em" viewBox="0 0 24 24">
+		<path
+			fill="currentColor"
+			d="M8 22q-.425 0-.712-.288T7 21V5q0-.425.288-.712T8 4h2V3q0-.425.288-.712T11 2h2q.425 0 .713.288T14 3v1h2q.425 0 .713.288T17 5v16q0 .425-.288.713T16 22zm1-2h6V6H9zm0 0h6zm1-5.275q0 .575.213 1.088t.612.912l.225.225q.275.275.688.275t.712-.275q.3-.3.3-.712t-.3-.713l-.225-.225q-.125-.125-.175-.262T12 14.75q0-.175.05-.312t.175-.263l.95-.95q.4-.4.613-.9t.212-1.05q0-.575-.212-1.087t-.613-.913l-.25-.25q-.3-.3-.7-.288t-.7.313q-.275.3-.288.7t.288.7l.225.225q.125.125.188.262t.062.313q0 .15-.062.288t-.188.262l-.925.95q-.4.4-.612.9T10 14.725"
+		/>
+	</svg>
+</template>
+
+<script>
+export default {
+	name: "Battery",
+};
+</script>
diff --git a/assets/js/components/VehicleIcon/Bulb.vue b/assets/js/components/VehicleIcon/Bulb.vue
new file mode 100644
index 00000000..a6e0a86c
--- /dev/null
+++ b/assets/js/components/VehicleIcon/Bulb.vue
@@ -0,0 +1,14 @@
+<template>
+	<svg width="1em" height="1em" viewBox="0 0 24 24">
+		<path
+			fill="currentColor"
+			d="M11 21v-1q0-.425.288-.712T12 19t.713.288T13 20v1q0 .425-.288.713T12 22t-.712-.288T11 21M3 11h1q.425 0 .713.288T5 12t-.288.713T4 13H3q-.425 0-.712-.288T2 12t.288-.712T3 11m17 0h1q.425 0 .713.288T22 12t-.288.713T21 13h-1q-.425 0-.712-.288T19 12t.288-.712T20 11m-2.7 8.2l-.7-.7q-.275-.275-.275-.7t.275-.7t.7-.275t.7.275l.7.7q.275.275.275.7t-.275.7t-.7.275t-.7-.275m-12-1.4l.7-.7q.275-.275.7-.275t.7.275t.275.7t-.275.7l-.7.7q-.275.275-.7.275t-.7-.275t-.275-.7t.275-.7M12 17q-2.075 0-3.537-1.462T7 12q0-1.2.538-2.238T9 8V5q0-.825.588-1.412T11 3h2q.825 0 1.413.588T15 5v3q.925.725 1.463 1.763T17 12q0 2.075-1.463 3.538T12 17m-1-9.9q.25-.05.5-.075T12 7t.5.025t.5.075V5h-2zm1 7.9q1.25 0 2.125-.875T15 12t-.875-2.125T12 9t-2.125.875T9 12t.875 2.125T12 15m0-3"
+		/>
+	</svg>
+</template>
+
+<script>
+export default {
+	name: "Bulb",
+};
+</script>
diff --git a/assets/js/components/VehicleIcon/Coffeemaker.vue b/assets/js/components/VehicleIcon/Coffeemaker.vue
new file mode 100644
index 00000000..c6845550
--- /dev/null
+++ b/assets/js/components/VehicleIcon/Coffeemaker.vue
@@ -0,0 +1,14 @@
+<template>
+	<svg width="1em" height="1em" viewBox="0 0 24 24">
+		<path
+			fill="currentColor"
+			d="M6 22q-.825 0-1.412-.587T4 20V4q0-.825.588-1.412T6 2h13q.425 0 .713.288T20 3t-.288.713T19 4h-1v2q0 .425-.288.713T17 7H9q-.425 0-.712-.288T8 6V4H6v16h4.05q-.95-.675-1.5-1.713T8 16v-3q0-.825.588-1.412T10 11h6q.825 0 1.413.588T18 13v3q0 1.25-.55 2.288T15.95 20H19q.425 0 .713.288T20 21t-.288.713T19 22zm7-3q1.25 0 2.125-.875T16 16v-3h-6v3q0 1.25.875 2.125T13 19m0-9q.425 0 .713-.288T14 9t-.288-.712T13 8t-.712.288T12 9t.288.713T13 10m0 3"
+		/>
+	</svg>
+</template>
+
+<script>
+export default {
+	name: "Coffeemaker",
+};
+</script>
diff --git a/assets/js/components/VehicleIcon/Cooking.vue b/assets/js/components/VehicleIcon/Cooking.vue
new file mode 100644
index 00000000..0015a095
--- /dev/null
+++ b/assets/js/components/VehicleIcon/Cooking.vue
@@ -0,0 +1,14 @@
+<template>
+	<svg width="1em" height="1em" viewBox="0 0 24 24">
+		<path
+			fill="currentColor"
+			d="M3.725 7q-.65-.775-.937-1.475T2.475 4q0-.425.313-.712T3.525 3q.375 0 .613.3t.237.7q0 .5.175.925t.6.925q.75.9 1.063 1.613T6.5 9q-.025.425-.35.713T5.4 10q-.35 0-.562-.3t-.213-.675q0-.575-.238-1.05T3.726 7M7.75 7q-.65-.775-.95-1.475T6.475 4q0-.425.313-.712T7.525 3q.375 0 .613.3t.237.7q0 .5.175.925t.6.925q.75.9 1.063 1.613T10.5 9q-.025.425-.35.713T9.4 10q-.35 0-.562-.3t-.213-.675q.025-.575-.213-1.05T7.75 7m4 0q-.65-.775-.95-1.475T10.475 4q0-.425.313-.712T11.525 3q.375 0 .613.3t.237.7q0 .5.175.925t.6.925q.75.9 1.063 1.613T14.5 9q-.025.425-.35.713T13.4 10q-.35 0-.562-.3t-.213-.675q.025-.575-.213-1.05T11.75 7M5 20q-1.25 0-2.125-.875T2 17v-4q0-.425.288-.712T3 12h13.025q.125-.85.675-1.487t1.35-.913l3.675-1.225q.4-.125.775.05T23 9t-.062.775t-.588.5L18.675 11.5q-.3.1-.488.363T18 12.45V17q0 1.25-.875 2.125T15 20zm0-2h10q.425 0 .713-.288T16 17v-3H4v3q0 .425.288.713T5 18m5-2"
+		/>
+	</svg>
+</template>
+
+<script>
+export default {
+	name: "Cooking",
+};
+</script>
diff --git a/assets/js/components/VehicleIcon/Desktop.vue b/assets/js/components/VehicleIcon/Desktop.vue
new file mode 100644
index 00000000..f642b08e
--- /dev/null
+++ b/assets/js/components/VehicleIcon/Desktop.vue
@@ -0,0 +1,14 @@
+<template>
+	<svg width="1em" height="1em" viewBox="0 0 24 24">
+		<path
+			fill="currentColor"
+			d="M10 19v-2H4q-.825 0-1.412-.587T2 15V5q0-.825.588-1.412T4 3h16q.825 0 1.413.588T22 5v10q0 .825-.587 1.413T20 17h-6v2h1q.425 0 .713.288T16 20t-.288.713T15 21H9q-.425 0-.712-.288T8 20t.288-.712T9 19zm-6-4h16V5H4zm0 0V5z"
+		/>
+	</svg>
+</template>
+
+<script>
+export default {
+	name: "Desktop",
+};
+</script>
diff --git a/assets/js/components/VehicleIcon/Dryer.vue b/assets/js/components/VehicleIcon/Dryer.vue
new file mode 100644
index 00000000..d04cf911
--- /dev/null
+++ b/assets/js/components/VehicleIcon/Dryer.vue
@@ -0,0 +1,14 @@
+<template>
+	<svg width="1em" height="1em" viewBox="0 0 24 24">
+		<path
+			fill="currentColor"
+			d="M4 12.6q0-1.65.613-3.062T6.35 7.05l4.6-4.525q.225-.2.5-.312T12 2.1t.55.113t.5.312l4.6 4.525q.725.725 1.263 1.6t.812 1.875q.1.35-.137.613t-.588.337t-.75-.137t-.625-.788t-.562-1.1t-.813-.95L12 4.3L7.75 8.5q-.875.825-1.312 1.863T6 12.6q0 1.9 1.138 3.425t2.887 2.15q.575.2.775.6t.15.75t-.312.588t-.613.137Q7.4 19.575 5.7 17.463T4 12.6m13.375 2.9q-.45-.2-.913-.35T15.5 15q-.4 0-.775.088t-.725.237q-.275.125-.575.025T13 14.975q-.125-.3 0-.6t.425-.425q.5-.2 1.025-.325t1.05-.125q.575 0 1.138.138t1.087.337q.45.2.913.35t.962.15q.4 0 .775-.087t.725-.238q.275-.125.575-.025t.425.375q.125.3 0 .6t-.425.425q-.5.2-1.025.325t-1.05.125q-.575 0-1.137-.137t-1.088-.338m0 3q-.45-.2-.913-.35T15.5 18q-.4 0-.775.088t-.725.237q-.275.125-.575.025T13 17.975q-.125-.3 0-.6t.425-.425q.5-.2 1.025-.325t1.05-.125q.575 0 1.138.137t1.087.338q.45.2.913.35t.962.15q.4 0 .775-.088t.725-.237q.275-.125.575-.025t.425.375q.125.3 0 .6t-.425.425q-.5.2-1.025.325t-1.05.125q-.575 0-1.137-.137t-1.088-.338m0 3q-.45-.2-.913-.35T15.5 21q-.4 0-.775.088t-.725.237q-.275.125-.575.025T13 20.975q-.125-.3 0-.6t.425-.425q.5-.2 1.025-.325t1.05-.125q.575 0 1.138.137t1.087.338q.45.2.913.35t.962.15q.4 0 .775-.088t.725-.237q.275-.125.575-.025t.425.375q.125.3 0 .6t-.425.425q-.5.2-1.025.325t-1.05.125q-.575 0-1.137-.137t-1.088-.338"
+		/>
+	</svg>
+</template>
+
+<script>
+export default {
+	name: "Dryer",
+};
+</script>
diff --git a/assets/js/components/VehicleIcon/Floorlamp.vue b/assets/js/components/VehicleIcon/Floorlamp.vue
new file mode 100644
index 00000000..c96055be
--- /dev/null
+++ b/assets/js/components/VehicleIcon/Floorlamp.vue
@@ -0,0 +1,14 @@
+<template>
+	<svg width="1em" height="1em" viewBox="0 0 24 24">
+		<path
+			fill="currentColor"
+			d="M12 19q-.425 0-.712-.288T11 18v-7H6q-.5 0-.8-.4t-.15-.9L7 3.4q.2-.625.725-1.013T8.9 2h6.2q.65 0 1.175.388T17 3.4l1.95 6.3q.15.5-.15.9t-.8.4h-5v7q0 .425-.288.713T12 19M7.35 9h9.3L15.1 4H8.9zM9 22q-.425 0-.712-.288T8 21t.288-.712T9 20h6q.425 0 .713.288T16 21t-.288.713T15 22zm3-15.5"
+		/>
+	</svg>
+</template>
+
+<script>
+export default {
+	name: "Floorlamp",
+};
+</script>
diff --git a/assets/js/components/VehicleIcon/Heatexchange.vue b/assets/js/components/VehicleIcon/Heatexchange.vue
new file mode 100644
index 00000000..bca74a38
--- /dev/null
+++ b/assets/js/components/VehicleIcon/Heatexchange.vue
@@ -0,0 +1,14 @@
+<template>
+	<svg width="1em" height="1em" viewBox="0 0 24 24">
+		<path
+			fill="currentColor"
+			d="M20.175 7.6H19q-.425 0-.712.288T18 8.6v7q0 1.25-.875 2.125T15 18.6t-2.125-.875T12 15.6v-6q0-.425-.288-.712T11 8.6t-.712.288T10 9.6v6q0 1.25-.875 2.125T7 18.6t-2.125-.875T4 15.6v-8q0-.425.288-.712T5 6.6t.713.288T6 7.6v8q0 .425.288.713T7 16.6t.713-.288T8 15.6v-6q0-1.25.875-2.125T11 6.6t2.125.875T14 9.6v6q0 .425.288.713T15 16.6t.713-.288T16 15.6v-7q0-1.25.875-2.125T19 5.6h1.175l-.475-.475q-.275-.275-.275-.687t.275-.713q.3-.3.713-.3t.712.3L23.3 5.9q.3.3.3.7t-.3.7l-2.2 2.175q-.3.275-.713.288t-.687-.288t-.275-.725t.3-.7zM3 21.6q-.825 0-1.412-.587T1 19.6v-7q0-.425.288-.712T2 11.6h20q.425 0 .713.288T23 12.6v7q0 .825-.587 1.413T21 21.6zm0-2h18v-6H3zm18-6H3z"
+		/>
+	</svg>
+</template>
+
+<script>
+export default {
+	name: "Heatexchange",
+};
+</script>
diff --git a/assets/js/components/VehicleIcon/Kettle.vue b/assets/js/components/VehicleIcon/Kettle.vue
new file mode 100644
index 00000000..452a29e2
--- /dev/null
+++ b/assets/js/components/VehicleIcon/Kettle.vue
@@ -0,0 +1,14 @@
+<template>
+	<svg width="1em" height="1em" viewBox="0 0 24 24">
+		<path
+			fill="currentColor"
+			d="M6 17V6L4.2 3.6q-.375-.5-.1-1.05T5 2h10.775q.925 0 1.575.65T18 4.225V5h2q.825 0 1.413.588T22 7v5q0 .825-.587 1.413T20 14h-2v3q0 .825-.587 1.413T16 19H8q-.825 0-1.412-.587T6 17m2 0h8V4H7l1 1.3zm10-5h2V7h-2zm-4.5-7q-.625 0-1.062.438T12 6.5v8q0 .625.438 1.063T13.5 16t1.063-.437T15 14.5v-8q0-.625-.437-1.062T13.5 5M4 22q-.425 0-.712-.288T3 21t.288-.712T4 20h16q.425 0 .713.288T21 21t-.288.713T20 22zm7.5-11.5"
+		/>
+	</svg>
+</template>
+
+<script>
+export default {
+	name: "Kettle",
+};
+</script>
diff --git a/assets/js/components/VehicleIcon/Laundry2.vue b/assets/js/components/VehicleIcon/Laundry2.vue
new file mode 100644
index 00000000..f22b386e
--- /dev/null
+++ b/assets/js/components/VehicleIcon/Laundry2.vue
@@ -0,0 +1,14 @@
+<template>
+	<svg width="1em" height="1em" viewBox="0 0 24 24">
+		<path
+			fill="currentColor"
+			d="M4.875 9.3L8 7.575V13.5q-.525.05-1.025.163T6 13.975v-3l-1.025.55q-.35.2-.75.088t-.6-.463l-2-3.475q-.2-.35-.088-.762T2 6.3l4.975-2.875q.3-.175.625-.3T8.275 3t.6.213t.375.537q.35.95.913 1.6T12 6t1.838-.65t.912-1.6q.125-.325.388-.537T15.75 3t.663.125t.612.3L22 6.3q.35.2.45.6t-.1.75l-1.975 3.5q-.2.35-.6.463t-.75-.088L18 10.975v4.8l-1.575 1.375q-.1.075-.2.138T16 17.4V7.575L19.125 9.3l1-1.75L16.3 5.325q-.6 1.225-1.763 1.95T12 8t-2.537-.725T7.7 5.325L3.85 7.55zM4 18.625q-.275-.325-.238-.737t.363-.688l1.4-1.2q.575-.5 1.313-.763t1.537-.262t1.525.263t1.3.762l2.9 2.475q.3.25.713.388t.837.137q.45 0 .838-.125t.687-.4l1.4-1.2q.325-.275.738-.25t.687.35t.238.738t-.363.687l-1.4 1.2q-.575.5-1.3.75T15.65 21t-1.537-.25T12.8 20l-2.9-2.475q-.3-.25-.687-.387T8.375 17q-.425 0-.837.138t-.713.387l-1.425 1.2q-.325.275-.725.25T4 18.625"
+		/>
+	</svg>
+</template>
+
+<script>
+export default {
+	name: "Laundry2",
+};
+</script>
diff --git a/assets/js/components/VehicleIcon/Machine.vue b/assets/js/components/VehicleIcon/Machine.vue
new file mode 100644
index 00000000..269c7740
--- /dev/null
+++ b/assets/js/components/VehicleIcon/Machine.vue
@@ -0,0 +1,14 @@
+<template>
+	<svg width="1em" height="1em" viewBox="0 0 24 24">
+		<path
+			fill="currentColor"
+			d="M5.475 21q-.625 0-1.062-.437T3.975 19.5t.438-1.062T5.475 18h1.6l-2.55-8.35q-.675-.375-1.112-1.1T2.975 7q0-1.25.875-2.125T5.975 4q.975 0 1.738.563T8.775 6h3.2V5q0-.425.288-.712T12.975 4q.225 0 .438.1t.362.3l1.7-1.6q.225-.225.538-.288t.612.088l3.9 1.8q.3.15.413.438t-.013.562q-.15.3-.437.388t-.563-.038l-3.6-1.65l-2.35 2.2v1.4l2.35 2.15l3.6-1.65q.275-.125.575-.025t.425.375q.15.3.025.575t-.425.425l-3.9 1.85q-.3.15-.612.087t-.538-.287l-1.7-1.6q-.15.15-.362.275t-.438.125q-.425 0-.712-.287T11.975 9V8h-3.2q-.075.2-.162.375t-.238.375l5 9.25h2.1q.625 0 1.063.438t.437 1.062t-.437 1.063t-1.063.437zm.5-13q.425 0 .713-.288T6.975 7t-.287-.712T5.975 6t-.712.288T4.975 7t.288.713t.712.287m3.15 10h1.95l-4.3-8h-.1zm1.95 0"
+		/>
+	</svg>
+</template>
+
+<script>
+export default {
+	name: "Machine",
+};
+</script>
diff --git a/assets/js/components/VehicleIcon/Microwave.vue b/assets/js/components/VehicleIcon/Microwave.vue
new file mode 100644
index 00000000..c55624df
--- /dev/null
+++ b/assets/js/components/VehicleIcon/Microwave.vue
@@ -0,0 +1,14 @@
+<template>
+	<svg width="1em" height="1em" viewBox="0 0 24 24">
+		<path
+			fill="currentColor"
+			d="M4 20q-.825 0-1.412-.587T2 18V6q0-.825.588-1.412T4 4h16q.825 0 1.413.588T22 6v12q0 .825-.587 1.413T20 20zm0-2h16V6H4zm2-1h8q.425 0 .713-.288T15 16V8q0-.425-.288-.712T14 7H6q-.425 0-.712.288T5 8v8q0 .425.288.713T6 17m12 0q.425 0 .713-.288T19 16t-.288-.712T18 15t-.712.288T17 16t.288.713T18 17M7 15V9h6v6zm11-2q.425 0 .713-.288T19 12t-.288-.712T18 11t-.712.288T17 12t.288.713T18 13m0-4q.425 0 .713-.288T19 8t-.288-.712T18 7t-.712.288T17 8t.288.713T18 9M4 18V6z"
+		/>
+	</svg>
+</template>
+
+<script>
+export default {
+	name: "Microwave",
+};
+</script>
diff --git a/assets/js/components/VehicleIcon/Pump.vue b/assets/js/components/VehicleIcon/Pump.vue
new file mode 100644
index 00000000..6bbf4b13
--- /dev/null
+++ b/assets/js/components/VehicleIcon/Pump.vue
@@ -0,0 +1,14 @@
+<template>
+	<svg width="1em" height="1em" viewBox="0 0 24 24">
+		<path
+			fill="currentColor"
+			d="M12 15q-.825 0-1.412-.587T10 13q0-.575.238-1.137t.912-1.613l.425-.625q.15-.225.425-.225t.425.225l.425.625q.675 1.05.913 1.613T14 13q0 .825-.587 1.413T12 15m-9 2h4.1q-.425-.425-.787-.925T5.675 15H3zm9 0q2.075 0 3.538-1.463T17 12t-1.463-3.537T12 7T8.463 8.463T7 12t1.463 3.538T12 17m6.325-8H21V7h-4.1q.425.425.788.925T18.325 9M3 19q0 .425-.288.713T2 20t-.712-.288T1 19v-6q0-.425.288-.712T2 12t.713.288T3 13h2.075q-.05-.25-.062-.488T5 12q0-2.925 2.038-4.962T12 5h9q0-.425.288-.712T22 4t.713.288T23 5v6q0 .425-.288.713T22 12t-.712-.288T21 11h-2.075q.05.25.063.488T19 12q0 2.925-2.037 4.963T12 19zm0-2v-2zm18-8V7zm-9 3"
+		/>
+	</svg>
+</template>
+
+<script>
+export default {
+	name: "Pump",
+};
+</script>
diff --git a/assets/js/components/VehicleIcon/Rickshaw.vue b/assets/js/components/VehicleIcon/Rickshaw.vue
new file mode 100644
index 00000000..6de4410e
--- /dev/null
+++ b/assets/js/components/VehicleIcon/Rickshaw.vue
@@ -0,0 +1,14 @@
+<template>
+	<svg width="1em" height="1em" viewBox="0 0 24 24">
+		<path
+			fill="currentColor"
+			d="M6 17q-.975 0-1.737-.562T3.2 15H3q-.825 0-1.412-.587T1 13V5q0-.825.588-1.412T3 3h12.05q.45 0 .85.175t.7.525l3.95 4.75q.225.275.338.588T21 9.7v1.45q.875.3 1.438 1.088T23 14q0 1.25-.875 2.125T20 17q-.975 0-1.763-.562T17.15 15h-8.3q-.35.875-1.112 1.438T6 17M3 8h4V5H3zm6 5h5V5H9v3h2q.425 0 .713.288T12 9t-.288.713T11 10H9zm7-4h2.4L16 6.1zM6 15q.425 0 .713-.288T7 14t-.288-.712T6 13t-.712.288T5 14t.288.713T6 15m14 0q.425 0 .713-.288T21 14t-.288-.712T20 13t-.712.288T19 14t.288.713T20 15m-7.725 7.65L7.95 20.475q-.175-.1-.137-.288T8.05 20H11v-1.2q0-.275.238-.425t.487-.025l4.325 2.175q.175.1.138.288T15.95 21H13v1.2q0 .275-.238.425t-.487.025M3 10v3h.15q.35-.875 1.113-1.437T6 11q.275 0 .525.038T7 11.15V10zm13 3h1.15q.225-.65.713-1.137T19 11.15V11h-3zM3 10h4zm13 1h3z"
+		/>
+	</svg>
+</template>
+
+<script>
+export default {
+	name: "Rickshaw",
+};
+</script>
diff --git a/assets/js/components/VehicleIcon/Rocket.vue b/assets/js/components/VehicleIcon/Rocket.vue
new file mode 100644
index 00000000..7be8f75a
--- /dev/null
+++ b/assets/js/components/VehicleIcon/Rocket.vue
@@ -0,0 +1,14 @@
+<template>
+	<svg width="1em" height="1em" viewBox="0 0 24 24">
+		<path
+			fill="currentColor"
+			d="M7.1 11.35q.35-.7.725-1.35t.825-1.3l-1.4-.275l-2.1 2.1zm12.05-6.875q-1.75.05-3.737 1.025T11.8 8.1q-1.05 1.05-1.875 2.25T8.7 12.6l2.85 2.825q1.05-.4 2.25-1.225t2.25-1.875q1.625-1.625 2.6-3.6T19.675 5q0-.1-.038-.2t-.112-.175t-.175-.112t-.2-.038m-5.5 6q-.575-.575-.575-1.412t.575-1.413t1.425-.575t1.425.575t.575 1.413t-.575 1.412t-1.425.575t-1.425-.575m-.85 6.55L13.625 19l2.1-2.1l-.275-1.4q-.65.45-1.3.813t-1.35.712m8.775-13.35q.2 2.75-.9 5.363T17.2 14.025l.5 2.475q.1.5-.05.975t-.5.825L14 21.45q-.375.375-.9.288t-.725-.588l-1.525-3.575L6.575 13.3L3 11.775q-.5-.2-.6-.725t.275-.9L5.825 7q.35-.35.837-.5t.988-.05l2.475.5q2.375-2.375 4.988-3.475t5.362-.9q.2.025.4.113t.35.237t.238.35t.112.4m-17.65 12.3q.875-.875 2.138-.887t2.137.862t.863 2.138t-.888 2.137q-1.2 1.2-2.838 1.425t-3.287.45l.45-3.287q.225-1.637 1.425-2.838m1.425 1.4q-.425.425-.587 1.025T4.5 19.625q.625-.1 1.225-.25T6.75 18.8q.3-.3.325-.725T6.8 17.35t-.725-.288t-.725.313"
+		/>
+	</svg>
+</template>
+
+<script>
+export default {
+	name: "Rocket",
+};
+</script>
diff --git a/assets/js/components/VehicleIcon/Taxi.vue b/assets/js/components/VehicleIcon/Taxi.vue
new file mode 100644
index 00000000..35085120
--- /dev/null
+++ b/assets/js/components/VehicleIcon/Taxi.vue
@@ -0,0 +1,14 @@
+<template>
+	<svg width="1em" height="1em" viewBox="0 0 24 24">
+		<path
+			fill="currentColor"
+			d="M6 19v.5q0 .625-.437 1.063T4.5 21t-1.062-.437T3 19.5v-7.15q0-.175.025-.35t.075-.325L4.975 6.35q.2-.6.725-.975T6.875 5H9V4q0-.425.288-.712T10 3h4q.425 0 .713.288T15 4v1h2.125q.65 0 1.175.375t.725.975l1.875 5.325q.05.15.075.325t.025.35v7.15q0 .625-.437 1.063T19.5 21t-1.062-.437T18 19.5V19zm-.2-9h12.4l-1.05-3H6.85zM5 12v5zm2.5 4q.625 0 1.063-.437T9 14.5t-.437-1.062T7.5 13t-1.062.438T6 14.5t.438 1.063T7.5 16m9 0q.625 0 1.063-.437T18 14.5t-.437-1.062T16.5 13t-1.062.438T15 14.5t.438 1.063T16.5 16M5 17h14v-5H5z"
+		/>
+	</svg>
+</template>
+
+<script>
+export default {
+	name: "Taxi",
+};
+</script>
diff --git a/assets/js/components/VehicleIcon/VehicleIcon.story.vue b/assets/js/components/VehicleIcon/VehicleIcon.story.vue
index 37a8eba4..cd1bb92f 100644
--- a/assets/js/components/VehicleIcon/VehicleIcon.story.vue
+++ b/assets/js/components/VehicleIcon/VehicleIcon.story.vue
@@ -7,23 +7,39 @@ const icons = [
 	"bus",
 	"moped",
 	"motorcycle",
+	"rocket",
 	"scooter",
+	"taxi",
 	"tractor",
+	"rickshaw",
 	"shuttle",
 	"van",
-	"heater",
-	"heatpump",
-	"waterheater",
-	"laundry",
-	"dishwasher",
 	"airpurifier",
+	"battery",
+	"bulb",
 	"climate",
+	"coffeemaker",
+	"compute",
+	"cooking",
 	"cooler",
-	"generic",
+	"desktop",
 	"device",
+	"dishwasher",
+	"dryer",
+	"floorlamp",
+	"generic",
+	"heater",
+	"heatexchange",
+	"heatpump",
+	"kettle",
+	"laundry",
+	"laundry2",
+	"machine",
 	"meter",
-	"compute",
+	"microwave",
+	"pump",
 	"tool",
+	"waterheater",
 ];
 </script>
 
diff --git a/assets/js/components/VehicleIcon/VehicleIcon.vue b/assets/js/components/VehicleIcon/VehicleIcon.vue
index bf61803d..c3e42b2d 100644
--- a/assets/js/components/VehicleIcon/VehicleIcon.vue
+++ b/assets/js/components/VehicleIcon/VehicleIcon.vue
@@ -8,22 +8,38 @@ import "@h2d2/shopicons/es/regular/car3";
 import MultiIcon from "../MultiIcon";
 
 import airpurifier from "./Airpurifier.vue";
+import battery from "./Battery.vue";
 import bike from "./Bike.vue";
+import bulb from "./Bulb.vue";
 import bus from "./Bus.vue";
 import climate from "./Climate.vue";
+import coffeemaker from "./Coffeemaker.vue";
 import compute from "./Compute.vue";
+import cooking from "./Cooking.vue";
 import cooler from "./Cooler.vue";
+import desktop from "./Desktop.vue";
 import device from "./Device.vue";
 import dishwasher from "./Dishwasher.vue";
+import dryer from "./Dryer.vue";
+import floorlamp from "./Floorlamp.vue";
 import generic from "./Generic.vue";
 import heater from "./Heater.vue";
+import heatexchange from "./Heatexchange.vue";
 import heatpump from "./Heatpump.vue";
+import kettle from "./Kettle.vue";
 import laundry from "./Laundry.vue";
+import laundry2 from "./Laundry2.vue";
+import machine from "./Machine.vue";
 import meter from "./Meter.vue";
+import microwave from "./Microwave.vue";
 import moped from "./Moped.vue";
 import motorcycle from "./Motorcycle.vue";
+import pump from "./Pump.vue";
+import rickshaw from "./Rickshaw.vue";
+import rocket from "./Rocket.vue";
 import scooter from "./Scooter.vue";
 import shuttle from "./Shuttle.vue";
+import taxi from "./Taxi.vue";
 import tool from "./Tool.vue";
 import tractor from "./Tractor.vue";
 import van from "./Van.vue";
@@ -31,23 +47,39 @@ import waterheater from "./WaterHeater.vue";
 
 const icons = {
 	airpurifier,
+	battery,
 	bike,
+	bulb,
 	bus,
 	car: "shopicon-regular-car3",
 	climate,
+	coffeemaker,
 	compute,
+	cooking,
 	cooler,
+	desktop,
 	device,
 	dishwasher,
+	dryer,
+	floorlamp,
 	generic,
 	heater,
+	heatexchange,
 	heatpump,
+	kettle,
 	laundry,
+	laundry2,
+	machine,
 	meter,
+	microwave,
 	moped,
 	motorcycle,
+	pump,
+	rickshaw,
+	rocket,
 	scooter,
 	shuttle,
+	taxi,
 	tool,
 	tractor,
 	van,
diff --git a/charger/go-e.go b/charger/go-e.go
index 6418ce86..4f4b3aa0 100644
--- a/charger/go-e.go
+++ b/charger/go-e.go
@@ -38,13 +38,18 @@ type GoE struct {
 }
 
 func init() {
-	registry.Add("go-e", NewGoEFromConfig)
+	registry.Add("go-e", func(other map[string]interface{}) (api.Charger, error) {
+		return newGoEFromConfig(true, other)
+	})
+	registry.Add("go-e-v3", func(other map[string]interface{}) (api.Charger, error) {
+		return newGoEFromConfig(false, other)
+	})
 }
 
-//go:generate decorate -f decorateGoE -b *GoE -r api.Charger -t "api.PhaseSwitcher,Phases1p3p,func(int) error"
+//go:generate decorate -f decorateGoE -b *GoE -r api.Charger -t "api.ChargeRater,ChargedEnergy,func() (float64, error)" -t "api.PhaseSwitcher,Phases1p3p,func(int) error"
 
-// NewGoEFromConfig creates a go-e charger from generic config
-func NewGoEFromConfig(other map[string]interface{}) (api.Charger, error) {
+// newGoEFromConfig creates a go-e charger from generic config
+func newGoEFromConfig(v2 bool, other map[string]interface{}) (api.Charger, error) {
 	cc := struct {
 		Token string
 		URI   string
@@ -61,11 +66,26 @@ func NewGoEFromConfig(other map[string]interface{}) (api.Charger, error) {
 		return nil, errors.New("must have either uri or token")
 	}
 
-	return NewGoE(cc.URI, cc.Token, cc.Cache)
+	c, err := NewGoE(cc.URI, cc.Token, cc.Cache)
+	if err != nil {
+		return nil, err
+	}
+
+	var chargedEnergy func() (float64, error)
+	if v2 {
+		chargedEnergy = c.chargedEnergy
+	}
+
+	var phases1p3p func(int) error
+	if c.api.IsV2() {
+		phases1p3p = c.phases1p3p
+	}
+
+	return decorateGoE(c, chargedEnergy, phases1p3p), nil
 }
 
 // NewGoE creates GoE charger
-func NewGoE(uri, token string, cache time.Duration) (api.Charger, error) {
+func NewGoE(uri, token string, cache time.Duration) (*GoE, error) {
 	c := &GoE{}
 
 	log := util.NewLogger("go-e").Redact(token)
@@ -80,10 +100,6 @@ func NewGoE(uri, token string, cache time.Duration) (api.Charger, error) {
 		return nil, api.ErrSponsorRequired
 	}
 
-	if c.api.IsV2() {
-		return decorateGoE(c, c.phases1p3p), nil
-	}
-
 	return c, nil
 }
 
@@ -203,6 +219,17 @@ func (c *GoE) TotalEnergy() (float64, error) {
 	return resp.TotalEnergy(), err
 }
 
+// chargedEnergy implements the api.ChargeRater interface - v2 only
+// https://github.com/evcc-io/evcc/issues/13726
+func (c *GoE) chargedEnergy() (float64, error) {
+	resp, err := c.api.Status()
+	if err != nil {
+		return 0, err
+	}
+
+	return resp.ChargedEnergy(), err
+}
+
 // phases1p3p implements the api.PhaseSwitcher interface - v2 only
 func (c *GoE) phases1p3p(phases int) error {
 	if phases == 3 {
diff --git a/charger/go-e_decorators.go b/charger/go-e_decorators.go
index 43aac409..ed0a7249 100644
--- a/charger/go-e_decorators.go
+++ b/charger/go-e_decorators.go
@@ -6,17 +6,43 @@ import (
 	"github.com/evcc-io/evcc/api"
 )
 
-func decorateGoE(base *GoE, phaseSwitcher func(int) error) api.Charger {
+func decorateGoE(base *GoE, chargeRater func() (float64, error), phaseSwitcher func(int) error) api.Charger {
 	switch {
-	case phaseSwitcher == nil:
+	case chargeRater == nil && phaseSwitcher == nil:
 		return base
 
-	case phaseSwitcher != nil:
+	case chargeRater != nil && phaseSwitcher == nil:
 		return &struct {
 			*GoE
+			api.ChargeRater
+		}{
+			GoE: base,
+			ChargeRater: &decorateGoEChargeRaterImpl{
+				chargeRater: chargeRater,
+			},
+		}
+
+	case chargeRater == nil && phaseSwitcher != nil:
+		return &struct {
+			*GoE
+			api.PhaseSwitcher
+		}{
+			GoE: base,
+			PhaseSwitcher: &decorateGoEPhaseSwitcherImpl{
+				phaseSwitcher: phaseSwitcher,
+			},
+		}
+
+	case chargeRater != nil && phaseSwitcher != nil:
+		return &struct {
+			*GoE
+			api.ChargeRater
 			api.PhaseSwitcher
 		}{
 			GoE: base,
+			ChargeRater: &decorateGoEChargeRaterImpl{
+				chargeRater: chargeRater,
+			},
 			PhaseSwitcher: &decorateGoEPhaseSwitcherImpl{
 				phaseSwitcher: phaseSwitcher,
 			},
@@ -26,6 +52,14 @@ func decorateGoE(base *GoE, phaseSwitcher func(int) error) api.Charger {
 	return nil
 }
 
+type decorateGoEChargeRaterImpl struct {
+	chargeRater func() (float64, error)
+}
+
+func (impl *decorateGoEChargeRaterImpl) ChargedEnergy() (float64, error) {
+	return impl.chargeRater()
+}
+
 type decorateGoEPhaseSwitcherImpl struct {
 	phaseSwitcher func(int) error
 }
diff --git a/core/stats.go b/core/stats.go
index ea4a082e..d224e357 100644
--- a/core/stats.go
+++ b/core/stats.go
@@ -7,6 +7,7 @@ import (
 	"github.com/evcc-io/evcc/core/keys"
 	"github.com/evcc-io/evcc/server/db"
 	"github.com/evcc-io/evcc/util"
+	"github.com/jinzhu/now"
 )
 
 // publisher gives access to the site's publish function
@@ -33,10 +34,10 @@ func (s *Stats) Update(p publisher) {
 	}
 
 	stats := map[string]map[string]float64{
-		"30d":      s.calculate(30),
-		"365d":     s.calculate(365),
-		"thisYear": s.calculate(time.Now().YearDay()),
-		"total":    s.calculate(365 * 100), // 100 years
+		"30d":      s.calculate(time.Now().AddDate(0, 0, -30)),
+		"365d":     s.calculate(time.Now().AddDate(0, 0, -365)),
+		"thisYear": s.calculate(now.BeginningOfYear()),
+		"total":    s.calculate(time.Time{}),
 	}
 	p.publish(keys.Statistics, stats)
 
@@ -44,7 +45,7 @@ func (s *Stats) Update(p publisher) {
 }
 
 // calculate reads the stats for the last n-days
-func (s *Stats) calculate(days int) map[string]float64 {
+func (s *Stats) calculate(fromDate time.Time) map[string]float64 {
 	result := make(map[string]float64)
 
 	executeQuery := func(selectClause string, whereClause string, fromDate time.Time, dest interface{}) {
@@ -60,7 +61,6 @@ func (s *Stats) calculate(days int) map[string]float64 {
 		}
 	}
 
-	fromDate := time.Now().AddDate(0, 0, -days)
 	var solarPercentage, chargedKWh, avgPrice, avgCo2 float64
 	executeQuery("SUM(charged_kwh * solar_percentage) / SUM(charged_kwh)", "AND solar_percentage IS NOT NULL", fromDate, &solarPercentage)
 	executeQuery("SUM(charged_kwh)", "AND solar_percentage IS NOT NULL", fromDate, &chargedKWh)
diff --git a/templates/definition/charger/go-e-v3.yaml b/templates/definition/charger/go-e-v3.yaml
index af427d07..db523f02 100644
--- a/templates/definition/charger/go-e-v3.yaml
+++ b/templates/definition/charger/go-e-v3.yaml
@@ -9,19 +9,15 @@ requirements:
   description:
     de: |
       Benötigt mindestens Firmware 052.1 oder neuer.
-
       Für 1P/3P-Phasenumschaltung muss die HTTP API v2 im Charger aktiviert sein.
-
       In der Go-E App (Menüpunkt "Auto") sollte die Option "Ausstecken simulieren" aktiviert sein.
     en: |
       Requires firmware 052.1 or later.
-
       For 1P/3P-Phase switching the HTTP API v2 in the charger setup needs to be activated.
-
       The “simulate unplugging” option should be activated in the Go-E app ("Car" menu item).
   evcc: ["sponsorship"]
 params:
   - name: host
 render: |
-  type: go-e
+  type: go-e-v3
   uri: http://{{ .host }}
diff --git a/templates/definition/vehicle/fiat.yaml b/templates/definition/vehicle/fiat.yaml
index 66e7b0c9..f29f02ec 100644
--- a/templates/definition/vehicle/fiat.yaml
+++ b/templates/definition/vehicle/fiat.yaml
@@ -9,13 +9,13 @@ params:
   - name: pin
     mask: true
     help:
-      en: Required for evcc to refresh the SoC while charging.
-      de: Benötigt zur Aktualisierung des Ladestands während der Ladung.
+      en: Required for evcc to refresh the SoC while charging. When connected to TWC3, used to start/stop charging.
+      de: Benötigt zur Aktualisierung des Ladestands während der Ladung. Bei Nutzung mit TWC3 kann der Ladevorgang mittels PIN gestartet und gestoppt werden.
   - preset: vehicle-features
 render: |
   type: fiat
   {{ include "vehicle-base" . }}
   {{- if .pin }}
-  pin: {{ .pin }} # mandatory to deep refresh Soc
+  pin: {{ .pin }} # mandatory to deep refresh Soc & start/stop charge
   {{- end }}
   {{ include "vehicle-features" . }}
diff --git a/util/templates/defaults.yaml b/util/templates/defaults.yaml
index 1db8a105..ba9ecb5e 100644
--- a/util/templates/defaults.yaml
+++ b/util/templates/defaults.yaml
@@ -238,23 +238,40 @@ params:
       - bus
       - moped
       - motorcycle
+      - rocket
       - scooter
+      - taxi
       - tractor
+      - rickshaw
       - shuttle
       - van
-      - heater
-      - heatpump
-      - waterheater
-      - laundry
-      - dishwasher
       - airpurifier
+      - battery
+      - bulb
       - climate
+      - coffeemaker
+      - compute
+      - cooking
       - cooler
-      - generic
+      - desktop
       - device
+      - dishwasher
+      - dryer
+      - floorlamp
+      - generic
+      - heater
+      - heatexchange
+      - heatpump
+      - kettle
+      - laundry
+      - laundry2
+      - machine
       - meter
-      - compute
+      - microwave
+      - pump
       - tool
+      - waterheater
+
   - name: ski
     required: true
     description:
diff --git a/vehicle/fiat.go b/vehicle/fiat.go
index c219069c..dc51cf9e 100644
--- a/vehicle/fiat.go
+++ b/vehicle/fiat.go
@@ -15,6 +15,7 @@ import (
 type Fiat struct {
 	*embed
 	*fiat.Provider
+	*fiat.Controller
 }
 
 func init() {
@@ -59,6 +60,7 @@ func NewFiatFromConfig(other map[string]interface{}) (api.Vehicle, error) {
 
 	if err == nil {
 		v.Provider = fiat.NewProvider(api, cc.VIN, cc.PIN, cc.Expiry, cc.Cache)
+		v.Controller = fiat.NewController(v.Provider, api, cc.VIN, cc.PIN)
 	}
 
 	return v, err
diff --git a/vehicle/fiat/api.go b/vehicle/fiat/api.go
index ef0e0dd4..76e78df7 100644
--- a/vehicle/fiat/api.go
+++ b/vehicle/fiat/api.go
@@ -158,3 +158,35 @@ func (v *API) Action(vin, pin, action, cmd string) (ActionResponse, error) {
 
 	return res, err
 }
+
+func (v *API) UpdateSchedule(vin, pin string, schedules []Schedule) (ActionResponse, error) {
+	var res ActionResponse
+
+	token, err := v.pinAuth(pin)
+	if err != nil {
+		return res, err
+	}
+
+	uri := fmt.Sprintf("%s/v2/accounts/%s/vehicles/%s/ev/schedule", ApiURI, v.identity.UID(), vin)
+
+	data := struct {
+		Command   string     `json:"command"`
+		PinAuth   string     `json:"pinAuth"`
+		Schedules []Schedule `json:"schedules"`
+	}{
+		Command:   "CPPLUS",
+		PinAuth:   token,
+		Schedules: schedules,
+	}
+
+	req, err := v.request(http.MethodPost, uri, request.MarshalJSON(data))
+	if err == nil {
+		err = v.DoJSON(req, &res)
+	}
+
+	if err == nil && res.Message != "" {
+		err = fmt.Errorf("action schedules: %s", res.Message)
+	}
+
+	return res, err
+}
diff --git a/vehicle/fiat/controller.go b/vehicle/fiat/controller.go
new file mode 100644
index 00000000..71b47e80
--- /dev/null
+++ b/vehicle/fiat/controller.go
@@ -0,0 +1,102 @@
+package fiat
+
+import (
+	"fmt"
+	"time"
+
+	"github.com/evcc-io/evcc/api"
+)
+
+type Controller struct {
+	pvd *Provider
+	api *API
+	vin string
+	pin string
+}
+
+// NewController creates a vehicle current and charge controller
+func NewController(provider *Provider, api *API, vin string, pin string) *Controller {
+	impl := &Controller{
+		pvd: provider,
+		api: api,
+		vin: vin,
+		pin: pin,
+	}
+	return impl
+}
+
+var _ api.CurrentController = (*Controller)(nil)
+
+// MaxCurrent implements the api.CurrentController interface
+func (c *Controller) MaxCurrent(current int64) error {
+	// Even if we cannot control the current, this interface must be implemented otherwise the ChargeEnable is never called
+	return nil
+}
+
+var _ api.ChargeController = (*Controller)(nil)
+
+// ChargeEnable implements the api.ChargeController interface
+func (c *Controller) ChargeEnable(enable bool) error {
+	if c.pin == "" {
+		return api.ErrMissingCredentials
+	}
+
+	// get current schedule status from provider (cached)
+	stat, err := c.pvd.statusG()
+	if err != nil {
+		return err
+	}
+	if stat.EvInfo == nil || stat.EvInfo.Schedules == nil || len(stat.EvInfo.Schedules) == 0 {
+		return api.ErrNotAvailable
+	}
+
+	// configure first schedule and make sure it's active
+	c.configureChargeSchedule(&stat.EvInfo.Schedules[0])
+
+	if enable {
+		// start charging by updating active charge schedule to start now and end in 12h
+		stat.EvInfo.Schedules[0].StartTime = time.Now().Format("15:04")                   // only hour and minutes
+		stat.EvInfo.Schedules[0].EndTime = time.Now().Add(time.Hour * 12).Format("15:04") // only hour and minutes
+	} else {
+		// stop charging by updating active charge schedule end time to now
+		stat.EvInfo.Schedules[0].EndTime = time.Now().Format("15:04") // only hour and minutes
+	}
+
+	// make sure the other charge schedules are disabled in case user changed them
+	c.disableConflictingChargeSchedule(&stat.EvInfo.Schedules[1])
+	c.disableConflictingChargeSchedule(&stat.EvInfo.Schedules[2])
+
+	// post new schedule
+	res, err := c.api.UpdateSchedule(c.vin, c.pin, stat.EvInfo.Schedules)
+	if err == nil && res.ResponseStatus != "pending" {
+		err = fmt.Errorf("invalid response status: %s", res.ResponseStatus)
+	}
+
+	return err
+}
+
+func (c *Controller) configureChargeSchedule(schedule *Schedule) {
+	// all values are set to be sure no manual change can lead to inconsistencies
+	schedule.CabinPriority = false
+	schedule.ChargeToFull = false
+	schedule.EnableScheduleType = true
+	schedule.RepeatSchedule = true
+	schedule.ScheduleType = "CHARGE"
+
+	// only enable for current day to avoid undesired charge start in the future
+	weekday := time.Now().Weekday()
+	schedule.ScheduledDays.Monday = (weekday == time.Monday)
+	schedule.ScheduledDays.Tuesday = (weekday == time.Tuesday)
+	schedule.ScheduledDays.Wednesday = (weekday == time.Wednesday)
+	schedule.ScheduledDays.Thursday = (weekday == time.Thursday)
+	schedule.ScheduledDays.Friday = (weekday == time.Friday)
+	schedule.ScheduledDays.Saturday = (weekday == time.Saturday)
+	schedule.ScheduledDays.Sunday = (weekday == time.Sunday)
+}
+
+func (c *Controller) disableConflictingChargeSchedule(schedule *Schedule) {
+	// make sure the other charge schedules are disabled in case user changed them
+	if schedule.ScheduleType == "CHARGE" && schedule.EnableScheduleType {
+		schedule.EnableScheduleType = false
+	}
+}
diff --git a/vehicle/fiat/types.go b/vehicle/fiat/types.go
index c175fba0..babb2467 100644
--- a/vehicle/fiat/types.go
+++ b/vehicle/fiat/types.go
@@ -28,6 +28,25 @@ type Vehicle struct {
 	VIN string
 }
 
+type Schedule struct {
+	CabinPriority      bool   `json:"cabinPriority"`
+	ChargeToFull       bool   `json:"chargeToFull"`
+	EnableScheduleType bool   `json:"enableScheduleType"`
+	EndTime            string `json:"endTime"`
+	RepeatSchedule     bool   `json:"repeatSchedule"`
+	ScheduleType       string `json:"scheduleType"`
+	ScheduledDays      struct {
+		Friday    bool `json:"friday"`
+		Monday    bool `json:"monday"`
+		Saturday  bool `json:"saturday"`
+		Sunday    bool `json:"sunday"`
+		Thursday  bool `json:"thursday"`
+		Tuesday   bool `json:"tuesday"`
+		Wednesday bool `json:"wednesday"`
+	} `json:"scheduledDays"`
+	StartTime string `json:"startTime"`
+}
+
 type StatusResponse struct {
 	VehicleInfo struct {
 		Odometer struct {
@@ -52,6 +71,7 @@ type StatusResponse struct {
 			TimeToFullyChargeL2 int     // 540
 			TotalRange          int     // 17
 		}
+		Schedules []Schedule
 		Timestamp TimeMillis
 	} `json:",omitempty"`
 	Timestamp TimeMillis


Test patch:
diff --git a/charger/go-e_test.go b/charger/go-e_test.go
index 7274e0d0..bb9d3021 100644
--- a/charger/go-e_test.go
+++ b/charger/go-e_test.go
@@ -33,12 +33,11 @@ func (h *handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
 }
 
 func TestGoEV1(t *testing.T) {
-	h := &handler{}
-	srv := httptest.NewServer(h)
+	srv := httptest.NewServer(new(handler))
 
 	sponsor.Subject = "foo"
 
-	wb, err := NewGoE(srv.URL, "", 0)
+	wb, err := newGoEFromConfig(false, map[string]any{"uri": srv.URL})
 	if err != nil {
 		t.Error(err)
 	}
@@ -57,13 +56,12 @@ func TestGoEV1(t *testing.T) {
 }
 
 func TestGoEV2(t *testing.T) {
-	h := &handler{}
-	srv := httptest.NewServer(h)
+	srv := httptest.NewServer(new(handler))
+	srv.Config.Handler.(*handler).expect("/api/status?filter=alw")
 
 	sponsor.Subject = "foo"
 
-	h.expect("/api/status?filter=alw")
-	wb, err := NewGoE(srv.URL, "", 0)
+	wb, err := newGoEFromConfig(false, map[string]any{"uri": srv.URL})
 	if err != nil {
 		t.Error(err)
 	}