]> git.basschouten.com Git - openhab-addons.git/blob
859f5810d67905bcfa0114bc2bc2e370955a0c74
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2023 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.dsmr.internal.discovery;
14
15 import static org.junit.jupiter.api.Assertions.assertNotNull;
16 import static org.junit.jupiter.api.Assertions.assertTrue;
17 import static org.mockito.Mockito.when;
18 import static org.openhab.binding.dsmr.internal.meter.DSMRMeterType.DEVICE_V5;
19 import static org.openhab.binding.dsmr.internal.meter.DSMRMeterType.ELECTRICITY_V4_2;
20 import static org.openhab.binding.dsmr.internal.meter.DSMRMeterType.M3_V5_0;
21
22 import java.util.Collections;
23 import java.util.EnumSet;
24 import java.util.Iterator;
25 import java.util.List;
26 import java.util.concurrent.atomic.AtomicBoolean;
27 import java.util.concurrent.atomic.AtomicReference;
28 import java.util.stream.Collectors;
29
30 import org.eclipse.jdt.annotation.NonNullByDefault;
31 import org.junit.jupiter.api.Test;
32 import org.junit.jupiter.api.extension.ExtendWith;
33 import org.mockito.Answers;
34 import org.mockito.Mock;
35 import org.mockito.junit.jupiter.MockitoExtension;
36 import org.openhab.binding.dsmr.internal.TelegramReaderUtil;
37 import org.openhab.binding.dsmr.internal.device.p1telegram.P1Telegram;
38 import org.openhab.binding.dsmr.internal.handler.DSMRBridgeHandler;
39 import org.openhab.binding.dsmr.internal.handler.DSMRMeterHandler;
40 import org.openhab.binding.dsmr.internal.meter.DSMRMeterDescriptor;
41 import org.openhab.binding.dsmr.internal.meter.DSMRMeterType;
42 import org.openhab.core.thing.Thing;
43 import org.openhab.core.thing.ThingUID;
44
45 /**
46  * Test class for {@link DSMRMeterDiscoveryService}.
47  *
48  * @author Hilbrand Bouwkamp - Initial contribution
49  */
50 @ExtendWith(MockitoExtension.class)
51 @NonNullByDefault
52 public class DSMRMeterDiscoveryServiceTest {
53
54     private static final String EXPECTED_CONFIGURED_TELEGRAM = "dsmr_50";
55     private static final String UNREGISTERED_METER_TELEGRAM = "unregistered_meter";
56
57     private @NonNullByDefault({}) @Mock(answer = Answers.RETURNS_DEEP_STUBS) DSMRBridgeHandler bridge;
58     private @NonNullByDefault({}) @Mock Thing thing;
59     private @NonNullByDefault({}) @Mock DSMRMeterHandler meterHandler;
60
61     /**
62      * Test if discovery reports when the user has incorrectly configured the binding with the wrong meter types.
63      * Some meters are a subset of other meters so it won't generates errors in usage, but some values will not be
64      * available to the user with the subset meter.
65      */
66     @Test
67     public void testInvalidConfiguredMeters() {
68         final P1Telegram expected = TelegramReaderUtil.readTelegram(EXPECTED_CONFIGURED_TELEGRAM);
69         final AtomicReference<List<DSMRMeterType>> invalidConfiguredRef = new AtomicReference<>();
70         final AtomicReference<List<DSMRMeterType>> unconfiguredRef = new AtomicReference<>();
71         final DSMRMeterDiscoveryService service = new DSMRMeterDiscoveryService() {
72             @Override
73             protected void reportConfigurationValidationResults(final List<DSMRMeterType> invalidConfigured,
74                     final List<DSMRMeterType> unconfiguredMeters) {
75                 super.reportConfigurationValidationResults(invalidConfigured, unconfiguredMeters);
76                 invalidConfiguredRef.set(invalidConfigured);
77                 unconfiguredRef.set(unconfiguredMeters);
78             }
79         };
80         service.setThingHandler(bridge);
81
82         // Mock the invalid configuration by reading a telegram that is valid for a meter that is a subset of the
83         // expected meter.
84         final List<DSMRMeterDescriptor> invalidConfiguredMeterDescriptors = EnumSet
85                 .of(DEVICE_V5, ELECTRICITY_V4_2, M3_V5_0).stream().map(mt -> new DSMRMeterDescriptor(mt, 0))
86                 .collect(Collectors.toList());
87         final List<Thing> things = invalidConfiguredMeterDescriptors.stream().map(m -> thing)
88                 .collect(Collectors.toList());
89         final AtomicReference<Iterator<DSMRMeterDescriptor>> detectMetersRef = new AtomicReference<>();
90
91         when((meterHandler).getMeterDescriptor()).then(a -> {
92             if (detectMetersRef.get() == null || !detectMetersRef.get().hasNext()) {
93                 detectMetersRef.set(invalidConfiguredMeterDescriptors.iterator());
94             }
95             return detectMetersRef.get().next();
96         });
97         when(thing.getHandler()).thenReturn(meterHandler);
98         when(bridge.getThing().getUID()).thenReturn(new ThingUID("dsmr:dsmrBridge:22e5393c"));
99         when(bridge.getThing().getThings()).thenReturn(things);
100
101         service.telegramReceived(expected);
102         assertNotNull(invalidConfiguredRef.get(), "Should have invalid configured meters");
103         assertTrue(invalidConfiguredRef.get().contains(DSMRMeterType.ELECTRICITY_V4_2),
104                 "Should have found specific invalid meter");
105         assertNotNull(unconfiguredRef.get(), "Should have undetected meters");
106         assertTrue(unconfiguredRef.get().contains(DSMRMeterType.ELECTRICITY_V5_0),
107                 "Should have found specific undetected meter");
108     }
109
110     /**
111      * Test if discovery correctly reports if a meter was detected that has not been registered with the energy
112      * provider. This meter doesn't report all values in telegram and therefore is not recognized as a specific
113      * meter. But reports with an empty equipment identifier.
114      */
115     @Test
116     public void testUnregisteredMeters() {
117         final P1Telegram telegram = TelegramReaderUtil.readTelegram(UNREGISTERED_METER_TELEGRAM);
118         final AtomicBoolean unregisteredMeter = new AtomicBoolean(false);
119         final DSMRMeterDiscoveryService service = new DSMRMeterDiscoveryService() {
120             @Override
121             protected void reportUnregisteredMeters() {
122                 super.reportUnregisteredMeters();
123                 unregisteredMeter.set(true);
124             }
125         };
126         service.setThingHandler(bridge);
127         when(bridge.getThing().getUID()).thenReturn(new ThingUID("dsmr:dsmrBridge:22e5393c"));
128         when(bridge.getThing().getThings()).thenReturn(Collections.emptyList());
129
130         service.telegramReceived(telegram);
131         assertTrue(unregisteredMeter.get(), "Should have found an unregistered meter");
132     }
133 }