Skip to content

Commit 2c2fb67

Browse files
committed
Refactor capability readers and fix tests
Cleanup and small feature/fix sweep across the binding: - CapabilityReaders: replace Function-based getValue helper with a private static Predicate using primitive equality, remove unused imports, and update reader registrations. - ACStringCommands: add HIGH4 fan speed constant. - CommandBase: use LocalDateTime.now() and remove unused ZoneId import. - MideaACHandler: remove redundant return statements after catch blocks. - channels.xml: correct several channel tags/descriptions (Level/Mode/LockState/Enabled/Setpoint) and minor punctuation fixes. - Tests: add typedMock helper to ensure non-null mocks, refactor ConnectionManagerTest to use a spied real instance and assert sent command type, update HumidityResponseTest expected fan speed and input data, and remove stray/unused annotations and comments in several test classes. - A1CommandHelper: fix Javadoc typo (Anion). These changes are primarily refactors, test robustness improvements, and minor behavioral/documentation corrections. Signed-off-by: Bob Eckhoff <katmandodo@yahoo.com>
1 parent c826927 commit 2c2fb67

14 files changed

Lines changed: 71 additions & 74 deletions

File tree

bundles/org.openhab.binding.mideaac/src/main/java/org/openhab/binding/mideaac/internal/devices/CommandBase.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@
1313
package org.openhab.binding.mideaac.internal.devices;
1414

1515
import java.time.LocalDateTime;
16-
import java.time.ZoneId;
1716
import java.util.Arrays;
1817

1918
import org.eclipse.jdt.annotation.NonNullByDefault;
@@ -99,7 +98,7 @@ public CommandBase() {
9998
}
10099

101100
protected void applyTimestamp() {
102-
LocalDateTime now = LocalDateTime.now(ZoneId.systemDefault());
101+
LocalDateTime now = LocalDateTime.now();
103102
data[data.length - 1] = (byte) now.getSecond();
104103
}
105104

