]> git.basschouten.com Git - openhab-addons.git/blob
ce2b93766d2138f6a87e5991cb07a1e596cc8486
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2024 Contributors to the openHAB project
3  *
4  * See the NOTICE file(s) distributed with this work for additional
5  * information.
6  *
7  * This program and the accompanying materials are made available under the
8  * terms of the Eclipse Public License 2.0 which is available at
9  * http://www.eclipse.org/legal/epl-2.0
10  *
11  * SPDX-License-Identifier: EPL-2.0
12  */
13 package org.openhab.binding.mercedesme.internal.handler;
14
15 import static org.junit.jupiter.api.Assertions.*;
16 import static org.mockito.Mockito.*;
17 import static org.openhab.binding.mercedesme.internal.Constants.*;
18
19 import java.util.Map;
20 import java.util.Optional;
21
22 import org.eclipse.jdt.annotation.NonNullByDefault;
23 import org.junit.jupiter.api.Test;
24 import org.openhab.binding.mercedesme.FileReader;
25 import org.openhab.binding.mercedesme.internal.Constants;
26 import org.openhab.binding.mercedesme.internal.MercedesMeCommandOptionProvider;
27 import org.openhab.binding.mercedesme.internal.MercedesMeStateOptionProvider;
28 import org.openhab.binding.mercedesme.internal.config.VehicleConfiguration;
29 import org.openhab.binding.mercedesme.internal.utils.Utils;
30 import org.openhab.core.events.EventPublisher;
31 import org.openhab.core.library.types.DateTimeType;
32 import org.openhab.core.library.types.DecimalType;
33 import org.openhab.core.library.types.QuantityType;
34 import org.openhab.core.thing.ChannelUID;
35 import org.openhab.core.thing.Thing;
36 import org.openhab.core.thing.ThingUID;
37 import org.openhab.core.thing.i18n.ChannelTypeI18nLocalizationService;
38 import org.openhab.core.thing.link.ItemChannelLinkRegistry;
39 import org.openhab.core.types.RefreshType;
40
41 import com.daimler.mbcarkit.proto.VehicleEvents.VEPUpdate;
42 import com.daimler.mbcarkit.proto.Vehicleapi.AppTwinCommandStatus;
43 import com.daimler.mbcarkit.proto.Vehicleapi.AppTwinCommandStatusUpdatesByPID;
44
45 /**
46  * {@link VehicleHandlerTest} check state updates and command sending of vehicles
47  *
48  * @author Bernd Weymann - Initial contribution
49  * @author Bernd Weymann - Additional test for https://github.com/openhab/openhab-addons/issues/16932
50  */
51 @NonNullByDefault
52 class VehicleHandlerTest {
53
54     @Test
55     public void testBEVFullUpdateNoCapacities() {
56         Thing thingMock = mock(Thing.class);
57         when(thingMock.getThingTypeUID()).thenReturn(Constants.THING_TYPE_BEV);
58         when(thingMock.getUID()).thenReturn(new ThingUID("test", Constants.BEV));
59         VehicleHandler vh = new VehicleHandler(thingMock, new LocationProviderMock(),
60                 mock(MercedesMeCommandOptionProvider.class), mock(MercedesMeStateOptionProvider.class));
61         vh.accountHandler = Optional.of(mock(AccountHandler.class));
62         VehicleConfiguration vehicleConfig = new VehicleConfiguration();
63         vh.config = Optional.of(vehicleConfig);
64         ThingCallbackListener updateListener = new ThingCallbackListener();
65         vh.setCallback(updateListener);
66
67         String json = FileReader.readFileInString("src/test/resources/proto-json/MB-BEV-EQA.json");
68         VEPUpdate update = ProtoConverter.json2Proto(json, true);
69         vh.distributeContent(update);
70
71         assertEquals(11, updateListener.updatesPerGroupMap.size(), "Group Update Count");
72         assertEquals(10, updateListener.getUpdatesForGroup("doors"), "Doors Update Count");
73         assertEquals(5, updateListener.getUpdatesForGroup("vehicle"), "Vehcile Update Count");
74         assertEquals(8, updateListener.getUpdatesForGroup("windows"), "Windows Update Count");
75         assertEquals(12, updateListener.getUpdatesForGroup("trip"), "Trip Update Count");
76         assertEquals(10, updateListener.getUpdatesForGroup("tires"), "Tire Update Count");
77         assertEquals(6, updateListener.getUpdatesForGroup("service"), "Service Update Count");
78         assertEquals(7, updateListener.getUpdatesForGroup("range"), "Range Update Count");
79         assertEquals(2, updateListener.getUpdatesForGroup("position"), "Position Update Count");
80         assertEquals(5, updateListener.getUpdatesForGroup("lock"), "Lock Update Count");
81         assertEquals(7, updateListener.getUpdatesForGroup("hvac"), "HVAC Update Count");
82         assertEquals(10, updateListener.getUpdatesForGroup("charge"), "Charge Update Count");
83     }
84
85     @Test
86     public void testBEVImperialUnits() {
87         Thing thingMock = mock(Thing.class);
88         when(thingMock.getThingTypeUID()).thenReturn(Constants.THING_TYPE_BEV);
89         when(thingMock.getUID()).thenReturn(new ThingUID("test", Constants.BEV));
90         MercedesMeDynamicStateDescriptionProviderMock<?> patternMock = new MercedesMeDynamicStateDescriptionProviderMock<>(
91                 mock(EventPublisher.class), mock(ItemChannelLinkRegistry.class),
92                 mock(ChannelTypeI18nLocalizationService.class));
93         MercedesMeCommandOptionProviderMock commandOptionMock = new MercedesMeCommandOptionProviderMock();
94         VehicleHandler vh = new VehicleHandler(thingMock, new LocationProviderMock(), commandOptionMock, patternMock);
95
96         AccountHandlerMock ahm = new AccountHandlerMock();
97         vh.accountHandler = Optional.of(ahm);
98         VehicleConfiguration vehicleConfig = new VehicleConfiguration();
99         vh.config = Optional.of(vehicleConfig);
100         ThingCallbackListener updateListener = new ThingCallbackListener();
101         vh.setCallback(updateListener);
102
103         String json = FileReader.readFileInString("src/test/resources/proto-json/MB-BEV-ImperialUnits.json");
104         VEPUpdate update = ProtoConverter.json2Proto(json, true);
105         vh.distributeContent(update);
106
107         assertEquals(11, updateListener.updatesPerGroupMap.size(), "Group Update Count");
108         assertEquals(10, updateListener.getUpdatesForGroup("doors"), "Doors Update Count");
109         assertEquals(5, updateListener.getUpdatesForGroup("vehicle"), "Vehcile Update Count");
110         assertEquals(8, updateListener.getUpdatesForGroup("windows"), "Windows Update Count");
111         assertEquals(12, updateListener.getUpdatesForGroup("trip"), "Trip Update Count");
112         assertEquals(10, updateListener.getUpdatesForGroup("tires"), "Tire Update Count");
113         assertEquals(6, updateListener.getUpdatesForGroup("service"), "Service Update Count");
114         assertEquals(7, updateListener.getUpdatesForGroup("range"), "Range Update Count");
115         assertEquals(2, updateListener.getUpdatesForGroup("position"), "Position Update Count");
116         assertEquals(5, updateListener.getUpdatesForGroup("lock"), "Lock Update Count");
117         assertEquals(7, updateListener.getUpdatesForGroup("hvac"), "HVAC Update Count");
118         assertEquals(10, updateListener.getUpdatesForGroup("charge"), "Charge Update Count");
119         assertTrue(updateListener.getResponse("test::bev:range#mileage").toFullString().endsWith("mi"),
120                 "Mileague Unit");
121         assertTrue(updateListener.getResponse("test::bev:range#range-electric").toFullString().endsWith("mi"),
122                 "Range Electric Unit");
123         assertTrue(updateListener.getResponse("test::bev:trip#distance").toFullString().endsWith("mi"),
124                 "Range Electric Unit");
125         assertTrue(updateListener.getResponse("test::bev:tires#pressure-front-left").toFullString().endsWith("psi"),
126                 "Pressure Unit");
127         assertTrue(updateListener.getResponse("test::bev:hvac#temperature").toFullString().endsWith("°F"),
128                 "Temperature Unit");
129         assertEquals("%.0f °F", patternMock.patternMap.get("test::bev:hvac#temperature"), "Temperature Pattern");
130         commandOptionMock.getCommandList("test::bev:hvac#temperature").forEach(cmd -> {
131             assertTrue(cmd.getCommand().endsWith(" °F"), "Command Option Fahrenheit Unit");
132         });
133
134         // overwrite with EU Units
135         json = FileReader.readFileInString("src/test/resources/proto-json/MB-BEV-EQA.json");
136         update = ProtoConverter.json2Proto(json, true);
137         vh.distributeContent(update);
138         assertEquals("%.1f °C", patternMock.patternMap.get("test::bev:hvac#temperature"), "Temperature Pattern");
139         commandOptionMock.getCommandList("test::bev:hvac#temperature").forEach(cmd -> {
140             assertTrue(cmd.getCommand().endsWith(" °C"), "Command Option Celsius Unit");
141         });
142     }
143
144     @Test
145     public void testBEVCharging() {
146         Thing thingMock = mock(Thing.class);
147         when(thingMock.getThingTypeUID()).thenReturn(Constants.THING_TYPE_BEV);
148         when(thingMock.getUID()).thenReturn(new ThingUID("test", Constants.BEV));
149         VehicleHandler vh = new VehicleHandler(thingMock, new LocationProviderMock(),
150                 mock(MercedesMeCommandOptionProvider.class), mock(MercedesMeStateOptionProvider.class));
151         vh.accountHandler = Optional.of(mock(AccountHandler.class));
152         VehicleConfiguration vehicleConfig = new VehicleConfiguration();
153         vh.config = Optional.of(vehicleConfig);
154         ThingCallbackListener updateListener = new ThingCallbackListener();
155         vh.setCallback(updateListener);
156
157         String json = FileReader.readFileInString("src/test/resources/proto-json/MB-BEV-EQA-Charging.json");
158         VEPUpdate update = ProtoConverter.json2Proto(json, true);
159         vh.distributeContent(update);
160
161         assertEquals(11, updateListener.updatesPerGroupMap.size(), "Group Update Count");
162         assertEquals(10, updateListener.getUpdatesForGroup("doors"), "Doors Update Count");
163         assertEquals(5, updateListener.getUpdatesForGroup("vehicle"), "Vehcile Update Count");
164         assertEquals(8, updateListener.getUpdatesForGroup("windows"), "Windows Update Count");
165         assertEquals(12, updateListener.getUpdatesForGroup("trip"), "Trip Update Count");
166         assertEquals(10, updateListener.getUpdatesForGroup("tires"), "Tire Update Count");
167         assertEquals(6, updateListener.getUpdatesForGroup("service"), "Service Update Count");
168         assertEquals(7, updateListener.getUpdatesForGroup("range"), "Range Update Count");
169         assertEquals(2, updateListener.getUpdatesForGroup("position"), "Position Update Count");
170         assertEquals(5, updateListener.getUpdatesForGroup("lock"), "Lock Update Count");
171         assertEquals(7, updateListener.getUpdatesForGroup("hvac"), "HVAC Update Count");
172         assertEquals(10, updateListener.getUpdatesForGroup("charge"), "Charge Update Count");
173         assertEquals("2023-09-06 13:55", ((DateTimeType) updateListener.getResponse("test::bev:charge#end-time"))
174                 .format("%1$tY-%1$tm-%1$td %1$tH:%1$tM"), "End of Charge Time");
175     }
176
177     @Test
178     public void testBEVChargeEndtime() {
179         Thing thingMock = mock(Thing.class);
180         when(thingMock.getThingTypeUID()).thenReturn(Constants.THING_TYPE_BEV);
181         when(thingMock.getUID()).thenReturn(new ThingUID("test", Constants.BEV));
182         VehicleHandler vh = new VehicleHandler(thingMock, new LocationProviderMock(),
183                 mock(MercedesMeCommandOptionProvider.class), mock(MercedesMeStateOptionProvider.class));
184         vh.accountHandler = Optional.of(mock(AccountHandler.class));
185         VehicleConfiguration vehicleConfig = new VehicleConfiguration();
186         vh.config = Optional.of(vehicleConfig);
187         ThingCallbackListener updateListener = new ThingCallbackListener();
188         vh.setCallback(updateListener);
189
190         String json = FileReader.readFileInString("src/test/resources/proto-json/MB-BEV-EQA-Charging-Weekday.json");
191         VEPUpdate update = ProtoConverter.json2Proto(json, true);
192         vh.distributeContent(update);
193         assertEquals("2023-09-09 13:54", ((DateTimeType) updateListener.getResponse("test::bev:charge#end-time"))
194                 .format("%1$tY-%1$tm-%1$td %1$tH:%1$tM"), "End of Charge Time");
195
196         json = FileReader.readFileInString("src/test/resources/proto-json/MB-BEV-EQA-Charging-Weekday-Underrun.json");
197         update = ProtoConverter.json2Proto(json, true);
198         vh.distributeContent(update);
199         assertEquals("2023-09-11 13:55", ((DateTimeType) updateListener.getResponse("test::bev:charge#end-time"))
200                 .format("%1$tY-%1$tm-%1$td %1$tH:%1$tM"), "End of Charge Time");
201     }
202
203     @Test
204     public void testBEVPartialChargingUpdate() {
205         Thing thingMock = mock(Thing.class);
206         when(thingMock.getThingTypeUID()).thenReturn(Constants.THING_TYPE_BEV);
207         when(thingMock.getUID()).thenReturn(new ThingUID("test", Constants.BEV));
208         VehicleHandler vh = new VehicleHandler(thingMock, new LocationProviderMock(),
209                 mock(MercedesMeCommandOptionProvider.class), mock(MercedesMeStateOptionProvider.class));
210         vh.accountHandler = Optional.of(mock(AccountHandler.class));
211         VehicleConfiguration vehicleConfig = new VehicleConfiguration();
212         vh.config = Optional.of(vehicleConfig);
213         ThingCallbackListener updateListener = new ThingCallbackListener();
214         vh.setCallback(updateListener);
215
216         String json = FileReader.readFileInString("src/test/resources/proto-json/PartialUpdate-Charging.json");
217         VEPUpdate update = ProtoConverter.json2Proto(json, false);
218         vh.distributeContent(update);
219         assertEquals(2, updateListener.updatesReceived.size(), "Update Count");
220         assertEquals("2023-09-19 20:45", ((DateTimeType) updateListener.getResponse("test::bev:charge#end-time"))
221                 .format("%1$tY-%1$tm-%1$td %1$tH:%1$tM"), "End of Charge Time");
222         assertEquals("2.1 kW", updateListener.getResponse("test::bev:charge#power").toFullString(), "Charge Power");
223     }
224
225     @Test
226     public void testBEVPartialGPSUpdate() {
227         Thing thingMock = mock(Thing.class);
228         when(thingMock.getThingTypeUID()).thenReturn(Constants.THING_TYPE_BEV);
229         when(thingMock.getUID()).thenReturn(new ThingUID("test", Constants.BEV));
230         VehicleHandler vh = new VehicleHandler(thingMock, new LocationProviderMock(),
231                 mock(MercedesMeCommandOptionProvider.class), mock(MercedesMeStateOptionProvider.class));
232         vh.accountHandler = Optional.of(mock(AccountHandler.class));
233         VehicleConfiguration vehicleConfig = new VehicleConfiguration();
234         vh.config = Optional.of(vehicleConfig);
235         ThingCallbackListener updateListener = new ThingCallbackListener();
236         vh.setCallback(updateListener);
237
238         String json = FileReader.readFileInString("src/test/resources/proto-json/PartialUpdate-GPS.json");
239         VEPUpdate update = ProtoConverter.json2Proto(json, false);
240         vh.distributeContent(update);
241         assertEquals(3, updateListener.updatesReceived.size(), "Update Count");
242         assertEquals("1.23,4.56", updateListener.getResponse("test::bev:position#gps").toFullString(), "GPS update");
243         assertEquals("41.9 °", updateListener.getResponse("test::bev:position#heading").toFullString(),
244                 "Heading Update");
245     }
246
247     @Test
248     public void testBEVPartialRangeUpdate() {
249         Thing thingMock = mock(Thing.class);
250         when(thingMock.getThingTypeUID()).thenReturn(Constants.THING_TYPE_BEV);
251         when(thingMock.getUID()).thenReturn(new ThingUID("test", Constants.BEV));
252         VehicleHandler vh = new VehicleHandler(thingMock, new LocationProviderMock(),
253                 mock(MercedesMeCommandOptionProvider.class), mock(MercedesMeStateOptionProvider.class));
254         vh.accountHandler = Optional.of(mock(AccountHandler.class));
255         VehicleConfiguration vehicleConfig = new VehicleConfiguration();
256         vh.config = Optional.of(vehicleConfig);
257         ThingCallbackListener updateListener = new ThingCallbackListener();
258         vh.setCallback(updateListener);
259
260         String json = FileReader.readFileInString("src/test/resources/proto-json/PartialUpdate-Range.json");
261         VEPUpdate update = ProtoConverter.json2Proto(json, false);
262         vh.distributeContent(update);
263         assertEquals(3, updateListener.updatesReceived.size(), "Update Count");
264         assertEquals("15017 km", updateListener.getResponse("test::bev:range#mileage").toFullString(),
265                 "Mileage Update");
266         assertEquals("246 km", updateListener.getResponse("test::bev:range#radius-electric").toFullString(),
267                 "Range Update");
268         assertEquals("307 km", updateListener.getResponse("test::bev:range#range-electric").toFullString(),
269                 "Range Radius Update");
270     }
271
272     @Test
273     public void testHybridFullUpdateNoCapacities() {
274         Thing thingMock = mock(Thing.class);
275         when(thingMock.getThingTypeUID()).thenReturn(Constants.THING_TYPE_HYBRID);
276         when(thingMock.getUID()).thenReturn(new ThingUID("test", Constants.HYBRID));
277         VehicleHandler vh = new VehicleHandler(thingMock, new LocationProviderMock(),
278                 mock(MercedesMeCommandOptionProvider.class), mock(MercedesMeStateOptionProvider.class));
279         vh.accountHandler = Optional.of(mock(AccountHandler.class));
280         VehicleConfiguration vehicleConfig = new VehicleConfiguration();
281         vh.config = Optional.of(vehicleConfig);
282         ThingCallbackListener updateListener = new ThingCallbackListener();
283         vh.setCallback(updateListener);
284
285         String json = FileReader.readFileInString("src/test/resources/proto-json/MB-Hybrid-Charging.json");
286         VEPUpdate update = ProtoConverter.json2Proto(json, true);
287         vh.distributeContent(update);
288
289         assertEquals(11, updateListener.updatesPerGroupMap.size(), "Group Update Count");
290         assertEquals(10, updateListener.getUpdatesForGroup("doors"), "Doors Update Count");
291         assertEquals(5, updateListener.getUpdatesForGroup("vehicle"), "Vehcile Update Count");
292         assertEquals(8, updateListener.getUpdatesForGroup("windows"), "Windows Update Count");
293         assertEquals(12, updateListener.getUpdatesForGroup("trip"), "Trip Update Count");
294         assertEquals(10, updateListener.getUpdatesForGroup("tires"), "Trip Update Count");
295         assertEquals(8, updateListener.getUpdatesForGroup("service"), "Trip Update Count");
296         assertEquals(14, updateListener.getUpdatesForGroup("range"), "Update Upadte Count");
297         assertEquals(2, updateListener.getUpdatesForGroup("position"), "Update Upadte Count");
298         assertEquals(6, updateListener.getUpdatesForGroup("lock"), "Lock Update Count");
299         assertEquals(7, updateListener.getUpdatesForGroup("hvac"), "HVAC Update Count");
300         assertEquals(7, updateListener.getUpdatesForGroup("charge"), "Charge Update Count");
301     }
302
303     @Test
304     public void testHybridFullUpadteWithCapacities() {
305         Thing thingMock = mock(Thing.class);
306         when(thingMock.getThingTypeUID()).thenReturn(Constants.THING_TYPE_HYBRID);
307         when(thingMock.getUID()).thenReturn(new ThingUID("test", "hybrid"));
308         VehicleHandler vh = new VehicleHandler(thingMock, new LocationProviderMock(),
309                 mock(MercedesMeCommandOptionProvider.class), mock(MercedesMeStateOptionProvider.class));
310         vh.accountHandler = Optional.of(mock(AccountHandler.class));
311         VehicleConfiguration vehicleConfig = new VehicleConfiguration();
312         vehicleConfig.batteryCapacity = (float) 9.2;
313         vehicleConfig.fuelCapacity = (float) 59.9;
314         vh.config = Optional.of(vehicleConfig);
315         ThingCallbackListener updateListener = new ThingCallbackListener();
316         vh.setCallback(updateListener);
317
318         String json = FileReader.readFileInString("src/test/resources/proto-json/MB-Hybrid-Charging.json");
319         VEPUpdate update = ProtoConverter.json2Proto(json, true);
320         vh.distributeContent(update);
321
322         // Test charged / uncharged battery and filled / unfilled tank volume
323         assertEquals("5.800000190734863 kWh", updateListener.getResponse("test::hybrid:range#charged").toFullString(),
324                 "Battery Charged Update");
325         assertEquals("3.4000000953674316 kWh",
326                 updateListener.getResponse("test::hybrid:range#uncharged").toFullString(), "Battery Uncharged Update");
327         assertEquals("9.579999923706055 l", updateListener.getResponse("test::hybrid:range#tank-remain").toFullString(),
328                 "Tank Remain Update");
329         assertEquals("50.31999969482422 l", updateListener.getResponse("test::hybrid:range#tank-open").toFullString(),
330                 "Tank Open Update");
331     }
332
333     @Test
334     public void testEventStorage() {
335         Thing thingMock = mock(Thing.class);
336         when(thingMock.getThingTypeUID()).thenReturn(Constants.THING_TYPE_BEV);
337         when(thingMock.getUID()).thenReturn(new ThingUID("test", Constants.BEV));
338         VehicleHandler vh = new VehicleHandler(thingMock, new LocationProviderMock(),
339                 mock(MercedesMeCommandOptionProvider.class), mock(MercedesMeStateOptionProvider.class));
340         vh.accountHandler = Optional.of(mock(AccountHandler.class));
341         VehicleConfiguration vehicleConfig = new VehicleConfiguration();
342         vh.config = Optional.of(vehicleConfig);
343         ThingCallbackListener updateListener = new ThingCallbackListener();
344         updateListener.linked = true;
345         vh.setCallback(updateListener);
346
347         String json = FileReader.readFileInString("src/test/resources/proto-json/MB-BEV-EQA.json");
348         VEPUpdate update = ProtoConverter.json2Proto(json, true);
349         vh.distributeContent(update);
350
351         assertEquals(11, updateListener.updatesPerGroupMap.size(), "Group Update Count");
352         assertEquals(10, updateListener.getUpdatesForGroup("doors"), "Doors Update Count");
353         // 1 update more due to proto channel connected
354         // assertEquals(6, updateListener.getUpdatesForGroup("vehicle"), "Vehcile Update Count");
355         assertEquals(8, updateListener.getUpdatesForGroup("windows"), "Windows Update Count");
356         assertEquals(12, updateListener.getUpdatesForGroup("trip"), "Trip Update Count");
357         assertEquals(10, updateListener.getUpdatesForGroup("tires"), "Tire Update Count");
358         assertEquals(6, updateListener.getUpdatesForGroup("service"), "Service Update Count");
359         assertEquals(7, updateListener.getUpdatesForGroup("range"), "Range Update Count");
360         assertEquals(2, updateListener.getUpdatesForGroup("position"), "Position Update Count");
361         assertEquals(5, updateListener.getUpdatesForGroup("lock"), "Lock Update Count");
362         assertEquals(7, updateListener.getUpdatesForGroup("hvac"), "HVAC Update Count");
363         assertEquals(10, updateListener.getUpdatesForGroup("charge"), "Charge Update Count");
364
365         /**
366          * VehicleHandler fully updated eventStorage shall contain all data
367          * Let's simulate an item ad causing a RefreshType command
368          * Shall deliver data immediately
369          */
370         assertEquals(83, vh.eventStorage.size());
371         assertEquals(83, updateListener.updatesReceived.size());
372         updateListener = new ThingCallbackListener();
373         vh.setCallback(updateListener);
374         ChannelUID mileageChannelUID = new ChannelUID(new ThingUID("test", Constants.BEV), Constants.GROUP_RANGE,
375                 "mileage");
376
377         vh.handleCommand(mileageChannelUID, RefreshType.REFRESH);
378         assertEquals(1, updateListener.updatesReceived.size());
379     }
380
381     @Test
382     public void testProtoChannelLinked() {
383         Thing thingMock = mock(Thing.class);
384         when(thingMock.getThingTypeUID()).thenReturn(Constants.THING_TYPE_BEV);
385         when(thingMock.getUID()).thenReturn(new ThingUID("test", Constants.BEV));
386         VehicleHandler vh = new VehicleHandler(thingMock, new LocationProviderMock(),
387                 mock(MercedesMeCommandOptionProvider.class), mock(MercedesMeStateOptionProvider.class));
388         vh.accountHandler = Optional.of(mock(AccountHandler.class));
389         VehicleConfiguration vehicleConfig = new VehicleConfiguration();
390         vh.config = Optional.of(vehicleConfig);
391         ThingCallbackListener updateListener = new ThingCallbackListener();
392         vh.setCallback(updateListener);
393
394         String json = FileReader.readFileInString("src/test/resources/proto-json/MB-BEV-EQA.json");
395         VEPUpdate update = ProtoConverter.json2Proto(json, true);
396         vh.distributeContent(update);
397         assertFalse(updateListener.updatesReceived.containsKey("test::bev:vehicle#proto-update"),
398                 "Proto Channel not updated");
399
400         updateListener.linked = true;
401         vh.distributeContent(update);
402         assertTrue(updateListener.updatesReceived.containsKey("test::bev:vehicle#proto-update"),
403                 "Proto Channel not updated");
404     }
405
406     @Test
407     public void testTemperaturePoints() {
408         Thing thingMock = mock(Thing.class);
409         when(thingMock.getThingTypeUID()).thenReturn(Constants.THING_TYPE_BEV);
410         when(thingMock.getUID()).thenReturn(new ThingUID("test", Constants.BEV));
411         VehicleHandler vh = new VehicleHandler(thingMock, new LocationProviderMock(),
412                 mock(MercedesMeCommandOptionProvider.class), mock(MercedesMeStateOptionProvider.class));
413         vh.accountHandler = Optional.of(mock(AccountHandler.class));
414         VehicleConfiguration vehicleConfig = new VehicleConfiguration();
415         vh.config = Optional.of(vehicleConfig);
416         AccountHandlerMock ahm = new AccountHandlerMock();
417         vh.accountHandler = Optional.of(ahm);
418         ThingCallbackListener updateListener = new ThingCallbackListener();
419         vh.setCallback(updateListener);
420
421         String json = FileReader.readFileInString("src/test/resources/proto-json/MB-Unknown.json");
422         VEPUpdate update = ProtoConverter.json2Proto(json, true);
423         vh.distributeContent(update);
424         assertEquals("22 °C", updateListener.getResponse("test::bev:hvac#temperature").toFullString(),
425                 "Temperature Point One Updated");
426
427         ChannelUID cuid = new ChannelUID(thingMock.getUID(), Constants.GROUP_HVAC, "zone");
428         updateListener = new ThingCallbackListener();
429         vh.setCallback(updateListener);
430         vh.handleCommand(cuid, new DecimalType(2));
431         assertEquals("2", updateListener.getResponse("test::bev:hvac#zone").toFullString(),
432                 "Temperature Point One Updated");
433         assertEquals("19 °C", updateListener.getResponse("test::bev:hvac#temperature").toFullString(),
434                 "Temperature Point One Updated");
435         vh.handleCommand(cuid, new DecimalType(-1));
436     }
437
438     @Test
439     public void testTemperaturePointSelection() {
440         Thing thingMock = mock(Thing.class);
441         when(thingMock.getThingTypeUID()).thenReturn(Constants.THING_TYPE_BEV);
442         when(thingMock.getUID()).thenReturn(new ThingUID("test", Constants.BEV));
443         when(thingMock.getProperties()).thenReturn(Map.of(MB_KEY_COMMAND_ZEV_PRECONDITION_CONFIGURE, "true"));
444         AccountHandlerMock ahm = new AccountHandlerMock();
445         VehicleHandler vh = new VehicleHandler(thingMock, new LocationProviderMock(),
446                 mock(MercedesMeCommandOptionProvider.class), mock(MercedesMeStateOptionProvider.class));
447         vh.accountHandler = Optional.of(ahm);
448         VehicleConfiguration vehicleConfig = new VehicleConfiguration();
449         vh.config = Optional.of(vehicleConfig);
450         ThingCallbackListener updateListener = new ThingCallbackListener();
451         vh.setCallback(updateListener);
452         String json = FileReader.readFileInString("src/test/resources/proto-json/MB-Unknown.json");
453         VEPUpdate update = ProtoConverter.json2Proto(json, true);
454         vh.distributeContent(update);
455
456         ChannelUID cuid = new ChannelUID(thingMock.getUID(), Constants.GROUP_HVAC, "temperature");
457         updateListener = new ThingCallbackListener();
458         vh.setCallback(updateListener);
459         vh.handleCommand(cuid, QuantityType.valueOf("18 °C"));
460         assertEquals("frontLeft", ahm.getCommand().get("zone").toString(), "Zone Selection");
461         assertEquals(18, ahm.getCommand().getDouble("temperature_in_celsius"), "Temperature Selection");
462         vh.handleCommand(cuid, QuantityType.valueOf("80 °F"));
463         assertEquals("frontLeft", ahm.getCommand().get("zone").toString(), "Zone Selection");
464         assertEquals(26, ahm.getCommand().getDouble("temperature_in_celsius"), "Temperature Selection");
465     }
466
467     @Test
468     public void testChargeProgramSelection() {
469         Thing thingMock = mock(Thing.class);
470         when(thingMock.getThingTypeUID()).thenReturn(Constants.THING_TYPE_BEV);
471         when(thingMock.getUID()).thenReturn(new ThingUID("test", Constants.BEV));
472         when(thingMock.getProperties()).thenReturn(Map.of(MB_KEY_COMMAND_CHARGE_PROGRAM_CONFIGURE, "true"));
473         AccountHandlerMock ahm = new AccountHandlerMock();
474         VehicleHandler vh = new VehicleHandler(thingMock, new LocationProviderMock(),
475                 mock(MercedesMeCommandOptionProvider.class), mock(MercedesMeStateOptionProvider.class));
476         vh.accountHandler = Optional.of(ahm);
477         VehicleConfiguration vehicleConfig = new VehicleConfiguration();
478         vh.config = Optional.of(vehicleConfig);
479         ThingCallbackListener updateListener = new ThingCallbackListener();
480         vh.setCallback(updateListener);
481
482         String json = FileReader.readFileInString("src/test/resources/proto-json/MB-BEV-EQA.json");
483         VEPUpdate update = ProtoConverter.json2Proto(json, true);
484         vh.distributeContent(update);
485
486         ChannelUID cuid = new ChannelUID(thingMock.getUID(), Constants.GROUP_CHARGE, "max-soc");
487         vh.handleCommand(cuid, QuantityType.valueOf("90 %"));
488         int selectedChargeProgram = ((DecimalType) updateListener.getResponse("test::bev:charge#program")).intValue();
489         assertEquals(selectedChargeProgram,
490                 Utils.getChargeProgramNumber(ahm.getCommand().get("charge_program").toString()),
491                 "Charge Program Command");
492         assertEquals(90, ahm.getCommand().getInt("max_soc"), "Charge Program SOC Setting");
493
494         cuid = new ChannelUID(thingMock.getUID(), Constants.GROUP_CHARGE, "program");
495         vh.handleCommand(cuid, new DecimalType(3));
496         assertEquals(3, Utils.getChargeProgramNumber(ahm.getCommand().get("charge_program").toString()),
497                 "Charge Program Command");
498         assertEquals(100, ahm.getCommand().getInt("max_soc"), "Charge Program SOC Setting");
499     }
500
501     @Test
502     /**
503      * Testing UNRECOGNIZED (-1) values in CommandStatus which throws Exception
504      */
505     public void testCommandDistribution() {
506         Thing thingMock = mock(Thing.class);
507         when(thingMock.getThingTypeUID()).thenReturn(Constants.THING_TYPE_BEV);
508         when(thingMock.getUID()).thenReturn(new ThingUID("test", Constants.BEV));
509         VehicleHandler vh = new VehicleHandler(thingMock, new LocationProviderMock(),
510                 mock(MercedesMeCommandOptionProvider.class), mock(MercedesMeStateOptionProvider.class));
511         AppTwinCommandStatus command = AppTwinCommandStatus.newBuilder().setStateValue(-1).setTypeValue(-1).build();
512         AppTwinCommandStatusUpdatesByPID commandPid = AppTwinCommandStatusUpdatesByPID.newBuilder()
513                 .putUpdatesByPid(Long.MIN_VALUE, command).build();
514         try {
515             vh.distributeCommandStatus(commandPid);
516         } catch (IllegalArgumentException iae) {
517             fail();
518         }
519     }
520 }