]> git.basschouten.com Git - openhab-addons.git/blob
5ebe6e1ff9c8d0804a2fc7a02b69c4b71398baac
[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.mybmw.internal.dto.charge;
14
15 import static org.junit.jupiter.api.Assertions.assertNotNull;
16 import static org.junit.jupiter.api.Assertions.assertTrue;
17 import static org.junit.jupiter.api.Assertions.fail;
18 import static org.mockito.Mockito.mock;
19 import static org.mockito.Mockito.times;
20 import static org.mockito.Mockito.verify;
21 import static org.mockito.Mockito.when;
22
23 import java.lang.reflect.Field;
24 import java.lang.reflect.Method;
25 import java.time.ZoneId;
26 import java.util.List;
27 import java.util.Map;
28 import java.util.Optional;
29
30 import org.eclipse.jdt.annotation.NonNullByDefault;
31 import org.eclipse.jdt.annotation.Nullable;
32 import org.junit.jupiter.api.Test;
33 import org.mockito.ArgumentCaptor;
34 import org.openhab.binding.mybmw.internal.MyBMWConstants.VehicleType;
35 import org.openhab.binding.mybmw.internal.MyBMWVehicleConfiguration;
36 import org.openhab.binding.mybmw.internal.dto.ChargingStatisticsWrapper;
37 import org.openhab.binding.mybmw.internal.handler.MyBMWCommandOptionProvider;
38 import org.openhab.binding.mybmw.internal.handler.VehicleHandler;
39 import org.openhab.binding.mybmw.internal.handler.backend.JsonStringDeserializer;
40 import org.openhab.binding.mybmw.internal.util.FileReader;
41 import org.openhab.binding.mybmw.internal.utils.Constants;
42 import org.openhab.core.i18n.LocationProvider;
43 import org.openhab.core.i18n.TimeZoneProvider;
44 import org.openhab.core.thing.ChannelUID;
45 import org.openhab.core.thing.Thing;
46 import org.openhab.core.thing.ThingUID;
47 import org.openhab.core.thing.binding.ThingHandlerCallback;
48 import org.openhab.core.types.State;
49 import org.slf4j.Logger;
50 import org.slf4j.LoggerFactory;
51
52 /**
53  * The {@link ChargingStatisticsTest} is responsible for handling commands, which
54  * are
55  * sent to one of the channels.
56  *
57  * @author Bernd Weymann - Initial contribution
58  * @author Martin Grassl - updated to new vehicles
59  */
60 @NonNullByDefault
61 @SuppressWarnings("null")
62 public class ChargingStatisticsTest {
63     private final Logger logger = LoggerFactory.getLogger(VehicleHandler.class);
64
65     private static final int EXPECTED_UPDATE_COUNT = 3;
66
67     @Nullable
68     ArgumentCaptor<ChannelUID> channelCaptor;
69     @Nullable
70     ArgumentCaptor<State> stateCaptor;
71     @Nullable
72     ThingHandlerCallback thingHandlerCallback;
73     @Nullable
74     VehicleHandler vehicleHandler;
75     @Nullable
76     List<ChannelUID> allChannels;
77     @Nullable
78     List<State> allStates;
79     String driveTrain = Constants.EMPTY;
80     boolean imperial;
81
82     /**
83      * Prepare environment for Vehicle Status Updates
84      */
85     public void setup(String type, boolean imperial) {
86         driveTrain = type;
87         this.imperial = imperial;
88         Thing thing = mock(Thing.class);
89         when(thing.getUID()).thenReturn(new ThingUID("testbinding", "test"));
90         MyBMWCommandOptionProvider myBmwCommandOptionProvider = mock(MyBMWCommandOptionProvider.class);
91         LocationProvider locationProvider = mock(LocationProvider.class);
92         TimeZoneProvider timeZoneProvider = mock(TimeZoneProvider.class);
93         when(timeZoneProvider.getTimeZone()).thenReturn(ZoneId.systemDefault());
94         vehicleHandler = new VehicleHandler(thing, myBmwCommandOptionProvider, locationProvider, timeZoneProvider,
95                 type);
96         MyBMWVehicleConfiguration vc = new MyBMWVehicleConfiguration();
97         vc.setVin(Constants.ANONYMOUS);
98
99         try {
100             Field vehicleConfigurationField = VehicleHandler.class.getDeclaredField("vehicleConfiguration");
101             vehicleConfigurationField.setAccessible(true);
102             vehicleConfigurationField.set(vehicleHandler, Optional.of(vc));
103         } catch (Exception e) {
104             logger.error("vehicleConfiguration could not be set", e);
105             fail("vehicleConfiguration could not be set", e);
106         }
107         thingHandlerCallback = mock(ThingHandlerCallback.class);
108         vehicleHandler.setCallback(thingHandlerCallback);
109         channelCaptor = ArgumentCaptor.forClass(ChannelUID.class);
110         stateCaptor = ArgumentCaptor.forClass(State.class);
111     }
112
113     private boolean testVehicle(String statusContent, int callbacksExpected,
114             Optional<Map<String, State>> concreteChecks) {
115         assertNotNull(statusContent);
116
117         try {
118             Method updateChargeStatisticsMethod = VehicleHandler.class.getDeclaredMethod("updateChargingStatistics",
119                     ChargingStatisticsContainer.class, String.class);
120             updateChargeStatisticsMethod.setAccessible(true);
121             updateChargeStatisticsMethod.invoke(vehicleHandler,
122                     JsonStringDeserializer.getChargingStatistics(statusContent), null);
123         } catch (Exception e) {
124             logger.error("chargeStatistics could not be set", e);
125             fail("chargeStatistics could not be set", e);
126         }
127         verify(thingHandlerCallback, times(callbacksExpected)).stateUpdated(channelCaptor.capture(),
128                 stateCaptor.capture());
129         allChannels = channelCaptor.getAllValues();
130         allStates = stateCaptor.getAllValues();
131
132         assertNotNull(driveTrain);
133         ChargingStatisticsWrapper checker = new ChargingStatisticsWrapper(statusContent);
134         trace();
135         return checker.checkResults(allChannels, allStates);
136     }
137
138     private void trace() {
139         for (int i = 0; i < allChannels.size(); i++) {
140             logger.info("Channel {} {}", allChannels.get(i), allStates.get(i));
141         }
142     }
143
144     @Test
145     public void testBevIx() {
146         logger.info("{}", Thread.currentThread().getStackTrace()[1].getMethodName());
147         setup(VehicleType.ELECTRIC_REX.toString(), false);
148         String content = FileReader.fileToString("responses/BEV/charging_statistics.json");
149         assertTrue(testVehicle(content, EXPECTED_UPDATE_COUNT, Optional.empty()));
150     }
151
152     @Test
153     public void testBevIX3() {
154         logger.info("{}", Thread.currentThread().getStackTrace()[1].getMethodName());
155         setup(VehicleType.ELECTRIC_REX.toString(), false);
156         String content = FileReader.fileToString("responses/BEV3/charging_statistics.json");
157         assertTrue(testVehicle(content, EXPECTED_UPDATE_COUNT, Optional.empty()));
158     }
159
160     @Test
161     public void testIceX320d() {
162         logger.info("{}", Thread.currentThread().getStackTrace()[1].getMethodName());
163         setup(VehicleType.PLUGIN_HYBRID.toString(), false);
164         String content = FileReader.fileToString("responses/ICE2/charging_statistics.json");
165         assertTrue(testVehicle(content, EXPECTED_UPDATE_COUNT, Optional.empty()));
166     }
167
168     @Test
169     public void testPhev330e() {
170         logger.info("{}", Thread.currentThread().getStackTrace()[1].getMethodName());
171         setup(VehicleType.PLUGIN_HYBRID.toString(), false);
172         String content = FileReader.fileToString("responses/PHEV2/charging_statistics.json");
173         assertTrue(testVehicle(content, EXPECTED_UPDATE_COUNT, Optional.empty()));
174     }
175 }