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 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);
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");
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");
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);
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");
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);
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(),
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);
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(),
266 assertEquals("246 km", updateListener.getResponse("test::bev:range#radius-electric").toFullString(),
268 assertEquals("307 km", updateListener.getResponse("test::bev:range#range-electric").toFullString(),
269 "Range Radius Update");
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);
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);
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");
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);
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);
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(),
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);
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);
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");
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
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,
377 vh.handleCommand(mileageChannelUID, RefreshType.REFRESH);
378 assertEquals(1, updateListener.updatesReceived.size());
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);
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");
400 updateListener.linked = true;
401 vh.distributeContent(update);
402 assertTrue(updateListener.updatesReceived.containsKey("test::bev:vehicle#proto-update"),
403 "Proto Channel not updated");
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);
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");
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));
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);
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");
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);
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);
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");
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");
503 * Testing UNRECOGNIZED (-1) values in CommandStatus which throws Exception
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();
515 vh.distributeCommandStatus(commandPid);
516 } catch (IllegalArgumentException iae) {