bundles/org.openhab.binding.mideaac/src/main/java/org/openhab/binding/mideaac/internal/devices/a1/A1CommandHelper.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,7 @@ public static A1CommandSet handleA1ChildLock(Command command, A1Response lastRes
167167
/**
168168
* Handle A1 Dehumidifier Anion
169169
*
170-
* @param command Anoin
170+
* @param command Anion
171171
*/
172172
public static A1CommandSet handleA1Anion(Command command, A1Response lastResponse)
173173
throws UnsupportedOperationException {

bundles/org.openhab.binding.mideaac/src/main/java/org/openhab/binding/mideaac/internal/devices/ac/ACStringCommands.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,7 @@ public enum FanSpeed {
153153

154154
AUTO3(102, 3),
155155
FULL3(0, 3),
156+
HIGH4(100, 3),
156157
HIGH3(80, 3),
157158
MEDIUM3(60, 3),
158159
LOW3(40, 3),

bundles/org.openhab.binding.mideaac/src/main/java/org/openhab/binding/mideaac/internal/devices/capabilities/CapabilityReaders.java

Lines changed: 24 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,7 @@
1515
import java.util.HashMap;
1616
import java.util.List;
1717
import java.util.Map;
18-
import java.util.Objects;
1918
import java.util.Optional;
20-
import java.util.function.Function;
2119
import java.util.function.Predicate;
2220
import java.util.stream.Collectors;
2321

@@ -35,17 +33,14 @@ public class CapabilityReaders {
3533
private static final Map<CapabilityId, List<Reader>> READERS = new HashMap<>();
3634

3735
static {
38-
// Helper to simplify creation of READERS
39-
Function<Integer, Predicate<Integer>> getValue = (expected) -> (value) -> Objects.equals(value, expected);
40-
4136
// Add READERS for each capability - Not all are supported by all AC devices
42-
READERS.put(CapabilityId.ANION, List.of(new Reader("anion", getValue.apply(1))));
43-
READERS.put(CapabilityId.AUX_ELECTRIC_HEAT, List.of(new Reader("auxElectricHeat", getValue.apply(1))));
44-
READERS.put(CapabilityId.BREEZE_AWAY, List.of(new Reader("breezeAway", getValue.apply(1))));
45-
READERS.put(CapabilityId.BREEZE_CONTROL, List.of(new Reader("breezeControl", getValue.apply(1))));
46-
READERS.put(CapabilityId.BREEZELESS, List.of(new Reader("breezeless", getValue.apply(1))));
47-
READERS.put(CapabilityId.BUZZER, List.of(new Reader("buzzer", getValue.apply(1))));
48-
READERS.put(CapabilityId.CHILD_LOCK, List.of(new Reader("childLock", getValue.apply(1))));
37+
READERS.put(CapabilityId.ANION, List.of(new Reader("anion", getValue(1))));
38+
READERS.put(CapabilityId.AUX_ELECTRIC_HEAT, List.of(new Reader("auxElectricHeat", getValue(1))));
39+
READERS.put(CapabilityId.BREEZE_AWAY, List.of(new Reader("breezeAway", getValue(1))));
40+
READERS.put(CapabilityId.BREEZE_CONTROL, List.of(new Reader("breezeControl", getValue(1))));
41+
READERS.put(CapabilityId.BREEZELESS, List.of(new Reader("breezeless", getValue(1))));
42+
READERS.put(CapabilityId.BUZZER, List.of(new Reader("buzzer", getValue(1))));
43+
READERS.put(CapabilityId.CHILD_LOCK, List.of(new Reader("childLock", getValue(1))));
4944

5045
READERS.put(CapabilityId.DISPLAY_CONTROL,
5146
List.of(new Reader("displayControl", (value) -> List.of(1, 2, 100).contains(value))));
@@ -55,15 +50,15 @@ public class CapabilityReaders {
5550
new Reader("energySetting", (value) -> List.of(3, 5).contains(value)),
5651
new Reader("energyBCD", (value) -> List.of(2, 3).contains(value))));
5752

58-
READERS.put(CapabilityId.FAHRENHEIT, List.of(new Reader("fahrenheit", getValue.apply(0))));
53+
READERS.put(CapabilityId.FAHRENHEIT, List.of(new Reader("fahrenheit", getValue(0))));
5954

6055
READERS.put(CapabilityId.FAN_SPEED_CONTROL,
61-
List.of(new Reader("fanSilent", getValue.apply(6)),
56+
List.of(new Reader("fanSilent", getValue(6)),
6257
new Reader("fanLow", (value) -> List.of(3, 4, 5, 6, 7).contains(value)),
6358
new Reader("fanMedium", (value) -> List.of(5, 6, 7).contains(value)),
6459
new Reader("fanHigh", (value) -> List.of(3, 4, 5, 6, 7).contains(value)),
6560
new Reader("fanAuto", (value) -> List.of(4, 5, 6).contains(value)),
66-
new Reader("fanCustom", getValue.apply(1))));
61+
new Reader("fanCustom", getValue(1))));
6762

6863
READERS.put(CapabilityId.FILTER_REMIND,
6964
List.of(new Reader("filterNotice", (value) -> List.of(1, 2, 4).contains(value)),
@@ -78,31 +73,35 @@ public class CapabilityReaders {
7873
new Reader("modeCool", (value) -> !List.of(2, 10, 12).contains(value)),
7974
new Reader("modeDry", (value) -> List.of(0, 1, 5, 6, 9, 11, 13).contains(value)),
8075
new Reader("modeAuto", (value) -> List.of(0, 1, 2, 7, 8, 9, 13).contains(value)),
81-
new Reader("modeAuxHeat", getValue.apply(9)),
76+
new Reader("modeAuxHeat", getValue(9)),
8277
new Reader("modeAux", (value) -> List.of(9, 10, 11, 13).contains(value))));
8378

8479
READERS.put(CapabilityId.PRESET_ECO, List.of(new Reader("ecoCool", (value) -> List.of(1, 2).contains(value))));
85-
READERS.put(CapabilityId.PRESET_FREEZE_PROTECTION, List.of(new Reader("freezeProtection", getValue.apply(1))));
86-
READERS.put(CapabilityId.PRESET_IECO, List.of(new Reader("ieco", getValue.apply(1))));
80+
READERS.put(CapabilityId.PRESET_FREEZE_PROTECTION, List.of(new Reader("freezeProtection", getValue(1))));
81+
READERS.put(CapabilityId.PRESET_IECO, List.of(new Reader("ieco", getValue(1))));
8782

8883
READERS.put(CapabilityId.PRESET_TURBO,
8984
List.of(new Reader("turboHeat", (value) -> List.of(1, 3).contains(value)),
9085
new Reader("turboCool", (value) -> value < 2)));
9186

92-
READERS.put(CapabilityId.RATE_SELECT, List.of(new Reader("rate_select_2_level", getValue.apply(1)),
87+
READERS.put(CapabilityId.RATE_SELECT, List.of(new Reader("rate_select_2_level", getValue(1)),
9388
new Reader("rateSelect5Level", (value) -> List.of(2, 3).contains(value))));
9489

95-
READERS.put(CapabilityId.SELF_CLEAN, List.of(new Reader("selfClean", getValue.apply(1))));
96-
READERS.put(CapabilityId.SMART_EYE, List.of(new Reader("smartEye", getValue.apply(1))));
97-
READERS.put(CapabilityId.SWING_LR_ANGLE, List.of(new Reader("swingHorizontalAngle", getValue.apply(1))));
98-
READERS.put(CapabilityId.SWING_UD_ANGLE, List.of(new Reader("swingVerticalAngle", getValue.apply(1))));
90+
READERS.put(CapabilityId.SELF_CLEAN, List.of(new Reader("selfClean", getValue(1))));
91+
READERS.put(CapabilityId.SMART_EYE, List.of(new Reader("smartEye", getValue(1))));
92+
READERS.put(CapabilityId.SWING_LR_ANGLE, List.of(new Reader("swingHorizontalAngle", getValue(1))));
93+
READERS.put(CapabilityId.SWING_UD_ANGLE, List.of(new Reader("swingVerticalAngle", getValue(1))));
9994

10095
READERS.put(CapabilityId.SWING_MODES,
10196
List.of(new Reader("swingHorizontal", (value) -> List.of(1, 3).contains(value)),
10297
new Reader("swingVertical", (value) -> value < 2)));
10398

104-
READERS.put(CapabilityId.WIND_OFF_ME, List.of(new Reader("windOffMe", getValue.apply(1))));
105-
READERS.put(CapabilityId.WIND_ON_ME, List.of(new Reader("windOnMe", getValue.apply(1))));
99+
READERS.put(CapabilityId.WIND_OFF_ME, List.of(new Reader("windOffMe", getValue(1))));
100+
READERS.put(CapabilityId.WIND_ON_ME, List.of(new Reader("windOnMe", getValue(1))));
101+
}
102+
103+
private static Predicate<Integer> getValue(int expected) {
104+
return value -> value == expected;
106105
}
107106

108107
/**

bundles/org.openhab.binding.mideaac/src/main/java/org/openhab/binding/mideaac/internal/handler/MideaACHandler.java

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,6 @@ protected void refreshDeviceState() {
124124
} catch (IOException e) {
125125
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, e.getMessage());
126126
}
127-
return;
128127
}
129128

130129
@Override
@@ -140,7 +139,6 @@ protected void refreshDeviceStateAll() {
140139
} catch (IOException e) {
141140
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, e.getMessage());
142141
}
143-
return;
144142
}
145143

146144
private void humidityUpdate() {

bundles/org.openhab.binding.mideaac/src/main/resources/OH-INF/thing/channels.xml

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -342,7 +342,7 @@
342342
<label>Tank Water Level</label>
343343
<tags>
344344
<tag>Measurement</tag>
345-
<tag>Humidity</tag>
345+
<tag>Level</tag>
346346
</tags>
347347
<state readOnly="true" pattern="%d%%"/>
348348
</channel-type>
@@ -365,11 +365,11 @@
365365
<channel-type id="dehumidifier-swing">
366366
<item-type>Switch</item-type>
367367
<label>Dehumidifer Swing</label>
368-
<description>Louver Movement. </description>
368+
<description>Louver Movement.</description>
369369
<category>Switch</category>
370370
<tags>
371371
<tag>Switch</tag>
372-
<tag>Humidity</tag>
372+
<tag>Mode</tag>
373373
</tags>
374374
</channel-type>
375375
<channel-type id="humidity">
@@ -401,7 +401,7 @@
401401
<category>Switch</category>
402402
<tags>
403403
<tag>Switch</tag>
404-
<tag>Humidity</tag>
404+
<tag>LockState</tag>
405405
</tags>
406406
</channel-type>
407407
<channel-type id="anion" advanced="true">
@@ -410,7 +410,7 @@
410410
<category>Switch</category>
411411
<tags>
412412
<tag>Switch</tag>
413-
<tag>Humidity</tag>
413+
<tag>Enabled</tag>
414414
</tags>
415415
<state readOnly="true"/>
416416
</channel-type>
@@ -420,7 +420,7 @@
420420
<description>Set Maximum Humidity level.</description>
421421
<category>Humidity</category>
422422
<tags>
423-
<tag>Control</tag>
423+
<tag>Setpoint</tag>
424424
<tag>Humidity</tag>
425425
</tags>
426426
<state pattern="%d%%"/>

bundles/org.openhab.binding.mideaac/src/test/java/org/openhab/binding/mideaac/internal/cloud/CloudTest.java

Lines changed: 18 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import static org.mockito.Mockito.*;
2020

2121
import java.lang.reflect.Field;
22+
import java.util.Objects;
2223
import java.util.concurrent.TimeUnit;
2324

2425
import org.eclipse.jdt.annotation.NonNullByDefault;
@@ -39,13 +40,17 @@
3940
@NonNullByDefault
4041
public class CloudTest {
4142

43+
private static <T> T typedMock(Class<T> clazz) {
44+
return Objects.requireNonNull(mock(clazz));
45+
}
46+
4247
@Test
4348
public void testLogin() throws Exception {
4449
// Mock HttpClient and ContentResponse
45-
HttpClient mockHttpClient = mock(HttpClient.class);
46-
Request mockRequest = mock(Request.class);
47-
ContentResponse mockResponse = mock(ContentResponse.class);
48-
HttpFields mockHeaders = mock(HttpFields.class);
50+
HttpClient mockHttpClient = typedMock(HttpClient.class);
51+
Request mockRequest = typedMock(Request.class);
52+
ContentResponse mockResponse = typedMock(ContentResponse.class);
53+
HttpFields mockHeaders = typedMock(HttpFields.class);
4954

5055
// Define behavior of HttpFields
5156
when(mockHeaders.toString()).thenReturn("Mocked Headers");
@@ -95,10 +100,10 @@ public void testLogin() throws Exception {
95100
@Test
96101
public void testLoginproxy() throws Exception {
97102
// Mock HttpClient and ContentResponse
98-
HttpClient mockHttpClient = mock(HttpClient.class);
99-
Request mockRequest = mock(Request.class);
100-
ContentResponse mockResponse = mock(ContentResponse.class);
101-
HttpFields mockHeaders = mock(HttpFields.class);
103+
HttpClient mockHttpClient = typedMock(HttpClient.class);
104+
Request mockRequest = typedMock(Request.class);
105+
ContentResponse mockResponse = typedMock(ContentResponse.class);
106+
HttpFields mockHeaders = typedMock(HttpFields.class);
102107

103108
// Define behavior of HttpFields
104109
when(mockHeaders.toString()).thenReturn("Mocked Headers");
@@ -148,7 +153,7 @@ public void testLoginWithSessionId() throws Exception {
148153
"https://mapp.appsmb.com", "xhdiwjnchekd4d512chdjx5d8e4c394D2D7S", "", "", "");
149154

150155
// Create the Cloud class
151-
HttpClient mockHttpClient = mock(HttpClient.class);
156+
HttpClient mockHttpClient = typedMock(HttpClient.class);
152157
Cloud cloud = new Cloud("email", "password", provider, mockHttpClient);
153158

154159
// Set loginId using reflection so that the getLoginId() check doesn't trigger
@@ -171,10 +176,10 @@ public void testLoginWithSessionId() throws Exception {
171176
@Test
172177
public void testGetLoginId() throws Exception {
173178
// Mock HttpClient and dependent objects
174-
HttpClient mockHttpClient = mock(HttpClient.class);
175-
Request mockRequest = mock(Request.class);
176-
ContentResponse mockResponse = mock(ContentResponse.class);
177-
HttpFields mockHeaders = mock(HttpFields.class);
179+
HttpClient mockHttpClient = typedMock(HttpClient.class);
180+
Request mockRequest = typedMock(Request.class);
181+
ContentResponse mockResponse = typedMock(ContentResponse.class);
182+
HttpFields mockHeaders = typedMock(HttpFields.class);
178183

179184
// Define behavior for HttpFields
180185
when(mockHeaders.toString()).thenReturn("Mocked Headers");

bundles/org.openhab.binding.mideaac/src/test/java/org/openhab/binding/mideaac/internal/connection/ConnectionManagerTest.java

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -14,16 +14,14 @@
1414

1515
import static org.junit.jupiter.api.Assertions.*;
1616
import static org.mockito.ArgumentMatchers.any;
17-
import static org.mockito.ArgumentMatchers.anyString;
18-
import static org.mockito.ArgumentMatchers.eq;
1917
import static org.mockito.Mockito.*;
2018

19+
import java.util.Objects;
20+
2121
import org.eclipse.jdt.annotation.NonNullByDefault;
2222
import org.junit.jupiter.api.Test;
23-
import org.mockito.ArgumentCaptor;
2423
import org.openhab.binding.mideaac.internal.callbacks.Callback;
2524
import org.openhab.binding.mideaac.internal.devices.A1CommandBase;
26-
import org.openhab.binding.mideaac.internal.devices.CommandBase;
2725

2826
/**
2927
* The {@link ConnectionManagerTest} tests the methods in the ConnectionManager
@@ -36,24 +34,28 @@ public class ConnectionManagerTest {
3634

3735
@Test
3836
public void testGetStatusUsesA1CommandBase() throws Exception {
39-
// Arrange
40-
ConnectionManager manager = mock(ConnectionManager.class);
37+
// Arrange: construct a real instance with dummy values
38+
ConnectionManager real = new ConnectionManager("127.0.0.1", 6444, 4, "", "", "", "", "", "000000000000", 3,
39+
false, "ac");
40+
ConnectionManager manager = spy(real);
41+
42+
Object[] sentCommand = new Object[1];
4143

42-
doCallRealMethod().when(manager).getStatus(any());
43-
doCallRealMethod().when(manager).setDeviceType(anyString());
44-
doNothing().when(manager).sendCommand(any(), any());
44+
// Stub sendCommand so no real network call is made
45+
doAnswer(invocation -> {
46+
sentCommand[0] = invocation.getArgument(0);
47+
return null;
48+
}).when(manager).sendCommand(any(), any());
4549

46-
manager.setDeviceType("a1"); // package-private setter
50+
manager.setDeviceType("a1");
4751

48-
Callback callback = mock(Callback.class);
52+
Callback callback = Objects.requireNonNull(mock(Callback.class));
4953

5054
// Act
5155
manager.getStatus(callback);
5256

5357
// Assert
54-
ArgumentCaptor<CommandBase> captor = ArgumentCaptor.forClass(CommandBase.class);
55-
verify(manager).sendCommand(captor.capture(), eq(callback));
56-
57-
assertTrue(captor.getValue() instanceof A1CommandBase);
58+
assertNotNull(sentCommand[0]);
59+
assertInstanceOf(A1CommandBase.class, sentCommand[0]);
5860
}
5961
}

bundles/org.openhab.binding.mideaac/src/test/java/org/openhab/binding/mideaac/internal/devices/a1/A1CommandSetTest.java

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@ public class A1CommandSetTest {
3030

3131
/**
3232
* Dehumidifier Swing Mode test
33-
*
3433
*/
3534
@Test
3635
public void testHandleA1SwingMode() {
@@ -46,8 +45,7 @@ public void testHandleA1SwingMode() {
4645
}
4746

4847
/**
49-
* Dehumidifier Power test- Should the 8 be removed?
50-
*
48+
* Dehumidifier Power test
5149
*/
5250
@Test
5351
public void testHandleA1Power() {

bundles/org.openhab.binding.mideaac/src/test/java/org/openhab/binding/mideaac/internal/devices/a1/A1ResponseTest.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@
2727
*/
2828
@NonNullByDefault
2929
public class A1ResponseTest {
30-
@org.jupnp.registry.event.Before
3130

3231
byte[] data = HexFormat.of().parseHex("C80104507F7F003700000000000000001E64000000003A67C2");
3332
A1Response response = new A1Response(data);

0 commit comments

Comments
 (0)