2 * Copyright (c) 2010-2024 Contributors to the openHAB project
4 * See the NOTICE file(s) distributed with this work for additional
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
11 * SPDX-License-Identifier: EPL-2.0
13 package org.openhab.binding.mercedesme.internal.handler;
15 import static org.junit.jupiter.api.Assertions.*;
16 import static org.mockito.Mockito.*;
17 import static org.openhab.binding.mercedesme.internal.Constants.*;
20 import java.util.Optional;
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;
41 import com.daimler.mbcarkit.proto.VehicleEvents.VEPUpdate;
42 import com.daimler.mbcarkit.proto.Vehicleapi.AppTwinCommandStatus;
43 import com.daimler.mbcarkit.proto.Vehicleapi.AppTwinCommandStatusUpdatesByPID;
46 * {@link VehicleHandlerTest} check state updates and command sending of vehicles
48 * @author Bernd Weymann - Initial contribution
49 * @author Bernd Weymann - Additional test for https://github.com/openhab/openhab-addons/issues/16932
52 class VehicleHandlerTest {
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);
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);
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");
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);
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);
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);
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"),
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"),
127 assertTrue(updateListener.getResponse("test::bev:hvac#temperature").toFullString().endsWith("°F"),
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");
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");
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);
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);
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");
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);
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");
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);
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(),
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);
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(),
240 assertEquals("246 km", updateListener.getResponse("test::bev:range#radius-electric").toFullString(),
242 assertEquals("307 km", updateListener.getResponse("test::bev:range#range-electric").toFullString(),
243 "Range Radius Update");
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);
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);
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");
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);
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);
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(),
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);
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);
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");
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
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,
351 vh.handleCommand(mileageChannelUID, RefreshType.REFRESH);
352 assertEquals(1, updateListener.updatesReceived.size());
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);
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");
374 updateListener.linked = true;
375 vh.distributeContent(update);
376 assertTrue(updateListener.updatesReceived.containsKey("test::bev:vehicle#proto-update"),
377 "Proto Channel not updated");
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);
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");
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));
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);
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");
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);
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);
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");
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");
477 * Testing UNRECOGNIZED (-1) values in CommandStatus which throws Exception
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();
489 vh.distributeCommandStatus(commandPid);
490 } catch (IllegalArgumentException iae) {