]> git.basschouten.com Git - openhab-addons.git/blob
dca4c824aa22796fa5e8aedad9703eb2ff904369
[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.mqtt.ruuvigateway.internal.parser;
14
15 import static org.junit.jupiter.api.Assertions.*;
16
17 import java.nio.ByteBuffer;
18 import java.nio.charset.StandardCharsets;
19 import java.time.Instant;
20 import java.util.Optional;
21
22 import org.eclipse.jdt.annotation.NonNullByDefault;
23 import org.junit.jupiter.api.Test;
24 import org.openhab.binding.mqtt.ruuvigateway.internal.parser.GatewayPayloadParser.GatewayPayload;
25
26 import com.google.gson.JsonSyntaxException;
27
28 /**
29  * Tests for {@link GatewayPayloadParser}
30  *
31  * @author Sami Salonen - Initial Contribution
32  */
33 @NonNullByDefault
34 public class GatewayPayloadParserTests {
35
36     private byte[] bytes(String str) {
37         ByteBuffer buffer = StandardCharsets.UTF_8.encode(str);
38         buffer.rewind();
39         byte[] bytes = new byte[buffer.remaining()];
40         buffer.get(bytes);
41         return bytes;
42     }
43
44     /**
45      * Test with valid data.
46      *
47      * See 'valid case' test vector from
48      * https://docs.ruuvi.com/communication/bluetooth-advertisements/data-format-5-rawv2
49      */
50     @Test
51     public void testValid() {
52         GatewayPayload parsed = GatewayPayloadParser.parse(bytes(//
53                 "{\"gw_mac\": \"DE:AD:BE:EF:00:00\","//
54                         + "  \"rssi\": -83,"//
55                         + "  \"aoa\": [],"//
56                         + "  \"gwts\": \"1659365438\","//
57                         + "  \"ts\": \"1659365439\","//
58                         + "  \"data\": \"0201061BFF99040512FC5394C37C0004FFFC040CAC364200CDCBB8334C884F\","//
59                         + "  \"coords\": \"\"" + "}"));
60         assertNotNull(parsed);
61         assertEquals(-83, parsed.rssi);
62         assertEquals(Optional.of(Instant.ofEpochSecond(1659365438)), parsed.gwts);
63         assertEquals(Optional.of(Instant.ofEpochSecond(1659365439)), parsed.ts);
64         assertEquals(24.3, parsed.measurement.getTemperature());
65         assertEquals(100044, parsed.measurement.getPressure());
66         assertEquals(5, parsed.measurement.getDataFormat());
67         assertEquals(53.49, parsed.measurement.getHumidity());
68         assertEquals(0.004, parsed.measurement.getAccelerationX());
69         assertEquals(-0.004, parsed.measurement.getAccelerationY());
70         assertEquals(1.036, parsed.measurement.getAccelerationZ());
71         assertEquals(4, parsed.measurement.getTxPower());
72         assertEquals(2.9770000000000003, parsed.measurement.getBatteryVoltage());
73         assertEquals(66, parsed.measurement.getMovementCounter());
74         assertEquals(205, parsed.measurement.getMeasurementSequenceNumber());
75     }
76
77     @Test
78     public void testInvalidJSON() {
79         assertThrows(JsonSyntaxException.class, () -> {
80             GatewayPayloadParser.parse(bytes(//
81                     "invalid json"));
82         });
83     }
84
85     @Test
86     public void testUnexpectedTypes() {
87         assertThrows(IllegalArgumentException.class, () -> {
88             GatewayPayloadParser.parse(bytes(//
89                     "{\"gw_mac\": \"DE:AD:BE:EF:00:00\","//
90                             + "  \"rssi\": -83,"//
91                             + "  \"aoa\": [],"//
92                             + "  \"gwts\": \"1659365438\","//
93                             + "  \"ts\": \"1659365438\","//
94                             + "  \"data\": 666," // should be hex-string of even length
95                             + "  \"coords\": \"\"" + "}"));
96         });
97     }
98
99     @Test
100     public void testInvalidHex() {
101         assertThrows(IllegalArgumentException.class, () -> {
102             GatewayPayloadParser.parse(bytes(//
103                     "{\"gw_mac\": \"DE:AD:BE:EF:00:00\","//
104                             + "  \"rssi\": -83,"//
105                             + "  \"aoa\": [],"//
106                             + "  \"gwts\": \"1659365438\","//
107                             + "  \"ts\": \"1659365438\","//
108                             + "  \"data\": \"XYZZ\"," // should be hex string
109                             + "  \"coords\": \"\"" + "}"));
110         });
111     }
112
113     @Test
114     public void testUnexpectedTypes3() {
115         assertThrows(JsonSyntaxException.class, () -> {
116             GatewayPayloadParser.parse(bytes(//
117                     "{\"gw_mac\": \"DE:AD:BE:EF:00:00\","//
118                             + "  \"rssi\": \"foobar\","// should be number
119                             + "  \"aoa\": [],"//
120                             + "  \"gwts\": \"1659365438\","//
121                             + "  \"ts\": \"1659365438\","//
122                             + "  \"data\": \"0201061BFF99040512FC5394C37C0004FFFC040CAC364200CDCBB8334C884F\","
123                             + "  \"coords\": \"\"" + "}"));
124         });
125     }
126
127     @Test
128     public void testDataTooShort() {
129         assertThrows(IllegalArgumentException.class, () -> {
130             GatewayPayloadParser.parse(bytes(//
131                     "{\"gw_mac\": \"DE:AD:BE:EF:00:00\","//
132                             + "  \"rssi\": -83," + "  \"aoa\": [],"//
133                             + "  \"gwts\": \"1659365438\","//
134                             + "  \"ts\": \"1659365438\","//
135                             + "  \"data\": \"0201061BFF990405\"," // too short
136                             + "  \"coords\": \"\"" + "}"));
137         });
138     }
139
140     @Test
141     public void testUnexpectedManufacturer() {
142         assertThrows(IllegalArgumentException.class, () -> {
143             GatewayPayloadParser.parse(bytes(//
144                     "{\"gw_mac\": \"DE:AD:BE:EF:00:00\","//
145                             + "  \"rssi\": -83,"//
146                             + "  \"aoa\": [],"//
147                             + "  \"gwts\": \"1659365438\","//
148                             + "  \"ts\": \"1659365438\","//
149             // manufacturer is not 99 04 (Ruuvi) but 99 99
150                             + "  \"data\": \"0201061BFF99990512FC5394C37C0004FFFC040CAC364200CDCBB8334C884F\","
151                             + "  \"coords\": \"\"" + "}"));
152         });
153     }
154
155     @Test
156     public void testDataNotBluetoothAdvertisement() {
157         assertThrows(IllegalArgumentException.class, () -> {
158             GatewayPayloadParser.parse(bytes(//
159                     "{\"gw_mac\": \"DE:AD:BE:EF:00:00\","//
160                             + "  \"rssi\": -83,"//
161                             + "  \"aoa\": [],"//
162                             + "  \"gwts\": \"1659365438\","//
163                             + "  \"ts\": \"1659365438\","//
164             // not advertisement (FF) but AA
165                             + "  \"data\": \"0201061BAA99040512FC5394C37C0004FFFC040CAC364200CDCBB8334C884F\","
166                             + "  \"coords\": \"\"" + "}"));
167         });
168     }
169 }