2 * Copyright (c) 2010-2023 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.onewire.device;
15 import static org.junit.jupiter.api.Assertions.*;
16 import static org.mockito.ArgumentMatchers.eq;
17 import static org.openhab.binding.onewire.internal.OwBindingConstants.*;
19 import java.util.Arrays;
20 import java.util.BitSet;
21 import java.util.HashMap;
24 import org.eclipse.jdt.annotation.NonNullByDefault;
25 import org.junit.jupiter.api.BeforeEach;
26 import org.junit.jupiter.api.Test;
27 import org.mockito.ArgumentCaptor;
28 import org.mockito.InOrder;
29 import org.mockito.Mockito;
30 import org.openhab.binding.onewire.internal.OwException;
31 import org.openhab.binding.onewire.internal.device.BAE0910;
32 import org.openhab.binding.onewire.internal.owserver.OwserverDeviceParameter;
33 import org.openhab.core.config.core.Configuration;
34 import org.openhab.core.library.types.DecimalType;
35 import org.openhab.core.library.types.OnOffType;
36 import org.openhab.core.library.types.QuantityType;
37 import org.openhab.core.thing.type.ChannelTypeUID;
38 import org.openhab.core.types.State;
41 * Tests cases for {@link BAE0910}.
43 * @author Jan N. Klug - Initial contribution
46 public class BAE0910Test extends DeviceTestParent<BAE0910> {
48 public void setupMocks() {
49 setupMocks(THING_TYPE_BAE091X, BAE0910.class);
55 public void counter() throws OwException {
56 addChannel(CHANNEL_COUNTER, "Number");
57 final BAE0910 testDevice = instantiateDevice();
58 final InOrder inOrder = Mockito.inOrder(mockThingHandler, mockBridgeHandler);
60 Mockito.when(mockBridgeHandler.checkPresence(testSensorId)).thenReturn(OnOffType.ON);
61 Mockito.when(mockBridgeHandler.readDecimalType(eq(testSensorId), eq(new OwserverDeviceParameter("/counter"))))
62 .thenReturn(new DecimalType(34567));
64 testDevice.enableChannel(CHANNEL_COUNTER);
65 testDevice.configureChannels(mockBridgeHandler);
68 ArgumentCaptor<State> stateArgumentCaptor = ArgumentCaptor.forClass(State.class);
69 testDevice.refresh(mockBridgeHandler, true);
70 inOrder.verify(mockBridgeHandler).readDecimalType(eq(testSensorId),
71 eq(new OwserverDeviceParameter("/counter")));
72 inOrder.verify(mockThingHandler).postUpdate(eq(CHANNEL_COUNTER), stateArgumentCaptor.capture());
73 assertEquals(new DecimalType(34567), stateArgumentCaptor.getValue());
76 assertFalse(testDevice.writeChannel(mockBridgeHandler, CHANNEL_COUNTER, new DecimalType(12345)));
78 inOrder.verifyNoMoreInteractions();
81 // pin 2: digital2 or pwm1
84 public void digitalOut2() throws OwException {
85 addChannel(CHANNEL_DIGITAL2, "Switch");
86 digitalBaseChannel(CHANNEL_DIGITAL2, bitSet(3, 4), 0, "/out", bitSet(0), true);
90 public void pwm4() throws OwException {
91 pwmBaseChannel(CHANNEL_PWM_FREQ2, CHANNEL_PWM_DUTY4, "/period2", "/duty4", 2);
94 // pin 6: pio or pwm 3
97 public void digital6PioIn() throws OwException {
98 Map<String, Object> channelConfig = new HashMap<>();
99 channelConfig.put("pulldevice", "pulldown");
100 channelConfig.put("mode", "input");
101 addChannel(CHANNEL_DIGITAL6, "Switch", new Configuration(channelConfig));
102 digitalBaseChannel(CHANNEL_DIGITAL6, bitSet(1, 2, 3, 4), 1, "/pio", bitSet(0), false);
106 public void digital6PioOut() throws OwException {
107 Map<String, Object> channelConfig = new HashMap<>();
108 channelConfig.put("mode", "output");
109 addChannel(CHANNEL_DIGITAL6, "Switch", new Configuration(channelConfig));
110 digitalBaseChannel(CHANNEL_DIGITAL6, bitSet(0, 3, 4), 1, "/pio", bitSet(0), true);
114 public void pwm3() throws OwException {
115 pwmBaseChannel(CHANNEL_PWM_FREQ1, CHANNEL_PWM_DUTY3, "/period1", "/duty3", 1);
118 // pin 7: analog, output, pwm2
121 public void analog() throws OwException {
122 Map<String, Object> channelConfig = new HashMap<>();
123 channelConfig.put("hires", "true");
124 addChannel(CHANNEL_VOLTAGE, "Number:ElectricPotential", new Configuration(channelConfig));
126 final BAE0910 testDevice = instantiateDevice();
127 final InOrder inOrder = Mockito.inOrder(mockThingHandler, mockBridgeHandler);
129 Mockito.when(mockBridgeHandler.checkPresence(testSensorId)).thenReturn(OnOffType.ON);
130 Mockito.when(mockBridgeHandler.readDecimalType(eq(testSensorId), eq(new OwserverDeviceParameter("/adc"))))
131 .thenReturn(new DecimalType(5.2));
133 testDevice.enableChannel(CHANNEL_VOLTAGE);
134 testDevice.configureChannels(mockBridgeHandler);
136 // test configuration
137 assertEquals(bitSet(3, 4), checkConfiguration(2));
140 ArgumentCaptor<State> stateArgumentCaptor = ArgumentCaptor.forClass(State.class);
141 testDevice.refresh(mockBridgeHandler, true);
142 inOrder.verify(mockBridgeHandler).readDecimalType(eq(testSensorId), eq(new OwserverDeviceParameter("/adc")));
143 inOrder.verify(mockThingHandler).postUpdate(eq(CHANNEL_VOLTAGE), stateArgumentCaptor.capture());
144 assertEquals(new QuantityType<>("5.2 V"), stateArgumentCaptor.getValue());
146 // write (should fail)
147 assertFalse(testDevice.writeChannel(mockBridgeHandler, CHANNEL_VOLTAGE, new QuantityType<>("3 V")));
149 inOrder.verifyNoMoreInteractions();
153 public void digitalOut7() throws OwException {
154 addChannel(CHANNEL_DIGITAL7, "Switch");
155 digitalBaseChannel(CHANNEL_DIGITAL7, bitSet(4), 4, "/tpm2c", bitSet(4, 7), true);
159 public void pwm2() throws OwException {
160 pwmBaseChannel(CHANNEL_PWM_FREQ2, CHANNEL_PWM_DUTY2, "/period2", "/duty2", 2);
163 // pin 8: digital in, digital out or pwm
166 public void digitalIn8() throws OwException {
167 addChannel(CHANNEL_DIGITAL8, "Switch", new ChannelTypeUID(BINDING_ID, "bae-in"));
168 digitalBaseChannel(CHANNEL_DIGITAL8, bitSet(4, 5), 3, "/tpm1c", bitSet(4, 5, 7), false);
172 public void digitalOut8() throws OwException {
173 addChannel(CHANNEL_DIGITAL8, "Switch");
174 digitalBaseChannel(CHANNEL_DIGITAL8, bitSet(4), 3, "/tpm1c", bitSet(4, 7), true);
178 public void pwm1() throws OwException {
179 pwmBaseChannel(CHANNEL_PWM_FREQ1, CHANNEL_PWM_DUTY1, "/period1", "/duty1", 1);
183 * base test for digital channels
185 * @param channel channel name
186 * @param configBitSet expected config register
187 * @param configRegister config register number
188 * @param channelParam channel parameter
189 * @param returnBitSet which bitset should be returned on read
190 * @param isOutput if this channel is an output
192 private void digitalBaseChannel(String channel, BitSet configBitSet, int configRegister, String channelParam,
193 BitSet returnBitSet, boolean isOutput) throws OwException {
194 final BAE0910 testDevice = instantiateDevice();
195 final InOrder inOrder = Mockito.inOrder(mockThingHandler, mockBridgeHandler);
197 Mockito.when(mockBridgeHandler.checkPresence(testSensorId)).thenReturn(OnOffType.ON);
198 Mockito.when(mockBridgeHandler.readBitSet(eq(testSensorId), eq(new OwserverDeviceParameter(channelParam))))
199 .thenReturn(returnBitSet);
201 testDevice.enableChannel(channel);
202 testDevice.configureChannels(mockBridgeHandler);
204 // test configuration
205 assertEquals(configBitSet, checkConfiguration(configRegister));
208 ArgumentCaptor<State> stateArgumentCaptor = ArgumentCaptor.forClass(State.class);
209 testDevice.refresh(mockBridgeHandler, true);
210 inOrder.verify(mockBridgeHandler).readBitSet(eq(testSensorId), eq(new OwserverDeviceParameter(channelParam)));
211 inOrder.verify(mockThingHandler).postUpdate(eq(channel), stateArgumentCaptor.capture());
212 assertEquals(OnOffType.ON, stateArgumentCaptor.getValue());
216 ArgumentCaptor<BitSet> bitSetArgumentCaptor = ArgumentCaptor.forClass(BitSet.class);
217 assertTrue(testDevice.writeChannel(mockBridgeHandler, channel, OnOffType.ON));
218 inOrder.verify(mockBridgeHandler).writeBitSet(eq(testSensorId),
219 eq(new OwserverDeviceParameter(channelParam)), bitSetArgumentCaptor.capture());
220 assertEquals(returnBitSet, bitSetArgumentCaptor.getValue());
222 assertFalse(testDevice.writeChannel(mockBridgeHandler, channel, OnOffType.ON));
225 inOrder.verifyNoMoreInteractions();
229 * base test case for PWM channels
231 * @param freqChannel channel name for frequency
232 * @param dutyChannel channel name for duty cycle
233 * @param freqParam owfs parameter for frequency
234 * @param dutyParam owfs parameter for duty cycle
235 * @param registerIndex index for TPM configuration register
237 private void pwmBaseChannel(String freqChannel, String dutyChannel, String freqParam, String dutyParam,
238 int registerIndex) throws OwException {
239 Map<String, Object> channelConfig = new HashMap<>();
240 channelConfig.put("prescaler", 5);
241 addChannel(freqChannel, "Number:Frequency", new Configuration(channelConfig));
242 addChannel(dutyChannel, "Number:Dimensionless");
244 final BAE0910 testDevice = instantiateDevice();
245 final InOrder inOrder = Mockito.inOrder(mockThingHandler, mockBridgeHandler);
247 Mockito.when(mockBridgeHandler.checkPresence(testSensorId)).thenReturn(OnOffType.ON);
248 Mockito.when(mockBridgeHandler.readDecimalType(eq(testSensorId), eq(new OwserverDeviceParameter(freqParam))))
249 .thenReturn(new DecimalType(32768));
250 Mockito.when(mockBridgeHandler.readDecimalType(eq(testSensorId), eq(new OwserverDeviceParameter(dutyParam))))
251 .thenReturn(new DecimalType(16384));
253 testDevice.enableChannel(freqChannel);
254 testDevice.enableChannel(dutyChannel);
255 testDevice.configureChannels(mockBridgeHandler);
257 // test configuration
258 assertEquals(bitSet(0, 2), checkConfiguration(registerIndex + 2));
261 ArgumentCaptor<State> stateArgumentCaptor = ArgumentCaptor.forClass(State.class);
262 testDevice.refresh(mockBridgeHandler, true);
263 inOrder.verify(mockBridgeHandler).readDecimalType(eq(testSensorId), eq(new OwserverDeviceParameter(freqParam)));
264 inOrder.verify(mockThingHandler).postUpdate(eq(freqChannel), stateArgumentCaptor.capture());
265 assertEquals(new QuantityType<>("15.2587890625 Hz"), stateArgumentCaptor.getValue());
266 inOrder.verify(mockBridgeHandler).readDecimalType(eq(testSensorId), eq(new OwserverDeviceParameter(dutyParam)));
267 inOrder.verify(mockThingHandler).postUpdate(eq(dutyChannel), stateArgumentCaptor.capture());
268 assertEquals(new QuantityType<>("50 %"), stateArgumentCaptor.getValue());
271 ArgumentCaptor<DecimalType> decimalTypeArgumentCaptor = ArgumentCaptor.forClass(DecimalType.class);
272 assertTrue(testDevice.writeChannel(mockBridgeHandler, freqChannel, new QuantityType<>("50000 Hz")));
273 inOrder.verify(mockBridgeHandler).writeDecimalType(eq(testSensorId), eq(new OwserverDeviceParameter(freqParam)),
274 decimalTypeArgumentCaptor.capture());
275 assertEquals(new DecimalType(10), decimalTypeArgumentCaptor.getValue());
276 testDevice.writeChannel(mockBridgeHandler, dutyChannel, new QuantityType<>("25 %"));
277 inOrder.verify(mockBridgeHandler).readDecimalType(eq(testSensorId), eq(new OwserverDeviceParameter(freqParam)));
278 inOrder.verify(mockBridgeHandler).writeDecimalType(eq(testSensorId), eq(new OwserverDeviceParameter(dutyParam)),
279 decimalTypeArgumentCaptor.capture());
280 assertEquals(new DecimalType(8192), decimalTypeArgumentCaptor.getValue());
282 inOrder.verifyNoMoreInteractions();
286 * check if all registers are written and return one
288 * @param registerIndex number of register to return
289 * @return this register's BitSet
290 * @throws OwException in case an error occurs
292 private BitSet checkConfiguration(int registerIndex) throws OwException {
293 ArgumentCaptor<BitSet> configArgumentCaptor = ArgumentCaptor.forClass(BitSet.class);
294 final InOrder inOrder = Mockito.inOrder(mockThingHandler, mockBridgeHandler);
296 inOrder.verify(mockBridgeHandler).writeBitSet(eq(testSensorId), eq(new OwserverDeviceParameter("/outc")),
297 configArgumentCaptor.capture());
298 inOrder.verify(mockBridgeHandler).writeBitSet(eq(testSensorId), eq(new OwserverDeviceParameter("/pioc")),
299 configArgumentCaptor.capture());
300 inOrder.verify(mockBridgeHandler).writeBitSet(eq(testSensorId), eq(new OwserverDeviceParameter("/adcc")),
301 configArgumentCaptor.capture());
302 inOrder.verify(mockBridgeHandler).writeBitSet(eq(testSensorId), eq(new OwserverDeviceParameter("/tpm1c")),
303 configArgumentCaptor.capture());
304 inOrder.verify(mockBridgeHandler).writeBitSet(eq(testSensorId), eq(new OwserverDeviceParameter("/tpm2c")),
305 configArgumentCaptor.capture());
306 return configArgumentCaptor.getAllValues().get(registerIndex);
310 * BitSet with pre-set bits
312 * @param bits which bits to set
315 private BitSet bitSet(int... bits) {
316 BitSet bitSet = new BitSet(8);
317 Arrays.stream(bits).forEach(b -> bitSet.set(b));