Commit c5c8fbd3f73e5def00efd4390449ca99acaf080f
Committed by
GitHub
1 parent
dff593a3
[3.2.2] [WIP] coap transport (#4239)
* init CoapDeviceProfile & added ui components * added transport payload type configuration for default coap device type * added AbstractCoapTransportResource & updated efento resource * fixed coap device profile save & update * fixed Attribute Updates notifications * revert CoapOkCallback onSuccess changes * updated provision request to handle proto payload type * fix license * updated Rpc subscribe/unsubscribe action * add more device emulator clients * added fix for Coap Transport: ability to handle requests with oneElementUriPaths and MultiElementUriPaths * fix TbCoapServer implementation * changed response type to CREATED in POST requests * improved implementation * fix typos * minor bug-fixes & improvements * fix TbCoapServerMessageDeliverer class * improved relay sensor implementation * added tests for CoAP transport\ * fix typo * removed nosql tests * fix coap endpoint creation & improved getAttributes tests * transport tests refactoring
Showing
137 changed files
with
5265 additions
and
787 deletions
application/src/test/java/org/thingsboard/server/transport/AbstractTransportIntegrationTest.java
renamed from
application/src/test/java/org/thingsboard/server/mqtt/AbstractMqttIntegrationTest.java
... | ... | @@ -13,7 +13,7 @@ |
13 | 13 | * See the License for the specific language governing permissions and |
14 | 14 | * limitations under the License. |
15 | 15 | */ |
16 | -package org.thingsboard.server.mqtt; | |
16 | +package org.thingsboard.server.transport; | |
17 | 17 | |
18 | 18 | import com.fasterxml.jackson.databind.node.ObjectNode; |
19 | 19 | import lombok.extern.slf4j.Slf4j; |
... | ... | @@ -56,13 +56,14 @@ import static org.junit.Assert.assertNotNull; |
56 | 56 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; |
57 | 57 | |
58 | 58 | @Slf4j |
59 | -public abstract class AbstractMqttIntegrationTest extends AbstractControllerTest { | |
59 | +public abstract class AbstractTransportIntegrationTest extends AbstractControllerTest { | |
60 | 60 | |
61 | 61 | protected static final String MQTT_URL = "tcp://localhost:1883"; |
62 | + protected static final String COAP_BASE_URL = "coap://localhost:5683/api/v1/"; | |
62 | 63 | |
63 | - private static final AtomicInteger atomicInteger = new AtomicInteger(2); | |
64 | + protected static final AtomicInteger atomicInteger = new AtomicInteger(2); | |
64 | 65 | |
65 | - public static final String DEVICE_TELEMETRY_PROTO_SCHEMA = "syntax =\"proto3\";\n" + | |
66 | + protected static final String DEVICE_TELEMETRY_PROTO_SCHEMA = "syntax =\"proto3\";\n" + | |
66 | 67 | "\n" + |
67 | 68 | "package test;\n" + |
68 | 69 | "\n" + |
... | ... | @@ -83,7 +84,7 @@ public abstract class AbstractMqttIntegrationTest extends AbstractControllerTest |
83 | 84 | " }\n" + |
84 | 85 | "}"; |
85 | 86 | |
86 | - public static final String DEVICE_ATTRIBUTES_PROTO_SCHEMA = "syntax =\"proto3\";\n" + | |
87 | + protected static final String DEVICE_ATTRIBUTES_PROTO_SCHEMA = "syntax =\"proto3\";\n" + | |
87 | 88 | "\n" + |
88 | 89 | "package test;\n" + |
89 | 90 | "\n" + |
... | ... | @@ -110,81 +111,8 @@ public abstract class AbstractMqttIntegrationTest extends AbstractControllerTest |
110 | 111 | protected Device savedDevice; |
111 | 112 | protected String accessToken; |
112 | 113 | |
113 | - protected Device savedGateway; | |
114 | - protected String gatewayAccessToken; | |
115 | - | |
116 | 114 | protected DeviceProfile deviceProfile; |
117 | 115 | |
118 | - protected void processBeforeTest (String deviceName, String gatewayName, TransportPayloadType payloadType, String telemetryTopic, String attributesTopic) throws Exception { | |
119 | - this.processBeforeTest(deviceName, gatewayName, payloadType, telemetryTopic, attributesTopic, null, null, DeviceProfileProvisionType.DISABLED, null, null); | |
120 | - } | |
121 | - | |
122 | - protected void processBeforeTest(String deviceName, | |
123 | - String gatewayName, | |
124 | - TransportPayloadType payloadType, | |
125 | - String telemetryTopic, | |
126 | - String attributesTopic, | |
127 | - String telemetryProtoSchema, | |
128 | - String attributesProtoSchema, | |
129 | - DeviceProfileProvisionType provisionType, | |
130 | - String provisionKey, String provisionSecret | |
131 | - ) throws Exception { | |
132 | - loginSysAdmin(); | |
133 | - | |
134 | - Tenant tenant = new Tenant(); | |
135 | - tenant.setTitle("My tenant"); | |
136 | - savedTenant = doPost("/api/tenant", tenant, Tenant.class); | |
137 | - Assert.assertNotNull(savedTenant); | |
138 | - | |
139 | - tenantAdmin = new User(); | |
140 | - tenantAdmin.setAuthority(Authority.TENANT_ADMIN); | |
141 | - tenantAdmin.setTenantId(savedTenant.getId()); | |
142 | - tenantAdmin.setEmail("tenant" + atomicInteger.getAndIncrement() + "@thingsboard.org"); | |
143 | - tenantAdmin.setFirstName("Joe"); | |
144 | - tenantAdmin.setLastName("Downs"); | |
145 | - | |
146 | - tenantAdmin = createUserAndLogin(tenantAdmin, "testPassword1"); | |
147 | - | |
148 | - Device device = new Device(); | |
149 | - device.setName(deviceName); | |
150 | - device.setType("default"); | |
151 | - | |
152 | - Device gateway = new Device(); | |
153 | - gateway.setName(gatewayName); | |
154 | - gateway.setType("default"); | |
155 | - ObjectNode additionalInfo = mapper.createObjectNode(); | |
156 | - additionalInfo.put("gateway", true); | |
157 | - gateway.setAdditionalInfo(additionalInfo); | |
158 | - | |
159 | - if (payloadType != null) { | |
160 | - DeviceProfile mqttDeviceProfile = createMqttDeviceProfile(payloadType, telemetryTopic, attributesTopic, telemetryProtoSchema, attributesProtoSchema, provisionType, provisionKey, provisionSecret); | |
161 | - deviceProfile = doPost("/api/deviceProfile", mqttDeviceProfile, DeviceProfile.class); | |
162 | - device.setType(deviceProfile.getName()); | |
163 | - device.setDeviceProfileId(deviceProfile.getId()); | |
164 | - gateway.setType(deviceProfile.getName()); | |
165 | - gateway.setDeviceProfileId(deviceProfile.getId()); | |
166 | - } | |
167 | - | |
168 | - savedDevice = doPost("/api/device", device, Device.class); | |
169 | - | |
170 | - DeviceCredentials deviceCredentials = | |
171 | - doGet("/api/device/" + savedDevice.getId().getId().toString() + "/credentials", DeviceCredentials.class); | |
172 | - | |
173 | - savedGateway = doPost("/api/device", gateway, Device.class); | |
174 | - | |
175 | - DeviceCredentials gatewayCredentials = | |
176 | - doGet("/api/device/" + savedGateway.getId().getId().toString() + "/credentials", DeviceCredentials.class); | |
177 | - | |
178 | - assertEquals(savedDevice.getId(), deviceCredentials.getDeviceId()); | |
179 | - accessToken = deviceCredentials.getCredentialsId(); | |
180 | - assertNotNull(accessToken); | |
181 | - | |
182 | - assertEquals(savedGateway.getId(), gatewayCredentials.getDeviceId()); | |
183 | - gatewayAccessToken = gatewayCredentials.getCredentialsId(); | |
184 | - assertNotNull(gatewayAccessToken); | |
185 | - | |
186 | - } | |
187 | - | |
188 | 116 | protected void processAfterTest() throws Exception { |
189 | 117 | loginSysAdmin(); |
190 | 118 | if (savedTenant != null) { |
... | ... | @@ -192,22 +120,6 @@ public abstract class AbstractMqttIntegrationTest extends AbstractControllerTest |
192 | 120 | } |
193 | 121 | } |
194 | 122 | |
195 | - protected MqttAsyncClient getMqttAsyncClient(String accessToken) throws MqttException { | |
196 | - String clientId = MqttAsyncClient.generateClientId(); | |
197 | - MqttAsyncClient client = new MqttAsyncClient(MQTT_URL, clientId, new MemoryPersistence()); | |
198 | - | |
199 | - MqttConnectOptions options = new MqttConnectOptions(); | |
200 | - options.setUserName(accessToken); | |
201 | - client.connect(options).waitForCompletion(); | |
202 | - return client; | |
203 | - } | |
204 | - | |
205 | - protected void publishMqttMsg(MqttAsyncClient client, byte[] payload, String topic) throws MqttException { | |
206 | - MqttMessage message = new MqttMessage(); | |
207 | - message.setPayload(payload); | |
208 | - client.publish(topic, message); | |
209 | - } | |
210 | - | |
211 | 123 | protected List<TransportProtos.KeyValueProto> getKvProtos(List<String> expectedKeys) { |
212 | 124 | List<TransportProtos.KeyValueProto> keyValueProtos = new ArrayList<>(); |
213 | 125 | TransportProtos.KeyValueProto strKeyValueProto = getKeyValueProto(expectedKeys.get(0), "value1", TransportProtos.KeyValueType.STRING_V); |
... | ... | @@ -247,72 +159,6 @@ public abstract class AbstractMqttIntegrationTest extends AbstractControllerTest |
247 | 159 | return keyValueProtoBuilder.build(); |
248 | 160 | } |
249 | 161 | |
250 | - protected DeviceProfile createMqttDeviceProfile(TransportPayloadType transportPayloadType, | |
251 | - String telemetryTopic, String attributesTopic, | |
252 | - String telemetryProtoSchema, String attributesProtoSchema, | |
253 | - DeviceProfileProvisionType provisionType, | |
254 | - String provisionKey, String provisionSecret) { | |
255 | - DeviceProfile deviceProfile = new DeviceProfile(); | |
256 | - deviceProfile.setName(transportPayloadType.name()); | |
257 | - deviceProfile.setType(DeviceProfileType.DEFAULT); | |
258 | - deviceProfile.setTransportType(DeviceTransportType.MQTT); | |
259 | - deviceProfile.setProvisionType(provisionType); | |
260 | - deviceProfile.setProvisionDeviceKey(provisionKey); | |
261 | - deviceProfile.setDescription(transportPayloadType.name() + " Test"); | |
262 | - DeviceProfileData deviceProfileData = new DeviceProfileData(); | |
263 | - DefaultDeviceProfileConfiguration configuration = new DefaultDeviceProfileConfiguration(); | |
264 | - MqttDeviceProfileTransportConfiguration mqttDeviceProfileTransportConfiguration = new MqttDeviceProfileTransportConfiguration(); | |
265 | - if (!StringUtils.isEmpty(telemetryTopic)) { | |
266 | - mqttDeviceProfileTransportConfiguration.setDeviceTelemetryTopic(telemetryTopic); | |
267 | - } | |
268 | - if (!StringUtils.isEmpty(attributesTopic)) { | |
269 | - mqttDeviceProfileTransportConfiguration.setDeviceAttributesTopic(attributesTopic); | |
270 | - } | |
271 | - TransportPayloadTypeConfiguration transportPayloadTypeConfiguration; | |
272 | - if (TransportPayloadType.JSON.equals(transportPayloadType)) { | |
273 | - transportPayloadTypeConfiguration = new JsonTransportPayloadConfiguration(); | |
274 | - } else { | |
275 | - ProtoTransportPayloadConfiguration protoTransportPayloadConfiguration = new ProtoTransportPayloadConfiguration(); | |
276 | - if (StringUtils.isEmpty(telemetryProtoSchema)) { | |
277 | - telemetryProtoSchema = DEVICE_TELEMETRY_PROTO_SCHEMA; | |
278 | - } | |
279 | - if (StringUtils.isEmpty(attributesProtoSchema)) { | |
280 | - attributesProtoSchema = DEVICE_ATTRIBUTES_PROTO_SCHEMA; | |
281 | - } | |
282 | - protoTransportPayloadConfiguration.setDeviceTelemetryProtoSchema(telemetryProtoSchema); | |
283 | - protoTransportPayloadConfiguration.setDeviceAttributesProtoSchema(attributesProtoSchema); | |
284 | - transportPayloadTypeConfiguration = protoTransportPayloadConfiguration; | |
285 | - } | |
286 | - mqttDeviceProfileTransportConfiguration.setTransportPayloadTypeConfiguration(transportPayloadTypeConfiguration); | |
287 | - deviceProfileData.setTransportConfiguration(mqttDeviceProfileTransportConfiguration); | |
288 | - DeviceProfileProvisionConfiguration provisionConfiguration; | |
289 | - switch (provisionType) { | |
290 | - case ALLOW_CREATE_NEW_DEVICES: | |
291 | - provisionConfiguration = new AllowCreateNewDevicesDeviceProfileProvisionConfiguration(provisionSecret); | |
292 | - break; | |
293 | - case CHECK_PRE_PROVISIONED_DEVICES: | |
294 | - provisionConfiguration = new CheckPreProvisionedDevicesDeviceProfileProvisionConfiguration(provisionSecret); | |
295 | - break; | |
296 | - case DISABLED: | |
297 | - default: | |
298 | - provisionConfiguration = new DisabledDeviceProfileProvisionConfiguration(provisionSecret); | |
299 | - break; | |
300 | - } | |
301 | - deviceProfileData.setProvisionConfiguration(provisionConfiguration); | |
302 | - deviceProfileData.setConfiguration(configuration); | |
303 | - deviceProfile.setProfileData(deviceProfileData); | |
304 | - deviceProfile.setDefault(false); | |
305 | - deviceProfile.setDefaultRuleChainId(null); | |
306 | - return deviceProfile; | |
307 | - } | |
308 | - | |
309 | - protected TransportProtos.PostAttributeMsg getPostAttributeMsg(List<String> expectedKeys) { | |
310 | - List<TransportProtos.KeyValueProto> kvProtos = getKvProtos(expectedKeys); | |
311 | - TransportProtos.PostAttributeMsg.Builder builder = TransportProtos.PostAttributeMsg.newBuilder(); | |
312 | - builder.addAllKv(kvProtos); | |
313 | - return builder.build(); | |
314 | - } | |
315 | - | |
316 | 162 | protected <T> T doExecuteWithRetriesAndInterval(SupplierWithThrowable<T> supplier, int retries, int intervalMs) throws Exception { |
317 | 163 | int count = 0; |
318 | 164 | T result = null; | ... | ... |
application/src/test/java/org/thingsboard/server/transport/TransportNoSqlTestSuite.java
renamed from
application/src/test/java/org/thingsboard/server/mqtt/MqttNoSqlTestSuite.java
... | ... | @@ -13,7 +13,7 @@ |
13 | 13 | * See the License for the specific language governing permissions and |
14 | 14 | * limitations under the License. |
15 | 15 | */ |
16 | -package org.thingsboard.server.mqtt; | |
16 | +package org.thingsboard.server.transport; | |
17 | 17 | |
18 | 18 | import org.cassandraunit.dataset.cql.ClassPathCQLDataSet; |
19 | 19 | import org.junit.BeforeClass; |
... | ... | @@ -28,8 +28,8 @@ import java.util.Arrays; |
28 | 28 | |
29 | 29 | @RunWith(ClasspathSuite.class) |
30 | 30 | @ClasspathSuite.ClassnameFilters({ |
31 | - "org.thingsboard.server.mqtt.*.nosql.*Test"}) | |
32 | -public class MqttNoSqlTestSuite { | |
31 | + "org.thingsboard.server.transport.*.telemetry.timeseries.nosql.*Test"}) | |
32 | +public class TransportNoSqlTestSuite { | |
33 | 33 | |
34 | 34 | @ClassRule |
35 | 35 | public static CustomSqlUnit sqlUnit = new CustomSqlUnit( | ... | ... |
application/src/test/java/org/thingsboard/server/transport/TransportSqlTestSuite.java
renamed from
application/src/test/java/org/thingsboard/server/mqtt/MqttSqlTestSuite.java
... | ... | @@ -13,7 +13,7 @@ |
13 | 13 | * See the License for the specific language governing permissions and |
14 | 14 | * limitations under the License. |
15 | 15 | */ |
16 | -package org.thingsboard.server.mqtt; | |
16 | +package org.thingsboard.server.transport; | |
17 | 17 | |
18 | 18 | import org.junit.BeforeClass; |
19 | 19 | import org.junit.ClassRule; |
... | ... | @@ -26,15 +26,15 @@ import java.util.Arrays; |
26 | 26 | |
27 | 27 | @RunWith(ClasspathSuite.class) |
28 | 28 | @ClasspathSuite.ClassnameFilters({ |
29 | - "org.thingsboard.server.mqtt.rpc.sql.*Test", | |
30 | - "org.thingsboard.server.mqtt.telemetry.timeseries.sql.*Test", | |
31 | - "org.thingsboard.server.mqtt.telemetry.attributes.sql.*Test", | |
32 | - "org.thingsboard.server.mqtt.attributes.updates.sql.*Test", | |
33 | - "org.thingsboard.server.mqtt.attributes.request.sql.*Test", | |
34 | - "org.thingsboard.server.mqtt.claim.sql.*Test", | |
35 | - "org.thingsboard.server.mqtt.provision.sql.*Test" | |
29 | + "org.thingsboard.server.transport.*.rpc.sql.*Test", | |
30 | + "org.thingsboard.server.transport.*.telemetry.timeseries.sql.*Test", | |
31 | + "org.thingsboard.server.transport.*.telemetry.attributes.sql.*Test", | |
32 | + "org.thingsboard.server.transport.*.attributes.updates.sql.*Test", | |
33 | + "org.thingsboard.server.transport.*.attributes.request.sql.*Test", | |
34 | + "org.thingsboard.server.transport.*.claim.sql.*Test", | |
35 | + "org.thingsboard.server.transport.*.provision.sql.*Test" | |
36 | 36 | }) |
37 | -public class MqttSqlTestSuite { | |
37 | +public class TransportSqlTestSuite { | |
38 | 38 | |
39 | 39 | @ClassRule |
40 | 40 | public static CustomSqlUnit sqlUnit = new CustomSqlUnit( | ... | ... |
application/src/test/java/org/thingsboard/server/transport/coap/AbstractCoapIntegrationTest.java
0 → 100644
1 | +/** | |
2 | + * Copyright © 2016-2021 The Thingsboard Authors | |
3 | + * | |
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | |
5 | + * you may not use this file except in compliance with the License. | |
6 | + * You may obtain a copy of the License at | |
7 | + * | |
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | |
9 | + * | |
10 | + * Unless required by applicable law or agreed to in writing, software | |
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | |
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 | + * See the License for the specific language governing permissions and | |
14 | + * limitations under the License. | |
15 | + */ | |
16 | +package org.thingsboard.server.transport.coap; | |
17 | + | |
18 | +import lombok.extern.slf4j.Slf4j; | |
19 | +import org.eclipse.californium.core.CoapClient; | |
20 | +import org.junit.Assert; | |
21 | +import org.springframework.util.StringUtils; | |
22 | +import org.thingsboard.server.common.data.CoapDeviceType; | |
23 | +import org.thingsboard.server.common.data.Device; | |
24 | +import org.thingsboard.server.common.data.DeviceProfile; | |
25 | +import org.thingsboard.server.common.data.DeviceProfileProvisionType; | |
26 | +import org.thingsboard.server.common.data.DeviceProfileType; | |
27 | +import org.thingsboard.server.common.data.DeviceTransportType; | |
28 | +import org.thingsboard.server.common.data.Tenant; | |
29 | +import org.thingsboard.server.common.data.TransportPayloadType; | |
30 | +import org.thingsboard.server.common.data.User; | |
31 | +import org.thingsboard.server.common.data.device.profile.AllowCreateNewDevicesDeviceProfileProvisionConfiguration; | |
32 | +import org.thingsboard.server.common.data.device.profile.CheckPreProvisionedDevicesDeviceProfileProvisionConfiguration; | |
33 | +import org.thingsboard.server.common.data.device.profile.CoapDeviceProfileTransportConfiguration; | |
34 | +import org.thingsboard.server.common.data.device.profile.CoapDeviceTypeConfiguration; | |
35 | +import org.thingsboard.server.common.data.device.profile.DefaultCoapDeviceTypeConfiguration; | |
36 | +import org.thingsboard.server.common.data.device.profile.DefaultDeviceProfileConfiguration; | |
37 | +import org.thingsboard.server.common.data.device.profile.DeviceProfileData; | |
38 | +import org.thingsboard.server.common.data.device.profile.DeviceProfileProvisionConfiguration; | |
39 | +import org.thingsboard.server.common.data.device.profile.DisabledDeviceProfileProvisionConfiguration; | |
40 | +import org.thingsboard.server.common.data.device.profile.EfentoCoapDeviceTypeConfiguration; | |
41 | +import org.thingsboard.server.common.data.device.profile.JsonTransportPayloadConfiguration; | |
42 | +import org.thingsboard.server.common.data.device.profile.ProtoTransportPayloadConfiguration; | |
43 | +import org.thingsboard.server.common.data.device.profile.TransportPayloadTypeConfiguration; | |
44 | +import org.thingsboard.server.common.data.security.Authority; | |
45 | +import org.thingsboard.server.common.data.security.DeviceCredentials; | |
46 | +import org.thingsboard.server.common.msg.session.FeatureType; | |
47 | +import org.thingsboard.server.transport.AbstractTransportIntegrationTest; | |
48 | + | |
49 | +import static org.junit.Assert.assertEquals; | |
50 | +import static org.junit.Assert.assertNotNull; | |
51 | + | |
52 | +@Slf4j | |
53 | +public abstract class AbstractCoapIntegrationTest extends AbstractTransportIntegrationTest { | |
54 | + | |
55 | + protected void processBeforeTest(String deviceName, CoapDeviceType coapDeviceType, TransportPayloadType payloadType) throws Exception { | |
56 | + this.processBeforeTest(deviceName, coapDeviceType, payloadType, null, null, DeviceProfileProvisionType.DISABLED, null, null); | |
57 | + } | |
58 | + | |
59 | + protected void processBeforeTest(String deviceName, | |
60 | + CoapDeviceType coapDeviceType, | |
61 | + TransportPayloadType payloadType, | |
62 | + String telemetryProtoSchema, | |
63 | + String attributesProtoSchema, | |
64 | + DeviceProfileProvisionType provisionType, | |
65 | + String provisionKey, String provisionSecret | |
66 | + ) throws Exception { | |
67 | + loginSysAdmin(); | |
68 | + | |
69 | + Tenant tenant = new Tenant(); | |
70 | + tenant.setTitle("My tenant"); | |
71 | + savedTenant = doPost("/api/tenant", tenant, Tenant.class); | |
72 | + Assert.assertNotNull(savedTenant); | |
73 | + | |
74 | + tenantAdmin = new User(); | |
75 | + tenantAdmin.setAuthority(Authority.TENANT_ADMIN); | |
76 | + tenantAdmin.setTenantId(savedTenant.getId()); | |
77 | + tenantAdmin.setEmail("tenant" + atomicInteger.getAndIncrement() + "@thingsboard.org"); | |
78 | + tenantAdmin.setFirstName("Joe"); | |
79 | + tenantAdmin.setLastName("Downs"); | |
80 | + | |
81 | + tenantAdmin = createUserAndLogin(tenantAdmin, "testPassword1"); | |
82 | + | |
83 | + Device device = new Device(); | |
84 | + device.setName(deviceName); | |
85 | + device.setType("default"); | |
86 | + | |
87 | + if (coapDeviceType != null) { | |
88 | + DeviceProfile coapDeviceProfile = createCoapDeviceProfile(payloadType, coapDeviceType, attributesProtoSchema, provisionType, provisionKey, provisionSecret, telemetryProtoSchema); | |
89 | + deviceProfile = doPost("/api/deviceProfile", coapDeviceProfile, DeviceProfile.class); | |
90 | + device.setType(deviceProfile.getName()); | |
91 | + device.setDeviceProfileId(deviceProfile.getId()); | |
92 | + } | |
93 | + | |
94 | + savedDevice = doPost("/api/device", device, Device.class); | |
95 | + | |
96 | + DeviceCredentials deviceCredentials = | |
97 | + doGet("/api/device/" + savedDevice.getId().getId().toString() + "/credentials", DeviceCredentials.class); | |
98 | + | |
99 | + assertEquals(savedDevice.getId(), deviceCredentials.getDeviceId()); | |
100 | + accessToken = deviceCredentials.getCredentialsId(); | |
101 | + assertNotNull(accessToken); | |
102 | + | |
103 | + } | |
104 | + | |
105 | + protected DeviceProfile createCoapDeviceProfile(TransportPayloadType transportPayloadType, CoapDeviceType coapDeviceType, | |
106 | + String attributesProtoSchema, DeviceProfileProvisionType provisionType, | |
107 | + String provisionKey, String provisionSecret, String telemetryProtoSchema) { | |
108 | + DeviceProfile deviceProfile = new DeviceProfile(); | |
109 | + deviceProfile.setName(transportPayloadType.name()); | |
110 | + deviceProfile.setType(DeviceProfileType.DEFAULT); | |
111 | + deviceProfile.setProvisionType(provisionType); | |
112 | + deviceProfile.setProvisionDeviceKey(provisionKey); | |
113 | + deviceProfile.setDescription(transportPayloadType.name() + " Test"); | |
114 | + DeviceProfileData deviceProfileData = new DeviceProfileData(); | |
115 | + DefaultDeviceProfileConfiguration configuration = new DefaultDeviceProfileConfiguration(); | |
116 | + deviceProfile.setTransportType(DeviceTransportType.COAP); | |
117 | + CoapDeviceProfileTransportConfiguration coapDeviceProfileTransportConfiguration = new CoapDeviceProfileTransportConfiguration(); | |
118 | + CoapDeviceTypeConfiguration coapDeviceTypeConfiguration; | |
119 | + if (CoapDeviceType.DEFAULT.equals(coapDeviceType)) { | |
120 | + DefaultCoapDeviceTypeConfiguration defaultCoapDeviceTypeConfiguration = new DefaultCoapDeviceTypeConfiguration(); | |
121 | + TransportPayloadTypeConfiguration transportPayloadTypeConfiguration; | |
122 | + if (TransportPayloadType.PROTOBUF.equals(transportPayloadType)) { | |
123 | + ProtoTransportPayloadConfiguration protoTransportPayloadConfiguration = new ProtoTransportPayloadConfiguration(); | |
124 | + if (StringUtils.isEmpty(telemetryProtoSchema)) { | |
125 | + telemetryProtoSchema = DEVICE_TELEMETRY_PROTO_SCHEMA; | |
126 | + } | |
127 | + if (StringUtils.isEmpty(attributesProtoSchema)) { | |
128 | + attributesProtoSchema = DEVICE_ATTRIBUTES_PROTO_SCHEMA; | |
129 | + } | |
130 | + protoTransportPayloadConfiguration.setDeviceTelemetryProtoSchema(telemetryProtoSchema); | |
131 | + protoTransportPayloadConfiguration.setDeviceAttributesProtoSchema(attributesProtoSchema); | |
132 | + transportPayloadTypeConfiguration = protoTransportPayloadConfiguration; | |
133 | + } else { | |
134 | + transportPayloadTypeConfiguration = new JsonTransportPayloadConfiguration(); | |
135 | + } | |
136 | + defaultCoapDeviceTypeConfiguration.setTransportPayloadTypeConfiguration(transportPayloadTypeConfiguration); | |
137 | + coapDeviceTypeConfiguration = defaultCoapDeviceTypeConfiguration; | |
138 | + } else { | |
139 | + coapDeviceTypeConfiguration = new EfentoCoapDeviceTypeConfiguration(); | |
140 | + } | |
141 | + coapDeviceProfileTransportConfiguration.setCoapDeviceTypeConfiguration(coapDeviceTypeConfiguration); | |
142 | + deviceProfileData.setTransportConfiguration(coapDeviceProfileTransportConfiguration); | |
143 | + DeviceProfileProvisionConfiguration provisionConfiguration; | |
144 | + switch (provisionType) { | |
145 | + case ALLOW_CREATE_NEW_DEVICES: | |
146 | + provisionConfiguration = new AllowCreateNewDevicesDeviceProfileProvisionConfiguration(provisionSecret); | |
147 | + break; | |
148 | + case CHECK_PRE_PROVISIONED_DEVICES: | |
149 | + provisionConfiguration = new CheckPreProvisionedDevicesDeviceProfileProvisionConfiguration(provisionSecret); | |
150 | + break; | |
151 | + case DISABLED: | |
152 | + default: | |
153 | + provisionConfiguration = new DisabledDeviceProfileProvisionConfiguration(provisionSecret); | |
154 | + break; | |
155 | + } | |
156 | + deviceProfileData.setProvisionConfiguration(provisionConfiguration); | |
157 | + deviceProfileData.setConfiguration(configuration); | |
158 | + deviceProfile.setProfileData(deviceProfileData); | |
159 | + deviceProfile.setDefault(false); | |
160 | + deviceProfile.setDefaultRuleChainId(null); | |
161 | + return deviceProfile; | |
162 | + } | |
163 | + | |
164 | + protected CoapClient getCoapClient(FeatureType featureType) { | |
165 | + return new CoapClient(getFeatureTokenUrl(accessToken, featureType)); | |
166 | + } | |
167 | + | |
168 | + protected CoapClient getCoapClient(String featureTokenUrl) { | |
169 | + return new CoapClient(featureTokenUrl); | |
170 | + } | |
171 | + | |
172 | + protected String getFeatureTokenUrl(String token, FeatureType featureType) { | |
173 | + return COAP_BASE_URL + token + "/" + featureType.name().toLowerCase(); | |
174 | + } | |
175 | +} | ... | ... |
1 | +/** | |
2 | + * Copyright © 2016-2021 The Thingsboard Authors | |
3 | + * | |
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | |
5 | + * you may not use this file except in compliance with the License. | |
6 | + * You may obtain a copy of the License at | |
7 | + * | |
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | |
9 | + * | |
10 | + * Unless required by applicable law or agreed to in writing, software | |
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | |
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 | + * See the License for the specific language governing permissions and | |
14 | + * limitations under the License. | |
15 | + */ | |
16 | +package org.thingsboard.server.transport.coap.attributes; | |
17 | + | |
18 | +import lombok.extern.slf4j.Slf4j; | |
19 | +import org.thingsboard.server.transport.coap.AbstractCoapIntegrationTest; | |
20 | +import org.thingsboard.server.common.data.CoapDeviceType; | |
21 | +import org.thingsboard.server.common.data.TransportPayloadType; | |
22 | +import org.thingsboard.server.gen.transport.TransportProtos; | |
23 | + | |
24 | +import java.util.ArrayList; | |
25 | +import java.util.List; | |
26 | + | |
27 | +@Slf4j | |
28 | +public abstract class AbstractCoapAttributesIntegrationTest extends AbstractCoapIntegrationTest { | |
29 | + | |
30 | + protected static final String POST_ATTRIBUTES_PAYLOAD = "{\"attribute1\":\"value1\",\"attribute2\":true,\"attribute3\":42.0,\"attribute4\":73," + | |
31 | + "\"attribute5\":{\"someNumber\":42,\"someArray\":[1,2,3],\"someNestedObject\":{\"key\":\"value\"}}}"; | |
32 | + | |
33 | + protected void processBeforeTest(String deviceName, CoapDeviceType coapDeviceType, TransportPayloadType payloadType) throws Exception { | |
34 | + super.processBeforeTest(deviceName, coapDeviceType, payloadType); | |
35 | + } | |
36 | + | |
37 | + protected void processAfterTest() throws Exception { | |
38 | + super.processAfterTest(); | |
39 | + } | |
40 | + | |
41 | + protected List<TransportProtos.TsKvProto> getTsKvProtoList() { | |
42 | + TransportProtos.TsKvProto tsKvProtoAttribute1 = getTsKvProto("attribute1", "value1", TransportProtos.KeyValueType.STRING_V); | |
43 | + TransportProtos.TsKvProto tsKvProtoAttribute2 = getTsKvProto("attribute2", "true", TransportProtos.KeyValueType.BOOLEAN_V); | |
44 | + TransportProtos.TsKvProto tsKvProtoAttribute3 = getTsKvProto("attribute3", "42.0", TransportProtos.KeyValueType.DOUBLE_V); | |
45 | + TransportProtos.TsKvProto tsKvProtoAttribute4 = getTsKvProto("attribute4", "73", TransportProtos.KeyValueType.LONG_V); | |
46 | + TransportProtos.TsKvProto tsKvProtoAttribute5 = getTsKvProto("attribute5", "{\"someNumber\":42,\"someArray\":[1,2,3],\"someNestedObject\":{\"key\":\"value\"}}", TransportProtos.KeyValueType.JSON_V); | |
47 | + List<TransportProtos.TsKvProto> tsKvProtoList = new ArrayList<>(); | |
48 | + tsKvProtoList.add(tsKvProtoAttribute1); | |
49 | + tsKvProtoList.add(tsKvProtoAttribute2); | |
50 | + tsKvProtoList.add(tsKvProtoAttribute3); | |
51 | + tsKvProtoList.add(tsKvProtoAttribute4); | |
52 | + tsKvProtoList.add(tsKvProtoAttribute5); | |
53 | + return tsKvProtoList; | |
54 | + } | |
55 | + | |
56 | + protected TransportProtos.TsKvProto getTsKvProto(String key, String value, TransportProtos.KeyValueType keyValueType) { | |
57 | + TransportProtos.TsKvProto.Builder tsKvProtoBuilder = TransportProtos.TsKvProto.newBuilder(); | |
58 | + TransportProtos.KeyValueProto keyValueProto = getKeyValueProto(key, value, keyValueType); | |
59 | + tsKvProtoBuilder.setKv(keyValueProto); | |
60 | + return tsKvProtoBuilder.build(); | |
61 | + } | |
62 | +} | ... | ... |
1 | +/** | |
2 | + * Copyright © 2016-2021 The Thingsboard Authors | |
3 | + * | |
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | |
5 | + * you may not use this file except in compliance with the License. | |
6 | + * You may obtain a copy of the License at | |
7 | + * | |
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | |
9 | + * | |
10 | + * Unless required by applicable law or agreed to in writing, software | |
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | |
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 | + * See the License for the specific language governing permissions and | |
14 | + * limitations under the License. | |
15 | + */ | |
16 | +package org.thingsboard.server.transport.coap.attributes.request; | |
17 | + | |
18 | +import com.fasterxml.jackson.core.type.TypeReference; | |
19 | +import com.google.protobuf.InvalidProtocolBufferException; | |
20 | +import lombok.extern.slf4j.Slf4j; | |
21 | +import org.eclipse.californium.core.CoapClient; | |
22 | +import org.eclipse.californium.core.CoapResponse; | |
23 | +import org.eclipse.californium.core.coap.CoAP; | |
24 | +import org.eclipse.californium.core.coap.MediaTypeRegistry; | |
25 | +import org.junit.After; | |
26 | +import org.junit.Before; | |
27 | +import org.junit.Test; | |
28 | +import org.thingsboard.server.transport.coap.attributes.AbstractCoapAttributesIntegrationTest; | |
29 | +import org.thingsboard.server.common.msg.session.FeatureType; | |
30 | +import org.thingsboard.server.dao.util.mapping.JacksonUtil; | |
31 | + | |
32 | +import java.nio.charset.StandardCharsets; | |
33 | +import java.util.List; | |
34 | + | |
35 | +import static org.junit.Assert.assertEquals; | |
36 | +import static org.junit.Assert.assertNotNull; | |
37 | +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; | |
38 | + | |
39 | +@Slf4j | |
40 | +public abstract class AbstractCoapAttributesRequestIntegrationTest extends AbstractCoapAttributesIntegrationTest { | |
41 | + | |
42 | + protected static final long CLIENT_REQUEST_TIMEOUT = 60000L; | |
43 | + | |
44 | + @Before | |
45 | + public void beforeTest() throws Exception { | |
46 | + processBeforeTest("Test Request attribute values from the server", null, null); | |
47 | + } | |
48 | + | |
49 | + @After | |
50 | + public void afterTest() throws Exception { | |
51 | + processAfterTest(); | |
52 | + } | |
53 | + | |
54 | + @Test | |
55 | + public void testRequestAttributesValuesFromTheServer() throws Exception { | |
56 | + processTestRequestAttributesValuesFromTheServer(); | |
57 | + } | |
58 | + | |
59 | + protected void processTestRequestAttributesValuesFromTheServer() throws Exception { | |
60 | + postAttributes(); | |
61 | + | |
62 | + long start = System.currentTimeMillis(); | |
63 | + long end = System.currentTimeMillis() + 5000; | |
64 | + | |
65 | + List<String> savedAttributeKeys = null; | |
66 | + while (start <= end) { | |
67 | + savedAttributeKeys = doGetAsyncTyped("/api/plugins/telemetry/DEVICE/" + savedDevice.getId().getId() + "/keys/attributes/CLIENT_SCOPE", new TypeReference<>() {}); | |
68 | + if (savedAttributeKeys.size() == 5) { | |
69 | + break; | |
70 | + } | |
71 | + Thread.sleep(100); | |
72 | + start += 100; | |
73 | + } | |
74 | + assertNotNull(savedAttributeKeys); | |
75 | + | |
76 | + String keys = "attribute1,attribute2,attribute3,attribute4,attribute5"; | |
77 | + String featureTokenUrl = getFeatureTokenUrl(accessToken, FeatureType.ATTRIBUTES) + "?clientKeys=" + keys + "&sharedKeys=" + keys; | |
78 | + CoapClient client = getCoapClient(featureTokenUrl); | |
79 | + | |
80 | + CoapResponse getAttributesResponse = client.setTimeout(CLIENT_REQUEST_TIMEOUT).get(); | |
81 | + validateResponse(getAttributesResponse); | |
82 | + } | |
83 | + | |
84 | + protected void postAttributes() throws Exception { | |
85 | + doPostAsync("/api/plugins/telemetry/DEVICE/" + savedDevice.getId().getId() + "/attributes/SHARED_SCOPE", POST_ATTRIBUTES_PAYLOAD, String.class, status().isOk()); | |
86 | + CoapClient client = getCoapClient(FeatureType.ATTRIBUTES); | |
87 | + CoapResponse coapResponse = client.setTimeout(CLIENT_REQUEST_TIMEOUT).post(POST_ATTRIBUTES_PAYLOAD.getBytes(), MediaTypeRegistry.APPLICATION_JSON); | |
88 | + assertEquals(CoAP.ResponseCode.CREATED, coapResponse.getCode()); | |
89 | + } | |
90 | + | |
91 | + protected void validateResponse(CoapResponse getAttributesResponse) throws InvalidProtocolBufferException { | |
92 | + assertEquals(CoAP.ResponseCode.CONTENT, getAttributesResponse.getCode()); | |
93 | + String expectedRequestPayload = "{\"client\":{\"attribute1\":\"value1\",\"attribute2\":true,\"attribute3\":42.0,\"attribute4\":73,\"attribute5\":{\"someNumber\":42,\"someArray\":[1,2,3],\"someNestedObject\":{\"key\":\"value\"}}},\"shared\":{\"attribute1\":\"value1\",\"attribute2\":true,\"attribute3\":42.0,\"attribute4\":73,\"attribute5\":{\"someNumber\":42,\"someArray\":[1,2,3],\"someNestedObject\":{\"key\":\"value\"}}}}"; | |
94 | + assertEquals(JacksonUtil.toJsonNode(expectedRequestPayload), JacksonUtil.toJsonNode(new String(getAttributesResponse.getPayload(), StandardCharsets.UTF_8))); | |
95 | + } | |
96 | +} | ... | ... |
1 | +/** | |
2 | + * Copyright © 2016-2021 The Thingsboard Authors | |
3 | + * | |
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | |
5 | + * you may not use this file except in compliance with the License. | |
6 | + * You may obtain a copy of the License at | |
7 | + * | |
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | |
9 | + * | |
10 | + * Unless required by applicable law or agreed to in writing, software | |
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | |
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 | + * See the License for the specific language governing permissions and | |
14 | + * limitations under the License. | |
15 | + */ | |
16 | +package org.thingsboard.server.transport.coap.attributes.request; | |
17 | + | |
18 | +import lombok.extern.slf4j.Slf4j; | |
19 | +import org.junit.After; | |
20 | +import org.junit.Before; | |
21 | +import org.junit.Test; | |
22 | +import org.thingsboard.server.common.data.CoapDeviceType; | |
23 | +import org.thingsboard.server.common.data.TransportPayloadType; | |
24 | + | |
25 | +@Slf4j | |
26 | +public abstract class AbstractCoapAttributesRequestJsonIntegrationTest extends AbstractCoapAttributesRequestIntegrationTest { | |
27 | + | |
28 | + @Before | |
29 | + public void beforeTest() throws Exception { | |
30 | + processBeforeTest("Test Request attribute values from the server json", CoapDeviceType.DEFAULT, TransportPayloadType.JSON); | |
31 | + } | |
32 | + | |
33 | + @After | |
34 | + public void afterTest() throws Exception { | |
35 | + processAfterTest(); | |
36 | + } | |
37 | + | |
38 | + @Test | |
39 | + public void testRequestAttributesValuesFromTheServer() throws Exception { | |
40 | + super.testRequestAttributesValuesFromTheServer(); | |
41 | + } | |
42 | +} | ... | ... |
1 | +/** | |
2 | + * Copyright © 2016-2021 The Thingsboard Authors | |
3 | + * | |
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | |
5 | + * you may not use this file except in compliance with the License. | |
6 | + * You may obtain a copy of the License at | |
7 | + * | |
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | |
9 | + * | |
10 | + * Unless required by applicable law or agreed to in writing, software | |
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | |
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 | + * See the License for the specific language governing permissions and | |
14 | + * limitations under the License. | |
15 | + */ | |
16 | +package org.thingsboard.server.transport.coap.attributes.request; | |
17 | + | |
18 | +import com.github.os72.protobuf.dynamic.DynamicSchema; | |
19 | +import com.google.protobuf.Descriptors; | |
20 | +import com.google.protobuf.DynamicMessage; | |
21 | +import com.google.protobuf.InvalidProtocolBufferException; | |
22 | +import com.squareup.wire.schema.internal.parser.ProtoFileElement; | |
23 | +import lombok.extern.slf4j.Slf4j; | |
24 | +import org.eclipse.californium.core.CoapClient; | |
25 | +import org.eclipse.californium.core.CoapResponse; | |
26 | +import org.eclipse.californium.core.coap.CoAP; | |
27 | +import org.eclipse.californium.core.coap.MediaTypeRegistry; | |
28 | +import org.junit.After; | |
29 | +import org.junit.Test; | |
30 | +import org.thingsboard.server.common.data.CoapDeviceType; | |
31 | +import org.thingsboard.server.common.data.DeviceProfileProvisionType; | |
32 | +import org.thingsboard.server.common.data.TransportPayloadType; | |
33 | +import org.thingsboard.server.common.data.device.profile.CoapDeviceProfileTransportConfiguration; | |
34 | +import org.thingsboard.server.common.data.device.profile.CoapDeviceTypeConfiguration; | |
35 | +import org.thingsboard.server.common.data.device.profile.DefaultCoapDeviceTypeConfiguration; | |
36 | +import org.thingsboard.server.common.data.device.profile.DeviceProfileTransportConfiguration; | |
37 | +import org.thingsboard.server.common.data.device.profile.ProtoTransportPayloadConfiguration; | |
38 | +import org.thingsboard.server.common.data.device.profile.TransportPayloadTypeConfiguration; | |
39 | +import org.thingsboard.server.common.msg.session.FeatureType; | |
40 | +import org.thingsboard.server.gen.transport.TransportProtos; | |
41 | + | |
42 | +import java.util.List; | |
43 | +import java.util.stream.Collectors; | |
44 | + | |
45 | +import static org.junit.Assert.assertEquals; | |
46 | +import static org.junit.Assert.assertNotNull; | |
47 | +import static org.junit.Assert.assertTrue; | |
48 | +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; | |
49 | + | |
50 | +@Slf4j | |
51 | +public abstract class AbstractCoapAttributesRequestProtoIntegrationTest extends AbstractCoapAttributesRequestIntegrationTest { | |
52 | + | |
53 | + public static final String ATTRIBUTES_SCHEMA_STR = "syntax =\"proto3\";\n" + | |
54 | + "\n" + | |
55 | + "package test;\n" + | |
56 | + "\n" + | |
57 | + "message PostAttributes {\n" + | |
58 | + " string attribute1 = 1;\n" + | |
59 | + " bool attribute2 = 2;\n" + | |
60 | + " double attribute3 = 3;\n" + | |
61 | + " int32 attribute4 = 4;\n" + | |
62 | + " JsonObject attribute5 = 5;\n" + | |
63 | + "\n" + | |
64 | + " message JsonObject {\n" + | |
65 | + " int32 someNumber = 6;\n" + | |
66 | + " repeated int32 someArray = 7;\n" + | |
67 | + " NestedJsonObject someNestedObject = 8;\n" + | |
68 | + " message NestedJsonObject {\n" + | |
69 | + " string key = 9;\n" + | |
70 | + " }\n" + | |
71 | + " }\n" + | |
72 | + "}"; | |
73 | + | |
74 | + @After | |
75 | + public void afterTest() throws Exception { | |
76 | + processAfterTest(); | |
77 | + } | |
78 | + | |
79 | + @Test | |
80 | + public void testRequestAttributesValuesFromTheServer() throws Exception { | |
81 | + super.processBeforeTest("Test Request attribute values from the server proto", CoapDeviceType.DEFAULT, | |
82 | + TransportPayloadType.PROTOBUF, null, ATTRIBUTES_SCHEMA_STR, DeviceProfileProvisionType.DISABLED, null, null); | |
83 | + processTestRequestAttributesValuesFromTheServer(); | |
84 | + } | |
85 | + | |
86 | + protected void postAttributes() throws Exception { | |
87 | + doPostAsync("/api/plugins/telemetry/DEVICE/" + savedDevice.getId().getId() + "/attributes/SHARED_SCOPE", POST_ATTRIBUTES_PAYLOAD, String.class, status().isOk()); | |
88 | + DeviceProfileTransportConfiguration transportConfiguration = deviceProfile.getProfileData().getTransportConfiguration(); | |
89 | + assertTrue(transportConfiguration instanceof CoapDeviceProfileTransportConfiguration); | |
90 | + CoapDeviceProfileTransportConfiguration coapTransportConfiguration = (CoapDeviceProfileTransportConfiguration) transportConfiguration; | |
91 | + CoapDeviceTypeConfiguration coapDeviceTypeConfiguration = coapTransportConfiguration.getCoapDeviceTypeConfiguration(); | |
92 | + assertTrue(coapDeviceTypeConfiguration instanceof DefaultCoapDeviceTypeConfiguration); | |
93 | + DefaultCoapDeviceTypeConfiguration defaultCoapDeviceTypeConfiguration = (DefaultCoapDeviceTypeConfiguration) coapDeviceTypeConfiguration; | |
94 | + TransportPayloadTypeConfiguration transportPayloadTypeConfiguration = defaultCoapDeviceTypeConfiguration.getTransportPayloadTypeConfiguration(); | |
95 | + assertTrue(transportPayloadTypeConfiguration instanceof ProtoTransportPayloadConfiguration); | |
96 | + ProtoTransportPayloadConfiguration protoTransportPayloadConfiguration = (ProtoTransportPayloadConfiguration) transportPayloadTypeConfiguration; | |
97 | + ProtoFileElement transportProtoSchema = protoTransportPayloadConfiguration.getTransportProtoSchema(ATTRIBUTES_SCHEMA_STR); | |
98 | + DynamicSchema attributesSchema = protoTransportPayloadConfiguration.getDynamicSchema(transportProtoSchema, ProtoTransportPayloadConfiguration.ATTRIBUTES_PROTO_SCHEMA); | |
99 | + | |
100 | + DynamicMessage.Builder nestedJsonObjectBuilder = attributesSchema.newMessageBuilder("PostAttributes.JsonObject.NestedJsonObject"); | |
101 | + Descriptors.Descriptor nestedJsonObjectBuilderDescriptor = nestedJsonObjectBuilder.getDescriptorForType(); | |
102 | + assertNotNull(nestedJsonObjectBuilderDescriptor); | |
103 | + DynamicMessage nestedJsonObject = nestedJsonObjectBuilder.setField(nestedJsonObjectBuilderDescriptor.findFieldByName("key"), "value").build(); | |
104 | + | |
105 | + DynamicMessage.Builder jsonObjectBuilder = attributesSchema.newMessageBuilder("PostAttributes.JsonObject"); | |
106 | + Descriptors.Descriptor jsonObjectBuilderDescriptor = jsonObjectBuilder.getDescriptorForType(); | |
107 | + assertNotNull(jsonObjectBuilderDescriptor); | |
108 | + DynamicMessage jsonObject = jsonObjectBuilder | |
109 | + .setField(jsonObjectBuilderDescriptor.findFieldByName("someNumber"), 42) | |
110 | + .addRepeatedField(jsonObjectBuilderDescriptor.findFieldByName("someArray"), 1) | |
111 | + .addRepeatedField(jsonObjectBuilderDescriptor.findFieldByName("someArray"), 2) | |
112 | + .addRepeatedField(jsonObjectBuilderDescriptor.findFieldByName("someArray"), 3) | |
113 | + .setField(jsonObjectBuilderDescriptor.findFieldByName("someNestedObject"), nestedJsonObject) | |
114 | + .build(); | |
115 | + | |
116 | + DynamicMessage.Builder postAttributesBuilder = attributesSchema.newMessageBuilder("PostAttributes"); | |
117 | + Descriptors.Descriptor postAttributesMsgDescriptor = postAttributesBuilder.getDescriptorForType(); | |
118 | + assertNotNull(postAttributesMsgDescriptor); | |
119 | + DynamicMessage postAttributesMsg = postAttributesBuilder | |
120 | + .setField(postAttributesMsgDescriptor.findFieldByName("attribute1"), "value1") | |
121 | + .setField(postAttributesMsgDescriptor.findFieldByName("attribute2"), true) | |
122 | + .setField(postAttributesMsgDescriptor.findFieldByName("attribute3"), 42.0) | |
123 | + .setField(postAttributesMsgDescriptor.findFieldByName("attribute4"), 73) | |
124 | + .setField(postAttributesMsgDescriptor.findFieldByName("attribute5"), jsonObject) | |
125 | + .build(); | |
126 | + byte[] payload = postAttributesMsg.toByteArray(); | |
127 | + CoapClient client = getCoapClient(FeatureType.ATTRIBUTES); | |
128 | + CoapResponse coapResponse = client.setTimeout(CLIENT_REQUEST_TIMEOUT).post(payload, MediaTypeRegistry.APPLICATION_JSON); | |
129 | + assertEquals(CoAP.ResponseCode.CREATED, coapResponse.getCode()); | |
130 | + } | |
131 | + | |
132 | + protected void validateResponse(CoapResponse getAttributesResponse) throws InvalidProtocolBufferException { | |
133 | + TransportProtos.GetAttributeResponseMsg expectedAttributesResponse = getExpectedAttributeResponseMsg(); | |
134 | + TransportProtos.GetAttributeResponseMsg actualAttributesResponse = TransportProtos.GetAttributeResponseMsg.parseFrom(getAttributesResponse.getPayload()); | |
135 | + assertEquals(expectedAttributesResponse.getRequestId(), actualAttributesResponse.getRequestId()); | |
136 | + List<TransportProtos.KeyValueProto> expectedClientKeyValueProtos = expectedAttributesResponse.getClientAttributeListList().stream().map(TransportProtos.TsKvProto::getKv).collect(Collectors.toList()); | |
137 | + List<TransportProtos.KeyValueProto> expectedSharedKeyValueProtos = expectedAttributesResponse.getSharedAttributeListList().stream().map(TransportProtos.TsKvProto::getKv).collect(Collectors.toList()); | |
138 | + List<TransportProtos.KeyValueProto> actualClientKeyValueProtos = actualAttributesResponse.getClientAttributeListList().stream().map(TransportProtos.TsKvProto::getKv).collect(Collectors.toList()); | |
139 | + List<TransportProtos.KeyValueProto> actualSharedKeyValueProtos = actualAttributesResponse.getSharedAttributeListList().stream().map(TransportProtos.TsKvProto::getKv).collect(Collectors.toList()); | |
140 | + assertTrue(actualClientKeyValueProtos.containsAll(expectedClientKeyValueProtos)); | |
141 | + assertTrue(actualSharedKeyValueProtos.containsAll(expectedSharedKeyValueProtos)); | |
142 | + } | |
143 | + | |
144 | + private TransportProtos.GetAttributeResponseMsg getExpectedAttributeResponseMsg() { | |
145 | + TransportProtos.GetAttributeResponseMsg.Builder result = TransportProtos.GetAttributeResponseMsg.newBuilder(); | |
146 | + List<TransportProtos.TsKvProto> tsKvProtoList = getTsKvProtoList(); | |
147 | + result.addAllClientAttributeList(tsKvProtoList); | |
148 | + result.addAllSharedAttributeList(tsKvProtoList); | |
149 | + result.setRequestId(0); | |
150 | + return result.build(); | |
151 | + } | |
152 | + | |
153 | +} | ... | ... |
1 | +/** | |
2 | + * Copyright © 2016-2021 The Thingsboard Authors | |
3 | + * | |
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | |
5 | + * you may not use this file except in compliance with the License. | |
6 | + * You may obtain a copy of the License at | |
7 | + * | |
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | |
9 | + * | |
10 | + * Unless required by applicable law or agreed to in writing, software | |
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | |
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 | + * See the License for the specific language governing permissions and | |
14 | + * limitations under the License. | |
15 | + */ | |
16 | +package org.thingsboard.server.transport.coap.attributes.request.sql; | |
17 | + | |
18 | +import org.thingsboard.server.transport.coap.attributes.request.AbstractCoapAttributesRequestJsonIntegrationTest; | |
19 | +import org.thingsboard.server.dao.service.DaoSqlTest; | |
20 | + | |
21 | +@DaoSqlTest | |
22 | +public class CoapAttributesRequestJsonSqlIntegrationTest extends AbstractCoapAttributesRequestJsonIntegrationTest { | |
23 | +} | ... | ... |
1 | +/** | |
2 | + * Copyright © 2016-2021 The Thingsboard Authors | |
3 | + * | |
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | |
5 | + * you may not use this file except in compliance with the License. | |
6 | + * You may obtain a copy of the License at | |
7 | + * | |
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | |
9 | + * | |
10 | + * Unless required by applicable law or agreed to in writing, software | |
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | |
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 | + * See the License for the specific language governing permissions and | |
14 | + * limitations under the License. | |
15 | + */ | |
16 | +package org.thingsboard.server.transport.coap.attributes.request.sql; | |
17 | + | |
18 | +import org.thingsboard.server.transport.coap.attributes.request.AbstractCoapAttributesRequestProtoIntegrationTest; | |
19 | +import org.thingsboard.server.dao.service.DaoSqlTest; | |
20 | + | |
21 | +@DaoSqlTest | |
22 | +public class CoapAttributesRequestProtoSqlIntegrationTest extends AbstractCoapAttributesRequestProtoIntegrationTest { | |
23 | +} | ... | ... |
application/src/test/java/org/thingsboard/server/transport/coap/attributes/request/sql/CoapAttributesRequestSqlIntegrationTest.java
renamed from
application/src/test/java/org/thingsboard/server/mqtt/telemetry/attributes/nosql/MqttAttributesNoSqlProtoIntegrationTest.java
... | ... | @@ -13,11 +13,11 @@ |
13 | 13 | * See the License for the specific language governing permissions and |
14 | 14 | * limitations under the License. |
15 | 15 | */ |
16 | -package org.thingsboard.server.mqtt.telemetry.attributes.nosql; | |
16 | +package org.thingsboard.server.transport.coap.attributes.request.sql; | |
17 | 17 | |
18 | -import org.thingsboard.server.dao.service.DaoNoSqlTest; | |
19 | -import org.thingsboard.server.mqtt.telemetry.attributes.AbstractMqttAttributesProtoIntegrationTest; | |
18 | +import org.thingsboard.server.transport.coap.attributes.request.AbstractCoapAttributesRequestIntegrationTest; | |
19 | +import org.thingsboard.server.dao.service.DaoSqlTest; | |
20 | 20 | |
21 | -@DaoNoSqlTest | |
22 | -public class MqttAttributesNoSqlProtoIntegrationTest extends AbstractMqttAttributesProtoIntegrationTest { | |
21 | +@DaoSqlTest | |
22 | +public class CoapAttributesRequestSqlIntegrationTest extends AbstractCoapAttributesRequestIntegrationTest { | |
23 | 23 | } | ... | ... |
1 | +/** | |
2 | + * Copyright © 2016-2021 The Thingsboard Authors | |
3 | + * | |
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | |
5 | + * you may not use this file except in compliance with the License. | |
6 | + * You may obtain a copy of the License at | |
7 | + * | |
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | |
9 | + * | |
10 | + * Unless required by applicable law or agreed to in writing, software | |
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | |
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 | + * See the License for the specific language governing permissions and | |
14 | + * limitations under the License. | |
15 | + */ | |
16 | +package org.thingsboard.server.transport.coap.attributes.updates; | |
17 | + | |
18 | +import com.google.protobuf.InvalidProtocolBufferException; | |
19 | +import lombok.extern.slf4j.Slf4j; | |
20 | +import org.eclipse.californium.core.CoapClient; | |
21 | +import org.eclipse.californium.core.CoapHandler; | |
22 | +import org.eclipse.californium.core.CoapObserveRelation; | |
23 | +import org.eclipse.californium.core.CoapResponse; | |
24 | +import org.eclipse.californium.core.coap.CoAP; | |
25 | +import org.eclipse.californium.core.coap.Request; | |
26 | +import org.junit.After; | |
27 | +import org.junit.Before; | |
28 | +import org.junit.Test; | |
29 | +import org.thingsboard.server.transport.coap.attributes.AbstractCoapAttributesIntegrationTest; | |
30 | +import org.thingsboard.server.common.msg.session.FeatureType; | |
31 | +import org.thingsboard.server.dao.util.mapping.JacksonUtil; | |
32 | + | |
33 | +import java.nio.charset.StandardCharsets; | |
34 | +import java.util.concurrent.CountDownLatch; | |
35 | +import java.util.concurrent.TimeUnit; | |
36 | + | |
37 | +import static org.junit.Assert.assertEquals; | |
38 | +import static org.junit.Assert.assertNotNull; | |
39 | +import static org.junit.Assert.assertTrue; | |
40 | +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; | |
41 | + | |
42 | +@Slf4j | |
43 | +public abstract class AbstractCoapAttributesUpdatesIntegrationTest extends AbstractCoapAttributesIntegrationTest { | |
44 | + | |
45 | + private static final String RESPONSE_ATTRIBUTES_PAYLOAD_DELETED = "{\"deleted\":[\"attribute5\"]}"; | |
46 | + | |
47 | + @Before | |
48 | + public void beforeTest() throws Exception { | |
49 | + processBeforeTest("Test Subscribe to attribute updates", null, null); | |
50 | + } | |
51 | + | |
52 | + @After | |
53 | + public void afterTest() throws Exception { | |
54 | + processAfterTest(); | |
55 | + } | |
56 | + | |
57 | + @Test | |
58 | + public void testSubscribeToAttributesUpdatesFromTheServer() throws Exception { | |
59 | + processTestSubscribeToAttributesUpdates(); | |
60 | + } | |
61 | + | |
62 | + protected void processTestSubscribeToAttributesUpdates() throws Exception { | |
63 | + | |
64 | + CoapClient client = getCoapClient(FeatureType.ATTRIBUTES); | |
65 | + | |
66 | + CountDownLatch latch = new CountDownLatch(1); | |
67 | + TestCoapCallback testCoapCallback = new TestCoapCallback(latch); | |
68 | + | |
69 | + Request request = Request.newGet().setObserve(); | |
70 | + request.setType(CoAP.Type.CON); | |
71 | + CoapObserveRelation observeRelation = client.observe(request, testCoapCallback); | |
72 | + | |
73 | + Thread.sleep(1000); | |
74 | + | |
75 | + doPostAsync("/api/plugins/telemetry/DEVICE/" + savedDevice.getId().getId() + "/attributes/SHARED_SCOPE", POST_ATTRIBUTES_PAYLOAD, String.class, status().isOk()); | |
76 | + latch.await(3, TimeUnit.SECONDS); | |
77 | + | |
78 | + validateUpdateAttributesResponse(testCoapCallback); | |
79 | + | |
80 | + latch = new CountDownLatch(1); | |
81 | + | |
82 | + doDelete("/api/plugins/telemetry/DEVICE/" + savedDevice.getId().getId() + "/SHARED_SCOPE?keys=attribute5", String.class); | |
83 | + latch.await(3, TimeUnit.SECONDS); | |
84 | + | |
85 | + validateDeleteAttributesResponse(testCoapCallback); | |
86 | + | |
87 | + observeRelation.proactiveCancel(); | |
88 | + assertTrue(observeRelation.isCanceled()); | |
89 | + } | |
90 | + | |
91 | + protected void validateUpdateAttributesResponse(TestCoapCallback callback) throws InvalidProtocolBufferException { | |
92 | + assertNotNull(callback.getPayloadBytes()); | |
93 | + assertNotNull(callback.getObserve()); | |
94 | + assertEquals(0, callback.getObserve().intValue()); | |
95 | + String response = new String(callback.getPayloadBytes(), StandardCharsets.UTF_8); | |
96 | + assertEquals(JacksonUtil.toJsonNode(POST_ATTRIBUTES_PAYLOAD), JacksonUtil.toJsonNode(response)); | |
97 | + } | |
98 | + | |
99 | + protected void validateDeleteAttributesResponse(TestCoapCallback callback) throws InvalidProtocolBufferException { | |
100 | + assertNotNull(callback.getPayloadBytes()); | |
101 | + assertNotNull(callback.getObserve()); | |
102 | + assertEquals(1, callback.getObserve().intValue()); | |
103 | + String response = new String(callback.getPayloadBytes(), StandardCharsets.UTF_8); | |
104 | + assertEquals(JacksonUtil.toJsonNode(RESPONSE_ATTRIBUTES_PAYLOAD_DELETED), JacksonUtil.toJsonNode(response)); | |
105 | + } | |
106 | + | |
107 | + protected static class TestCoapCallback implements CoapHandler { | |
108 | + | |
109 | + private final CountDownLatch latch; | |
110 | + | |
111 | + private Integer observe; | |
112 | + private byte[] payloadBytes; | |
113 | + | |
114 | + public byte[] getPayloadBytes() { | |
115 | + return payloadBytes; | |
116 | + } | |
117 | + | |
118 | + public Integer getObserve() { | |
119 | + return observe; | |
120 | + } | |
121 | + | |
122 | + private TestCoapCallback(CountDownLatch latch) { | |
123 | + this.latch = latch; | |
124 | + } | |
125 | + | |
126 | + @Override | |
127 | + public void onLoad(CoapResponse response) { | |
128 | + assertNotNull(response.getPayload()); | |
129 | + assertEquals(response.getCode(), CoAP.ResponseCode.CONTENT); | |
130 | + observe = response.getOptions().getObserve(); | |
131 | + payloadBytes = response.getPayload(); | |
132 | + latch.countDown(); | |
133 | + } | |
134 | + | |
135 | + @Override | |
136 | + public void onError() { | |
137 | + log.warn("Command Response Ack Error, No connect"); | |
138 | + } | |
139 | + | |
140 | + } | |
141 | +} | ... | ... |
1 | +/** | |
2 | + * Copyright © 2016-2021 The Thingsboard Authors | |
3 | + * | |
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | |
5 | + * you may not use this file except in compliance with the License. | |
6 | + * You may obtain a copy of the License at | |
7 | + * | |
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | |
9 | + * | |
10 | + * Unless required by applicable law or agreed to in writing, software | |
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | |
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 | + * See the License for the specific language governing permissions and | |
14 | + * limitations under the License. | |
15 | + */ | |
16 | +package org.thingsboard.server.transport.coap.attributes.updates; | |
17 | + | |
18 | +import lombok.extern.slf4j.Slf4j; | |
19 | +import org.junit.After; | |
20 | +import org.junit.Before; | |
21 | +import org.junit.Test; | |
22 | +import org.thingsboard.server.common.data.CoapDeviceType; | |
23 | +import org.thingsboard.server.common.data.TransportPayloadType; | |
24 | + | |
25 | +@Slf4j | |
26 | +public abstract class AbstractCoapAttributesUpdatesJsonIntegrationTest extends AbstractCoapAttributesUpdatesIntegrationTest { | |
27 | + | |
28 | + @Before | |
29 | + public void beforeTest() throws Exception { | |
30 | + processBeforeTest("Test Subscribe to attribute updates", CoapDeviceType.DEFAULT, TransportPayloadType.JSON); | |
31 | + } | |
32 | + | |
33 | + @After | |
34 | + public void afterTest() throws Exception { | |
35 | + processAfterTest(); | |
36 | + } | |
37 | + | |
38 | + @Test | |
39 | + public void testSubscribeToAttributesUpdatesFromTheServer() throws Exception { | |
40 | + super.testSubscribeToAttributesUpdatesFromTheServer(); | |
41 | + } | |
42 | +} | ... | ... |
1 | +/** | |
2 | + * Copyright © 2016-2021 The Thingsboard Authors | |
3 | + * | |
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | |
5 | + * you may not use this file except in compliance with the License. | |
6 | + * You may obtain a copy of the License at | |
7 | + * | |
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | |
9 | + * | |
10 | + * Unless required by applicable law or agreed to in writing, software | |
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | |
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 | + * See the License for the specific language governing permissions and | |
14 | + * limitations under the License. | |
15 | + */ | |
16 | +package org.thingsboard.server.transport.coap.attributes.updates; | |
17 | + | |
18 | +import com.google.protobuf.InvalidProtocolBufferException; | |
19 | +import lombok.extern.slf4j.Slf4j; | |
20 | +import org.junit.After; | |
21 | +import org.junit.Before; | |
22 | +import org.junit.Test; | |
23 | +import org.thingsboard.server.common.data.CoapDeviceType; | |
24 | +import org.thingsboard.server.common.data.TransportPayloadType; | |
25 | +import org.thingsboard.server.gen.transport.TransportProtos; | |
26 | + | |
27 | +import java.util.List; | |
28 | +import java.util.stream.Collectors; | |
29 | + | |
30 | +import static org.junit.Assert.assertEquals; | |
31 | +import static org.junit.Assert.assertNotNull; | |
32 | +import static org.junit.Assert.assertTrue; | |
33 | + | |
34 | +@Slf4j | |
35 | +public abstract class AbstractCoapAttributesUpdatesProtoIntegrationTest extends AbstractCoapAttributesUpdatesIntegrationTest { | |
36 | + | |
37 | + @Before | |
38 | + public void beforeTest() throws Exception { | |
39 | + processBeforeTest("Test Subscribe to attribute updates", CoapDeviceType.DEFAULT, TransportPayloadType.PROTOBUF); | |
40 | + } | |
41 | + | |
42 | + @After | |
43 | + public void afterTest() throws Exception { | |
44 | + processAfterTest(); | |
45 | + } | |
46 | + | |
47 | + @Test | |
48 | + public void testSubscribeToAttributesUpdatesFromTheServer() throws Exception { | |
49 | + processTestSubscribeToAttributesUpdates(); | |
50 | + } | |
51 | + | |
52 | + protected void validateUpdateAttributesResponse(TestCoapCallback callback) throws InvalidProtocolBufferException { | |
53 | + assertNotNull(callback.getPayloadBytes()); | |
54 | + TransportProtos.AttributeUpdateNotificationMsg.Builder attributeUpdateNotificationMsgBuilder = TransportProtos.AttributeUpdateNotificationMsg.newBuilder(); | |
55 | + List<TransportProtos.TsKvProto> tsKvProtoList = getTsKvProtoList(); | |
56 | + attributeUpdateNotificationMsgBuilder.addAllSharedUpdated(tsKvProtoList); | |
57 | + | |
58 | + TransportProtos.AttributeUpdateNotificationMsg expectedAttributeUpdateNotificationMsg = attributeUpdateNotificationMsgBuilder.build(); | |
59 | + TransportProtos.AttributeUpdateNotificationMsg actualAttributeUpdateNotificationMsg = TransportProtos.AttributeUpdateNotificationMsg.parseFrom(callback.getPayloadBytes()); | |
60 | + | |
61 | + List<TransportProtos.KeyValueProto> actualSharedUpdatedList = actualAttributeUpdateNotificationMsg.getSharedUpdatedList().stream().map(TransportProtos.TsKvProto::getKv).collect(Collectors.toList()); | |
62 | + List<TransportProtos.KeyValueProto> expectedSharedUpdatedList = expectedAttributeUpdateNotificationMsg.getSharedUpdatedList().stream().map(TransportProtos.TsKvProto::getKv).collect(Collectors.toList()); | |
63 | + | |
64 | + assertEquals(expectedSharedUpdatedList.size(), actualSharedUpdatedList.size()); | |
65 | + assertTrue(actualSharedUpdatedList.containsAll(expectedSharedUpdatedList)); | |
66 | + | |
67 | + } | |
68 | + | |
69 | + protected void validateDeleteAttributesResponse(TestCoapCallback callback) throws InvalidProtocolBufferException { | |
70 | + assertNotNull(callback.getPayloadBytes()); | |
71 | + TransportProtos.AttributeUpdateNotificationMsg.Builder attributeUpdateNotificationMsgBuilder = TransportProtos.AttributeUpdateNotificationMsg.newBuilder(); | |
72 | + attributeUpdateNotificationMsgBuilder.addSharedDeleted("attribute5"); | |
73 | + | |
74 | + TransportProtos.AttributeUpdateNotificationMsg expectedAttributeUpdateNotificationMsg = attributeUpdateNotificationMsgBuilder.build(); | |
75 | + TransportProtos.AttributeUpdateNotificationMsg actualAttributeUpdateNotificationMsg = TransportProtos.AttributeUpdateNotificationMsg.parseFrom(callback.getPayloadBytes()); | |
76 | + | |
77 | + assertEquals(expectedAttributeUpdateNotificationMsg.getSharedDeletedList().size(), actualAttributeUpdateNotificationMsg.getSharedDeletedList().size()); | |
78 | + assertEquals("attribute5", actualAttributeUpdateNotificationMsg.getSharedDeletedList().get(0)); | |
79 | + | |
80 | + } | |
81 | + | |
82 | +} | ... | ... |
1 | +/** | |
2 | + * Copyright © 2016-2021 The Thingsboard Authors | |
3 | + * | |
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | |
5 | + * you may not use this file except in compliance with the License. | |
6 | + * You may obtain a copy of the License at | |
7 | + * | |
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | |
9 | + * | |
10 | + * Unless required by applicable law or agreed to in writing, software | |
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | |
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 | + * See the License for the specific language governing permissions and | |
14 | + * limitations under the License. | |
15 | + */ | |
16 | +package org.thingsboard.server.transport.coap.attributes.updates.sql; | |
17 | + | |
18 | +import org.thingsboard.server.transport.coap.attributes.updates.AbstractCoapAttributesUpdatesIntegrationTest; | |
19 | +import org.thingsboard.server.dao.service.DaoSqlTest; | |
20 | + | |
21 | +@DaoSqlTest | |
22 | +public class CoapAttributesUpdatesSqlIntegrationTest extends AbstractCoapAttributesUpdatesIntegrationTest { | |
23 | +} | ... | ... |
1 | +/** | |
2 | + * Copyright © 2016-2021 The Thingsboard Authors | |
3 | + * | |
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | |
5 | + * you may not use this file except in compliance with the License. | |
6 | + * You may obtain a copy of the License at | |
7 | + * | |
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | |
9 | + * | |
10 | + * Unless required by applicable law or agreed to in writing, software | |
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | |
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 | + * See the License for the specific language governing permissions and | |
14 | + * limitations under the License. | |
15 | + */ | |
16 | +package org.thingsboard.server.transport.coap.attributes.updates.sql; | |
17 | + | |
18 | +import org.thingsboard.server.transport.coap.attributes.updates.AbstractCoapAttributesUpdatesJsonIntegrationTest; | |
19 | +import org.thingsboard.server.dao.service.DaoSqlTest; | |
20 | + | |
21 | +@DaoSqlTest | |
22 | +public class CoapAttributesUpdatesSqlJsonIntegrationTest extends AbstractCoapAttributesUpdatesJsonIntegrationTest { | |
23 | +} | ... | ... |
1 | +/** | |
2 | + * Copyright © 2016-2021 The Thingsboard Authors | |
3 | + * | |
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | |
5 | + * you may not use this file except in compliance with the License. | |
6 | + * You may obtain a copy of the License at | |
7 | + * | |
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | |
9 | + * | |
10 | + * Unless required by applicable law or agreed to in writing, software | |
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | |
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 | + * See the License for the specific language governing permissions and | |
14 | + * limitations under the License. | |
15 | + */ | |
16 | +package org.thingsboard.server.transport.coap.attributes.updates.sql; | |
17 | + | |
18 | +import org.thingsboard.server.transport.coap.attributes.updates.AbstractCoapAttributesUpdatesProtoIntegrationTest; | |
19 | +import org.thingsboard.server.dao.service.DaoSqlTest; | |
20 | + | |
21 | +@DaoSqlTest | |
22 | +public class CoapAttributesUpdatesSqlProtoIntegrationTest extends AbstractCoapAttributesUpdatesProtoIntegrationTest { | |
23 | +} | ... | ... |
1 | +/** | |
2 | + * Copyright © 2016-2021 The Thingsboard Authors | |
3 | + * | |
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | |
5 | + * you may not use this file except in compliance with the License. | |
6 | + * You may obtain a copy of the License at | |
7 | + * | |
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | |
9 | + * | |
10 | + * Unless required by applicable law or agreed to in writing, software | |
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | |
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 | + * See the License for the specific language governing permissions and | |
14 | + * limitations under the License. | |
15 | + */ | |
16 | +package org.thingsboard.server.transport.coap.claim; | |
17 | + | |
18 | +import lombok.extern.slf4j.Slf4j; | |
19 | +import org.eclipse.californium.core.CoapClient; | |
20 | +import org.eclipse.californium.core.CoapResponse; | |
21 | +import org.eclipse.californium.core.coap.CoAP; | |
22 | +import org.eclipse.californium.core.coap.MediaTypeRegistry; | |
23 | +import org.eclipse.californium.elements.exception.ConnectorException; | |
24 | +import org.junit.After; | |
25 | +import org.junit.Before; | |
26 | +import org.junit.Test; | |
27 | +import org.thingsboard.server.transport.coap.AbstractCoapIntegrationTest; | |
28 | +import org.thingsboard.server.common.data.ClaimRequest; | |
29 | +import org.thingsboard.server.common.data.Customer; | |
30 | +import org.thingsboard.server.common.data.Device; | |
31 | +import org.thingsboard.server.common.data.User; | |
32 | +import org.thingsboard.server.common.data.security.Authority; | |
33 | +import org.thingsboard.server.common.msg.session.FeatureType; | |
34 | +import org.thingsboard.server.dao.device.claim.ClaimResponse; | |
35 | +import org.thingsboard.server.dao.device.claim.ClaimResult; | |
36 | + | |
37 | +import java.io.IOException; | |
38 | + | |
39 | +import static org.junit.Assert.assertEquals; | |
40 | +import static org.junit.Assert.assertNotNull; | |
41 | +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; | |
42 | + | |
43 | +@Slf4j | |
44 | +public abstract class AbstractCoapClaimDeviceTest extends AbstractCoapIntegrationTest { | |
45 | + | |
46 | + protected static final String CUSTOMER_USER_PASSWORD = "customerUser123!"; | |
47 | + | |
48 | + protected User customerAdmin; | |
49 | + protected Customer savedCustomer; | |
50 | + | |
51 | + @Before | |
52 | + public void beforeTest() throws Exception { | |
53 | + super.processBeforeTest("Test Claim device", null, null); | |
54 | + createCustomerAndUser(); | |
55 | + } | |
56 | + | |
57 | + protected void createCustomerAndUser() throws Exception { | |
58 | + Customer customer = new Customer(); | |
59 | + customer.setTenantId(savedTenant.getId()); | |
60 | + customer.setTitle("Test Claiming Customer"); | |
61 | + savedCustomer = doPost("/api/customer", customer, Customer.class); | |
62 | + assertNotNull(savedCustomer); | |
63 | + assertEquals(savedTenant.getId(), savedCustomer.getTenantId()); | |
64 | + | |
65 | + User user = new User(); | |
66 | + user.setAuthority(Authority.CUSTOMER_USER); | |
67 | + user.setTenantId(savedTenant.getId()); | |
68 | + user.setCustomerId(savedCustomer.getId()); | |
69 | + user.setEmail("customer@thingsboard.org"); | |
70 | + | |
71 | + customerAdmin = createUser(user, CUSTOMER_USER_PASSWORD); | |
72 | + assertNotNull(customerAdmin); | |
73 | + assertEquals(customerAdmin.getCustomerId(), savedCustomer.getId()); | |
74 | + } | |
75 | + | |
76 | + @After | |
77 | + public void afterTest() throws Exception { | |
78 | + super.processAfterTest(); | |
79 | + } | |
80 | + | |
81 | + @Test | |
82 | + public void testClaimingDevice() throws Exception { | |
83 | + processTestClaimingDevice(false); | |
84 | + } | |
85 | + | |
86 | + @Test | |
87 | + public void testClaimingDeviceWithoutSecretAndDuration() throws Exception { | |
88 | + processTestClaimingDevice(true); | |
89 | + } | |
90 | + | |
91 | + protected void processTestClaimingDevice(boolean emptyPayload) throws Exception { | |
92 | + log.warn("[testClaimingDevice] Device: {}, Transport type: {}", savedDevice.getName(), savedDevice.getType()); | |
93 | + CoapClient client = getCoapClient(FeatureType.CLAIM); | |
94 | + byte[] payloadBytes; | |
95 | + byte[] failurePayloadBytes; | |
96 | + if (emptyPayload) { | |
97 | + payloadBytes = "{}".getBytes(); | |
98 | + failurePayloadBytes = "{\"durationMs\":1}".getBytes(); | |
99 | + } else { | |
100 | + payloadBytes = "{\"secretKey\":\"value\", \"durationMs\":60000}".getBytes(); | |
101 | + failurePayloadBytes = "{\"secretKey\":\"value\", \"durationMs\":1}".getBytes(); | |
102 | + } | |
103 | + validateClaimResponse(emptyPayload, client, payloadBytes, failurePayloadBytes); | |
104 | + } | |
105 | + | |
106 | + protected void validateClaimResponse(boolean emptyPayload, CoapClient client, byte[] payloadBytes, byte[] failurePayloadBytes) throws Exception { | |
107 | + postClaimRequest(client, failurePayloadBytes); | |
108 | + | |
109 | + loginUser(customerAdmin.getName(), CUSTOMER_USER_PASSWORD); | |
110 | + ClaimRequest claimRequest; | |
111 | + if (!emptyPayload) { | |
112 | + claimRequest = new ClaimRequest("value"); | |
113 | + } else { | |
114 | + claimRequest = new ClaimRequest(null); | |
115 | + } | |
116 | + | |
117 | + ClaimResponse claimResponse = doExecuteWithRetriesAndInterval( | |
118 | + () -> doPostClaimAsync("/api/customer/device/" + savedDevice.getName() + "/claim", claimRequest, ClaimResponse.class, status().isBadRequest()), | |
119 | + 20, | |
120 | + 100 | |
121 | + ); | |
122 | + | |
123 | + assertEquals(claimResponse, ClaimResponse.FAILURE); | |
124 | + | |
125 | + postClaimRequest(client, payloadBytes); | |
126 | + | |
127 | + ClaimResult claimResult = doExecuteWithRetriesAndInterval( | |
128 | + () -> doPostClaimAsync("/api/customer/device/" + savedDevice.getName() + "/claim", claimRequest, ClaimResult.class, status().isOk()), | |
129 | + 20, | |
130 | + 100 | |
131 | + ); | |
132 | + assertEquals(claimResult.getResponse(), ClaimResponse.SUCCESS); | |
133 | + Device claimedDevice = claimResult.getDevice(); | |
134 | + assertNotNull(claimedDevice); | |
135 | + assertNotNull(claimedDevice.getCustomerId()); | |
136 | + assertEquals(customerAdmin.getCustomerId(), claimedDevice.getCustomerId()); | |
137 | + | |
138 | + claimResponse = doPostClaimAsync("/api/customer/device/" + savedDevice.getName() + "/claim", claimRequest, ClaimResponse.class, status().isBadRequest()); | |
139 | + assertEquals(claimResponse, ClaimResponse.CLAIMED); | |
140 | + } | |
141 | + | |
142 | + private void postClaimRequest(CoapClient client, byte[] payload) throws IOException, ConnectorException { | |
143 | + CoapResponse coapResponse = client.setTimeout((long) 60000).post(payload, MediaTypeRegistry.APPLICATION_JSON); | |
144 | + assertEquals(CoAP.ResponseCode.CREATED, coapResponse.getCode()); | |
145 | + } | |
146 | + | |
147 | +} | ... | ... |
1 | +/** | |
2 | + * Copyright © 2016-2021 The Thingsboard Authors | |
3 | + * | |
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | |
5 | + * you may not use this file except in compliance with the License. | |
6 | + * You may obtain a copy of the License at | |
7 | + * | |
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | |
9 | + * | |
10 | + * Unless required by applicable law or agreed to in writing, software | |
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | |
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 | + * See the License for the specific language governing permissions and | |
14 | + * limitations under the License. | |
15 | + */ | |
16 | +package org.thingsboard.server.transport.coap.claim; | |
17 | + | |
18 | +import lombok.extern.slf4j.Slf4j; | |
19 | +import org.junit.After; | |
20 | +import org.junit.Before; | |
21 | +import org.junit.Test; | |
22 | +import org.thingsboard.server.common.data.CoapDeviceType; | |
23 | +import org.thingsboard.server.common.data.TransportPayloadType; | |
24 | + | |
25 | +@Slf4j | |
26 | +public abstract class AbstractCoapClaimJsonDeviceTest extends AbstractCoapClaimDeviceTest { | |
27 | + | |
28 | + @Before | |
29 | + public void beforeTest() throws Exception { | |
30 | + super.processBeforeTest("Test Claim device Json", CoapDeviceType.DEFAULT, TransportPayloadType.JSON); | |
31 | + createCustomerAndUser(); | |
32 | + } | |
33 | + | |
34 | + @After | |
35 | + public void afterTest() throws Exception { | |
36 | + super.afterTest(); | |
37 | + } | |
38 | + | |
39 | + @Test | |
40 | + public void testClaimingDevice() throws Exception { | |
41 | + super.testClaimingDevice(); | |
42 | + } | |
43 | + | |
44 | + @Test | |
45 | + public void testClaimingDeviceWithoutSecretAndDuration() throws Exception { | |
46 | + super.testClaimingDeviceWithoutSecretAndDuration(); | |
47 | + } | |
48 | +} | ... | ... |
1 | +/** | |
2 | + * Copyright © 2016-2021 The Thingsboard Authors | |
3 | + * | |
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | |
5 | + * you may not use this file except in compliance with the License. | |
6 | + * You may obtain a copy of the License at | |
7 | + * | |
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | |
9 | + * | |
10 | + * Unless required by applicable law or agreed to in writing, software | |
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | |
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 | + * See the License for the specific language governing permissions and | |
14 | + * limitations under the License. | |
15 | + */ | |
16 | +package org.thingsboard.server.transport.coap.claim; | |
17 | + | |
18 | +import lombok.extern.slf4j.Slf4j; | |
19 | +import org.eclipse.californium.core.CoapClient; | |
20 | +import org.junit.After; | |
21 | +import org.junit.Before; | |
22 | +import org.junit.Test; | |
23 | +import org.thingsboard.server.common.data.CoapDeviceType; | |
24 | +import org.thingsboard.server.common.data.TransportPayloadType; | |
25 | +import org.thingsboard.server.common.msg.session.FeatureType; | |
26 | +import org.thingsboard.server.gen.transport.TransportApiProtos; | |
27 | + | |
28 | +@Slf4j | |
29 | +public abstract class AbstractCoapClaimProtoDeviceTest extends AbstractCoapClaimDeviceTest { | |
30 | + | |
31 | + @Before | |
32 | + public void beforeTest() throws Exception { | |
33 | + processBeforeTest("Test Claim device Proto", CoapDeviceType.DEFAULT, TransportPayloadType.PROTOBUF); | |
34 | + createCustomerAndUser(); | |
35 | + } | |
36 | + | |
37 | + @After | |
38 | + public void afterTest() throws Exception { super.afterTest(); } | |
39 | + | |
40 | + @Test | |
41 | + public void testClaimingDevice() throws Exception { | |
42 | + processTestClaimingDevice(false); | |
43 | + } | |
44 | + | |
45 | + @Test | |
46 | + public void testClaimingDeviceWithoutSecretAndDuration() throws Exception { | |
47 | + processTestClaimingDevice(true); | |
48 | + } | |
49 | + | |
50 | + @Override | |
51 | + protected void processTestClaimingDevice(boolean emptyPayload) throws Exception { | |
52 | + CoapClient client = getCoapClient(FeatureType.CLAIM); | |
53 | + byte[] payloadBytes; | |
54 | + if (emptyPayload) { | |
55 | + TransportApiProtos.ClaimDevice claimDevice = getClaimDevice(0, emptyPayload); | |
56 | + payloadBytes = claimDevice.toByteArray(); | |
57 | + } else { | |
58 | + TransportApiProtos.ClaimDevice claimDevice = getClaimDevice(60000, emptyPayload); | |
59 | + payloadBytes = claimDevice.toByteArray(); | |
60 | + } | |
61 | + TransportApiProtos.ClaimDevice claimDevice = getClaimDevice(1, emptyPayload); | |
62 | + byte[] failurePayloadBytes = claimDevice.toByteArray(); | |
63 | + validateClaimResponse(emptyPayload, client, payloadBytes, failurePayloadBytes); | |
64 | + } | |
65 | + | |
66 | + private TransportApiProtos.ClaimDevice getClaimDevice(long duration, boolean emptyPayload) { | |
67 | + TransportApiProtos.ClaimDevice.Builder claimDeviceBuilder = TransportApiProtos.ClaimDevice.newBuilder(); | |
68 | + if (!emptyPayload) { | |
69 | + claimDeviceBuilder.setSecretKey("value"); | |
70 | + } | |
71 | + if (duration > 0) { | |
72 | + claimDeviceBuilder.setSecretKey("value"); | |
73 | + claimDeviceBuilder.setDurationMs(duration); | |
74 | + } else { | |
75 | + claimDeviceBuilder.setDurationMs(0); | |
76 | + } | |
77 | + return claimDeviceBuilder.build(); | |
78 | + } | |
79 | + | |
80 | + | |
81 | +} | ... | ... |
1 | +/** | |
2 | + * Copyright © 2016-2021 The Thingsboard Authors | |
3 | + * | |
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | |
5 | + * you may not use this file except in compliance with the License. | |
6 | + * You may obtain a copy of the License at | |
7 | + * | |
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | |
9 | + * | |
10 | + * Unless required by applicable law or agreed to in writing, software | |
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | |
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 | + * See the License for the specific language governing permissions and | |
14 | + * limitations under the License. | |
15 | + */ | |
16 | +package org.thingsboard.server.transport.coap.claim.sql; | |
17 | + | |
18 | +import org.thingsboard.server.transport.coap.claim.AbstractCoapClaimJsonDeviceTest; | |
19 | +import org.thingsboard.server.dao.service.DaoSqlTest; | |
20 | + | |
21 | +@DaoSqlTest | |
22 | +public class CoapClaimDeviceJsonSqlTest extends AbstractCoapClaimJsonDeviceTest { | |
23 | +} | ... | ... |
1 | +/** | |
2 | + * Copyright © 2016-2021 The Thingsboard Authors | |
3 | + * | |
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | |
5 | + * you may not use this file except in compliance with the License. | |
6 | + * You may obtain a copy of the License at | |
7 | + * | |
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | |
9 | + * | |
10 | + * Unless required by applicable law or agreed to in writing, software | |
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | |
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 | + * See the License for the specific language governing permissions and | |
14 | + * limitations under the License. | |
15 | + */ | |
16 | +package org.thingsboard.server.transport.coap.claim.sql; | |
17 | + | |
18 | +import org.thingsboard.server.transport.coap.claim.AbstractCoapClaimProtoDeviceTest; | |
19 | +import org.thingsboard.server.dao.service.DaoSqlTest; | |
20 | + | |
21 | +@DaoSqlTest | |
22 | +public class CoapClaimDeviceProtoSqlTest extends AbstractCoapClaimProtoDeviceTest { | |
23 | +} | ... | ... |
application/src/test/java/org/thingsboard/server/transport/coap/claim/sql/CoapClaimDeviceSqlTest.java
renamed from
application/src/test/java/org/thingsboard/server/mqtt/attributes/updates/nosql/MqttAttributesUpdatesNoSqlIntegrationTest.java
... | ... | @@ -13,12 +13,11 @@ |
13 | 13 | * See the License for the specific language governing permissions and |
14 | 14 | * limitations under the License. |
15 | 15 | */ |
16 | -package org.thingsboard.server.mqtt.attributes.updates.nosql; | |
16 | +package org.thingsboard.server.transport.coap.claim.sql; | |
17 | 17 | |
18 | -import org.thingsboard.server.dao.service.DaoNoSqlTest; | |
19 | -import org.thingsboard.server.mqtt.attributes.updates.AbstractMqttAttributesUpdatesJsonIntegrationTest; | |
18 | +import org.thingsboard.server.transport.coap.claim.AbstractCoapClaimDeviceTest; | |
19 | +import org.thingsboard.server.dao.service.DaoSqlTest; | |
20 | 20 | |
21 | - | |
22 | -@DaoNoSqlTest | |
23 | -public class MqttAttributesUpdatesNoSqlIntegrationTest extends AbstractMqttAttributesUpdatesJsonIntegrationTest { | |
21 | +@DaoSqlTest | |
22 | +public class CoapClaimDeviceSqlTest extends AbstractCoapClaimDeviceTest { | |
24 | 23 | } | ... | ... |
1 | +/** | |
2 | + * Copyright © 2016-2021 The Thingsboard Authors | |
3 | + * | |
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | |
5 | + * you may not use this file except in compliance with the License. | |
6 | + * You may obtain a copy of the License at | |
7 | + * | |
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | |
9 | + * | |
10 | + * Unless required by applicable law or agreed to in writing, software | |
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | |
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 | + * See the License for the specific language governing permissions and | |
14 | + * limitations under the License. | |
15 | + */ | |
16 | +package org.thingsboard.server.transport.coap.provision; | |
17 | + | |
18 | +import com.google.gson.JsonObject; | |
19 | +import lombok.extern.slf4j.Slf4j; | |
20 | +import org.eclipse.californium.core.CoapClient; | |
21 | +import org.eclipse.californium.core.CoapResponse; | |
22 | +import org.eclipse.californium.core.coap.MediaTypeRegistry; | |
23 | +import org.eclipse.californium.elements.exception.ConnectorException; | |
24 | +import org.junit.After; | |
25 | +import org.junit.Assert; | |
26 | +import org.junit.Test; | |
27 | +import org.springframework.beans.factory.annotation.Autowired; | |
28 | +import org.thingsboard.server.transport.coap.AbstractCoapIntegrationTest; | |
29 | +import org.thingsboard.server.common.data.CoapDeviceType; | |
30 | +import org.thingsboard.server.common.data.Device; | |
31 | +import org.thingsboard.server.common.data.DeviceProfileProvisionType; | |
32 | +import org.thingsboard.server.common.data.TransportPayloadType; | |
33 | +import org.thingsboard.server.common.data.security.DeviceCredentials; | |
34 | +import org.thingsboard.server.common.msg.EncryptionUtil; | |
35 | +import org.thingsboard.server.common.msg.session.FeatureType; | |
36 | +import org.thingsboard.server.common.transport.util.JsonUtils; | |
37 | +import org.thingsboard.server.dao.device.DeviceCredentialsService; | |
38 | +import org.thingsboard.server.dao.device.DeviceService; | |
39 | +import org.thingsboard.server.dao.device.provision.ProvisionResponseStatus; | |
40 | + | |
41 | +import java.io.IOException; | |
42 | + | |
43 | +import static org.junit.Assert.assertEquals; | |
44 | + | |
45 | +@Slf4j | |
46 | +public abstract class AbstractCoapProvisionJsonDeviceTest extends AbstractCoapIntegrationTest { | |
47 | + | |
48 | + @Autowired | |
49 | + DeviceCredentialsService deviceCredentialsService; | |
50 | + | |
51 | + @Autowired | |
52 | + DeviceService deviceService; | |
53 | + | |
54 | + @After | |
55 | + public void afterTest() throws Exception { | |
56 | + super.processAfterTest(); | |
57 | + } | |
58 | + | |
59 | + @Test | |
60 | + public void testProvisioningDisabledDevice() throws Exception { | |
61 | + processTestProvisioningDisabledDevice(); | |
62 | + } | |
63 | + | |
64 | + @Test | |
65 | + public void testProvisioningCheckPreProvisionedDevice() throws Exception { | |
66 | + processTestProvisioningCheckPreProvisionedDevice(); | |
67 | + } | |
68 | + | |
69 | + @Test | |
70 | + public void testProvisioningCreateNewDeviceWithoutCredentials() throws Exception { | |
71 | + processTestProvisioningCreateNewDeviceWithoutCredentials(); | |
72 | + } | |
73 | + | |
74 | + @Test | |
75 | + public void testProvisioningCreateNewDeviceWithAccessToken() throws Exception { | |
76 | + processTestProvisioningCreateNewDeviceWithAccessToken(); | |
77 | + } | |
78 | + | |
79 | + @Test | |
80 | + public void testProvisioningCreateNewDeviceWithCert() throws Exception { | |
81 | + processTestProvisioningCreateNewDeviceWithCert(); | |
82 | + } | |
83 | + | |
84 | + @Test | |
85 | + public void testProvisioningWithBadKeyDevice() throws Exception { | |
86 | + processTestProvisioningWithBadKeyDevice(); | |
87 | + } | |
88 | + | |
89 | + | |
90 | + private void processTestProvisioningDisabledDevice() throws Exception { | |
91 | + super.processBeforeTest("Test Provision device", CoapDeviceType.DEFAULT, TransportPayloadType.JSON, null, null, DeviceProfileProvisionType.DISABLED, null, null); | |
92 | + byte[] result = createCoapClientAndPublish().getPayload(); | |
93 | + JsonObject response = JsonUtils.parse(new String(result)).getAsJsonObject(); | |
94 | + Assert.assertEquals("Provision data was not found!", response.get("errorMsg").getAsString()); | |
95 | + Assert.assertEquals(ProvisionResponseStatus.NOT_FOUND.name(), response.get("status").getAsString()); | |
96 | + } | |
97 | + | |
98 | + | |
99 | + private void processTestProvisioningCreateNewDeviceWithoutCredentials() throws Exception { | |
100 | + super.processBeforeTest("Test Provision device3", CoapDeviceType.DEFAULT, TransportPayloadType.JSON, null, null, DeviceProfileProvisionType.ALLOW_CREATE_NEW_DEVICES, "testProvisionKey", "testProvisionSecret"); | |
101 | + byte[] result = createCoapClientAndPublish().getPayload(); | |
102 | + JsonObject response = JsonUtils.parse(new String(result)).getAsJsonObject(); | |
103 | + | |
104 | + Device createdDevice = deviceService.findDeviceByTenantIdAndName(savedTenant.getTenantId(), "Test Provision device"); | |
105 | + | |
106 | + Assert.assertNotNull(createdDevice); | |
107 | + | |
108 | + DeviceCredentials deviceCredentials = deviceCredentialsService.findDeviceCredentialsByDeviceId(savedTenant.getTenantId(), createdDevice.getId()); | |
109 | + | |
110 | + Assert.assertEquals(deviceCredentials.getCredentialsType().name(), response.get("credentialsType").getAsString()); | |
111 | + Assert.assertEquals(ProvisionResponseStatus.SUCCESS.name(), response.get("status").getAsString()); | |
112 | + } | |
113 | + | |
114 | + | |
115 | + private void processTestProvisioningCreateNewDeviceWithAccessToken() throws Exception { | |
116 | + super.processBeforeTest("Test Provision device3", CoapDeviceType.DEFAULT, TransportPayloadType.JSON, null, null, DeviceProfileProvisionType.ALLOW_CREATE_NEW_DEVICES, "testProvisionKey", "testProvisionSecret"); | |
117 | + String requestCredentials = ",\"credentialsType\": \"ACCESS_TOKEN\",\"token\": \"test_token\""; | |
118 | + byte[] result = createCoapClientAndPublish(requestCredentials).getPayload(); | |
119 | + JsonObject response = JsonUtils.parse(new String(result)).getAsJsonObject(); | |
120 | + | |
121 | + Device createdDevice = deviceService.findDeviceByTenantIdAndName(savedTenant.getTenantId(), "Test Provision device"); | |
122 | + | |
123 | + Assert.assertNotNull(createdDevice); | |
124 | + | |
125 | + DeviceCredentials deviceCredentials = deviceCredentialsService.findDeviceCredentialsByDeviceId(savedTenant.getTenantId(), createdDevice.getId()); | |
126 | + | |
127 | + Assert.assertEquals(deviceCredentials.getCredentialsType().name(), response.get("credentialsType").getAsString()); | |
128 | + Assert.assertEquals(deviceCredentials.getCredentialsType().name(), "ACCESS_TOKEN"); | |
129 | + Assert.assertEquals(deviceCredentials.getCredentialsId(), "test_token"); | |
130 | + Assert.assertEquals(ProvisionResponseStatus.SUCCESS.name(), response.get("status").getAsString()); | |
131 | + } | |
132 | + | |
133 | + | |
134 | + private void processTestProvisioningCreateNewDeviceWithCert() throws Exception { | |
135 | + super.processBeforeTest("Test Provision device3", CoapDeviceType.DEFAULT, TransportPayloadType.JSON, null, null, DeviceProfileProvisionType.ALLOW_CREATE_NEW_DEVICES, "testProvisionKey", "testProvisionSecret"); | |
136 | + String requestCredentials = ",\"credentialsType\": \"X509_CERTIFICATE\",\"hash\": \"testHash\""; | |
137 | + byte[] result = createCoapClientAndPublish(requestCredentials).getPayload(); | |
138 | + JsonObject response = JsonUtils.parse(new String(result)).getAsJsonObject(); | |
139 | + | |
140 | + Device createdDevice = deviceService.findDeviceByTenantIdAndName(savedTenant.getTenantId(), "Test Provision device"); | |
141 | + | |
142 | + Assert.assertNotNull(createdDevice); | |
143 | + | |
144 | + DeviceCredentials deviceCredentials = deviceCredentialsService.findDeviceCredentialsByDeviceId(savedTenant.getTenantId(), createdDevice.getId()); | |
145 | + | |
146 | + Assert.assertEquals(deviceCredentials.getCredentialsType().name(), response.get("credentialsType").getAsString()); | |
147 | + Assert.assertEquals(deviceCredentials.getCredentialsType().name(), "X509_CERTIFICATE"); | |
148 | + | |
149 | + String cert = EncryptionUtil.trimNewLines(deviceCredentials.getCredentialsValue()); | |
150 | + String sha3Hash = EncryptionUtil.getSha3Hash(cert); | |
151 | + | |
152 | + Assert.assertEquals(deviceCredentials.getCredentialsId(), sha3Hash); | |
153 | + | |
154 | + Assert.assertEquals(deviceCredentials.getCredentialsValue(), "testHash"); | |
155 | + Assert.assertEquals(ProvisionResponseStatus.SUCCESS.name(), response.get("status").getAsString()); | |
156 | + } | |
157 | + | |
158 | + private void processTestProvisioningCheckPreProvisionedDevice() throws Exception { | |
159 | + super.processBeforeTest("Test Provision device", CoapDeviceType.DEFAULT, TransportPayloadType.JSON, null, null, DeviceProfileProvisionType.CHECK_PRE_PROVISIONED_DEVICES, "testProvisionKey", "testProvisionSecret"); | |
160 | + byte[] result = createCoapClientAndPublish().getPayload(); | |
161 | + JsonObject response = JsonUtils.parse(new String(result)).getAsJsonObject(); | |
162 | + | |
163 | + DeviceCredentials deviceCredentials = deviceCredentialsService.findDeviceCredentialsByDeviceId(savedTenant.getTenantId(), savedDevice.getId()); | |
164 | + | |
165 | + Assert.assertEquals(deviceCredentials.getCredentialsType().name(), response.get("credentialsType").getAsString()); | |
166 | + Assert.assertEquals(ProvisionResponseStatus.SUCCESS.name(), response.get("status").getAsString()); | |
167 | + } | |
168 | + | |
169 | + private void processTestProvisioningWithBadKeyDevice() throws Exception { | |
170 | + super.processBeforeTest("Test Provision device", CoapDeviceType.DEFAULT, TransportPayloadType.JSON, null, null, DeviceProfileProvisionType.CHECK_PRE_PROVISIONED_DEVICES, "testProvisionKeyOrig", "testProvisionSecret"); | |
171 | + byte[] result = createCoapClientAndPublish().getPayload(); | |
172 | + JsonObject response = JsonUtils.parse(new String(result)).getAsJsonObject(); | |
173 | + Assert.assertEquals("Provision data was not found!", response.get("errorMsg").getAsString()); | |
174 | + Assert.assertEquals(ProvisionResponseStatus.NOT_FOUND.name(), response.get("status").getAsString()); | |
175 | + } | |
176 | + | |
177 | + private CoapResponse createCoapClientAndPublish() throws Exception { | |
178 | + return createCoapClientAndPublish(""); | |
179 | + } | |
180 | + | |
181 | + private CoapResponse createCoapClientAndPublish(String deviceCredentials) throws Exception { | |
182 | + String provisionRequestMsg = createTestProvisionMessage(deviceCredentials); | |
183 | + CoapClient client = getCoapClient(FeatureType.PROVISION); | |
184 | + return postProvision(client, provisionRequestMsg.getBytes()); | |
185 | + } | |
186 | + | |
187 | + | |
188 | + private CoapResponse postProvision(CoapClient client, byte[] payload) throws IOException, ConnectorException { | |
189 | + return client.setTimeout((long) 60000).post(payload, MediaTypeRegistry.APPLICATION_JSON); | |
190 | + } | |
191 | + | |
192 | + private String createTestProvisionMessage(String deviceCredentials) { | |
193 | + return "{\"deviceName\":\"Test Provision device\",\"provisionDeviceKey\":\"testProvisionKey\", \"provisionDeviceSecret\":\"testProvisionSecret\"" + deviceCredentials + "}"; | |
194 | + } | |
195 | +} | ... | ... |
1 | +/** | |
2 | + * Copyright © 2016-2021 The Thingsboard Authors | |
3 | + * | |
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | |
5 | + * you may not use this file except in compliance with the License. | |
6 | + * You may obtain a copy of the License at | |
7 | + * | |
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | |
9 | + * | |
10 | + * Unless required by applicable law or agreed to in writing, software | |
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | |
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 | + * See the License for the specific language governing permissions and | |
14 | + * limitations under the License. | |
15 | + */ | |
16 | +package org.thingsboard.server.transport.coap.provision; | |
17 | + | |
18 | +import lombok.extern.slf4j.Slf4j; | |
19 | +import org.eclipse.californium.core.CoapClient; | |
20 | +import org.eclipse.californium.core.CoapResponse; | |
21 | +import org.eclipse.californium.core.coap.MediaTypeRegistry; | |
22 | +import org.eclipse.californium.elements.exception.ConnectorException; | |
23 | +import org.junit.After; | |
24 | +import org.junit.Assert; | |
25 | +import org.junit.Test; | |
26 | +import org.springframework.beans.factory.annotation.Autowired; | |
27 | +import org.thingsboard.server.transport.coap.AbstractCoapIntegrationTest; | |
28 | +import org.thingsboard.server.common.data.CoapDeviceType; | |
29 | +import org.thingsboard.server.common.data.Device; | |
30 | +import org.thingsboard.server.common.data.DeviceProfileProvisionType; | |
31 | +import org.thingsboard.server.common.data.TransportPayloadType; | |
32 | +import org.thingsboard.server.common.data.security.DeviceCredentials; | |
33 | +import org.thingsboard.server.common.data.security.DeviceCredentialsType; | |
34 | +import org.thingsboard.server.common.msg.EncryptionUtil; | |
35 | +import org.thingsboard.server.common.msg.session.FeatureType; | |
36 | +import org.thingsboard.server.dao.device.DeviceCredentialsService; | |
37 | +import org.thingsboard.server.dao.device.DeviceService; | |
38 | +import org.thingsboard.server.dao.device.provision.ProvisionResponseStatus; | |
39 | +import org.thingsboard.server.gen.transport.TransportProtos.CredentialsDataProto; | |
40 | +import org.thingsboard.server.gen.transport.TransportProtos.CredentialsType; | |
41 | +import org.thingsboard.server.gen.transport.TransportProtos.ProvisionDeviceCredentialsMsg; | |
42 | +import org.thingsboard.server.gen.transport.TransportProtos.ProvisionDeviceRequestMsg; | |
43 | +import org.thingsboard.server.gen.transport.TransportProtos.ProvisionDeviceResponseMsg; | |
44 | +import org.thingsboard.server.gen.transport.TransportProtos.ValidateDeviceTokenRequestMsg; | |
45 | +import org.thingsboard.server.gen.transport.TransportProtos.ValidateDeviceX509CertRequestMsg; | |
46 | + | |
47 | +import java.io.IOException; | |
48 | + | |
49 | +@Slf4j | |
50 | +public abstract class AbstractCoapProvisionProtoDeviceTest extends AbstractCoapIntegrationTest { | |
51 | + | |
52 | + @Autowired | |
53 | + DeviceCredentialsService deviceCredentialsService; | |
54 | + | |
55 | + @Autowired | |
56 | + DeviceService deviceService; | |
57 | + | |
58 | + @After | |
59 | + public void afterTest() throws Exception { | |
60 | + super.processAfterTest(); | |
61 | + } | |
62 | + | |
63 | + @Test | |
64 | + public void testProvisioningDisabledDevice() throws Exception { | |
65 | + processTestProvisioningDisabledDevice(); | |
66 | + } | |
67 | + | |
68 | + @Test | |
69 | + public void testProvisioningCheckPreProvisionedDevice() throws Exception { | |
70 | + processTestProvisioningCheckPreProvisionedDevice(); | |
71 | + } | |
72 | + | |
73 | + @Test | |
74 | + public void testProvisioningCreateNewDeviceWithoutCredentials() throws Exception { | |
75 | + processTestProvisioningCreateNewDeviceWithoutCredentials(); | |
76 | + } | |
77 | + | |
78 | + @Test | |
79 | + public void testProvisioningCreateNewDeviceWithAccessToken() throws Exception { | |
80 | + processTestProvisioningCreateNewDeviceWithAccessToken(); | |
81 | + } | |
82 | + | |
83 | + @Test | |
84 | + public void testProvisioningCreateNewDeviceWithCert() throws Exception { | |
85 | + processTestProvisioningCreateNewDeviceWithCert(); | |
86 | + } | |
87 | + | |
88 | + @Test | |
89 | + public void testProvisioningWithBadKeyDevice() throws Exception { | |
90 | + processTestProvisioningWithBadKeyDevice(); | |
91 | + } | |
92 | + | |
93 | + | |
94 | + private void processTestProvisioningDisabledDevice() throws Exception { | |
95 | + super.processBeforeTest("Test Provision device", CoapDeviceType.DEFAULT, TransportPayloadType.PROTOBUF, null, null, DeviceProfileProvisionType.DISABLED, null, null); | |
96 | + ProvisionDeviceResponseMsg result = ProvisionDeviceResponseMsg.parseFrom(createCoapClientAndPublish().getPayload()); | |
97 | + Assert.assertNotNull(result); | |
98 | + Assert.assertEquals(ProvisionResponseStatus.NOT_FOUND.name(), result.getStatus().toString()); | |
99 | + } | |
100 | + | |
101 | + private void processTestProvisioningCreateNewDeviceWithoutCredentials() throws Exception { | |
102 | + super.processBeforeTest("Test Provision device3", CoapDeviceType.DEFAULT, TransportPayloadType.PROTOBUF, null, null, DeviceProfileProvisionType.ALLOW_CREATE_NEW_DEVICES, "testProvisionKey", "testProvisionSecret"); | |
103 | + ProvisionDeviceResponseMsg response = ProvisionDeviceResponseMsg.parseFrom(createCoapClientAndPublish().getPayload()); | |
104 | + | |
105 | + Device createdDevice = deviceService.findDeviceByTenantIdAndName(savedTenant.getTenantId(), "Test Provision device"); | |
106 | + | |
107 | + Assert.assertNotNull(createdDevice); | |
108 | + | |
109 | + DeviceCredentials deviceCredentials = deviceCredentialsService.findDeviceCredentialsByDeviceId(savedTenant.getTenantId(), createdDevice.getId()); | |
110 | + | |
111 | + Assert.assertEquals(deviceCredentials.getCredentialsType().name(), response.getCredentialsType().toString()); | |
112 | + Assert.assertEquals(ProvisionResponseStatus.SUCCESS.name(), response.getStatus().toString()); | |
113 | + } | |
114 | + | |
115 | + private void processTestProvisioningCreateNewDeviceWithAccessToken() throws Exception { | |
116 | + super.processBeforeTest("Test Provision device3", CoapDeviceType.DEFAULT, TransportPayloadType.PROTOBUF, null, null, DeviceProfileProvisionType.ALLOW_CREATE_NEW_DEVICES, "testProvisionKey", "testProvisionSecret"); | |
117 | + CredentialsDataProto requestCredentials = CredentialsDataProto.newBuilder().setValidateDeviceTokenRequestMsg(ValidateDeviceTokenRequestMsg.newBuilder().setToken("test_token").build()).build(); | |
118 | + | |
119 | + ProvisionDeviceResponseMsg response = ProvisionDeviceResponseMsg.parseFrom(createCoapClientAndPublish(createTestsProvisionMessage(CredentialsType.ACCESS_TOKEN, requestCredentials)).getPayload()); | |
120 | + | |
121 | + Device createdDevice = deviceService.findDeviceByTenantIdAndName(savedTenant.getTenantId(), "Test Provision device"); | |
122 | + | |
123 | + Assert.assertNotNull(createdDevice); | |
124 | + | |
125 | + DeviceCredentials deviceCredentials = deviceCredentialsService.findDeviceCredentialsByDeviceId(savedTenant.getTenantId(), createdDevice.getId()); | |
126 | + | |
127 | + Assert.assertEquals(deviceCredentials.getCredentialsType().name(), response.getCredentialsType().toString()); | |
128 | + Assert.assertEquals(deviceCredentials.getCredentialsType(), DeviceCredentialsType.ACCESS_TOKEN); | |
129 | + Assert.assertEquals(deviceCredentials.getCredentialsId(), "test_token"); | |
130 | + Assert.assertEquals(ProvisionResponseStatus.SUCCESS.name(), response.getStatus().toString()); | |
131 | + } | |
132 | + | |
133 | + private void processTestProvisioningCreateNewDeviceWithCert() throws Exception { | |
134 | + super.processBeforeTest("Test Provision device3", CoapDeviceType.DEFAULT, TransportPayloadType.PROTOBUF, null, null, DeviceProfileProvisionType.ALLOW_CREATE_NEW_DEVICES, "testProvisionKey", "testProvisionSecret"); | |
135 | + CredentialsDataProto requestCredentials = CredentialsDataProto.newBuilder().setValidateDeviceX509CertRequestMsg(ValidateDeviceX509CertRequestMsg.newBuilder().setHash("testHash").build()).build(); | |
136 | + | |
137 | + ProvisionDeviceResponseMsg response = ProvisionDeviceResponseMsg.parseFrom(createCoapClientAndPublish(createTestsProvisionMessage(CredentialsType.X509_CERTIFICATE, requestCredentials)).getPayload()); | |
138 | + | |
139 | + Device createdDevice = deviceService.findDeviceByTenantIdAndName(savedTenant.getTenantId(), "Test Provision device"); | |
140 | + | |
141 | + Assert.assertNotNull(createdDevice); | |
142 | + | |
143 | + DeviceCredentials deviceCredentials = deviceCredentialsService.findDeviceCredentialsByDeviceId(savedTenant.getTenantId(), createdDevice.getId()); | |
144 | + | |
145 | + Assert.assertEquals(deviceCredentials.getCredentialsType().name(), response.getCredentialsType().toString()); | |
146 | + Assert.assertEquals(deviceCredentials.getCredentialsType(), DeviceCredentialsType.X509_CERTIFICATE); | |
147 | + | |
148 | + String cert = EncryptionUtil.trimNewLines(deviceCredentials.getCredentialsValue()); | |
149 | + String sha3Hash = EncryptionUtil.getSha3Hash(cert); | |
150 | + | |
151 | + Assert.assertEquals(deviceCredentials.getCredentialsId(), sha3Hash); | |
152 | + | |
153 | + Assert.assertEquals(deviceCredentials.getCredentialsValue(), "testHash"); | |
154 | + Assert.assertEquals(ProvisionResponseStatus.SUCCESS.name(), response.getStatus().toString()); | |
155 | + } | |
156 | + | |
157 | + private void processTestProvisioningCheckPreProvisionedDevice() throws Exception { | |
158 | + super.processBeforeTest("Test Provision device", CoapDeviceType.DEFAULT, TransportPayloadType.PROTOBUF, null, null, DeviceProfileProvisionType.CHECK_PRE_PROVISIONED_DEVICES, "testProvisionKey", "testProvisionSecret"); | |
159 | + ProvisionDeviceResponseMsg response = ProvisionDeviceResponseMsg.parseFrom(createCoapClientAndPublish().getPayload()); | |
160 | + | |
161 | + DeviceCredentials deviceCredentials = deviceCredentialsService.findDeviceCredentialsByDeviceId(savedTenant.getTenantId(), savedDevice.getId()); | |
162 | + | |
163 | + Assert.assertEquals(deviceCredentials.getCredentialsType().name(), response.getCredentialsType().toString()); | |
164 | + Assert.assertEquals(ProvisionResponseStatus.SUCCESS.name(), response.getStatus().toString()); | |
165 | + } | |
166 | + | |
167 | + private void processTestProvisioningWithBadKeyDevice() throws Exception { | |
168 | + super.processBeforeTest("Test Provision device", CoapDeviceType.DEFAULT, TransportPayloadType.PROTOBUF, null, null, DeviceProfileProvisionType.CHECK_PRE_PROVISIONED_DEVICES, "testProvisionKeyOrig", "testProvisionSecret"); | |
169 | + ProvisionDeviceResponseMsg response = ProvisionDeviceResponseMsg.parseFrom(createCoapClientAndPublish().getPayload()); | |
170 | + Assert.assertEquals(ProvisionResponseStatus.NOT_FOUND.name(), response.getStatus().toString()); | |
171 | + } | |
172 | + | |
173 | + private CoapResponse createCoapClientAndPublish() throws Exception { | |
174 | + byte[] provisionRequestMsg = createTestProvisionMessage(); | |
175 | + return createCoapClientAndPublish(provisionRequestMsg); | |
176 | + } | |
177 | + | |
178 | + private CoapResponse createCoapClientAndPublish(byte[] provisionRequestMsg) throws Exception { | |
179 | + CoapClient client = getCoapClient(FeatureType.PROVISION); | |
180 | + return postProvision(client, provisionRequestMsg); | |
181 | + } | |
182 | + | |
183 | + private CoapResponse postProvision(CoapClient client, byte[] payload) throws IOException, ConnectorException { | |
184 | + return client.setTimeout((long) 60000).post(payload, MediaTypeRegistry.APPLICATION_JSON); | |
185 | + } | |
186 | + | |
187 | + private byte[] createTestsProvisionMessage(CredentialsType credentialsType, CredentialsDataProto credentialsData) throws Exception { | |
188 | + return ProvisionDeviceRequestMsg.newBuilder() | |
189 | + .setDeviceName("Test Provision device") | |
190 | + .setCredentialsType(credentialsType != null ? credentialsType : CredentialsType.ACCESS_TOKEN) | |
191 | + .setCredentialsDataProto(credentialsData != null ? credentialsData: CredentialsDataProto.newBuilder().build()) | |
192 | + .setProvisionDeviceCredentialsMsg( | |
193 | + ProvisionDeviceCredentialsMsg.newBuilder() | |
194 | + .setProvisionDeviceKey("testProvisionKey") | |
195 | + .setProvisionDeviceSecret("testProvisionSecret") | |
196 | + ).build() | |
197 | + .toByteArray(); | |
198 | + } | |
199 | + | |
200 | + | |
201 | + private byte[] createTestProvisionMessage() throws Exception { | |
202 | + return createTestsProvisionMessage(null, null); | |
203 | + } | |
204 | + | |
205 | +} | ... | ... |
1 | +/** | |
2 | + * Copyright © 2016-2021 The Thingsboard Authors | |
3 | + * | |
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | |
5 | + * you may not use this file except in compliance with the License. | |
6 | + * You may obtain a copy of the License at | |
7 | + * | |
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | |
9 | + * | |
10 | + * Unless required by applicable law or agreed to in writing, software | |
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | |
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 | + * See the License for the specific language governing permissions and | |
14 | + * limitations under the License. | |
15 | + */ | |
16 | +package org.thingsboard.server.transport.coap.provision.sql; | |
17 | + | |
18 | +import org.thingsboard.server.transport.coap.provision.AbstractCoapProvisionJsonDeviceTest; | |
19 | +import org.thingsboard.server.dao.service.DaoSqlTest; | |
20 | + | |
21 | +@DaoSqlTest | |
22 | +public class CoapProvisionDeviceJsonSqlTest extends AbstractCoapProvisionJsonDeviceTest { | |
23 | +} | ... | ... |
1 | +/** | |
2 | + * Copyright © 2016-2021 The Thingsboard Authors | |
3 | + * | |
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | |
5 | + * you may not use this file except in compliance with the License. | |
6 | + * You may obtain a copy of the License at | |
7 | + * | |
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | |
9 | + * | |
10 | + * Unless required by applicable law or agreed to in writing, software | |
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | |
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 | + * See the License for the specific language governing permissions and | |
14 | + * limitations under the License. | |
15 | + */ | |
16 | +package org.thingsboard.server.transport.coap.provision.sql; | |
17 | + | |
18 | +import org.thingsboard.server.transport.coap.provision.AbstractCoapProvisionProtoDeviceTest; | |
19 | +import org.thingsboard.server.dao.service.DaoSqlTest; | |
20 | + | |
21 | +@DaoSqlTest | |
22 | +public class CoapProvisionDeviceProtoSqlTest extends AbstractCoapProvisionProtoDeviceTest { | |
23 | +} | ... | ... |
1 | +/** | |
2 | + * Copyright © 2016-2021 The Thingsboard Authors | |
3 | + * | |
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | |
5 | + * you may not use this file except in compliance with the License. | |
6 | + * You may obtain a copy of the License at | |
7 | + * | |
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | |
9 | + * | |
10 | + * Unless required by applicable law or agreed to in writing, software | |
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | |
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 | + * See the License for the specific language governing permissions and | |
14 | + * limitations under the License. | |
15 | + */ | |
16 | +package org.thingsboard.server.transport.coap.rpc; | |
17 | + | |
18 | +import com.datastax.oss.driver.api.core.uuid.Uuids; | |
19 | +import lombok.extern.slf4j.Slf4j; | |
20 | +import org.junit.After; | |
21 | +import org.junit.Assert; | |
22 | +import org.junit.Before; | |
23 | +import org.junit.Test; | |
24 | +import org.thingsboard.server.service.security.AccessValidator; | |
25 | + | |
26 | +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; | |
27 | + | |
28 | +@Slf4j | |
29 | +public abstract class AbstractCoapServerSideRpcDefaultIntegrationTest extends AbstractCoapServerSideRpcIntegrationTest { | |
30 | + | |
31 | + @Before | |
32 | + public void beforeTest() throws Exception { | |
33 | + processBeforeTest("RPC test device", null, null); | |
34 | + } | |
35 | + | |
36 | + @After | |
37 | + public void afterTest() throws Exception { | |
38 | + super.processAfterTest(); | |
39 | + } | |
40 | + | |
41 | + @Test | |
42 | + public void testServerCoapOneWayRpcDeviceOffline() throws Exception { | |
43 | + String setGpioRequest = "{\"method\":\"setGpio\",\"params\":{\"pin\": \"24\",\"value\": 1},\"timeout\": 6000}"; | |
44 | + String deviceId = savedDevice.getId().getId().toString(); | |
45 | + | |
46 | + doPostAsync("/api/plugins/rpc/oneway/" + deviceId, setGpioRequest, String.class, status().is(409), | |
47 | + asyncContextTimeoutToUseRpcPlugin); | |
48 | + } | |
49 | + | |
50 | + @Test | |
51 | + public void testServerCoapOneWayRpcDeviceDoesNotExist() throws Exception { | |
52 | + String setGpioRequest = "{\"method\":\"setGpio\",\"params\":{\"pin\": \"25\",\"value\": 1}}"; | |
53 | + String nonExistentDeviceId = Uuids.timeBased().toString(); | |
54 | + | |
55 | + String result = doPostAsync("/api/plugins/rpc/oneway/" + nonExistentDeviceId, setGpioRequest, String.class, | |
56 | + status().isNotFound()); | |
57 | + Assert.assertEquals(AccessValidator.DEVICE_WITH_REQUESTED_ID_NOT_FOUND, result); | |
58 | + } | |
59 | + | |
60 | + @Test | |
61 | + public void testServerCoapTwoWayRpcDeviceOffline() throws Exception { | |
62 | + String setGpioRequest = "{\"method\":\"setGpio\",\"params\":{\"pin\": \"27\",\"value\": 1},\"timeout\": 6000}"; | |
63 | + String deviceId = savedDevice.getId().getId().toString(); | |
64 | + | |
65 | + doPostAsync("/api/plugins/rpc/twoway/" + deviceId, setGpioRequest, String.class, status().is(409), | |
66 | + asyncContextTimeoutToUseRpcPlugin); | |
67 | + } | |
68 | + | |
69 | + @Test | |
70 | + public void testServerCoapTwoWayRpcDeviceDoesNotExist() throws Exception { | |
71 | + String setGpioRequest = "{\"method\":\"setGpio\",\"params\":{\"pin\": \"28\",\"value\": 1}}"; | |
72 | + String nonExistentDeviceId = Uuids.timeBased().toString(); | |
73 | + | |
74 | + String result = doPostAsync("/api/plugins/rpc/twoway/" + nonExistentDeviceId, setGpioRequest, String.class, | |
75 | + status().isNotFound()); | |
76 | + Assert.assertEquals(AccessValidator.DEVICE_WITH_REQUESTED_ID_NOT_FOUND, result); | |
77 | + } | |
78 | + | |
79 | + @Test | |
80 | + public void testServerCoapOneWayRpc() throws Exception { | |
81 | + processOneWayRpcTest(); | |
82 | + } | |
83 | + | |
84 | + @Test | |
85 | + public void testServerCoapTwoWayRpc() throws Exception { | |
86 | + processTwoWayRpcTest(); | |
87 | + } | |
88 | + | |
89 | +} | ... | ... |
1 | +/** | |
2 | + * Copyright © 2016-2021 The Thingsboard Authors | |
3 | + * | |
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | |
5 | + * you may not use this file except in compliance with the License. | |
6 | + * You may obtain a copy of the License at | |
7 | + * | |
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | |
9 | + * | |
10 | + * Unless required by applicable law or agreed to in writing, software | |
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | |
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 | + * See the License for the specific language governing permissions and | |
14 | + * limitations under the License. | |
15 | + */ | |
16 | +package org.thingsboard.server.transport.coap.rpc; | |
17 | + | |
18 | +import lombok.extern.slf4j.Slf4j; | |
19 | +import org.apache.commons.lang3.StringUtils; | |
20 | +import org.eclipse.californium.core.CoapClient; | |
21 | +import org.eclipse.californium.core.CoapHandler; | |
22 | +import org.eclipse.californium.core.CoapObserveRelation; | |
23 | +import org.eclipse.californium.core.CoapResponse; | |
24 | +import org.eclipse.californium.core.coap.CoAP; | |
25 | +import org.eclipse.californium.core.coap.MediaTypeRegistry; | |
26 | +import org.eclipse.californium.core.coap.Request; | |
27 | +import org.junit.Assert; | |
28 | +import org.thingsboard.server.transport.coap.AbstractCoapIntegrationTest; | |
29 | +import org.thingsboard.server.common.data.CoapDeviceType; | |
30 | +import org.thingsboard.server.common.data.TransportPayloadType; | |
31 | +import org.thingsboard.server.common.msg.session.FeatureType; | |
32 | + | |
33 | +import java.util.concurrent.CountDownLatch; | |
34 | +import java.util.concurrent.TimeUnit; | |
35 | + | |
36 | +import static org.junit.Assert.assertEquals; | |
37 | +import static org.junit.Assert.assertNotNull; | |
38 | +import static org.junit.Assert.assertTrue; | |
39 | +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; | |
40 | + | |
41 | +@Slf4j | |
42 | +public abstract class AbstractCoapServerSideRpcIntegrationTest extends AbstractCoapIntegrationTest { | |
43 | + | |
44 | + protected static final String DEVICE_RESPONSE = "{\"value1\":\"A\",\"value2\":\"B\"}"; | |
45 | + | |
46 | + protected Long asyncContextTimeoutToUseRpcPlugin; | |
47 | + | |
48 | + protected void processBeforeTest(String deviceName, CoapDeviceType coapDeviceType, TransportPayloadType payloadType) throws Exception { | |
49 | + super.processBeforeTest(deviceName, coapDeviceType, payloadType); | |
50 | + asyncContextTimeoutToUseRpcPlugin = 10000L; | |
51 | + } | |
52 | + | |
53 | + protected void processOneWayRpcTest() throws Exception { | |
54 | + CoapClient client = getCoapClient(FeatureType.RPC); | |
55 | + client.useCONs(); | |
56 | + | |
57 | + CountDownLatch latch = new CountDownLatch(1); | |
58 | + TestCoapCallback testCoapCallback = new TestCoapCallback(client, latch, true); | |
59 | + | |
60 | + Request request = Request.newGet().setObserve(); | |
61 | + CoapObserveRelation observeRelation = client.observe(request, testCoapCallback); | |
62 | + | |
63 | + String setGpioRequest = "{\"method\":\"setGpio\",\"params\":{\"pin\": \"23\",\"value\": 1}}"; | |
64 | + String deviceId = savedDevice.getId().getId().toString(); | |
65 | + String result = doPostAsync("/api/plugins/rpc/oneway/" + deviceId, setGpioRequest, String.class, status().isOk()); | |
66 | + Assert.assertTrue(StringUtils.isEmpty(result)); | |
67 | + latch.await(3, TimeUnit.SECONDS); | |
68 | + assertEquals(0, testCoapCallback.getObserve().intValue()); | |
69 | + observeRelation.proactiveCancel(); | |
70 | + assertTrue(observeRelation.isCanceled()); | |
71 | + } | |
72 | + | |
73 | + protected void processTwoWayRpcTest() throws Exception { | |
74 | + CoapClient client = getCoapClient(FeatureType.RPC); | |
75 | + client.useCONs(); | |
76 | + | |
77 | + CountDownLatch latch = new CountDownLatch(1); | |
78 | + TestCoapCallback testCoapCallback = new TestCoapCallback(client, latch, false); | |
79 | + | |
80 | + Request request = Request.newGet().setObserve(); | |
81 | + request.setType(CoAP.Type.CON); | |
82 | + CoapObserveRelation observeRelation = client.observe(request, testCoapCallback); | |
83 | + | |
84 | + String setGpioRequest = "{\"method\":\"setGpio\",\"params\":{\"pin\": \"26\",\"value\": 1}}"; | |
85 | + String deviceId = savedDevice.getId().getId().toString(); | |
86 | + | |
87 | + String expected = "{\"value1\":\"A\",\"value2\":\"B\"}"; | |
88 | + | |
89 | + String result = doPostAsync("/api/plugins/rpc/twoway/" + deviceId, setGpioRequest, String.class, status().isOk()); | |
90 | + latch.await(3, TimeUnit.SECONDS); | |
91 | + | |
92 | + assertEquals(expected, result); | |
93 | + assertEquals(0, testCoapCallback.getObserve().intValue()); | |
94 | + observeRelation.proactiveCancel(); | |
95 | + assertTrue(observeRelation.isCanceled()); | |
96 | + | |
97 | +// // TODO: 3/11/21 Fix test to validate next RPC | |
98 | +// latch = new CountDownLatch(1); | |
99 | +// | |
100 | +// result = doPostAsync("/api/plugins/rpc/twoway/" + deviceId, setGpioRequest, String.class, status().isOk()); | |
101 | +// latch.await(3, TimeUnit.SECONDS); | |
102 | +// | |
103 | +// assertEquals(expected, result); | |
104 | +// assertEquals(1, testCoapCallback.getObserve().intValue()); | |
105 | + } | |
106 | + | |
107 | + protected void processOnLoadResponse(CoapResponse response, CoapClient client, Integer observe, CountDownLatch latch) { | |
108 | + client.setURI(getRpcResponseFeatureTokenUrl(accessToken, observe)); | |
109 | + client.post(new CoapHandler() { | |
110 | + @Override | |
111 | + public void onLoad(CoapResponse response) { | |
112 | + log.warn("Command Response Ack: {}, {}", response.getCode(), response.getResponseText()); | |
113 | + latch.countDown(); | |
114 | + } | |
115 | + | |
116 | + @Override | |
117 | + public void onError() { | |
118 | + log.warn("Command Response Ack Error, No connect"); | |
119 | + } | |
120 | + }, DEVICE_RESPONSE, MediaTypeRegistry.APPLICATION_JSON); | |
121 | + } | |
122 | + | |
123 | + protected String getRpcResponseFeatureTokenUrl(String token, int requestId) { | |
124 | + return COAP_BASE_URL + token + "/" + FeatureType.RPC.name().toLowerCase() + "/" + requestId; | |
125 | + } | |
126 | + | |
127 | + private class TestCoapCallback implements CoapHandler { | |
128 | + | |
129 | + private final CoapClient client; | |
130 | + private final CountDownLatch latch; | |
131 | + private final boolean isOneWayRpc; | |
132 | + | |
133 | + public Integer getObserve() { | |
134 | + return observe; | |
135 | + } | |
136 | + | |
137 | + private Integer observe; | |
138 | + | |
139 | + private TestCoapCallback(CoapClient client, CountDownLatch latch, boolean isOneWayRpc) { | |
140 | + this.client = client; | |
141 | + this.latch = latch; | |
142 | + this.isOneWayRpc = isOneWayRpc; | |
143 | + } | |
144 | + | |
145 | + @Override | |
146 | + public void onLoad(CoapResponse response) { | |
147 | + log.warn("coap response: {}, {}", response, response.getCode()); | |
148 | + assertNotNull(response.getPayload()); | |
149 | + assertEquals(response.getCode(), CoAP.ResponseCode.CONTENT); | |
150 | + observe = response.getOptions().getObserve(); | |
151 | + if (!isOneWayRpc) { | |
152 | + processOnLoadResponse(response, client, observe, latch); | |
153 | + } else { | |
154 | + latch.countDown(); | |
155 | + } | |
156 | + } | |
157 | + | |
158 | + @Override | |
159 | + public void onError() { | |
160 | + log.warn("Command Response Ack Error, No connect"); | |
161 | + } | |
162 | + | |
163 | + } | |
164 | + | |
165 | +} | ... | ... |
1 | +/** | |
2 | + * Copyright © 2016-2021 The Thingsboard Authors | |
3 | + * | |
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | |
5 | + * you may not use this file except in compliance with the License. | |
6 | + * You may obtain a copy of the License at | |
7 | + * | |
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | |
9 | + * | |
10 | + * Unless required by applicable law or agreed to in writing, software | |
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | |
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 | + * See the License for the specific language governing permissions and | |
14 | + * limitations under the License. | |
15 | + */ | |
16 | +package org.thingsboard.server.transport.coap.rpc; | |
17 | + | |
18 | +import lombok.extern.slf4j.Slf4j; | |
19 | +import org.junit.After; | |
20 | +import org.junit.Before; | |
21 | +import org.junit.Test; | |
22 | +import org.thingsboard.server.common.data.CoapDeviceType; | |
23 | +import org.thingsboard.server.common.data.TransportPayloadType; | |
24 | + | |
25 | +@Slf4j | |
26 | +public abstract class AbstractCoapServerSideRpcJsonIntegrationTest extends AbstractCoapServerSideRpcIntegrationTest { | |
27 | + | |
28 | + @Before | |
29 | + public void beforeTest() throws Exception { | |
30 | + processBeforeTest("RPC test device", CoapDeviceType.DEFAULT, TransportPayloadType.JSON); | |
31 | + } | |
32 | + | |
33 | + @After | |
34 | + public void afterTest() throws Exception { | |
35 | + super.processAfterTest(); | |
36 | + } | |
37 | + | |
38 | + @Test | |
39 | + public void testServerMqttOneWayRpc() throws Exception { | |
40 | + processOneWayRpcTest(); | |
41 | + } | |
42 | + | |
43 | + @Test | |
44 | + public void testServerMqttTwoWayRpc() throws Exception { | |
45 | + processTwoWayRpcTest(); | |
46 | + } | |
47 | + | |
48 | +} | ... | ... |
1 | +/** | |
2 | + * Copyright © 2016-2021 The Thingsboard Authors | |
3 | + * | |
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | |
5 | + * you may not use this file except in compliance with the License. | |
6 | + * You may obtain a copy of the License at | |
7 | + * | |
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | |
9 | + * | |
10 | + * Unless required by applicable law or agreed to in writing, software | |
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | |
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 | + * See the License for the specific language governing permissions and | |
14 | + * limitations under the License. | |
15 | + */ | |
16 | +package org.thingsboard.server.transport.coap.rpc; | |
17 | + | |
18 | +import lombok.extern.slf4j.Slf4j; | |
19 | +import org.eclipse.californium.core.CoapClient; | |
20 | +import org.eclipse.californium.core.CoapHandler; | |
21 | +import org.eclipse.californium.core.CoapResponse; | |
22 | +import org.eclipse.californium.core.coap.MediaTypeRegistry; | |
23 | +import org.junit.After; | |
24 | +import org.junit.Before; | |
25 | +import org.junit.Test; | |
26 | +import org.thingsboard.server.common.data.CoapDeviceType; | |
27 | +import org.thingsboard.server.common.data.TransportPayloadType; | |
28 | +import org.thingsboard.server.gen.transport.TransportProtos; | |
29 | + | |
30 | +import java.util.concurrent.CountDownLatch; | |
31 | + | |
32 | +@Slf4j | |
33 | +public abstract class AbstractCoapServerSideRpcProtoIntegrationTest extends AbstractCoapServerSideRpcIntegrationTest { | |
34 | + | |
35 | + @Before | |
36 | + public void beforeTest() throws Exception { | |
37 | + processBeforeTest("RPC test device", CoapDeviceType.DEFAULT, TransportPayloadType.PROTOBUF); | |
38 | + } | |
39 | + | |
40 | + @After | |
41 | + public void afterTest() throws Exception { | |
42 | + super.processAfterTest(); | |
43 | + } | |
44 | + | |
45 | + @Test | |
46 | + public void testServerMqttOneWayRpc() throws Exception { | |
47 | + processOneWayRpcTest(); | |
48 | + } | |
49 | + | |
50 | + @Test | |
51 | + public void testServerMqttTwoWayRpc() throws Exception { | |
52 | + processTwoWayRpcTest(); | |
53 | + } | |
54 | + | |
55 | + @Override | |
56 | + protected void processOnLoadResponse(CoapResponse response, CoapClient client, Integer observe, CountDownLatch latch) { | |
57 | + client.setURI(getRpcResponseFeatureTokenUrl(accessToken, observe)); | |
58 | + TransportProtos.ToDeviceRpcResponseMsg toDeviceRpcResponseMsg = TransportProtos.ToDeviceRpcResponseMsg.newBuilder() | |
59 | + .setPayload(DEVICE_RESPONSE) | |
60 | + .setRequestId(observe) | |
61 | + .build(); | |
62 | + client.post(new CoapHandler() { | |
63 | + @Override | |
64 | + public void onLoad(CoapResponse response) { | |
65 | + log.warn("Command Response Ack: {}, {}", response.getCode(), response.getResponseText()); | |
66 | + latch.countDown(); | |
67 | + } | |
68 | + | |
69 | + @Override | |
70 | + public void onError() { | |
71 | + log.warn("Command Response Ack Error, No connect"); | |
72 | + } | |
73 | + }, toDeviceRpcResponseMsg.toByteArray(), MediaTypeRegistry.APPLICATION_JSON); | |
74 | + } | |
75 | +} | ... | ... |
1 | +/** | |
2 | + * Copyright © 2016-2021 The Thingsboard Authors | |
3 | + * | |
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | |
5 | + * you may not use this file except in compliance with the License. | |
6 | + * You may obtain a copy of the License at | |
7 | + * | |
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | |
9 | + * | |
10 | + * Unless required by applicable law or agreed to in writing, software | |
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | |
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 | + * See the License for the specific language governing permissions and | |
14 | + * limitations under the License. | |
15 | + */ | |
16 | +package org.thingsboard.server.transport.coap.rpc.sql; | |
17 | + | |
18 | +import org.thingsboard.server.transport.coap.rpc.AbstractCoapServerSideRpcJsonIntegrationTest; | |
19 | +import org.thingsboard.server.dao.service.DaoSqlTest; | |
20 | + | |
21 | +@DaoSqlTest | |
22 | +public class CoapServerSideRpcJsonSqlIntegrationTest extends AbstractCoapServerSideRpcJsonIntegrationTest { | |
23 | +} | ... | ... |
1 | +/** | |
2 | + * Copyright © 2016-2021 The Thingsboard Authors | |
3 | + * | |
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | |
5 | + * you may not use this file except in compliance with the License. | |
6 | + * You may obtain a copy of the License at | |
7 | + * | |
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | |
9 | + * | |
10 | + * Unless required by applicable law or agreed to in writing, software | |
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | |
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 | + * See the License for the specific language governing permissions and | |
14 | + * limitations under the License. | |
15 | + */ | |
16 | +package org.thingsboard.server.transport.coap.rpc.sql; | |
17 | + | |
18 | +import org.thingsboard.server.transport.coap.rpc.AbstractCoapServerSideRpcProtoIntegrationTest; | |
19 | +import org.thingsboard.server.dao.service.DaoSqlTest; | |
20 | + | |
21 | + | |
22 | +@DaoSqlTest | |
23 | +public class CoapServerSideRpcProtoSqlIntegrationTest extends AbstractCoapServerSideRpcProtoIntegrationTest { | |
24 | +} | ... | ... |
1 | +/** | |
2 | + * Copyright © 2016-2021 The Thingsboard Authors | |
3 | + * | |
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | |
5 | + * you may not use this file except in compliance with the License. | |
6 | + * You may obtain a copy of the License at | |
7 | + * | |
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | |
9 | + * | |
10 | + * Unless required by applicable law or agreed to in writing, software | |
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | |
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 | + * See the License for the specific language governing permissions and | |
14 | + * limitations under the License. | |
15 | + */ | |
16 | +package org.thingsboard.server.transport.coap.rpc.sql; | |
17 | + | |
18 | +import org.thingsboard.server.transport.coap.rpc.AbstractCoapServerSideRpcDefaultIntegrationTest; | |
19 | +import org.thingsboard.server.dao.service.DaoSqlTest; | |
20 | + | |
21 | +@DaoSqlTest | |
22 | +public class CoapServerSideRpcSqlIntegrationTest extends AbstractCoapServerSideRpcDefaultIntegrationTest { | |
23 | +} | ... | ... |
1 | +/** | |
2 | + * Copyright © 2016-2021 The Thingsboard Authors | |
3 | + * | |
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | |
5 | + * you may not use this file except in compliance with the License. | |
6 | + * You may obtain a copy of the License at | |
7 | + * | |
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | |
9 | + * | |
10 | + * Unless required by applicable law or agreed to in writing, software | |
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | |
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 | + * See the License for the specific language governing permissions and | |
14 | + * limitations under the License. | |
15 | + */ | |
16 | +package org.thingsboard.server.transport.coap.telemetry.attributes; | |
17 | + | |
18 | +import com.fasterxml.jackson.core.JsonProcessingException; | |
19 | +import com.fasterxml.jackson.core.type.TypeReference; | |
20 | +import lombok.extern.slf4j.Slf4j; | |
21 | +import org.eclipse.californium.core.CoapClient; | |
22 | +import org.eclipse.californium.core.CoapResponse; | |
23 | +import org.eclipse.californium.core.coap.CoAP; | |
24 | +import org.eclipse.californium.core.coap.MediaTypeRegistry; | |
25 | +import org.eclipse.californium.elements.exception.ConnectorException; | |
26 | +import org.junit.After; | |
27 | +import org.junit.Before; | |
28 | +import org.junit.Test; | |
29 | +import org.thingsboard.server.transport.coap.AbstractCoapIntegrationTest; | |
30 | +import org.thingsboard.server.common.data.id.DeviceId; | |
31 | +import org.thingsboard.server.common.msg.session.FeatureType; | |
32 | + | |
33 | +import java.io.IOException; | |
34 | +import java.util.Arrays; | |
35 | +import java.util.HashSet; | |
36 | +import java.util.LinkedHashMap; | |
37 | +import java.util.List; | |
38 | +import java.util.Map; | |
39 | +import java.util.Set; | |
40 | + | |
41 | +import static org.junit.Assert.assertEquals; | |
42 | +import static org.junit.Assert.assertNotNull; | |
43 | +import static org.junit.Assert.assertTrue; | |
44 | + | |
45 | +@Slf4j | |
46 | +public abstract class AbstractCoapAttributesIntegrationTest extends AbstractCoapIntegrationTest { | |
47 | + | |
48 | + private static final String PAYLOAD_VALUES_STR = "{\"key1\":\"value1\", \"key2\":true, \"key3\": 3.0, \"key4\": 4," + | |
49 | + " \"key5\": {\"someNumber\": 42, \"someArray\": [1,2,3], \"someNestedObject\": {\"key\": \"value\"}}}"; | |
50 | + | |
51 | + @Before | |
52 | + public void beforeTest() throws Exception { | |
53 | + processBeforeTest("Test Post Attributes device", null, null); | |
54 | + } | |
55 | + | |
56 | + @After | |
57 | + public void afterTest() throws Exception { | |
58 | + processAfterTest(); | |
59 | + } | |
60 | + | |
61 | + @Test | |
62 | + public void testPushAttributes() throws Exception { | |
63 | + List<String> expectedKeys = Arrays.asList("key1", "key2", "key3", "key4", "key5"); | |
64 | + processAttributesTest(expectedKeys, PAYLOAD_VALUES_STR.getBytes()); | |
65 | + } | |
66 | + | |
67 | + protected void processAttributesTest(List<String> expectedKeys, byte[] payload) throws Exception { | |
68 | + log.warn("[testPushAttributes] Device: {}, Transport type: {}", savedDevice.getName(), savedDevice.getType()); | |
69 | + CoapClient client = getCoapClient(FeatureType.ATTRIBUTES); | |
70 | + | |
71 | + postAttributes(client, payload); | |
72 | + | |
73 | + DeviceId deviceId = savedDevice.getId(); | |
74 | + | |
75 | + long start = System.currentTimeMillis(); | |
76 | + long end = System.currentTimeMillis() + 5000; | |
77 | + | |
78 | + List<String> actualKeys = null; | |
79 | + while (start <= end) { | |
80 | + actualKeys = doGetAsyncTyped("/api/plugins/telemetry/DEVICE/" + deviceId + "/keys/attributes/CLIENT_SCOPE", new TypeReference<>() {}); | |
81 | + if (actualKeys.size() == expectedKeys.size()) { | |
82 | + break; | |
83 | + } | |
84 | + Thread.sleep(100); | |
85 | + start += 100; | |
86 | + } | |
87 | + assertNotNull(actualKeys); | |
88 | + | |
89 | + Set<String> actualKeySet = new HashSet<>(actualKeys); | |
90 | + | |
91 | + Set<String> expectedKeySet = new HashSet<>(expectedKeys); | |
92 | + | |
93 | + assertEquals(expectedKeySet, actualKeySet); | |
94 | + | |
95 | + String getAttributesValuesUrl = getAttributesValuesUrl(deviceId, actualKeySet); | |
96 | + List<Map<String, Object>> values = doGetAsyncTyped(getAttributesValuesUrl, new TypeReference<>() {}); | |
97 | + assertAttributesValues(values, expectedKeySet); | |
98 | + String deleteAttributesUrl = "/api/plugins/telemetry/DEVICE/" + deviceId + "/CLIENT_SCOPE?keys=" + String.join(",", actualKeySet); | |
99 | + doDelete(deleteAttributesUrl); | |
100 | + } | |
101 | + | |
102 | + private void postAttributes(CoapClient client, byte[] payload) throws IOException, ConnectorException { | |
103 | + if (payload == null) { | |
104 | + payload = PAYLOAD_VALUES_STR.getBytes(); | |
105 | + } | |
106 | + CoapResponse coapResponse = client.setTimeout((long) 60000).post(payload, MediaTypeRegistry.APPLICATION_JSON); | |
107 | + assertEquals(CoAP.ResponseCode.CREATED, coapResponse.getCode()); | |
108 | + } | |
109 | + | |
110 | + @SuppressWarnings("unchecked") | |
111 | + protected void assertAttributesValues(List<Map<String, Object>> deviceValues, Set<String> expectedKeySet) throws JsonProcessingException { | |
112 | + for (Map<String, Object> map : deviceValues) { | |
113 | + String key = (String) map.get("key"); | |
114 | + Object value = map.get("value"); | |
115 | + assertTrue(expectedKeySet.contains(key)); | |
116 | + switch (key) { | |
117 | + case "key1": | |
118 | + assertEquals("value1", value); | |
119 | + break; | |
120 | + case "key2": | |
121 | + assertEquals(true, value); | |
122 | + break; | |
123 | + case "key3": | |
124 | + assertEquals(3.0, value); | |
125 | + break; | |
126 | + case "key4": | |
127 | + assertEquals(4, value); | |
128 | + break; | |
129 | + case "key5": | |
130 | + assertNotNull(value); | |
131 | + assertEquals(3, ((LinkedHashMap) value).size()); | |
132 | + assertEquals(42, ((LinkedHashMap) value).get("someNumber")); | |
133 | + assertEquals(Arrays.asList(1, 2, 3), ((LinkedHashMap) value).get("someArray")); | |
134 | + LinkedHashMap<String, String> someNestedObject = (LinkedHashMap) ((LinkedHashMap) value).get("someNestedObject"); | |
135 | + assertEquals("value", someNestedObject.get("key")); | |
136 | + break; | |
137 | + } | |
138 | + } | |
139 | + } | |
140 | + | |
141 | + private String getAttributesValuesUrl(DeviceId deviceId, Set<String> actualKeySet) { | |
142 | + return "/api/plugins/telemetry/DEVICE/" + deviceId + "/values/attributes/CLIENT_SCOPE?keys=" + String.join(",", actualKeySet); | |
143 | + } | |
144 | + | |
145 | +} | ... | ... |
1 | +/** | |
2 | + * Copyright © 2016-2021 The Thingsboard Authors | |
3 | + * | |
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | |
5 | + * you may not use this file except in compliance with the License. | |
6 | + * You may obtain a copy of the License at | |
7 | + * | |
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | |
9 | + * | |
10 | + * Unless required by applicable law or agreed to in writing, software | |
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | |
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 | + * See the License for the specific language governing permissions and | |
14 | + * limitations under the License. | |
15 | + */ | |
16 | +package org.thingsboard.server.transport.coap.telemetry.attributes; | |
17 | + | |
18 | +import lombok.extern.slf4j.Slf4j; | |
19 | +import org.junit.After; | |
20 | +import org.junit.Before; | |
21 | +import org.junit.Test; | |
22 | +import org.thingsboard.server.common.data.CoapDeviceType; | |
23 | +import org.thingsboard.server.common.data.TransportPayloadType; | |
24 | + | |
25 | +@Slf4j | |
26 | +public abstract class AbstractCoapAttributesJsonIntegrationTest extends AbstractCoapAttributesIntegrationTest { | |
27 | + | |
28 | + @Before | |
29 | + public void beforeTest() throws Exception { | |
30 | + processBeforeTest("Test Post Attributes device Json", CoapDeviceType.DEFAULT, TransportPayloadType.JSON); | |
31 | + } | |
32 | + | |
33 | + @After | |
34 | + public void afterTest() throws Exception { | |
35 | + processAfterTest(); | |
36 | + } | |
37 | + | |
38 | + @Test | |
39 | + public void testPushAttributes() throws Exception { | |
40 | + super.testPushAttributes(); | |
41 | + } | |
42 | +} | ... | ... |
1 | +/** | |
2 | + * Copyright © 2016-2021 The Thingsboard Authors | |
3 | + * | |
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | |
5 | + * you may not use this file except in compliance with the License. | |
6 | + * You may obtain a copy of the License at | |
7 | + * | |
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | |
9 | + * | |
10 | + * Unless required by applicable law or agreed to in writing, software | |
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | |
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 | + * See the License for the specific language governing permissions and | |
14 | + * limitations under the License. | |
15 | + */ | |
16 | +package org.thingsboard.server.transport.coap.telemetry.attributes; | |
17 | + | |
18 | +import com.github.os72.protobuf.dynamic.DynamicSchema; | |
19 | +import com.google.protobuf.Descriptors; | |
20 | +import com.google.protobuf.DynamicMessage; | |
21 | +import com.squareup.wire.schema.internal.parser.ProtoFileElement; | |
22 | +import lombok.extern.slf4j.Slf4j; | |
23 | +import org.junit.After; | |
24 | +import org.junit.Test; | |
25 | +import org.thingsboard.server.common.data.CoapDeviceType; | |
26 | +import org.thingsboard.server.common.data.TransportPayloadType; | |
27 | +import org.thingsboard.server.common.data.device.profile.CoapDeviceProfileTransportConfiguration; | |
28 | +import org.thingsboard.server.common.data.device.profile.CoapDeviceTypeConfiguration; | |
29 | +import org.thingsboard.server.common.data.device.profile.DefaultCoapDeviceTypeConfiguration; | |
30 | +import org.thingsboard.server.common.data.device.profile.DeviceProfileTransportConfiguration; | |
31 | +import org.thingsboard.server.common.data.device.profile.ProtoTransportPayloadConfiguration; | |
32 | +import org.thingsboard.server.common.data.device.profile.TransportPayloadTypeConfiguration; | |
33 | + | |
34 | +import java.util.Arrays; | |
35 | +import java.util.List; | |
36 | + | |
37 | +import static org.junit.Assert.assertNotNull; | |
38 | +import static org.junit.Assert.assertTrue; | |
39 | + | |
40 | +@Slf4j | |
41 | +public abstract class AbstractCoapAttributesProtoIntegrationTest extends AbstractCoapAttributesIntegrationTest { | |
42 | + | |
43 | + @After | |
44 | + public void afterTest() throws Exception { | |
45 | + processAfterTest(); | |
46 | + } | |
47 | + | |
48 | + @Test | |
49 | + public void testPushAttributes() throws Exception { | |
50 | + super.processBeforeTest("Test Post Attributes device Proto", CoapDeviceType.DEFAULT, TransportPayloadType.PROTOBUF); | |
51 | + List<String> expectedKeys = Arrays.asList("key1", "key2", "key3", "key4", "key5"); | |
52 | + DeviceProfileTransportConfiguration transportConfiguration = deviceProfile.getProfileData().getTransportConfiguration(); | |
53 | + assertTrue(transportConfiguration instanceof CoapDeviceProfileTransportConfiguration); | |
54 | + CoapDeviceProfileTransportConfiguration coapTransportConfiguration = (CoapDeviceProfileTransportConfiguration) transportConfiguration; | |
55 | + CoapDeviceTypeConfiguration coapDeviceTypeConfiguration = coapTransportConfiguration.getCoapDeviceTypeConfiguration(); | |
56 | + assertTrue(coapDeviceTypeConfiguration instanceof DefaultCoapDeviceTypeConfiguration); | |
57 | + DefaultCoapDeviceTypeConfiguration defaultCoapDeviceTypeConfiguration = (DefaultCoapDeviceTypeConfiguration) coapDeviceTypeConfiguration; | |
58 | + TransportPayloadTypeConfiguration transportPayloadTypeConfiguration = defaultCoapDeviceTypeConfiguration.getTransportPayloadTypeConfiguration(); | |
59 | + assertTrue(transportPayloadTypeConfiguration instanceof ProtoTransportPayloadConfiguration); | |
60 | + ProtoTransportPayloadConfiguration protoTransportPayloadConfiguration = (ProtoTransportPayloadConfiguration) transportPayloadTypeConfiguration; | |
61 | + ProtoFileElement transportProtoSchemaFile = protoTransportPayloadConfiguration.getTransportProtoSchema(DEVICE_ATTRIBUTES_PROTO_SCHEMA); | |
62 | + DynamicSchema attributesSchema = protoTransportPayloadConfiguration.getDynamicSchema(transportProtoSchemaFile, ProtoTransportPayloadConfiguration.ATTRIBUTES_PROTO_SCHEMA); | |
63 | + | |
64 | + DynamicMessage.Builder nestedJsonObjectBuilder = attributesSchema.newMessageBuilder("PostAttributes.JsonObject.NestedJsonObject"); | |
65 | + Descriptors.Descriptor nestedJsonObjectBuilderDescriptor = nestedJsonObjectBuilder.getDescriptorForType(); | |
66 | + assertNotNull(nestedJsonObjectBuilderDescriptor); | |
67 | + DynamicMessage nestedJsonObject = nestedJsonObjectBuilder.setField(nestedJsonObjectBuilderDescriptor.findFieldByName("key"), "value").build(); | |
68 | + | |
69 | + DynamicMessage.Builder jsonObjectBuilder = attributesSchema.newMessageBuilder("PostAttributes.JsonObject"); | |
70 | + Descriptors.Descriptor jsonObjectBuilderDescriptor = jsonObjectBuilder.getDescriptorForType(); | |
71 | + assertNotNull(jsonObjectBuilderDescriptor); | |
72 | + DynamicMessage jsonObject = jsonObjectBuilder | |
73 | + .setField(jsonObjectBuilderDescriptor.findFieldByName("someNumber"), 42) | |
74 | + .addRepeatedField(jsonObjectBuilderDescriptor.findFieldByName("someArray"), 1) | |
75 | + .addRepeatedField(jsonObjectBuilderDescriptor.findFieldByName("someArray"), 2) | |
76 | + .addRepeatedField(jsonObjectBuilderDescriptor.findFieldByName("someArray"), 3) | |
77 | + .setField(jsonObjectBuilderDescriptor.findFieldByName("someNestedObject"), nestedJsonObject) | |
78 | + .build(); | |
79 | + | |
80 | + DynamicMessage.Builder postAttributesBuilder = attributesSchema.newMessageBuilder("PostAttributes"); | |
81 | + Descriptors.Descriptor postAttributesMsgDescriptor = postAttributesBuilder.getDescriptorForType(); | |
82 | + assertNotNull(postAttributesMsgDescriptor); | |
83 | + DynamicMessage postAttributesMsg = postAttributesBuilder | |
84 | + .setField(postAttributesMsgDescriptor.findFieldByName("key1"), "value1") | |
85 | + .setField(postAttributesMsgDescriptor.findFieldByName("key2"), true) | |
86 | + .setField(postAttributesMsgDescriptor.findFieldByName("key3"), 3.0) | |
87 | + .setField(postAttributesMsgDescriptor.findFieldByName("key4"), 4) | |
88 | + .setField(postAttributesMsgDescriptor.findFieldByName("key5"), jsonObject) | |
89 | + .build(); | |
90 | + processAttributesTest(expectedKeys, postAttributesMsg.toByteArray()); | |
91 | + } | |
92 | + | |
93 | +} | ... | ... |
application/src/test/java/org/thingsboard/server/transport/coap/telemetry/attributes/sql/CoapAttributesSqlIntegrationTest.java
renamed from
application/src/test/java/org/thingsboard/server/mqtt/rpc/nosql/MqttServerSideRpcNoSqlIntegrationTest.java
... | ... | @@ -13,14 +13,14 @@ |
13 | 13 | * See the License for the specific language governing permissions and |
14 | 14 | * limitations under the License. |
15 | 15 | */ |
16 | -package org.thingsboard.server.mqtt.rpc.nosql; | |
16 | +package org.thingsboard.server.transport.coap.telemetry.attributes.sql; | |
17 | 17 | |
18 | -import org.thingsboard.server.dao.service.DaoNoSqlTest; | |
19 | -import org.thingsboard.server.mqtt.rpc.AbstractMqttServerSideRpcDefaultIntegrationTest; | |
18 | +import org.thingsboard.server.transport.coap.telemetry.attributes.AbstractCoapAttributesIntegrationTest; | |
19 | +import org.thingsboard.server.dao.service.DaoSqlTest; | |
20 | 20 | |
21 | 21 | /** |
22 | 22 | * Created by Valerii Sosliuk on 8/22/2017. |
23 | 23 | */ |
24 | -@DaoNoSqlTest | |
25 | -public class MqttServerSideRpcNoSqlIntegrationTest extends AbstractMqttServerSideRpcDefaultIntegrationTest { | |
24 | +@DaoSqlTest | |
25 | +public class CoapAttributesSqlIntegrationTest extends AbstractCoapAttributesIntegrationTest { | |
26 | 26 | } | ... | ... |
1 | +/** | |
2 | + * Copyright © 2016-2021 The Thingsboard Authors | |
3 | + * | |
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | |
5 | + * you may not use this file except in compliance with the License. | |
6 | + * You may obtain a copy of the License at | |
7 | + * | |
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | |
9 | + * | |
10 | + * Unless required by applicable law or agreed to in writing, software | |
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | |
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 | + * See the License for the specific language governing permissions and | |
14 | + * limitations under the License. | |
15 | + */ | |
16 | +package org.thingsboard.server.transport.coap.telemetry.attributes.sql; | |
17 | + | |
18 | +import org.thingsboard.server.transport.coap.telemetry.attributes.AbstractCoapAttributesJsonIntegrationTest; | |
19 | +import org.thingsboard.server.dao.service.DaoSqlTest; | |
20 | + | |
21 | +/** | |
22 | + * Created by Valerii Sosliuk on 8/22/2017. | |
23 | + */ | |
24 | +@DaoSqlTest | |
25 | +public class CoapAttributesSqlJsonIntegrationTest extends AbstractCoapAttributesJsonIntegrationTest { | |
26 | +} | ... | ... |
1 | +/** | |
2 | + * Copyright © 2016-2021 The Thingsboard Authors | |
3 | + * | |
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | |
5 | + * you may not use this file except in compliance with the License. | |
6 | + * You may obtain a copy of the License at | |
7 | + * | |
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | |
9 | + * | |
10 | + * Unless required by applicable law or agreed to in writing, software | |
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | |
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 | + * See the License for the specific language governing permissions and | |
14 | + * limitations under the License. | |
15 | + */ | |
16 | +package org.thingsboard.server.transport.coap.telemetry.attributes.sql; | |
17 | + | |
18 | +import org.thingsboard.server.transport.coap.telemetry.attributes.AbstractCoapAttributesProtoIntegrationTest; | |
19 | +import org.thingsboard.server.dao.service.DaoSqlTest; | |
20 | + | |
21 | +/** | |
22 | + * Created by Valerii Sosliuk on 8/22/2017. | |
23 | + */ | |
24 | +@DaoSqlTest | |
25 | +public class CoapAttributesSqlProtoIntegrationTest extends AbstractCoapAttributesProtoIntegrationTest { | |
26 | +} | ... | ... |
1 | +/** | |
2 | + * Copyright © 2016-2021 The Thingsboard Authors | |
3 | + * | |
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | |
5 | + * you may not use this file except in compliance with the License. | |
6 | + * You may obtain a copy of the License at | |
7 | + * | |
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | |
9 | + * | |
10 | + * Unless required by applicable law or agreed to in writing, software | |
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | |
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 | + * See the License for the specific language governing permissions and | |
14 | + * limitations under the License. | |
15 | + */ | |
16 | +package org.thingsboard.server.transport.coap.telemetry.timeseries; | |
17 | + | |
18 | +import com.fasterxml.jackson.core.type.TypeReference; | |
19 | +import lombok.extern.slf4j.Slf4j; | |
20 | +import org.eclipse.californium.core.CoapClient; | |
21 | +import org.eclipse.californium.core.CoapResponse; | |
22 | +import org.eclipse.californium.core.coap.CoAP; | |
23 | +import org.eclipse.californium.core.coap.MediaTypeRegistry; | |
24 | +import org.eclipse.californium.elements.exception.ConnectorException; | |
25 | +import org.junit.After; | |
26 | +import org.junit.Before; | |
27 | +import org.junit.Test; | |
28 | +import org.thingsboard.server.transport.coap.AbstractCoapIntegrationTest; | |
29 | +import org.thingsboard.server.common.msg.session.FeatureType; | |
30 | + | |
31 | +import java.io.IOException; | |
32 | +import java.util.Arrays; | |
33 | +import java.util.HashSet; | |
34 | +import java.util.List; | |
35 | +import java.util.Map; | |
36 | +import java.util.Set; | |
37 | + | |
38 | +import static org.junit.Assert.assertEquals; | |
39 | +import static org.junit.Assert.assertNotNull; | |
40 | + | |
41 | +@Slf4j | |
42 | +public abstract class AbstractCoapTimeseriesIntegrationTest extends AbstractCoapIntegrationTest { | |
43 | + | |
44 | + private static final String PAYLOAD_VALUES_STR = "{\"key1\":\"value1\", \"key2\":true, \"key3\": 3.0, \"key4\": 4," + | |
45 | + " \"key5\": {\"someNumber\": 42, \"someArray\": [1,2,3], \"someNestedObject\": {\"key\": \"value\"}}}"; | |
46 | + | |
47 | + @Before | |
48 | + public void beforeTest() throws Exception { | |
49 | + processBeforeTest("Test Post Telemetry device", null, null); | |
50 | + } | |
51 | + | |
52 | + @After | |
53 | + public void afterTest() throws Exception { | |
54 | + processAfterTest(); | |
55 | + } | |
56 | + | |
57 | + @Test | |
58 | + public void testPushTelemetry() throws Exception { | |
59 | + processTestPostTelemetry(null, false); | |
60 | + } | |
61 | + | |
62 | + @Test | |
63 | + public void testPushTelemetryWithTs() throws Exception { | |
64 | + String payloadStr = "{\"ts\": 10000, \"values\": " + PAYLOAD_VALUES_STR + "}"; | |
65 | + processTestPostTelemetry(payloadStr.getBytes(), true); | |
66 | + } | |
67 | + | |
68 | + protected void processTestPostTelemetry(byte[] payloadBytes, boolean withTs) throws Exception { | |
69 | + log.warn("[testPushTelemetry] Device: {}, Transport type: {}", savedDevice.getName(), savedDevice.getType()); | |
70 | + List<String> expectedKeys = Arrays.asList("key1", "key2", "key3", "key4", "key5"); | |
71 | + CoapClient coapClient = getCoapClient(FeatureType.TELEMETRY); | |
72 | + postTelemetry(coapClient, payloadBytes); | |
73 | + | |
74 | + String deviceId = savedDevice.getId().getId().toString(); | |
75 | + | |
76 | + long start = System.currentTimeMillis(); | |
77 | + long end = System.currentTimeMillis() + 5000; | |
78 | + | |
79 | + List<String> actualKeys = null; | |
80 | + while (start <= end) { | |
81 | + actualKeys = doGetAsyncTyped("/api/plugins/telemetry/DEVICE/" + deviceId + "/keys/timeseries", new TypeReference<>() {}); | |
82 | + if (actualKeys.size() == expectedKeys.size()) { | |
83 | + break; | |
84 | + } | |
85 | + Thread.sleep(100); | |
86 | + start += 100; | |
87 | + } | |
88 | + assertNotNull(actualKeys); | |
89 | + | |
90 | + Set<String> actualKeySet = new HashSet<>(actualKeys); | |
91 | + Set<String> expectedKeySet = new HashSet<>(expectedKeys); | |
92 | + | |
93 | + assertEquals(expectedKeySet, actualKeySet); | |
94 | + | |
95 | + String getTelemetryValuesUrl; | |
96 | + if (withTs) { | |
97 | + getTelemetryValuesUrl = "/api/plugins/telemetry/DEVICE/" + deviceId + "/values/timeseries?startTs=0&endTs=15000&keys=" + String.join(",", actualKeySet); | |
98 | + } else { | |
99 | + getTelemetryValuesUrl = "/api/plugins/telemetry/DEVICE/" + deviceId + "/values/timeseries?keys=" + String.join(",", actualKeySet); | |
100 | + } | |
101 | + start = System.currentTimeMillis(); | |
102 | + end = System.currentTimeMillis() + 5000; | |
103 | + Map<String, List<Map<String, Object>>> values = null; | |
104 | + while (start <= end) { | |
105 | + values = doGetAsyncTyped(getTelemetryValuesUrl, new TypeReference<>() {}); | |
106 | + boolean valid = values.size() == expectedKeys.size(); | |
107 | + if (valid) { | |
108 | + for (String key : expectedKeys) { | |
109 | + List<Map<String, Object>> tsValues = values.get(key); | |
110 | + if (tsValues != null && tsValues.size() > 0) { | |
111 | + Object ts = tsValues.get(0).get("ts"); | |
112 | + if (ts == null) { | |
113 | + valid = false; | |
114 | + break; | |
115 | + } | |
116 | + } else { | |
117 | + valid = false; | |
118 | + break; | |
119 | + } | |
120 | + } | |
121 | + } | |
122 | + if (valid) { | |
123 | + break; | |
124 | + } | |
125 | + Thread.sleep(100); | |
126 | + start += 100; | |
127 | + } | |
128 | + assertNotNull(values); | |
129 | + | |
130 | + if (withTs) { | |
131 | + assertTs(values, expectedKeys, 10000, 0); | |
132 | + } | |
133 | + assertValues(values, 0); | |
134 | + } | |
135 | + | |
136 | + private void postTelemetry(CoapClient client, byte[] payload) throws IOException, ConnectorException { | |
137 | + if (payload == null) { | |
138 | + payload = PAYLOAD_VALUES_STR.getBytes(); | |
139 | + } | |
140 | + CoapResponse coapResponse = client.setTimeout((long) 60000).post(payload, MediaTypeRegistry.APPLICATION_JSON); | |
141 | + assertEquals(CoAP.ResponseCode.CREATED, coapResponse.getCode()); | |
142 | + } | |
143 | + | |
144 | + private void assertTs(Map<String, List<Map<String, Object>>> deviceValues, List<String> expectedKeys, int ts, int arrayIndex) { | |
145 | + assertEquals(ts, deviceValues.get(expectedKeys.get(0)).get(arrayIndex).get("ts")); | |
146 | + assertEquals(ts, deviceValues.get(expectedKeys.get(1)).get(arrayIndex).get("ts")); | |
147 | + assertEquals(ts, deviceValues.get(expectedKeys.get(2)).get(arrayIndex).get("ts")); | |
148 | + assertEquals(ts, deviceValues.get(expectedKeys.get(3)).get(arrayIndex).get("ts")); | |
149 | + assertEquals(ts, deviceValues.get(expectedKeys.get(4)).get(arrayIndex).get("ts")); | |
150 | + } | |
151 | + | |
152 | + private void assertValues(Map<String, List<Map<String, Object>>> deviceValues, int arrayIndex) { | |
153 | + for (Map.Entry<String, List<Map<String, Object>>> entry : deviceValues.entrySet()) { | |
154 | + String key = entry.getKey(); | |
155 | + List<Map<String, Object>> tsKv = entry.getValue(); | |
156 | + String value = (String) tsKv.get(arrayIndex).get("value"); | |
157 | + switch (key) { | |
158 | + case "key1": | |
159 | + assertEquals("value1", value); | |
160 | + break; | |
161 | + case "key2": | |
162 | + assertEquals("true", value); | |
163 | + break; | |
164 | + case "key3": | |
165 | + assertEquals("3.0", value); | |
166 | + break; | |
167 | + case "key4": | |
168 | + assertEquals("4", value); | |
169 | + break; | |
170 | + case "key5": | |
171 | + assertEquals("{\"someNumber\":42,\"someArray\":[1,2,3],\"someNestedObject\":{\"key\":\"value\"}}", value); | |
172 | + break; | |
173 | + } | |
174 | + } | |
175 | + } | |
176 | + | |
177 | + | |
178 | +} | ... | ... |
1 | +/** | |
2 | + * Copyright © 2016-2021 The Thingsboard Authors | |
3 | + * | |
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | |
5 | + * you may not use this file except in compliance with the License. | |
6 | + * You may obtain a copy of the License at | |
7 | + * | |
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | |
9 | + * | |
10 | + * Unless required by applicable law or agreed to in writing, software | |
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | |
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 | + * See the License for the specific language governing permissions and | |
14 | + * limitations under the License. | |
15 | + */ | |
16 | +package org.thingsboard.server.transport.coap.telemetry.timeseries; | |
17 | + | |
18 | +import lombok.extern.slf4j.Slf4j; | |
19 | +import org.junit.After; | |
20 | +import org.junit.Before; | |
21 | +import org.junit.Test; | |
22 | +import org.thingsboard.server.common.data.CoapDeviceType; | |
23 | +import org.thingsboard.server.common.data.TransportPayloadType; | |
24 | + | |
25 | +@Slf4j | |
26 | +public abstract class AbstractCoapTimeseriesJsonIntegrationTest extends AbstractCoapTimeseriesIntegrationTest { | |
27 | + | |
28 | + @Before | |
29 | + public void beforeTest() throws Exception { | |
30 | + processBeforeTest("Test Post Telemetry device json payload", CoapDeviceType.DEFAULT, TransportPayloadType.JSON); | |
31 | + } | |
32 | + | |
33 | + @After | |
34 | + public void afterTest() throws Exception { | |
35 | + processAfterTest(); | |
36 | + } | |
37 | + | |
38 | + | |
39 | + @Test | |
40 | + public void testPushTelemetry() throws Exception { | |
41 | + super.testPushTelemetry(); | |
42 | + } | |
43 | + | |
44 | + @Test | |
45 | + public void testPushTelemetryWithTs() throws Exception { | |
46 | + super.testPushTelemetryWithTs(); | |
47 | + } | |
48 | + | |
49 | + | |
50 | +} | ... | ... |
1 | +/** | |
2 | + * Copyright © 2016-2021 The Thingsboard Authors | |
3 | + * | |
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | |
5 | + * you may not use this file except in compliance with the License. | |
6 | + * You may obtain a copy of the License at | |
7 | + * | |
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | |
9 | + * | |
10 | + * Unless required by applicable law or agreed to in writing, software | |
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | |
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 | + * See the License for the specific language governing permissions and | |
14 | + * limitations under the License. | |
15 | + */ | |
16 | +package org.thingsboard.server.transport.coap.telemetry.timeseries; | |
17 | + | |
18 | +import com.github.os72.protobuf.dynamic.DynamicSchema; | |
19 | +import com.google.protobuf.Descriptors; | |
20 | +import com.google.protobuf.DynamicMessage; | |
21 | +import com.squareup.wire.schema.internal.parser.ProtoFileElement; | |
22 | +import lombok.extern.slf4j.Slf4j; | |
23 | +import org.junit.After; | |
24 | +import org.junit.Test; | |
25 | +import org.thingsboard.server.common.data.CoapDeviceType; | |
26 | +import org.thingsboard.server.common.data.DeviceProfileProvisionType; | |
27 | +import org.thingsboard.server.common.data.TransportPayloadType; | |
28 | +import org.thingsboard.server.common.data.device.profile.CoapDeviceProfileTransportConfiguration; | |
29 | +import org.thingsboard.server.common.data.device.profile.CoapDeviceTypeConfiguration; | |
30 | +import org.thingsboard.server.common.data.device.profile.DefaultCoapDeviceTypeConfiguration; | |
31 | +import org.thingsboard.server.common.data.device.profile.DeviceProfileTransportConfiguration; | |
32 | +import org.thingsboard.server.common.data.device.profile.ProtoTransportPayloadConfiguration; | |
33 | +import org.thingsboard.server.common.data.device.profile.TransportPayloadTypeConfiguration; | |
34 | + | |
35 | +import static org.junit.Assert.assertNotNull; | |
36 | +import static org.junit.Assert.assertTrue; | |
37 | + | |
38 | +@Slf4j | |
39 | +public abstract class AbstractCoapTimeseriesProtoIntegrationTest extends AbstractCoapTimeseriesIntegrationTest { | |
40 | + | |
41 | + @After | |
42 | + public void afterTest() throws Exception { | |
43 | + processAfterTest(); | |
44 | + } | |
45 | + | |
46 | + @Test | |
47 | + public void testPushTelemetry() throws Exception { | |
48 | + super.processBeforeTest("Test Post Telemetry device proto payload", CoapDeviceType.DEFAULT, TransportPayloadType.PROTOBUF); | |
49 | + DeviceProfileTransportConfiguration transportConfiguration = deviceProfile.getProfileData().getTransportConfiguration(); | |
50 | + assertTrue(transportConfiguration instanceof CoapDeviceProfileTransportConfiguration); | |
51 | + CoapDeviceProfileTransportConfiguration coapDeviceProfileTransportConfiguration = (CoapDeviceProfileTransportConfiguration) transportConfiguration; | |
52 | + CoapDeviceTypeConfiguration coapDeviceTypeConfiguration = coapDeviceProfileTransportConfiguration.getCoapDeviceTypeConfiguration(); | |
53 | + assertTrue(coapDeviceTypeConfiguration instanceof DefaultCoapDeviceTypeConfiguration); | |
54 | + DefaultCoapDeviceTypeConfiguration defaultCoapDeviceTypeConfiguration = (DefaultCoapDeviceTypeConfiguration) coapDeviceTypeConfiguration; | |
55 | + TransportPayloadTypeConfiguration transportPayloadTypeConfiguration = defaultCoapDeviceTypeConfiguration.getTransportPayloadTypeConfiguration(); | |
56 | + assertTrue(transportPayloadTypeConfiguration instanceof ProtoTransportPayloadConfiguration); | |
57 | + ProtoTransportPayloadConfiguration protoTransportPayloadConfiguration = (ProtoTransportPayloadConfiguration) transportPayloadTypeConfiguration; | |
58 | + ProtoFileElement transportProtoSchema = protoTransportPayloadConfiguration.getTransportProtoSchema(DEVICE_TELEMETRY_PROTO_SCHEMA); | |
59 | + DynamicSchema telemetrySchema = protoTransportPayloadConfiguration.getDynamicSchema(transportProtoSchema, "telemetrySchema"); | |
60 | + | |
61 | + DynamicMessage.Builder nestedJsonObjectBuilder = telemetrySchema.newMessageBuilder("PostTelemetry.JsonObject.NestedJsonObject"); | |
62 | + Descriptors.Descriptor nestedJsonObjectBuilderDescriptor = nestedJsonObjectBuilder.getDescriptorForType(); | |
63 | + assertNotNull(nestedJsonObjectBuilderDescriptor); | |
64 | + DynamicMessage nestedJsonObject = nestedJsonObjectBuilder.setField(nestedJsonObjectBuilderDescriptor.findFieldByName("key"), "value").build(); | |
65 | + | |
66 | + DynamicMessage.Builder jsonObjectBuilder = telemetrySchema.newMessageBuilder("PostTelemetry.JsonObject"); | |
67 | + Descriptors.Descriptor jsonObjectBuilderDescriptor = jsonObjectBuilder.getDescriptorForType(); | |
68 | + assertNotNull(jsonObjectBuilderDescriptor); | |
69 | + DynamicMessage jsonObject = jsonObjectBuilder | |
70 | + .setField(jsonObjectBuilderDescriptor.findFieldByName("someNumber"), 42) | |
71 | + .addRepeatedField(jsonObjectBuilderDescriptor.findFieldByName("someArray"), 1) | |
72 | + .addRepeatedField(jsonObjectBuilderDescriptor.findFieldByName("someArray"), 2) | |
73 | + .addRepeatedField(jsonObjectBuilderDescriptor.findFieldByName("someArray"), 3) | |
74 | + .setField(jsonObjectBuilderDescriptor.findFieldByName("someNestedObject"), nestedJsonObject) | |
75 | + .build(); | |
76 | + | |
77 | + DynamicMessage.Builder postTelemetryBuilder = telemetrySchema.newMessageBuilder("PostTelemetry"); | |
78 | + Descriptors.Descriptor postTelemetryMsgDescriptor = postTelemetryBuilder.getDescriptorForType(); | |
79 | + assertNotNull(postTelemetryMsgDescriptor); | |
80 | + DynamicMessage postTelemetryMsg = postTelemetryBuilder | |
81 | + .setField(postTelemetryMsgDescriptor.findFieldByName("key1"), "value1") | |
82 | + .setField(postTelemetryMsgDescriptor.findFieldByName("key2"), true) | |
83 | + .setField(postTelemetryMsgDescriptor.findFieldByName("key3"), 3.0) | |
84 | + .setField(postTelemetryMsgDescriptor.findFieldByName("key4"), 4) | |
85 | + .setField(postTelemetryMsgDescriptor.findFieldByName("key5"), jsonObject) | |
86 | + .build(); | |
87 | + processTestPostTelemetry(postTelemetryMsg.toByteArray(), false); | |
88 | + } | |
89 | + | |
90 | + @Test | |
91 | + public void testPushTelemetryWithTs() throws Exception { | |
92 | + String schemaStr = "syntax =\"proto3\";\n" + | |
93 | + "\n" + | |
94 | + "package test;\n" + | |
95 | + "\n" + | |
96 | + "message PostTelemetry {\n" + | |
97 | + " int64 ts = 1;\n" + | |
98 | + " Values values = 2;\n" + | |
99 | + " \n" + | |
100 | + " message Values {\n" + | |
101 | + " string key1 = 3;\n" + | |
102 | + " bool key2 = 4;\n" + | |
103 | + " double key3 = 5;\n" + | |
104 | + " int32 key4 = 6;\n" + | |
105 | + " JsonObject key5 = 7;\n" + | |
106 | + " }\n" + | |
107 | + " \n" + | |
108 | + " message JsonObject {\n" + | |
109 | + " int32 someNumber = 8;\n" + | |
110 | + " repeated int32 someArray = 9;\n" + | |
111 | + " NestedJsonObject someNestedObject = 10;\n" + | |
112 | + " message NestedJsonObject {\n" + | |
113 | + " string key = 11;\n" + | |
114 | + " }\n" + | |
115 | + " }\n" + | |
116 | + "}"; | |
117 | + super.processBeforeTest("Test Post Telemetry device proto payload", CoapDeviceType.DEFAULT, TransportPayloadType.PROTOBUF, schemaStr, null, DeviceProfileProvisionType.DISABLED, null, null); | |
118 | + DeviceProfileTransportConfiguration transportConfiguration = deviceProfile.getProfileData().getTransportConfiguration(); | |
119 | + assertTrue(transportConfiguration instanceof CoapDeviceProfileTransportConfiguration); | |
120 | + CoapDeviceProfileTransportConfiguration coapDeviceProfileTransportConfiguration = (CoapDeviceProfileTransportConfiguration) transportConfiguration; | |
121 | + CoapDeviceTypeConfiguration coapDeviceTypeConfiguration = coapDeviceProfileTransportConfiguration.getCoapDeviceTypeConfiguration(); | |
122 | + assertTrue(coapDeviceTypeConfiguration instanceof DefaultCoapDeviceTypeConfiguration); | |
123 | + DefaultCoapDeviceTypeConfiguration defaultCoapDeviceTypeConfiguration = (DefaultCoapDeviceTypeConfiguration) coapDeviceTypeConfiguration; | |
124 | + TransportPayloadTypeConfiguration transportPayloadTypeConfiguration = defaultCoapDeviceTypeConfiguration.getTransportPayloadTypeConfiguration(); | |
125 | + assertTrue(transportPayloadTypeConfiguration instanceof ProtoTransportPayloadConfiguration); | |
126 | + ProtoTransportPayloadConfiguration protoTransportPayloadConfiguration = (ProtoTransportPayloadConfiguration) transportPayloadTypeConfiguration; | |
127 | + ProtoFileElement transportProtoSchema = protoTransportPayloadConfiguration.getTransportProtoSchema(schemaStr); | |
128 | + DynamicSchema telemetrySchema = protoTransportPayloadConfiguration.getDynamicSchema(transportProtoSchema, "telemetrySchema"); | |
129 | + | |
130 | + DynamicMessage.Builder nestedJsonObjectBuilder = telemetrySchema.newMessageBuilder("PostTelemetry.JsonObject.NestedJsonObject"); | |
131 | + Descriptors.Descriptor nestedJsonObjectBuilderDescriptor = nestedJsonObjectBuilder.getDescriptorForType(); | |
132 | + assertNotNull(nestedJsonObjectBuilderDescriptor); | |
133 | + DynamicMessage nestedJsonObject = nestedJsonObjectBuilder.setField(nestedJsonObjectBuilderDescriptor.findFieldByName("key"), "value").build(); | |
134 | + | |
135 | + DynamicMessage.Builder jsonObjectBuilder = telemetrySchema.newMessageBuilder("PostTelemetry.JsonObject"); | |
136 | + Descriptors.Descriptor jsonObjectBuilderDescriptor = jsonObjectBuilder.getDescriptorForType(); | |
137 | + assertNotNull(jsonObjectBuilderDescriptor); | |
138 | + DynamicMessage jsonObject = jsonObjectBuilder | |
139 | + .setField(jsonObjectBuilderDescriptor.findFieldByName("someNumber"), 42) | |
140 | + .addRepeatedField(jsonObjectBuilderDescriptor.findFieldByName("someArray"), 1) | |
141 | + .addRepeatedField(jsonObjectBuilderDescriptor.findFieldByName("someArray"), 2) | |
142 | + .addRepeatedField(jsonObjectBuilderDescriptor.findFieldByName("someArray"), 3) | |
143 | + .setField(jsonObjectBuilderDescriptor.findFieldByName("someNestedObject"), nestedJsonObject) | |
144 | + .build(); | |
145 | + | |
146 | + | |
147 | + DynamicMessage.Builder valuesBuilder = telemetrySchema.newMessageBuilder("PostTelemetry.Values"); | |
148 | + Descriptors.Descriptor valuesDescriptor = valuesBuilder.getDescriptorForType(); | |
149 | + assertNotNull(valuesDescriptor); | |
150 | + | |
151 | + DynamicMessage valuesMsg = valuesBuilder | |
152 | + .setField(valuesDescriptor.findFieldByName("key1"), "value1") | |
153 | + .setField(valuesDescriptor.findFieldByName("key2"), true) | |
154 | + .setField(valuesDescriptor.findFieldByName("key3"), 3.0) | |
155 | + .setField(valuesDescriptor.findFieldByName("key4"), 4) | |
156 | + .setField(valuesDescriptor.findFieldByName("key5"), jsonObject) | |
157 | + .build(); | |
158 | + | |
159 | + DynamicMessage.Builder postTelemetryBuilder = telemetrySchema.newMessageBuilder("PostTelemetry"); | |
160 | + Descriptors.Descriptor postTelemetryMsgDescriptor = postTelemetryBuilder.getDescriptorForType(); | |
161 | + assertNotNull(postTelemetryMsgDescriptor); | |
162 | + DynamicMessage postTelemetryMsg = postTelemetryBuilder | |
163 | + .setField(postTelemetryMsgDescriptor.findFieldByName("ts"), 10000L) | |
164 | + .setField(postTelemetryMsgDescriptor.findFieldByName("values"), valuesMsg) | |
165 | + .build(); | |
166 | + | |
167 | + processTestPostTelemetry(postTelemetryMsg.toByteArray(), true); | |
168 | + } | |
169 | + | |
170 | +} | ... | ... |
application/src/test/java/org/thingsboard/server/transport/coap/telemetry/timeseries/nosql/CoapTimeseriesNoSqlIntegrationTest.java
renamed from
application/src/test/java/org/thingsboard/server/mqtt/telemetry/attributes/nosql/MqttAttributesNoSqlIntegrationTest.java
... | ... | @@ -13,11 +13,11 @@ |
13 | 13 | * See the License for the specific language governing permissions and |
14 | 14 | * limitations under the License. |
15 | 15 | */ |
16 | -package org.thingsboard.server.mqtt.telemetry.attributes.nosql; | |
16 | +package org.thingsboard.server.transport.coap.telemetry.timeseries.nosql; | |
17 | 17 | |
18 | +import org.thingsboard.server.transport.coap.telemetry.timeseries.AbstractCoapTimeseriesIntegrationTest; | |
18 | 19 | import org.thingsboard.server.dao.service.DaoNoSqlTest; |
19 | -import org.thingsboard.server.mqtt.telemetry.attributes.AbstractMqttAttributesIntegrationTest; | |
20 | 20 | |
21 | 21 | @DaoNoSqlTest |
22 | -public class MqttAttributesNoSqlIntegrationTest extends AbstractMqttAttributesIntegrationTest { | |
22 | +public class CoapTimeseriesNoSqlIntegrationTest extends AbstractCoapTimeseriesIntegrationTest { | |
23 | 23 | } | ... | ... |
application/src/test/java/org/thingsboard/server/transport/coap/telemetry/timeseries/nosql/CoapTimeseriesNoSqlJsonIntegrationTest.java
renamed from
application/src/test/java/org/thingsboard/server/mqtt/telemetry/attributes/nosql/MqttAttributesNoSqlJsonIntegrationTest.java
... | ... | @@ -13,11 +13,11 @@ |
13 | 13 | * See the License for the specific language governing permissions and |
14 | 14 | * limitations under the License. |
15 | 15 | */ |
16 | -package org.thingsboard.server.mqtt.telemetry.attributes.nosql; | |
16 | +package org.thingsboard.server.transport.coap.telemetry.timeseries.nosql; | |
17 | 17 | |
18 | +import org.thingsboard.server.transport.coap.telemetry.timeseries.AbstractCoapTimeseriesJsonIntegrationTest; | |
18 | 19 | import org.thingsboard.server.dao.service.DaoNoSqlTest; |
19 | -import org.thingsboard.server.mqtt.telemetry.attributes.AbstractMqttAttributesJsonIntegrationTest; | |
20 | 20 | |
21 | 21 | @DaoNoSqlTest |
22 | -public class MqttAttributesNoSqlJsonIntegrationTest extends AbstractMqttAttributesJsonIntegrationTest { | |
22 | +public class CoapTimeseriesNoSqlJsonIntegrationTest extends AbstractCoapTimeseriesJsonIntegrationTest { | |
23 | 23 | } | ... | ... |
application/src/test/java/org/thingsboard/server/transport/coap/telemetry/timeseries/nosql/CoapTimeseriesNoSqlProtoIntegrationTest.java
renamed from
application/src/test/java/org/thingsboard/server/mqtt/claim/nosql/MqttClaimDeviceNoSqlTest.java
... | ... | @@ -13,12 +13,11 @@ |
13 | 13 | * See the License for the specific language governing permissions and |
14 | 14 | * limitations under the License. |
15 | 15 | */ |
16 | -package org.thingsboard.server.mqtt.claim.nosql; | |
16 | +package org.thingsboard.server.transport.coap.telemetry.timeseries.nosql; | |
17 | 17 | |
18 | +import org.thingsboard.server.transport.coap.telemetry.timeseries.AbstractCoapTimeseriesProtoIntegrationTest; | |
18 | 19 | import org.thingsboard.server.dao.service.DaoNoSqlTest; |
19 | -import org.thingsboard.server.mqtt.claim.AbstractMqttClaimDeviceTest; | |
20 | - | |
21 | 20 | |
22 | 21 | @DaoNoSqlTest |
23 | -public class MqttClaimDeviceNoSqlTest extends AbstractMqttClaimDeviceTest { | |
22 | +public class CoapTimeseriesNoSqlProtoIntegrationTest extends AbstractCoapTimeseriesProtoIntegrationTest { | |
24 | 23 | } | ... | ... |
1 | +/** | |
2 | + * Copyright © 2016-2021 The Thingsboard Authors | |
3 | + * | |
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | |
5 | + * you may not use this file except in compliance with the License. | |
6 | + * You may obtain a copy of the License at | |
7 | + * | |
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | |
9 | + * | |
10 | + * Unless required by applicable law or agreed to in writing, software | |
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | |
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 | + * See the License for the specific language governing permissions and | |
14 | + * limitations under the License. | |
15 | + */ | |
16 | +package org.thingsboard.server.transport.coap.telemetry.timeseries.sql; | |
17 | + | |
18 | +import org.thingsboard.server.transport.coap.telemetry.timeseries.AbstractCoapTimeseriesIntegrationTest; | |
19 | +import org.thingsboard.server.dao.service.DaoSqlTest; | |
20 | + | |
21 | +/** | |
22 | + * Created by Valerii Sosliuk on 8/22/2017. | |
23 | + */ | |
24 | +@DaoSqlTest | |
25 | +public class CoapTimeseriesSqlIntegrationTest extends AbstractCoapTimeseriesIntegrationTest { | |
26 | +} | ... | ... |
1 | +/** | |
2 | + * Copyright © 2016-2021 The Thingsboard Authors | |
3 | + * | |
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | |
5 | + * you may not use this file except in compliance with the License. | |
6 | + * You may obtain a copy of the License at | |
7 | + * | |
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | |
9 | + * | |
10 | + * Unless required by applicable law or agreed to in writing, software | |
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | |
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 | + * See the License for the specific language governing permissions and | |
14 | + * limitations under the License. | |
15 | + */ | |
16 | +package org.thingsboard.server.transport.coap.telemetry.timeseries.sql; | |
17 | + | |
18 | +import org.thingsboard.server.transport.coap.telemetry.timeseries.AbstractCoapTimeseriesJsonIntegrationTest; | |
19 | +import org.thingsboard.server.dao.service.DaoSqlTest; | |
20 | + | |
21 | +/** | |
22 | + * Created by Valerii Sosliuk on 8/22/2017. | |
23 | + */ | |
24 | +@DaoSqlTest | |
25 | +public class CoapTimeseriesSqlJsonIntegrationTest extends AbstractCoapTimeseriesJsonIntegrationTest { | |
26 | +} | ... | ... |
1 | +/** | |
2 | + * Copyright © 2016-2021 The Thingsboard Authors | |
3 | + * | |
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | |
5 | + * you may not use this file except in compliance with the License. | |
6 | + * You may obtain a copy of the License at | |
7 | + * | |
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | |
9 | + * | |
10 | + * Unless required by applicable law or agreed to in writing, software | |
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | |
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 | + * See the License for the specific language governing permissions and | |
14 | + * limitations under the License. | |
15 | + */ | |
16 | +package org.thingsboard.server.transport.coap.telemetry.timeseries.sql; | |
17 | + | |
18 | +import org.thingsboard.server.transport.coap.telemetry.timeseries.AbstractCoapTimeseriesProtoIntegrationTest; | |
19 | +import org.thingsboard.server.dao.service.DaoSqlTest; | |
20 | + | |
21 | +/** | |
22 | + * Created by Valerii Sosliuk on 8/22/2017. | |
23 | + */ | |
24 | +@DaoSqlTest | |
25 | +public class CoapTimeseriesSqlProtoIntegrationTest extends AbstractCoapTimeseriesProtoIntegrationTest { | |
26 | +} | ... | ... |
application/src/test/java/org/thingsboard/server/transport/mqtt/AbstractMqttIntegrationTest.java
0 → 100644
1 | +/** | |
2 | + * Copyright © 2016-2021 The Thingsboard Authors | |
3 | + * | |
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | |
5 | + * you may not use this file except in compliance with the License. | |
6 | + * You may obtain a copy of the License at | |
7 | + * | |
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | |
9 | + * | |
10 | + * Unless required by applicable law or agreed to in writing, software | |
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | |
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 | + * See the License for the specific language governing permissions and | |
14 | + * limitations under the License. | |
15 | + */ | |
16 | +package org.thingsboard.server.transport.mqtt; | |
17 | + | |
18 | +import com.fasterxml.jackson.databind.node.ObjectNode; | |
19 | +import lombok.extern.slf4j.Slf4j; | |
20 | +import org.eclipse.paho.client.mqttv3.MqttAsyncClient; | |
21 | +import org.eclipse.paho.client.mqttv3.MqttConnectOptions; | |
22 | +import org.eclipse.paho.client.mqttv3.MqttException; | |
23 | +import org.eclipse.paho.client.mqttv3.MqttMessage; | |
24 | +import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence; | |
25 | +import org.junit.Assert; | |
26 | +import org.springframework.util.StringUtils; | |
27 | +import org.thingsboard.server.common.data.Device; | |
28 | +import org.thingsboard.server.common.data.DeviceProfile; | |
29 | +import org.thingsboard.server.common.data.DeviceProfileProvisionType; | |
30 | +import org.thingsboard.server.common.data.DeviceProfileType; | |
31 | +import org.thingsboard.server.common.data.DeviceTransportType; | |
32 | +import org.thingsboard.server.common.data.Tenant; | |
33 | +import org.thingsboard.server.common.data.TransportPayloadType; | |
34 | +import org.thingsboard.server.common.data.User; | |
35 | +import org.thingsboard.server.common.data.device.profile.AllowCreateNewDevicesDeviceProfileProvisionConfiguration; | |
36 | +import org.thingsboard.server.common.data.device.profile.CheckPreProvisionedDevicesDeviceProfileProvisionConfiguration; | |
37 | +import org.thingsboard.server.common.data.device.profile.DefaultDeviceProfileConfiguration; | |
38 | +import org.thingsboard.server.common.data.device.profile.DeviceProfileData; | |
39 | +import org.thingsboard.server.common.data.device.profile.DeviceProfileProvisionConfiguration; | |
40 | +import org.thingsboard.server.common.data.device.profile.DisabledDeviceProfileProvisionConfiguration; | |
41 | +import org.thingsboard.server.common.data.device.profile.JsonTransportPayloadConfiguration; | |
42 | +import org.thingsboard.server.common.data.device.profile.MqttDeviceProfileTransportConfiguration; | |
43 | +import org.thingsboard.server.common.data.device.profile.ProtoTransportPayloadConfiguration; | |
44 | +import org.thingsboard.server.common.data.device.profile.TransportPayloadTypeConfiguration; | |
45 | +import org.thingsboard.server.common.data.security.Authority; | |
46 | +import org.thingsboard.server.common.data.security.DeviceCredentials; | |
47 | +import org.thingsboard.server.gen.transport.TransportProtos; | |
48 | +import org.thingsboard.server.transport.AbstractTransportIntegrationTest; | |
49 | + | |
50 | +import java.util.List; | |
51 | + | |
52 | +import static org.junit.Assert.assertEquals; | |
53 | +import static org.junit.Assert.assertNotNull; | |
54 | +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; | |
55 | + | |
56 | +@Slf4j | |
57 | +public abstract class AbstractMqttIntegrationTest extends AbstractTransportIntegrationTest { | |
58 | + | |
59 | + protected Device savedGateway; | |
60 | + protected String gatewayAccessToken; | |
61 | + | |
62 | + protected DeviceProfile deviceProfile; | |
63 | + | |
64 | + protected void processBeforeTest (String deviceName, String gatewayName, TransportPayloadType payloadType, String telemetryTopic, String attributesTopic) throws Exception { | |
65 | + this.processBeforeTest(deviceName, gatewayName, payloadType, telemetryTopic, attributesTopic, null, null, DeviceProfileProvisionType.DISABLED, null, null); | |
66 | + } | |
67 | + | |
68 | + protected void processBeforeTest(String deviceName, | |
69 | + String gatewayName, | |
70 | + TransportPayloadType payloadType, | |
71 | + String telemetryTopic, | |
72 | + String attributesTopic, | |
73 | + String telemetryProtoSchema, | |
74 | + String attributesProtoSchema, | |
75 | + DeviceProfileProvisionType provisionType, | |
76 | + String provisionKey, String provisionSecret | |
77 | + ) throws Exception { | |
78 | + loginSysAdmin(); | |
79 | + | |
80 | + Tenant tenant = new Tenant(); | |
81 | + tenant.setTitle("My tenant"); | |
82 | + savedTenant = doPost("/api/tenant", tenant, Tenant.class); | |
83 | + Assert.assertNotNull(savedTenant); | |
84 | + | |
85 | + tenantAdmin = new User(); | |
86 | + tenantAdmin.setAuthority(Authority.TENANT_ADMIN); | |
87 | + tenantAdmin.setTenantId(savedTenant.getId()); | |
88 | + tenantAdmin.setEmail("tenant" + atomicInteger.getAndIncrement() + "@thingsboard.org"); | |
89 | + tenantAdmin.setFirstName("Joe"); | |
90 | + tenantAdmin.setLastName("Downs"); | |
91 | + | |
92 | + tenantAdmin = createUserAndLogin(tenantAdmin, "testPassword1"); | |
93 | + | |
94 | + Device device = new Device(); | |
95 | + device.setName(deviceName); | |
96 | + device.setType("default"); | |
97 | + | |
98 | + Device gateway = new Device(); | |
99 | + gateway.setName(gatewayName); | |
100 | + gateway.setType("default"); | |
101 | + ObjectNode additionalInfo = mapper.createObjectNode(); | |
102 | + additionalInfo.put("gateway", true); | |
103 | + gateway.setAdditionalInfo(additionalInfo); | |
104 | + | |
105 | + if (payloadType != null) { | |
106 | + DeviceProfile mqttDeviceProfile = createMqttDeviceProfile(payloadType, telemetryTopic, attributesTopic, telemetryProtoSchema, attributesProtoSchema, provisionType, provisionKey, provisionSecret); | |
107 | + deviceProfile = doPost("/api/deviceProfile", mqttDeviceProfile, DeviceProfile.class); | |
108 | + device.setType(deviceProfile.getName()); | |
109 | + device.setDeviceProfileId(deviceProfile.getId()); | |
110 | + gateway.setType(deviceProfile.getName()); | |
111 | + gateway.setDeviceProfileId(deviceProfile.getId()); | |
112 | + } | |
113 | + | |
114 | + savedDevice = doPost("/api/device", device, Device.class); | |
115 | + | |
116 | + DeviceCredentials deviceCredentials = | |
117 | + doGet("/api/device/" + savedDevice.getId().getId().toString() + "/credentials", DeviceCredentials.class); | |
118 | + | |
119 | + savedGateway = doPost("/api/device", gateway, Device.class); | |
120 | + | |
121 | + DeviceCredentials gatewayCredentials = | |
122 | + doGet("/api/device/" + savedGateway.getId().getId().toString() + "/credentials", DeviceCredentials.class); | |
123 | + | |
124 | + assertEquals(savedDevice.getId(), deviceCredentials.getDeviceId()); | |
125 | + accessToken = deviceCredentials.getCredentialsId(); | |
126 | + assertNotNull(accessToken); | |
127 | + | |
128 | + assertEquals(savedGateway.getId(), gatewayCredentials.getDeviceId()); | |
129 | + gatewayAccessToken = gatewayCredentials.getCredentialsId(); | |
130 | + assertNotNull(gatewayAccessToken); | |
131 | + | |
132 | + } | |
133 | + | |
134 | + protected void processAfterTest() throws Exception { | |
135 | + loginSysAdmin(); | |
136 | + if (savedTenant != null) { | |
137 | + doDelete("/api/tenant/" + savedTenant.getId().getId().toString()).andExpect(status().isOk()); | |
138 | + } | |
139 | + } | |
140 | + | |
141 | + protected MqttAsyncClient getMqttAsyncClient(String accessToken) throws MqttException { | |
142 | + String clientId = MqttAsyncClient.generateClientId(); | |
143 | + MqttAsyncClient client = new MqttAsyncClient(MQTT_URL, clientId, new MemoryPersistence()); | |
144 | + | |
145 | + MqttConnectOptions options = new MqttConnectOptions(); | |
146 | + options.setUserName(accessToken); | |
147 | + client.connect(options).waitForCompletion(); | |
148 | + return client; | |
149 | + } | |
150 | + | |
151 | + protected void publishMqttMsg(MqttAsyncClient client, byte[] payload, String topic) throws MqttException { | |
152 | + MqttMessage message = new MqttMessage(); | |
153 | + message.setPayload(payload); | |
154 | + client.publish(topic, message); | |
155 | + } | |
156 | + | |
157 | + protected DeviceProfile createMqttDeviceProfile(TransportPayloadType transportPayloadType, | |
158 | + String telemetryTopic, String attributesTopic, | |
159 | + String telemetryProtoSchema, String attributesProtoSchema, | |
160 | + DeviceProfileProvisionType provisionType, | |
161 | + String provisionKey, String provisionSecret) { | |
162 | + DeviceProfile deviceProfile = new DeviceProfile(); | |
163 | + deviceProfile.setName(transportPayloadType.name()); | |
164 | + deviceProfile.setType(DeviceProfileType.DEFAULT); | |
165 | + deviceProfile.setTransportType(DeviceTransportType.MQTT); | |
166 | + deviceProfile.setProvisionType(provisionType); | |
167 | + deviceProfile.setProvisionDeviceKey(provisionKey); | |
168 | + deviceProfile.setDescription(transportPayloadType.name() + " Test"); | |
169 | + DeviceProfileData deviceProfileData = new DeviceProfileData(); | |
170 | + DefaultDeviceProfileConfiguration configuration = new DefaultDeviceProfileConfiguration(); | |
171 | + MqttDeviceProfileTransportConfiguration mqttDeviceProfileTransportConfiguration = new MqttDeviceProfileTransportConfiguration(); | |
172 | + if (!StringUtils.isEmpty(telemetryTopic)) { | |
173 | + mqttDeviceProfileTransportConfiguration.setDeviceTelemetryTopic(telemetryTopic); | |
174 | + } | |
175 | + if (!StringUtils.isEmpty(attributesTopic)) { | |
176 | + mqttDeviceProfileTransportConfiguration.setDeviceAttributesTopic(attributesTopic); | |
177 | + } | |
178 | + TransportPayloadTypeConfiguration transportPayloadTypeConfiguration; | |
179 | + if (TransportPayloadType.JSON.equals(transportPayloadType)) { | |
180 | + transportPayloadTypeConfiguration = new JsonTransportPayloadConfiguration(); | |
181 | + } else { | |
182 | + ProtoTransportPayloadConfiguration protoTransportPayloadConfiguration = new ProtoTransportPayloadConfiguration(); | |
183 | + if (StringUtils.isEmpty(telemetryProtoSchema)) { | |
184 | + telemetryProtoSchema = DEVICE_TELEMETRY_PROTO_SCHEMA; | |
185 | + } | |
186 | + if (StringUtils.isEmpty(attributesProtoSchema)) { | |
187 | + attributesProtoSchema = DEVICE_ATTRIBUTES_PROTO_SCHEMA; | |
188 | + } | |
189 | + protoTransportPayloadConfiguration.setDeviceTelemetryProtoSchema(telemetryProtoSchema); | |
190 | + protoTransportPayloadConfiguration.setDeviceAttributesProtoSchema(attributesProtoSchema); | |
191 | + transportPayloadTypeConfiguration = protoTransportPayloadConfiguration; | |
192 | + } | |
193 | + mqttDeviceProfileTransportConfiguration.setTransportPayloadTypeConfiguration(transportPayloadTypeConfiguration); | |
194 | + deviceProfileData.setTransportConfiguration(mqttDeviceProfileTransportConfiguration); | |
195 | + DeviceProfileProvisionConfiguration provisionConfiguration; | |
196 | + switch (provisionType) { | |
197 | + case ALLOW_CREATE_NEW_DEVICES: | |
198 | + provisionConfiguration = new AllowCreateNewDevicesDeviceProfileProvisionConfiguration(provisionSecret); | |
199 | + break; | |
200 | + case CHECK_PRE_PROVISIONED_DEVICES: | |
201 | + provisionConfiguration = new CheckPreProvisionedDevicesDeviceProfileProvisionConfiguration(provisionSecret); | |
202 | + break; | |
203 | + case DISABLED: | |
204 | + default: | |
205 | + provisionConfiguration = new DisabledDeviceProfileProvisionConfiguration(provisionSecret); | |
206 | + break; | |
207 | + } | |
208 | + deviceProfileData.setProvisionConfiguration(provisionConfiguration); | |
209 | + deviceProfileData.setConfiguration(configuration); | |
210 | + deviceProfile.setProfileData(deviceProfileData); | |
211 | + deviceProfile.setDefault(false); | |
212 | + deviceProfile.setDefaultRuleChainId(null); | |
213 | + return deviceProfile; | |
214 | + } | |
215 | + | |
216 | + protected TransportProtos.PostAttributeMsg getPostAttributeMsg(List<String> expectedKeys) { | |
217 | + List<TransportProtos.KeyValueProto> kvProtos = getKvProtos(expectedKeys); | |
218 | + TransportProtos.PostAttributeMsg.Builder builder = TransportProtos.PostAttributeMsg.newBuilder(); | |
219 | + builder.addAllKv(kvProtos); | |
220 | + return builder.build(); | |
221 | + } | |
222 | +} | ... | ... |
application/src/test/java/org/thingsboard/server/transport/mqtt/attributes/AbstractMqttAttributesIntegrationTest.java
renamed from
application/src/test/java/org/thingsboard/server/mqtt/attributes/AbstractMqttAttributesIntegrationTest.java
... | ... | @@ -13,7 +13,7 @@ |
13 | 13 | * See the License for the specific language governing permissions and |
14 | 14 | * limitations under the License. |
15 | 15 | */ |
16 | -package org.thingsboard.server.mqtt.attributes; | |
16 | +package org.thingsboard.server.transport.mqtt.attributes; | |
17 | 17 | |
18 | 18 | import lombok.extern.slf4j.Slf4j; |
19 | 19 | import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken; |
... | ... | @@ -21,7 +21,7 @@ import org.eclipse.paho.client.mqttv3.MqttCallback; |
21 | 21 | import org.eclipse.paho.client.mqttv3.MqttMessage; |
22 | 22 | import org.thingsboard.server.common.data.TransportPayloadType; |
23 | 23 | import org.thingsboard.server.gen.transport.TransportProtos; |
24 | -import org.thingsboard.server.mqtt.AbstractMqttIntegrationTest; | |
24 | +import org.thingsboard.server.transport.mqtt.AbstractMqttIntegrationTest; | |
25 | 25 | |
26 | 26 | import java.util.ArrayList; |
27 | 27 | import java.util.List; | ... | ... |
application/src/test/java/org/thingsboard/server/transport/mqtt/attributes/request/AbstractMqttAttributesRequestIntegrationTest.java
renamed from
application/src/test/java/org/thingsboard/server/mqtt/attributes/request/AbstractMqttAttributesRequestIntegrationTest.java
... | ... | @@ -13,7 +13,7 @@ |
13 | 13 | * See the License for the specific language governing permissions and |
14 | 14 | * limitations under the License. |
15 | 15 | */ |
16 | -package org.thingsboard.server.mqtt.attributes.request; | |
16 | +package org.thingsboard.server.transport.mqtt.attributes.request; | |
17 | 17 | |
18 | 18 | import com.google.protobuf.InvalidProtocolBufferException; |
19 | 19 | import io.netty.handler.codec.mqtt.MqttQoS; |
... | ... | @@ -27,7 +27,7 @@ import org.junit.Test; |
27 | 27 | import org.thingsboard.server.common.data.Device; |
28 | 28 | import org.thingsboard.server.common.data.device.profile.MqttTopics; |
29 | 29 | import org.thingsboard.server.dao.util.mapping.JacksonUtil; |
30 | -import org.thingsboard.server.mqtt.attributes.AbstractMqttAttributesIntegrationTest; | |
30 | +import org.thingsboard.server.transport.mqtt.attributes.AbstractMqttAttributesIntegrationTest; | |
31 | 31 | |
32 | 32 | import java.nio.charset.StandardCharsets; |
33 | 33 | import java.util.concurrent.CountDownLatch; | ... | ... |
application/src/test/java/org/thingsboard/server/transport/mqtt/attributes/request/AbstractMqttAttributesRequestJsonIntegrationTest.java
renamed from
application/src/test/java/org/thingsboard/server/mqtt/attributes/request/AbstractMqttAttributesRequestJsonIntegrationTest.java
... | ... | @@ -13,7 +13,7 @@ |
13 | 13 | * See the License for the specific language governing permissions and |
14 | 14 | * limitations under the License. |
15 | 15 | */ |
16 | -package org.thingsboard.server.mqtt.attributes.request; | |
16 | +package org.thingsboard.server.transport.mqtt.attributes.request; | |
17 | 17 | |
18 | 18 | import lombok.extern.slf4j.Slf4j; |
19 | 19 | import org.junit.After; | ... | ... |
application/src/test/java/org/thingsboard/server/transport/mqtt/attributes/request/AbstractMqttAttributesRequestProtoIntegrationTest.java
renamed from
application/src/test/java/org/thingsboard/server/mqtt/attributes/request/AbstractMqttAttributesRequestProtoIntegrationTest.java
... | ... | @@ -13,7 +13,7 @@ |
13 | 13 | * See the License for the specific language governing permissions and |
14 | 14 | * limitations under the License. |
15 | 15 | */ |
16 | -package org.thingsboard.server.mqtt.attributes.request; | |
16 | +package org.thingsboard.server.transport.mqtt.attributes.request; | |
17 | 17 | |
18 | 18 | import com.github.os72.protobuf.dynamic.DynamicSchema; |
19 | 19 | import com.google.protobuf.Descriptors; |
... | ... | @@ -37,6 +37,7 @@ import org.thingsboard.server.common.data.device.profile.MqttTopics; |
37 | 37 | import org.thingsboard.server.common.data.device.profile.TransportPayloadTypeConfiguration; |
38 | 38 | import org.thingsboard.server.gen.transport.TransportApiProtos; |
39 | 39 | import org.thingsboard.server.gen.transport.TransportProtos; |
40 | +import org.thingsboard.server.transport.mqtt.attributes.AbstractMqttAttributesIntegrationTest; | |
40 | 41 | |
41 | 42 | import java.util.ArrayList; |
42 | 43 | import java.util.Arrays; |
... | ... | @@ -93,7 +94,7 @@ public abstract class AbstractMqttAttributesRequestProtoIntegrationTest extends |
93 | 94 | } |
94 | 95 | |
95 | 96 | protected void postAttributesAndSubscribeToTopic(Device savedDevice, MqttAsyncClient client) throws Exception { |
96 | - doPostAsync("/api/plugins/telemetry/DEVICE/" + savedDevice.getId().getId() + "/attributes/SHARED_SCOPE", POST_ATTRIBUTES_PAYLOAD, String.class, status().isOk()); | |
97 | + doPostAsync("/api/plugins/telemetry/DEVICE/" + savedDevice.getId().getId() + "/attributes/SHARED_SCOPE", AbstractMqttAttributesIntegrationTest.POST_ATTRIBUTES_PAYLOAD, String.class, status().isOk()); | |
97 | 98 | DeviceProfileTransportConfiguration transportConfiguration = deviceProfile.getProfileData().getTransportConfiguration(); |
98 | 99 | assertTrue(transportConfiguration instanceof MqttDeviceProfileTransportConfiguration); |
99 | 100 | MqttDeviceProfileTransportConfiguration mqttTransportConfiguration = (MqttDeviceProfileTransportConfiguration) transportConfiguration; |
... | ... | @@ -148,7 +149,7 @@ public abstract class AbstractMqttAttributesRequestProtoIntegrationTest extends |
148 | 149 | client.publish(MqttTopics.GATEWAY_ATTRIBUTES_TOPIC, new MqttMessage(bytes)); |
149 | 150 | } |
150 | 151 | |
151 | - protected void validateResponse(MqttAsyncClient client, CountDownLatch latch, TestMqttCallback callback) throws MqttException, InterruptedException, InvalidProtocolBufferException { | |
152 | + protected void validateResponse(MqttAsyncClient client, CountDownLatch latch, AbstractMqttAttributesIntegrationTest.TestMqttCallback callback) throws MqttException, InterruptedException, InvalidProtocolBufferException { | |
152 | 153 | String keys = "attribute1,attribute2,attribute3,attribute4,attribute5"; |
153 | 154 | TransportApiProtos.AttributesRequest.Builder attributesRequestBuilder = TransportApiProtos.AttributesRequest.newBuilder(); |
154 | 155 | attributesRequestBuilder.setClientKeys(keys); |
... | ... | @@ -170,7 +171,7 @@ public abstract class AbstractMqttAttributesRequestProtoIntegrationTest extends |
170 | 171 | assertTrue(actualSharedKeyValueProtos.containsAll(expectedSharedKeyValueProtos)); |
171 | 172 | } |
172 | 173 | |
173 | - protected void validateClientResponseGateway(MqttAsyncClient client, TestMqttCallback callback) throws MqttException, InterruptedException, InvalidProtocolBufferException { | |
174 | + protected void validateClientResponseGateway(MqttAsyncClient client, AbstractMqttAttributesIntegrationTest.TestMqttCallback callback) throws MqttException, InterruptedException, InvalidProtocolBufferException { | |
174 | 175 | String keys = "attribute1,attribute2,attribute3,attribute4,attribute5"; |
175 | 176 | TransportApiProtos.GatewayAttributesRequestMsg gatewayAttributesRequestMsg = getGatewayAttributesRequestMsg(keys, true); |
176 | 177 | client.publish(MqttTopics.GATEWAY_ATTRIBUTES_REQUEST_TOPIC, new MqttMessage(gatewayAttributesRequestMsg.toByteArray())); |
... | ... | @@ -189,7 +190,7 @@ public abstract class AbstractMqttAttributesRequestProtoIntegrationTest extends |
189 | 190 | assertTrue(actualClientKeyValueProtos.containsAll(expectedClientKeyValueProtos)); |
190 | 191 | } |
191 | 192 | |
192 | - protected void validateSharedResponseGateway(MqttAsyncClient client, TestMqttCallback callback) throws MqttException, InterruptedException, InvalidProtocolBufferException { | |
193 | + protected void validateSharedResponseGateway(MqttAsyncClient client, AbstractMqttAttributesIntegrationTest.TestMqttCallback callback) throws MqttException, InterruptedException, InvalidProtocolBufferException { | |
193 | 194 | String keys = "attribute1,attribute2,attribute3,attribute4,attribute5"; |
194 | 195 | TransportApiProtos.GatewayAttributesRequestMsg gatewayAttributesRequestMsg = getGatewayAttributesRequestMsg(keys, false); |
195 | 196 | client.publish(MqttTopics.GATEWAY_ATTRIBUTES_REQUEST_TOPIC, new MqttMessage(gatewayAttributesRequestMsg.toByteArray())); | ... | ... |
application/src/test/java/org/thingsboard/server/transport/mqtt/attributes/request/sql/MqttAttributesRequestJsonSqlIntegrationTest.java
renamed from
application/src/test/java/org/thingsboard/server/mqtt/attributes/request/sql/MqttAttributesRequestJsonSqlIntegrationTest.java
... | ... | @@ -13,10 +13,10 @@ |
13 | 13 | * See the License for the specific language governing permissions and |
14 | 14 | * limitations under the License. |
15 | 15 | */ |
16 | -package org.thingsboard.server.mqtt.attributes.request.sql; | |
16 | +package org.thingsboard.server.transport.mqtt.attributes.request.sql; | |
17 | 17 | |
18 | 18 | import org.thingsboard.server.dao.service.DaoSqlTest; |
19 | -import org.thingsboard.server.mqtt.attributes.request.AbstractMqttAttributesRequestJsonIntegrationTest; | |
19 | +import org.thingsboard.server.transport.mqtt.attributes.request.AbstractMqttAttributesRequestJsonIntegrationTest; | |
20 | 20 | |
21 | 21 | @DaoSqlTest |
22 | 22 | public class MqttAttributesRequestJsonSqlIntegrationTest extends AbstractMqttAttributesRequestJsonIntegrationTest { | ... | ... |
application/src/test/java/org/thingsboard/server/transport/mqtt/attributes/request/sql/MqttAttributesRequestProtoSqlIntegrationTest.java
renamed from
application/src/test/java/org/thingsboard/server/mqtt/attributes/request/sql/MqttAttributesRequestProtoSqlIntegrationTest.java
... | ... | @@ -13,10 +13,10 @@ |
13 | 13 | * See the License for the specific language governing permissions and |
14 | 14 | * limitations under the License. |
15 | 15 | */ |
16 | -package org.thingsboard.server.mqtt.attributes.request.sql; | |
16 | +package org.thingsboard.server.transport.mqtt.attributes.request.sql; | |
17 | 17 | |
18 | 18 | import org.thingsboard.server.dao.service.DaoSqlTest; |
19 | -import org.thingsboard.server.mqtt.attributes.request.AbstractMqttAttributesRequestProtoIntegrationTest; | |
19 | +import org.thingsboard.server.transport.mqtt.attributes.request.AbstractMqttAttributesRequestProtoIntegrationTest; | |
20 | 20 | |
21 | 21 | @DaoSqlTest |
22 | 22 | public class MqttAttributesRequestProtoSqlIntegrationTest extends AbstractMqttAttributesRequestProtoIntegrationTest { | ... | ... |
application/src/test/java/org/thingsboard/server/transport/mqtt/attributes/request/sql/MqttAttributesRequestSqlIntegrationTest.java
renamed from
application/src/test/java/org/thingsboard/server/mqtt/attributes/request/sql/MqttAttributesRequestSqlIntegrationTest.java
... | ... | @@ -13,10 +13,10 @@ |
13 | 13 | * See the License for the specific language governing permissions and |
14 | 14 | * limitations under the License. |
15 | 15 | */ |
16 | -package org.thingsboard.server.mqtt.attributes.request.sql; | |
16 | +package org.thingsboard.server.transport.mqtt.attributes.request.sql; | |
17 | 17 | |
18 | 18 | import org.thingsboard.server.dao.service.DaoSqlTest; |
19 | -import org.thingsboard.server.mqtt.attributes.request.AbstractMqttAttributesRequestIntegrationTest; | |
19 | +import org.thingsboard.server.transport.mqtt.attributes.request.AbstractMqttAttributesRequestIntegrationTest; | |
20 | 20 | |
21 | 21 | @DaoSqlTest |
22 | 22 | public class MqttAttributesRequestSqlIntegrationTest extends AbstractMqttAttributesRequestIntegrationTest { | ... | ... |
application/src/test/java/org/thingsboard/server/transport/mqtt/attributes/updates/AbstractMqttAttributesUpdatesIntegrationTest.java
renamed from
application/src/test/java/org/thingsboard/server/mqtt/attributes/updates/AbstractMqttAttributesUpdatesIntegrationTest.java
... | ... | @@ -13,7 +13,7 @@ |
13 | 13 | * See the License for the specific language governing permissions and |
14 | 14 | * limitations under the License. |
15 | 15 | */ |
16 | -package org.thingsboard.server.mqtt.attributes.updates; | |
16 | +package org.thingsboard.server.transport.mqtt.attributes.updates; | |
17 | 17 | |
18 | 18 | import com.google.protobuf.InvalidProtocolBufferException; |
19 | 19 | import io.netty.handler.codec.mqtt.MqttQoS; |
... | ... | @@ -26,7 +26,7 @@ import org.thingsboard.server.common.data.Device; |
26 | 26 | import org.thingsboard.server.common.data.TransportPayloadType; |
27 | 27 | import org.thingsboard.server.common.data.device.profile.MqttTopics; |
28 | 28 | import org.thingsboard.server.dao.util.mapping.JacksonUtil; |
29 | -import org.thingsboard.server.mqtt.attributes.AbstractMqttAttributesIntegrationTest; | |
29 | +import org.thingsboard.server.transport.mqtt.attributes.AbstractMqttAttributesIntegrationTest; | |
30 | 30 | |
31 | 31 | import java.nio.charset.StandardCharsets; |
32 | 32 | import java.util.concurrent.TimeUnit; | ... | ... |
application/src/test/java/org/thingsboard/server/transport/mqtt/attributes/updates/AbstractMqttAttributesUpdatesJsonIntegrationTest.java
renamed from
application/src/test/java/org/thingsboard/server/mqtt/attributes/updates/AbstractMqttAttributesUpdatesJsonIntegrationTest.java
... | ... | @@ -13,7 +13,7 @@ |
13 | 13 | * See the License for the specific language governing permissions and |
14 | 14 | * limitations under the License. |
15 | 15 | */ |
16 | -package org.thingsboard.server.mqtt.attributes.updates; | |
16 | +package org.thingsboard.server.transport.mqtt.attributes.updates; | |
17 | 17 | |
18 | 18 | import lombok.extern.slf4j.Slf4j; |
19 | 19 | import org.junit.After; | ... | ... |
application/src/test/java/org/thingsboard/server/transport/mqtt/attributes/updates/AbstractMqttAttributesUpdatesProtoIntegrationTest.java
renamed from
application/src/test/java/org/thingsboard/server/mqtt/attributes/updates/AbstractMqttAttributesUpdatesProtoIntegrationTest.java
... | ... | @@ -13,7 +13,7 @@ |
13 | 13 | * See the License for the specific language governing permissions and |
14 | 14 | * limitations under the License. |
15 | 15 | */ |
16 | -package org.thingsboard.server.mqtt.attributes.updates; | |
16 | +package org.thingsboard.server.transport.mqtt.attributes.updates; | |
17 | 17 | |
18 | 18 | import com.google.protobuf.InvalidProtocolBufferException; |
19 | 19 | import lombok.extern.slf4j.Slf4j; | ... | ... |
application/src/test/java/org/thingsboard/server/transport/mqtt/attributes/updates/sql/MqttAttributesUpdatesSqlIntegrationTest.java
renamed from
application/src/test/java/org/thingsboard/server/mqtt/attributes/updates/sql/MqttAttributesUpdatesSqlIntegrationTest.java
... | ... | @@ -13,10 +13,10 @@ |
13 | 13 | * See the License for the specific language governing permissions and |
14 | 14 | * limitations under the License. |
15 | 15 | */ |
16 | -package org.thingsboard.server.mqtt.attributes.updates.sql; | |
16 | +package org.thingsboard.server.transport.mqtt.attributes.updates.sql; | |
17 | 17 | |
18 | 18 | import org.thingsboard.server.dao.service.DaoSqlTest; |
19 | -import org.thingsboard.server.mqtt.attributes.updates.AbstractMqttAttributesUpdatesIntegrationTest; | |
19 | +import org.thingsboard.server.transport.mqtt.attributes.updates.AbstractMqttAttributesUpdatesIntegrationTest; | |
20 | 20 | |
21 | 21 | @DaoSqlTest |
22 | 22 | public class MqttAttributesUpdatesSqlIntegrationTest extends AbstractMqttAttributesUpdatesIntegrationTest { | ... | ... |
application/src/test/java/org/thingsboard/server/transport/mqtt/attributes/updates/sql/MqttAttributesUpdatesSqlJsonIntegrationTest.java
renamed from
application/src/test/java/org/thingsboard/server/mqtt/attributes/updates/sql/MqttAttributesUpdatesSqlJsonIntegrationTest.java
... | ... | @@ -13,10 +13,10 @@ |
13 | 13 | * See the License for the specific language governing permissions and |
14 | 14 | * limitations under the License. |
15 | 15 | */ |
16 | -package org.thingsboard.server.mqtt.attributes.updates.sql; | |
16 | +package org.thingsboard.server.transport.mqtt.attributes.updates.sql; | |
17 | 17 | |
18 | 18 | import org.thingsboard.server.dao.service.DaoSqlTest; |
19 | -import org.thingsboard.server.mqtt.attributes.updates.AbstractMqttAttributesUpdatesJsonIntegrationTest; | |
19 | +import org.thingsboard.server.transport.mqtt.attributes.updates.AbstractMqttAttributesUpdatesJsonIntegrationTest; | |
20 | 20 | |
21 | 21 | @DaoSqlTest |
22 | 22 | public class MqttAttributesUpdatesSqlJsonIntegrationTest extends AbstractMqttAttributesUpdatesJsonIntegrationTest { | ... | ... |
application/src/test/java/org/thingsboard/server/transport/mqtt/attributes/updates/sql/MqttAttributesUpdatesSqlProtoIntegrationTest.java
renamed from
application/src/test/java/org/thingsboard/server/mqtt/attributes/updates/sql/MqttAttributesUpdatesSqlProtoIntegrationTest.java
... | ... | @@ -13,10 +13,10 @@ |
13 | 13 | * See the License for the specific language governing permissions and |
14 | 14 | * limitations under the License. |
15 | 15 | */ |
16 | -package org.thingsboard.server.mqtt.attributes.updates.sql; | |
16 | +package org.thingsboard.server.transport.mqtt.attributes.updates.sql; | |
17 | 17 | |
18 | 18 | import org.thingsboard.server.dao.service.DaoSqlTest; |
19 | -import org.thingsboard.server.mqtt.attributes.updates.AbstractMqttAttributesUpdatesProtoIntegrationTest; | |
19 | +import org.thingsboard.server.transport.mqtt.attributes.updates.AbstractMqttAttributesUpdatesProtoIntegrationTest; | |
20 | 20 | |
21 | 21 | @DaoSqlTest |
22 | 22 | public class MqttAttributesUpdatesSqlProtoIntegrationTest extends AbstractMqttAttributesUpdatesProtoIntegrationTest { | ... | ... |
application/src/test/java/org/thingsboard/server/transport/mqtt/claim/AbstractMqttClaimDeviceTest.java
renamed from
application/src/test/java/org/thingsboard/server/mqtt/claim/AbstractMqttClaimDeviceTest.java
... | ... | @@ -13,7 +13,7 @@ |
13 | 13 | * See the License for the specific language governing permissions and |
14 | 14 | * limitations under the License. |
15 | 15 | */ |
16 | -package org.thingsboard.server.mqtt.claim; | |
16 | +package org.thingsboard.server.transport.mqtt.claim; | |
17 | 17 | |
18 | 18 | import lombok.extern.slf4j.Slf4j; |
19 | 19 | import org.eclipse.paho.client.mqttv3.MqttAsyncClient; |
... | ... | @@ -29,7 +29,7 @@ import org.thingsboard.server.common.data.device.profile.MqttTopics; |
29 | 29 | import org.thingsboard.server.common.data.security.Authority; |
30 | 30 | import org.thingsboard.server.dao.device.claim.ClaimResponse; |
31 | 31 | import org.thingsboard.server.dao.device.claim.ClaimResult; |
32 | -import org.thingsboard.server.mqtt.AbstractMqttIntegrationTest; | |
32 | +import org.thingsboard.server.transport.mqtt.AbstractMqttIntegrationTest; | |
33 | 33 | |
34 | 34 | import static org.junit.Assert.assertEquals; |
35 | 35 | import static org.junit.Assert.assertNotNull; | ... | ... |
application/src/test/java/org/thingsboard/server/transport/mqtt/claim/AbstractMqttClaimJsonDeviceTest.java
renamed from
application/src/test/java/org/thingsboard/server/mqtt/claim/AbstractMqttClaimJsonDeviceTest.java
... | ... | @@ -13,7 +13,7 @@ |
13 | 13 | * See the License for the specific language governing permissions and |
14 | 14 | * limitations under the License. |
15 | 15 | */ |
16 | -package org.thingsboard.server.mqtt.claim; | |
16 | +package org.thingsboard.server.transport.mqtt.claim; | |
17 | 17 | |
18 | 18 | import lombok.extern.slf4j.Slf4j; |
19 | 19 | import org.junit.After; | ... | ... |
application/src/test/java/org/thingsboard/server/transport/mqtt/claim/AbstractMqttClaimProtoDeviceTest.java
renamed from
application/src/test/java/org/thingsboard/server/mqtt/claim/AbstractMqttClaimProtoDeviceTest.java
... | ... | @@ -13,7 +13,7 @@ |
13 | 13 | * See the License for the specific language governing permissions and |
14 | 14 | * limitations under the License. |
15 | 15 | */ |
16 | -package org.thingsboard.server.mqtt.claim; | |
16 | +package org.thingsboard.server.transport.mqtt.claim; | |
17 | 17 | |
18 | 18 | import lombok.extern.slf4j.Slf4j; |
19 | 19 | import org.eclipse.paho.client.mqttv3.MqttAsyncClient; | ... | ... |
application/src/test/java/org/thingsboard/server/transport/mqtt/claim/sql/MqttClaimDeviceJsonSqlTest.java
renamed from
application/src/test/java/org/thingsboard/server/mqtt/claim/sql/MqttClaimDeviceJsonSqlTest.java
... | ... | @@ -13,10 +13,10 @@ |
13 | 13 | * See the License for the specific language governing permissions and |
14 | 14 | * limitations under the License. |
15 | 15 | */ |
16 | -package org.thingsboard.server.mqtt.claim.sql; | |
16 | +package org.thingsboard.server.transport.mqtt.claim.sql; | |
17 | 17 | |
18 | 18 | import org.thingsboard.server.dao.service.DaoSqlTest; |
19 | -import org.thingsboard.server.mqtt.claim.AbstractMqttClaimJsonDeviceTest; | |
19 | +import org.thingsboard.server.transport.mqtt.claim.AbstractMqttClaimJsonDeviceTest; | |
20 | 20 | |
21 | 21 | @DaoSqlTest |
22 | 22 | public class MqttClaimDeviceJsonSqlTest extends AbstractMqttClaimJsonDeviceTest { | ... | ... |
application/src/test/java/org/thingsboard/server/transport/mqtt/claim/sql/MqttClaimDeviceProtoSqlTest.java
renamed from
application/src/test/java/org/thingsboard/server/mqtt/claim/sql/MqttClaimDeviceProtoSqlTest.java
... | ... | @@ -13,10 +13,10 @@ |
13 | 13 | * See the License for the specific language governing permissions and |
14 | 14 | * limitations under the License. |
15 | 15 | */ |
16 | -package org.thingsboard.server.mqtt.claim.sql; | |
16 | +package org.thingsboard.server.transport.mqtt.claim.sql; | |
17 | 17 | |
18 | 18 | import org.thingsboard.server.dao.service.DaoSqlTest; |
19 | -import org.thingsboard.server.mqtt.claim.AbstractMqttClaimProtoDeviceTest; | |
19 | +import org.thingsboard.server.transport.mqtt.claim.AbstractMqttClaimProtoDeviceTest; | |
20 | 20 | |
21 | 21 | @DaoSqlTest |
22 | 22 | public class MqttClaimDeviceProtoSqlTest extends AbstractMqttClaimProtoDeviceTest { | ... | ... |
application/src/test/java/org/thingsboard/server/transport/mqtt/claim/sql/MqttClaimDeviceSqlTest.java
renamed from
application/src/test/java/org/thingsboard/server/mqtt/claim/sql/MqttClaimDeviceSqlTest.java
... | ... | @@ -13,10 +13,10 @@ |
13 | 13 | * See the License for the specific language governing permissions and |
14 | 14 | * limitations under the License. |
15 | 15 | */ |
16 | -package org.thingsboard.server.mqtt.claim.sql; | |
16 | +package org.thingsboard.server.transport.mqtt.claim.sql; | |
17 | 17 | |
18 | 18 | import org.thingsboard.server.dao.service.DaoSqlTest; |
19 | -import org.thingsboard.server.mqtt.claim.AbstractMqttClaimDeviceTest; | |
19 | +import org.thingsboard.server.transport.mqtt.claim.AbstractMqttClaimDeviceTest; | |
20 | 20 | |
21 | 21 | @DaoSqlTest |
22 | 22 | public class MqttClaimDeviceSqlTest extends AbstractMqttClaimDeviceTest { | ... | ... |
application/src/test/java/org/thingsboard/server/transport/mqtt/provision/AbstractMqttProvisionJsonDeviceTest.java
renamed from
application/src/test/java/org/thingsboard/server/mqtt/provision/AbstractMqttProvisionJsonDeviceTest.java
... | ... | @@ -13,7 +13,7 @@ |
13 | 13 | * See the License for the specific language governing permissions and |
14 | 14 | * limitations under the License. |
15 | 15 | */ |
16 | -package org.thingsboard.server.mqtt.provision; | |
16 | +package org.thingsboard.server.transport.mqtt.provision; | |
17 | 17 | |
18 | 18 | import com.google.gson.JsonObject; |
19 | 19 | import io.netty.handler.codec.mqtt.MqttQoS; |
... | ... | @@ -38,7 +38,7 @@ import org.thingsboard.server.dao.device.DeviceCredentialsService; |
38 | 38 | import org.thingsboard.server.dao.device.DeviceService; |
39 | 39 | import org.thingsboard.server.dao.device.provision.ProvisionResponseStatus; |
40 | 40 | import org.thingsboard.server.dao.util.mapping.JacksonUtil; |
41 | -import org.thingsboard.server.mqtt.AbstractMqttIntegrationTest; | |
41 | +import org.thingsboard.server.transport.mqtt.AbstractMqttIntegrationTest; | |
42 | 42 | |
43 | 43 | import java.util.concurrent.CountDownLatch; |
44 | 44 | import java.util.concurrent.TimeUnit; | ... | ... |
application/src/test/java/org/thingsboard/server/transport/mqtt/provision/AbstractMqttProvisionProtoDeviceTest.java
renamed from
application/src/test/java/org/thingsboard/server/mqtt/provision/AbstractMqttProvisionProtoDeviceTest.java
... | ... | @@ -13,7 +13,7 @@ |
13 | 13 | * See the License for the specific language governing permissions and |
14 | 14 | * limitations under the License. |
15 | 15 | */ |
16 | -package org.thingsboard.server.mqtt.provision; | |
16 | +package org.thingsboard.server.transport.mqtt.provision; | |
17 | 17 | |
18 | 18 | import io.netty.handler.codec.mqtt.MqttQoS; |
19 | 19 | import lombok.extern.slf4j.Slf4j; |
... | ... | @@ -45,9 +45,8 @@ import org.thingsboard.server.gen.transport.TransportProtos.ProvisionDeviceRespo |
45 | 45 | import org.thingsboard.server.gen.transport.TransportProtos.ValidateBasicMqttCredRequestMsg; |
46 | 46 | import org.thingsboard.server.gen.transport.TransportProtos.ValidateDeviceTokenRequestMsg; |
47 | 47 | import org.thingsboard.server.gen.transport.TransportProtos.ValidateDeviceX509CertRequestMsg; |
48 | -import org.thingsboard.server.mqtt.AbstractMqttIntegrationTest; | |
48 | +import org.thingsboard.server.transport.mqtt.AbstractMqttIntegrationTest; | |
49 | 49 | |
50 | -import java.util.UUID; | |
51 | 50 | import java.util.concurrent.CountDownLatch; |
52 | 51 | import java.util.concurrent.TimeUnit; |
53 | 52 | ... | ... |
application/src/test/java/org/thingsboard/server/transport/mqtt/provision/sql/MqttProvisionDeviceJsonSqlTest.java
renamed from
application/src/test/java/org/thingsboard/server/mqtt/provision/sql/MqttProvisionDeviceJsonSqlTest.java
... | ... | @@ -13,10 +13,10 @@ |
13 | 13 | * See the License for the specific language governing permissions and |
14 | 14 | * limitations under the License. |
15 | 15 | */ |
16 | -package org.thingsboard.server.mqtt.provision.sql; | |
16 | +package org.thingsboard.server.transport.mqtt.provision.sql; | |
17 | 17 | |
18 | 18 | import org.thingsboard.server.dao.service.DaoSqlTest; |
19 | -import org.thingsboard.server.mqtt.provision.AbstractMqttProvisionJsonDeviceTest; | |
19 | +import org.thingsboard.server.transport.mqtt.provision.AbstractMqttProvisionJsonDeviceTest; | |
20 | 20 | |
21 | 21 | @DaoSqlTest |
22 | 22 | public class MqttProvisionDeviceJsonSqlTest extends AbstractMqttProvisionJsonDeviceTest { | ... | ... |
application/src/test/java/org/thingsboard/server/transport/mqtt/provision/sql/MqttProvisionDeviceProtoSqlTest.java
renamed from
application/src/test/java/org/thingsboard/server/mqtt/provision/sql/MqttProvisionDeviceProtoSqlTest.java
... | ... | @@ -13,10 +13,10 @@ |
13 | 13 | * See the License for the specific language governing permissions and |
14 | 14 | * limitations under the License. |
15 | 15 | */ |
16 | -package org.thingsboard.server.mqtt.provision.sql; | |
16 | +package org.thingsboard.server.transport.mqtt.provision.sql; | |
17 | 17 | |
18 | 18 | import org.thingsboard.server.dao.service.DaoSqlTest; |
19 | -import org.thingsboard.server.mqtt.provision.AbstractMqttProvisionProtoDeviceTest; | |
19 | +import org.thingsboard.server.transport.mqtt.provision.AbstractMqttProvisionProtoDeviceTest; | |
20 | 20 | |
21 | 21 | @DaoSqlTest |
22 | 22 | public class MqttProvisionDeviceProtoSqlTest extends AbstractMqttProvisionProtoDeviceTest { | ... | ... |
application/src/test/java/org/thingsboard/server/transport/mqtt/rpc/AbstractMqttServerSideRpcDefaultIntegrationTest.java
renamed from
application/src/test/java/org/thingsboard/server/mqtt/rpc/AbstractMqttServerSideRpcDefaultIntegrationTest.java
... | ... | @@ -13,7 +13,7 @@ |
13 | 13 | * See the License for the specific language governing permissions and |
14 | 14 | * limitations under the License. |
15 | 15 | */ |
16 | -package org.thingsboard.server.mqtt.rpc; | |
16 | +package org.thingsboard.server.transport.mqtt.rpc; | |
17 | 17 | |
18 | 18 | import com.datastax.oss.driver.api.core.uuid.Uuids; |
19 | 19 | import lombok.extern.slf4j.Slf4j; | ... | ... |
application/src/test/java/org/thingsboard/server/transport/mqtt/rpc/AbstractMqttServerSideRpcIntegrationTest.java
renamed from
application/src/test/java/org/thingsboard/server/mqtt/rpc/AbstractMqttServerSideRpcIntegrationTest.java
... | ... | @@ -13,7 +13,7 @@ |
13 | 13 | * See the License for the specific language governing permissions and |
14 | 14 | * limitations under the License. |
15 | 15 | */ |
16 | -package org.thingsboard.server.mqtt.rpc; | |
16 | +package org.thingsboard.server.transport.mqtt.rpc; | |
17 | 17 | |
18 | 18 | import com.fasterxml.jackson.databind.JsonNode; |
19 | 19 | import com.google.protobuf.InvalidProtocolBufferException; |
... | ... | @@ -31,7 +31,7 @@ import org.thingsboard.server.common.data.Device; |
31 | 31 | import org.thingsboard.server.common.data.TransportPayloadType; |
32 | 32 | import org.thingsboard.server.common.data.device.profile.MqttTopics; |
33 | 33 | import org.thingsboard.server.dao.util.mapping.JacksonUtil; |
34 | -import org.thingsboard.server.mqtt.AbstractMqttIntegrationTest; | |
34 | +import org.thingsboard.server.transport.mqtt.AbstractMqttIntegrationTest; | |
35 | 35 | |
36 | 36 | import java.util.Arrays; |
37 | 37 | import java.util.concurrent.CountDownLatch; | ... | ... |
application/src/test/java/org/thingsboard/server/transport/mqtt/rpc/AbstractMqttServerSideRpcJsonIntegrationTest.java
renamed from
application/src/test/java/org/thingsboard/server/mqtt/rpc/AbstractMqttServerSideRpcJsonIntegrationTest.java
... | ... | @@ -13,7 +13,7 @@ |
13 | 13 | * See the License for the specific language governing permissions and |
14 | 14 | * limitations under the License. |
15 | 15 | */ |
16 | -package org.thingsboard.server.mqtt.rpc; | |
16 | +package org.thingsboard.server.transport.mqtt.rpc; | |
17 | 17 | |
18 | 18 | import lombok.extern.slf4j.Slf4j; |
19 | 19 | import org.eclipse.paho.client.mqttv3.MqttAsyncClient; | ... | ... |
application/src/test/java/org/thingsboard/server/transport/mqtt/rpc/AbstractMqttServerSideRpcProtoIntegrationTest.java
renamed from
application/src/test/java/org/thingsboard/server/mqtt/rpc/AbstractMqttServerSideRpcProtoIntegrationTest.java
... | ... | @@ -13,7 +13,7 @@ |
13 | 13 | * See the License for the specific language governing permissions and |
14 | 14 | * limitations under the License. |
15 | 15 | */ |
16 | -package org.thingsboard.server.mqtt.rpc; | |
16 | +package org.thingsboard.server.transport.mqtt.rpc; | |
17 | 17 | |
18 | 18 | import com.google.protobuf.InvalidProtocolBufferException; |
19 | 19 | import lombok.extern.slf4j.Slf4j; | ... | ... |
application/src/test/java/org/thingsboard/server/transport/mqtt/rpc/sql/MqttServerSideRpcJsonSqlIntegrationTest.java
renamed from
application/src/test/java/org/thingsboard/server/mqtt/rpc/sql/MqttServerSideRpcJsonSqlIntegrationTest.java
... | ... | @@ -13,10 +13,10 @@ |
13 | 13 | * See the License for the specific language governing permissions and |
14 | 14 | * limitations under the License. |
15 | 15 | */ |
16 | -package org.thingsboard.server.mqtt.rpc.sql; | |
16 | +package org.thingsboard.server.transport.mqtt.rpc.sql; | |
17 | 17 | |
18 | 18 | import org.thingsboard.server.dao.service.DaoSqlTest; |
19 | -import org.thingsboard.server.mqtt.rpc.AbstractMqttServerSideRpcJsonIntegrationTest; | |
19 | +import org.thingsboard.server.transport.mqtt.rpc.AbstractMqttServerSideRpcJsonIntegrationTest; | |
20 | 20 | |
21 | 21 | @DaoSqlTest |
22 | 22 | public class MqttServerSideRpcJsonSqlIntegrationTest extends AbstractMqttServerSideRpcJsonIntegrationTest { | ... | ... |
application/src/test/java/org/thingsboard/server/transport/mqtt/rpc/sql/MqttServerSideRpcProtoSqlIntegrationTest.java
renamed from
application/src/test/java/org/thingsboard/server/mqtt/rpc/sql/MqttServerSideRpcProtoSqlIntegrationTest.java
... | ... | @@ -13,10 +13,10 @@ |
13 | 13 | * See the License for the specific language governing permissions and |
14 | 14 | * limitations under the License. |
15 | 15 | */ |
16 | -package org.thingsboard.server.mqtt.rpc.sql; | |
16 | +package org.thingsboard.server.transport.mqtt.rpc.sql; | |
17 | 17 | |
18 | 18 | import org.thingsboard.server.dao.service.DaoSqlTest; |
19 | -import org.thingsboard.server.mqtt.rpc.AbstractMqttServerSideRpcProtoIntegrationTest; | |
19 | +import org.thingsboard.server.transport.mqtt.rpc.AbstractMqttServerSideRpcProtoIntegrationTest; | |
20 | 20 | |
21 | 21 | |
22 | 22 | @DaoSqlTest | ... | ... |
application/src/test/java/org/thingsboard/server/transport/mqtt/rpc/sql/MqttServerSideRpcSqlIntegrationTest.java
renamed from
application/src/test/java/org/thingsboard/server/mqtt/rpc/sql/MqttServerSideRpcSqlIntegrationTest.java
... | ... | @@ -13,10 +13,10 @@ |
13 | 13 | * See the License for the specific language governing permissions and |
14 | 14 | * limitations under the License. |
15 | 15 | */ |
16 | -package org.thingsboard.server.mqtt.rpc.sql; | |
16 | +package org.thingsboard.server.transport.mqtt.rpc.sql; | |
17 | 17 | |
18 | 18 | import org.thingsboard.server.dao.service.DaoSqlTest; |
19 | -import org.thingsboard.server.mqtt.rpc.AbstractMqttServerSideRpcDefaultIntegrationTest; | |
19 | +import org.thingsboard.server.transport.mqtt.rpc.AbstractMqttServerSideRpcDefaultIntegrationTest; | |
20 | 20 | |
21 | 21 | /** |
22 | 22 | * Created by Valerii Sosliuk on 8/22/2017. | ... | ... |
application/src/test/java/org/thingsboard/server/transport/mqtt/telemetry/attributes/AbstractMqttAttributesIntegrationTest.java
renamed from
application/src/test/java/org/thingsboard/server/mqtt/telemetry/attributes/AbstractMqttAttributesIntegrationTest.java
... | ... | @@ -13,7 +13,7 @@ |
13 | 13 | * See the License for the specific language governing permissions and |
14 | 14 | * limitations under the License. |
15 | 15 | */ |
16 | -package org.thingsboard.server.mqtt.telemetry.attributes; | |
16 | +package org.thingsboard.server.transport.mqtt.telemetry.attributes; | |
17 | 17 | |
18 | 18 | import com.fasterxml.jackson.core.JsonProcessingException; |
19 | 19 | import com.fasterxml.jackson.core.type.TypeReference; |
... | ... | @@ -25,7 +25,7 @@ import org.junit.Test; |
25 | 25 | import org.thingsboard.server.common.data.Device; |
26 | 26 | import org.thingsboard.server.common.data.device.profile.MqttTopics; |
27 | 27 | import org.thingsboard.server.common.data.id.DeviceId; |
28 | -import org.thingsboard.server.mqtt.AbstractMqttIntegrationTest; | |
28 | +import org.thingsboard.server.transport.mqtt.AbstractMqttIntegrationTest; | |
29 | 29 | |
30 | 30 | import java.util.Arrays; |
31 | 31 | import java.util.HashSet; | ... | ... |
application/src/test/java/org/thingsboard/server/transport/mqtt/telemetry/attributes/AbstractMqttAttributesJsonIntegrationTest.java
renamed from
application/src/test/java/org/thingsboard/server/mqtt/telemetry/attributes/AbstractMqttAttributesJsonIntegrationTest.java
... | ... | @@ -13,7 +13,7 @@ |
13 | 13 | * See the License for the specific language governing permissions and |
14 | 14 | * limitations under the License. |
15 | 15 | */ |
16 | -package org.thingsboard.server.mqtt.telemetry.attributes; | |
16 | +package org.thingsboard.server.transport.mqtt.telemetry.attributes; | |
17 | 17 | |
18 | 18 | import lombok.extern.slf4j.Slf4j; |
19 | 19 | import org.junit.After; | ... | ... |
application/src/test/java/org/thingsboard/server/transport/mqtt/telemetry/attributes/AbstractMqttAttributesProtoIntegrationTest.java
renamed from
application/src/test/java/org/thingsboard/server/mqtt/telemetry/attributes/AbstractMqttAttributesProtoIntegrationTest.java
... | ... | @@ -13,7 +13,7 @@ |
13 | 13 | * See the License for the specific language governing permissions and |
14 | 14 | * limitations under the License. |
15 | 15 | */ |
16 | -package org.thingsboard.server.mqtt.telemetry.attributes; | |
16 | +package org.thingsboard.server.transport.mqtt.telemetry.attributes; | |
17 | 17 | |
18 | 18 | import com.github.os72.protobuf.dynamic.DynamicSchema; |
19 | 19 | import com.google.protobuf.Descriptors; | ... | ... |
application/src/test/java/org/thingsboard/server/transport/mqtt/telemetry/attributes/sql/MqttAttributesSqlIntegrationTest.java
renamed from
application/src/test/java/org/thingsboard/server/mqtt/telemetry/attributes/sql/MqttAttributesSqlIntegrationTest.java
... | ... | @@ -13,10 +13,10 @@ |
13 | 13 | * See the License for the specific language governing permissions and |
14 | 14 | * limitations under the License. |
15 | 15 | */ |
16 | -package org.thingsboard.server.mqtt.telemetry.attributes.sql; | |
16 | +package org.thingsboard.server.transport.mqtt.telemetry.attributes.sql; | |
17 | 17 | |
18 | 18 | import org.thingsboard.server.dao.service.DaoSqlTest; |
19 | -import org.thingsboard.server.mqtt.telemetry.attributes.AbstractMqttAttributesIntegrationTest; | |
19 | +import org.thingsboard.server.transport.mqtt.telemetry.attributes.AbstractMqttAttributesIntegrationTest; | |
20 | 20 | |
21 | 21 | @DaoSqlTest |
22 | 22 | public class MqttAttributesSqlIntegrationTest extends AbstractMqttAttributesIntegrationTest { | ... | ... |
application/src/test/java/org/thingsboard/server/transport/mqtt/telemetry/attributes/sql/MqttAttributesSqlJsonIntegrationTest.java
renamed from
application/src/test/java/org/thingsboard/server/mqtt/telemetry/attributes/sql/MqttAttributesSqlJsonIntegrationTest.java
... | ... | @@ -13,10 +13,10 @@ |
13 | 13 | * See the License for the specific language governing permissions and |
14 | 14 | * limitations under the License. |
15 | 15 | */ |
16 | -package org.thingsboard.server.mqtt.telemetry.attributes.sql; | |
16 | +package org.thingsboard.server.transport.mqtt.telemetry.attributes.sql; | |
17 | 17 | |
18 | 18 | import org.thingsboard.server.dao.service.DaoSqlTest; |
19 | -import org.thingsboard.server.mqtt.telemetry.attributes.AbstractMqttAttributesJsonIntegrationTest; | |
19 | +import org.thingsboard.server.transport.mqtt.telemetry.attributes.AbstractMqttAttributesJsonIntegrationTest; | |
20 | 20 | |
21 | 21 | @DaoSqlTest |
22 | 22 | public class MqttAttributesSqlJsonIntegrationTest extends AbstractMqttAttributesJsonIntegrationTest { | ... | ... |
application/src/test/java/org/thingsboard/server/transport/mqtt/telemetry/attributes/sql/MqttAttributesSqlProtoIntegrationTest.java
renamed from
application/src/test/java/org/thingsboard/server/mqtt/telemetry/attributes/sql/MqttAttributesSqlProtoIntegrationTest.java
... | ... | @@ -13,10 +13,10 @@ |
13 | 13 | * See the License for the specific language governing permissions and |
14 | 14 | * limitations under the License. |
15 | 15 | */ |
16 | -package org.thingsboard.server.mqtt.telemetry.attributes.sql; | |
16 | +package org.thingsboard.server.transport.mqtt.telemetry.attributes.sql; | |
17 | 17 | |
18 | 18 | import org.thingsboard.server.dao.service.DaoSqlTest; |
19 | -import org.thingsboard.server.mqtt.telemetry.attributes.AbstractMqttAttributesProtoIntegrationTest; | |
19 | +import org.thingsboard.server.transport.mqtt.telemetry.attributes.AbstractMqttAttributesProtoIntegrationTest; | |
20 | 20 | |
21 | 21 | @DaoSqlTest |
22 | 22 | public class MqttAttributesSqlProtoIntegrationTest extends AbstractMqttAttributesProtoIntegrationTest { | ... | ... |
application/src/test/java/org/thingsboard/server/transport/mqtt/telemetry/timeseries/AbstractMqttTimeseriesIntegrationTest.java
renamed from
application/src/test/java/org/thingsboard/server/mqtt/telemetry/timeseries/AbstractMqttTimeseriesIntegrationTest.java
... | ... | @@ -13,7 +13,7 @@ |
13 | 13 | * See the License for the specific language governing permissions and |
14 | 14 | * limitations under the License. |
15 | 15 | */ |
16 | -package org.thingsboard.server.mqtt.telemetry.timeseries; | |
16 | +package org.thingsboard.server.transport.mqtt.telemetry.timeseries; | |
17 | 17 | |
18 | 18 | import com.fasterxml.jackson.core.type.TypeReference; |
19 | 19 | import io.netty.handler.codec.mqtt.MqttQoS; |
... | ... | @@ -26,12 +26,11 @@ import org.eclipse.paho.client.mqttv3.MqttMessage; |
26 | 26 | import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence; |
27 | 27 | import org.junit.After; |
28 | 28 | import org.junit.Before; |
29 | -import org.junit.Ignore; | |
30 | 29 | import org.junit.Test; |
31 | 30 | import org.thingsboard.server.common.data.Device; |
32 | 31 | import org.thingsboard.server.common.data.device.profile.MqttTopics; |
33 | 32 | import org.thingsboard.server.common.data.id.DeviceId; |
34 | -import org.thingsboard.server.mqtt.AbstractMqttIntegrationTest; | |
33 | +import org.thingsboard.server.transport.mqtt.AbstractMqttIntegrationTest; | |
35 | 34 | |
36 | 35 | import java.util.Arrays; |
37 | 36 | import java.util.HashSet; | ... | ... |
application/src/test/java/org/thingsboard/server/transport/mqtt/telemetry/timeseries/AbstractMqttTimeseriesJsonIntegrationTest.java
renamed from
application/src/test/java/org/thingsboard/server/mqtt/telemetry/timeseries/AbstractMqttTimeseriesJsonIntegrationTest.java
... | ... | @@ -13,7 +13,7 @@ |
13 | 13 | * See the License for the specific language governing permissions and |
14 | 14 | * limitations under the License. |
15 | 15 | */ |
16 | -package org.thingsboard.server.mqtt.telemetry.timeseries; | |
16 | +package org.thingsboard.server.transport.mqtt.telemetry.timeseries; | |
17 | 17 | |
18 | 18 | import lombok.extern.slf4j.Slf4j; |
19 | 19 | import org.eclipse.paho.client.mqttv3.MqttAsyncClient; | ... | ... |
application/src/test/java/org/thingsboard/server/transport/mqtt/telemetry/timeseries/AbstractMqttTimeseriesProtoIntegrationTest.java
renamed from
application/src/test/java/org/thingsboard/server/mqtt/telemetry/timeseries/AbstractMqttTimeseriesProtoIntegrationTest.java
... | ... | @@ -13,7 +13,7 @@ |
13 | 13 | * See the License for the specific language governing permissions and |
14 | 14 | * limitations under the License. |
15 | 15 | */ |
16 | -package org.thingsboard.server.mqtt.telemetry.timeseries; | |
16 | +package org.thingsboard.server.transport.mqtt.telemetry.timeseries; | |
17 | 17 | |
18 | 18 | import com.github.os72.protobuf.dynamic.DynamicSchema; |
19 | 19 | import com.google.protobuf.Descriptors; | ... | ... |
application/src/test/java/org/thingsboard/server/transport/mqtt/telemetry/timeseries/nosql/MqttTimeseriesNoSqlIntegrationTest.java
renamed from
application/src/test/java/org/thingsboard/server/mqtt/telemetry/timeseries/nosql/MqttTimeseriesNoSqlIntegrationTest.java
... | ... | @@ -13,10 +13,10 @@ |
13 | 13 | * See the License for the specific language governing permissions and |
14 | 14 | * limitations under the License. |
15 | 15 | */ |
16 | -package org.thingsboard.server.mqtt.telemetry.timeseries.nosql; | |
16 | +package org.thingsboard.server.transport.mqtt.telemetry.timeseries.nosql; | |
17 | 17 | |
18 | 18 | import org.thingsboard.server.dao.service.DaoNoSqlTest; |
19 | -import org.thingsboard.server.mqtt.telemetry.timeseries.AbstractMqttTimeseriesIntegrationTest; | |
19 | +import org.thingsboard.server.transport.mqtt.telemetry.timeseries.AbstractMqttTimeseriesIntegrationTest; | |
20 | 20 | |
21 | 21 | /** |
22 | 22 | * Created by Valerii Sosliuk on 8/22/2017. | ... | ... |
application/src/test/java/org/thingsboard/server/transport/mqtt/telemetry/timeseries/nosql/MqttTimeseriesNoSqlJsonIntegrationTest.java
renamed from
application/src/test/java/org/thingsboard/server/mqtt/telemetry/timeseries/nosql/MqttTimeseriesNoSqlJsonIntegrationTest.java
... | ... | @@ -13,10 +13,10 @@ |
13 | 13 | * See the License for the specific language governing permissions and |
14 | 14 | * limitations under the License. |
15 | 15 | */ |
16 | -package org.thingsboard.server.mqtt.telemetry.timeseries.nosql; | |
16 | +package org.thingsboard.server.transport.mqtt.telemetry.timeseries.nosql; | |
17 | 17 | |
18 | 18 | import org.thingsboard.server.dao.service.DaoNoSqlTest; |
19 | -import org.thingsboard.server.mqtt.telemetry.timeseries.AbstractMqttTimeseriesJsonIntegrationTest; | |
19 | +import org.thingsboard.server.transport.mqtt.telemetry.timeseries.AbstractMqttTimeseriesJsonIntegrationTest; | |
20 | 20 | |
21 | 21 | @DaoNoSqlTest |
22 | 22 | public class MqttTimeseriesNoSqlJsonIntegrationTest extends AbstractMqttTimeseriesJsonIntegrationTest { | ... | ... |
application/src/test/java/org/thingsboard/server/transport/mqtt/telemetry/timeseries/nosql/MqttTimeseriesNoSqlProtoIntegrationTest.java
renamed from
application/src/test/java/org/thingsboard/server/mqtt/telemetry/timeseries/nosql/MqttTimeseriesNoSqlProtoIntegrationTest.java
... | ... | @@ -13,10 +13,10 @@ |
13 | 13 | * See the License for the specific language governing permissions and |
14 | 14 | * limitations under the License. |
15 | 15 | */ |
16 | -package org.thingsboard.server.mqtt.telemetry.timeseries.nosql; | |
16 | +package org.thingsboard.server.transport.mqtt.telemetry.timeseries.nosql; | |
17 | 17 | |
18 | 18 | import org.thingsboard.server.dao.service.DaoNoSqlTest; |
19 | -import org.thingsboard.server.mqtt.telemetry.timeseries.AbstractMqttTimeseriesProtoIntegrationTest; | |
19 | +import org.thingsboard.server.transport.mqtt.telemetry.timeseries.AbstractMqttTimeseriesProtoIntegrationTest; | |
20 | 20 | |
21 | 21 | @DaoNoSqlTest |
22 | 22 | public class MqttTimeseriesNoSqlProtoIntegrationTest extends AbstractMqttTimeseriesProtoIntegrationTest { | ... | ... |
application/src/test/java/org/thingsboard/server/transport/mqtt/telemetry/timeseries/sql/MqttTimeseriesSqlIntegrationTest.java
renamed from
application/src/test/java/org/thingsboard/server/mqtt/telemetry/timeseries/sql/MqttTimeseriesSqlIntegrationTest.java
... | ... | @@ -13,10 +13,10 @@ |
13 | 13 | * See the License for the specific language governing permissions and |
14 | 14 | * limitations under the License. |
15 | 15 | */ |
16 | -package org.thingsboard.server.mqtt.telemetry.timeseries.sql; | |
16 | +package org.thingsboard.server.transport.mqtt.telemetry.timeseries.sql; | |
17 | 17 | |
18 | 18 | import org.thingsboard.server.dao.service.DaoSqlTest; |
19 | -import org.thingsboard.server.mqtt.telemetry.timeseries.AbstractMqttTimeseriesIntegrationTest; | |
19 | +import org.thingsboard.server.transport.mqtt.telemetry.timeseries.AbstractMqttTimeseriesIntegrationTest; | |
20 | 20 | |
21 | 21 | /** |
22 | 22 | * Created by Valerii Sosliuk on 8/22/2017. | ... | ... |
application/src/test/java/org/thingsboard/server/transport/mqtt/telemetry/timeseries/sql/MqttTimeseriesSqlJsonIntegrationTest.java
renamed from
application/src/test/java/org/thingsboard/server/mqtt/telemetry/timeseries/sql/MqttTimeseriesSqlJsonIntegrationTest.java
... | ... | @@ -13,10 +13,10 @@ |
13 | 13 | * See the License for the specific language governing permissions and |
14 | 14 | * limitations under the License. |
15 | 15 | */ |
16 | -package org.thingsboard.server.mqtt.telemetry.timeseries.sql; | |
16 | +package org.thingsboard.server.transport.mqtt.telemetry.timeseries.sql; | |
17 | 17 | |
18 | 18 | import org.thingsboard.server.dao.service.DaoSqlTest; |
19 | -import org.thingsboard.server.mqtt.telemetry.timeseries.AbstractMqttTimeseriesJsonIntegrationTest; | |
19 | +import org.thingsboard.server.transport.mqtt.telemetry.timeseries.AbstractMqttTimeseriesJsonIntegrationTest; | |
20 | 20 | |
21 | 21 | /** |
22 | 22 | * Created by Valerii Sosliuk on 8/22/2017. | ... | ... |
application/src/test/java/org/thingsboard/server/transport/mqtt/telemetry/timeseries/sql/MqttTimeseriesSqlProtoIntegrationTest.java
renamed from
application/src/test/java/org/thingsboard/server/mqtt/telemetry/timeseries/sql/MqttTimeseriesSqlProtoIntegrationTest.java
... | ... | @@ -13,10 +13,10 @@ |
13 | 13 | * See the License for the specific language governing permissions and |
14 | 14 | * limitations under the License. |
15 | 15 | */ |
16 | -package org.thingsboard.server.mqtt.telemetry.timeseries.sql; | |
16 | +package org.thingsboard.server.transport.mqtt.telemetry.timeseries.sql; | |
17 | 17 | |
18 | 18 | import org.thingsboard.server.dao.service.DaoSqlTest; |
19 | -import org.thingsboard.server.mqtt.telemetry.timeseries.AbstractMqttTimeseriesProtoIntegrationTest; | |
19 | +import org.thingsboard.server.transport.mqtt.telemetry.timeseries.AbstractMqttTimeseriesProtoIntegrationTest; | |
20 | 20 | |
21 | 21 | /** |
22 | 22 | * Created by Valerii Sosliuk on 8/22/2017. | ... | ... |
common/data/src/main/java/org/thingsboard/server/common/data/CoapDeviceType.java
renamed from
application/src/test/java/org/thingsboard/server/mqtt/attributes/request/nosql/MqttAttributesRequestNoSqlIntegrationTest.java
... | ... | @@ -13,12 +13,9 @@ |
13 | 13 | * See the License for the specific language governing permissions and |
14 | 14 | * limitations under the License. |
15 | 15 | */ |
16 | -package org.thingsboard.server.mqtt.attributes.request.nosql; | |
16 | +package org.thingsboard.server.common.data; | |
17 | 17 | |
18 | -import org.thingsboard.server.dao.service.DaoNoSqlTest; | |
19 | -import org.thingsboard.server.mqtt.attributes.request.AbstractMqttAttributesRequestIntegrationTest; | |
20 | - | |
21 | - | |
22 | -@DaoNoSqlTest | |
23 | -public class MqttAttributesRequestNoSqlIntegrationTest extends AbstractMqttAttributesRequestIntegrationTest { | |
18 | +public enum CoapDeviceType { | |
19 | + DEFAULT, | |
20 | + EFENTO | |
24 | 21 | } | ... | ... |
1 | +/** | |
2 | + * Copyright © 2016-2021 The Thingsboard Authors | |
3 | + * | |
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | |
5 | + * you may not use this file except in compliance with the License. | |
6 | + * You may obtain a copy of the License at | |
7 | + * | |
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | |
9 | + * | |
10 | + * Unless required by applicable law or agreed to in writing, software | |
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | |
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 | + * See the License for the specific language governing permissions and | |
14 | + * limitations under the License. | |
15 | + */ | |
16 | +package org.thingsboard.server.common.data.device.data; | |
17 | + | |
18 | +import com.fasterxml.jackson.annotation.JsonAnyGetter; | |
19 | +import com.fasterxml.jackson.annotation.JsonAnySetter; | |
20 | +import com.fasterxml.jackson.annotation.JsonIgnore; | |
21 | +import lombok.Data; | |
22 | +import org.thingsboard.server.common.data.DeviceTransportType; | |
23 | + | |
24 | +import java.util.HashMap; | |
25 | +import java.util.Map; | |
26 | + | |
27 | +@Data | |
28 | +public class CoapDeviceTransportConfiguration implements DeviceTransportConfiguration { | |
29 | + | |
30 | + @JsonIgnore | |
31 | + private Map<String, Object> properties = new HashMap<>(); | |
32 | + | |
33 | + @JsonAnyGetter | |
34 | + public Map<String, Object> properties() { | |
35 | + return this.properties; | |
36 | + } | |
37 | + | |
38 | + @JsonAnySetter | |
39 | + public void put(String name, Object value) { | |
40 | + this.properties.put(name, value); | |
41 | + } | |
42 | + | |
43 | + @Override | |
44 | + public DeviceTransportType getType() { | |
45 | + return DeviceTransportType.COAP; | |
46 | + } | |
47 | + | |
48 | +} | ... | ... |
... | ... | @@ -29,7 +29,8 @@ import org.thingsboard.server.common.data.DeviceTransportType; |
29 | 29 | @JsonSubTypes({ |
30 | 30 | @JsonSubTypes.Type(value = DefaultDeviceTransportConfiguration.class, name = "DEFAULT"), |
31 | 31 | @JsonSubTypes.Type(value = MqttDeviceTransportConfiguration.class, name = "MQTT"), |
32 | - @JsonSubTypes.Type(value = Lwm2mDeviceTransportConfiguration.class, name = "LWM2M")}) | |
32 | + @JsonSubTypes.Type(value = Lwm2mDeviceTransportConfiguration.class, name = "LWM2M"), | |
33 | + @JsonSubTypes.Type(value = CoapDeviceTransportConfiguration.class, name = "COAP")}) | |
33 | 34 | public interface DeviceTransportConfiguration { |
34 | 35 | |
35 | 36 | @JsonIgnore | ... | ... |
1 | +/** | |
2 | + * Copyright © 2016-2021 The Thingsboard Authors | |
3 | + * | |
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | |
5 | + * you may not use this file except in compliance with the License. | |
6 | + * You may obtain a copy of the License at | |
7 | + * | |
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | |
9 | + * | |
10 | + * Unless required by applicable law or agreed to in writing, software | |
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | |
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 | + * See the License for the specific language governing permissions and | |
14 | + * limitations under the License. | |
15 | + */ | |
16 | +package org.thingsboard.server.common.data.device.profile; | |
17 | + | |
18 | +import lombok.Data; | |
19 | +import org.thingsboard.server.common.data.DeviceTransportType; | |
20 | + | |
21 | +@Data | |
22 | +public class CoapDeviceProfileTransportConfiguration implements DeviceProfileTransportConfiguration { | |
23 | + | |
24 | + private CoapDeviceTypeConfiguration coapDeviceTypeConfiguration; | |
25 | + | |
26 | + @Override | |
27 | + public DeviceTransportType getType() { | |
28 | + return DeviceTransportType.COAP; | |
29 | + } | |
30 | + | |
31 | + public CoapDeviceTypeConfiguration getCoapDeviceTypeConfiguration() { | |
32 | + if (coapDeviceTypeConfiguration != null) { | |
33 | + return coapDeviceTypeConfiguration; | |
34 | + } else { | |
35 | + return new DefaultCoapDeviceTypeConfiguration(); | |
36 | + } | |
37 | + } | |
38 | +} | |
\ No newline at end of file | ... | ... |
1 | +/** | |
2 | + * Copyright © 2016-2021 The Thingsboard Authors | |
3 | + * | |
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | |
5 | + * you may not use this file except in compliance with the License. | |
6 | + * You may obtain a copy of the License at | |
7 | + * | |
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | |
9 | + * | |
10 | + * Unless required by applicable law or agreed to in writing, software | |
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | |
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 | + * See the License for the specific language governing permissions and | |
14 | + * limitations under the License. | |
15 | + */ | |
16 | +package org.thingsboard.server.common.data.device.profile; | |
17 | + | |
18 | +import com.fasterxml.jackson.annotation.JsonIgnore; | |
19 | +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; | |
20 | +import com.fasterxml.jackson.annotation.JsonSubTypes; | |
21 | +import com.fasterxml.jackson.annotation.JsonTypeInfo; | |
22 | +import org.thingsboard.server.common.data.CoapDeviceType; | |
23 | + | |
24 | +@JsonIgnoreProperties(ignoreUnknown = true) | |
25 | +@JsonTypeInfo( | |
26 | + use = JsonTypeInfo.Id.NAME, | |
27 | + include = JsonTypeInfo.As.PROPERTY, | |
28 | + property = "coapDeviceType") | |
29 | +@JsonSubTypes({ | |
30 | + @JsonSubTypes.Type(value = DefaultCoapDeviceTypeConfiguration.class, name = "DEFAULT"), | |
31 | + @JsonSubTypes.Type(value = EfentoCoapDeviceTypeConfiguration.class, name = "EFENTO")}) | |
32 | +public interface CoapDeviceTypeConfiguration { | |
33 | + | |
34 | + @JsonIgnore | |
35 | + CoapDeviceType getCoapDeviceType(); | |
36 | + | |
37 | +} | ... | ... |
1 | +/** | |
2 | + * Copyright © 2016-2021 The Thingsboard Authors | |
3 | + * | |
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | |
5 | + * you may not use this file except in compliance with the License. | |
6 | + * You may obtain a copy of the License at | |
7 | + * | |
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | |
9 | + * | |
10 | + * Unless required by applicable law or agreed to in writing, software | |
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | |
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 | + * See the License for the specific language governing permissions and | |
14 | + * limitations under the License. | |
15 | + */ | |
16 | +package org.thingsboard.server.common.data.device.profile; | |
17 | + | |
18 | +import lombok.Data; | |
19 | +import org.thingsboard.server.common.data.CoapDeviceType; | |
20 | + | |
21 | +@Data | |
22 | +public class DefaultCoapDeviceTypeConfiguration implements CoapDeviceTypeConfiguration { | |
23 | + | |
24 | + private TransportPayloadTypeConfiguration transportPayloadTypeConfiguration; | |
25 | + | |
26 | + @Override | |
27 | + public CoapDeviceType getCoapDeviceType() { | |
28 | + return CoapDeviceType.DEFAULT; | |
29 | + } | |
30 | + | |
31 | + public TransportPayloadTypeConfiguration getTransportPayloadTypeConfiguration() { | |
32 | + if (transportPayloadTypeConfiguration != null) { | |
33 | + return transportPayloadTypeConfiguration; | |
34 | + } else { | |
35 | + return new JsonTransportPayloadConfiguration(); | |
36 | + } | |
37 | + } | |
38 | + | |
39 | +} | ... | ... |
... | ... | @@ -30,7 +30,8 @@ import org.thingsboard.server.common.data.DeviceTransportType; |
30 | 30 | @JsonSubTypes({ |
31 | 31 | @JsonSubTypes.Type(value = DefaultDeviceProfileTransportConfiguration.class, name = "DEFAULT"), |
32 | 32 | @JsonSubTypes.Type(value = MqttDeviceProfileTransportConfiguration.class, name = "MQTT"), |
33 | - @JsonSubTypes.Type(value = Lwm2mDeviceProfileTransportConfiguration.class, name = "LWM2M")}) | |
33 | + @JsonSubTypes.Type(value = Lwm2mDeviceProfileTransportConfiguration.class, name = "LWM2M"), | |
34 | + @JsonSubTypes.Type(value = CoapDeviceProfileTransportConfiguration.class, name = "COAP")}) | |
34 | 35 | public interface DeviceProfileTransportConfiguration { |
35 | 36 | |
36 | 37 | @JsonIgnore | ... | ... |
common/data/src/main/java/org/thingsboard/server/common/data/device/profile/EfentoCoapDeviceTypeConfiguration.java
renamed from
application/src/test/java/org/thingsboard/server/mqtt/DbConfigurationTestRule.java
... | ... | @@ -13,19 +13,16 @@ |
13 | 13 | * See the License for the specific language governing permissions and |
14 | 14 | * limitations under the License. |
15 | 15 | */ |
16 | -package org.thingsboard.server.mqtt; | |
16 | +package org.thingsboard.server.common.data.device.profile; | |
17 | 17 | |
18 | -import org.junit.rules.TestRule; | |
19 | -import org.junit.runner.Description; | |
20 | -import org.junit.runners.model.Statement; | |
18 | +import lombok.Data; | |
19 | +import org.thingsboard.server.common.data.CoapDeviceType; | |
21 | 20 | |
22 | -/** | |
23 | - * Created by ashvayka on 11.05.18. | |
24 | - */ | |
25 | -public class DbConfigurationTestRule implements TestRule { | |
21 | +@Data | |
22 | +public class EfentoCoapDeviceTypeConfiguration implements CoapDeviceTypeConfiguration { | |
26 | 23 | |
27 | 24 | @Override |
28 | - public Statement apply(Statement base, Description description) { | |
29 | - return null; | |
25 | + public CoapDeviceType getCoapDeviceType() { | |
26 | + return CoapDeviceType.EFENTO; | |
30 | 27 | } |
31 | 28 | } | ... | ... |
... | ... | @@ -83,6 +83,19 @@ |
83 | 83 | <artifactId>mockito-core</artifactId> |
84 | 84 | <scope>test</scope> |
85 | 85 | </dependency> |
86 | + <dependency> | |
87 | + <groupId>com.google.protobuf</groupId> | |
88 | + <artifactId>protobuf-java</artifactId> | |
89 | + </dependency> | |
86 | 90 | </dependencies> |
87 | 91 | |
92 | + <build> | |
93 | + <plugins> | |
94 | + <plugin> | |
95 | + <groupId>org.xolstice.maven.plugins</groupId> | |
96 | + <artifactId>protobuf-maven-plugin</artifactId> | |
97 | + </plugin> | |
98 | + </plugins> | |
99 | + </build> | |
100 | + | |
88 | 101 | </project> | ... | ... |
1 | +/** | |
2 | + * Copyright © 2016-2021 The Thingsboard Authors | |
3 | + * | |
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | |
5 | + * you may not use this file except in compliance with the License. | |
6 | + * You may obtain a copy of the License at | |
7 | + * | |
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | |
9 | + * | |
10 | + * Unless required by applicable law or agreed to in writing, software | |
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | |
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 | + * See the License for the specific language governing permissions and | |
14 | + * limitations under the License. | |
15 | + */ | |
16 | +package org.thingsboard.server.transport.coap; | |
17 | + | |
18 | +import lombok.extern.slf4j.Slf4j; | |
19 | +import org.eclipse.californium.core.CoapResource; | |
20 | +import org.eclipse.californium.core.coap.CoAP; | |
21 | +import org.eclipse.californium.core.server.resources.CoapExchange; | |
22 | +import org.thingsboard.server.common.data.DeviceProfile; | |
23 | +import org.thingsboard.server.common.transport.TransportContext; | |
24 | +import org.thingsboard.server.common.transport.TransportService; | |
25 | +import org.thingsboard.server.common.transport.TransportServiceCallback; | |
26 | +import org.thingsboard.server.common.transport.auth.SessionInfoCreator; | |
27 | +import org.thingsboard.server.common.transport.auth.ValidateDeviceCredentialsResponse; | |
28 | +import org.thingsboard.server.gen.transport.TransportProtos; | |
29 | + | |
30 | +import java.util.UUID; | |
31 | +import java.util.function.BiConsumer; | |
32 | + | |
33 | +@Slf4j | |
34 | +public abstract class AbstractCoapTransportResource extends CoapResource { | |
35 | + | |
36 | + protected final CoapTransportContext transportContext; | |
37 | + protected final TransportService transportService; | |
38 | + | |
39 | + public AbstractCoapTransportResource(CoapTransportContext context, String name) { | |
40 | + super(name); | |
41 | + this.transportContext = context; | |
42 | + this.transportService = context.getTransportService(); | |
43 | + } | |
44 | + | |
45 | + @Override | |
46 | + public void handleGET(CoapExchange exchange) { | |
47 | + processHandleGet(exchange); | |
48 | + } | |
49 | + | |
50 | + @Override | |
51 | + public void handlePOST(CoapExchange exchange) { | |
52 | + processHandlePost(exchange); | |
53 | + } | |
54 | + | |
55 | + protected abstract void processHandleGet(CoapExchange exchange); | |
56 | + | |
57 | + protected abstract void processHandlePost(CoapExchange exchange); | |
58 | + | |
59 | + protected void reportActivity(TransportProtos.SessionInfoProto sessionInfo, boolean hasAttributeSubscription, boolean hasRpcSubscription) { | |
60 | + transportContext.getTransportService().process(sessionInfo, TransportProtos.SubscriptionInfoProto.newBuilder() | |
61 | + .setAttributeSubscription(hasAttributeSubscription) | |
62 | + .setRpcSubscription(hasRpcSubscription) | |
63 | + .setLastActivityTime(System.currentTimeMillis()) | |
64 | + .build(), TransportServiceCallback.EMPTY); | |
65 | + } | |
66 | + | |
67 | + protected static TransportProtos.SessionEventMsg getSessionEventMsg(TransportProtos.SessionEvent event) { | |
68 | + return TransportProtos.SessionEventMsg.newBuilder() | |
69 | + .setSessionType(TransportProtos.SessionType.ASYNC) | |
70 | + .setEvent(event).build(); | |
71 | + } | |
72 | + | |
73 | + public static class CoapDeviceAuthCallback implements TransportServiceCallback<ValidateDeviceCredentialsResponse> { | |
74 | + private final TransportContext transportContext; | |
75 | + private final CoapExchange exchange; | |
76 | + private final BiConsumer<TransportProtos.SessionInfoProto, DeviceProfile> onSuccess; | |
77 | + | |
78 | + public CoapDeviceAuthCallback(TransportContext transportContext, CoapExchange exchange, BiConsumer<TransportProtos.SessionInfoProto, DeviceProfile> onSuccess) { | |
79 | + this.transportContext = transportContext; | |
80 | + this.exchange = exchange; | |
81 | + this.onSuccess = onSuccess; | |
82 | + } | |
83 | + | |
84 | + @Override | |
85 | + public void onSuccess(ValidateDeviceCredentialsResponse msg) { | |
86 | + DeviceProfile deviceProfile = msg.getDeviceProfile(); | |
87 | + if (msg.hasDeviceInfo() && deviceProfile != null) { | |
88 | + TransportProtos.SessionInfoProto sessionInfoProto = SessionInfoCreator.create(msg, transportContext, UUID.randomUUID()); | |
89 | + onSuccess.accept(sessionInfoProto, deviceProfile); | |
90 | + } else { | |
91 | + exchange.respond(CoAP.ResponseCode.UNAUTHORIZED); | |
92 | + } | |
93 | + } | |
94 | + | |
95 | + @Override | |
96 | + public void onError(Throwable e) { | |
97 | + log.warn("Failed to process request", e); | |
98 | + exchange.respond(CoAP.ResponseCode.INTERNAL_SERVER_ERROR); | |
99 | + } | |
100 | + } | |
101 | + | |
102 | + public static class CoapOkCallback implements TransportServiceCallback<Void> { | |
103 | + private final CoapExchange exchange; | |
104 | + private final CoAP.ResponseCode onSuccessResponse; | |
105 | + private final CoAP.ResponseCode onFailureResponse; | |
106 | + | |
107 | + public CoapOkCallback(CoapExchange exchange, CoAP.ResponseCode onSuccessResponse, CoAP.ResponseCode onFailureResponse) { | |
108 | + this.exchange = exchange; | |
109 | + this.onSuccessResponse = onSuccessResponse; | |
110 | + this.onFailureResponse = onFailureResponse; | |
111 | + } | |
112 | + | |
113 | + @Override | |
114 | + public void onSuccess(Void msg) { | |
115 | + exchange.respond(onSuccessResponse); | |
116 | + } | |
117 | + | |
118 | + @Override | |
119 | + public void onError(Throwable e) { | |
120 | + exchange.respond(onFailureResponse); | |
121 | + } | |
122 | + } | |
123 | + | |
124 | + public static class CoapNoOpCallback implements TransportServiceCallback<Void> { | |
125 | + private final CoapExchange exchange; | |
126 | + | |
127 | + CoapNoOpCallback(CoapExchange exchange) { | |
128 | + this.exchange = exchange; | |
129 | + } | |
130 | + | |
131 | + @Override | |
132 | + public void onSuccess(Void msg) { | |
133 | + } | |
134 | + | |
135 | + @Override | |
136 | + public void onError(Throwable e) { | |
137 | + exchange.respond(CoAP.ResponseCode.INTERNAL_SERVER_ERROR); | |
138 | + } | |
139 | + } | |
140 | +} | ... | ... |
... | ... | @@ -22,7 +22,9 @@ import org.springframework.beans.factory.annotation.Value; |
22 | 22 | import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; |
23 | 23 | import org.springframework.stereotype.Component; |
24 | 24 | import org.thingsboard.server.common.transport.TransportContext; |
25 | -import org.thingsboard.server.transport.coap.adaptors.CoapTransportAdaptor; | |
25 | +import org.thingsboard.server.transport.coap.efento.adaptor.EfentoCoapAdaptor; | |
26 | +import org.thingsboard.server.transport.coap.adaptors.JsonCoapAdaptor; | |
27 | +import org.thingsboard.server.transport.coap.adaptors.ProtoCoapAdaptor; | |
26 | 28 | |
27 | 29 | /** |
28 | 30 | * Created by ashvayka on 18.10.18. |
... | ... | @@ -46,6 +48,14 @@ public class CoapTransportContext extends TransportContext { |
46 | 48 | |
47 | 49 | @Getter |
48 | 50 | @Autowired |
49 | - private CoapTransportAdaptor adaptor; | |
51 | + private JsonCoapAdaptor jsonCoapAdaptor; | |
52 | + | |
53 | + @Getter | |
54 | + @Autowired | |
55 | + private ProtoCoapAdaptor protoCoapAdaptor; | |
56 | + | |
57 | + @Getter | |
58 | + @Autowired | |
59 | + private EfentoCoapAdaptor efentoCoapAdaptor; | |
50 | 60 | |
51 | 61 | } | ... | ... |
common/transport/coap/src/main/java/org/thingsboard/server/transport/coap/CoapTransportResource.java
... | ... | @@ -15,32 +15,40 @@ |
15 | 15 | */ |
16 | 16 | package org.thingsboard.server.transport.coap; |
17 | 17 | |
18 | +import com.google.gson.JsonParseException; | |
19 | +import com.google.protobuf.Descriptors; | |
20 | +import lombok.Data; | |
18 | 21 | import lombok.extern.slf4j.Slf4j; |
19 | -import org.eclipse.californium.core.CoapResource; | |
20 | -import org.eclipse.californium.core.coap.CoAP.ResponseCode; | |
22 | +import org.eclipse.californium.core.coap.CoAP; | |
21 | 23 | import org.eclipse.californium.core.coap.Request; |
24 | +import org.eclipse.californium.core.coap.Response; | |
22 | 25 | import org.eclipse.californium.core.network.Exchange; |
23 | -import org.eclipse.californium.core.network.ExchangeObserver; | |
26 | +import org.eclipse.californium.core.observe.ObserveRelation; | |
24 | 27 | import org.eclipse.californium.core.server.resources.CoapExchange; |
25 | 28 | import org.eclipse.californium.core.server.resources.Resource; |
26 | -import org.springframework.util.ReflectionUtils; | |
29 | +import org.eclipse.californium.core.server.resources.ResourceObserver; | |
27 | 30 | import org.thingsboard.server.common.data.DataConstants; |
31 | +import org.thingsboard.server.common.data.DeviceProfile; | |
28 | 32 | import org.thingsboard.server.common.data.DeviceTransportType; |
33 | +import org.thingsboard.server.common.data.TransportPayloadType; | |
34 | +import org.thingsboard.server.common.data.device.profile.CoapDeviceProfileTransportConfiguration; | |
35 | +import org.thingsboard.server.common.data.device.profile.CoapDeviceTypeConfiguration; | |
36 | +import org.thingsboard.server.common.data.device.profile.DefaultCoapDeviceTypeConfiguration; | |
37 | +import org.thingsboard.server.common.data.device.profile.DefaultDeviceProfileTransportConfiguration; | |
38 | +import org.thingsboard.server.common.data.device.profile.DeviceProfileTransportConfiguration; | |
39 | +import org.thingsboard.server.common.data.device.profile.JsonTransportPayloadConfiguration; | |
40 | +import org.thingsboard.server.common.data.device.profile.ProtoTransportPayloadConfiguration; | |
41 | +import org.thingsboard.server.common.data.device.profile.TransportPayloadTypeConfiguration; | |
29 | 42 | import org.thingsboard.server.common.data.security.DeviceTokenCredentials; |
30 | 43 | import org.thingsboard.server.common.msg.session.FeatureType; |
31 | 44 | import org.thingsboard.server.common.msg.session.SessionMsgType; |
32 | 45 | import org.thingsboard.server.common.transport.SessionMsgListener; |
33 | -import org.thingsboard.server.common.transport.TransportContext; | |
34 | -import org.thingsboard.server.common.transport.TransportService; | |
35 | 46 | import org.thingsboard.server.common.transport.TransportServiceCallback; |
36 | 47 | import org.thingsboard.server.common.transport.adaptor.AdaptorException; |
37 | 48 | import org.thingsboard.server.common.transport.adaptor.JsonConverter; |
38 | -import org.thingsboard.server.common.transport.auth.SessionInfoCreator; | |
39 | -import org.thingsboard.server.common.transport.auth.ValidateDeviceCredentialsResponse; | |
40 | 49 | import org.thingsboard.server.gen.transport.TransportProtos; |
41 | -import org.thingsboard.server.gen.transport.TransportProtos.ProvisionDeviceResponseMsg; | |
50 | +import org.thingsboard.server.transport.coap.adaptors.CoapTransportAdaptor; | |
42 | 51 | |
43 | -import java.lang.reflect.Field; | |
44 | 52 | import java.util.List; |
45 | 53 | import java.util.Optional; |
46 | 54 | import java.util.Set; |
... | ... | @@ -48,52 +56,60 @@ import java.util.UUID; |
48 | 56 | import java.util.concurrent.ConcurrentHashMap; |
49 | 57 | import java.util.concurrent.ConcurrentMap; |
50 | 58 | import java.util.concurrent.atomic.AtomicInteger; |
51 | -import java.util.function.Consumer; | |
52 | 59 | |
53 | 60 | @Slf4j |
54 | -public class CoapTransportResource extends CoapResource { | |
55 | - // coap://localhost:port/api/v1/DEVICE_TOKEN/[attributes|telemetry|rpc[/requestId]] | |
61 | +public class CoapTransportResource extends AbstractCoapTransportResource { | |
56 | 62 | private static final int ACCESS_TOKEN_POSITION = 3; |
57 | 63 | private static final int FEATURE_TYPE_POSITION = 4; |
58 | 64 | private static final int REQUEST_ID_POSITION = 5; |
59 | 65 | |
60 | - private final CoapTransportContext transportContext; | |
61 | - private final TransportService transportService; | |
62 | - private final Field observerField; | |
63 | - private final long timeout; | |
64 | 66 | private final ConcurrentMap<String, TransportProtos.SessionInfoProto> tokenToSessionIdMap = new ConcurrentHashMap<>(); |
67 | + private final ConcurrentMap<String, AtomicInteger> tokenToNotificationCounterMap = new ConcurrentHashMap<>(); | |
65 | 68 | private final Set<UUID> rpcSubscriptions = ConcurrentHashMap.newKeySet(); |
66 | 69 | private final Set<UUID> attributeSubscriptions = ConcurrentHashMap.newKeySet(); |
67 | 70 | |
68 | - public CoapTransportResource(CoapTransportContext context, String name) { | |
69 | - super(name); | |
70 | - this.transportContext = context; | |
71 | - this.transportService = context.getTransportService(); | |
72 | - this.timeout = context.getTimeout(); | |
73 | - // This is important to turn off existing observable logic in | |
74 | - // CoapResource. We will have our own observe monitoring due to 1:1 | |
75 | - // observe relationship. | |
76 | - this.setObservable(false); | |
77 | - observerField = ReflectionUtils.findField(Exchange.class, "observer"); | |
78 | - observerField.setAccessible(true); | |
71 | + public CoapTransportResource(CoapTransportContext coapTransportContext, String name) { | |
72 | + super(coapTransportContext, name); | |
73 | + this.setObservable(true); // enable observing | |
74 | + this.addObserver(new CoapResourceObserver()); | |
75 | +// this.setObservable(false); // disable observing | |
76 | +// this.setObserveType(CoAP.Type.CON); // configure the notification type to CONs | |
77 | +// this.getAttributes().setObservable(); // mark observable in the Link-Format | |
78 | + } | |
79 | + | |
80 | + public void checkObserveRelation(Exchange exchange, Response response) { | |
81 | + String token = getTokenFromRequest(exchange.getRequest()); | |
82 | + final ObserveRelation relation = exchange.getRelation(); | |
83 | + if (relation == null || relation.isCanceled()) { | |
84 | + return; // because request did not try to establish a relation | |
85 | + } | |
86 | + if (CoAP.ResponseCode.isSuccess(response.getCode())) { | |
87 | + | |
88 | + if (!relation.isEstablished()) { | |
89 | + relation.setEstablished(); | |
90 | + addObserveRelation(relation); | |
91 | + } | |
92 | + AtomicInteger notificationCounter = tokenToNotificationCounterMap.computeIfAbsent(token, s -> new AtomicInteger(0)); | |
93 | + response.getOptions().setObserve(notificationCounter.getAndIncrement()); | |
94 | + } // ObserveLayer takes care of the else case | |
79 | 95 | } |
80 | 96 | |
81 | 97 | @Override |
82 | - public void handleGET(CoapExchange exchange) { | |
98 | + protected void processHandleGet(CoapExchange exchange) { | |
83 | 99 | Optional<FeatureType> featureType = getFeatureType(exchange.advanced().getRequest()); |
84 | - if (!featureType.isPresent()) { | |
100 | + if (featureType.isEmpty()) { | |
85 | 101 | log.trace("Missing feature type parameter"); |
86 | - exchange.respond(ResponseCode.BAD_REQUEST); | |
102 | + exchange.respond(CoAP.ResponseCode.BAD_REQUEST); | |
87 | 103 | } else if (featureType.get() == FeatureType.TELEMETRY) { |
88 | 104 | log.trace("Can't fetch/subscribe to timeseries updates"); |
89 | - exchange.respond(ResponseCode.BAD_REQUEST); | |
105 | + exchange.respond(CoAP.ResponseCode.BAD_REQUEST); | |
90 | 106 | } else if (exchange.getRequestOptions().hasObserve()) { |
91 | 107 | processExchangeGetRequest(exchange, featureType.get()); |
92 | 108 | } else if (featureType.get() == FeatureType.ATTRIBUTES) { |
93 | 109 | processRequest(exchange, SessionMsgType.GET_ATTRIBUTES_REQUEST); |
94 | 110 | } else { |
95 | 111 | log.trace("Invalid feature type parameter"); |
96 | - exchange.respond(ResponseCode.BAD_REQUEST); | |
112 | + exchange.respond(CoAP.ResponseCode.BAD_REQUEST); | |
97 | 113 | } |
98 | 114 | } |
99 | 115 | |
... | ... | @@ -109,11 +125,11 @@ public class CoapTransportResource extends CoapResource { |
109 | 125 | } |
110 | 126 | |
111 | 127 | @Override |
112 | - public void handlePOST(CoapExchange exchange) { | |
128 | + protected void processHandlePost(CoapExchange exchange) { | |
113 | 129 | Optional<FeatureType> featureType = getFeatureType(exchange.advanced().getRequest()); |
114 | - if (!featureType.isPresent()) { | |
130 | + if (featureType.isEmpty()) { | |
115 | 131 | log.trace("Missing feature type parameter"); |
116 | - exchange.respond(ResponseCode.BAD_REQUEST); | |
132 | + exchange.respond(CoAP.ResponseCode.BAD_REQUEST); | |
117 | 133 | } else { |
118 | 134 | switch (featureType.get()) { |
119 | 135 | case ATTRIBUTES: |
... | ... | @@ -141,14 +157,27 @@ public class CoapTransportResource extends CoapResource { |
141 | 157 | } |
142 | 158 | |
143 | 159 | private void processProvision(CoapExchange exchange) { |
144 | - log.trace("Processing {}", exchange.advanced().getRequest()); | |
145 | 160 | exchange.accept(); |
146 | 161 | try { |
147 | - transportService.process(transportContext.getAdaptor().convertToProvisionRequestMsg(UUID.randomUUID(), exchange.advanced().getRequest()), | |
148 | - new DeviceProvisionCallback(exchange)); | |
162 | + UUID sessionId = UUID.randomUUID(); | |
163 | + log.trace("[{}] Processing provision publish msg [{}]!", sessionId, exchange.advanced().getRequest()); | |
164 | + TransportProtos.ProvisionDeviceRequestMsg provisionRequestMsg; | |
165 | + TransportPayloadType payloadType; | |
166 | + try { | |
167 | + provisionRequestMsg = transportContext.getJsonCoapAdaptor().convertToProvisionRequestMsg(sessionId, exchange.advanced().getRequest()); | |
168 | + payloadType = TransportPayloadType.JSON; | |
169 | + } catch (Exception e) { | |
170 | + if (e instanceof JsonParseException || (e.getCause() != null && e.getCause() instanceof JsonParseException)) { | |
171 | + provisionRequestMsg = transportContext.getProtoCoapAdaptor().convertToProvisionRequestMsg(sessionId, exchange.advanced().getRequest()); | |
172 | + payloadType = TransportPayloadType.PROTOBUF; | |
173 | + } else { | |
174 | + throw new AdaptorException(e); | |
175 | + } | |
176 | + } | |
177 | + transportService.process(provisionRequestMsg, new DeviceProvisionCallback(exchange, payloadType)); | |
149 | 178 | } catch (AdaptorException e) { |
150 | 179 | log.trace("Failed to decode message: ", e); |
151 | - exchange.respond(ResponseCode.BAD_REQUEST); | |
180 | + exchange.respond(CoAP.ResponseCode.BAD_REQUEST); | |
152 | 181 | } |
153 | 182 | } |
154 | 183 | |
... | ... | @@ -159,123 +188,123 @@ public class CoapTransportResource extends CoapResource { |
159 | 188 | Request request = advanced.getRequest(); |
160 | 189 | |
161 | 190 | Optional<DeviceTokenCredentials> credentials = decodeCredentials(request); |
162 | - if (!credentials.isPresent()) { | |
163 | - exchange.respond(ResponseCode.BAD_REQUEST); | |
191 | + if (credentials.isEmpty()) { | |
192 | + exchange.respond(CoAP.ResponseCode.BAD_REQUEST); | |
164 | 193 | return; |
165 | 194 | } |
166 | 195 | |
167 | - transportService.process(DeviceTransportType.DEFAULT, TransportProtos.ValidateDeviceTokenRequestMsg.newBuilder().setToken(credentials.get().getCredentialsId()).build(), | |
168 | - new DeviceAuthCallback(transportContext, exchange, sessionInfo -> { | |
196 | + transportService.process(DeviceTransportType.COAP, TransportProtos.ValidateDeviceTokenRequestMsg.newBuilder().setToken(credentials.get().getCredentialsId()).build(), | |
197 | + new CoapDeviceAuthCallback(transportContext, exchange, (sessionInfo, deviceProfile) -> { | |
169 | 198 | UUID sessionId = new UUID(sessionInfo.getSessionIdMSB(), sessionInfo.getSessionIdLSB()); |
170 | 199 | try { |
200 | + TransportConfigurationContainer transportConfigurationContainer = getTransportConfigurationContainer(deviceProfile); | |
201 | + CoapTransportAdaptor coapTransportAdaptor = getCoapTransportAdaptor(transportConfigurationContainer.isJsonPayload()); | |
171 | 202 | switch (type) { |
172 | 203 | case POST_ATTRIBUTES_REQUEST: |
173 | 204 | transportService.process(sessionInfo, |
174 | - transportContext.getAdaptor().convertToPostAttributes(sessionId, request), | |
175 | - new CoapOkCallback(exchange)); | |
176 | - reportActivity(sessionId, sessionInfo); | |
205 | + coapTransportAdaptor.convertToPostAttributes(sessionId, request, | |
206 | + transportConfigurationContainer.getAttributesMsgDescriptor()), | |
207 | + new CoapOkCallback(exchange, CoAP.ResponseCode.CREATED, CoAP.ResponseCode.INTERNAL_SERVER_ERROR)); | |
208 | + reportActivity(sessionInfo, attributeSubscriptions.contains(sessionId), rpcSubscriptions.contains(sessionId)); | |
177 | 209 | break; |
178 | 210 | case POST_TELEMETRY_REQUEST: |
179 | 211 | transportService.process(sessionInfo, |
180 | - transportContext.getAdaptor().convertToPostTelemetry(sessionId, request), | |
181 | - new CoapOkCallback(exchange)); | |
182 | - reportActivity(sessionId, sessionInfo); | |
212 | + coapTransportAdaptor.convertToPostTelemetry(sessionId, request, | |
213 | + transportConfigurationContainer.getTelemetryMsgDescriptor()), | |
214 | + new CoapOkCallback(exchange, CoAP.ResponseCode.CREATED, CoAP.ResponseCode.INTERNAL_SERVER_ERROR)); | |
215 | + reportActivity(sessionInfo, attributeSubscriptions.contains(sessionId), rpcSubscriptions.contains(sessionId)); | |
183 | 216 | break; |
184 | 217 | case CLAIM_REQUEST: |
185 | 218 | transportService.process(sessionInfo, |
186 | - transportContext.getAdaptor().convertToClaimDevice(sessionId, request, sessionInfo), | |
187 | - new CoapOkCallback(exchange)); | |
219 | + coapTransportAdaptor.convertToClaimDevice(sessionId, request, sessionInfo), | |
220 | + new CoapOkCallback(exchange, CoAP.ResponseCode.CREATED, CoAP.ResponseCode.INTERNAL_SERVER_ERROR)); | |
188 | 221 | break; |
189 | 222 | case SUBSCRIBE_ATTRIBUTES_REQUEST: |
190 | - attributeSubscriptions.add(sessionId); | |
191 | - advanced.setObserver(new CoapExchangeObserverProxy((ExchangeObserver) observerField.get(advanced), | |
192 | - registerAsyncCoapSession(exchange, request, sessionInfo, sessionId))); | |
193 | - transportService.process(sessionInfo, | |
194 | - TransportProtos.SubscribeToAttributeUpdatesMsg.getDefaultInstance(), | |
195 | - new CoapNoOpCallback(exchange)); | |
223 | + TransportProtos.SessionInfoProto currentAttrSession = tokenToSessionIdMap.get(getTokenFromRequest(request)); | |
224 | + if (currentAttrSession == null) { | |
225 | + attributeSubscriptions.add(sessionId); | |
226 | + registerAsyncCoapSession(exchange, sessionInfo, coapTransportAdaptor, getTokenFromRequest(request)); | |
227 | + transportService.process(sessionInfo, | |
228 | + TransportProtos.SubscribeToAttributeUpdatesMsg.getDefaultInstance(), new CoapNoOpCallback(exchange)); | |
229 | + } | |
196 | 230 | break; |
197 | 231 | case UNSUBSCRIBE_ATTRIBUTES_REQUEST: |
198 | - attributeSubscriptions.remove(sessionId); | |
199 | - TransportProtos.SessionInfoProto attrSession = lookupAsyncSessionInfo(request); | |
232 | + TransportProtos.SessionInfoProto attrSession = lookupAsyncSessionInfo(getTokenFromRequest(request)); | |
200 | 233 | if (attrSession != null) { |
234 | + UUID attrSessionId = new UUID(attrSession.getSessionIdMSB(), attrSession.getSessionIdLSB()); | |
235 | + attributeSubscriptions.remove(attrSessionId); | |
201 | 236 | transportService.process(attrSession, |
202 | 237 | TransportProtos.SubscribeToAttributeUpdatesMsg.newBuilder().setUnsubscribe(true).build(), |
203 | - new CoapOkCallback(exchange)); | |
204 | - closeAndDeregister(sessionInfo); | |
238 | + new CoapOkCallback(exchange, CoAP.ResponseCode.DELETED, CoAP.ResponseCode.INTERNAL_SERVER_ERROR)); | |
239 | + closeAndDeregister(sessionInfo, sessionId); | |
205 | 240 | } |
206 | 241 | break; |
207 | 242 | case SUBSCRIBE_RPC_COMMANDS_REQUEST: |
208 | - rpcSubscriptions.add(sessionId); | |
209 | - advanced.setObserver(new CoapExchangeObserverProxy((ExchangeObserver) observerField.get(advanced), | |
210 | - registerAsyncCoapSession(exchange, request, sessionInfo, sessionId))); | |
211 | - transportService.process(sessionInfo, | |
212 | - TransportProtos.SubscribeToRPCMsg.getDefaultInstance(), | |
213 | - new CoapNoOpCallback(exchange)); | |
243 | + TransportProtos.SessionInfoProto currentRpcSession = tokenToSessionIdMap.get(getTokenFromRequest(request)); | |
244 | + if (currentRpcSession == null) { | |
245 | + rpcSubscriptions.add(sessionId); | |
246 | + registerAsyncCoapSession(exchange, sessionInfo, coapTransportAdaptor, getTokenFromRequest(request)); | |
247 | + transportService.process(sessionInfo, | |
248 | + TransportProtos.SubscribeToRPCMsg.getDefaultInstance(), | |
249 | + new CoapNoOpCallback(exchange)); | |
250 | + } else { | |
251 | + UUID rpcSessionId = new UUID(currentRpcSession.getSessionIdMSB(), currentRpcSession.getSessionIdLSB()); | |
252 | + reportActivity(currentRpcSession, attributeSubscriptions.contains(rpcSessionId), rpcSubscriptions.contains(rpcSessionId)); | |
253 | + } | |
214 | 254 | break; |
215 | 255 | case UNSUBSCRIBE_RPC_COMMANDS_REQUEST: |
216 | - rpcSubscriptions.remove(sessionId); | |
217 | - TransportProtos.SessionInfoProto rpcSession = lookupAsyncSessionInfo(request); | |
256 | + TransportProtos.SessionInfoProto rpcSession = lookupAsyncSessionInfo(getTokenFromRequest(request)); | |
218 | 257 | if (rpcSession != null) { |
258 | + UUID rpcSessionId = new UUID(rpcSession.getSessionIdMSB(), rpcSession.getSessionIdLSB()); | |
259 | + rpcSubscriptions.remove(rpcSessionId); | |
219 | 260 | transportService.process(rpcSession, |
220 | 261 | TransportProtos.SubscribeToRPCMsg.newBuilder().setUnsubscribe(true).build(), |
221 | - new CoapOkCallback(exchange)); | |
222 | - closeAndDeregister(sessionInfo); | |
262 | + new CoapOkCallback(exchange, CoAP.ResponseCode.DELETED, CoAP.ResponseCode.INTERNAL_SERVER_ERROR)); | |
263 | + closeAndDeregister(sessionInfo, sessionId); | |
223 | 264 | } |
224 | 265 | break; |
225 | 266 | case TO_DEVICE_RPC_RESPONSE: |
226 | 267 | transportService.process(sessionInfo, |
227 | - transportContext.getAdaptor().convertToDeviceRpcResponse(sessionId, request), | |
228 | - new CoapOkCallback(exchange)); | |
268 | + coapTransportAdaptor.convertToDeviceRpcResponse(sessionId, request), | |
269 | + new CoapOkCallback(exchange, CoAP.ResponseCode.CREATED, CoAP.ResponseCode.INTERNAL_SERVER_ERROR)); | |
229 | 270 | break; |
230 | 271 | case TO_SERVER_RPC_REQUEST: |
231 | - transportService.registerSyncSession(sessionInfo, new CoapSessionListener(sessionId, exchange), transportContext.getTimeout()); | |
272 | + transportService.registerSyncSession(sessionInfo, getCoapSessionListener(exchange, coapTransportAdaptor), transportContext.getTimeout()); | |
232 | 273 | transportService.process(sessionInfo, |
233 | - transportContext.getAdaptor().convertToServerRpcRequest(sessionId, request), | |
274 | + coapTransportAdaptor.convertToServerRpcRequest(sessionId, request), | |
234 | 275 | new CoapNoOpCallback(exchange)); |
235 | 276 | break; |
236 | 277 | case GET_ATTRIBUTES_REQUEST: |
237 | - transportService.registerSyncSession(sessionInfo, new CoapSessionListener(sessionId, exchange), transportContext.getTimeout()); | |
278 | + transportService.registerSyncSession(sessionInfo, getCoapSessionListener(exchange, coapTransportAdaptor), transportContext.getTimeout()); | |
238 | 279 | transportService.process(sessionInfo, |
239 | - transportContext.getAdaptor().convertToGetAttributes(sessionId, request), | |
280 | + coapTransportAdaptor.convertToGetAttributes(sessionId, request), | |
240 | 281 | new CoapNoOpCallback(exchange)); |
241 | 282 | break; |
242 | 283 | } |
243 | 284 | } catch (AdaptorException e) { |
244 | 285 | log.trace("[{}] Failed to decode message: ", sessionId, e); |
245 | - exchange.respond(ResponseCode.BAD_REQUEST); | |
246 | - } catch (IllegalAccessException e) { | |
247 | - log.trace("[{}] Failed to process message: ", sessionId, e); | |
248 | - exchange.respond(ResponseCode.INTERNAL_SERVER_ERROR); | |
286 | + exchange.respond(CoAP.ResponseCode.BAD_REQUEST); | |
249 | 287 | } |
250 | 288 | })); |
251 | 289 | } |
252 | 290 | |
253 | - private void reportActivity(UUID sessionId, TransportProtos.SessionInfoProto sessionInfo) { | |
254 | - transportContext.getTransportService().process(sessionInfo, TransportProtos.SubscriptionInfoProto.newBuilder() | |
255 | - .setAttributeSubscription(attributeSubscriptions.contains(sessionId)) | |
256 | - .setRpcSubscription(rpcSubscriptions.contains(sessionId)) | |
257 | - .setLastActivityTime(System.currentTimeMillis()) | |
258 | - .build(), TransportServiceCallback.EMPTY); | |
259 | - } | |
260 | - | |
261 | - private TransportProtos.SessionInfoProto lookupAsyncSessionInfo(Request request) { | |
262 | - String token = request.getSource().getHostAddress() + ":" + request.getSourcePort() + ":" + request.getTokenString(); | |
291 | + private TransportProtos.SessionInfoProto lookupAsyncSessionInfo(String token) { | |
292 | + tokenToNotificationCounterMap.remove(token); | |
263 | 293 | return tokenToSessionIdMap.remove(token); |
264 | 294 | } |
265 | 295 | |
266 | - private String registerAsyncCoapSession(CoapExchange exchange, Request request, TransportProtos.SessionInfoProto sessionInfo, UUID sessionId) { | |
267 | - String token = request.getSource().getHostAddress() + ":" + request.getSourcePort() + ":" + request.getTokenString(); | |
296 | + private void registerAsyncCoapSession(CoapExchange exchange, TransportProtos.SessionInfoProto sessionInfo, CoapTransportAdaptor coapTransportAdaptor, String token) { | |
268 | 297 | tokenToSessionIdMap.putIfAbsent(token, sessionInfo); |
269 | - CoapSessionListener attrListener = new CoapSessionListener(sessionId, exchange); | |
270 | - transportService.registerAsyncSession(sessionInfo, attrListener); | |
298 | + transportService.registerAsyncSession(sessionInfo, getCoapSessionListener(exchange, coapTransportAdaptor)); | |
271 | 299 | transportService.process(sessionInfo, getSessionEventMsg(TransportProtos.SessionEvent.OPEN), null); |
272 | - return token; | |
273 | 300 | } |
274 | 301 | |
275 | - private static TransportProtos.SessionEventMsg getSessionEventMsg(TransportProtos.SessionEvent event) { | |
276 | - return TransportProtos.SessionEventMsg.newBuilder() | |
277 | - .setSessionType(TransportProtos.SessionType.ASYNC) | |
278 | - .setEvent(event).build(); | |
302 | + private CoapSessionListener getCoapSessionListener(CoapExchange exchange, CoapTransportAdaptor coapTransportAdaptor) { | |
303 | + return new CoapSessionListener(exchange, coapTransportAdaptor); | |
304 | + } | |
305 | + | |
306 | + private String getTokenFromRequest(Request request) { | |
307 | + return request.getSource().getHostAddress() + ":" + request.getSourcePort() + ":" + request.getTokenString(); | |
279 | 308 | } |
280 | 309 | |
281 | 310 | private Optional<DeviceTokenCredentials> decodeCredentials(Request request) { |
... | ... | @@ -318,174 +347,192 @@ public class CoapTransportResource extends CoapResource { |
318 | 347 | return this; |
319 | 348 | } |
320 | 349 | |
321 | - private static class DeviceAuthCallback implements TransportServiceCallback<ValidateDeviceCredentialsResponse> { | |
322 | - private final TransportContext transportContext; | |
350 | + private static class DeviceProvisionCallback implements TransportServiceCallback<TransportProtos.ProvisionDeviceResponseMsg> { | |
323 | 351 | private final CoapExchange exchange; |
324 | - private final Consumer<TransportProtos.SessionInfoProto> onSuccess; | |
352 | + private final TransportPayloadType payloadType; | |
325 | 353 | |
326 | - DeviceAuthCallback(TransportContext transportContext, CoapExchange exchange, Consumer<TransportProtos.SessionInfoProto> onSuccess) { | |
327 | - this.transportContext = transportContext; | |
354 | + DeviceProvisionCallback(CoapExchange exchange, TransportPayloadType payloadType) { | |
328 | 355 | this.exchange = exchange; |
329 | - this.onSuccess = onSuccess; | |
356 | + this.payloadType = payloadType; | |
330 | 357 | } |
331 | 358 | |
332 | 359 | @Override |
333 | - public void onSuccess(ValidateDeviceCredentialsResponse msg) { | |
334 | - if (msg.hasDeviceInfo()) { | |
335 | - onSuccess.accept(SessionInfoCreator.create(msg, transportContext, UUID.randomUUID())); | |
360 | + public void onSuccess(TransportProtos.ProvisionDeviceResponseMsg msg) { | |
361 | + CoAP.ResponseCode responseCode = CoAP.ResponseCode.CREATED; | |
362 | + if (!msg.getStatus().equals(TransportProtos.ProvisionResponseStatus.SUCCESS)) { | |
363 | + responseCode = CoAP.ResponseCode.BAD_REQUEST; | |
364 | + } | |
365 | + if (payloadType.equals(TransportPayloadType.JSON)) { | |
366 | + exchange.respond(responseCode, JsonConverter.toJson(msg).toString()); | |
336 | 367 | } else { |
337 | - exchange.respond(ResponseCode.UNAUTHORIZED); | |
368 | + exchange.respond(responseCode, msg.toByteArray()); | |
338 | 369 | } |
339 | 370 | } |
340 | 371 | |
341 | 372 | @Override |
342 | 373 | public void onError(Throwable e) { |
343 | 374 | log.warn("Failed to process request", e); |
344 | - exchange.respond(ResponseCode.INTERNAL_SERVER_ERROR); | |
375 | + exchange.respond(CoAP.ResponseCode.INTERNAL_SERVER_ERROR); | |
345 | 376 | } |
346 | 377 | } |
347 | 378 | |
348 | - private static class DeviceProvisionCallback implements TransportServiceCallback<ProvisionDeviceResponseMsg> { | |
349 | - private final CoapExchange exchange; | |
379 | + private static class CoapSessionListener implements SessionMsgListener { | |
350 | 380 | |
351 | - DeviceProvisionCallback(CoapExchange exchange) { | |
352 | - this.exchange = exchange; | |
353 | - } | |
354 | - | |
355 | - @Override | |
356 | - public void onSuccess(TransportProtos.ProvisionDeviceResponseMsg msg) { | |
357 | - exchange.respond(JsonConverter.toJson(msg).toString()); | |
358 | - } | |
359 | - | |
360 | - @Override | |
361 | - public void onError(Throwable e) { | |
362 | - log.warn("Failed to process request", e); | |
363 | - exchange.respond(ResponseCode.INTERNAL_SERVER_ERROR); | |
364 | - } | |
365 | - } | |
366 | - | |
367 | - private static class CoapOkCallback implements TransportServiceCallback<Void> { | |
368 | 381 | private final CoapExchange exchange; |
382 | + private final CoapTransportAdaptor coapTransportAdaptor; | |
369 | 383 | |
370 | - CoapOkCallback(CoapExchange exchange) { | |
371 | - this.exchange = exchange; | |
372 | - } | |
373 | - | |
374 | - @Override | |
375 | - public void onSuccess(Void msg) { | |
376 | - exchange.respond(ResponseCode.VALID); | |
377 | - } | |
378 | - | |
379 | - @Override | |
380 | - public void onError(Throwable e) { | |
381 | - exchange.respond(ResponseCode.INTERNAL_SERVER_ERROR); | |
382 | - } | |
383 | - } | |
384 | - | |
385 | - private static class CoapNoOpCallback implements TransportServiceCallback<Void> { | |
386 | - private final CoapExchange exchange; | |
387 | - | |
388 | - CoapNoOpCallback(CoapExchange exchange) { | |
389 | - this.exchange = exchange; | |
390 | - } | |
391 | - | |
392 | - @Override | |
393 | - public void onSuccess(Void msg) { | |
394 | - | |
395 | - } | |
396 | - | |
397 | - @Override | |
398 | - public void onError(Throwable e) { | |
399 | - exchange.respond(ResponseCode.INTERNAL_SERVER_ERROR); | |
400 | - } | |
401 | - } | |
402 | - | |
403 | - public class CoapSessionListener implements SessionMsgListener { | |
404 | - | |
405 | - private final CoapExchange exchange; | |
406 | - private final AtomicInteger seqNumber = new AtomicInteger(2); | |
407 | - | |
408 | - CoapSessionListener(UUID sessionId, CoapExchange exchange) { | |
384 | + CoapSessionListener(CoapExchange exchange, CoapTransportAdaptor coapTransportAdaptor) { | |
409 | 385 | this.exchange = exchange; |
386 | + this.coapTransportAdaptor = coapTransportAdaptor; | |
410 | 387 | } |
411 | 388 | |
412 | 389 | @Override |
413 | 390 | public void onGetAttributesResponse(TransportProtos.GetAttributeResponseMsg msg) { |
414 | 391 | try { |
415 | - exchange.respond(transportContext.getAdaptor().convertToPublish(this, msg)); | |
392 | + exchange.respond(coapTransportAdaptor.convertToPublish(msg)); | |
416 | 393 | } catch (AdaptorException e) { |
417 | 394 | log.trace("Failed to reply due to error", e); |
418 | - exchange.respond(ResponseCode.INTERNAL_SERVER_ERROR); | |
395 | + exchange.respond(CoAP.ResponseCode.INTERNAL_SERVER_ERROR); | |
419 | 396 | } |
420 | 397 | } |
421 | 398 | |
422 | 399 | @Override |
423 | 400 | public void onAttributeUpdate(TransportProtos.AttributeUpdateNotificationMsg msg) { |
424 | 401 | try { |
425 | - exchange.respond(transportContext.getAdaptor().convertToPublish(this, msg)); | |
402 | + exchange.respond(coapTransportAdaptor.convertToPublish(isConRequest(), msg)); | |
426 | 403 | } catch (AdaptorException e) { |
427 | 404 | log.trace("Failed to reply due to error", e); |
428 | - exchange.respond(ResponseCode.INTERNAL_SERVER_ERROR); | |
405 | + exchange.respond(CoAP.ResponseCode.INTERNAL_SERVER_ERROR); | |
429 | 406 | } |
430 | 407 | } |
431 | 408 | |
432 | 409 | @Override |
433 | 410 | public void onRemoteSessionCloseCommand(TransportProtos.SessionCloseNotificationProto sessionCloseNotification) { |
434 | - exchange.respond(ResponseCode.SERVICE_UNAVAILABLE); | |
411 | + exchange.respond(CoAP.ResponseCode.SERVICE_UNAVAILABLE); | |
435 | 412 | } |
436 | 413 | |
437 | 414 | @Override |
438 | 415 | public void onToDeviceRpcRequest(TransportProtos.ToDeviceRpcRequestMsg msg) { |
439 | 416 | try { |
440 | - exchange.respond(transportContext.getAdaptor().convertToPublish(this, msg)); | |
417 | + exchange.respond(coapTransportAdaptor.convertToPublish(isConRequest(), msg)); | |
441 | 418 | } catch (AdaptorException e) { |
442 | 419 | log.trace("Failed to reply due to error", e); |
443 | - exchange.respond(ResponseCode.INTERNAL_SERVER_ERROR); | |
420 | + exchange.respond(CoAP.ResponseCode.INTERNAL_SERVER_ERROR); | |
444 | 421 | } |
445 | 422 | } |
446 | 423 | |
447 | 424 | @Override |
448 | 425 | public void onToServerRpcResponse(TransportProtos.ToServerRpcResponseMsg msg) { |
449 | 426 | try { |
450 | - exchange.respond(transportContext.getAdaptor().convertToPublish(this, msg)); | |
427 | + exchange.respond(coapTransportAdaptor.convertToPublish(msg)); | |
451 | 428 | } catch (AdaptorException e) { |
452 | 429 | log.trace("Failed to reply due to error", e); |
453 | - exchange.respond(ResponseCode.INTERNAL_SERVER_ERROR); | |
430 | + exchange.respond(CoAP.ResponseCode.INTERNAL_SERVER_ERROR); | |
454 | 431 | } |
455 | 432 | } |
456 | 433 | |
457 | - public int getNextSeqNumber() { | |
458 | - return seqNumber.getAndIncrement(); | |
434 | + private boolean isConRequest() { | |
435 | + return exchange.advanced().getRequest().isConfirmable(); | |
459 | 436 | } |
460 | 437 | } |
461 | 438 | |
462 | - public class CoapExchangeObserverProxy implements ExchangeObserver { | |
439 | + public class CoapResourceObserver implements ResourceObserver { | |
440 | + | |
441 | + @Override | |
442 | + public void changedName(String old) { | |
443 | + } | |
444 | + | |
445 | + @Override | |
446 | + public void changedPath(String old) { | |
447 | + } | |
448 | + | |
449 | + @Override | |
450 | + public void addedChild(Resource child) { | |
451 | + } | |
463 | 452 | |
464 | - private final ExchangeObserver proxy; | |
465 | - private final String token; | |
453 | + @Override | |
454 | + public void removedChild(Resource child) { | |
455 | + } | |
466 | 456 | |
467 | - CoapExchangeObserverProxy(ExchangeObserver proxy, String token) { | |
468 | - super(); | |
469 | - this.proxy = proxy; | |
470 | - this.token = token; | |
457 | + @Override | |
458 | + public void addedObserveRelation(ObserveRelation relation) { | |
459 | + if (log.isTraceEnabled()) { | |
460 | + Request request = relation.getExchange().getRequest(); | |
461 | + log.trace("Added Observe relation for token: {}", getTokenFromRequest(request)); | |
462 | + } | |
471 | 463 | } |
472 | 464 | |
473 | 465 | @Override |
474 | - public void completed(Exchange exchange) { | |
475 | - proxy.completed(exchange); | |
476 | - TransportProtos.SessionInfoProto session = tokenToSessionIdMap.remove(token); | |
477 | - if (session != null) { | |
478 | - closeAndDeregister(session); | |
466 | + public void removedObserveRelation(ObserveRelation relation) { | |
467 | + Request request = relation.getExchange().getRequest(); | |
468 | + String tokenFromRequest = getTokenFromRequest(request); | |
469 | + log.trace("Relation removed for token: {}", tokenFromRequest); | |
470 | + TransportProtos.SessionInfoProto sessionInfoToRemove = lookupAsyncSessionInfo(tokenFromRequest); | |
471 | + if (sessionInfoToRemove != null) { | |
472 | + closeAndDeregister(sessionInfoToRemove, new UUID(sessionInfoToRemove.getSessionIdMSB(), sessionInfoToRemove.getDeviceIdLSB())); | |
479 | 473 | } |
480 | 474 | } |
481 | 475 | } |
482 | 476 | |
483 | - private void closeAndDeregister(TransportProtos.SessionInfoProto session) { | |
477 | + private void closeAndDeregister(TransportProtos.SessionInfoProto session, UUID sessionId) { | |
484 | 478 | transportService.process(session, getSessionEventMsg(TransportProtos.SessionEvent.CLOSED), null); |
485 | 479 | transportService.deregisterSession(session); |
486 | - UUID sessionId = new UUID(session.getSessionIdMSB(), session.getSessionIdLSB()); | |
487 | 480 | rpcSubscriptions.remove(sessionId); |
488 | 481 | attributeSubscriptions.remove(sessionId); |
489 | 482 | } |
490 | 483 | |
484 | + private TransportConfigurationContainer getTransportConfigurationContainer(DeviceProfile deviceProfile) throws AdaptorException { | |
485 | + DeviceProfileTransportConfiguration transportConfiguration = deviceProfile.getProfileData().getTransportConfiguration(); | |
486 | + if (transportConfiguration instanceof DefaultDeviceProfileTransportConfiguration) { | |
487 | + return new TransportConfigurationContainer(true); | |
488 | + } else if (transportConfiguration instanceof CoapDeviceProfileTransportConfiguration) { | |
489 | + CoapDeviceProfileTransportConfiguration coapDeviceProfileTransportConfiguration = | |
490 | + (CoapDeviceProfileTransportConfiguration) transportConfiguration; | |
491 | + CoapDeviceTypeConfiguration coapDeviceTypeConfiguration = | |
492 | + coapDeviceProfileTransportConfiguration.getCoapDeviceTypeConfiguration(); | |
493 | + if (coapDeviceTypeConfiguration instanceof DefaultCoapDeviceTypeConfiguration) { | |
494 | + DefaultCoapDeviceTypeConfiguration defaultCoapDeviceTypeConfiguration = | |
495 | + (DefaultCoapDeviceTypeConfiguration) coapDeviceTypeConfiguration; | |
496 | + TransportPayloadTypeConfiguration transportPayloadTypeConfiguration = | |
497 | + defaultCoapDeviceTypeConfiguration.getTransportPayloadTypeConfiguration(); | |
498 | + if (transportPayloadTypeConfiguration instanceof JsonTransportPayloadConfiguration) { | |
499 | + return new TransportConfigurationContainer(true); | |
500 | + } else { | |
501 | + ProtoTransportPayloadConfiguration protoTransportPayloadConfiguration = | |
502 | + (ProtoTransportPayloadConfiguration) transportPayloadTypeConfiguration; | |
503 | + String deviceTelemetryProtoSchema = protoTransportPayloadConfiguration.getDeviceTelemetryProtoSchema(); | |
504 | + String deviceAttributesProtoSchema = protoTransportPayloadConfiguration.getDeviceAttributesProtoSchema(); | |
505 | + return new TransportConfigurationContainer(false, | |
506 | + protoTransportPayloadConfiguration.getTelemetryDynamicMessageDescriptor(deviceTelemetryProtoSchema), | |
507 | + protoTransportPayloadConfiguration.getAttributesDynamicMessageDescriptor(deviceAttributesProtoSchema)); | |
508 | + } | |
509 | + } else { | |
510 | + throw new AdaptorException("Invalid CoapDeviceTypeConfiguration type: " + coapDeviceTypeConfiguration.getClass().getSimpleName() + "!"); | |
511 | + } | |
512 | + } else { | |
513 | + throw new AdaptorException("Invalid DeviceProfileTransportConfiguration type" + transportConfiguration.getClass().getSimpleName() + "!"); | |
514 | + } | |
515 | + } | |
516 | + | |
517 | + private CoapTransportAdaptor getCoapTransportAdaptor(boolean jsonPayloadType) { | |
518 | + return jsonPayloadType ? transportContext.getJsonCoapAdaptor() : transportContext.getProtoCoapAdaptor(); | |
519 | + } | |
520 | + | |
521 | + @Data | |
522 | + private static class TransportConfigurationContainer { | |
523 | + | |
524 | + private boolean jsonPayload; | |
525 | + private Descriptors.Descriptor telemetryMsgDescriptor; | |
526 | + private Descriptors.Descriptor attributesMsgDescriptor; | |
527 | + | |
528 | + public TransportConfigurationContainer(boolean jsonPayload, Descriptors.Descriptor telemetryMsgDescriptor, Descriptors.Descriptor attributesMsgDescriptor) { | |
529 | + this.jsonPayload = jsonPayload; | |
530 | + this.telemetryMsgDescriptor = telemetryMsgDescriptor; | |
531 | + this.attributesMsgDescriptor = attributesMsgDescriptor; | |
532 | + } | |
533 | + | |
534 | + public TransportConfigurationContainer(boolean jsonPayload) { | |
535 | + this.jsonPayload = jsonPayload; | |
536 | + } | |
537 | + } | |
491 | 538 | } | ... | ... |
... | ... | @@ -19,10 +19,11 @@ import lombok.extern.slf4j.Slf4j; |
19 | 19 | import org.eclipse.californium.core.CoapResource; |
20 | 20 | import org.eclipse.californium.core.CoapServer; |
21 | 21 | import org.eclipse.californium.core.network.CoapEndpoint; |
22 | -import org.eclipse.californium.core.network.config.NetworkConfig; | |
22 | +import org.eclipse.californium.core.server.resources.Resource; | |
23 | 23 | import org.springframework.beans.factory.annotation.Autowired; |
24 | 24 | import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; |
25 | 25 | import org.springframework.stereotype.Service; |
26 | +import org.thingsboard.server.transport.coap.efento.CoapEfentoTransportResource; | |
26 | 27 | |
27 | 28 | import javax.annotation.PostConstruct; |
28 | 29 | import javax.annotation.PreDestroy; |
... | ... | @@ -37,6 +38,8 @@ public class CoapTransportService { |
37 | 38 | |
38 | 39 | private static final String V1 = "v1"; |
39 | 40 | private static final String API = "api"; |
41 | + private static final String EFENTO = "efento"; | |
42 | + private static final String MEASUREMENTS = "m"; | |
40 | 43 | |
41 | 44 | @Autowired |
42 | 45 | private CoapTransportContext coapTransportContext; |
... | ... | @@ -47,11 +50,21 @@ public class CoapTransportService { |
47 | 50 | public void init() throws UnknownHostException { |
48 | 51 | log.info("Starting CoAP transport..."); |
49 | 52 | log.info("Starting CoAP transport server"); |
50 | - this.server = new CoapServer(NetworkConfig.createStandardWithoutFile()); | |
53 | + | |
54 | + this.server = new CoapServer(); | |
51 | 55 | createResources(); |
56 | + Resource root = this.server.getRoot(); | |
57 | + TbCoapServerMessageDeliverer messageDeliverer = new TbCoapServerMessageDeliverer(root); | |
58 | + this.server.setMessageDeliverer(messageDeliverer); | |
59 | + | |
52 | 60 | InetAddress addr = InetAddress.getByName(coapTransportContext.getHost()); |
53 | 61 | InetSocketAddress sockAddr = new InetSocketAddress(addr, coapTransportContext.getPort()); |
54 | - server.addEndpoint(new CoapEndpoint(sockAddr)); | |
62 | + | |
63 | + CoapEndpoint.Builder coapEndpoitBuilder = new CoapEndpoint.Builder(); | |
64 | + coapEndpoitBuilder.setInetSocketAddress(sockAddr); | |
65 | + CoapEndpoint coapEndpoint = coapEndpoitBuilder.build(); | |
66 | + | |
67 | + server.addEndpoint(coapEndpoint); | |
55 | 68 | server.start(); |
56 | 69 | log.info("CoAP transport started!"); |
57 | 70 | } |
... | ... | @@ -59,7 +72,13 @@ public class CoapTransportService { |
59 | 72 | private void createResources() { |
60 | 73 | CoapResource api = new CoapResource(API); |
61 | 74 | api.add(new CoapTransportResource(coapTransportContext, V1)); |
75 | + | |
76 | + CoapResource efento = new CoapResource(EFENTO); | |
77 | + CoapEfentoTransportResource efentoMeasurementsTransportResource = new CoapEfentoTransportResource(coapTransportContext, MEASUREMENTS); | |
78 | + efento.add(efentoMeasurementsTransportResource); | |
79 | + | |
62 | 80 | server.add(api); |
81 | + server.add(efento); | |
63 | 82 | } |
64 | 83 | |
65 | 84 | @PreDestroy | ... | ... |
1 | +/** | |
2 | + * Copyright © 2016-2021 The Thingsboard Authors | |
3 | + * | |
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | |
5 | + * you may not use this file except in compliance with the License. | |
6 | + * You may obtain a copy of the License at | |
7 | + * | |
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | |
9 | + * | |
10 | + * Unless required by applicable law or agreed to in writing, software | |
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | |
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 | + * See the License for the specific language governing permissions and | |
14 | + * limitations under the License. | |
15 | + */ | |
16 | +package org.thingsboard.server.transport.coap; | |
17 | + | |
18 | +import lombok.extern.slf4j.Slf4j; | |
19 | +import org.eclipse.californium.core.coap.OptionSet; | |
20 | +import org.eclipse.californium.core.network.Exchange; | |
21 | +import org.eclipse.californium.core.server.ServerMessageDeliverer; | |
22 | +import org.eclipse.californium.core.server.resources.Resource; | |
23 | +import org.springframework.util.CollectionUtils; | |
24 | + | |
25 | +import java.util.List; | |
26 | + | |
27 | +@Slf4j | |
28 | +public class TbCoapServerMessageDeliverer extends ServerMessageDeliverer { | |
29 | + | |
30 | + public TbCoapServerMessageDeliverer(Resource root) { | |
31 | + super(root); | |
32 | + } | |
33 | + | |
34 | + @Override | |
35 | + protected Resource findResource(Exchange exchange) { | |
36 | + validateUriPath(exchange); | |
37 | + return findResource(exchange.getRequest().getOptions().getUriPath()); | |
38 | + } | |
39 | + | |
40 | + private void validateUriPath(Exchange exchange) { | |
41 | + OptionSet options = exchange.getRequest().getOptions(); | |
42 | + List<String> uriPathList = options.getUriPath(); | |
43 | + String path = toPath(uriPathList); | |
44 | + if (path != null) { | |
45 | + options.setUriPath(path); | |
46 | + exchange.getRequest().setOptions(options); | |
47 | + } | |
48 | + } | |
49 | + | |
50 | + private String toPath(List<String> list) { | |
51 | + if (!CollectionUtils.isEmpty(list) && list.size() == 1) { | |
52 | + final String slash = "/"; | |
53 | + String path = list.get(0); | |
54 | + if (path.startsWith(slash)) { | |
55 | + path = path.substring(slash.length()); | |
56 | + } | |
57 | + return path; | |
58 | + } | |
59 | + return null; | |
60 | + } | |
61 | + | |
62 | +} | |
\ No newline at end of file | ... | ... |
1 | +/** | |
2 | + * Copyright © 2016-2021 The Thingsboard Authors | |
3 | + * | |
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | |
5 | + * you may not use this file except in compliance with the License. | |
6 | + * You may obtain a copy of the License at | |
7 | + * | |
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | |
9 | + * | |
10 | + * Unless required by applicable law or agreed to in writing, software | |
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | |
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 | + * See the License for the specific language governing permissions and | |
14 | + * limitations under the License. | |
15 | + */ | |
16 | +package org.thingsboard.server.transport.coap.adaptors; | |
17 | + | |
18 | +import org.eclipse.californium.core.coap.Request; | |
19 | +import org.springframework.util.StringUtils; | |
20 | +import org.thingsboard.server.common.transport.adaptor.AdaptorException; | |
21 | +import org.thingsboard.server.gen.transport.TransportProtos; | |
22 | + | |
23 | +import java.util.Arrays; | |
24 | +import java.util.HashSet; | |
25 | +import java.util.List; | |
26 | +import java.util.Set; | |
27 | + | |
28 | +public class CoapAdaptorUtils { | |
29 | + | |
30 | + public static TransportProtos.GetAttributeRequestMsg toGetAttributeRequestMsg(Request inbound) throws AdaptorException { | |
31 | + List<String> queryElements = inbound.getOptions().getUriQuery(); | |
32 | + TransportProtos.GetAttributeRequestMsg.Builder result = TransportProtos.GetAttributeRequestMsg.newBuilder(); | |
33 | + if (queryElements != null && queryElements.size() > 0) { | |
34 | + Set<String> clientKeys = toKeys(queryElements, "clientKeys"); | |
35 | + Set<String> sharedKeys = toKeys(queryElements, "sharedKeys"); | |
36 | + if (clientKeys != null) { | |
37 | + result.addAllClientAttributeNames(clientKeys); | |
38 | + } | |
39 | + if (sharedKeys != null) { | |
40 | + result.addAllSharedAttributeNames(sharedKeys); | |
41 | + } | |
42 | + } | |
43 | + return result.build(); | |
44 | + } | |
45 | + | |
46 | + private static Set<String> toKeys(List<String> queryElements, String attributeName) throws AdaptorException { | |
47 | + String keys = null; | |
48 | + for (String queryElement : queryElements) { | |
49 | + String[] queryItem = queryElement.split("="); | |
50 | + if (queryItem.length == 2 && queryItem[0].equals(attributeName)) { | |
51 | + keys = queryItem[1]; | |
52 | + } | |
53 | + } | |
54 | + if (keys != null && !StringUtils.isEmpty(keys)) { | |
55 | + return new HashSet<>(Arrays.asList(keys.split(","))); | |
56 | + } else { | |
57 | + return null; | |
58 | + } | |
59 | + } | |
60 | +} | ... | ... |
... | ... | @@ -15,20 +15,20 @@ |
15 | 15 | */ |
16 | 16 | package org.thingsboard.server.transport.coap.adaptors; |
17 | 17 | |
18 | +import com.google.protobuf.Descriptors; | |
18 | 19 | import org.eclipse.californium.core.coap.Request; |
19 | 20 | import org.eclipse.californium.core.coap.Response; |
20 | 21 | import org.thingsboard.server.common.transport.adaptor.AdaptorException; |
21 | 22 | import org.thingsboard.server.gen.transport.TransportProtos; |
22 | 23 | import org.thingsboard.server.gen.transport.TransportProtos.ProvisionDeviceRequestMsg; |
23 | -import org.thingsboard.server.transport.coap.CoapTransportResource; | |
24 | 24 | |
25 | 25 | import java.util.UUID; |
26 | 26 | |
27 | 27 | public interface CoapTransportAdaptor { |
28 | 28 | |
29 | - TransportProtos.PostTelemetryMsg convertToPostTelemetry(UUID sessionId, Request inbound) throws AdaptorException; | |
29 | + TransportProtos.PostTelemetryMsg convertToPostTelemetry(UUID sessionId, Request inbound, Descriptors.Descriptor telemetryMsgDescriptor) throws AdaptorException; | |
30 | 30 | |
31 | - TransportProtos.PostAttributeMsg convertToPostAttributes(UUID sessionId, Request inbound) throws AdaptorException; | |
31 | + TransportProtos.PostAttributeMsg convertToPostAttributes(UUID sessionId, Request inbound, Descriptors.Descriptor attributesMsgDescriptor) throws AdaptorException; | |
32 | 32 | |
33 | 33 | TransportProtos.GetAttributeRequestMsg convertToGetAttributes(UUID sessionId, Request inbound) throws AdaptorException; |
34 | 34 | |
... | ... | @@ -38,13 +38,13 @@ public interface CoapTransportAdaptor { |
38 | 38 | |
39 | 39 | TransportProtos.ClaimDeviceMsg convertToClaimDevice(UUID sessionId, Request inbound, TransportProtos.SessionInfoProto sessionInfo) throws AdaptorException; |
40 | 40 | |
41 | - Response convertToPublish(CoapTransportResource.CoapSessionListener session, TransportProtos.GetAttributeResponseMsg responseMsg) throws AdaptorException; | |
41 | + Response convertToPublish(TransportProtos.GetAttributeResponseMsg responseMsg) throws AdaptorException; | |
42 | 42 | |
43 | - Response convertToPublish(CoapTransportResource.CoapSessionListener session, TransportProtos.AttributeUpdateNotificationMsg notificationMsg) throws AdaptorException; | |
43 | + Response convertToPublish(boolean isConfirmable, TransportProtos.AttributeUpdateNotificationMsg notificationMsg) throws AdaptorException; | |
44 | 44 | |
45 | - Response convertToPublish(CoapTransportResource.CoapSessionListener session, TransportProtos.ToDeviceRpcRequestMsg rpcRequest) throws AdaptorException; | |
45 | + Response convertToPublish(boolean isConfirmable, TransportProtos.ToDeviceRpcRequestMsg rpcRequest) throws AdaptorException; | |
46 | 46 | |
47 | - Response convertToPublish(CoapTransportResource.CoapSessionListener coapSessionListener, TransportProtos.ToServerRpcResponseMsg msg) throws AdaptorException; | |
47 | + Response convertToPublish(TransportProtos.ToServerRpcResponseMsg msg) throws AdaptorException; | |
48 | 48 | |
49 | 49 | ProvisionDeviceRequestMsg convertToProvisionRequestMsg(UUID sessionId, Request inbound) throws AdaptorException; |
50 | 50 | ... | ... |
... | ... | @@ -19,31 +19,27 @@ import com.google.gson.JsonElement; |
19 | 19 | import com.google.gson.JsonObject; |
20 | 20 | import com.google.gson.JsonParser; |
21 | 21 | import com.google.gson.JsonSyntaxException; |
22 | +import com.google.protobuf.Descriptors; | |
22 | 23 | import lombok.extern.slf4j.Slf4j; |
23 | 24 | import org.eclipse.californium.core.coap.CoAP; |
24 | 25 | import org.eclipse.californium.core.coap.Request; |
25 | 26 | import org.eclipse.californium.core.coap.Response; |
26 | 27 | import org.springframework.stereotype.Component; |
27 | -import org.springframework.util.StringUtils; | |
28 | 28 | import org.thingsboard.server.common.data.id.DeviceId; |
29 | 29 | import org.thingsboard.server.common.transport.adaptor.AdaptorException; |
30 | 30 | import org.thingsboard.server.common.transport.adaptor.JsonConverter; |
31 | 31 | import org.thingsboard.server.gen.transport.TransportProtos; |
32 | 32 | import org.thingsboard.server.transport.coap.CoapTransportResource; |
33 | 33 | |
34 | -import java.util.Arrays; | |
35 | -import java.util.HashSet; | |
36 | -import java.util.List; | |
37 | 34 | import java.util.Optional; |
38 | -import java.util.Set; | |
39 | 35 | import java.util.UUID; |
40 | 36 | |
41 | -@Component("JsonCoapAdaptor") | |
37 | +@Component | |
42 | 38 | @Slf4j |
43 | 39 | public class JsonCoapAdaptor implements CoapTransportAdaptor { |
44 | 40 | |
45 | 41 | @Override |
46 | - public TransportProtos.PostTelemetryMsg convertToPostTelemetry(UUID sessionId, Request inbound) throws AdaptorException { | |
42 | + public TransportProtos.PostTelemetryMsg convertToPostTelemetry(UUID sessionId, Request inbound, Descriptors.Descriptor telemetryMsgDescriptor) throws AdaptorException { | |
47 | 43 | String payload = validatePayload(sessionId, inbound, false); |
48 | 44 | try { |
49 | 45 | return JsonConverter.convertToTelemetryProto(new JsonParser().parse(payload)); |
... | ... | @@ -53,7 +49,7 @@ public class JsonCoapAdaptor implements CoapTransportAdaptor { |
53 | 49 | } |
54 | 50 | |
55 | 51 | @Override |
56 | - public TransportProtos.PostAttributeMsg convertToPostAttributes(UUID sessionId, Request inbound) throws AdaptorException { | |
52 | + public TransportProtos.PostAttributeMsg convertToPostAttributes(UUID sessionId, Request inbound, Descriptors.Descriptor attributesMsgDescriptor) throws AdaptorException { | |
57 | 53 | String payload = validatePayload(sessionId, inbound, false); |
58 | 54 | try { |
59 | 55 | return JsonConverter.convertToAttributesProto(new JsonParser().parse(payload)); |
... | ... | @@ -64,19 +60,7 @@ public class JsonCoapAdaptor implements CoapTransportAdaptor { |
64 | 60 | |
65 | 61 | @Override |
66 | 62 | public TransportProtos.GetAttributeRequestMsg convertToGetAttributes(UUID sessionId, Request inbound) throws AdaptorException { |
67 | - List<String> queryElements = inbound.getOptions().getUriQuery(); | |
68 | - TransportProtos.GetAttributeRequestMsg.Builder result = TransportProtos.GetAttributeRequestMsg.newBuilder(); | |
69 | - if (queryElements != null && queryElements.size() > 0) { | |
70 | - Set<String> clientKeys = toKeys(queryElements, "clientKeys"); | |
71 | - Set<String> sharedKeys = toKeys(queryElements, "sharedKeys"); | |
72 | - if (clientKeys != null) { | |
73 | - result.addAllClientAttributeNames(clientKeys); | |
74 | - } | |
75 | - if (sharedKeys != null) { | |
76 | - result.addAllSharedAttributeNames(sharedKeys); | |
77 | - } | |
78 | - } | |
79 | - return result.build(); | |
63 | + return CoapAdaptorUtils.toGetAttributeRequestMsg(inbound); | |
80 | 64 | } |
81 | 65 | |
82 | 66 | @Override |
... | ... | @@ -106,17 +90,17 @@ public class JsonCoapAdaptor implements CoapTransportAdaptor { |
106 | 90 | } |
107 | 91 | |
108 | 92 | @Override |
109 | - public Response convertToPublish(CoapTransportResource.CoapSessionListener session, TransportProtos.AttributeUpdateNotificationMsg msg) throws AdaptorException { | |
110 | - return getObserveNotification(session.getNextSeqNumber(), JsonConverter.toJson(msg)); | |
93 | + public Response convertToPublish(boolean isConfirmable, TransportProtos.AttributeUpdateNotificationMsg msg) throws AdaptorException { | |
94 | + return getObserveNotification(isConfirmable, JsonConverter.toJson(msg)); | |
111 | 95 | } |
112 | 96 | |
113 | 97 | @Override |
114 | - public Response convertToPublish(CoapTransportResource.CoapSessionListener session, TransportProtos.ToDeviceRpcRequestMsg msg) throws AdaptorException { | |
115 | - return getObserveNotification(session.getNextSeqNumber(), JsonConverter.toJson(msg, true)); | |
98 | + public Response convertToPublish(boolean isConfirmable, TransportProtos.ToDeviceRpcRequestMsg msg) throws AdaptorException { | |
99 | + return getObserveNotification(isConfirmable, JsonConverter.toJson(msg, true)); | |
116 | 100 | } |
117 | 101 | |
118 | 102 | @Override |
119 | - public Response convertToPublish(CoapTransportResource.CoapSessionListener coapSessionListener, TransportProtos.ToServerRpcResponseMsg msg) throws AdaptorException { | |
103 | + public Response convertToPublish(TransportProtos.ToServerRpcResponseMsg msg) throws AdaptorException { | |
120 | 104 | Response response = new Response(CoAP.ResponseCode.CONTENT); |
121 | 105 | JsonElement result = JsonConverter.toJson(msg); |
122 | 106 | response.setPayload(result.toString()); |
... | ... | @@ -134,7 +118,7 @@ public class JsonCoapAdaptor implements CoapTransportAdaptor { |
134 | 118 | } |
135 | 119 | |
136 | 120 | @Override |
137 | - public Response convertToPublish(CoapTransportResource.CoapSessionListener session, TransportProtos.GetAttributeResponseMsg msg) throws AdaptorException { | |
121 | + public Response convertToPublish(TransportProtos.GetAttributeResponseMsg msg) throws AdaptorException { | |
138 | 122 | if (msg.getClientAttributeListCount() == 0 && msg.getSharedAttributeListCount() == 0) { |
139 | 123 | return new Response(CoAP.ResponseCode.NOT_FOUND); |
140 | 124 | } else { |
... | ... | @@ -145,10 +129,10 @@ public class JsonCoapAdaptor implements CoapTransportAdaptor { |
145 | 129 | } |
146 | 130 | } |
147 | 131 | |
148 | - private Response getObserveNotification(int seqNumber, JsonElement json) { | |
132 | + private Response getObserveNotification(boolean confirmable, JsonElement json) { | |
149 | 133 | Response response = new Response(CoAP.ResponseCode.CONTENT); |
150 | - response.getOptions().setObserve(seqNumber); | |
151 | 134 | response.setPayload(json.toString()); |
135 | + response.setConfirmable(confirmable); | |
152 | 136 | return response; |
153 | 137 | } |
154 | 138 | |
... | ... | @@ -163,19 +147,4 @@ public class JsonCoapAdaptor implements CoapTransportAdaptor { |
163 | 147 | return payload; |
164 | 148 | } |
165 | 149 | |
166 | - private Set<String> toKeys(List<String> queryElements, String attributeName) throws AdaptorException { | |
167 | - String keys = null; | |
168 | - for (String queryElement : queryElements) { | |
169 | - String[] queryItem = queryElement.split("="); | |
170 | - if (queryItem.length == 2 && queryItem[0].equals(attributeName)) { | |
171 | - keys = queryItem[1]; | |
172 | - } | |
173 | - } | |
174 | - if (keys != null && !StringUtils.isEmpty(keys)) { | |
175 | - return new HashSet<>(Arrays.asList(keys.split(","))); | |
176 | - } else { | |
177 | - return null; | |
178 | - } | |
179 | - } | |
180 | - | |
181 | 150 | } | ... | ... |
1 | +/** | |
2 | + * Copyright © 2016-2021 The Thingsboard Authors | |
3 | + * | |
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | |
5 | + * you may not use this file except in compliance with the License. | |
6 | + * You may obtain a copy of the License at | |
7 | + * | |
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | |
9 | + * | |
10 | + * Unless required by applicable law or agreed to in writing, software | |
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | |
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 | + * See the License for the specific language governing permissions and | |
14 | + * limitations under the License. | |
15 | + */ | |
16 | +package org.thingsboard.server.transport.coap.adaptors; | |
17 | + | |
18 | +import com.google.gson.JsonParser; | |
19 | +import com.google.protobuf.Descriptors; | |
20 | +import com.google.protobuf.DynamicMessage; | |
21 | +import com.google.protobuf.InvalidProtocolBufferException; | |
22 | +import com.google.protobuf.util.JsonFormat; | |
23 | +import lombok.extern.slf4j.Slf4j; | |
24 | +import org.eclipse.californium.core.coap.CoAP; | |
25 | +import org.eclipse.californium.core.coap.Request; | |
26 | +import org.eclipse.californium.core.coap.Response; | |
27 | +import org.springframework.stereotype.Component; | |
28 | +import org.thingsboard.server.common.data.id.DeviceId; | |
29 | +import org.thingsboard.server.common.transport.adaptor.AdaptorException; | |
30 | +import org.thingsboard.server.common.transport.adaptor.JsonConverter; | |
31 | +import org.thingsboard.server.common.transport.adaptor.ProtoConverter; | |
32 | +import org.thingsboard.server.gen.transport.TransportProtos; | |
33 | +import org.thingsboard.server.transport.coap.CoapTransportResource; | |
34 | + | |
35 | +import java.util.Optional; | |
36 | +import java.util.UUID; | |
37 | + | |
38 | +@Component | |
39 | +@Slf4j | |
40 | +public class ProtoCoapAdaptor implements CoapTransportAdaptor { | |
41 | + | |
42 | + @Override | |
43 | + public TransportProtos.PostTelemetryMsg convertToPostTelemetry(UUID sessionId, Request inbound, Descriptors.Descriptor telemetryMsgDescriptor) throws AdaptorException { | |
44 | + try { | |
45 | + return JsonConverter.convertToTelemetryProto(new JsonParser().parse(dynamicMsgToJson(inbound.getPayload(), telemetryMsgDescriptor))); | |
46 | + } catch (Exception e) { | |
47 | + throw new AdaptorException(e); | |
48 | + } | |
49 | + } | |
50 | + | |
51 | + @Override | |
52 | + public TransportProtos.PostAttributeMsg convertToPostAttributes(UUID sessionId, Request inbound, Descriptors.Descriptor attributesMsgDescriptor) throws AdaptorException { | |
53 | + try { | |
54 | + return JsonConverter.convertToAttributesProto(new JsonParser().parse(dynamicMsgToJson(inbound.getPayload(), attributesMsgDescriptor))); | |
55 | + } catch (Exception e) { | |
56 | + throw new AdaptorException(e); | |
57 | + } | |
58 | + } | |
59 | + | |
60 | + @Override | |
61 | + public TransportProtos.GetAttributeRequestMsg convertToGetAttributes(UUID sessionId, Request inbound) throws AdaptorException { | |
62 | + return CoapAdaptorUtils.toGetAttributeRequestMsg(inbound); | |
63 | + } | |
64 | + | |
65 | + @Override | |
66 | + public TransportProtos.ToDeviceRpcResponseMsg convertToDeviceRpcResponse(UUID sessionId, Request inbound) throws AdaptorException { | |
67 | + Optional<Integer> requestId = CoapTransportResource.getRequestId(inbound); | |
68 | + if (requestId.isEmpty()) { | |
69 | + throw new AdaptorException("Request id is missing!"); | |
70 | + } else { | |
71 | + try { | |
72 | + String payload = TransportProtos.ToDeviceRpcResponseMsg.parseFrom(inbound.getPayload()).getPayload(); | |
73 | + return TransportProtos.ToDeviceRpcResponseMsg.newBuilder().setRequestId(requestId.get()) | |
74 | + .setPayload(payload).build(); | |
75 | + } catch (InvalidProtocolBufferException e) { | |
76 | + throw new AdaptorException(e); | |
77 | + } | |
78 | + } | |
79 | + } | |
80 | + | |
81 | + @Override | |
82 | + public TransportProtos.ToServerRpcRequestMsg convertToServerRpcRequest(UUID sessionId, Request inbound) throws AdaptorException { | |
83 | + try { | |
84 | + return ProtoConverter.convertToServerRpcRequest(inbound.getPayload(), 0); | |
85 | + } catch (InvalidProtocolBufferException ex) { | |
86 | + throw new AdaptorException(ex); | |
87 | + } | |
88 | + } | |
89 | + | |
90 | + @Override | |
91 | + public TransportProtos.ClaimDeviceMsg convertToClaimDevice(UUID sessionId, Request inbound, TransportProtos.SessionInfoProto sessionInfo) throws AdaptorException { | |
92 | + DeviceId deviceId = new DeviceId(new UUID(sessionInfo.getDeviceIdMSB(), sessionInfo.getDeviceIdLSB())); | |
93 | + try { | |
94 | + return ProtoConverter.convertToClaimDeviceProto(deviceId, inbound.getPayload()); | |
95 | + } catch (InvalidProtocolBufferException ex) { | |
96 | + throw new AdaptorException(ex); | |
97 | + } | |
98 | + } | |
99 | + | |
100 | + @Override | |
101 | + public TransportProtos.ProvisionDeviceRequestMsg convertToProvisionRequestMsg(UUID sessionId, Request inbound) throws AdaptorException { | |
102 | + try { | |
103 | + return ProtoConverter.convertToProvisionRequestMsg(inbound.getPayload()); | |
104 | + } catch (InvalidProtocolBufferException ex) { | |
105 | + throw new AdaptorException(ex); | |
106 | + } | |
107 | + } | |
108 | + | |
109 | + @Override | |
110 | + public Response convertToPublish(boolean isConfirmable, TransportProtos.AttributeUpdateNotificationMsg msg) throws AdaptorException { | |
111 | + return getObserveNotification(isConfirmable, msg.toByteArray()); | |
112 | + } | |
113 | + | |
114 | + @Override | |
115 | + public Response convertToPublish(boolean isConfirmable, TransportProtos.ToDeviceRpcRequestMsg msg) throws AdaptorException { | |
116 | + return getObserveNotification(isConfirmable, msg.toByteArray()); | |
117 | + } | |
118 | + | |
119 | + @Override | |
120 | + public Response convertToPublish(TransportProtos.ToServerRpcResponseMsg msg) throws AdaptorException { | |
121 | + Response response = new Response(CoAP.ResponseCode.CONTENT); | |
122 | + response.setPayload(msg.toByteArray()); | |
123 | + return response; | |
124 | + } | |
125 | + | |
126 | + @Override | |
127 | + public Response convertToPublish(TransportProtos.GetAttributeResponseMsg msg) throws AdaptorException { | |
128 | + if (msg.getClientAttributeListCount() == 0 && msg.getSharedAttributeListCount() == 0) { | |
129 | + return new Response(CoAP.ResponseCode.NOT_FOUND); | |
130 | + } else { | |
131 | + Response response = new Response(CoAP.ResponseCode.CONTENT); | |
132 | + response.setPayload(msg.toByteArray()); | |
133 | + return response; | |
134 | + } | |
135 | + } | |
136 | + | |
137 | + private Response getObserveNotification(boolean confirmable, byte[] notification) { | |
138 | + Response response = new Response(CoAP.ResponseCode.CONTENT); | |
139 | + response.setPayload(notification); | |
140 | + response.setConfirmable(confirmable); | |
141 | + return response; | |
142 | + } | |
143 | + | |
144 | + private String dynamicMsgToJson(byte[] bytes, Descriptors.Descriptor descriptor) throws InvalidProtocolBufferException { | |
145 | + DynamicMessage dynamicMessage = DynamicMessage.parseFrom(descriptor, bytes); | |
146 | + return JsonFormat.printer().includingDefaultValueFields().print(dynamicMessage); | |
147 | + } | |
148 | + | |
149 | +} | ... | ... |
common/transport/coap/src/main/java/org/thingsboard/server/transport/coap/client/DeviceEmulator.java
deleted
100644 → 0
1 | -/** | |
2 | - * Copyright © 2016-2021 The Thingsboard Authors | |
3 | - * | |
4 | - * Licensed under the Apache License, Version 2.0 (the "License"); | |
5 | - * you may not use this file except in compliance with the License. | |
6 | - * You may obtain a copy of the License at | |
7 | - * | |
8 | - * http://www.apache.org/licenses/LICENSE-2.0 | |
9 | - * | |
10 | - * Unless required by applicable law or agreed to in writing, software | |
11 | - * distributed under the License is distributed on an "AS IS" BASIS, | |
12 | - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 | - * See the License for the specific language governing permissions and | |
14 | - * limitations under the License. | |
15 | - */ | |
16 | -package org.thingsboard.server.transport.coap.client; | |
17 | - | |
18 | -import java.io.IOException; | |
19 | -import java.util.Random; | |
20 | -import java.util.concurrent.ExecutorService; | |
21 | -import java.util.concurrent.Executors; | |
22 | -import java.util.concurrent.atomic.AtomicInteger; | |
23 | - | |
24 | -import com.fasterxml.jackson.core.JsonProcessingException; | |
25 | -import com.fasterxml.jackson.databind.JsonNode; | |
26 | -import lombok.extern.slf4j.Slf4j; | |
27 | -import org.eclipse.californium.core.CoapClient; | |
28 | -import org.eclipse.californium.core.CoapHandler; | |
29 | -import org.eclipse.californium.core.CoapResponse; | |
30 | -import org.eclipse.californium.core.coap.MediaTypeRegistry; | |
31 | -import org.thingsboard.server.common.msg.session.FeatureType; | |
32 | -import org.slf4j.Logger; | |
33 | -import org.slf4j.LoggerFactory; | |
34 | - | |
35 | -import com.fasterxml.jackson.databind.ObjectMapper; | |
36 | -import com.fasterxml.jackson.databind.node.ArrayNode; | |
37 | -import com.fasterxml.jackson.databind.node.ObjectNode; | |
38 | - | |
39 | -@Slf4j | |
40 | -public class DeviceEmulator { | |
41 | - | |
42 | - public static final String SN = "SN-" + new Random().nextInt(1000); | |
43 | - public static final String MODEL = "Model " + new Random().nextInt(1000); | |
44 | - private static final ObjectMapper mapper = new ObjectMapper(); | |
45 | - | |
46 | - private final String host; | |
47 | - private final int port; | |
48 | - private final String token; | |
49 | - | |
50 | - private CoapClient attributesClient; | |
51 | - private CoapClient telemetryClient; | |
52 | - private CoapClient rpcClient; | |
53 | - private String[] keys; | |
54 | - private ExecutorService executor = Executors.newFixedThreadPool(1); | |
55 | - private AtomicInteger seq = new AtomicInteger(100); | |
56 | - | |
57 | - private DeviceEmulator(String host, int port, String token, String keys) { | |
58 | - this.host = host; | |
59 | - this.port = port; | |
60 | - this.token = token; | |
61 | - this.attributesClient = new CoapClient(getFeatureTokenUrl(host, port, token, FeatureType.ATTRIBUTES)); | |
62 | - this.telemetryClient = new CoapClient(getFeatureTokenUrl(host, port, token, FeatureType.TELEMETRY)); | |
63 | - this.rpcClient = new CoapClient(getFeatureTokenUrl(host, port, token, FeatureType.RPC)); | |
64 | - this.keys = keys.split(","); | |
65 | - } | |
66 | - | |
67 | - public void start() { | |
68 | - executor.submit(new Runnable() { | |
69 | - | |
70 | - @Override | |
71 | - public void run() { | |
72 | - try { | |
73 | - sendObserveRequest(rpcClient); | |
74 | - while (!Thread.interrupted()) { | |
75 | - | |
76 | - | |
77 | - sendRequest(attributesClient, createAttributesRequest()); | |
78 | - sendRequest(telemetryClient, createTelemetryRequest()); | |
79 | - | |
80 | - Thread.sleep(1000); | |
81 | - } | |
82 | - } catch (Exception e) { | |
83 | - log.error("Error occurred while sending COAP requests", e); | |
84 | - } | |
85 | - } | |
86 | - | |
87 | - private void sendRequest(CoapClient client, JsonNode request) throws JsonProcessingException { | |
88 | - CoapResponse telemetryResponse = client.setTimeout(60000).post(mapper.writeValueAsString(request), | |
89 | - MediaTypeRegistry.APPLICATION_JSON); | |
90 | - log.info("Response: {}, {}", telemetryResponse.getCode(), telemetryResponse.getResponseText()); | |
91 | - } | |
92 | - | |
93 | - private void sendObserveRequest(CoapClient client) throws JsonProcessingException { | |
94 | - client.observe(new CoapHandler() { | |
95 | - @Override | |
96 | - public void onLoad(CoapResponse coapResponse) { | |
97 | - log.info("Command: {}, {}", coapResponse.getCode(), coapResponse.getResponseText()); | |
98 | - try { | |
99 | - JsonNode node = mapper.readTree(coapResponse.getResponseText()); | |
100 | - int requestId = node.get("id").asInt(); | |
101 | - String method = node.get("method").asText(); | |
102 | - ObjectNode params = (ObjectNode) node.get("params"); | |
103 | - ObjectNode response = mapper.createObjectNode(); | |
104 | - response.put("id", requestId); | |
105 | - response.set("response", params); | |
106 | - log.info("Command Response: {}, {}", requestId, mapper.writeValueAsString(response)); | |
107 | - CoapClient commandResponseClient = new CoapClient(getFeatureTokenUrl(host, port, token, FeatureType.RPC)); | |
108 | - commandResponseClient.post(new CoapHandler() { | |
109 | - @Override | |
110 | - public void onLoad(CoapResponse response) { | |
111 | - log.info("Command Response Ack: {}, {}", response.getCode(), response.getResponseText()); | |
112 | - } | |
113 | - | |
114 | - @Override | |
115 | - public void onError() { | |
116 | - //Do nothing | |
117 | - } | |
118 | - }, mapper.writeValueAsString(response), MediaTypeRegistry.APPLICATION_JSON); | |
119 | - | |
120 | - } catch (IOException e) { | |
121 | - log.error("Error occurred while processing COAP response", e); | |
122 | - } | |
123 | - } | |
124 | - | |
125 | - @Override | |
126 | - public void onError() { | |
127 | - //Do nothing | |
128 | - } | |
129 | - }); | |
130 | - } | |
131 | - | |
132 | - }); | |
133 | - } | |
134 | - | |
135 | - private ObjectNode createAttributesRequest() { | |
136 | - ObjectNode element = mapper.createObjectNode(); | |
137 | - element.put("serialNumber", SN); | |
138 | - element.put("model", MODEL); | |
139 | - return element; | |
140 | - } | |
141 | - | |
142 | - private ArrayNode createTelemetryRequest() { | |
143 | - ArrayNode rootNode = mapper.createArrayNode(); | |
144 | - for (String key : keys) { | |
145 | - ObjectNode element = mapper.createObjectNode(); | |
146 | - element.put(key, seq.incrementAndGet()); | |
147 | - rootNode.add(element); | |
148 | - } | |
149 | - return rootNode; | |
150 | - } | |
151 | - | |
152 | - protected void stop() { | |
153 | - executor.shutdownNow(); | |
154 | - } | |
155 | - | |
156 | - public static void main(String args[]) { | |
157 | - if (args.length != 4) { | |
158 | - System.out.println("Usage: java -jar " + DeviceEmulator.class.getSimpleName() + ".jar host port device_token keys"); | |
159 | - } | |
160 | - final DeviceEmulator emulator = new DeviceEmulator(args[0], Integer.parseInt(args[1]), args[2], args[3]); | |
161 | - emulator.start(); | |
162 | - Runtime.getRuntime().addShutdownHook(new Thread() { | |
163 | - @Override | |
164 | - public void run() { | |
165 | - emulator.stop(); | |
166 | - } | |
167 | - }); | |
168 | - } | |
169 | - | |
170 | - | |
171 | - private String getFeatureTokenUrl(String host, int port, String token, FeatureType featureType) { | |
172 | - return getBaseUrl(host, port) + token + "/" + featureType.name().toLowerCase(); | |
173 | - } | |
174 | - | |
175 | - private String getBaseUrl(String host, int port) { | |
176 | - return "coap://" + host + ":" + port + "/api/v1/"; | |
177 | - } | |
178 | - | |
179 | -} |
1 | +/** | |
2 | + * Copyright © 2016-2021 The Thingsboard Authors | |
3 | + * | |
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | |
5 | + * you may not use this file except in compliance with the License. | |
6 | + * You may obtain a copy of the License at | |
7 | + * | |
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | |
9 | + * | |
10 | + * Unless required by applicable law or agreed to in writing, software | |
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | |
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 | + * See the License for the specific language governing permissions and | |
14 | + * limitations under the License. | |
15 | + */ | |
16 | +package org.thingsboard.server.transport.coap.efento; | |
17 | + | |
18 | +import com.google.gson.JsonObject; | |
19 | +import lombok.AllArgsConstructor; | |
20 | +import lombok.Data; | |
21 | +import lombok.extern.slf4j.Slf4j; | |
22 | +import org.eclipse.californium.core.coap.CoAP; | |
23 | +import org.eclipse.californium.core.coap.Request; | |
24 | +import org.eclipse.californium.core.network.Exchange; | |
25 | +import org.eclipse.californium.core.server.resources.CoapExchange; | |
26 | +import org.eclipse.californium.core.server.resources.Resource; | |
27 | +import org.springframework.util.CollectionUtils; | |
28 | +import org.thingsboard.server.common.data.DeviceProfile; | |
29 | +import org.thingsboard.server.common.data.DeviceTransportType; | |
30 | +import org.thingsboard.server.common.data.device.profile.CoapDeviceProfileTransportConfiguration; | |
31 | +import org.thingsboard.server.common.data.device.profile.DeviceProfileTransportConfiguration; | |
32 | +import org.thingsboard.server.common.data.device.profile.EfentoCoapDeviceTypeConfiguration; | |
33 | +import org.thingsboard.server.common.transport.adaptor.AdaptorException; | |
34 | +import org.thingsboard.server.gen.transport.TransportProtos; | |
35 | +import org.thingsboard.server.gen.transport.coap.MeasurementTypeProtos; | |
36 | +import org.thingsboard.server.gen.transport.coap.MeasurementsProtos; | |
37 | +import org.thingsboard.server.transport.coap.AbstractCoapTransportResource; | |
38 | +import org.thingsboard.server.transport.coap.CoapTransportContext; | |
39 | +import org.thingsboard.server.transport.coap.efento.utils.CoapEfentoUtils; | |
40 | + | |
41 | +import java.util.ArrayList; | |
42 | +import java.util.List; | |
43 | +import java.util.Map; | |
44 | +import java.util.TreeMap; | |
45 | +import java.util.UUID; | |
46 | +import java.util.concurrent.TimeUnit; | |
47 | + | |
48 | +@Slf4j | |
49 | +public class CoapEfentoTransportResource extends AbstractCoapTransportResource { | |
50 | + | |
51 | + private static final int MEASUREMENTS_POSITION = 2; | |
52 | + private static final String MEASUREMENTS = "m"; | |
53 | + | |
54 | + public CoapEfentoTransportResource(CoapTransportContext context, String name) { | |
55 | + super(context, name); | |
56 | + this.setObservable(true); // enable observing | |
57 | + this.setObserveType(CoAP.Type.CON); // configure the notification type to CONs | |
58 | +// this.getAttributes().setObservable(); // mark observable in the Link-Format | |
59 | + } | |
60 | + | |
61 | + @Override | |
62 | + protected void processHandleGet(CoapExchange exchange) { | |
63 | + exchange.respond(CoAP.ResponseCode.METHOD_NOT_ALLOWED); | |
64 | + } | |
65 | + | |
66 | + @Override | |
67 | + protected void processHandlePost(CoapExchange exchange) { | |
68 | + Exchange advanced = exchange.advanced(); | |
69 | + Request request = advanced.getRequest(); | |
70 | + List<String> uriPath = request.getOptions().getUriPath(); | |
71 | + boolean validPath = uriPath.size() == MEASUREMENTS_POSITION && uriPath.get(1).equals(MEASUREMENTS); | |
72 | + if (!validPath) { | |
73 | + exchange.respond(CoAP.ResponseCode.BAD_REQUEST); | |
74 | + return; | |
75 | + } | |
76 | + byte[] bytes = request.getPayload(); | |
77 | + try { | |
78 | + MeasurementsProtos.ProtoMeasurements protoMeasurements = MeasurementsProtos.ProtoMeasurements.parseFrom(bytes); | |
79 | + log.trace("Successfully parsed Efento ProtoMeasurements: [{}]", protoMeasurements.getCloudToken()); | |
80 | + String token = protoMeasurements.getCloudToken(); | |
81 | + transportService.process(DeviceTransportType.COAP, TransportProtos.ValidateDeviceTokenRequestMsg.newBuilder().setToken(token).build(), | |
82 | + new CoapDeviceAuthCallback(transportContext, exchange, (sessionInfo, deviceProfile) -> { | |
83 | + UUID sessionId = new UUID(sessionInfo.getSessionIdMSB(), sessionInfo.getSessionIdLSB()); | |
84 | + try { | |
85 | + validateEfentoTransportConfiguration(deviceProfile); | |
86 | + List<EfentoMeasurements> efentoMeasurements = getEfentoMeasurements(protoMeasurements, sessionId); | |
87 | + transportService.process(sessionInfo, | |
88 | + transportContext.getEfentoCoapAdaptor().convertToPostTelemetry(sessionId, efentoMeasurements), | |
89 | + new CoapOkCallback(exchange, CoAP.ResponseCode.CREATED, CoAP.ResponseCode.INTERNAL_SERVER_ERROR)); | |
90 | + reportActivity(sessionInfo, false, false); | |
91 | + } catch (AdaptorException e) { | |
92 | + log.error("[{}] Failed to decode Efento ProtoMeasurements: ", sessionId, e); | |
93 | + exchange.respond(CoAP.ResponseCode.BAD_REQUEST); | |
94 | + } | |
95 | + })); | |
96 | + } catch (Exception e) { | |
97 | + log.error("Failed to decode Efento ProtoMeasurements: ", e); | |
98 | + exchange.respond(CoAP.ResponseCode.INTERNAL_SERVER_ERROR); | |
99 | + } | |
100 | + } | |
101 | + | |
102 | + @Override | |
103 | + public Resource getChild(String name) { | |
104 | + return this; | |
105 | + } | |
106 | + | |
107 | + private void validateEfentoTransportConfiguration(DeviceProfile deviceProfile) throws AdaptorException { | |
108 | + DeviceProfileTransportConfiguration transportConfiguration = deviceProfile.getProfileData().getTransportConfiguration(); | |
109 | + if (transportConfiguration instanceof CoapDeviceProfileTransportConfiguration) { | |
110 | + CoapDeviceProfileTransportConfiguration coapDeviceProfileTransportConfiguration = | |
111 | + (CoapDeviceProfileTransportConfiguration) transportConfiguration; | |
112 | + if (!(coapDeviceProfileTransportConfiguration.getCoapDeviceTypeConfiguration() instanceof EfentoCoapDeviceTypeConfiguration)) { | |
113 | + throw new AdaptorException("Invalid CoapDeviceTypeConfiguration type: " + coapDeviceProfileTransportConfiguration.getCoapDeviceTypeConfiguration().getClass().getSimpleName() + "!"); | |
114 | + } | |
115 | + } else { | |
116 | + throw new AdaptorException("Invalid DeviceProfileTransportConfiguration type" + transportConfiguration.getClass().getSimpleName() + "!"); | |
117 | + } | |
118 | + } | |
119 | + | |
120 | + private List<EfentoMeasurements> getEfentoMeasurements(MeasurementsProtos.ProtoMeasurements protoMeasurements, UUID sessionId) { | |
121 | + String serialNumber = CoapEfentoUtils.convertByteArrayToString(protoMeasurements.getSerialNum().toByteArray()); | |
122 | + boolean batteryStatus = protoMeasurements.getBatteryStatus(); | |
123 | + int measurementPeriodBase = protoMeasurements.getMeasurementPeriodBase(); | |
124 | + int measurementPeriodFactor = protoMeasurements.getMeasurementPeriodFactor(); | |
125 | + int signal = protoMeasurements.getSignal(); | |
126 | + List<MeasurementsProtos.ProtoChannel> channelsList = protoMeasurements.getChannelsList(); | |
127 | + Map<Long, JsonObject> valuesMap = new TreeMap<>(); | |
128 | + if (!CollectionUtils.isEmpty(channelsList)) { | |
129 | + int channel = 0; | |
130 | + JsonObject values; | |
131 | + for (MeasurementsProtos.ProtoChannel protoChannel : channelsList) { | |
132 | + channel++; | |
133 | + boolean isBinarySensor = false; | |
134 | + MeasurementTypeProtos.MeasurementType measurementType = protoChannel.getType(); | |
135 | + String measurementTypeName = measurementType.name(); | |
136 | + if (measurementType.equals(MeasurementTypeProtos.MeasurementType.OK_ALARM) | |
137 | + || measurementType.equals(MeasurementTypeProtos.MeasurementType.FLOODING)) { | |
138 | + isBinarySensor = true; | |
139 | + } | |
140 | + if (measurementPeriodFactor == 0 && isBinarySensor) { | |
141 | + measurementPeriodFactor = 14; | |
142 | + } else { | |
143 | + measurementPeriodFactor = 1; | |
144 | + } | |
145 | + int measurementPeriod = measurementPeriodBase * measurementPeriodFactor; | |
146 | + long measurementPeriodMillis = TimeUnit.SECONDS.toMillis(measurementPeriod); | |
147 | + long nextTransmissionAtMillis = TimeUnit.SECONDS.toMillis(protoMeasurements.getNextTransmissionAt()); | |
148 | + int startPoint = protoChannel.getStartPoint(); | |
149 | + int startTimestamp = protoChannel.getTimestamp(); | |
150 | + long startTimestampMillis = TimeUnit.SECONDS.toMillis(startTimestamp); | |
151 | + List<Integer> sampleOffsetsList = protoChannel.getSampleOffsetsList(); | |
152 | + if (!CollectionUtils.isEmpty(sampleOffsetsList)) { | |
153 | + int sampleOfssetsListSize = sampleOffsetsList.size(); | |
154 | + for (int i = 0; i < sampleOfssetsListSize; i++) { | |
155 | + int sampleOffset = sampleOffsetsList.get(i); | |
156 | + Integer previousSampleOffset = isBinarySensor && i > 0 ? sampleOffsetsList.get(i - 1) : null; | |
157 | + if (sampleOffset == -32768) { | |
158 | + log.warn("[{}],[{}] Sensor error value! Ignoring.", sessionId, sampleOffset); | |
159 | + } else { | |
160 | + switch (measurementType) { | |
161 | + case TEMPERATURE: | |
162 | + values = valuesMap.computeIfAbsent(startTimestampMillis, k -> | |
163 | + CoapEfentoUtils.setDefaultMeasurements(serialNumber, batteryStatus, measurementPeriod, nextTransmissionAtMillis, signal, k)); | |
164 | + values.addProperty("temperature_" + channel, ((double) (startPoint + sampleOffset)) / 10f); | |
165 | + startTimestampMillis = startTimestampMillis + measurementPeriodMillis; | |
166 | + break; | |
167 | + case HUMIDITY: | |
168 | + values = valuesMap.computeIfAbsent(startTimestampMillis, k -> | |
169 | + CoapEfentoUtils.setDefaultMeasurements(serialNumber, batteryStatus, measurementPeriod, nextTransmissionAtMillis, signal, k)); | |
170 | + values.addProperty("humidity_" + channel, (double) (startPoint + sampleOffset)); | |
171 | + startTimestampMillis = startTimestampMillis + measurementPeriodMillis; | |
172 | + break; | |
173 | + case ATMOSPHERIC_PRESSURE: | |
174 | + values = valuesMap.computeIfAbsent(startTimestampMillis, k -> | |
175 | + CoapEfentoUtils.setDefaultMeasurements(serialNumber, batteryStatus, measurementPeriod, nextTransmissionAtMillis, signal, k)); | |
176 | + values.addProperty("pressure_" + channel, (double) (startPoint + sampleOffset) / 10f); | |
177 | + startTimestampMillis = startTimestampMillis + measurementPeriodMillis; | |
178 | + break; | |
179 | + case DIFFERENTIAL_PRESSURE: | |
180 | + values = valuesMap.computeIfAbsent(startTimestampMillis, k -> | |
181 | + CoapEfentoUtils.setDefaultMeasurements(serialNumber, batteryStatus, measurementPeriod, nextTransmissionAtMillis, signal, k)); | |
182 | + values.addProperty("pressure_diff_" + channel, (double) (startPoint + sampleOffset)); | |
183 | + startTimestampMillis = startTimestampMillis + measurementPeriodMillis; | |
184 | + break; | |
185 | + case OK_ALARM: | |
186 | + boolean currentIsOk = sampleOffset < 0; | |
187 | + if (previousSampleOffset != null) { | |
188 | + boolean previousIsOk = previousSampleOffset < 0; | |
189 | + boolean isOk = previousIsOk && currentIsOk; | |
190 | + boolean isAlarm = !previousIsOk && !currentIsOk; | |
191 | + if (isOk || isAlarm) { | |
192 | + break; | |
193 | + } | |
194 | + } | |
195 | + String data = currentIsOk ? "OK" : "ALARM"; | |
196 | + long sampleOffsetMillis = TimeUnit.SECONDS.toMillis(sampleOffset); | |
197 | + long measurementTimestamp = startTimestampMillis + Math.abs(sampleOffsetMillis); | |
198 | + values = valuesMap.computeIfAbsent(measurementTimestamp - 1000, k -> | |
199 | + CoapEfentoUtils.setDefaultMeasurements(serialNumber, batteryStatus, measurementPeriod, nextTransmissionAtMillis, signal, k)); | |
200 | + values.addProperty("ok_alarm_" + channel, data); | |
201 | + break; | |
202 | + case NO_SENSOR: | |
203 | + case UNRECOGNIZED: | |
204 | + log.trace("[{}][{}] Sensor error value! Ignoring.", sessionId, measurementTypeName); | |
205 | + break; | |
206 | + default: | |
207 | + log.trace("[{}],[{}] Unsupported measurementType! Ignoring.", sessionId, measurementTypeName); | |
208 | + break; | |
209 | + } | |
210 | + } | |
211 | + } | |
212 | + } else { | |
213 | + log.trace("[{}][{}] sampleOffsetsList list is empty!", sessionId, measurementTypeName); | |
214 | + } | |
215 | + } | |
216 | + } else { | |
217 | + throw new IllegalStateException("[" + sessionId + "]: Failed to get Efento measurements, reason: channels list is empty!"); | |
218 | + } | |
219 | + if (!CollectionUtils.isEmpty(valuesMap)) { | |
220 | + List<EfentoMeasurements> efentoMeasurements = new ArrayList<>(); | |
221 | + for (Long ts : valuesMap.keySet()) { | |
222 | + EfentoMeasurements measurement = new EfentoMeasurements(ts, valuesMap.get(ts)); | |
223 | + efentoMeasurements.add(measurement); | |
224 | + } | |
225 | + return efentoMeasurements; | |
226 | + } else { | |
227 | + throw new IllegalStateException("[" + sessionId + "]: Failed to collect Efento measurements, reason, values map is empty!"); | |
228 | + } | |
229 | + } | |
230 | + | |
231 | + @Data | |
232 | + @AllArgsConstructor | |
233 | + public static class EfentoMeasurements { | |
234 | + | |
235 | + private long ts; | |
236 | + private JsonObject values; | |
237 | + | |
238 | + } | |
239 | +} | ... | ... |
1 | +/** | |
2 | + * Copyright © 2016-2021 The Thingsboard Authors | |
3 | + * | |
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | |
5 | + * you may not use this file except in compliance with the License. | |
6 | + * You may obtain a copy of the License at | |
7 | + * | |
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | |
9 | + * | |
10 | + * Unless required by applicable law or agreed to in writing, software | |
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | |
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 | + * See the License for the specific language governing permissions and | |
14 | + * limitations under the License. | |
15 | + */ | |
16 | +package org.thingsboard.server.transport.coap.efento.adaptor; | |
17 | + | |
18 | +import com.google.gson.Gson; | |
19 | +import lombok.extern.slf4j.Slf4j; | |
20 | +import org.springframework.stereotype.Component; | |
21 | +import org.thingsboard.server.common.transport.adaptor.AdaptorException; | |
22 | +import org.thingsboard.server.common.transport.adaptor.JsonConverter; | |
23 | +import org.thingsboard.server.gen.transport.TransportProtos; | |
24 | +import org.thingsboard.server.transport.coap.efento.CoapEfentoTransportResource; | |
25 | + | |
26 | +import java.util.List; | |
27 | +import java.util.UUID; | |
28 | + | |
29 | +@Component | |
30 | +@Slf4j | |
31 | +public class EfentoCoapAdaptor { | |
32 | + | |
33 | + private static final Gson gson = new Gson(); | |
34 | + | |
35 | + public TransportProtos.PostTelemetryMsg convertToPostTelemetry(UUID sessionId, List<CoapEfentoTransportResource.EfentoMeasurements> measurements) throws AdaptorException { | |
36 | + try { | |
37 | + return JsonConverter.convertToTelemetryProto(gson.toJsonTree(measurements)); | |
38 | + } catch (Exception ex) { | |
39 | + log.warn("[{}] Failed to convert EfentoMeasurements to PostTelemetry request!", sessionId); | |
40 | + throw new AdaptorException(ex); | |
41 | + } | |
42 | + } | |
43 | +} | ... | ... |
1 | +/** | |
2 | + * Copyright © 2016-2021 The Thingsboard Authors | |
3 | + * | |
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | |
5 | + * you may not use this file except in compliance with the License. | |
6 | + * You may obtain a copy of the License at | |
7 | + * | |
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | |
9 | + * | |
10 | + * Unless required by applicable law or agreed to in writing, software | |
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | |
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 | + * See the License for the specific language governing permissions and | |
14 | + * limitations under the License. | |
15 | + */ | |
16 | +package org.thingsboard.server.transport.coap.efento.utils; | |
17 | + | |
18 | +import com.google.gson.JsonObject; | |
19 | + | |
20 | +import java.text.SimpleDateFormat; | |
21 | +import java.util.Date; | |
22 | +import java.util.TimeZone; | |
23 | + | |
24 | +public class CoapEfentoUtils { | |
25 | + | |
26 | + public static String convertByteArrayToString(byte[] a) { | |
27 | + StringBuilder out = new StringBuilder(); | |
28 | + for (byte b : a) { | |
29 | + out.append(String.format("%02X", b)); | |
30 | + } | |
31 | + return out.toString(); | |
32 | + } | |
33 | + | |
34 | + public static String convertTimestampToUtcString(long timestampInMillis) { | |
35 | + String dateFormat = "yyyy-MM-dd HH:mm:ss"; | |
36 | + String utcZone = "UTC"; | |
37 | + SimpleDateFormat simpleDateFormat = new SimpleDateFormat(dateFormat); | |
38 | + simpleDateFormat.setTimeZone(TimeZone.getTimeZone(utcZone)); | |
39 | + return String.format("%s UTC", simpleDateFormat.format(new Date(timestampInMillis))); | |
40 | + } | |
41 | + | |
42 | + public static JsonObject setDefaultMeasurements(String serialNumber, boolean batteryStatus, long measurementPeriod, long nextTransmissionAtMillis, long signal, long startTimestampMillis) { | |
43 | + JsonObject values = new JsonObject(); | |
44 | + values.addProperty("serial", serialNumber); | |
45 | + values.addProperty("battery", batteryStatus ? "ok" : "low"); | |
46 | + values.addProperty("measured_at", convertTimestampToUtcString(startTimestampMillis)); | |
47 | + values.addProperty("next_transmission_at", convertTimestampToUtcString(nextTransmissionAtMillis)); | |
48 | + values.addProperty("signal", signal); | |
49 | + values.addProperty("measurement_interval", measurementPeriod); | |
50 | + return values; | |
51 | + } | |
52 | + | |
53 | +} | ... | ... |
1 | +/** | |
2 | + * Copyright © 2016-2021 The Thingsboard Authors | |
3 | + * | |
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | |
5 | + * you may not use this file except in compliance with the License. | |
6 | + * You may obtain a copy of the License at | |
7 | + * | |
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | |
9 | + * | |
10 | + * Unless required by applicable law or agreed to in writing, software | |
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | |
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 | + * See the License for the specific language governing permissions and | |
14 | + * limitations under the License. | |
15 | + */ | |
16 | +syntax = "proto3"; | |
17 | + | |
18 | +option java_package = "org.thingsboard.server.gen.transport.coap"; | |
19 | +option java_outer_classname = "MeasurementTypeProtos"; | |
20 | + | |
21 | +enum MeasurementType { | |
22 | + NO_SENSOR = 0; | |
23 | + | |
24 | + /* [°C] - Celsius degree. Resolution 0.1°C. Range [-273.2-4000.0]. Type: Continuous */ | |
25 | + TEMPERATURE = 1; | |
26 | + | |
27 | + /* [% RH] - Relative humidity. Resolution 1%. Range [0-100]. Type: Continuous */ | |
28 | + HUMIDITY = 2; | |
29 | + | |
30 | + /* [hPa] - Hectopascal (1hPa = 100Pa). Resolution 0.1hPa. Range: [1.0-2000.0]. Type: Continuous */ | |
31 | + ATMOSPHERIC_PRESSURE = 3; | |
32 | + | |
33 | + /* [Pa] - Pascal. Resolution 1Pa. Range [-10000-10000]Type: Continuous */ | |
34 | + DIFFERENTIAL_PRESSURE = 4; | |
35 | + | |
36 | + /* Sign indicates state: (+) ALARM, (-) OK. Type: Binary */ | |
37 | + OK_ALARM = 5; | |
38 | + | |
39 | + /* [IAQ] - Iaq index. Resolution 1IAQ. Range [0-500]. Sensor return also calibration status */ | |
40 | + /* as offset to measured value: */ | |
41 | + /* - offset 3000: Sensor not stabilized (always returns 25 IAQ value) */ | |
42 | + /* - offset 2000: Calibration required (sensor returns not accurate values) */ | |
43 | + /* - offset 1000: Calibration on-going (sensor returns not accurate values) */ | |
44 | + /* - offset 0: Calibration done (best accuracy of IAQ sensor) */ | |
45 | + /* Type: Continuous */ | |
46 | + IAQ = 6; | |
47 | + | |
48 | + /* Sign indicates water presence: (+) water not detected, (-) water detected. Type: Binary */ | |
49 | + FLOODING = 7; | |
50 | + | |
51 | + /* [NB] Number of pulses. Resolution 1 pulse. Range [0-16711679]. Type: Continuous */ | |
52 | + PULSE_CNT = 8; | |
53 | + | |
54 | + /* [Wh] - Watthour; Resolution 1Wh. Range [0-16711679]. Number of Watthours in a single period. Type: Continuous */ | |
55 | + ELECTRICITY_METER = 9; | |
56 | + | |
57 | + /* [l] - Liter. Resolution 1l. Range [0-16711679]. Number of litres in a single period. Type: Continuous */ | |
58 | + WATER_METER = 10; | |
59 | + | |
60 | + /* [kPa] - Kilopascal (1kPa = 1000Pa); Resolution 1kPa. Range [-1000-0]. Soil moisture (tension). Type: Continuous */ | |
61 | + SOIL_MOISTURE = 11; | |
62 | + | |
63 | + /* [ppm] - Parts per million. Resolution 1ppm. Range [0-1000000]. Carbon monoxide concentration. Type: Continuous */ | |
64 | + CO_GAS = 12; | |
65 | + | |
66 | + /* [ppm] - Parts per million. Resolution 0.01ppm. Range [0-1000000.00]. Nitrogen dioxide concentration. Type: Continuous*/ | |
67 | + NO2_GAS = 13; | |
68 | + | |
69 | + /* [ppm] - Parts per million. Resolution 1ppm. Range [0-1000000]. Hydrogen sulfide concentration. Type: Continuous */ | |
70 | + H2S_GAS = 14; | |
71 | + | |
72 | + /* [lx] - Illuminance. Resolution 0.1lx. Range [0-100000.0]. Type: Continuous */ | |
73 | + AMBIENT_LIGHT = 15; | |
74 | + | |
75 | + /* [µg/m^3] - Micro gram per cubic meter. Resolution 1µg/m^3 Range [0-1000]. */ | |
76 | + /* particles with an aerodynamic diameter less than 1 micrometer. Type: Continuous */ | |
77 | + PM_1_0 = 16; // µg/m^3 | |
78 | + | |
79 | + /* [µg/m^3] - Micro gram per cubic meter. Resolution 1µg/m^3 Range [0-1000]. */ | |
80 | + /* particles with an aerodynamic diameter less than 2.5 micrometers. Type: Continuous */ | |
81 | + PM_2_5 = 17; // µg/m^3 | |
82 | + | |
83 | + /* [µg/m^3] - Micro gram per cubic meter. Resolution 1µg/m^3 Range [0-1000]. */ | |
84 | + /* particles with an aerodynamic diameter less than 10 micrometers. Type: Continuous */ | |
85 | + PM_10_0 = 18; // µg/m^3 | |
86 | + | |
87 | + /* [dB] - Decibels. Resolution 0.1 dB. Range: [0-130.0]. Noise level. Type: Continuous */ | |
88 | + NOISE_LEVEL = 19; // 0.1 dB | |
89 | + | |
90 | + /* [ppm] - Parts per million. Resolution 1ppm. Range [0-1000000]. Ammonia concentration. Type: Continuous */ | |
91 | + NH3_GAS = 20; | |
92 | + | |
93 | + /* [ppm] - Parts per million. Resolution 1ppm. Range [0-1000000]. Methane concentration. Type: Continuous */ | |
94 | + CH4_GAS = 21; | |
95 | +} | |
96 | + | |
97 | + | ... | ... |
1 | +/** | |
2 | + * Copyright © 2016-2021 The Thingsboard Authors | |
3 | + * | |
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | |
5 | + * you may not use this file except in compliance with the License. | |
6 | + * You may obtain a copy of the License at | |
7 | + * | |
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | |
9 | + * | |
10 | + * Unless required by applicable law or agreed to in writing, software | |
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | |
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 | + * See the License for the specific language governing permissions and | |
14 | + * limitations under the License. | |
15 | + */ | |
16 | +syntax = "proto3"; | |
17 | +import "proto_measurement_types.proto"; | |
18 | + | |
19 | +option java_package = "org.thingsboard.server.gen.transport.coap"; | |
20 | +option java_outer_classname = "MeasurementsProtos"; | |
21 | + | |
22 | +message ProtoChannel{ | |
23 | + /* Type of channel */ | |
24 | + MeasurementType type = 1; | |
25 | + | |
26 | + /* Timestamp of the first sample (the oldest one) in seconds since UNIX EPOCH 01-01-1970 */ | |
27 | + int32 timestamp = 2; | |
28 | + | |
29 | + /* Only used for 'Continuous' sensor types. Value used as the starting point for calculating the values of all */ | |
30 | + /* measurements in the package. */ | |
31 | + /* Format defined by 'MeasurementType' field */ | |
32 | + sint32 start_point = 4; | |
33 | + | |
34 | + /* 'Continuous' sensor types */ | |
35 | + /* Value of the offset from the 'start_point' for each measurement in the package. The oldest sample first ([0]). */ | |
36 | + /* 'sample_offsets' format defined by 'MeasurementType' field. */ | |
37 | + /* Example: MeasurementType = 1 (temperature), start_point = 100, sample_offsets[0] = 15, sample_offsets[1] = 20 */ | |
38 | + /* 1st sample in the package temperature value = 11.5 °C, 2nd sample in the package temperature value = 12 °C */ | |
39 | + /* Calculating timestamps of the measurements: timestamp = 1606391700, measurement_period_base = 60, */ | |
40 | + /* measurement_period_factor = 1. Timestamp of the 1st sample = 1606391700, timestamp of the 2nd sample = 1606391760 */ | |
41 | + /* 'Binary' sensor types: */ | |
42 | + /* Absolute value of the 'sample_offsets' field indicates the offset in seconds from 'timestamp' field. */ | |
43 | + /* Sign (- or +) indicates the state of measurements depend of sensor type. */ | |
44 | + /* Value of this field equals to '1' or '-1' indicates the state at the 'timestamp'. Other values */ | |
45 | + /* indicate the state of the relay at the time (in seconds) equal to 'timestamp' + value. */ | |
46 | + /* Values of this field are incremented starting from 1 (1->0: state at the time */ | |
47 | + /* of 'timestamp', 2->1: state at the time equal to 'timestamp' + 1 s, 3->2 : */ | |
48 | + /* state at the time equal to 'timestamp' + 2 s, etc.). The first and the last sample define the time range of the */ | |
49 | + /* measurements. Only state changes in the time range are included in the 'sample_offsets' field */ | |
50 | + /* Examples: if 'timestamp' value is 1553518060 and 'sample_offsets' equals '1', it means that at 1553518060 the state */ | |
51 | + /* was high, if 'timestamp' value is 1553518060 and 'sample_offsets' equals '-9', it means at 1553518068 the state was low */ | |
52 | + repeated sint32 sample_offsets = 5 [packed=true]; | |
53 | + | |
54 | + /* Deprecated - configuration is sent to endpoint 'c' */ | |
55 | + //int32 lo_threshold = 6; | |
56 | + | |
57 | + /* Deprecated - configuration is sent to endpoint 'c' */ | |
58 | + //int32 hi_threshold = 7; | |
59 | + | |
60 | + /* Deprecated - configurationis sent to endpoint 'c' */ | |
61 | + //int32 diff_threshold = 8; | |
62 | + } | |
63 | + | |
64 | +message ProtoMeasurements { | |
65 | + | |
66 | + /* serial number of the device */ | |
67 | + bytes serial_num = 1; | |
68 | + | |
69 | + /* true - battery ok, false - battery low */ | |
70 | + bool battery_status = 2; | |
71 | + | |
72 | + /* 'Measurement_period_base' and 'measurement_period_factor' define how often the measurements are taken. */ | |
73 | + /* Sensors of 'Continuous' type take measurement each Measurement_period_base * measurement_period_factor. */ | |
74 | + /* Sensors of 'Binary' type take measurement each Measurement_period_base. */ | |
75 | + /* For backward compatibility with versions 5.x in case of binary/mixed sensors, if the 'measurement_period_factor' is */ | |
76 | + /* not sent (equal to 0), then the default value '14' shall be used for period calculation. */ | |
77 | + /* For backward compatibility with versions 5.x in case of continues sensors, if the measurement_period_factor is */ | |
78 | + /* not sent (equal to 0), then the default value '1' shall be used for period calculation. */ | |
79 | + /* measurement period base in seconds */ | |
80 | + uint32 measurement_period_base = 3; | |
81 | + | |
82 | + /* Measurement period factor */ | |
83 | + uint32 measurement_period_factor = 8; | |
84 | + | |
85 | + repeated ProtoChannel channels = 4; | |
86 | + | |
87 | + /* Timestamp of the next scheduled transmission. If the device will not send data until this time, */ | |
88 | + /* it should be considered as 'lost' */ | |
89 | + uint32 next_transmission_at = 5; | |
90 | + | |
91 | + /* reason of transmission - unsigned integer where each bit indicates different */ | |
92 | + /* possible communication reason. Can be more than one */ | |
93 | + /* - bit 0: first message after sensor reset */ | |
94 | + /* - bit 1: user button triggered */ | |
95 | + /* - bit 2: user BLE triggered */ | |
96 | + /* - bit 3-7: number of retries -> incremented after each unsuccessful transmission. Max value 4. */ | |
97 | + /* Set to 0 after a successful transmission. */ | |
98 | + /* - bit 8: channel 1 lower threshold exceeded */ | |
99 | + /* - bit 9: channel 1 lower threshold returned */ | |
100 | + /* - bit 10: channel 1 higher threshold exceeded */ | |
101 | + /* - bit 11: channel 1 higher threshold returned */ | |
102 | + /* - bit 12: channel 1 differential threshold crossed */ | |
103 | + /* - bits 13-17: channel 2 thresholds (same as for channel 1) */ | |
104 | + /* - bits 18-22: channel 3 thresholds (same as for channel 1) */ | |
105 | + /* - bits 23-27: channel 4 or 5 or 6 thresholds (same as for channel 1) */ | |
106 | + uint32 transfer_reason = 6; | |
107 | + | |
108 | + /* Signal strength level mapped from RSSI */ | |
109 | + /* - 0 : 113 dBm or less */ | |
110 | + /* - 1 : 111 dBm */ | |
111 | + /* - 2...30 : 109...-53 dBm */ | |
112 | + /* - 31 : -51 dBm or greater */ | |
113 | + /* - 99 : Not known or not detectable */ | |
114 | + uint32 signal = 7; | |
115 | + | |
116 | + /* Hash of the current configuration. Hash value changes each time a device receives a new configuration */ | |
117 | + uint32 hash = 9; | |
118 | + | |
119 | + /* Optional string up to 36 bytes long. Can be set to any user define value or hold device's IMEI */ | |
120 | + string cloud_token = 16; | |
121 | +} | |
\ No newline at end of file | ... | ... |
... | ... | @@ -73,6 +73,9 @@ public class ProtoConverter { |
73 | 73 | } |
74 | 74 | |
75 | 75 | public static TransportProtos.ClaimDeviceMsg convertToClaimDeviceProto(DeviceId deviceId, byte[] bytes) throws InvalidProtocolBufferException { |
76 | + if (bytes == null) { | |
77 | + return buildClaimDeviceMsg(deviceId, DataConstants.DEFAULT_SECRET_KEY, 0); | |
78 | + } | |
76 | 79 | TransportApiProtos.ClaimDevice proto = TransportApiProtos.ClaimDevice.parseFrom(bytes); |
77 | 80 | String secretKey = proto.getSecretKey() != null ? proto.getSecretKey() : DataConstants.DEFAULT_SECRET_KEY; |
78 | 81 | long durationMs = proto.getDurationMs(); | ... | ... |
... | ... | @@ -41,6 +41,9 @@ import org.thingsboard.server.common.data.DeviceProfileProvisionType; |
41 | 41 | import org.thingsboard.server.common.data.DeviceProfileType; |
42 | 42 | import org.thingsboard.server.common.data.DeviceTransportType; |
43 | 43 | import org.thingsboard.server.common.data.Tenant; |
44 | +import org.thingsboard.server.common.data.device.profile.CoapDeviceProfileTransportConfiguration; | |
45 | +import org.thingsboard.server.common.data.device.profile.CoapDeviceTypeConfiguration; | |
46 | +import org.thingsboard.server.common.data.device.profile.DefaultCoapDeviceTypeConfiguration; | |
44 | 47 | import org.thingsboard.server.common.data.device.profile.DefaultDeviceProfileConfiguration; |
45 | 48 | import org.thingsboard.server.common.data.device.profile.DefaultDeviceProfileTransportConfiguration; |
46 | 49 | import org.thingsboard.server.common.data.device.profile.DeviceProfileAlarm; |
... | ... | @@ -49,6 +52,7 @@ import org.thingsboard.server.common.data.device.profile.DeviceProfileTransportC |
49 | 52 | import org.thingsboard.server.common.data.device.profile.DisabledDeviceProfileProvisionConfiguration; |
50 | 53 | import org.thingsboard.server.common.data.device.profile.MqttDeviceProfileTransportConfiguration; |
51 | 54 | import org.thingsboard.server.common.data.device.profile.ProtoTransportPayloadConfiguration; |
55 | +import org.thingsboard.server.common.data.device.profile.TransportPayloadTypeConfiguration; | |
52 | 56 | import org.thingsboard.server.common.data.id.DeviceProfileId; |
53 | 57 | import org.thingsboard.server.common.data.id.TenantId; |
54 | 58 | import org.thingsboard.server.common.data.page.PageData; |
... | ... | @@ -355,11 +359,17 @@ public class DeviceProfileServiceImpl extends AbstractEntityService implements D |
355 | 359 | if (mqttTransportConfiguration.getTransportPayloadTypeConfiguration() instanceof ProtoTransportPayloadConfiguration) { |
356 | 360 | ProtoTransportPayloadConfiguration protoTransportPayloadTypeConfiguration = |
357 | 361 | (ProtoTransportPayloadConfiguration) mqttTransportConfiguration.getTransportPayloadTypeConfiguration(); |
358 | - try { | |
359 | - validateTransportProtoSchema(protoTransportPayloadTypeConfiguration.getDeviceAttributesProtoSchema(), ATTRIBUTES_PROTO_SCHEMA); | |
360 | - validateTransportProtoSchema(protoTransportPayloadTypeConfiguration.getDeviceTelemetryProtoSchema(), TELEMETRY_PROTO_SCHEMA); | |
361 | - } catch (Exception exception) { | |
362 | - throw new DataValidationException(exception.getMessage()); | |
362 | + validateProtoSchemas(protoTransportPayloadTypeConfiguration); | |
363 | + } | |
364 | + } else if (transportConfiguration instanceof CoapDeviceProfileTransportConfiguration) { | |
365 | + CoapDeviceProfileTransportConfiguration coapDeviceProfileTransportConfiguration = (CoapDeviceProfileTransportConfiguration) transportConfiguration; | |
366 | + CoapDeviceTypeConfiguration coapDeviceTypeConfiguration = coapDeviceProfileTransportConfiguration.getCoapDeviceTypeConfiguration(); | |
367 | + if (coapDeviceTypeConfiguration instanceof DefaultCoapDeviceTypeConfiguration) { | |
368 | + DefaultCoapDeviceTypeConfiguration defaultCoapDeviceTypeConfiguration = (DefaultCoapDeviceTypeConfiguration) coapDeviceTypeConfiguration; | |
369 | + TransportPayloadTypeConfiguration transportPayloadTypeConfiguration = defaultCoapDeviceTypeConfiguration.getTransportPayloadTypeConfiguration(); | |
370 | + if (transportPayloadTypeConfiguration instanceof ProtoTransportPayloadConfiguration) { | |
371 | + ProtoTransportPayloadConfiguration protoTransportPayloadConfiguration = (ProtoTransportPayloadConfiguration) transportPayloadTypeConfiguration; | |
372 | + validateProtoSchemas(protoTransportPayloadConfiguration); | |
363 | 373 | } |
364 | 374 | } |
365 | 375 | } |
... | ... | @@ -403,6 +413,15 @@ public class DeviceProfileServiceImpl extends AbstractEntityService implements D |
403 | 413 | } |
404 | 414 | } |
405 | 415 | |
416 | + private void validateProtoSchemas(ProtoTransportPayloadConfiguration protoTransportPayloadTypeConfiguration) { | |
417 | + try { | |
418 | + validateTransportProtoSchema(protoTransportPayloadTypeConfiguration.getDeviceAttributesProtoSchema(), ATTRIBUTES_PROTO_SCHEMA); | |
419 | + validateTransportProtoSchema(protoTransportPayloadTypeConfiguration.getDeviceTelemetryProtoSchema(), TELEMETRY_PROTO_SCHEMA); | |
420 | + } catch (Exception exception) { | |
421 | + throw new DataValidationException(exception.getMessage()); | |
422 | + } | |
423 | + } | |
424 | + | |
406 | 425 | private void validateTransportProtoSchema(String schema, String schemaName) throws IllegalArgumentException { |
407 | 426 | ProtoParser schemaParser = new ProtoParser(LOCATION, schema.toCharArray()); |
408 | 427 | ProtoFileElement protoFileElement; | ... | ... |
... | ... | @@ -42,6 +42,7 @@ import org.thingsboard.server.common.data.EntityView; |
42 | 42 | import org.thingsboard.server.common.data.Tenant; |
43 | 43 | import org.thingsboard.server.common.data.device.DeviceSearchQuery; |
44 | 44 | import org.thingsboard.server.common.data.device.credentials.BasicMqttCredentials; |
45 | +import org.thingsboard.server.common.data.device.data.CoapDeviceTransportConfiguration; | |
45 | 46 | import org.thingsboard.server.common.data.device.data.DefaultDeviceConfiguration; |
46 | 47 | import org.thingsboard.server.common.data.device.data.DefaultDeviceTransportConfiguration; |
47 | 48 | import org.thingsboard.server.common.data.device.data.DeviceData; |
... | ... | @@ -242,6 +243,9 @@ public class DeviceServiceImpl extends AbstractEntityService implements DeviceSe |
242 | 243 | case LWM2M: |
243 | 244 | deviceData.setTransportConfiguration(new Lwm2mDeviceTransportConfiguration()); |
244 | 245 | break; |
246 | + case COAP: | |
247 | + deviceData.setTransportConfiguration(new CoapDeviceTransportConfiguration()); | |
248 | + break; | |
245 | 249 | } |
246 | 250 | } |
247 | 251 | return deviceData; | ... | ... |
... | ... | @@ -65,7 +65,7 @@ |
65 | 65 | <jackson-annotations.version>2.12.1</jackson-annotations.version> |
66 | 66 | <jackson-core.version>2.12.1</jackson-core.version> |
67 | 67 | <json-schema-validator.version>2.2.6</json-schema-validator.version> |
68 | - <californium.version>1.0.2</californium.version> | |
68 | + <californium.version>2.6.1</californium.version> | |
69 | 69 | <gson.version>2.6.2</gson.version> |
70 | 70 | <freemarker.version>2.3.30</freemarker.version> |
71 | 71 | <mail.version>1.6.2</mail.version> | ... | ... |
... | ... | @@ -97,6 +97,7 @@ import { DeviceProfileDialogComponent } from '@home/components/profile/device-pr |
97 | 97 | import { DeviceProfileAutocompleteComponent } from '@home/components/profile/device-profile-autocomplete.component'; |
98 | 98 | import { MqttDeviceProfileTransportConfigurationComponent } from '@home/components/profile/device/mqtt-device-profile-transport-configuration.component'; |
99 | 99 | import { Lwm2mDeviceProfileTransportConfigurationComponent } from '@home/components/profile/device/lwm2m-device-profile-transport-configuration.component'; |
100 | +import {CoapDeviceProfileTransportConfigurationComponent} from '@home/components/profile/device/coap-device-profile-transport-configuration.component'; | |
100 | 101 | import { DeviceProfileAlarmsComponent } from '@home/components/profile/alarm/device-profile-alarms.component'; |
101 | 102 | import { DeviceProfileAlarmComponent } from '@home/components/profile/alarm/device-profile-alarm.component'; |
102 | 103 | import { CreateAlarmRulesComponent } from '@home/components/profile/alarm/create-alarm-rules.component'; |
... | ... | @@ -213,6 +214,7 @@ import { DisplayWidgetTypesPanelComponent } from '@home/components/dashboard-pag |
213 | 214 | DefaultDeviceProfileTransportConfigurationComponent, |
214 | 215 | MqttDeviceProfileTransportConfigurationComponent, |
215 | 216 | Lwm2mDeviceProfileTransportConfigurationComponent, |
217 | + CoapDeviceProfileTransportConfigurationComponent, | |
216 | 218 | DeviceProfileTransportConfigurationComponent, |
217 | 219 | CreateAlarmRulesComponent, |
218 | 220 | AlarmRuleComponent, |
... | ... | @@ -315,6 +317,7 @@ import { DisplayWidgetTypesPanelComponent } from '@home/components/dashboard-pag |
315 | 317 | DefaultDeviceProfileTransportConfigurationComponent, |
316 | 318 | MqttDeviceProfileTransportConfigurationComponent, |
317 | 319 | Lwm2mDeviceProfileTransportConfigurationComponent, |
320 | + CoapDeviceProfileTransportConfigurationComponent, | |
318 | 321 | DeviceProfileTransportConfigurationComponent, |
319 | 322 | CreateAlarmRulesComponent, |
320 | 323 | AlarmRuleComponent, | ... | ... |
1 | +<!-- | |
2 | + | |
3 | + Copyright © 2016-2021 The Thingsboard Authors | |
4 | + | |
5 | + Licensed under the Apache License, Version 2.0 (the "License"); | |
6 | + you may not use this file except in compliance with the License. | |
7 | + You may obtain a copy of the License at | |
8 | + | |
9 | + http://www.apache.org/licenses/LICENSE-2.0 | |
10 | + | |
11 | + Unless required by applicable law or agreed to in writing, software | |
12 | + distributed under the License is distributed on an "AS IS" BASIS, | |
13 | + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
14 | + See the License for the specific language governing permissions and | |
15 | + limitations under the License. | |
16 | + | |
17 | +--> | |
18 | +<form [formGroup]="coapDeviceProfileTransportConfigurationFormGroup" style="padding-bottom: 16px;"> | |
19 | + <section formGroupName="coapDeviceTypeConfiguration"> | |
20 | + <fieldset class="fields-group"> | |
21 | + <legend class="group-title" translate>device-profile.coap-device-type</legend> | |
22 | + <div fxLayoutGap="8px" fxLayout="column"> | |
23 | + <mat-form-field class="mat-block"> | |
24 | + <mat-select formControlName="coapDeviceType" required> | |
25 | + <mat-option *ngFor="let type of coapTransportDeviceTypes" [value]="type"> | |
26 | + {{coapTransportDeviceTypeTranslations.get(type) | translate}} | |
27 | + </mat-option> | |
28 | + </mat-select> | |
29 | + <mat-error *ngIf="coapDeviceProfileTransportConfigurationFormGroup.get('coapDeviceTypeConfiguration.coapDeviceType').hasError('required')"> | |
30 | + {{ 'device-profile.coap-device-type-required' | translate }} | |
31 | + </mat-error> | |
32 | + </mat-form-field> | |
33 | + </div> | |
34 | + </fieldset> | |
35 | + <div *ngIf="coapDeviceTypeDefault" formGroupName="transportPayloadTypeConfiguration"> | |
36 | + <fieldset class="fields-group"> | |
37 | + <legend class="group-title" translate>device-profile.coap-device-payload-type</legend> | |
38 | + <div fxLayoutGap="8px" fxLayout="column"> | |
39 | + <mat-form-field class="mat-block"> | |
40 | + <mat-select formControlName="transportPayloadType" required> | |
41 | + <mat-option *ngFor="let type of transportPayloadTypes" [value]="type"> | |
42 | + {{transportPayloadTypeTranslations.get(type) | translate}} | |
43 | + </mat-option> | |
44 | + </mat-select> | |
45 | + <mat-error *ngIf="coapDeviceProfileTransportConfigurationFormGroup.get('coapDeviceTypeConfiguration.transportPayloadTypeConfiguration.transportPayloadType').hasError('required')"> | |
46 | + {{ 'device-profile.mqtt-payload-type-required' | translate }} | |
47 | + </mat-error> | |
48 | + </mat-form-field> | |
49 | + <div *ngIf="protoPayloadType" fxLayout="column"> | |
50 | + <mat-form-field fxFlex> | |
51 | + <mat-label translate>device-profile.telemetry-proto-schema</mat-label> | |
52 | + <textarea matInput required formControlName="deviceTelemetryProtoSchema" rows="5"></textarea> | |
53 | + <mat-error *ngIf="coapDeviceProfileTransportConfigurationFormGroup.get('coapDeviceTypeConfiguration.transportPayloadTypeConfiguration.deviceTelemetryProtoSchema').hasError('required')"> | |
54 | + {{ 'device-profile.telemetry-proto-schema-required' | translate}} | |
55 | + </mat-error> | |
56 | + </mat-form-field> | |
57 | + <mat-form-field fxFlex> | |
58 | + <mat-label translate>device-profile.attributes-proto-schema</mat-label> | |
59 | + <textarea matInput required formControlName="deviceAttributesProtoSchema" rows="5"></textarea> | |
60 | + <mat-error *ngIf="coapDeviceProfileTransportConfigurationFormGroup.get('coapDeviceTypeConfiguration.transportPayloadTypeConfiguration.deviceAttributesProtoSchema').hasError('required')"> | |
61 | + {{ 'device-profile.attributes-proto-schema-required' | translate}} | |
62 | + </mat-error> | |
63 | + </mat-form-field> | |
64 | + </div> | |
65 | + </div> | |
66 | + </fieldset> | |
67 | + </div> | |
68 | + </section> | |
69 | +</form> | ... | ... |
1 | +/** | |
2 | + * Copyright © 2016-2021 The Thingsboard Authors | |
3 | + * | |
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | |
5 | + * you may not use this file except in compliance with the License. | |
6 | + * You may obtain a copy of the License at | |
7 | + * | |
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | |
9 | + * | |
10 | + * Unless required by applicable law or agreed to in writing, software | |
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | |
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 | + * See the License for the specific language governing permissions and | |
14 | + * limitations under the License. | |
15 | + */ | |
16 | +:host{ | |
17 | + .fields-group { | |
18 | + padding: 8px; | |
19 | + margin: 10px 0; | |
20 | + border: 1px groove rgba(0, 0, 0, .25); | |
21 | + border-radius: 4px; | |
22 | + | |
23 | + legend { | |
24 | + color: rgba(0, 0, 0, .7); | |
25 | + } | |
26 | + | |
27 | + .tb-hint{ | |
28 | + padding: 0; | |
29 | + } | |
30 | + } | |
31 | +} | ... | ... |
1 | +/// | |
2 | +/// Copyright © 2016-2021 The Thingsboard Authors | |
3 | +/// | |
4 | +/// Licensed under the Apache License, Version 2.0 (the "License"); | |
5 | +/// you may not use this file except in compliance with the License. | |
6 | +/// You may obtain a copy of the License at | |
7 | +/// | |
8 | +/// http://www.apache.org/licenses/LICENSE-2.0 | |
9 | +/// | |
10 | +/// Unless required by applicable law or agreed to in writing, software | |
11 | +/// distributed under the License is distributed on an "AS IS" BASIS, | |
12 | +/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 | +/// See the License for the specific language governing permissions and | |
14 | +/// limitations under the License. | |
15 | +/// | |
16 | + | |
17 | +import { Component, forwardRef, Input, OnInit } from '@angular/core'; | |
18 | +import { ControlValueAccessor, FormBuilder, FormGroup, NG_VALUE_ACCESSOR, Validators } from '@angular/forms'; | |
19 | +import { Store } from '@ngrx/store'; | |
20 | +import { AppState } from '@app/core/core.state'; | |
21 | +import { coerceBooleanProperty } from '@angular/cdk/coercion'; | |
22 | +import { | |
23 | + CoapDeviceProfileTransportConfiguration, | |
24 | + coapDeviceTypeTranslationMap, | |
25 | + CoapTransportDeviceType, | |
26 | + defaultAttributesSchema, | |
27 | + defaultTelemetrySchema, | |
28 | + DeviceProfileTransportConfiguration, | |
29 | + DeviceTransportType, | |
30 | + TransportPayloadType, | |
31 | + transportPayloadTypeTranslationMap, | |
32 | +} from '@shared/models/device.models'; | |
33 | +import { isDefinedAndNotNull } from '@core/utils'; | |
34 | + | |
35 | +@Component({ | |
36 | + selector: 'tb-coap-device-profile-transport-configuration', | |
37 | + templateUrl: './coap-device-profile-transport-configuration.component.html', | |
38 | + styleUrls: ['./coap-device-profile-transport-configuration.component.scss'], | |
39 | + providers: [{ | |
40 | + provide: NG_VALUE_ACCESSOR, | |
41 | + useExisting: forwardRef(() => CoapDeviceProfileTransportConfigurationComponent), | |
42 | + multi: true | |
43 | + }] | |
44 | +}) | |
45 | +export class CoapDeviceProfileTransportConfigurationComponent implements ControlValueAccessor, OnInit { | |
46 | + | |
47 | + coapTransportDeviceTypes = Object.keys(CoapTransportDeviceType); | |
48 | + | |
49 | + coapTransportDeviceTypeTranslations = coapDeviceTypeTranslationMap; | |
50 | + | |
51 | + transportPayloadTypes = Object.keys(TransportPayloadType); | |
52 | + | |
53 | + transportPayloadTypeTranslations = transportPayloadTypeTranslationMap; | |
54 | + | |
55 | + coapDeviceProfileTransportConfigurationFormGroup: FormGroup; | |
56 | + | |
57 | + private requiredValue: boolean; | |
58 | + | |
59 | + private transportPayloadTypeConfiguration = this.fb.group({ | |
60 | + transportPayloadType: [TransportPayloadType.JSON, Validators.required], | |
61 | + deviceTelemetryProtoSchema: [defaultTelemetrySchema, Validators.required], | |
62 | + deviceAttributesProtoSchema: [defaultAttributesSchema, Validators.required] | |
63 | + }); | |
64 | + | |
65 | + get required(): boolean { | |
66 | + return this.requiredValue; | |
67 | + } | |
68 | + | |
69 | + @Input() | |
70 | + set required(value: boolean) { | |
71 | + this.requiredValue = coerceBooleanProperty(value); | |
72 | + } | |
73 | + | |
74 | + @Input() | |
75 | + disabled: boolean; | |
76 | + | |
77 | + private propagateChange = (v: any) => { }; | |
78 | + | |
79 | + constructor(private store: Store<AppState>, | |
80 | + private fb: FormBuilder) { | |
81 | + } | |
82 | + | |
83 | + registerOnChange(fn: any): void { | |
84 | + this.propagateChange = fn; | |
85 | + } | |
86 | + | |
87 | + registerOnTouched(fn: any): void { | |
88 | + } | |
89 | + | |
90 | + ngOnInit() { | |
91 | + this.coapDeviceProfileTransportConfigurationFormGroup = this.fb.group({ | |
92 | + coapDeviceTypeConfiguration: this.fb.group({ | |
93 | + coapDeviceType: [CoapTransportDeviceType.DEFAULT, Validators.required], | |
94 | + transportPayloadTypeConfiguration: this.transportPayloadTypeConfiguration | |
95 | + }) | |
96 | + } | |
97 | + ); | |
98 | + this.coapDeviceProfileTransportConfigurationFormGroup.get('coapDeviceTypeConfiguration.coapDeviceType') | |
99 | + .valueChanges.subscribe(coapDeviceType => { | |
100 | + this.updateCoapDeviceTypeBasedControls(coapDeviceType, true); | |
101 | + }); | |
102 | + this.coapDeviceProfileTransportConfigurationFormGroup.valueChanges.subscribe(() => { | |
103 | + this.updateModel(); | |
104 | + }); | |
105 | + } | |
106 | + | |
107 | + get coapDeviceTypeDefault(): boolean { | |
108 | + const coapDeviceType = this.coapDeviceProfileTransportConfigurationFormGroup.get('coapDeviceTypeConfiguration.coapDeviceType').value; | |
109 | + return coapDeviceType === CoapTransportDeviceType.DEFAULT; | |
110 | + } | |
111 | + | |
112 | + get protoPayloadType(): boolean { | |
113 | + const transportPayloadTypePath = 'coapDeviceTypeConfiguration.transportPayloadTypeConfiguration.transportPayloadType'; | |
114 | + const transportPayloadType = this.coapDeviceProfileTransportConfigurationFormGroup.get(transportPayloadTypePath).value; | |
115 | + return transportPayloadType === TransportPayloadType.PROTOBUF; | |
116 | + } | |
117 | + | |
118 | + | |
119 | + private updateCoapDeviceTypeBasedControls(type: CoapTransportDeviceType, forceUpdated = false) { | |
120 | + const coapDeviceTypeConfigurationFormGroup = this.coapDeviceProfileTransportConfigurationFormGroup | |
121 | + .get('coapDeviceTypeConfiguration') as FormGroup; | |
122 | + if (forceUpdated) { | |
123 | + coapDeviceTypeConfigurationFormGroup.patchValue({ | |
124 | + transportPayloadTypeConfiguration: this.transportPayloadTypeConfiguration | |
125 | + }, {emitEvent: false}); | |
126 | + } | |
127 | + if (type === CoapTransportDeviceType.DEFAULT && !this.disabled) { | |
128 | + coapDeviceTypeConfigurationFormGroup.get('transportPayloadTypeConfiguration').enable({emitEvent: false}); | |
129 | + } else { | |
130 | + coapDeviceTypeConfigurationFormGroup.get('transportPayloadTypeConfiguration').disable({emitEvent: false}); | |
131 | + } | |
132 | + } | |
133 | + | |
134 | + setDisabledState(isDisabled: boolean): void { | |
135 | + this.disabled = isDisabled; | |
136 | + if (this.disabled) { | |
137 | + this.coapDeviceProfileTransportConfigurationFormGroup.disable({emitEvent: false}); | |
138 | + } else { | |
139 | + this.coapDeviceProfileTransportConfigurationFormGroup.enable({emitEvent: false}); | |
140 | + } | |
141 | + } | |
142 | + | |
143 | + writeValue(value: CoapDeviceProfileTransportConfiguration | null): void { | |
144 | + if (isDefinedAndNotNull(value)) { | |
145 | + this.coapDeviceProfileTransportConfigurationFormGroup.patchValue(value, {emitEvent: false}); | |
146 | + this.updateCoapDeviceTypeBasedControls(value.coapDeviceTypeConfiguration?.coapDeviceType); | |
147 | + } | |
148 | + } | |
149 | + | |
150 | + private updateModel() { | |
151 | + let configuration: DeviceProfileTransportConfiguration = null; | |
152 | + if (this.coapDeviceProfileTransportConfigurationFormGroup.valid) { | |
153 | + configuration = this.coapDeviceProfileTransportConfigurationFormGroup.value; | |
154 | + configuration.type = DeviceTransportType.COAP; | |
155 | + } | |
156 | + this.propagateChange(configuration); | |
157 | + } | |
158 | + | |
159 | +} | ... | ... |
... | ... | @@ -35,5 +35,11 @@ |
35 | 35 | formControlName="configuration"> |
36 | 36 | </tb-lwm2m-device-profile-transport-configuration> |
37 | 37 | </ng-template--> |
38 | + <ng-template [ngSwitchCase]="deviceTransportType.COAP"> | |
39 | + <tb-coap-device-profile-transport-configuration | |
40 | + [required]="required" | |
41 | + formControlName="configuration"> | |
42 | + </tb-coap-device-profile-transport-configuration> | |
43 | + </ng-template> | |
38 | 44 | </div> |
39 | 45 | </div> | ... | ... |
... | ... | @@ -65,8 +65,8 @@ |
65 | 65 | <div fxLayoutGap="8px" fxLayout="column"> |
66 | 66 | <mat-form-field class="mat-block"> |
67 | 67 | <mat-select formControlName="transportPayloadType" required> |
68 | - <mat-option *ngFor="let type of mqttTransportPayloadTypes" [value]="type"> | |
69 | - {{mqttTransportPayloadTypeTranslations.get(type) | translate}} | |
68 | + <mat-option *ngFor="let type of transportPayloadTypes" [value]="type"> | |
69 | + {{transportPayloadTypeTranslations.get(type) | translate}} | |
70 | 70 | </mat-option> |
71 | 71 | </mat-select> |
72 | 72 | <mat-error *ngIf="mqttDeviceProfileTransportConfigurationFormGroup.get('transportPayloadTypeConfiguration.transportPayloadType').hasError('required')"> | ... | ... |
... | ... | @@ -28,11 +28,13 @@ import { Store } from '@ngrx/store'; |
28 | 28 | import { AppState } from '@app/core/core.state'; |
29 | 29 | import { coerceBooleanProperty } from '@angular/cdk/coercion'; |
30 | 30 | import { |
31 | + defaultAttributesSchema, | |
32 | + defaultTelemetrySchema, | |
31 | 33 | DeviceProfileTransportConfiguration, |
32 | 34 | DeviceTransportType, |
33 | 35 | MqttDeviceProfileTransportConfiguration, |
34 | - MqttTransportPayloadType, | |
35 | - mqttTransportPayloadTypeTranslationMap | |
36 | + TransportPayloadType, | |
37 | + transportPayloadTypeTranslationMap | |
36 | 38 | } from '@shared/models/device.models'; |
37 | 39 | import { isDefinedAndNotNull } from '@core/utils'; |
38 | 40 | |
... | ... | @@ -48,40 +50,12 @@ import { isDefinedAndNotNull } from '@core/utils'; |
48 | 50 | }) |
49 | 51 | export class MqttDeviceProfileTransportConfigurationComponent implements ControlValueAccessor, OnInit { |
50 | 52 | |
51 | - mqttTransportPayloadTypes = Object.keys(MqttTransportPayloadType); | |
53 | + transportPayloadTypes = Object.keys(TransportPayloadType); | |
52 | 54 | |
53 | - mqttTransportPayloadTypeTranslations = mqttTransportPayloadTypeTranslationMap; | |
55 | + transportPayloadTypeTranslations = transportPayloadTypeTranslationMap; | |
54 | 56 | |
55 | 57 | mqttDeviceProfileTransportConfigurationFormGroup: FormGroup; |
56 | 58 | |
57 | - private defaultTelemetrySchema = | |
58 | - 'syntax ="proto3";\n' + | |
59 | - 'package telemetry;\n' + | |
60 | - '\n' + | |
61 | - 'message SensorDataReading {\n' + | |
62 | - '\n' + | |
63 | - ' double temperature = 1;\n' + | |
64 | - ' double humidity = 2;\n' + | |
65 | - ' InnerObject innerObject = 3;\n' + | |
66 | - '\n' + | |
67 | - ' message InnerObject {\n' + | |
68 | - ' string key1 = 1;\n' + | |
69 | - ' bool key2 = 2;\n' + | |
70 | - ' double key3 = 3;\n' + | |
71 | - ' int32 key4 = 4;\n' + | |
72 | - ' string key5 = 5;\n' + | |
73 | - ' }\n' + | |
74 | - '}\n'; | |
75 | - | |
76 | - private defaultAttributesSchema = | |
77 | - 'syntax ="proto3";\n' + | |
78 | - 'package attributes;\n' + | |
79 | - '\n' + | |
80 | - 'message SensorConfiguration {\n' + | |
81 | - ' string firmwareVersion = 1;\n' + | |
82 | - ' string serialNumber = 2;\n' + | |
83 | - '}'; | |
84 | - | |
85 | 59 | private requiredValue: boolean; |
86 | 60 | |
87 | 61 | get required(): boolean { |
... | ... | @@ -114,9 +88,9 @@ export class MqttDeviceProfileTransportConfigurationComponent implements Control |
114 | 88 | deviceAttributesTopic: [null, [Validators.required, this.validationMQTTTopic()]], |
115 | 89 | deviceTelemetryTopic: [null, [Validators.required, this.validationMQTTTopic()]], |
116 | 90 | transportPayloadTypeConfiguration: this.fb.group({ |
117 | - transportPayloadType: [MqttTransportPayloadType.JSON, Validators.required], | |
118 | - deviceTelemetryProtoSchema: [this.defaultTelemetrySchema, Validators.required], | |
119 | - deviceAttributesProtoSchema: [this.defaultAttributesSchema, Validators.required] | |
91 | + transportPayloadType: [TransportPayloadType.JSON, Validators.required], | |
92 | + deviceTelemetryProtoSchema: [defaultTelemetrySchema, Validators.required], | |
93 | + deviceAttributesProtoSchema: [defaultAttributesSchema, Validators.required] | |
120 | 94 | }) |
121 | 95 | }, {validator: this.uniqueDeviceTopicValidator} |
122 | 96 | ); |
... | ... | @@ -140,7 +114,7 @@ export class MqttDeviceProfileTransportConfigurationComponent implements Control |
140 | 114 | |
141 | 115 | get protoPayloadType(): boolean { |
142 | 116 | const transportPayloadType = this.mqttDeviceProfileTransportConfigurationFormGroup.get('transportPayloadTypeConfiguration.transportPayloadType').value; |
143 | - return transportPayloadType === MqttTransportPayloadType.PROTOBUF; | |
117 | + return transportPayloadType === TransportPayloadType.PROTOBUF; | |
144 | 118 | } |
145 | 119 | |
146 | 120 | writeValue(value: MqttDeviceProfileTransportConfiguration | null): void { |
... | ... | @@ -159,16 +133,16 @@ export class MqttDeviceProfileTransportConfigurationComponent implements Control |
159 | 133 | this.propagateChange(configuration); |
160 | 134 | } |
161 | 135 | |
162 | - private updateTransportPayloadBasedControls(type: MqttTransportPayloadType, forceUpdated = false) { | |
136 | + private updateTransportPayloadBasedControls(type: TransportPayloadType, forceUpdated = false) { | |
163 | 137 | const transportPayloadTypeForm = this.mqttDeviceProfileTransportConfigurationFormGroup |
164 | 138 | .get('transportPayloadTypeConfiguration') as FormGroup; |
165 | 139 | if (forceUpdated) { |
166 | 140 | transportPayloadTypeForm.patchValue({ |
167 | - deviceTelemetryProtoSchema: this.defaultTelemetrySchema, | |
168 | - deviceAttributesProtoSchema: this.defaultAttributesSchema | |
141 | + deviceTelemetryProtoSchema: defaultTelemetrySchema, | |
142 | + deviceAttributesProtoSchema: defaultAttributesSchema | |
169 | 143 | }, {emitEvent: false}); |
170 | 144 | } |
171 | - if (type === MqttTransportPayloadType.PROTOBUF && !this.disabled) { | |
145 | + if (type === TransportPayloadType.PROTOBUF && !this.disabled) { | |
172 | 146 | transportPayloadTypeForm.get('deviceTelemetryProtoSchema').enable({emitEvent: false}); |
173 | 147 | transportPayloadTypeForm.get('deviceAttributesProtoSchema').enable({emitEvent: false}); |
174 | 148 | } else { | ... | ... |
ui-ngx/src/app/modules/home/pages/device/data/coap-device-transport-configuration.component.html
0 → 100644
1 | +<!-- | |
2 | + | |
3 | + Copyright © 2016-2021 The Thingsboard Authors | |
4 | + | |
5 | + Licensed under the Apache License, Version 2.0 (the "License"); | |
6 | + you may not use this file except in compliance with the License. | |
7 | + You may obtain a copy of the License at | |
8 | + | |
9 | + http://www.apache.org/licenses/LICENSE-2.0 | |
10 | + | |
11 | + Unless required by applicable law or agreed to in writing, software | |
12 | + distributed under the License is distributed on an "AS IS" BASIS, | |
13 | + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
14 | + See the License for the specific language governing permissions and | |
15 | + limitations under the License. | |
16 | + | |
17 | +--> | |
18 | +<form [formGroup]="coapDeviceTransportConfigurationFormGroup" style="padding-bottom: 16px;"> | |
19 | + <!--tb-json-object-edit | |
20 | + [required]="required" | |
21 | + label="{{ 'device-profile.transport-type-coap' | translate }}" | |
22 | + formControlName="configuration"> | |
23 | + </tb-json-object-edit--> | |
24 | +</form> | ... | ... |
ui-ngx/src/app/modules/home/pages/device/data/coap-device-transport-configuration.component.ts
0 → 100644
1 | +/// | |
2 | +/// Copyright © 2016-2021 The Thingsboard Authors | |
3 | +/// | |
4 | +/// Licensed under the Apache License, Version 2.0 (the "License"); | |
5 | +/// you may not use this file except in compliance with the License. | |
6 | +/// You may obtain a copy of the License at | |
7 | +/// | |
8 | +/// http://www.apache.org/licenses/LICENSE-2.0 | |
9 | +/// | |
10 | +/// Unless required by applicable law or agreed to in writing, software | |
11 | +/// distributed under the License is distributed on an "AS IS" BASIS, | |
12 | +/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 | +/// See the License for the specific language governing permissions and | |
14 | +/// limitations under the License. | |
15 | +/// | |
16 | + | |
17 | +import { Component, forwardRef, Input, OnInit } from '@angular/core'; | |
18 | +import { ControlValueAccessor, FormBuilder, FormGroup, NG_VALUE_ACCESSOR, Validators } from '@angular/forms'; | |
19 | +import { Store } from '@ngrx/store'; | |
20 | +import { AppState } from '@app/core/core.state'; | |
21 | +import { coerceBooleanProperty } from '@angular/cdk/coercion'; | |
22 | +import { | |
23 | + CoapDeviceTransportConfiguration, | |
24 | + DeviceTransportConfiguration, | |
25 | + DeviceTransportType | |
26 | +} from '@shared/models/device.models'; | |
27 | + | |
28 | +@Component({ | |
29 | + selector: 'tb-coap-device-transport-configuration', | |
30 | + templateUrl: './coap-device-transport-configuration.component.html', | |
31 | + styleUrls: [], | |
32 | + providers: [{ | |
33 | + provide: NG_VALUE_ACCESSOR, | |
34 | + useExisting: forwardRef(() => CoapDeviceTransportConfigurationComponent), | |
35 | + multi: true | |
36 | + }] | |
37 | +}) | |
38 | +export class CoapDeviceTransportConfigurationComponent implements ControlValueAccessor, OnInit { | |
39 | + | |
40 | + coapDeviceTransportConfigurationFormGroup: FormGroup; | |
41 | + | |
42 | + private requiredValue: boolean; | |
43 | + get required(): boolean { | |
44 | + return this.requiredValue; | |
45 | + } | |
46 | + @Input() | |
47 | + set required(value: boolean) { | |
48 | + this.requiredValue = coerceBooleanProperty(value); | |
49 | + } | |
50 | + | |
51 | + @Input() | |
52 | + disabled: boolean; | |
53 | + | |
54 | + private propagateChange = (v: any) => { }; | |
55 | + | |
56 | + constructor(private store: Store<AppState>, | |
57 | + private fb: FormBuilder) { | |
58 | + } | |
59 | + | |
60 | + registerOnChange(fn: any): void { | |
61 | + this.propagateChange = fn; | |
62 | + } | |
63 | + | |
64 | + registerOnTouched(fn: any): void { | |
65 | + } | |
66 | + | |
67 | + ngOnInit() { | |
68 | + this.coapDeviceTransportConfigurationFormGroup = this.fb.group({ | |
69 | + configuration: [null, Validators.required] | |
70 | + }); | |
71 | + this.coapDeviceTransportConfigurationFormGroup.valueChanges.subscribe(() => { | |
72 | + this.updateModel(); | |
73 | + }); | |
74 | + } | |
75 | + | |
76 | + setDisabledState(isDisabled: boolean): void { | |
77 | + this.disabled = isDisabled; | |
78 | + if (this.disabled) { | |
79 | + this.coapDeviceTransportConfigurationFormGroup.disable({emitEvent: false}); | |
80 | + } else { | |
81 | + this.coapDeviceTransportConfigurationFormGroup.enable({emitEvent: false}); | |
82 | + } | |
83 | + } | |
84 | + | |
85 | + writeValue(value: CoapDeviceTransportConfiguration | null): void { | |
86 | + this.coapDeviceTransportConfigurationFormGroup.patchValue({configuration: value}, {emitEvent: false}); | |
87 | + } | |
88 | + | |
89 | + private updateModel() { | |
90 | + let configuration: DeviceTransportConfiguration = null; | |
91 | + if (this.coapDeviceTransportConfigurationFormGroup.valid) { | |
92 | + configuration = this.coapDeviceTransportConfigurationFormGroup.getRawValue().configuration; | |
93 | + configuration.type = DeviceTransportType.COAP; | |
94 | + } | |
95 | + this.propagateChange(configuration); | |
96 | + } | |
97 | +} | ... | ... |
... | ... | @@ -35,5 +35,11 @@ |
35 | 35 | formControlName="configuration"> |
36 | 36 | </tb-lwm2m-device-transport-configuration> |
37 | 37 | </ng-template--> |
38 | + <ng-template [ngSwitchCase]="deviceTransportType.COAP"> | |
39 | + <tb-coap-device-transport-configuration | |
40 | + [required]="required" | |
41 | + formControlName="configuration"> | |
42 | + </tb-coap-device-transport-configuration> | |
43 | + </ng-template> | |
38 | 44 | </div> |
39 | 45 | </div> | ... | ... |
... | ... | @@ -31,6 +31,7 @@ import { DefaultDeviceTransportConfigurationComponent } from './data/default-dev |
31 | 31 | import { DeviceTransportConfigurationComponent } from './data/device-transport-configuration.component'; |
32 | 32 | import { MqttDeviceTransportConfigurationComponent } from './data/mqtt-device-transport-configuration.component'; |
33 | 33 | import { Lwm2mDeviceTransportConfigurationComponent } from './data/lwm2m-device-transport-configuration.component'; |
34 | +import { CoapDeviceTransportConfigurationComponent } from './data/coap-device-transport-configuration.component'; | |
34 | 35 | |
35 | 36 | @NgModule({ |
36 | 37 | declarations: [ |
... | ... | @@ -39,6 +40,7 @@ import { Lwm2mDeviceTransportConfigurationComponent } from './data/lwm2m-device- |
39 | 40 | DefaultDeviceTransportConfigurationComponent, |
40 | 41 | MqttDeviceTransportConfigurationComponent, |
41 | 42 | Lwm2mDeviceTransportConfigurationComponent, |
43 | + CoapDeviceTransportConfigurationComponent, | |
42 | 44 | DeviceTransportConfigurationComponent, |
43 | 45 | DeviceDataComponent, |
44 | 46 | DeviceComponent, | ... | ... |
... | ... | @@ -36,13 +36,19 @@ export enum DeviceTransportType { |
36 | 36 | DEFAULT = 'DEFAULT', |
37 | 37 | MQTT = 'MQTT', |
38 | 38 | // LWM2M = 'LWM2M' |
39 | + COAP = 'COAP' | |
39 | 40 | } |
40 | 41 | |
41 | -export enum MqttTransportPayloadType { | |
42 | +export enum TransportPayloadType { | |
42 | 43 | JSON = 'JSON', |
43 | 44 | PROTOBUF = 'PROTOBUF' |
44 | 45 | } |
45 | 46 | |
47 | +export enum CoapTransportDeviceType { | |
48 | + DEFAULT = 'DEFAULT', | |
49 | + EFENTO = 'EFENTO' | |
50 | +} | |
51 | + | |
46 | 52 | export enum DeviceProvisionType { |
47 | 53 | DISABLED = 'DISABLED', |
48 | 54 | ALLOW_CREATE_NEW_DEVICES = 'ALLOW_CREATE_NEW_DEVICES', |
... | ... | @@ -77,6 +83,7 @@ export const deviceTransportTypeTranslationMap = new Map<DeviceTransportType, st |
77 | 83 | [DeviceTransportType.DEFAULT, 'device-profile.transport-type-default'], |
78 | 84 | [DeviceTransportType.MQTT, 'device-profile.transport-type-mqtt'], |
79 | 85 | // [DeviceTransportType.LWM2M, 'device-profile.transport-type-lwm2m'] |
86 | + [DeviceTransportType.COAP, 'device-profile.transport-type-coap'] | |
80 | 87 | ] |
81 | 88 | ); |
82 | 89 | |
... | ... | @@ -94,13 +101,49 @@ export const deviceTransportTypeHintMap = new Map<DeviceTransportType, string>( |
94 | 101 | [DeviceTransportType.DEFAULT, 'device-profile.transport-type-default-hint'], |
95 | 102 | [DeviceTransportType.MQTT, 'device-profile.transport-type-mqtt-hint'], |
96 | 103 | // [DeviceTransportType.LWM2M, 'device-profile.transport-type-lwm2m-hint'] |
104 | + [DeviceTransportType.COAP, 'device-profile.transport-type-coap-hint'] | |
97 | 105 | ] |
98 | 106 | ); |
99 | 107 | |
100 | -export const mqttTransportPayloadTypeTranslationMap = new Map<MqttTransportPayloadType, string>( | |
108 | +export const transportPayloadTypeTranslationMap = new Map<TransportPayloadType, string>( | |
101 | 109 | [ |
102 | - [MqttTransportPayloadType.JSON, 'device-profile.mqtt-device-payload-type-json'], | |
103 | - [MqttTransportPayloadType.PROTOBUF, 'device-profile.mqtt-device-payload-type-proto'] | |
110 | + [TransportPayloadType.JSON, 'device-profile.transport-device-payload-type-json'], | |
111 | + [TransportPayloadType.PROTOBUF, 'device-profile.transport-device-payload-type-proto'] | |
112 | + ] | |
113 | +); | |
114 | + | |
115 | +export const defaultTelemetrySchema = | |
116 | + 'syntax ="proto3";\n' + | |
117 | + 'package telemetry;\n' + | |
118 | + '\n' + | |
119 | + 'message SensorDataReading {\n' + | |
120 | + '\n' + | |
121 | + ' double temperature = 1;\n' + | |
122 | + ' double humidity = 2;\n' + | |
123 | + ' InnerObject innerObject = 3;\n' + | |
124 | + '\n' + | |
125 | + ' message InnerObject {\n' + | |
126 | + ' string key1 = 1;\n' + | |
127 | + ' bool key2 = 2;\n' + | |
128 | + ' double key3 = 3;\n' + | |
129 | + ' int32 key4 = 4;\n' + | |
130 | + ' string key5 = 5;\n' + | |
131 | + ' }\n' + | |
132 | + '}\n'; | |
133 | + | |
134 | +export const defaultAttributesSchema = | |
135 | + 'syntax ="proto3";\n' + | |
136 | + 'package attributes;\n' + | |
137 | + '\n' + | |
138 | + 'message SensorConfiguration {\n' + | |
139 | + ' string firmwareVersion = 1;\n' + | |
140 | + ' string serialNumber = 2;\n' + | |
141 | + '}'; | |
142 | + | |
143 | +export const coapDeviceTypeTranslationMap = new Map<CoapTransportDeviceType, string>( | |
144 | + [ | |
145 | + [CoapTransportDeviceType.DEFAULT, 'device-profile.coap-device-type-default'], | |
146 | + [CoapTransportDeviceType.EFENTO, 'device-profile.coap-device-type-efento'] | |
104 | 147 | ] |
105 | 148 | ); |
106 | 149 | |
... | ... | @@ -128,6 +171,13 @@ export const deviceTransportTypeConfigurationInfoMap = new Map<DeviceTransportTy |
128 | 171 | hasDeviceConfiguration: false, |
129 | 172 | } |
130 | 173 | ]*/ |
174 | + [ | |
175 | + DeviceTransportType.COAP, | |
176 | + { | |
177 | + hasProfileConfiguration: true, | |
178 | + hasDeviceConfiguration: false, | |
179 | + } | |
180 | + ] | |
131 | 181 | ] |
132 | 182 | ); |
133 | 183 | |
... | ... | @@ -149,17 +199,28 @@ export interface MqttDeviceProfileTransportConfiguration { |
149 | 199 | deviceTelemetryTopic?: string; |
150 | 200 | deviceAttributesTopic?: string; |
151 | 201 | transportPayloadTypeConfiguration?: { |
152 | - transportPayloadType?: MqttTransportPayloadType; | |
202 | + transportPayloadType?: TransportPayloadType; | |
153 | 203 | }; |
154 | 204 | [key: string]: any; |
155 | 205 | } |
156 | 206 | |
207 | +export interface CoapDeviceProfileTransportConfiguration { | |
208 | + coapDeviceTypeConfiguration?: { | |
209 | + coapDeviceType?: CoapTransportDeviceType; | |
210 | + transportPayloadTypeConfiguration?: { | |
211 | + transportPayloadType?: TransportPayloadType; | |
212 | + [key: string]: any; | |
213 | + }; | |
214 | + }; | |
215 | +} | |
216 | + | |
157 | 217 | export interface Lwm2mDeviceProfileTransportConfiguration { |
158 | 218 | [key: string]: any; |
159 | 219 | } |
160 | 220 | |
161 | 221 | export type DeviceProfileTransportConfigurations = DefaultDeviceProfileTransportConfiguration & |
162 | 222 | MqttDeviceProfileTransportConfiguration & |
223 | + CoapDeviceProfileTransportConfiguration & | |
163 | 224 | Lwm2mDeviceProfileTransportConfiguration; |
164 | 225 | |
165 | 226 | export interface DeviceProfileTransportConfiguration extends DeviceProfileTransportConfigurations { |
... | ... | @@ -210,7 +271,7 @@ export function createDeviceProfileTransportConfiguration(type: DeviceTransportT |
210 | 271 | const mqttTransportConfiguration: MqttDeviceProfileTransportConfiguration = { |
211 | 272 | deviceTelemetryTopic: 'v1/devices/me/telemetry', |
212 | 273 | deviceAttributesTopic: 'v1/devices/me/attributes', |
213 | - transportPayloadTypeConfiguration: {transportPayloadType: MqttTransportPayloadType.JSON} | |
274 | + transportPayloadTypeConfiguration: {transportPayloadType: TransportPayloadType.JSON} | |
214 | 275 | }; |
215 | 276 | transportConfiguration = {...mqttTransportConfiguration, type: DeviceTransportType.MQTT}; |
216 | 277 | break; |
... | ... | @@ -218,6 +279,12 @@ export function createDeviceProfileTransportConfiguration(type: DeviceTransportT |
218 | 279 | const lwm2mTransportConfiguration: Lwm2mDeviceProfileTransportConfiguration = {}; |
219 | 280 | transportConfiguration = {...lwm2mTransportConfiguration, type: DeviceTransportType.LWM2M}; |
220 | 281 | break;*/ |
282 | + case DeviceTransportType.COAP: | |
283 | + const coapTransportConfiguration: CoapDeviceProfileTransportConfiguration = { | |
284 | + coapDeviceTypeConfiguration: {coapDeviceType: CoapTransportDeviceType.DEFAULT, transportPayloadTypeConfiguration: {transportPayloadType: TransportPayloadType.JSON}} | |
285 | + }; | |
286 | + transportConfiguration = {...coapTransportConfiguration, type: DeviceTransportType.COAP}; | |
287 | + break; | |
221 | 288 | } |
222 | 289 | } |
223 | 290 | return transportConfiguration; |
... | ... | @@ -239,6 +306,10 @@ export function createDeviceTransportConfiguration(type: DeviceTransportType): D |
239 | 306 | const lwm2mTransportConfiguration: Lwm2mDeviceTransportConfiguration = {}; |
240 | 307 | transportConfiguration = {...lwm2mTransportConfiguration, type: DeviceTransportType.LWM2M}; |
241 | 308 | break;*/ |
309 | + case DeviceTransportType.COAP: | |
310 | + const coapTransportConfiguration: CoapDeviceTransportConfiguration = {}; | |
311 | + transportConfiguration = {...coapTransportConfiguration, type: DeviceTransportType.COAP}; | |
312 | + break; | |
242 | 313 | } |
243 | 314 | } |
244 | 315 | return transportConfiguration; |
... | ... | @@ -399,12 +470,17 @@ export interface MqttDeviceTransportConfiguration { |
399 | 470 | [key: string]: any; |
400 | 471 | } |
401 | 472 | |
473 | +export interface CoapDeviceTransportConfiguration { | |
474 | + [key: string]: any; | |
475 | +} | |
476 | + | |
402 | 477 | export interface Lwm2mDeviceTransportConfiguration { |
403 | 478 | [key: string]: any; |
404 | 479 | } |
405 | 480 | |
406 | 481 | export type DeviceTransportConfigurations = DefaultDeviceTransportConfiguration & |
407 | 482 | MqttDeviceTransportConfiguration & |
483 | + CoapDeviceTransportConfiguration & | |
408 | 484 | Lwm2mDeviceTransportConfiguration; |
409 | 485 | |
410 | 486 | export interface DeviceTransportConfiguration extends DeviceTransportConfigurations { | ... | ... |
... | ... | @@ -967,6 +967,8 @@ |
967 | 967 | "transport-type-mqtt-hint": "Enables advanced MQTT transport settings", |
968 | 968 | "transport-type-lwm2m": "LWM2M", |
969 | 969 | "transport-type-lwm2m-hint": "LWM2M transport type", |
970 | + "transport-type-coap": "CoAP", | |
971 | + "transport-type-coap-hint": "Enables advanced CoAP transport settings", | |
970 | 972 | "description": "Description", |
971 | 973 | "default": "Default", |
972 | 974 | "profile-configuration": "Profile configuration", |
... | ... | @@ -984,9 +986,14 @@ |
984 | 986 | "mqtt-device-topic-filters": "MQTT device topic filters", |
985 | 987 | "mqtt-device-topic-filters-unique": "MQTT device topic filters need to be unique.", |
986 | 988 | "mqtt-device-payload-type": "MQTT device payload", |
987 | - "mqtt-device-payload-type-json": "JSON", | |
988 | - "mqtt-device-payload-type-proto": "Protobuf", | |
989 | + "transport-device-payload-type-json": "JSON", | |
990 | + "transport-device-payload-type-proto": "Protobuf", | |
989 | 991 | "mqtt-payload-type-required": "Payload type is required.", |
992 | + "coap-device-type": "CoAP device type", | |
993 | + "coap-device-payload-type": "CoAP device payload", | |
994 | + "coap-device-type-required": "CoAP device type is required.", | |
995 | + "coap-device-type-default": "Default", | |
996 | + "coap-device-type-efento": "Efento NB-IoT", | |
990 | 997 | "support-level-wildcards": "Single <code>[+]</code> and multi-level <code>[#]</code> wildcards supported.", |
991 | 998 | "telemetry-topic-filter": "Telemetry topic filter", |
992 | 999 | "telemetry-topic-filter-required": "Telemetry topic filter is required.", | ... | ... |