diff --git a/monitoring/pom.xml b/monitoring/pom.xml
index 429df521b6..e044635e98 100644
--- a/monitoring/pom.xml
+++ b/monitoring/pom.xml
@@ -41,6 +41,9 @@
${project.build.directory}/windows
ThingsBoard Monitoring Service
org.thingsboard.monitoring.ThingsboardMonitoringApplication
+
+ 2.6.1
+ 2.0.0-M4
@@ -65,10 +68,12 @@
org.eclipse.californium
californium-core
+ ${californium.version}
org.eclipse.californium
scandium
+ ${californium.version}
org.eclipse.paho
@@ -78,6 +83,16 @@
org.apache.httpcomponents
httpclient
+
+ org.eclipse.leshan
+ leshan-client-cf
+ ${leshan.version}
+
+
+ org.eclipse.leshan
+ leshan-core
+ ${leshan.version}
+
org.java-websocket
Java-WebSocket
diff --git a/monitoring/src/main/java/org/thingsboard/monitoring/client/Lwm2mClient.java b/monitoring/src/main/java/org/thingsboard/monitoring/client/Lwm2mClient.java
new file mode 100644
index 0000000000..473a17aa00
--- /dev/null
+++ b/monitoring/src/main/java/org/thingsboard/monitoring/client/Lwm2mClient.java
@@ -0,0 +1,171 @@
+/**
+ * Copyright © 2016-2023 The Thingsboard Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.thingsboard.monitoring.client;
+
+import lombok.Getter;
+import lombok.Setter;
+import lombok.SneakyThrows;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+import org.eclipse.californium.core.network.CoapEndpoint;
+import org.eclipse.californium.core.network.config.NetworkConfig;
+import org.eclipse.californium.core.observe.ObservationStore;
+import org.eclipse.californium.scandium.DTLSConnector;
+import org.eclipse.californium.scandium.config.DtlsConnectorConfig;
+import org.eclipse.leshan.client.californium.LeshanClient;
+import org.eclipse.leshan.client.californium.LeshanClientBuilder;
+import org.eclipse.leshan.client.engine.DefaultRegistrationEngineFactory;
+import org.eclipse.leshan.client.object.Security;
+import org.eclipse.leshan.client.object.Server;
+import org.eclipse.leshan.client.resource.BaseInstanceEnabler;
+import org.eclipse.leshan.client.resource.DummyInstanceEnabler;
+import org.eclipse.leshan.client.resource.ObjectsInitializer;
+import org.eclipse.leshan.client.servers.ServerIdentity;
+import org.eclipse.leshan.core.californium.EndpointFactory;
+import org.eclipse.leshan.core.model.InvalidDDFFileException;
+import org.eclipse.leshan.core.model.LwM2mModel;
+import org.eclipse.leshan.core.model.ObjectLoader;
+import org.eclipse.leshan.core.model.ObjectModel;
+import org.eclipse.leshan.core.model.StaticModel;
+import org.eclipse.leshan.core.node.codec.DefaultLwM2mDecoder;
+import org.eclipse.leshan.core.node.codec.DefaultLwM2mEncoder;
+import org.eclipse.leshan.core.response.ReadResponse;
+import org.thingsboard.monitoring.util.ResourceUtils;
+
+import javax.security.auth.Destroyable;
+import java.io.IOException;
+import java.net.InetSocketAddress;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import static org.eclipse.leshan.client.object.Security.noSec;
+import static org.eclipse.leshan.core.LwM2mId.ACCESS_CONTROL;
+import static org.eclipse.leshan.core.LwM2mId.DEVICE;
+import static org.eclipse.leshan.core.LwM2mId.SECURITY;
+import static org.eclipse.leshan.core.LwM2mId.SERVER;
+
+@Slf4j
+public class Lwm2mClient extends BaseInstanceEnabler implements Destroyable {
+
+ @Getter
+ @Setter
+ private LeshanClient leshanClient;
+
+ private static final List supportedResources = Collections.singletonList(0);
+
+ private String data = "";
+
+ private String serverUri;
+ private String endpoint;
+
+ public Lwm2mClient(String serverUri, String endpoint) {
+ this.serverUri = serverUri;
+ this.endpoint = endpoint;
+ }
+
+ public Lwm2mClient() {
+ }
+
+ public void initClient() throws InvalidDDFFileException, IOException {
+ String[] resources = new String[]{"0.xml", "1.xml", "2.xml", "test-model.xml"};
+ List models = new ArrayList<>();
+ for (String resourceName : resources) {
+ models.addAll(ObjectLoader.loadDdfFile(ResourceUtils.getResourceAsStream("lwm2m/models/" + resourceName), resourceName));
+ }
+
+ Security security = noSec(serverUri, 123);
+ NetworkConfig coapConfig = new NetworkConfig().setString(NetworkConfig.Keys.COAP_PORT, StringUtils.substringAfterLast(serverUri, ":"));
+
+ LeshanClient leshanClient;
+
+ LwM2mModel model = new StaticModel(models);
+ ObjectsInitializer initializer = new ObjectsInitializer(model);
+ initializer.setInstancesForObject(SECURITY, security);
+ initializer.setInstancesForObject(SERVER, new Server(123, 300));
+ initializer.setInstancesForObject(DEVICE, this);
+ initializer.setClassForObject(ACCESS_CONTROL, DummyInstanceEnabler.class);
+ DtlsConnectorConfig.Builder dtlsConfig = new DtlsConnectorConfig.Builder();
+ dtlsConfig.setRecommendedCipherSuitesOnly(true);
+ dtlsConfig.setClientOnly();
+
+ DefaultRegistrationEngineFactory engineFactory = new DefaultRegistrationEngineFactory();
+ engineFactory.setReconnectOnUpdate(false);
+ engineFactory.setResumeOnConnect(true);
+
+ EndpointFactory endpointFactory = new EndpointFactory() {
+
+ @Override
+ public CoapEndpoint createUnsecuredEndpoint(InetSocketAddress address, NetworkConfig coapConfig,
+ ObservationStore store) {
+ CoapEndpoint.Builder builder = new CoapEndpoint.Builder();
+ builder.setInetSocketAddress(address);
+ builder.setNetworkConfig(coapConfig);
+ return builder.build();
+ }
+
+ @Override
+ public CoapEndpoint createSecuredEndpoint(DtlsConnectorConfig dtlsConfig, NetworkConfig coapConfig,
+ ObservationStore store) {
+ CoapEndpoint.Builder builder = new CoapEndpoint.Builder();
+ DtlsConnectorConfig.Builder dtlsConfigBuilder = new DtlsConnectorConfig.Builder(dtlsConfig);
+ builder.setConnector(new DTLSConnector(dtlsConfigBuilder.build()));
+ builder.setNetworkConfig(coapConfig);
+ return builder.build();
+ }
+ };
+
+ LeshanClientBuilder builder = new LeshanClientBuilder(endpoint);
+ builder.setObjects(initializer.createAll());
+ builder.setCoapConfig(coapConfig);
+ builder.setDtlsConfig(dtlsConfig);
+ builder.setRegistrationEngineFactory(engineFactory);
+ builder.setEndpointFactory(endpointFactory);
+ builder.setDecoder(new DefaultLwM2mDecoder(false));
+ builder.setEncoder(new DefaultLwM2mEncoder(false));
+ leshanClient = builder.build();
+
+ setLeshanClient(leshanClient);
+
+ leshanClient.start();
+ }
+
+ @Override
+ public List getAvailableResourceIds(ObjectModel model) {
+ return supportedResources;
+ }
+
+ @Override
+ public ReadResponse read(ServerIdentity identity, int resourceId) {
+ if (supportedResources.contains(resourceId)) {
+ return ReadResponse.success(resourceId, data);
+ }
+ return super.read(identity, resourceId);
+ }
+
+ @SneakyThrows
+ public void send(String data, int resource) {
+ this.data = data;
+ fireResourcesChange(resource);
+ }
+
+ @Override
+ public void destroy() {
+ if (leshanClient != null) {
+ leshanClient.destroy(true);
+ }
+ }
+}
diff --git a/monitoring/src/main/java/org/thingsboard/monitoring/config/TransportType.java b/monitoring/src/main/java/org/thingsboard/monitoring/config/TransportType.java
index ed0a4ea331..a3aaa7ec98 100644
--- a/monitoring/src/main/java/org/thingsboard/monitoring/config/TransportType.java
+++ b/monitoring/src/main/java/org/thingsboard/monitoring/config/TransportType.java
@@ -20,6 +20,7 @@ import lombok.Getter;
import org.thingsboard.monitoring.transport.TransportHealthChecker;
import org.thingsboard.monitoring.transport.impl.CoapTransportHealthChecker;
import org.thingsboard.monitoring.transport.impl.HttpTransportHealthChecker;
+import org.thingsboard.monitoring.transport.impl.Lwm2mTransportHealthChecker;
import org.thingsboard.monitoring.transport.impl.MqttTransportHealthChecker;
@AllArgsConstructor
@@ -28,7 +29,8 @@ public enum TransportType {
MQTT(MqttTransportHealthChecker.class),
COAP(CoapTransportHealthChecker.class),
- HTTP(HttpTransportHealthChecker.class);
+ HTTP(HttpTransportHealthChecker.class),
+ LWM2M(Lwm2mTransportHealthChecker.class);
private final Class extends TransportHealthChecker>> serviceClass;
diff --git a/monitoring/src/main/java/org/thingsboard/monitoring/config/service/Lwm2mTransportMonitoringConfig.java b/monitoring/src/main/java/org/thingsboard/monitoring/config/service/Lwm2mTransportMonitoringConfig.java
new file mode 100644
index 0000000000..4d97de8366
--- /dev/null
+++ b/monitoring/src/main/java/org/thingsboard/monitoring/config/service/Lwm2mTransportMonitoringConfig.java
@@ -0,0 +1,33 @@
+/**
+ * Copyright © 2016-2023 The Thingsboard Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.thingsboard.monitoring.config.service;
+
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.stereotype.Component;
+import org.thingsboard.monitoring.config.TransportType;
+
+@Component
+@ConditionalOnProperty(name = "monitoring.transports.lwm2m.enabled", havingValue = "true")
+@ConfigurationProperties(prefix = "monitoring.transports.lwm2m")
+public class Lwm2mTransportMonitoringConfig extends TransportMonitoringConfig {
+
+ @Override
+ public TransportType getTransportType() {
+ return TransportType.LWM2M;
+ }
+
+}
diff --git a/monitoring/src/main/java/org/thingsboard/monitoring/transport/TransportHealthChecker.java b/monitoring/src/main/java/org/thingsboard/monitoring/transport/TransportHealthChecker.java
index 9717b98f51..0c742e7709 100644
--- a/monitoring/src/main/java/org/thingsboard/monitoring/transport/TransportHealthChecker.java
+++ b/monitoring/src/main/java/org/thingsboard/monitoring/transport/TransportHealthChecker.java
@@ -67,7 +67,7 @@ public abstract class TransportHealthChecker {
log.info("Creating new device '{}'", deviceName);
- Device monitoringDevice = new Device();
- monitoringDevice.setName(deviceName);
- monitoringDevice.setType("default");
- DeviceData deviceData = new DeviceData();
- deviceData.setConfiguration(new DefaultDeviceConfiguration());
- deviceData.setTransportConfiguration(new DefaultDeviceTransportConfiguration());
- return tbClient.saveDevice(monitoringDevice);
+ return createDevice(config.getTransportType(), deviceName, tbClient);
});
deviceId = device.getId();
target.getDevice().setId(deviceId.toString());
@@ -134,10 +141,58 @@ public final class TransportMonitoringService {
deviceId = new DeviceId(deviceConfig.getId());
}
- log.info("Loading credentials for device {}", deviceId);
+ log.info("Using device {} for {} monitoring", deviceId, config.getTransportType());
DeviceCredentials credentials = tbClient.getDeviceCredentialsByDeviceId(deviceId)
.orElseThrow(() -> new IllegalArgumentException("No credentials found for device " + deviceId));
target.getDevice().setCredentials(credentials);
}
+ private Device createDevice(TransportType transportType, String name, TbClient tbClient) {
+ Device device = new Device();
+ device.setName(name);
+
+ DeviceCredentials credentials = new DeviceCredentials();
+ credentials.setCredentialsId(RandomStringUtils.randomAlphabetic(20));
+
+ DeviceData deviceData = new DeviceData();
+ deviceData.setConfiguration(new DefaultDeviceConfiguration());
+ if (transportType != TransportType.LWM2M) {
+ device.setType("default");
+ deviceData.setTransportConfiguration(new DefaultDeviceTransportConfiguration());
+ credentials.setCredentialsType(DeviceCredentialsType.ACCESS_TOKEN);
+ } else {
+ tbClient.getResources(new PageLink(1, 0, "lwm2m monitoring")).getData()
+ .stream().findFirst()
+ .orElseGet(() -> {
+ TbResource newResource = ResourceUtils.getResource("lwm2m/resource.json", TbResource.class);
+ log.info("Creating LwM2M resource");
+ return tbClient.saveResource(newResource);
+ });
+ String profileName = "LwM2M Monitoring";
+ DeviceProfile profile = tbClient.getDeviceProfiles(new PageLink(1, 0, profileName)).getData()
+ .stream().findFirst()
+ .orElseGet(() -> {
+ DeviceProfile newProfile = ResourceUtils.getResource("lwm2m/device_profile.json", DeviceProfile.class);
+ newProfile.setName(profileName);
+ log.info("Creating LwM2M device profile");
+ return tbClient.saveDeviceProfile(newProfile);
+ });
+ device.setType(profileName);
+ device.setDeviceProfileId(profile.getId());
+ deviceData.setTransportConfiguration(new Lwm2mDeviceTransportConfiguration());
+
+ credentials.setCredentialsType(DeviceCredentialsType.LWM2M_CREDENTIALS);
+ LwM2MDeviceCredentials lwm2mCreds = new LwM2MDeviceCredentials();
+ NoSecClientCredential client = new NoSecClientCredential();
+ client.setEndpoint(credentials.getCredentialsId());
+ lwm2mCreds.setClient(client);
+ LwM2MBootstrapClientCredentials bootstrap = new LwM2MBootstrapClientCredentials();
+ bootstrap.setBootstrapServer(new NoSecBootstrapClientCredential());
+ bootstrap.setLwm2mServer(new NoSecBootstrapClientCredential());
+ lwm2mCreds.setBootstrap(bootstrap);
+ credentials.setCredentialsValue(JacksonUtil.toString(lwm2mCreds));
+ }
+ return tbClient.saveDeviceWithCredentials(device, credentials).get();
+ }
+
}
diff --git a/monitoring/src/main/java/org/thingsboard/monitoring/transport/impl/Lwm2mTransportHealthChecker.java b/monitoring/src/main/java/org/thingsboard/monitoring/transport/impl/Lwm2mTransportHealthChecker.java
new file mode 100644
index 0000000000..6487003e0c
--- /dev/null
+++ b/monitoring/src/main/java/org/thingsboard/monitoring/transport/impl/Lwm2mTransportHealthChecker.java
@@ -0,0 +1,72 @@
+/**
+ * Copyright © 2016-2023 The Thingsboard Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.thingsboard.monitoring.transport.impl;
+
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.config.ConfigurableBeanFactory;
+import org.springframework.context.annotation.Scope;
+import org.springframework.stereotype.Service;
+import org.thingsboard.monitoring.client.Lwm2mClient;
+import org.thingsboard.monitoring.config.MonitoringTargetConfig;
+import org.thingsboard.monitoring.config.TransportType;
+import org.thingsboard.monitoring.config.service.Lwm2mTransportMonitoringConfig;
+import org.thingsboard.monitoring.transport.TransportHealthChecker;
+
+@Service
+@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
+@Slf4j
+public class Lwm2mTransportHealthChecker extends TransportHealthChecker {
+
+ private Lwm2mClient lwm2mClient;
+
+ protected Lwm2mTransportHealthChecker(Lwm2mTransportMonitoringConfig config, MonitoringTargetConfig target) {
+ super(config, target);
+ }
+
+ @Override
+ protected void initClient() throws Exception {
+ if (lwm2mClient == null || lwm2mClient.getLeshanClient() == null || lwm2mClient.isDestroyed()) {
+ String endpoint = target.getDevice().getCredentials().getCredentialsId();
+ lwm2mClient = new Lwm2mClient(target.getBaseUrl(), endpoint);
+ lwm2mClient.initClient();
+ log.debug("Initialized LwM2M client for endpoint '{}'", endpoint);
+ }
+ }
+
+ @Override
+ protected void sendTestPayload(String payload) throws Exception {
+ lwm2mClient.send(payload, 0);
+ }
+
+ @Override
+ protected String createTestPayload(String testValue) {
+ return testValue;
+ }
+
+ @Override
+ protected void destroyClient() throws Exception {
+ if (lwm2mClient != null) {
+ lwm2mClient.destroy();
+ lwm2mClient = null;
+ }
+ }
+
+ @Override
+ protected TransportType getTransportType() {
+ return TransportType.LWM2M;
+ }
+
+}
diff --git a/monitoring/src/main/java/org/thingsboard/monitoring/util/ResourceUtils.java b/monitoring/src/main/java/org/thingsboard/monitoring/util/ResourceUtils.java
new file mode 100644
index 0000000000..4cc1efe8cb
--- /dev/null
+++ b/monitoring/src/main/java/org/thingsboard/monitoring/util/ResourceUtils.java
@@ -0,0 +1,42 @@
+/**
+ * Copyright © 2016-2023 The Thingsboard Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.thingsboard.monitoring.util;
+
+import lombok.SneakyThrows;
+import org.thingsboard.common.util.JacksonUtil;
+
+import java.io.InputStream;
+
+public class ResourceUtils {
+
+ @SneakyThrows
+ public static T getResource(String path, Class type) {
+ InputStream resource = ResourceUtils.class.getClassLoader().getResourceAsStream(path);
+ if (resource == null) {
+ throw new IllegalArgumentException("Resource not found for path " + path);
+ }
+ return JacksonUtil.OBJECT_MAPPER.readValue(resource, type);
+ }
+
+ public static InputStream getResourceAsStream(String path) {
+ InputStream resource = ResourceUtils.class.getClassLoader().getResourceAsStream(path);
+ if (resource == null) {
+ throw new IllegalArgumentException("Resource not found for path " + path);
+ }
+ return resource;
+ }
+
+}
diff --git a/monitoring/src/main/resources/lwm2m/device_profile.json b/monitoring/src/main/resources/lwm2m/device_profile.json
new file mode 100644
index 0000000000..7f93a7e6b6
--- /dev/null
+++ b/monitoring/src/main/resources/lwm2m/device_profile.json
@@ -0,0 +1,59 @@
+{
+ "name": "LwM2M Monitoring",
+ "type": "DEFAULT",
+ "image": null,
+ "defaultQueueName": null,
+ "transportType": "LWM2M",
+ "provisionType": "DISABLED",
+ "description": "",
+ "profileData": {
+ "configuration": {
+ "type": "DEFAULT"
+ },
+ "transportConfiguration": {
+ "observeAttr": {
+ "observe": [
+ "/3_1.0/0/0"
+ ],
+ "attribute": [],
+ "telemetry": [
+ "/3_1.0/0/0"
+ ],
+ "keyName": {
+ "/3_1.0/0/0": "testData"
+ },
+ "attributeLwm2m": {}
+ },
+ "bootstrap": [
+ {
+ "shortServerId": 123,
+ "bootstrapServerIs": false,
+ "host": "0.0.0.0",
+ "port": 5685,
+ "clientHoldOffTime": 1,
+ "serverPublicKey": "",
+ "serverCertificate": "",
+ "bootstrapServerAccountTimeout": 0,
+ "lifetime": 300,
+ "defaultMinPeriod": 1,
+ "notifIfDisabled": true,
+ "binding": "U",
+ "securityMode": "NO_SEC"
+ }
+ ],
+ "clientLwM2mSettings": {
+ "clientOnlyObserveAfterConnect": 1,
+ "fwUpdateStrategy": 1,
+ "swUpdateStrategy": 1,
+ "powerMode": "DRX",
+ "compositeOperationsSupport": false
+ },
+ "bootstrapServerUpdateEnable": false,
+ "type": "LWM2M"
+ },
+ "alarms": null,
+ "provisionConfiguration": {
+ "type": "DISABLED"
+ }
+ }
+}
\ No newline at end of file
diff --git a/monitoring/src/main/resources/lwm2m/models/0.xml b/monitoring/src/main/resources/lwm2m/models/0.xml
new file mode 100644
index 0000000000..d122984c16
--- /dev/null
+++ b/monitoring/src/main/resources/lwm2m/models/0.xml
@@ -0,0 +1,364 @@
+
+
+
+
+
diff --git a/monitoring/src/main/resources/lwm2m/models/1.xml b/monitoring/src/main/resources/lwm2m/models/1.xml
new file mode 100644
index 0000000000..a81caa27b0
--- /dev/null
+++ b/monitoring/src/main/resources/lwm2m/models/1.xml
@@ -0,0 +1,319 @@
+
+
+
+
+
diff --git a/monitoring/src/main/resources/lwm2m/models/2.xml b/monitoring/src/main/resources/lwm2m/models/2.xml
new file mode 100644
index 0000000000..79b2ed1321
--- /dev/null
+++ b/monitoring/src/main/resources/lwm2m/models/2.xml
@@ -0,0 +1,83 @@
+
+
+
+
+
diff --git a/monitoring/src/main/resources/lwm2m/models/test-model.xml b/monitoring/src/main/resources/lwm2m/models/test-model.xml
new file mode 100644
index 0000000000..c8e49ce32c
--- /dev/null
+++ b/monitoring/src/main/resources/lwm2m/models/test-model.xml
@@ -0,0 +1,45 @@
+
+
+
+
+
diff --git a/monitoring/src/main/resources/lwm2m/resource.json b/monitoring/src/main/resources/lwm2m/resource.json
new file mode 100644
index 0000000000..b624fa400e
--- /dev/null
+++ b/monitoring/src/main/resources/lwm2m/resource.json
@@ -0,0 +1,6 @@
+{
+ "title": "",
+ "resourceType": "LWM2M_MODEL",
+ "fileName": "test-model.xml",
+ "data": "PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPCEtLQoKICAgIENvcHlyaWdodCDCqSAyMDE2LTIwMjIgVGhlIFRoaW5nc2JvYXJkIEF1dGhvcnMKCiAgICBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgIkxpY2Vuc2UiKTsKICAgIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS4KICAgIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdAoKICAgICAgICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjAKCiAgICBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlCiAgICBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiAiQVMgSVMiIEJBU0lTLAogICAgV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuCiAgICBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kCiAgICBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS4KCi0tPgo8TFdNMk0geG1sbnM6eHNpPSJodHRwOi8vd3d3LnczLm9yZy8yMDAxL1hNTFNjaGVtYS1pbnN0YW5jZSIKICAgICAgIHhzaTpub05hbWVzcGFjZVNjaGVtYUxvY2F0aW9uPSJodHRwOi8vd3d3Lm9wZW5tb2JpbGVhbGxpYW5jZS5vcmcvdGVjaC9wcm9maWxlcy9MV00yTS12MV8xLnhzZCI+CiAgICA8T2JqZWN0IE9iamVjdFR5cGU9Ik1PRGVmaW5pdGlvbiI+CiAgICAgICAgPE5hbWU+THdNMk0gTW9uaXRvcmluZzwvTmFtZT4KICAgICAgICA8RGVzY3JpcHRpb24xPgogICAgICAgICAgICA8IVtDREFUQVtdXT48L0Rlc2NyaXB0aW9uMT4KICAgICAgICA8T2JqZWN0SUQ+MzwvT2JqZWN0SUQ+CiAgICAgICAgPE9iamVjdFVSTj51cm46b21hOmx3bTJtOm9tYTozOjEuMDwvT2JqZWN0VVJOPgogICAgICAgIDxMV00yTVZlcnNpb24+MS4xPC9MV00yTVZlcnNpb24+CiAgICAgICAgPE9iamVjdFZlcnNpb24+MS4wPC9PYmplY3RWZXJzaW9uPgogICAgICAgIDxNdWx0aXBsZUluc3RhbmNlcz5TaW5nbGU8L011bHRpcGxlSW5zdGFuY2VzPgogICAgICAgIDxNYW5kYXRvcnk+TWFuZGF0b3J5PC9NYW5kYXRvcnk+CiAgICAgICAgPFJlc291cmNlcz4KICAgICAgICAgICAgPEl0ZW0gSUQ9IjAiPgogICAgICAgICAgICAgICAgPE5hbWU+VGVzdCBkYXRhPC9OYW1lPgogICAgICAgICAgICAgICAgPE9wZXJhdGlvbnM+UjwvT3BlcmF0aW9ucz4KICAgICAgICAgICAgICAgIDxNdWx0aXBsZUluc3RhbmNlcz5TaW5nbGU8L011bHRpcGxlSW5zdGFuY2VzPgogICAgICAgICAgICAgICAgPE1hbmRhdG9yeT5PcHRpb25hbDwvTWFuZGF0b3J5PgogICAgICAgICAgICAgICAgPFR5cGU+U3RyaW5nPC9UeXBlPgogICAgICAgICAgICAgICAgPFJhbmdlRW51bWVyYXRpb24+PC9SYW5nZUVudW1lcmF0aW9uPgogICAgICAgICAgICAgICAgPFVuaXRzPjwvVW5pdHM+CiAgICAgICAgICAgICAgICA8RGVzY3JpcHRpb24+PCFbQ0RBVEFbVGVzdCBkYXRhXV0+PC9EZXNjcmlwdGlvbj4KICAgICAgICAgICAgPC9JdGVtPgogICAgICAgIDwvUmVzb3VyY2VzPgogICAgICAgIDxEZXNjcmlwdGlvbjI+PC9EZXNjcmlwdGlvbjI+CiAgICA8L09iamVjdD4KPC9MV00yTT4K"
+}
\ No newline at end of file
diff --git a/monitoring/src/main/resources/tb-monitoring.yml b/monitoring/src/main/resources/tb-monitoring.yml
index 403b29acc2..d89886cd72 100644
--- a/monitoring/src/main/resources/tb-monitoring.yml
+++ b/monitoring/src/main/resources/tb-monitoring.yml
@@ -91,6 +91,21 @@ monitoring:
# monitoring.transports.http.targets[1].base_url, monitoring.transports.http.targets[1].device.id,
# monitoring.transports.http.targets[2].base_url, monitoring.transports.http.targets[2].device.id, etc.
+ lwm2m:
+ # Enable LwM2M checks
+ enabled: '${LWM2M_TRANSPORT_MONITORING_ENABLED:true}'
+ # LwM2M request timeout in milliseconds
+ request_timeout_ms: '${LWM2M_REQUEST_TIMEOUT_MS:4000}'
+ targets:
+ # LwM2M base url, coap://DOMAIN:5685 by default
+ - base_url: '${LWM2M_TRANSPORT_BASE_URL:coap://${monitoring.domain}:5685}'
+ # LwM2M device to push telemetry for. If not set - device will be found or created automatically
+ device:
+ id: '${LWM2M_TRANSPORT_TARGET_DEVICE_ID:}'
+ # To add more targets, use following environment variables:
+ # monitoring.transports.lwm2m.targets[1].base_url, monitoring.transports.lwm2m.targets[1].device.id,
+ # monitoring.transports.lwm2m.targets[2].base_url, monitoring.transports.lwm2m.targets[2].device.id, etc.
+
notification_channels:
slack:
# Enable notifying via Slack