]> git.basschouten.com Git - openhab-addons.git/blob
84b7ce88a28255bc2c706d3f1be30ca8f2e755fa
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2020 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.neohub.test;
14
15 import static org.junit.Assert.assertEquals;
16 import static org.junit.Assert.assertFalse;
17 import static org.junit.Assert.assertNotNull;
18 import static org.junit.Assert.assertNull;
19 import static org.junit.Assert.assertTrue;
20 import static org.junit.Assert.fail;
21 import static org.openhab.binding.neohub.internal.NeoHubBindingConstants.*;
22
23 import java.io.BufferedReader;
24 import java.io.FileReader;
25 import java.io.IOException;
26 import java.math.BigDecimal;
27 import java.time.Instant;
28
29 import org.eclipse.jdt.annotation.NonNullByDefault;
30 import org.junit.Test;
31 import org.openhab.binding.neohub.internal.NeoHubAbstractDeviceData;
32 import org.openhab.binding.neohub.internal.NeoHubAbstractDeviceData.AbstractRecord;
33 import org.openhab.binding.neohub.internal.NeoHubGetEngineersData;
34 import org.openhab.binding.neohub.internal.NeoHubInfoResponse;
35 import org.openhab.binding.neohub.internal.NeoHubInfoResponse.InfoRecord;
36 import org.openhab.binding.neohub.internal.NeoHubLiveDeviceData;
37 import org.openhab.binding.neohub.internal.NeoHubReadDcbResponse;
38 import org.openhab.binding.neohub.internal.NeoHubSocket;
39 import org.openhab.core.library.unit.ImperialUnits;
40 import org.openhab.core.library.unit.SIUnits;
41
42 /**
43  * The {@link NeoHubTestData} class defines common constants, which are used
44  * across the whole binding.
45  *
46  * @author Andrew Fiddian-Green - Initial contribution
47  */
48 @NonNullByDefault
49 public class NeoHubTestData {
50
51     /*
52      * Load the test JSON payload string from a file
53      */
54     private String load(String fileName) {
55         try (FileReader file = new FileReader(String.format("src/test/resources/%s.json", fileName));
56                 BufferedReader reader = new BufferedReader(file)) {
57             StringBuilder builder = new StringBuilder();
58             String line;
59             while ((line = reader.readLine()) != null) {
60                 builder.append(line).append("\n");
61             }
62             return builder.toString();
63         } catch (IOException e) {
64             fail(e.getMessage());
65         }
66         return "";
67     }
68
69     /*
70      * Test an INFO JSON response string as produced by older firmware versions
71      */
72     @Test
73     public void testInfoJsonOld() {
74         // load INFO JSON response string in old JSON format
75         NeoHubAbstractDeviceData infoResponse = NeoHubInfoResponse.createDeviceData(load("info_old"));
76         assertNotNull(infoResponse);
77
78         // missing device
79         AbstractRecord device = infoResponse.getDeviceRecord("Aardvark");
80         assertNull(device);
81
82         // existing type 12 thermostat device
83         device = infoResponse.getDeviceRecord("Dining Room");
84         assertNotNull(device);
85         assertEquals("Dining Room", device.getDeviceName());
86         assertEquals(new BigDecimal("22.0"), device.getTargetTemperature());
87         assertEquals(new BigDecimal("22.2"), device.getActualTemperature());
88         assertEquals(new BigDecimal("23"), device.getFloorTemperature());
89         assertTrue(device instanceof InfoRecord);
90         assertEquals(12, ((InfoRecord) device).getDeviceType());
91         assertFalse(device.isStandby());
92         assertFalse(device.isHeating());
93         assertFalse(device.isPreHeating());
94         assertFalse(device.isTimerOn());
95         assertFalse(device.offline());
96         assertFalse(device.stateManual());
97         assertTrue(device.stateAuto());
98         assertFalse(device.isWindowOpen());
99         assertFalse(device.isBatteryLow());
100
101         // existing type 6 plug device (MANUAL OFF)
102         device = infoResponse.getDeviceRecord("Plug South");
103         assertNotNull(device);
104         assertEquals("Plug South", device.getDeviceName());
105         assertTrue(device instanceof InfoRecord);
106         assertEquals(6, ((InfoRecord) device).getDeviceType());
107         assertFalse(device.isTimerOn());
108         assertTrue(device.stateManual());
109
110         // existing type 6 plug device (MANUAL ON)
111         device = infoResponse.getDeviceRecord("Plug North");
112         assertNotNull(device);
113         assertEquals("Plug North", device.getDeviceName());
114         assertTrue(device instanceof InfoRecord);
115         assertEquals(6, ((InfoRecord) device).getDeviceType());
116         assertTrue(device.isTimerOn());
117         assertTrue(device.stateManual());
118
119         // existing type 6 plug device (AUTO OFF)
120         device = infoResponse.getDeviceRecord("Watering System");
121         assertNotNull(device);
122         assertEquals("Watering System", device.getDeviceName());
123         assertTrue(device instanceof InfoRecord);
124         assertEquals(6, ((InfoRecord) device).getDeviceType());
125         assertFalse(device.isTimerOn());
126         assertFalse(device.stateManual());
127     }
128
129     /*
130      * Test an INFO JSON response string as produced by newer firmware versions
131      */
132     @Test
133     public void testInfoJsonNew() {
134         // load INFO JSON response string in new JSON format
135         NeoHubAbstractDeviceData infoResponse = NeoHubInfoResponse.createDeviceData(load("info_new"));
136         assertNotNull(infoResponse);
137
138         // existing device (new JSON format)
139         AbstractRecord device = infoResponse.getDeviceRecord("Dining Room");
140         assertNotNull(device);
141         assertEquals("Dining Room", device.getDeviceName());
142         assertFalse(device.offline());
143         assertFalse(device.isWindowOpen());
144
145         // existing repeater device
146         device = infoResponse.getDeviceRecord("repeaternode54473");
147         assertNotNull(device);
148         assertEquals("repeaternode54473", device.getDeviceName());
149         assertEquals(new BigDecimal("127"), device.getFloorTemperature());
150         assertEquals(new BigDecimal("255.255"), device.getActualTemperature());
151     }
152
153     /*
154      * Test for a READ_DCB JSON string that has valid CORF C response
155      */
156     @Test
157     public void testReadDcbJson() {
158         // load READ_DCB JSON response string with valid CORF C response
159         NeoHubReadDcbResponse dcbResponse = NeoHubReadDcbResponse.createSystemData(load("dcb_celsius"));
160         assertNotNull(dcbResponse);
161         assertEquals(SIUnits.CELSIUS, dcbResponse.getTemperatureUnit());
162
163         // load READ_DCB JSON response string with valid CORF F response
164         dcbResponse = NeoHubReadDcbResponse.createSystemData(load("dcb_fahrenheit"));
165         assertNotNull(dcbResponse);
166         assertEquals(ImperialUnits.FAHRENHEIT, dcbResponse.getTemperatureUnit());
167
168         // load READ_DCB JSON response string with missing CORF element
169         dcbResponse = NeoHubReadDcbResponse.createSystemData(load("dcb_corf_missing"));
170         assertNotNull(dcbResponse);
171         assertEquals(SIUnits.CELSIUS, dcbResponse.getTemperatureUnit());
172
173         // load READ_DCB JSON response string where CORF element is an empty string
174         dcbResponse = NeoHubReadDcbResponse.createSystemData(load("dcb_corf_empty"));
175         assertNotNull(dcbResponse);
176         assertEquals(SIUnits.CELSIUS, dcbResponse.getTemperatureUnit());
177     }
178
179     /*
180      * Test an INFO JSON string that has a door contact and a temperature sensor
181      */
182     @Test
183     public void testInfoJsonWithSensors() {
184         /*
185          * load an INFO JSON response string that has a closed door contact and a
186          * temperature sensor
187          */
188         // save("info_sensors_closed", NEOHUB_JSON_TEST_STRING_INFO_SENSORS_CLOSED);
189         NeoHubAbstractDeviceData infoResponse = NeoHubInfoResponse.createDeviceData(load("info_sensors_closed"));
190         assertNotNull(infoResponse);
191
192         // existing contact device type 5 (CLOSED)
193         AbstractRecord device = infoResponse.getDeviceRecord("Back Door");
194         assertNotNull(device);
195         assertEquals("Back Door", device.getDeviceName());
196         assertTrue(device instanceof InfoRecord);
197         assertEquals(5, ((InfoRecord) device).getDeviceType());
198         assertFalse(device.isWindowOpen());
199         assertFalse(device.isBatteryLow());
200
201         // existing temperature sensor type 14
202         device = infoResponse.getDeviceRecord("Master Bedroom");
203         assertNotNull(device);
204         assertEquals("Master Bedroom", device.getDeviceName());
205         assertTrue(device instanceof InfoRecord);
206         assertEquals(14, ((InfoRecord) device).getDeviceType());
207         assertEquals(new BigDecimal("19.5"), device.getActualTemperature());
208
209         // existing thermostat type 1
210         device = infoResponse.getDeviceRecord("Living Room Floor");
211         assertNotNull(device);
212         assertEquals("Living Room Floor", device.getDeviceName());
213         assertTrue(device instanceof InfoRecord);
214         assertEquals(1, ((InfoRecord) device).getDeviceType());
215         assertEquals(new BigDecimal("19.8"), device.getActualTemperature());
216
217         // load an INFO JSON response string that has an open door contact
218         // save("info_sensors_open", NEOHUB_JSON_TEST_STRING_INFO_SENSORS_OPEN);
219         infoResponse = NeoHubInfoResponse.createDeviceData(load("info_sensors_open"));
220         assertNotNull(infoResponse);
221
222         // existing contact device type 5 (OPEN)
223         device = infoResponse.getDeviceRecord("Back Door");
224         assertNotNull(device);
225         assertEquals("Back Door", device.getDeviceName());
226         assertTrue(device instanceof InfoRecord);
227         assertEquals(5, ((InfoRecord) device).getDeviceType());
228         assertTrue(device.isWindowOpen());
229         assertTrue(device.isBatteryLow());
230     }
231
232     /*
233      * From NeoHub rev2.6 onwards the READ_DCB command is "deprecated" so we can
234      * also test the replacement GET_SYSTEM command (valid CORF response)
235      */
236     @Test
237     public void testGetSystemJson() {
238         // load GET_SYSTEM JSON response string
239         NeoHubReadDcbResponse dcbResponse;
240         dcbResponse = NeoHubReadDcbResponse.createSystemData(load("system"));
241         assertNotNull(dcbResponse);
242         assertEquals(SIUnits.CELSIUS, dcbResponse.getTemperatureUnit());
243     }
244
245     /*
246      * From NeoHub rev2.6 onwards the INFO command is "deprecated" so we must test
247      * the replacement GET_LIVE_DATA command
248      */
249     @Test
250     public void testGetLiveDataJson() {
251         // load GET_LIVE_DATA JSON response string
252         NeoHubLiveDeviceData liveDataResponse = NeoHubLiveDeviceData.createDeviceData(load("live_data"));
253         assertNotNull(liveDataResponse);
254
255         // test the time stamps
256         assertEquals(1588494785, liveDataResponse.getTimestampEngineers());
257         assertEquals(0, liveDataResponse.getTimestampSystem());
258
259         // missing device
260         AbstractRecord device = liveDataResponse.getDeviceRecord("Aardvark");
261         assertNull(device);
262
263         // test an existing thermostat device
264         device = liveDataResponse.getDeviceRecord("Dining Room");
265         assertNotNull(device);
266         assertEquals("Dining Room", device.getDeviceName());
267         assertEquals(new BigDecimal("22.0"), device.getTargetTemperature());
268         assertEquals(new BigDecimal("22.2"), device.getActualTemperature());
269         assertEquals(new BigDecimal("20.50"), device.getFloorTemperature());
270         assertFalse(device.isStandby());
271         assertFalse(device.isHeating());
272         assertFalse(device.isPreHeating());
273         assertFalse(device.isTimerOn());
274         assertFalse(device.offline());
275         assertFalse(device.stateManual());
276         assertTrue(device.stateAuto());
277         assertFalse(device.isWindowOpen());
278         assertFalse(device.isBatteryLow());
279
280         // test a plug device (MANUAL OFF)
281         device = liveDataResponse.getDeviceRecord("Living Room South");
282         assertNotNull(device);
283         assertEquals("Living Room South", device.getDeviceName());
284         assertFalse(device.isTimerOn());
285         assertTrue(device.stateManual());
286
287         // test a plug device (MANUAL ON)
288         device = liveDataResponse.getDeviceRecord("Living Room North");
289         assertNotNull(device);
290         assertEquals("Living Room North", device.getDeviceName());
291         assertTrue(device.isTimerOn());
292         assertTrue(device.stateManual());
293
294         // test a plug device (AUTO OFF)
295         device = liveDataResponse.getDeviceRecord("Green Wall Watering");
296         assertNotNull(device);
297         assertEquals("Green Wall Watering", device.getDeviceName());
298         assertFalse(device.isTimerOn());
299         assertFalse(device.stateManual());
300
301         // test a device that is offline
302         device = liveDataResponse.getDeviceRecord("Shower Room");
303         assertNotNull(device);
304         assertEquals("Shower Room", device.getDeviceName());
305         assertTrue(device.offline());
306
307         // test a device with a low battery
308         device = liveDataResponse.getDeviceRecord("Conservatory");
309         assertNotNull(device);
310         assertEquals("Conservatory", device.getDeviceName());
311         assertTrue(device.isBatteryLow());
312
313         // test a device with an open window alarm
314         device = liveDataResponse.getDeviceRecord("Door Contact");
315         assertNotNull(device);
316         assertEquals("Door Contact", device.getDeviceName());
317         assertTrue(device.isWindowOpen());
318
319         // test a wireless temperature sensor
320         device = liveDataResponse.getDeviceRecord("Room Sensor");
321         assertNotNull(device);
322         assertEquals("Room Sensor", device.getDeviceName());
323         assertEquals(new BigDecimal("21.5"), device.getActualTemperature());
324
325         // test a repeater node
326         device = liveDataResponse.getDeviceRecord("repeaternode54473");
327         assertNotNull(device);
328         assertEquals("repeaternode54473", device.getDeviceName());
329         assertTrue(MATCHER_HEATMISER_REPEATER.matcher(device.getDeviceName()).matches());
330     }
331
332     /*
333      * From NeoHub rev2.6 onwards the INFO command is "deprecated" and the DEVICE_ID
334      * element is not returned in the GET_LIVE_DATA call so we must test the
335      * replacement GET_ENGINEERS command
336      */
337     @Test
338     public void testGetEngineersJson() {
339         // load GET_ENGINEERS JSON response string
340         NeoHubGetEngineersData engResponse = NeoHubGetEngineersData.createEngineersData(load("engineers"));
341         assertNotNull(engResponse);
342
343         // test device ID (type 12 thermostat device)
344         assertEquals(12, engResponse.getDeviceType("Dining Room"));
345
346         // test device ID (type 6 plug device)
347         assertEquals(6, engResponse.getDeviceType("Living Room South"));
348     }
349
350     /*
351      * send JSON request to the socket and retrieve JSON response
352      */
353     private String testCommunicationInner(String requestJson) {
354         NeoHubSocket socket = new NeoHubSocket("192.168.1.109", 4242, 5);
355         String responseJson = "";
356         try {
357             responseJson = socket.sendMessage(requestJson);
358         } catch (Exception e) {
359             assertTrue(false);
360         }
361         return responseJson;
362     }
363
364     /*
365      * Test the communications
366      */
367     @Test
368     public void testCommunications() {
369         String responseJson = testCommunicationInner(CMD_CODE_INFO);
370         assertFalse(responseJson.isEmpty());
371
372         responseJson = testCommunicationInner(CMD_CODE_READ_DCB);
373         assertFalse(responseJson.isEmpty());
374
375         NeoHubReadDcbResponse dcbResponse = NeoHubReadDcbResponse.createSystemData(responseJson);
376         assertNotNull(dcbResponse);
377
378         long timeStamp = dcbResponse.timeStamp;
379         assertEquals(Instant.now().getEpochSecond(), timeStamp, 1);
380
381         responseJson = testCommunicationInner(CMD_CODE_GET_LIVE_DATA);
382         assertFalse(responseJson.isEmpty());
383
384         NeoHubLiveDeviceData liveDataResponse = NeoHubLiveDeviceData.createDeviceData(responseJson);
385         assertNotNull(liveDataResponse);
386
387         assertTrue(timeStamp > liveDataResponse.getTimestampEngineers());
388         assertTrue(timeStamp > liveDataResponse.getTimestampSystem());
389
390         responseJson = testCommunicationInner(CMD_CODE_GET_ENGINEERS);
391         assertFalse(responseJson.isEmpty());
392
393         responseJson = testCommunicationInner(CMD_CODE_GET_SYSTEM);
394         assertFalse(responseJson.isEmpty());
395
396         responseJson = testCommunicationInner(String.format(CMD_CODE_TEMP, "20", "Hallway"));
397         assertFalse(responseJson.isEmpty());
398     }
399 }