]> git.basschouten.com Git - openhab-addons.git/blob
cf55bd982d810d2e12c3f8e094cfbfafe12d9f89
[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 testBEVPartialChargingUpdate() {
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/PartialUpdate-Charging.json");
191         VEPUpdate update = ProtoConverter.json2Proto(json, false);
192         vh.distributeContent(update);
193         assertEquals(2, updateListener.updatesReceived.size(), "Update Count");
194         assertEquals("2023-09-19 20:45", ((DateTimeType) updateListener.getResponse("test::bev:charge#end-time"))
195                 .format("%1$tY-%1$tm-%1$td %1$tH:%1$tM"), "End of Charge Time");
196         assertEquals("2.1 kW", updateListener.getResponse("test::bev:charge#power").toFullString(), "Charge Power");
197     }
198
199     @Test
200     public void testBEVPartialGPSUpdate() {
201         Thing thingMock = mock(Thing.class);
202         when(thingMock.getThingTypeUID()).thenReturn(Constants.THING_TYPE_BEV);
203         when(thingMock.getUID()).thenReturn(new ThingUID("test", Constants.BEV));
204         VehicleHandler vh = new VehicleHandler(thingMock, new LocationProviderMock(),
205                 mock(MercedesMeCommandOptionProvider.class), mock(MercedesMeStateOptionProvider.class));
206         vh.accountHandler = Optional.of(mock(AccountHandler.class));
207         VehicleConfiguration vehicleConfig = new VehicleConfiguration();
208         vh.config = Optional.of(vehicleConfig);
209         ThingCallbackListener updateListener = new ThingCallbackListener();
210         vh.setCallback(updateListener);
211
212         String json = FileReader.readFileInString("src/test/resources/proto-json/PartialUpdate-GPS.json");
213         VEPUpdate update = ProtoConverter.json2Proto(json, false);
214         vh.distributeContent(update);
215         assertEquals(3, updateListener.updatesReceived.size(), "Update Count");
216         assertEquals("1.23,4.56", updateListener.getResponse("test::bev:position#gps").toFullString(), "GPS update");
217         assertEquals("41.9 °", updateListener.getResponse("test::bev:position#heading").toFullString(),
218                 "Heading Update");
219     }
220
221     @Test
222     public void testBEVPartialRangeUpdate() {
223         Thing thingMock = mock(Thing.class);
224         when(thingMock.getThingTypeUID()).thenReturn(Constants.THING_TYPE_BEV);
225         when(thingMock.getUID()).thenReturn(new ThingUID("test", Constants.BEV));
226         VehicleHandler vh = new VehicleHandler(thingMock, new LocationProviderMock(),
227                 mock(MercedesMeCommandOptionProvider.class), mock(MercedesMeStateOptionProvider.class));
228         vh.accountHandler = Optional.of(mock(AccountHandler.class));
229         VehicleConfiguration vehicleConfig = new VehicleConfiguration();
230         vh.config = Optional.of(vehicleConfig);
231         ThingCallbackListener updateListener = new ThingCallbackListener();
232         vh.setCallback(updateListener);
233
234         String json = FileReader.readFileInString("src/test/resources/proto-json/PartialUpdate-Range.json");
235         VEPUpdate update = ProtoConverter.json2Proto(json, false);
236         vh.distributeContent(update);
237         assertEquals(3, updateListener.updatesReceived.size(), "Update Count");
238         assertEquals("15017 km", updateListener.getResponse("test::bev:range#mileage").toFullString(),
239                 "Mileage Update");
240         assertEquals("246 km", updateListener.getResponse("test::bev:range#radius-electric").toFullString(),
241                 "Range Update");
242         assertEquals("307 km", updateListener.getResponse("test::bev:range#range-electric").toFullString(),
243                 "Range Radius Update");
244     }
245
246     @Test
247     public void testHybridFullUpdateNoCapacities() {
248         Thing thingMock = mock(Thing.class);
249         when(thingMock.getThingTypeUID()).thenReturn(Constants.THING_TYPE_HYBRID);
250         when(thingMock.getUID()).thenReturn(new ThingUID("test", Constants.HYBRID));
251         VehicleHandler vh = new VehicleHandler(thingMock, new LocationProviderMock(),
252                 mock(MercedesMeCommandOptionProvider.class), mock(MercedesMeStateOptionProvider.class));
253         vh.accountHandler = Optional.of(mock(AccountHandler.class));
254         VehicleConfiguration vehicleConfig = new VehicleConfiguration();
255         vh.config = Optional.of(vehicleConfig);
256         ThingCallbackListener updateListener = new ThingCallbackListener();
257         vh.setCallback(updateListener);
258
259         String json = FileReader.readFileInString("src/test/resources/proto-json/MB-Hybrid-Charging.json");
260         VEPUpdate update = ProtoConverter.json2Proto(json, true);
261         vh.distributeContent(update);
262
263         assertEquals(11, updateListener.updatesPerGroupMap.size(), "Group Update Count");
264         assertEquals(10, updateListener.getUpdatesForGroup("doors"), "Doors Update Count");
265         assertEquals(5, updateListener.getUpdatesForGroup("vehicle"), "Vehcile Update Count");
266         assertEquals(8, updateListener.getUpdatesForGroup("windows"), "Windows Update Count");
267         assertEquals(12, updateListener.getUpdatesForGroup("trip"), "Trip Update Count");
268         assertEquals(10, updateListener.getUpdatesForGroup("tires"), "Trip Update Count");
269         assertEquals(8, updateListener.getUpdatesForGroup("service"), "Trip Update Count");
270         assertEquals(14, updateListener.getUpdatesForGroup("range"), "Update Upadte Count");
271         assertEquals(2, updateListener.getUpdatesForGroup("position"), "Update Upadte Count");
272         assertEquals(6, updateListener.getUpdatesForGroup("lock"), "Lock Update Count");
273         assertEquals(7, updateListener.getUpdatesForGroup("hvac"), "HVAC Update Count");
274         assertEquals(7, updateListener.getUpdatesForGroup("charge"), "Charge Update Count");
275     }
276
277     @Test
278     public void testHybridFullUpadteWithCapacities() {
279         Thing thingMock = mock(Thing.class);
280         when(thingMock.getThingTypeUID()).thenReturn(Constants.THING_TYPE_HYBRID);
281         when(thingMock.getUID()).thenReturn(new ThingUID("test", "hybrid"));
282         VehicleHandler vh = new VehicleHandler(thingMock, new LocationProviderMock(),
283                 mock(MercedesMeCommandOptionProvider.class), mock(MercedesMeStateOptionProvider.class));
284         vh.accountHandler = Optional.of(mock(AccountHandler.class));
285         VehicleConfiguration vehicleConfig = new VehicleConfiguration();
286         vehicleConfig.batteryCapacity = (float) 9.2;
287         vehicleConfig.fuelCapacity = (float) 59.9;
288         vh.config = Optional.of(vehicleConfig);
289         ThingCallbackListener updateListener = new ThingCallbackListener();
290         vh.setCallback(updateListener);
291
292         String json = FileReader.readFileInString("src/test/resources/proto-json/MB-Hybrid-Charging.json");
293         VEPUpdate update = ProtoConverter.json2Proto(json, true);
294         vh.distributeContent(update);
295
296         // Test charged / uncharged battery and filled / unfilled tank volume
297         assertEquals("5.800000190734863 kWh", updateListener.getResponse("test::hybrid:range#charged").toFullString(),
298                 "Battery Charged Update");
299         assertEquals("3.4000000953674316 kWh",
300                 updateListener.getResponse("test::hybrid:range#uncharged").toFullString(), "Battery Uncharged Update");
301         assertEquals("9.579999923706055 l", updateListener.getResponse("test::hybrid:range#tank-remain").toFullString(),
302                 "Tank Remain Update");
303         assertEquals("50.31999969482422 l", updateListener.getResponse("test::hybrid:range#tank-open").toFullString(),
304                 "Tank Open Update");
305     }
306
307     @Test
308     public void testEventStorage() {
309         Thing thingMock = mock(Thing.class);
310         when(thingMock.getThingTypeUID()).thenReturn(Constants.THING_TYPE_BEV);
311         when(thingMock.getUID()).thenReturn(new ThingUID("test", Constants.BEV));
312         VehicleHandler vh = new VehicleHandler(thingMock, new LocationProviderMock(),
313                 mock(MercedesMeCommandOptionProvider.class), mock(MercedesMeStateOptionProvider.class));
314         vh.accountHandler = Optional.of(mock(AccountHandler.class));
315         VehicleConfiguration vehicleConfig = new VehicleConfiguration();
316         vh.config = Optional.of(vehicleConfig);
317         ThingCallbackListener updateListener = new ThingCallbackListener();
318         updateListener.linked = true;
319         vh.setCallback(updateListener);
320
321         String json = FileReader.readFileInString("src/test/resources/proto-json/MB-BEV-EQA.json");
322         VEPUpdate update = ProtoConverter.json2Proto(json, true);
323         vh.distributeContent(update);
324
325         assertEquals(11, updateListener.updatesPerGroupMap.size(), "Group Update Count");
326         assertEquals(10, updateListener.getUpdatesForGroup("doors"), "Doors Update Count");
327         // 1 update more due to proto channel connected
328         // assertEquals(6, updateListener.getUpdatesForGroup("vehicle"), "Vehcile Update Count");
329         assertEquals(8, updateListener.getUpdatesForGroup("windows"), "Windows Update Count");
330         assertEquals(12, updateListener.getUpdatesForGroup("trip"), "Trip Update Count");
331         assertEquals(10, updateListener.getUpdatesForGroup("tires"), "Tire Update Count");
332         assertEquals(6, updateListener.getUpdatesForGroup("service"), "Service Update Count");
333         assertEquals(7, updateListener.getUpdatesForGroup("range"), "Range Update Count");
334         assertEquals(2, updateListener.getUpdatesForGroup("position"), "Position Update Count");
335         assertEquals(5, updateListener.getUpdatesForGroup("lock"), "Lock Update Count");
336         assertEquals(7, updateListener.getUpdatesForGroup("hvac"), "HVAC Update Count");
337         assertEquals(10, updateListener.getUpdatesForGroup("charge"), "Charge Update Count");
338
339         /**
340          * VehicleHandler fully updated eventStorage shall contain all data
341          * Let's simulate an item ad causing a RefreshType command
342          * Shall deliver data immediately
343          */
344         assertEquals(83, vh.eventStorage.size());
345         assertEquals(83, updateListener.updatesReceived.size());
346         updateListener = new ThingCallbackListener();
347         vh.setCallback(updateListener);
348         ChannelUID mileageChannelUID = new ChannelUID(new ThingUID("test", Constants.BEV), Constants.GROUP_RANGE,
349                 "mileage");
350
351         vh.handleCommand(mileageChannelUID, RefreshType.REFRESH);
352         assertEquals(1, updateListener.updatesReceived.size());
353     }
354
355     @Test
356     public void testProtoChannelLinked() {
357         Thing thingMock = mock(Thing.class);
358         when(thingMock.getThingTypeUID()).thenReturn(Constants.THING_TYPE_BEV);
359         when(thingMock.getUID()).thenReturn(new ThingUID("test", Constants.BEV));
360         VehicleHandler vh = new VehicleHandler(thingMock, new LocationProviderMock(),
361                 mock(MercedesMeCommandOptionProvider.class), mock(MercedesMeStateOptionProvider.class));
362         vh.accountHandler = Optional.of(mock(AccountHandler.class));
363         VehicleConfiguration vehicleConfig = new VehicleConfiguration();
364         vh.config = Optional.of(vehicleConfig);
365         ThingCallbackListener updateListener = new ThingCallbackListener();
366         vh.setCallback(updateListener);
367
368         String json = FileReader.readFileInString("src/test/resources/proto-json/MB-BEV-EQA.json");
369         VEPUpdate update = ProtoConverter.json2Proto(json, true);
370         vh.distributeContent(update);
371         assertFalse(updateListener.updatesReceived.containsKey("test::bev:vehicle#proto-update"),
372                 "Proto Channel not updated");
373
374         updateListener.linked = true;
375         vh.distributeContent(update);
376         assertTrue(updateListener.updatesReceived.containsKey("test::bev:vehicle#proto-update"),
377                 "Proto Channel not updated");
378     }
379
380     @Test
381     public void testTemperaturePoints() {
382         Thing thingMock = mock(Thing.class);
383         when(thingMock.getThingTypeUID()).thenReturn(Constants.THING_TYPE_BEV);
384         when(thingMock.getUID()).thenReturn(new ThingUID("test", Constants.BEV));
385         VehicleHandler vh = new VehicleHandler(thingMock, new LocationProviderMock(),
386                 mock(MercedesMeCommandOptionProvider.class), mock(MercedesMeStateOptionProvider.class));
387         vh.accountHandler = Optional.of(mock(AccountHandler.class));
388         VehicleConfiguration vehicleConfig = new VehicleConfiguration();
389         vh.config = Optional.of(vehicleConfig);
390         AccountHandlerMock ahm = new AccountHandlerMock();
391         vh.accountHandler = Optional.of(ahm);
392         ThingCallbackListener updateListener = new ThingCallbackListener();
393         vh.setCallback(updateListener);
394
395         String json = FileReader.readFileInString("src/test/resources/proto-json/MB-Unknown.json");
396         VEPUpdate update = ProtoConverter.json2Proto(json, true);
397         vh.distributeContent(update);
398         assertEquals("22 °C", updateListener.getResponse("test::bev:hvac#temperature").toFullString(),
399                 "Temperature Point One Updated");
400
401         ChannelUID cuid = new ChannelUID(thingMock.getUID(), Constants.GROUP_HVAC, "zone");
402         updateListener = new ThingCallbackListener();
403         vh.setCallback(updateListener);
404         vh.handleCommand(cuid, new DecimalType(2));
405         assertEquals("2", updateListener.getResponse("test::bev:hvac#zone").toFullString(),
406                 "Temperature Point One Updated");
407         assertEquals("19 °C", updateListener.getResponse("test::bev:hvac#temperature").toFullString(),
408                 "Temperature Point One Updated");
409         vh.handleCommand(cuid, new DecimalType(-1));
410     }
411
412     @Test
413     public void testTemperaturePointSelection() {
414         Thing thingMock = mock(Thing.class);
415         when(thingMock.getThingTypeUID()).thenReturn(Constants.THING_TYPE_BEV);
416         when(thingMock.getUID()).thenReturn(new ThingUID("test", Constants.BEV));
417         when(thingMock.getProperties()).thenReturn(Map.of(MB_KEY_COMMAND_ZEV_PRECONDITION_CONFIGURE, "true"));
418         AccountHandlerMock ahm = new AccountHandlerMock();
419         VehicleHandler vh = new VehicleHandler(thingMock, new LocationProviderMock(),
420                 mock(MercedesMeCommandOptionProvider.class), mock(MercedesMeStateOptionProvider.class));
421         vh.accountHandler = Optional.of(ahm);
422         VehicleConfiguration vehicleConfig = new VehicleConfiguration();
423         vh.config = Optional.of(vehicleConfig);
424         ThingCallbackListener updateListener = new ThingCallbackListener();
425         vh.setCallback(updateListener);
426         String json = FileReader.readFileInString("src/test/resources/proto-json/MB-Unknown.json");
427         VEPUpdate update = ProtoConverter.json2Proto(json, true);
428         vh.distributeContent(update);
429
430         ChannelUID cuid = new ChannelUID(thingMock.getUID(), Constants.GROUP_HVAC, "temperature");
431         updateListener = new ThingCallbackListener();
432         vh.setCallback(updateListener);
433         vh.handleCommand(cuid, QuantityType.valueOf("18 °C"));
434         assertEquals("frontLeft", ahm.getCommand().get("zone").toString(), "Zone Selection");
435         assertEquals(18, ahm.getCommand().getDouble("temperature_in_celsius"), "Temperature Selection");
436         vh.handleCommand(cuid, QuantityType.valueOf("80 °F"));
437         assertEquals("frontLeft", ahm.getCommand().get("zone").toString(), "Zone Selection");
438         assertEquals(26, ahm.getCommand().getDouble("temperature_in_celsius"), "Temperature Selection");
439     }
440
441     @Test
442     public void testChargeProgramSelection() {
443         Thing thingMock = mock(Thing.class);
444         when(thingMock.getThingTypeUID()).thenReturn(Constants.THING_TYPE_BEV);
445         when(thingMock.getUID()).thenReturn(new ThingUID("test", Constants.BEV));
446         when(thingMock.getProperties()).thenReturn(Map.of(MB_KEY_COMMAND_CHARGE_PROGRAM_CONFIGURE, "true"));
447         AccountHandlerMock ahm = new AccountHandlerMock();
448         VehicleHandler vh = new VehicleHandler(thingMock, new LocationProviderMock(),
449                 mock(MercedesMeCommandOptionProvider.class), mock(MercedesMeStateOptionProvider.class));
450         vh.accountHandler = Optional.of(ahm);
451         VehicleConfiguration vehicleConfig = new VehicleConfiguration();
452         vh.config = Optional.of(vehicleConfig);
453         ThingCallbackListener updateListener = new ThingCallbackListener();
454         vh.setCallback(updateListener);
455
456         String json = FileReader.readFileInString("src/test/resources/proto-json/MB-BEV-EQA.json");
457         VEPUpdate update = ProtoConverter.json2Proto(json, true);
458         vh.distributeContent(update);
459
460         ChannelUID cuid = new ChannelUID(thingMock.getUID(), Constants.GROUP_CHARGE, "max-soc");
461         vh.handleCommand(cuid, QuantityType.valueOf("90 %"));
462         int selectedChargeProgram = ((DecimalType) updateListener.getResponse("test::bev:charge#program")).intValue();
463         assertEquals(selectedChargeProgram,
464                 Utils.getChargeProgramNumber(ahm.getCommand().get("charge_program").toString()),
465                 "Charge Program Command");
466         assertEquals(90, ahm.getCommand().getInt("max_soc"), "Charge Program SOC Setting");
467
468         cuid = new ChannelUID(thingMock.getUID(), Constants.GROUP_CHARGE, "program");
469         vh.handleCommand(cuid, new DecimalType(3));
470         assertEquals(3, Utils.getChargeProgramNumber(ahm.getCommand().get("charge_program").toString()),
471                 "Charge Program Command");
472         assertEquals(100, ahm.getCommand().getInt("max_soc"), "Charge Program SOC Setting");
473     }
474
475     @Test
476     /**
477      * Testing UNRECOGNIZED (-1) values in CommandStatus which throws Exception
478      */
479     public void testCommandDistribution() {
480         Thing thingMock = mock(Thing.class);
481         when(thingMock.getThingTypeUID()).thenReturn(Constants.THING_TYPE_BEV);
482         when(thingMock.getUID()).thenReturn(new ThingUID("test", Constants.BEV));
483         VehicleHandler vh = new VehicleHandler(thingMock, new LocationProviderMock(),
484                 mock(MercedesMeCommandOptionProvider.class), mock(MercedesMeStateOptionProvider.class));
485         AppTwinCommandStatus command = AppTwinCommandStatus.newBuilder().setStateValue(-1).setTypeValue(-1).build();
486         AppTwinCommandStatusUpdatesByPID commandPid = AppTwinCommandStatusUpdatesByPID.newBuilder()
487                 .putUpdatesByPid(Long.MIN_VALUE, command).build();
488         try {
489             vh.distributeCommandStatus(commandPid);
490         } catch (IllegalArgumentException iae) {
491             fail();
492         }
493     }
494 }