Merge branch 'master' of https://github.com/thingsboard/thingsboard into lwm2m-tests-fix
This commit is contained in:
commit
4b831d0eea
@ -18,8 +18,8 @@
|
|||||||
"resources": [],
|
"resources": [],
|
||||||
"templateHtml": "<div style=\"height: 100%; overflow-y: auto;\" id=\"device-terminal\"></div>",
|
"templateHtml": "<div style=\"height: 100%; overflow-y: auto;\" id=\"device-terminal\"></div>",
|
||||||
"templateCss": ".cmd .cursor.blink {\n -webkit-animation-name: terminal-underline;\n -moz-animation-name: terminal-underline;\n -ms-animation-name: terminal-underline;\n animation-name: terminal-underline;\n}\n.terminal .inverted, .cmd .inverted {\n border-bottom-color: #aaa;\n}\n\n",
|
"templateCss": ".cmd .cursor.blink {\n -webkit-animation-name: terminal-underline;\n -moz-animation-name: terminal-underline;\n -ms-animation-name: terminal-underline;\n animation-name: terminal-underline;\n}\n.terminal .inverted, .cmd .inverted {\n border-bottom-color: #aaa;\n}\n\n",
|
||||||
"controllerScript": "var requestTimeout = 500;\n\nself.onInit = function() {\n var subscription = self.ctx.defaultSubscription;\n var rpcEnabled = subscription.rpcEnabled;\n var deviceName = 'Simulated';\n var prompt;\n if (subscription.targetDeviceName && subscription.targetDeviceName.length) {\n deviceName = subscription.targetDeviceName;\n }\n if (self.ctx.settings.requestTimeout) {\n requestTimeout = self.ctx.settings.requestTimeout;\n }\n var greetings = 'Welcome to ThingsBoard RPC debug terminal.\\n\\n';\n if (!rpcEnabled) {\n greetings += 'Target device is not set!\\n\\n';\n prompt = '';\n } else {\n greetings += 'Current target device for RPC commands: [[b;#fff;]' + deviceName + ']\\n\\n';\n greetings += 'Please type [[b;#fff;]\\'help\\'] to see usage.\\n';\n prompt = '[[b;#8bc34a;]' + deviceName +']> ';\n }\n \n var terminal = $('#device-terminal', self.ctx.$container).terminal(\n function(command) {\n if (command !== '') {\n try {\n var localCommand = command.trim();\n var requestUUID = uuidv4();\n if (localCommand === 'help') {\n printUsage(this);\n } else {\n var spaceIndex = localCommand.indexOf(' ');\n if (spaceIndex === -1 && !localCommand.length) {\n this.error(\"Wrong number of arguments!\");\n this.echo(' ');\n } else {\n var params;\n if (spaceIndex === -1) {\n spaceIndex = localCommand.length;\n }\n var name = localCommand.substr(0, spaceIndex);\n var args = localCommand.substr(spaceIndex + 1);\n if (args.length) {\n try {\n params = JSON.parse(args);\n } catch (e) {\n params = args;\n }\n }\n performRpc(this, name, params, requestUUID);\n }\n }\n } catch(e) {\n this.error(new String(e));\n }\n } else {\n this.echo('');\n }\n }, {\n greetings: greetings,\n prompt: prompt,\n enabled: rpcEnabled\n });\n \n if (!rpcEnabled) {\n terminal.error('No RPC target detected!').pause();\n }\n}\n\n\nfunction printUsage(terminal) {\n var commandsListText = '\\n[[b;#fff;]Usage:]\\n';\n commandsListText += ' <method> [params body]]\\n\\n';\n commandsListText += '[[b;#fff;]Example 1:]\\n'; \n commandsListText += ' myRemoteMethod1 myText\\n\\n'; \n commandsListText += '[[b;#fff;]Example 2:]\\n'; \n commandsListText += ' myOtherRemoteMethod \"{\\\\\"key1\\\\\": 2, \\\\\"key2\\\\\": \\\\\"myVal\\\\\"}\"\\n'; \n terminal.echo(new String(commandsListText));\n}\n\n\nfunction performRpc(terminal, method, params, requestUUID) {\n terminal.pause();\n self.ctx.controlApi.sendTwoWayCommand(method, params, requestTimeout, requestUUID).subscribe(\n function success(responseBody) {\n terminal.echo(JSON.stringify(responseBody));\n terminal.echo(' ');\n terminal.resume();\n },\n function fail() {\n var errorText = self.ctx.defaultSubscription.rpcErrorText;\n terminal.error(errorText);\n terminal.echo(' ');\n terminal.resume();\n }\n );\n}\n\n\nfunction uuidv4() {\n return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {\n var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8);\n return v.toString(16);\n });\n}\n\n \nself.onDestroy = function() {\n}",
|
"controllerScript": "var requestTimeout = 500;\nvar requestPersistent = false;\n\nself.onInit = function() {\n var subscription = self.ctx.defaultSubscription;\n var rpcEnabled = subscription.rpcEnabled;\n var deviceName = 'Simulated';\n var prompt;\n if (subscription.targetDeviceName && subscription.targetDeviceName.length) {\n deviceName = subscription.targetDeviceName;\n }\n if (self.ctx.settings.requestTimeout) {\n requestTimeout = self.ctx.settings.requestTimeout;\n }\n if (self.ctx.settings.requestPersistent) {\n requestPersistent = self.ctx.settings.requestPersistent;\n }\n var greetings = 'Welcome to ThingsBoard RPC debug terminal.\\n\\n';\n if (!rpcEnabled) {\n greetings += 'Target device is not set!\\n\\n';\n prompt = '';\n } else {\n greetings += 'Current target device for RPC commands: [[b;#fff;]' + deviceName + ']\\n\\n';\n greetings += 'Please type [[b;#fff;]\\'help\\'] to see usage.\\n';\n prompt = '[[b;#8bc34a;]' + deviceName +']> ';\n }\n \n var terminal = $('#device-terminal', self.ctx.$container).terminal(\n function(command) {\n if (command !== '') {\n try {\n var localCommand = command.trim();\n var requestUUID = uuidv4();\n if (localCommand === 'help') {\n printUsage(this);\n } else {\n var spaceIndex = localCommand.indexOf(' ');\n if (spaceIndex === -1 && !localCommand.length) {\n this.error(\"Wrong number of arguments!\");\n this.echo(' ');\n } else {\n var params;\n if (spaceIndex === -1) {\n spaceIndex = localCommand.length;\n }\n var name = localCommand.substr(0, spaceIndex);\n var args = localCommand.substr(spaceIndex + 1);\n if (args.length) {\n try {\n params = JSON.parse(args);\n } catch (e) {\n params = args;\n }\n }\n performRpc(this, name, params, requestUUID);\n }\n }\n } catch(e) {\n this.error(new String(e));\n }\n } else {\n this.echo('');\n }\n }, {\n greetings: greetings,\n prompt: prompt,\n enabled: rpcEnabled\n });\n \n if (!rpcEnabled) {\n terminal.error('No RPC target detected!').pause();\n }\n}\n\n\nfunction printUsage(terminal) {\n var commandsListText = '\\n[[b;#fff;]Usage:]\\n';\n commandsListText += ' <method> [params body]]\\n\\n';\n commandsListText += '[[b;#fff;]Example 1:]\\n'; \n commandsListText += ' myRemoteMethod1 myText\\n\\n'; \n commandsListText += '[[b;#fff;]Example 2:]\\n'; \n commandsListText += ' myOtherRemoteMethod \"{\\\\\"key1\\\\\": 2, \\\\\"key2\\\\\": \\\\\"myVal\\\\\"}\"\\n'; \n terminal.echo(new String(commandsListText));\n}\n\n\nfunction performRpc(terminal, method, params, requestUUID) {\n terminal.pause();\n self.ctx.controlApi.sendTwoWayCommand(method, params, requestTimeout, requestPersistent, requestUUID).subscribe(\n function success(responseBody) {\n terminal.echo(JSON.stringify(responseBody));\n terminal.echo(' ');\n terminal.resume();\n },\n function fail() {\n var errorText = self.ctx.defaultSubscription.rpcErrorText;\n terminal.error(errorText);\n terminal.echo(' ');\n terminal.resume();\n }\n );\n}\n\n\nfunction uuidv4() {\n return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {\n var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8);\n return v.toString(16);\n });\n}\n\n \nself.onDestroy = function() {\n}",
|
||||||
"settingsSchema": "{\n \"schema\": {\n \"type\": \"object\",\n \"title\": \"Settings\",\n \"properties\": {\n \"requestTimeout\": {\n \"title\": \"RPC request timeout (ms)\",\n \"type\": \"number\",\n \"default\": 500\n }\n },\n \"required\": [\"requestTimeout\"]\n },\n \"form\": [\n \"requestTimeout\"\n ]\n}",
|
"settingsSchema": "{\n \"schema\": {\n \"type\": \"object\",\n \"title\": \"Settings\",\n \"properties\": {\n \"requestTimeout\": {\n \"title\": \"RPC request timeout (ms)\",\n \"type\": \"number\",\n \"default\": 500\n },\n \"requestPersistent\": {\n \"title\": \"RPC request persistent\",\n \"type\": \"boolean\",\n \"default\": false\n }\n },\n \"required\": [\"requestTimeout\"]\n },\n \"form\": [\n \"requestTimeout\",\n \"requestPersistent\"\n ]\n}",
|
||||||
"dataKeySettingsSchema": "{}\n",
|
"dataKeySettingsSchema": "{}\n",
|
||||||
"defaultConfig": "{\"targetDeviceAliases\":[],\"showTitle\":true,\"backgroundColor\":\"#010101\",\"color\":\"rgba(255, 254, 254, 0.87)\",\"padding\":\"0px\",\"settings\":{\"parseGpioStatusFunction\":\"return body[pin] === true;\",\"gpioStatusChangeRequest\":{\"method\":\"setGpioStatus\",\"paramsBody\":\"{\\n \\\"pin\\\": \\\"{$pin}\\\",\\n \\\"enabled\\\": \\\"{$enabled}\\\"\\n}\"},\"requestTimeout\":500,\"switchPanelBackgroundColor\":\"#b71c1c\",\"gpioStatusRequest\":{\"method\":\"getGpioStatus\",\"paramsBody\":\"{}\"},\"gpioList\":[{\"pin\":1,\"label\":\"GPIO 1\",\"row\":0,\"col\":0,\"_uniqueKey\":0},{\"pin\":2,\"label\":\"GPIO 2\",\"row\":0,\"col\":1,\"_uniqueKey\":1},{\"pin\":3,\"label\":\"GPIO 3\",\"row\":1,\"col\":0,\"_uniqueKey\":2}]},\"title\":\"RPC debug terminal\",\"dropShadow\":true,\"enableFullscreen\":true,\"widgetStyle\":{},\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400},\"useDashboardTimewindow\":true,\"showLegend\":false,\"actions\":{}}"
|
"defaultConfig": "{\"targetDeviceAliases\":[],\"showTitle\":true,\"backgroundColor\":\"#010101\",\"color\":\"rgba(255, 254, 254, 0.87)\",\"padding\":\"0px\",\"settings\":{\"parseGpioStatusFunction\":\"return body[pin] === true;\",\"gpioStatusChangeRequest\":{\"method\":\"setGpioStatus\",\"paramsBody\":\"{\\n \\\"pin\\\": \\\"{$pin}\\\",\\n \\\"enabled\\\": \\\"{$enabled}\\\"\\n}\"},\"requestTimeout\":500,\"switchPanelBackgroundColor\":\"#b71c1c\",\"gpioStatusRequest\":{\"method\":\"getGpioStatus\",\"paramsBody\":\"{}\"},\"gpioList\":[{\"pin\":1,\"label\":\"GPIO 1\",\"row\":0,\"col\":0,\"_uniqueKey\":0},{\"pin\":2,\"label\":\"GPIO 2\",\"row\":0,\"col\":1,\"_uniqueKey\":1},{\"pin\":3,\"label\":\"GPIO 3\",\"row\":1,\"col\":0,\"_uniqueKey\":2}]},\"title\":\"RPC debug terminal\",\"dropShadow\":true,\"enableFullscreen\":true,\"widgetStyle\":{},\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400},\"useDashboardTimewindow\":true,\"showLegend\":false,\"actions\":{}}"
|
||||||
}
|
}
|
||||||
|
|||||||
@ -64,7 +64,7 @@ DROP INDEX IF EXISTS public.idx_event_ts;
|
|||||||
-- Hint: add CONCURRENTLY to CREATE INDEX query in case of more then 1 million records or during live update
|
-- Hint: add CONCURRENTLY to CREATE INDEX query in case of more then 1 million records or during live update
|
||||||
-- CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_event_ts
|
-- CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_event_ts
|
||||||
CREATE INDEX IF NOT EXISTS idx_event_ts
|
CREATE INDEX IF NOT EXISTS idx_event_ts
|
||||||
ON public.event USING btree
|
ON public.event
|
||||||
(ts DESC NULLS LAST)
|
(ts DESC NULLS LAST)
|
||||||
WITH (FILLFACTOR=95);
|
WITH (FILLFACTOR=95);
|
||||||
|
|
||||||
@ -78,8 +78,8 @@ DROP INDEX IF EXISTS public.idx_event_tenant_entity_type_entity_event_type_creat
|
|||||||
|
|
||||||
-- CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_event_tenant_entity_type_entity_event_type_created_time_des
|
-- CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_event_tenant_entity_type_entity_event_type_created_time_des
|
||||||
CREATE INDEX IF NOT EXISTS idx_event_tenant_entity_type_entity_event_type_created_time_des
|
CREATE INDEX IF NOT EXISTS idx_event_tenant_entity_type_entity_event_type_created_time_des
|
||||||
ON public.event USING btree
|
ON public.event
|
||||||
(tenant_id ASC NULLS LAST, entity_type ASC NULLS LAST, entity_id ASC NULLS LAST, event_type ASC NULLS LAST, created_time DESC NULLS LAST)
|
(tenant_id ASC, entity_type ASC, entity_id ASC, event_type ASC, created_time DESC NULLS LAST)
|
||||||
WITH (FILLFACTOR=95);
|
WITH (FILLFACTOR=95);
|
||||||
|
|
||||||
COMMENT ON INDEX public.idx_event_tenant_entity_type_entity_event_type_created_time_des
|
COMMENT ON INDEX public.idx_event_tenant_entity_type_entity_event_type_created_time_des
|
||||||
|
|||||||
@ -206,13 +206,13 @@ class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcessor {
|
|||||||
syncSessionSet.forEach(rpcSubscriptions::remove);
|
syncSessionSet.forEach(rpcSubscriptions::remove);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (persisted && !(sent || request.isOneway())) {
|
if (persisted) {
|
||||||
ObjectNode response = JacksonUtil.newObjectNode();
|
ObjectNode response = JacksonUtil.newObjectNode();
|
||||||
response.put("rpcId", request.getId().toString());
|
response.put("rpcId", request.getId().toString());
|
||||||
systemContext.getTbCoreDeviceRpcService().processRpcResponseFromDeviceActor(new FromDeviceRpcResponse(msg.getMsg().getId(), JacksonUtil.toString(response), null));
|
systemContext.getTbCoreDeviceRpcService().processRpcResponseFromDeviceActor(new FromDeviceRpcResponse(msg.getMsg().getId(), JacksonUtil.toString(response), null));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (request.isOneway() && sent) {
|
if (!persisted && request.isOneway() && sent) {
|
||||||
log.debug("[{}] Rpc command response sent [{}]!", deviceId, request.getId());
|
log.debug("[{}] Rpc command response sent [{}]!", deviceId, request.getId());
|
||||||
systemContext.getTbCoreDeviceRpcService().processRpcResponseFromDeviceActor(new FromDeviceRpcResponse(msg.getMsg().getId(), null, null));
|
systemContext.getTbCoreDeviceRpcService().processRpcResponseFromDeviceActor(new FromDeviceRpcResponse(msg.getMsg().getId(), null, null));
|
||||||
} else {
|
} else {
|
||||||
@ -298,7 +298,7 @@ class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcessor {
|
|||||||
toDeviceRpcPendingMap.entrySet().stream().findFirst().ifPresent(processPendingRpc(context, sessionId, sessionInfo.getNodeId(), sentOneWayIds));
|
toDeviceRpcPendingMap.entrySet().stream().findFirst().ifPresent(processPendingRpc(context, sessionId, sessionInfo.getNodeId(), sentOneWayIds));
|
||||||
}
|
}
|
||||||
|
|
||||||
sentOneWayIds.forEach(toDeviceRpcPendingMap::remove);
|
sentOneWayIds.stream().filter(id -> !toDeviceRpcPendingMap.get(id).getMsg().getMsg().isPersisted()).forEach(toDeviceRpcPendingMap::remove);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Consumer<Map.Entry<Integer, ToDeviceRpcRequestMetadata>> processPendingRpc(TbActorCtx context, UUID sessionId, String nodeId, Set<Integer> sentOneWayIds) {
|
private Consumer<Map.Entry<Integer, ToDeviceRpcRequestMetadata>> processPendingRpc(TbActorCtx context, UUID sessionId, String nodeId, Set<Integer> sentOneWayIds) {
|
||||||
@ -503,9 +503,6 @@ class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcessor {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
log.debug("[{}] Rpc command response [{}] is stale!", deviceId, responseMsg.getRequestId());
|
log.debug("[{}] Rpc command response [{}] is stale!", deviceId, responseMsg.getRequestId());
|
||||||
if (requestMd.getMsg().getMsg().isPersisted()) {
|
|
||||||
systemContext.getTbRpcService().save(tenantId, new RpcId(requestMd.getMsg().getMsg().getId()), RpcStatus.FAILED, JacksonUtil.toJsonNode(responseMsg.getPayload()));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -34,6 +34,7 @@ import org.springframework.web.bind.annotation.ResponseBody;
|
|||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
import org.springframework.web.context.request.async.DeferredResult;
|
import org.springframework.web.context.request.async.DeferredResult;
|
||||||
import org.thingsboard.rule.engine.api.RpcError;
|
import org.thingsboard.rule.engine.api.RpcError;
|
||||||
|
import org.thingsboard.server.common.data.DataConstants;
|
||||||
import org.thingsboard.server.common.data.audit.ActionType;
|
import org.thingsboard.server.common.data.audit.ActionType;
|
||||||
import org.thingsboard.server.common.data.exception.ThingsboardErrorCode;
|
import org.thingsboard.server.common.data.exception.ThingsboardErrorCode;
|
||||||
import org.thingsboard.server.common.data.exception.ThingsboardException;
|
import org.thingsboard.server.common.data.exception.ThingsboardException;
|
||||||
@ -100,7 +101,7 @@ public class RpcController extends BaseController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
|
@PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
|
||||||
@RequestMapping(value = "/persisted/{rpcId}", method = RequestMethod.GET)
|
@RequestMapping(value = "/persistent/{rpcId}", method = RequestMethod.GET)
|
||||||
@ResponseBody
|
@ResponseBody
|
||||||
public Rpc getPersistedRpc(@PathVariable("rpcId") String strRpc) throws ThingsboardException {
|
public Rpc getPersistedRpc(@PathVariable("rpcId") String strRpc) throws ThingsboardException {
|
||||||
checkParameter("RpcId", strRpc);
|
checkParameter("RpcId", strRpc);
|
||||||
@ -113,7 +114,7 @@ public class RpcController extends BaseController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
|
@PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
|
||||||
@RequestMapping(value = "/persisted/{deviceId}", method = RequestMethod.GET)
|
@RequestMapping(value = "/persistent/device/{deviceId}", method = RequestMethod.GET)
|
||||||
@ResponseBody
|
@ResponseBody
|
||||||
public PageData<Rpc> getPersistedRpcByDevice(@PathVariable("deviceId") String strDeviceId,
|
public PageData<Rpc> getPersistedRpcByDevice(@PathVariable("deviceId") String strDeviceId,
|
||||||
@RequestParam int pageSize,
|
@RequestParam int pageSize,
|
||||||
@ -134,7 +135,7 @@ public class RpcController extends BaseController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@PreAuthorize("hasAnyAuthority('TENANT_ADMIN')")
|
@PreAuthorize("hasAnyAuthority('TENANT_ADMIN')")
|
||||||
@RequestMapping(value = "/persisted/{rpcId}", method = RequestMethod.DELETE)
|
@RequestMapping(value = "/persistent/{rpcId}", method = RequestMethod.DELETE)
|
||||||
@ResponseBody
|
@ResponseBody
|
||||||
public void deleteResource(@PathVariable("rpcId") String strRpc) throws ThingsboardException {
|
public void deleteResource(@PathVariable("rpcId") String strRpc) throws ThingsboardException {
|
||||||
checkParameter("RpcId", strRpc);
|
checkParameter("RpcId", strRpc);
|
||||||
@ -155,7 +156,7 @@ public class RpcController extends BaseController {
|
|||||||
long timeout = rpcRequestBody.has("timeout") ? rpcRequestBody.get("timeout").asLong() : defaultTimeout;
|
long timeout = rpcRequestBody.has("timeout") ? rpcRequestBody.get("timeout").asLong() : defaultTimeout;
|
||||||
long expTime = System.currentTimeMillis() + Math.max(minTimeout, timeout);
|
long expTime = System.currentTimeMillis() + Math.max(minTimeout, timeout);
|
||||||
UUID rpcRequestUUID = rpcRequestBody.has("requestUUID") ? UUID.fromString(rpcRequestBody.get("requestUUID").asText()) : UUID.randomUUID();
|
UUID rpcRequestUUID = rpcRequestBody.has("requestUUID") ? UUID.fromString(rpcRequestBody.get("requestUUID").asText()) : UUID.randomUUID();
|
||||||
boolean persisted = rpcRequestBody.has("persisted") && rpcRequestBody.get("persisted").asBoolean();
|
boolean persisted = rpcRequestBody.has(DataConstants.PERSISTENT) && rpcRequestBody.get(DataConstants.PERSISTENT).asBoolean();
|
||||||
accessValidator.validate(currentUser, Operation.RPC_CALL, deviceId, new HttpValidationCallback(response, new FutureCallback<DeferredResult<ResponseEntity>>() {
|
accessValidator.validate(currentUser, Operation.RPC_CALL, deviceId, new HttpValidationCallback(response, new FutureCallback<DeferredResult<ResponseEntity>>() {
|
||||||
@Override
|
@Override
|
||||||
public void onSuccess(@Nullable DeferredResult<ResponseEntity> result) {
|
public void onSuccess(@Nullable DeferredResult<ResponseEntity> result) {
|
||||||
|
|||||||
@ -15,6 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
package org.thingsboard.server.service.install;
|
package org.thingsboard.server.service.install;
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.context.annotation.Profile;
|
import org.springframework.context.annotation.Profile;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.thingsboard.server.dao.util.PsqlDao;
|
import org.thingsboard.server.dao.util.PsqlDao;
|
||||||
@ -22,9 +23,22 @@ import org.thingsboard.server.dao.util.PsqlDao;
|
|||||||
@Service
|
@Service
|
||||||
@PsqlDao
|
@PsqlDao
|
||||||
@Profile("install")
|
@Profile("install")
|
||||||
|
@Slf4j
|
||||||
public class PsqlEntityDatabaseSchemaService extends SqlAbstractDatabaseSchemaService
|
public class PsqlEntityDatabaseSchemaService extends SqlAbstractDatabaseSchemaService
|
||||||
implements EntityDatabaseSchemaService {
|
implements EntityDatabaseSchemaService {
|
||||||
|
public static final String SCHEMA_ENTITIES_SQL = "schema-entities.sql";
|
||||||
|
public static final String SCHEMA_ENTITIES_IDX_SQL = "schema-entities-idx.sql";
|
||||||
|
public static final String SCHEMA_ENTITIES_IDX_PSQL_ADDON_SQL = "schema-entities-idx-psql-addon.sql";
|
||||||
|
|
||||||
public PsqlEntityDatabaseSchemaService() {
|
public PsqlEntityDatabaseSchemaService() {
|
||||||
super("schema-entities.sql", "schema-entities-idx.sql");
|
super(SCHEMA_ENTITIES_SQL, SCHEMA_ENTITIES_IDX_SQL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void createDatabaseIndexes() throws Exception {
|
||||||
|
super.createDatabaseIndexes();
|
||||||
|
log.info("Installing SQL DataBase schema PostgreSQL specific indexes part: " + SCHEMA_ENTITIES_IDX_PSQL_ADDON_SQL);
|
||||||
|
executeQueryFromFile(SCHEMA_ENTITIES_IDX_PSQL_ADDON_SQL);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -19,7 +19,7 @@ import lombok.extern.slf4j.Slf4j;
|
|||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
|
||||||
import java.nio.charset.Charset;
|
import java.io.IOException;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.nio.file.Paths;
|
import java.nio.file.Paths;
|
||||||
@ -59,14 +59,8 @@ public abstract class SqlAbstractDatabaseSchemaService implements DatabaseSchema
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void createDatabaseSchema(boolean createIndexes) throws Exception {
|
public void createDatabaseSchema(boolean createIndexes) throws Exception {
|
||||||
|
|
||||||
log.info("Installing SQL DataBase schema part: " + schemaSql);
|
log.info("Installing SQL DataBase schema part: " + schemaSql);
|
||||||
|
executeQueryFromFile(schemaSql);
|
||||||
Path schemaFile = Paths.get(installScripts.getDataDir(), SQL_DIR, schemaSql);
|
|
||||||
try (Connection conn = DriverManager.getConnection(dbUrl, dbUserName, dbPassword)) {
|
|
||||||
String sql = new String(Files.readAllBytes(schemaFile), Charset.forName("UTF-8"));
|
|
||||||
conn.createStatement().execute(sql); //NOSONAR, ignoring because method used to load initial thingsboard database schema
|
|
||||||
}
|
|
||||||
|
|
||||||
if (createIndexes) {
|
if (createIndexes) {
|
||||||
this.createDatabaseIndexes();
|
this.createDatabaseIndexes();
|
||||||
@ -77,11 +71,15 @@ public abstract class SqlAbstractDatabaseSchemaService implements DatabaseSchema
|
|||||||
public void createDatabaseIndexes() throws Exception {
|
public void createDatabaseIndexes() throws Exception {
|
||||||
if (schemaIdxSql != null) {
|
if (schemaIdxSql != null) {
|
||||||
log.info("Installing SQL DataBase schema indexes part: " + schemaIdxSql);
|
log.info("Installing SQL DataBase schema indexes part: " + schemaIdxSql);
|
||||||
Path schemaIdxFile = Paths.get(installScripts.getDataDir(), SQL_DIR, schemaIdxSql);
|
executeQueryFromFile(schemaIdxSql);
|
||||||
try (Connection conn = DriverManager.getConnection(dbUrl, dbUserName, dbPassword)) {
|
}
|
||||||
String sql = new String(Files.readAllBytes(schemaIdxFile), Charset.forName("UTF-8"));
|
}
|
||||||
conn.createStatement().execute(sql); //NOSONAR, ignoring because method used to load initial thingsboard database schema
|
|
||||||
}
|
void executeQueryFromFile(String schemaIdxSql) throws SQLException, IOException {
|
||||||
|
Path schemaIdxFile = Paths.get(installScripts.getDataDir(), SQL_DIR, schemaIdxSql);
|
||||||
|
String sql = Files.readString(schemaIdxFile);
|
||||||
|
try (Connection conn = DriverManager.getConnection(dbUrl, dbUserName, dbPassword)) {
|
||||||
|
conn.createStatement().execute(sql); //NOSONAR, ignoring because method used to load initial thingsboard database schema
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -91,7 +89,8 @@ public abstract class SqlAbstractDatabaseSchemaService implements DatabaseSchema
|
|||||||
log.info("Successfully executed query: {}", query);
|
log.info("Successfully executed query: {}", query);
|
||||||
Thread.sleep(5000);
|
Thread.sleep(5000);
|
||||||
} catch (InterruptedException | SQLException e) {
|
} catch (InterruptedException | SQLException e) {
|
||||||
log.info("Failed to execute query: {} due to: {}", query, e.getMessage());
|
log.error("Failed to execute query: {} due to: {}", query, e.getMessage());
|
||||||
|
throw new RuntimeException("Failed to execute query: " + query, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -31,6 +31,7 @@ import org.springframework.mail.javamail.MimeMessageHelper;
|
|||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.ui.freemarker.FreeMarkerTemplateUtils;
|
import org.springframework.ui.freemarker.FreeMarkerTemplateUtils;
|
||||||
import org.thingsboard.rule.engine.api.MailService;
|
import org.thingsboard.rule.engine.api.MailService;
|
||||||
|
import org.thingsboard.rule.engine.api.TbEmail;
|
||||||
import org.thingsboard.server.common.data.AdminSettings;
|
import org.thingsboard.server.common.data.AdminSettings;
|
||||||
import org.thingsboard.server.common.data.ApiFeature;
|
import org.thingsboard.server.common.data.ApiFeature;
|
||||||
import org.thingsboard.server.common.data.ApiUsageRecordKey;
|
import org.thingsboard.server.common.data.ApiUsageRecordKey;
|
||||||
@ -250,35 +251,35 @@ public class DefaultMailService implements MailService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void send(TenantId tenantId, CustomerId customerId, String from, String to, String cc, String bcc, String subject, String body, boolean isHtml, Map<String, String> images) throws ThingsboardException {
|
public void send(TenantId tenantId, CustomerId customerId, TbEmail tbEmail) throws ThingsboardException {
|
||||||
sendMail(tenantId, customerId, from, to, cc, bcc, subject, body, isHtml, images, this.mailSender);
|
sendMail(tenantId, customerId, tbEmail, this.mailSender);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void send(TenantId tenantId, CustomerId customerId, String from, String to, String cc, String bcc, String subject, String body, boolean isHtml, Map<String, String> images, JavaMailSender javaMailSender) throws ThingsboardException {
|
public void send(TenantId tenantId, CustomerId customerId, TbEmail tbEmail, JavaMailSender javaMailSender) throws ThingsboardException {
|
||||||
sendMail(tenantId, customerId, from, to, cc, bcc, subject, body, isHtml, images, javaMailSender);
|
sendMail(tenantId, customerId, tbEmail, javaMailSender);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void sendMail(TenantId tenantId, CustomerId customerId, String from, String to, String cc, String bcc, String subject, String body, boolean isHtml, Map<String, String> images, JavaMailSender javaMailSender) throws ThingsboardException {
|
private void sendMail(TenantId tenantId, CustomerId customerId, TbEmail tbEmail, JavaMailSender javaMailSender) throws ThingsboardException {
|
||||||
if (apiUsageStateService.getApiUsageState(tenantId).isEmailSendEnabled()) {
|
if (apiUsageStateService.getApiUsageState(tenantId).isEmailSendEnabled()) {
|
||||||
try {
|
try {
|
||||||
MimeMessage mailMsg = javaMailSender.createMimeMessage();
|
MimeMessage mailMsg = javaMailSender.createMimeMessage();
|
||||||
boolean multipart = (images != null && !images.isEmpty());
|
boolean multipart = (tbEmail.getImages() != null && !tbEmail.getImages().isEmpty());
|
||||||
MimeMessageHelper helper = new MimeMessageHelper(mailMsg, multipart, "UTF-8");
|
MimeMessageHelper helper = new MimeMessageHelper(mailMsg, multipart, "UTF-8");
|
||||||
helper.setFrom(StringUtils.isBlank(from) ? mailFrom : from);
|
helper.setFrom(StringUtils.isBlank(tbEmail.getFrom()) ? mailFrom : tbEmail.getFrom());
|
||||||
helper.setTo(to.split("\\s*,\\s*"));
|
helper.setTo(tbEmail.getTo().split("\\s*,\\s*"));
|
||||||
if (!StringUtils.isBlank(cc)) {
|
if (!StringUtils.isBlank(tbEmail.getCc())) {
|
||||||
helper.setCc(cc.split("\\s*,\\s*"));
|
helper.setCc(tbEmail.getCc().split("\\s*,\\s*"));
|
||||||
}
|
}
|
||||||
if (!StringUtils.isBlank(bcc)) {
|
if (!StringUtils.isBlank(tbEmail.getBcc())) {
|
||||||
helper.setBcc(bcc.split("\\s*,\\s*"));
|
helper.setBcc(tbEmail.getBcc().split("\\s*,\\s*"));
|
||||||
}
|
}
|
||||||
helper.setSubject(subject);
|
helper.setSubject(tbEmail.getSubject());
|
||||||
helper.setText(body, isHtml);
|
helper.setText(tbEmail.getBody(), tbEmail.isHtml());
|
||||||
|
|
||||||
if (multipart) {
|
if (multipart) {
|
||||||
for (String imgId : images.keySet()) {
|
for (String imgId : tbEmail.getImages().keySet()) {
|
||||||
String imgValue = images.get(imgId);
|
String imgValue = tbEmail.getImages().get(imgId);
|
||||||
String value = imgValue.replaceFirst("^data:image/[^;]*;base64,?", "");
|
String value = imgValue.replaceFirst("^data:image/[^;]*;base64,?", "");
|
||||||
byte[] bytes = javax.xml.bind.DatatypeConverter.parseBase64Binary(value);
|
byte[] bytes = javax.xml.bind.DatatypeConverter.parseBase64Binary(value);
|
||||||
String contentType = helper.getFileTypeMap().getContentType(imgId);
|
String contentType = helper.getFileTypeMap().getContentType(imgId);
|
||||||
|
|||||||
@ -157,7 +157,7 @@ public class DefaultTbCoreDeviceRpcService implements TbCoreDeviceRpcService {
|
|||||||
metaData.putValue("originServiceId", serviceId);
|
metaData.putValue("originServiceId", serviceId);
|
||||||
metaData.putValue("expirationTime", Long.toString(msg.getExpirationTime()));
|
metaData.putValue("expirationTime", Long.toString(msg.getExpirationTime()));
|
||||||
metaData.putValue("oneway", Boolean.toString(msg.isOneway()));
|
metaData.putValue("oneway", Boolean.toString(msg.isOneway()));
|
||||||
metaData.putValue("persisted", Boolean.toString(msg.isPersisted()));
|
metaData.putValue(DataConstants.PERSISTENT, Boolean.toString(msg.isPersisted()));
|
||||||
|
|
||||||
Device device = deviceService.findDeviceById(msg.getTenantId(), msg.getDeviceId());
|
Device device = deviceService.findDeviceById(msg.getTenantId(), msg.getDeviceId());
|
||||||
if (device != null) {
|
if (device != null) {
|
||||||
|
|||||||
@ -462,9 +462,12 @@ public class DefaultTransportApiService implements TransportApiService {
|
|||||||
|
|
||||||
private DeviceInfoProto getDeviceInfoProto(Device device) throws JsonProcessingException {
|
private DeviceInfoProto getDeviceInfoProto(Device device) throws JsonProcessingException {
|
||||||
PowerMode powerMode = null;
|
PowerMode powerMode = null;
|
||||||
|
Long edrxCycle = null;
|
||||||
switch (device.getDeviceData().getTransportConfiguration().getType()) {
|
switch (device.getDeviceData().getTransportConfiguration().getType()) {
|
||||||
case LWM2M:
|
case LWM2M:
|
||||||
powerMode = ((Lwm2mDeviceTransportConfiguration) device.getDeviceData().getTransportConfiguration()).getPowerMode();
|
Lwm2mDeviceTransportConfiguration transportConfiguration = (Lwm2mDeviceTransportConfiguration) device.getDeviceData().getTransportConfiguration();
|
||||||
|
powerMode = transportConfiguration.getPowerMode();
|
||||||
|
edrxCycle = transportConfiguration.getEdrxCycle();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -482,6 +485,7 @@ public class DefaultTransportApiService implements TransportApiService {
|
|||||||
.setAdditionalInfo(mapper.writeValueAsString(device.getAdditionalInfo()));
|
.setAdditionalInfo(mapper.writeValueAsString(device.getAdditionalInfo()));
|
||||||
if (powerMode != null) {
|
if (powerMode != null) {
|
||||||
builder.setPowerMode(powerMode.name());
|
builder.setPowerMode(powerMode.name());
|
||||||
|
builder.setEdrxCycle(edrxCycle);
|
||||||
}
|
}
|
||||||
return builder.build();
|
return builder.build();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,54 @@
|
|||||||
|
/**
|
||||||
|
* Copyright © 2016-2021 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.server.service.install;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import static org.mockito.ArgumentMatchers.anyString;
|
||||||
|
import static org.mockito.BDDMockito.willDoNothing;
|
||||||
|
import static org.mockito.Mockito.spy;
|
||||||
|
import static org.mockito.Mockito.times;
|
||||||
|
import static org.mockito.Mockito.verify;
|
||||||
|
|
||||||
|
public class PsqlEntityDatabaseSchemaServiceTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenPsqlDbSchemaService_whenCreateDatabaseSchema_thenVerifyPsqlIndexSpecificCall() throws Exception {
|
||||||
|
PsqlEntityDatabaseSchemaService service = spy(new PsqlEntityDatabaseSchemaService());
|
||||||
|
willDoNothing().given(service).executeQueryFromFile(anyString());
|
||||||
|
|
||||||
|
service.createDatabaseSchema();
|
||||||
|
|
||||||
|
verify(service, times(1)).createDatabaseIndexes();
|
||||||
|
verify(service, times(1)).executeQueryFromFile(PsqlEntityDatabaseSchemaService.SCHEMA_ENTITIES_SQL);
|
||||||
|
verify(service, times(1)).executeQueryFromFile(PsqlEntityDatabaseSchemaService.SCHEMA_ENTITIES_IDX_SQL);
|
||||||
|
verify(service, times(1)).executeQueryFromFile(PsqlEntityDatabaseSchemaService.SCHEMA_ENTITIES_IDX_PSQL_ADDON_SQL);
|
||||||
|
verify(service, times(3)).executeQueryFromFile(anyString());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenPsqlDbSchemaService_whenCreateDatabaseIndexes_thenVerifyPsqlIndexSpecificCall() throws Exception {
|
||||||
|
PsqlEntityDatabaseSchemaService service = spy(new PsqlEntityDatabaseSchemaService());
|
||||||
|
willDoNothing().given(service).executeQueryFromFile(anyString());
|
||||||
|
|
||||||
|
service.createDatabaseIndexes();
|
||||||
|
|
||||||
|
verify(service, times(1)).executeQueryFromFile(PsqlEntityDatabaseSchemaService.SCHEMA_ENTITIES_IDX_SQL);
|
||||||
|
verify(service, times(1)).executeQueryFromFile(PsqlEntityDatabaseSchemaService.SCHEMA_ENTITIES_IDX_PSQL_ADDON_SQL);
|
||||||
|
verify(service, times(2)).executeQueryFromFile(anyString());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -35,6 +35,7 @@ public class DataConstants {
|
|||||||
public static final String IS_CLEARED_ALARM = "isClearedAlarm";
|
public static final String IS_CLEARED_ALARM = "isClearedAlarm";
|
||||||
public static final String ALARM_CONDITION_REPEATS = "alarmConditionRepeats";
|
public static final String ALARM_CONDITION_REPEATS = "alarmConditionRepeats";
|
||||||
public static final String ALARM_CONDITION_DURATION = "alarmConditionDuration";
|
public static final String ALARM_CONDITION_DURATION = "alarmConditionDuration";
|
||||||
|
public static final String PERSISTENT = "persistent";
|
||||||
|
|
||||||
public static final String[] allScopes() {
|
public static final String[] allScopes() {
|
||||||
return new String[]{CLIENT_SCOPE, SHARED_SCOPE, SERVER_SCOPE};
|
return new String[]{CLIENT_SCOPE, SHARED_SCOPE, SERVER_SCOPE};
|
||||||
|
|||||||
@ -29,6 +29,8 @@ public class Lwm2mDeviceTransportConfiguration implements DeviceTransportConfigu
|
|||||||
|
|
||||||
private PowerMode powerMode;
|
private PowerMode powerMode;
|
||||||
|
|
||||||
|
private Long edrxCycle;
|
||||||
|
|
||||||
@JsonIgnore
|
@JsonIgnore
|
||||||
private Map<String, Object> properties = new HashMap<>();
|
private Map<String, Object> properties = new HashMap<>();
|
||||||
|
|
||||||
|
|||||||
@ -27,6 +27,7 @@ public class OtherConfiguration {
|
|||||||
private Integer swUpdateStrategy;
|
private Integer swUpdateStrategy;
|
||||||
private Integer clientOnlyObserveAfterConnect;
|
private Integer clientOnlyObserveAfterConnect;
|
||||||
private PowerMode powerMode;
|
private PowerMode powerMode;
|
||||||
|
private Long edrxCycle;
|
||||||
private String fwUpdateResource;
|
private String fwUpdateResource;
|
||||||
private String swUpdateResource;
|
private String swUpdateResource;
|
||||||
private boolean compositeOperationsSupport;
|
private boolean compositeOperationsSupport;
|
||||||
|
|||||||
@ -116,6 +116,7 @@ message DeviceInfoProto {
|
|||||||
int64 customerIdMSB = 10;
|
int64 customerIdMSB = 10;
|
||||||
int64 customerIdLSB = 11;
|
int64 customerIdLSB = 11;
|
||||||
string powerMode = 12;
|
string powerMode = 12;
|
||||||
|
int64 edrxCycle = 13;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -191,7 +191,7 @@ public class DefaultLwM2MAttributesService implements LwM2MAttributesService {
|
|||||||
|
|
||||||
private void pushUpdateToClientIfNeeded(LwM2mClient lwM2MClient, Object valueOld, Object newValue, String versionedId) {
|
private void pushUpdateToClientIfNeeded(LwM2mClient lwM2MClient, Object valueOld, Object newValue, String versionedId) {
|
||||||
if (newValue != null && (valueOld == null || !newValue.toString().equals(valueOld.toString()))) {
|
if (newValue != null && (valueOld == null || !newValue.toString().equals(valueOld.toString()))) {
|
||||||
TbLwM2MWriteReplaceRequest request = TbLwM2MWriteReplaceRequest.builder().versionedId(versionedId).value(newValue).timeout(this.config.getTimeout()).build();
|
TbLwM2MWriteReplaceRequest request = TbLwM2MWriteReplaceRequest.builder().versionedId(versionedId).value(newValue).timeout(clientContext.getRequestTimeout(lwM2MClient)).build();
|
||||||
downlinkHandler.sendWriteReplaceRequest(lwM2MClient, request, new TbLwM2MWriteResponseCallback(uplinkHandler, logService, lwM2MClient, versionedId));
|
downlinkHandler.sendWriteReplaceRequest(lwM2MClient, request, new TbLwM2MWriteResponseCallback(uplinkHandler, logService, lwM2MClient, versionedId));
|
||||||
} else {
|
} else {
|
||||||
log.error("Failed update resource [{}] [{}]", versionedId, newValue);
|
log.error("Failed update resource [{}] [{}]", versionedId, newValue);
|
||||||
|
|||||||
@ -93,6 +93,8 @@ public class LwM2mClient implements Serializable {
|
|||||||
@Getter
|
@Getter
|
||||||
private PowerMode powerMode;
|
private PowerMode powerMode;
|
||||||
@Getter
|
@Getter
|
||||||
|
private Long edrxCycle;
|
||||||
|
@Getter
|
||||||
@Setter
|
@Setter
|
||||||
private Registration registration;
|
private Registration registration;
|
||||||
|
|
||||||
@ -115,6 +117,7 @@ public class LwM2mClient implements Serializable {
|
|||||||
this.deviceId = new UUID(session.getDeviceIdMSB(), session.getDeviceIdLSB());
|
this.deviceId = new UUID(session.getDeviceIdMSB(), session.getDeviceIdLSB());
|
||||||
this.profileId = new UUID(session.getDeviceProfileIdMSB(), session.getDeviceProfileIdLSB());
|
this.profileId = new UUID(session.getDeviceProfileIdMSB(), session.getDeviceProfileIdLSB());
|
||||||
this.powerMode = credentials.getDeviceInfo().getPowerMode();
|
this.powerMode = credentials.getDeviceInfo().getPowerMode();
|
||||||
|
this.edrxCycle = credentials.getDeviceInfo().getEdrxCycle();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void lock() {
|
public void lock() {
|
||||||
@ -133,7 +136,9 @@ public class LwM2mClient implements Serializable {
|
|||||||
builder.setDeviceName(device.getName());
|
builder.setDeviceName(device.getName());
|
||||||
deviceProfileOpt.ifPresent(deviceProfile -> updateSession(deviceProfile, builder));
|
deviceProfileOpt.ifPresent(deviceProfile -> updateSession(deviceProfile, builder));
|
||||||
this.session = builder.build();
|
this.session = builder.build();
|
||||||
this.powerMode = ((Lwm2mDeviceTransportConfiguration) device.getDeviceData().getTransportConfiguration()).getPowerMode();
|
Lwm2mDeviceTransportConfiguration transportConfiguration = (Lwm2mDeviceTransportConfiguration) device.getDeviceData().getTransportConfiguration();
|
||||||
|
this.powerMode = transportConfiguration.getPowerMode();
|
||||||
|
this.edrxCycle = transportConfiguration.getEdrxCycle();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onDeviceProfileUpdate(DeviceProfile deviceProfile) {
|
public void onDeviceProfileUpdate(DeviceProfile deviceProfile) {
|
||||||
|
|||||||
@ -62,4 +62,6 @@ public interface LwM2mClientContext {
|
|||||||
void sendMsgsAfterSleeping(LwM2mClient lwM2MClient);
|
void sendMsgsAfterSleeping(LwM2mClient lwM2MClient);
|
||||||
|
|
||||||
boolean isComposite(LwM2mClient client);
|
boolean isComposite(LwM2mClient client);
|
||||||
|
|
||||||
|
Long getRequestTimeout(LwM2mClient client);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -26,6 +26,7 @@ import org.springframework.context.annotation.Lazy;
|
|||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.thingsboard.server.common.data.DeviceProfile;
|
import org.thingsboard.server.common.data.DeviceProfile;
|
||||||
import org.thingsboard.server.common.data.device.data.PowerMode;
|
import org.thingsboard.server.common.data.device.data.PowerMode;
|
||||||
|
import org.thingsboard.server.common.data.device.data.lwm2m.OtherConfiguration;
|
||||||
import org.thingsboard.server.common.data.device.profile.Lwm2mDeviceProfileTransportConfiguration;
|
import org.thingsboard.server.common.data.device.profile.Lwm2mDeviceProfileTransportConfiguration;
|
||||||
import org.thingsboard.server.common.data.id.DeviceProfileId;
|
import org.thingsboard.server.common.data.id.DeviceProfileId;
|
||||||
import org.thingsboard.server.common.transport.TransportDeviceProfileCache;
|
import org.thingsboard.server.common.transport.TransportDeviceProfileCache;
|
||||||
@ -346,6 +347,24 @@ public class LwM2mClientContextImpl implements LwM2mClientContext {
|
|||||||
getProfile(client.getProfileId()).getClientLwM2mSettings().isCompositeOperationsSupport();
|
getProfile(client.getProfileId()).getClientLwM2mSettings().isCompositeOperationsSupport();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Long getRequestTimeout(LwM2mClient client) {
|
||||||
|
Long timeout = null;
|
||||||
|
if (PowerMode.E_DRX.equals(client.getPowerMode()) && client.getEdrxCycle() != null) {
|
||||||
|
timeout = client.getEdrxCycle();
|
||||||
|
} else {
|
||||||
|
var clientProfile = getProfile(client.getProfileId());
|
||||||
|
OtherConfiguration clientLwM2mSettings = clientProfile.getClientLwM2mSettings();
|
||||||
|
if (PowerMode.E_DRX.equals(clientLwM2mSettings.getPowerMode())) {
|
||||||
|
timeout = clientLwM2mSettings.getEdrxCycle();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (timeout == null || timeout == 0L) {
|
||||||
|
timeout = this.config.getTimeout();
|
||||||
|
}
|
||||||
|
return timeout;
|
||||||
|
}
|
||||||
|
|
||||||
private boolean validateResourceInModel(LwM2mClient lwM2mClient, String pathIdVer, boolean isWritableNotOptional) {
|
private boolean validateResourceInModel(LwM2mClient lwM2mClient, String pathIdVer, boolean isWritableNotOptional) {
|
||||||
ResourceModel resourceModel = lwM2mClient.getResourceModel(pathIdVer, this.config
|
ResourceModel resourceModel = lwM2mClient.getResourceModel(pathIdVer, this.config
|
||||||
.getModelProvider());
|
.getModelProvider());
|
||||||
|
|||||||
@ -131,7 +131,7 @@ public class DefaultLwM2mDownlinkMsgHandler extends LwM2MExecutorAwareService im
|
|||||||
ContentFormat responseContentFormat = ContentFormat.SENML_JSON;
|
ContentFormat responseContentFormat = ContentFormat.SENML_JSON;
|
||||||
|
|
||||||
ReadCompositeRequest downlink = new ReadCompositeRequest(requestContentFormat, responseContentFormat, request.getObjectIds());
|
ReadCompositeRequest downlink = new ReadCompositeRequest(requestContentFormat, responseContentFormat, request.getObjectIds());
|
||||||
sendCompositeRequest(client, downlink, this.config.getTimeout(), callback);
|
sendCompositeRequest(client, downlink, request.getTimeout(), callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -248,7 +248,8 @@ public class DefaultLwM2mDownlinkMsgHandler extends LwM2MExecutorAwareService im
|
|||||||
ContentFormat contentFormat = ContentFormat.SENML_JSON;
|
ContentFormat contentFormat = ContentFormat.SENML_JSON;
|
||||||
try {
|
try {
|
||||||
WriteCompositeRequest downlink = new WriteCompositeRequest(contentFormat, rpcWriteCompositeRequest.getNodes());
|
WriteCompositeRequest downlink = new WriteCompositeRequest(contentFormat, rpcWriteCompositeRequest.getNodes());
|
||||||
sendWriteCompositeRequest(client, downlink, this.config.getTimeout(), callback);
|
//TODO: replace config.getTimeout();
|
||||||
|
sendWriteCompositeRequest(client, downlink, config.getTimeout(), callback);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
callback.onError(JacksonUtil.toString(rpcWriteCompositeRequest), e);
|
callback.onError(JacksonUtil.toString(rpcWriteCompositeRequest), e);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -417,7 +417,7 @@ public class DefaultLwM2MOtaUpdateService extends LwM2MExecutorAwareService impl
|
|||||||
|
|
||||||
private void startUpdateUsingUrl(LwM2mClient client, String id, String url) {
|
private void startUpdateUsingUrl(LwM2mClient client, String id, String url) {
|
||||||
String targetIdVer = convertObjectIdToVersionedId(id, client.getRegistration());
|
String targetIdVer = convertObjectIdToVersionedId(id, client.getRegistration());
|
||||||
TbLwM2MWriteReplaceRequest request = TbLwM2MWriteReplaceRequest.builder().versionedId(targetIdVer).value(url).timeout(config.getTimeout()).build();
|
TbLwM2MWriteReplaceRequest request = TbLwM2MWriteReplaceRequest.builder().versionedId(targetIdVer).value(url).timeout(clientContext.getRequestTimeout(client)).build();
|
||||||
downlinkHandler.sendWriteReplaceRequest(client, request, new TbLwM2MWriteResponseCallback(uplinkHandler, logService, client, targetIdVer));
|
downlinkHandler.sendWriteReplaceRequest(client, request, new TbLwM2MWriteResponseCallback(uplinkHandler, logService, client, targetIdVer));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -486,7 +486,7 @@ public class DefaultLwM2MOtaUpdateService extends LwM2MExecutorAwareService impl
|
|||||||
byte[] firmwareChunk = otaPackageDataCache.get(otaPackageId.toString(), 0, 0);
|
byte[] firmwareChunk = otaPackageDataCache.get(otaPackageId.toString(), 0, 0);
|
||||||
TbLwM2MWriteReplaceRequest writeRequest = TbLwM2MWriteReplaceRequest.builder().versionedId(versionedId)
|
TbLwM2MWriteReplaceRequest writeRequest = TbLwM2MWriteReplaceRequest.builder().versionedId(versionedId)
|
||||||
.value(firmwareChunk).contentFormat(ContentFormat.OPAQUE)
|
.value(firmwareChunk).contentFormat(ContentFormat.OPAQUE)
|
||||||
.timeout(config.getTimeout()).build();
|
.timeout(clientContext.getRequestTimeout(client)).build();
|
||||||
downlinkHandler.sendWriteReplaceRequest(client, writeRequest, new TbLwM2MWriteResponseCallback(uplinkHandler, logService, client, versionedId));
|
downlinkHandler.sendWriteReplaceRequest(client, writeRequest, new TbLwM2MWriteResponseCallback(uplinkHandler, logService, client, versionedId));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -501,17 +501,17 @@ public class DefaultLwM2MOtaUpdateService extends LwM2MExecutorAwareService impl
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void executeFwUpdate(LwM2mClient client) {
|
private void executeFwUpdate(LwM2mClient client) {
|
||||||
TbLwM2MExecuteRequest request = TbLwM2MExecuteRequest.builder().versionedId(FW_EXECUTE_ID).timeout(config.getTimeout()).build();
|
TbLwM2MExecuteRequest request = TbLwM2MExecuteRequest.builder().versionedId(FW_EXECUTE_ID).timeout(clientContext.getRequestTimeout(client)).build();
|
||||||
downlinkHandler.sendExecuteRequest(client, request, new TbLwM2MExecuteCallback(logService, client, FW_EXECUTE_ID));
|
downlinkHandler.sendExecuteRequest(client, request, new TbLwM2MExecuteCallback(logService, client, FW_EXECUTE_ID));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void executeSwInstall(LwM2mClient client) {
|
private void executeSwInstall(LwM2mClient client) {
|
||||||
TbLwM2MExecuteRequest request = TbLwM2MExecuteRequest.builder().versionedId(SW_INSTALL_ID).timeout(config.getTimeout()).build();
|
TbLwM2MExecuteRequest request = TbLwM2MExecuteRequest.builder().versionedId(SW_INSTALL_ID).timeout(clientContext.getRequestTimeout(client)).build();
|
||||||
downlinkHandler.sendExecuteRequest(client, request, new TbLwM2MExecuteCallback(logService, client, SW_INSTALL_ID));
|
downlinkHandler.sendExecuteRequest(client, request, new TbLwM2MExecuteCallback(logService, client, SW_INSTALL_ID));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void executeSwUninstallForUpdate(LwM2mClient client) {
|
private void executeSwUninstallForUpdate(LwM2mClient client) {
|
||||||
TbLwM2MExecuteRequest request = TbLwM2MExecuteRequest.builder().versionedId(SW_UN_INSTALL_ID).params("1").timeout(config.getTimeout()).build();
|
TbLwM2MExecuteRequest request = TbLwM2MExecuteRequest.builder().versionedId(SW_UN_INSTALL_ID).params("1").timeout(clientContext.getRequestTimeout(client)).build();
|
||||||
downlinkHandler.sendExecuteRequest(client, request, new TbLwM2MExecuteCallback(logService, client, SW_INSTALL_ID));
|
downlinkHandler.sendExecuteRequest(client, request, new TbLwM2MExecuteCallback(logService, client, SW_INSTALL_ID));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -171,7 +171,7 @@ public class DefaultLwM2MRpcRequestHandler implements LwM2MRpcRequestHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void sendReadRequest(LwM2mClient client, TransportProtos.ToDeviceRpcRequestMsg requestMsg, String versionedId) {
|
private void sendReadRequest(LwM2mClient client, TransportProtos.ToDeviceRpcRequestMsg requestMsg, String versionedId) {
|
||||||
TbLwM2MReadRequest request = TbLwM2MReadRequest.builder().versionedId(versionedId).timeout(this.config.getTimeout()).build();
|
TbLwM2MReadRequest request = TbLwM2MReadRequest.builder().versionedId(versionedId).timeout(clientContext.getRequestTimeout(client)).build();
|
||||||
var mainCallback = new TbLwM2MReadCallback(uplinkHandler, logService, client, versionedId);
|
var mainCallback = new TbLwM2MReadCallback(uplinkHandler, logService, client, versionedId);
|
||||||
var rpcCallback = new RpcReadResponseCallback<>(transportService, client, requestMsg, mainCallback);
|
var rpcCallback = new RpcReadResponseCallback<>(transportService, client, requestMsg, mainCallback);
|
||||||
downlinkHandler.sendReadRequest(client, request, rpcCallback);
|
downlinkHandler.sendReadRequest(client, request, rpcCallback);
|
||||||
@ -179,38 +179,38 @@ public class DefaultLwM2MRpcRequestHandler implements LwM2MRpcRequestHandler {
|
|||||||
|
|
||||||
private void sendReadCompositeRequest(LwM2mClient client, TransportProtos.ToDeviceRpcRequestMsg requestMsg) {
|
private void sendReadCompositeRequest(LwM2mClient client, TransportProtos.ToDeviceRpcRequestMsg requestMsg) {
|
||||||
String[] versionedIds = getIdsFromParameters(client, requestMsg);
|
String[] versionedIds = getIdsFromParameters(client, requestMsg);
|
||||||
TbLwM2MReadCompositeRequest request = TbLwM2MReadCompositeRequest.builder().versionedIds(versionedIds).timeout(this.config.getTimeout()).build();
|
TbLwM2MReadCompositeRequest request = TbLwM2MReadCompositeRequest.builder().versionedIds(versionedIds).timeout(clientContext.getRequestTimeout(client)).build();
|
||||||
var mainCallback = new TbLwM2MReadCompositeCallback(uplinkHandler, logService, client, versionedIds);
|
var mainCallback = new TbLwM2MReadCompositeCallback(uplinkHandler, logService, client, versionedIds);
|
||||||
var rpcCallback = new RpcReadResponseCompositeCallback(transportService, client, requestMsg, mainCallback);
|
var rpcCallback = new RpcReadResponseCompositeCallback(transportService, client, requestMsg, mainCallback);
|
||||||
downlinkHandler.sendReadCompositeRequest(client, request, rpcCallback);
|
downlinkHandler.sendReadCompositeRequest(client, request, rpcCallback);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void sendObserveRequest(LwM2mClient client, TransportProtos.ToDeviceRpcRequestMsg requestMsg, String versionedId) {
|
private void sendObserveRequest(LwM2mClient client, TransportProtos.ToDeviceRpcRequestMsg requestMsg, String versionedId) {
|
||||||
TbLwM2MObserveRequest request = TbLwM2MObserveRequest.builder().versionedId(versionedId).timeout(this.config.getTimeout()).build();
|
TbLwM2MObserveRequest request = TbLwM2MObserveRequest.builder().versionedId(versionedId).timeout(clientContext.getRequestTimeout(client)).build();
|
||||||
var mainCallback = new TbLwM2MObserveCallback(uplinkHandler, logService, client, versionedId);
|
var mainCallback = new TbLwM2MObserveCallback(uplinkHandler, logService, client, versionedId);
|
||||||
var rpcCallback = new RpcReadResponseCallback<>(transportService, client, requestMsg, mainCallback);
|
var rpcCallback = new RpcReadResponseCallback<>(transportService, client, requestMsg, mainCallback);
|
||||||
downlinkHandler.sendObserveRequest(client, request, rpcCallback);
|
downlinkHandler.sendObserveRequest(client, request, rpcCallback);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void sendObserveAllRequest(LwM2mClient client, TransportProtos.ToDeviceRpcRequestMsg requestMsg) {
|
private void sendObserveAllRequest(LwM2mClient client, TransportProtos.ToDeviceRpcRequestMsg requestMsg) {
|
||||||
TbLwM2MObserveAllRequest request = TbLwM2MObserveAllRequest.builder().timeout(this.config.getTimeout()).build();
|
TbLwM2MObserveAllRequest request = TbLwM2MObserveAllRequest.builder().timeout(clientContext.getRequestTimeout(client)).build();
|
||||||
downlinkHandler.sendObserveAllRequest(client, request, new RpcLinkSetCallback<>(transportService, client, requestMsg, null));
|
downlinkHandler.sendObserveAllRequest(client, request, new RpcLinkSetCallback<>(transportService, client, requestMsg, null));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void sendDiscoverAllRequest(LwM2mClient client, TransportProtos.ToDeviceRpcRequestMsg requestMsg) {
|
private void sendDiscoverAllRequest(LwM2mClient client, TransportProtos.ToDeviceRpcRequestMsg requestMsg) {
|
||||||
TbLwM2MDiscoverAllRequest request = TbLwM2MDiscoverAllRequest.builder().timeout(this.config.getTimeout()).build();
|
TbLwM2MDiscoverAllRequest request = TbLwM2MDiscoverAllRequest.builder().timeout(clientContext.getRequestTimeout(client)).build();
|
||||||
downlinkHandler.sendDiscoverAllRequest(client, request, new RpcLinkSetCallback<>(transportService, client, requestMsg, null));
|
downlinkHandler.sendDiscoverAllRequest(client, request, new RpcLinkSetCallback<>(transportService, client, requestMsg, null));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void sendDiscoverRequest(LwM2mClient client, TransportProtos.ToDeviceRpcRequestMsg requestMsg, String versionedId) {
|
private void sendDiscoverRequest(LwM2mClient client, TransportProtos.ToDeviceRpcRequestMsg requestMsg, String versionedId) {
|
||||||
TbLwM2MDiscoverRequest request = TbLwM2MDiscoverRequest.builder().versionedId(versionedId).timeout(this.config.getTimeout()).build();
|
TbLwM2MDiscoverRequest request = TbLwM2MDiscoverRequest.builder().versionedId(versionedId).timeout(clientContext.getRequestTimeout(client)).build();
|
||||||
var mainCallback = new TbLwM2MDiscoverCallback(logService, client, versionedId);
|
var mainCallback = new TbLwM2MDiscoverCallback(logService, client, versionedId);
|
||||||
var rpcCallback = new RpcDiscoverCallback(transportService, client, requestMsg, mainCallback);
|
var rpcCallback = new RpcDiscoverCallback(transportService, client, requestMsg, mainCallback);
|
||||||
downlinkHandler.sendDiscoverRequest(client, request, rpcCallback);
|
downlinkHandler.sendDiscoverRequest(client, request, rpcCallback);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void sendExecuteRequest(LwM2mClient client, TransportProtos.ToDeviceRpcRequestMsg requestMsg, String versionedId) {
|
private void sendExecuteRequest(LwM2mClient client, TransportProtos.ToDeviceRpcRequestMsg requestMsg, String versionedId) {
|
||||||
TbLwM2MExecuteRequest downlink = TbLwM2MExecuteRequest.builder().versionedId(versionedId).timeout(this.config.getTimeout()).build();
|
TbLwM2MExecuteRequest downlink = TbLwM2MExecuteRequest.builder().versionedId(versionedId).timeout(clientContext.getRequestTimeout(client)).build();
|
||||||
var mainCallback = new TbLwM2MExecuteCallback(logService, client, versionedId);
|
var mainCallback = new TbLwM2MExecuteCallback(logService, client, versionedId);
|
||||||
var rpcCallback = new RpcEmptyResponseCallback<>(transportService, client, requestMsg, mainCallback);
|
var rpcCallback = new RpcEmptyResponseCallback<>(transportService, client, requestMsg, mainCallback);
|
||||||
downlinkHandler.sendExecuteRequest(client, downlink, rpcCallback);
|
downlinkHandler.sendExecuteRequest(client, downlink, rpcCallback);
|
||||||
@ -220,7 +220,7 @@ public class DefaultLwM2MRpcRequestHandler implements LwM2MRpcRequestHandler {
|
|||||||
RpcWriteAttributesRequest requestBody = JacksonUtil.fromString(requestMsg.getParams(), RpcWriteAttributesRequest.class);
|
RpcWriteAttributesRequest requestBody = JacksonUtil.fromString(requestMsg.getParams(), RpcWriteAttributesRequest.class);
|
||||||
TbLwM2MWriteAttributesRequest request = TbLwM2MWriteAttributesRequest.builder().versionedId(versionedId)
|
TbLwM2MWriteAttributesRequest request = TbLwM2MWriteAttributesRequest.builder().versionedId(versionedId)
|
||||||
.attributes(requestBody.getAttributes())
|
.attributes(requestBody.getAttributes())
|
||||||
.timeout(this.config.getTimeout()).build();
|
.timeout(clientContext.getRequestTimeout(client)).build();
|
||||||
var mainCallback = new TbLwM2MWriteAttributesCallback(logService, client, versionedId);
|
var mainCallback = new TbLwM2MWriteAttributesCallback(logService, client, versionedId);
|
||||||
var rpcCallback = new RpcEmptyResponseCallback<>(transportService, client, requestMsg, mainCallback);
|
var rpcCallback = new RpcEmptyResponseCallback<>(transportService, client, requestMsg, mainCallback);
|
||||||
downlinkHandler.sendWriteAttributesRequest(client, request, rpcCallback);
|
downlinkHandler.sendWriteAttributesRequest(client, request, rpcCallback);
|
||||||
@ -229,7 +229,7 @@ public class DefaultLwM2MRpcRequestHandler implements LwM2MRpcRequestHandler {
|
|||||||
private void sendWriteUpdateRequest(LwM2mClient client, TransportProtos.ToDeviceRpcRequestMsg requestMsg, String versionedId) {
|
private void sendWriteUpdateRequest(LwM2mClient client, TransportProtos.ToDeviceRpcRequestMsg requestMsg, String versionedId) {
|
||||||
RpcWriteUpdateRequest requestBody = JacksonUtil.fromString(requestMsg.getParams(), RpcWriteUpdateRequest.class);
|
RpcWriteUpdateRequest requestBody = JacksonUtil.fromString(requestMsg.getParams(), RpcWriteUpdateRequest.class);
|
||||||
TbLwM2MWriteUpdateRequest.TbLwM2MWriteUpdateRequestBuilder builder = TbLwM2MWriteUpdateRequest.builder().versionedId(versionedId);
|
TbLwM2MWriteUpdateRequest.TbLwM2MWriteUpdateRequestBuilder builder = TbLwM2MWriteUpdateRequest.builder().versionedId(versionedId);
|
||||||
builder.value(requestBody.getValue()).timeout(this.config.getTimeout());
|
builder.value(requestBody.getValue()).timeout(clientContext.getRequestTimeout(client));
|
||||||
var mainCallback = new TbLwM2MWriteResponseCallback(uplinkHandler, logService, client, versionedId);
|
var mainCallback = new TbLwM2MWriteResponseCallback(uplinkHandler, logService, client, versionedId);
|
||||||
var rpcCallback = new RpcEmptyResponseCallback<>(transportService, client, requestMsg, mainCallback);
|
var rpcCallback = new RpcEmptyResponseCallback<>(transportService, client, requestMsg, mainCallback);
|
||||||
downlinkHandler.sendWriteUpdateRequest(client, builder.build(), rpcCallback);
|
downlinkHandler.sendWriteUpdateRequest(client, builder.build(), rpcCallback);
|
||||||
@ -239,7 +239,7 @@ public class DefaultLwM2MRpcRequestHandler implements LwM2MRpcRequestHandler {
|
|||||||
RpcWriteReplaceRequest requestBody = JacksonUtil.fromString(requestMsg.getParams(), RpcWriteReplaceRequest.class);
|
RpcWriteReplaceRequest requestBody = JacksonUtil.fromString(requestMsg.getParams(), RpcWriteReplaceRequest.class);
|
||||||
TbLwM2MWriteReplaceRequest request = TbLwM2MWriteReplaceRequest.builder().versionedId(versionedId)
|
TbLwM2MWriteReplaceRequest request = TbLwM2MWriteReplaceRequest.builder().versionedId(versionedId)
|
||||||
.value(requestBody.getValue())
|
.value(requestBody.getValue())
|
||||||
.timeout(this.config.getTimeout()).build();
|
.timeout(clientContext.getRequestTimeout(client)).build();
|
||||||
var mainCallback = new TbLwM2MWriteResponseCallback(uplinkHandler, logService, client, versionedId);
|
var mainCallback = new TbLwM2MWriteResponseCallback(uplinkHandler, logService, client, versionedId);
|
||||||
var rpcCallback = new RpcEmptyResponseCallback<>(transportService, client, requestMsg, mainCallback);
|
var rpcCallback = new RpcEmptyResponseCallback<>(transportService, client, requestMsg, mainCallback);
|
||||||
downlinkHandler.sendWriteReplaceRequest(client, request, rpcCallback);
|
downlinkHandler.sendWriteReplaceRequest(client, request, rpcCallback);
|
||||||
@ -261,21 +261,21 @@ public class DefaultLwM2MRpcRequestHandler implements LwM2MRpcRequestHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void sendCancelObserveRequest(LwM2mClient client, TransportProtos.ToDeviceRpcRequestMsg requestMsg, String versionedId) {
|
private void sendCancelObserveRequest(LwM2mClient client, TransportProtos.ToDeviceRpcRequestMsg requestMsg, String versionedId) {
|
||||||
TbLwM2MCancelObserveRequest downlink = TbLwM2MCancelObserveRequest.builder().versionedId(versionedId).timeout(this.config.getTimeout()).build();
|
TbLwM2MCancelObserveRequest downlink = TbLwM2MCancelObserveRequest.builder().versionedId(versionedId).timeout(clientContext.getRequestTimeout(client)).build();
|
||||||
var mainCallback = new TbLwM2MCancelObserveCallback(logService, client, versionedId);
|
var mainCallback = new TbLwM2MCancelObserveCallback(logService, client, versionedId);
|
||||||
var rpcCallback = new RpcCancelObserveCallback(transportService, client, requestMsg, mainCallback);
|
var rpcCallback = new RpcCancelObserveCallback(transportService, client, requestMsg, mainCallback);
|
||||||
downlinkHandler.sendCancelObserveRequest(client, downlink, rpcCallback);
|
downlinkHandler.sendCancelObserveRequest(client, downlink, rpcCallback);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void sendDeleteRequest(LwM2mClient client, TransportProtos.ToDeviceRpcRequestMsg requestMsg, String versionedId) {
|
private void sendDeleteRequest(LwM2mClient client, TransportProtos.ToDeviceRpcRequestMsg requestMsg, String versionedId) {
|
||||||
TbLwM2MDeleteRequest downlink = TbLwM2MDeleteRequest.builder().versionedId(versionedId).timeout(this.config.getTimeout()).build();
|
TbLwM2MDeleteRequest downlink = TbLwM2MDeleteRequest.builder().versionedId(versionedId).timeout(clientContext.getRequestTimeout(client)).build();
|
||||||
var mainCallback = new TbLwM2MDeleteCallback(logService, client, versionedId);
|
var mainCallback = new TbLwM2MDeleteCallback(logService, client, versionedId);
|
||||||
var rpcCallback = new RpcEmptyResponseCallback<>(transportService, client, requestMsg, mainCallback);
|
var rpcCallback = new RpcEmptyResponseCallback<>(transportService, client, requestMsg, mainCallback);
|
||||||
downlinkHandler.sendDeleteRequest(client, downlink, rpcCallback);
|
downlinkHandler.sendDeleteRequest(client, downlink, rpcCallback);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void sendCancelAllObserveRequest(LwM2mClient client, TransportProtos.ToDeviceRpcRequestMsg requestMsg) {
|
private void sendCancelAllObserveRequest(LwM2mClient client, TransportProtos.ToDeviceRpcRequestMsg requestMsg) {
|
||||||
TbLwM2MCancelAllRequest downlink = TbLwM2MCancelAllRequest.builder().timeout(this.config.getTimeout()).build();
|
TbLwM2MCancelAllRequest downlink = TbLwM2MCancelAllRequest.builder().timeout(clientContext.getRequestTimeout(client)).build();
|
||||||
var mainCallback = new TbLwM2MCancelAllObserveCallback(logService, client);
|
var mainCallback = new TbLwM2MCancelAllObserveCallback(logService, client);
|
||||||
var rpcCallback = new RpcCancelAllObserveCallback(transportService, client, requestMsg, mainCallback);
|
var rpcCallback = new RpcCancelAllObserveCallback(transportService, client, requestMsg, mainCallback);
|
||||||
downlinkHandler.sendCancelAllRequest(client, downlink, rpcCallback);
|
downlinkHandler.sendCancelAllRequest(client, downlink, rpcCallback);
|
||||||
|
|||||||
@ -457,7 +457,7 @@ public class DefaultLwM2MUplinkMsgHandler extends LwM2MExecutorAwareService impl
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void sendDiscoverRequest(LwM2mClient lwM2MClient, String targetId) {
|
private void sendDiscoverRequest(LwM2mClient lwM2MClient, String targetId) {
|
||||||
TbLwM2MDiscoverRequest request = TbLwM2MDiscoverRequest.builder().versionedId(targetId).timeout(this.config.getTimeout()).build();
|
TbLwM2MDiscoverRequest request = TbLwM2MDiscoverRequest.builder().versionedId(targetId).timeout(clientContext.getRequestTimeout(lwM2MClient)).build();
|
||||||
defaultLwM2MDownlinkMsgHandler.sendDiscoverRequest(lwM2MClient, request, new TbLwM2MDiscoverCallback(logService, lwM2MClient, targetId));
|
defaultLwM2MDownlinkMsgHandler.sendDiscoverRequest(lwM2MClient, request, new TbLwM2MDiscoverCallback(logService, lwM2MClient, targetId));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -466,7 +466,7 @@ public class DefaultLwM2MUplinkMsgHandler extends LwM2MExecutorAwareService impl
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void sendReadRequest(LwM2mClient lwM2MClient, String versionedId, DownlinkRequestCallback<ReadRequest, ReadResponse> callback) {
|
private void sendReadRequest(LwM2mClient lwM2MClient, String versionedId, DownlinkRequestCallback<ReadRequest, ReadResponse> callback) {
|
||||||
TbLwM2MReadRequest request = TbLwM2MReadRequest.builder().versionedId(versionedId).timeout(this.config.getTimeout()).build();
|
TbLwM2MReadRequest request = TbLwM2MReadRequest.builder().versionedId(versionedId).timeout(clientContext.getRequestTimeout(lwM2MClient)).build();
|
||||||
defaultLwM2MDownlinkMsgHandler.sendReadRequest(lwM2MClient, request, callback);
|
defaultLwM2MDownlinkMsgHandler.sendReadRequest(lwM2MClient, request, callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -475,17 +475,17 @@ public class DefaultLwM2MUplinkMsgHandler extends LwM2MExecutorAwareService impl
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void sendObserveRequest(LwM2mClient lwM2MClient, String versionedId, DownlinkRequestCallback<ObserveRequest, ObserveResponse> callback) {
|
private void sendObserveRequest(LwM2mClient lwM2MClient, String versionedId, DownlinkRequestCallback<ObserveRequest, ObserveResponse> callback) {
|
||||||
TbLwM2MObserveRequest request = TbLwM2MObserveRequest.builder().versionedId(versionedId).timeout(this.config.getTimeout()).build();
|
TbLwM2MObserveRequest request = TbLwM2MObserveRequest.builder().versionedId(versionedId).timeout(clientContext.getRequestTimeout(lwM2MClient)).build();
|
||||||
defaultLwM2MDownlinkMsgHandler.sendObserveRequest(lwM2MClient, request, callback);
|
defaultLwM2MDownlinkMsgHandler.sendObserveRequest(lwM2MClient, request, callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void sendWriteAttributesRequest(LwM2mClient lwM2MClient, String targetId, ObjectAttributes params) {
|
private void sendWriteAttributesRequest(LwM2mClient lwM2MClient, String targetId, ObjectAttributes params) {
|
||||||
TbLwM2MWriteAttributesRequest request = TbLwM2MWriteAttributesRequest.builder().versionedId(targetId).attributes(params).timeout(this.config.getTimeout()).build();
|
TbLwM2MWriteAttributesRequest request = TbLwM2MWriteAttributesRequest.builder().versionedId(targetId).attributes(params).timeout(clientContext.getRequestTimeout(lwM2MClient)).build();
|
||||||
defaultLwM2MDownlinkMsgHandler.sendWriteAttributesRequest(lwM2MClient, request, new TbLwM2MWriteAttributesCallback(logService, lwM2MClient, targetId));
|
defaultLwM2MDownlinkMsgHandler.sendWriteAttributesRequest(lwM2MClient, request, new TbLwM2MWriteAttributesCallback(logService, lwM2MClient, targetId));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void sendCancelObserveRequest(String versionedId, LwM2mClient client) {
|
private void sendCancelObserveRequest(String versionedId, LwM2mClient client) {
|
||||||
TbLwM2MCancelObserveRequest request = TbLwM2MCancelObserveRequest.builder().versionedId(versionedId).timeout(this.config.getTimeout()).build();
|
TbLwM2MCancelObserveRequest request = TbLwM2MCancelObserveRequest.builder().versionedId(versionedId).timeout(clientContext.getRequestTimeout(client)).build();
|
||||||
defaultLwM2MDownlinkMsgHandler.sendCancelObserveRequest(client, request, new TbLwM2MCancelObserveCallback(logService, client, versionedId));
|
defaultLwM2MDownlinkMsgHandler.sendCancelObserveRequest(client, request, new TbLwM2MCancelObserveCallback(logService, client, versionedId));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -35,5 +35,5 @@ public class TransportDeviceInfo implements Serializable {
|
|||||||
private String deviceType;
|
private String deviceType;
|
||||||
private PowerMode powerMode;
|
private PowerMode powerMode;
|
||||||
private String additionalInfo;
|
private String additionalInfo;
|
||||||
|
private Long edrxCycle;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -443,6 +443,7 @@ public class DefaultTransportService implements TransportService {
|
|||||||
tdi.setDeviceType(di.getDeviceType());
|
tdi.setDeviceType(di.getDeviceType());
|
||||||
if (StringUtils.isNotEmpty(di.getPowerMode())) {
|
if (StringUtils.isNotEmpty(di.getPowerMode())) {
|
||||||
tdi.setPowerMode(PowerMode.valueOf(di.getPowerMode()));
|
tdi.setPowerMode(PowerMode.valueOf(di.getPowerMode()));
|
||||||
|
tdi.setEdrxCycle(di.getEdrxCycle());
|
||||||
}
|
}
|
||||||
return tdi;
|
return tdi;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,38 @@
|
|||||||
|
--
|
||||||
|
-- Copyright © 2016-2021 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.
|
||||||
|
--
|
||||||
|
|
||||||
|
-- This file describes PostgreSQL-specific indexes that not supported by hsql
|
||||||
|
-- It is not a stand-alone file! Run schema-entities-idx.sql before!
|
||||||
|
-- Note: Hibernate DESC order translates to native SQL "ORDER BY .. DESC NULLS LAST"
|
||||||
|
-- While creating index PostgreSQL transforms short notation (ts DESC) to the full (DESC NULLS FIRST)
|
||||||
|
-- That difference between NULLS LAST and NULLS FIRST prevents to hit index while querying latest by ts
|
||||||
|
-- That why we need to define DESC index explicitly as (ts DESC NULLS LAST)
|
||||||
|
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_event_ts
|
||||||
|
ON public.event
|
||||||
|
(ts DESC NULLS LAST)
|
||||||
|
WITH (FILLFACTOR=95);
|
||||||
|
|
||||||
|
COMMENT ON INDEX public.idx_event_ts
|
||||||
|
IS 'This index helps to delete events by TTL using timestamp';
|
||||||
|
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_event_tenant_entity_type_entity_event_type_created_time_des
|
||||||
|
ON public.event
|
||||||
|
(tenant_id ASC, entity_type ASC, entity_id ASC, event_type ASC, created_time DESC NULLS LAST)
|
||||||
|
WITH (FILLFACTOR=95);
|
||||||
|
|
||||||
|
COMMENT ON INDEX public.idx_event_tenant_entity_type_entity_event_type_created_time_des
|
||||||
|
IS 'This index helps to open latest events on UI fast';
|
||||||
@ -45,19 +45,3 @@ CREATE INDEX IF NOT EXISTS idx_attribute_kv_by_key_and_last_update_ts ON attribu
|
|||||||
CREATE INDEX IF NOT EXISTS idx_audit_log_tenant_id_and_created_time ON audit_log(tenant_id, created_time);
|
CREATE INDEX IF NOT EXISTS idx_audit_log_tenant_id_and_created_time ON audit_log(tenant_id, created_time);
|
||||||
|
|
||||||
CREATE INDEX IF NOT EXISTS idx_rpc_tenant_id_device_id ON rpc(tenant_id, device_id);
|
CREATE INDEX IF NOT EXISTS idx_rpc_tenant_id_device_id ON rpc(tenant_id, device_id);
|
||||||
|
|
||||||
CREATE INDEX IF NOT EXISTS idx_event_ts
|
|
||||||
ON public.event USING btree
|
|
||||||
(ts DESC NULLS LAST)
|
|
||||||
WITH (FILLFACTOR=95);
|
|
||||||
|
|
||||||
COMMENT ON INDEX public.idx_event_ts
|
|
||||||
IS 'This index helps to delete events by TTL using timestamp';
|
|
||||||
|
|
||||||
CREATE INDEX IF NOT EXISTS idx_event_tenant_entity_type_entity_event_type_created_time_des
|
|
||||||
ON public.event USING btree
|
|
||||||
(tenant_id ASC NULLS LAST, entity_type ASC NULLS LAST, entity_id ASC NULLS LAST, event_type ASC NULLS LAST, created_time DESC NULLS LAST)
|
|
||||||
WITH (FILLFACTOR=95);
|
|
||||||
|
|
||||||
COMMENT ON INDEX public.idx_event_tenant_entity_type_entity_event_type_created_time_des
|
|
||||||
IS 'This index helps to open latest events on UI fast';
|
|
||||||
2
pom.xml
2
pom.xml
@ -99,7 +99,7 @@
|
|||||||
</sonar.exclusions>
|
</sonar.exclusions>
|
||||||
<elasticsearch.version>5.0.2</elasticsearch.version>
|
<elasticsearch.version>5.0.2</elasticsearch.version>
|
||||||
<delight-nashorn-sandbox.version>0.1.16</delight-nashorn-sandbox.version>
|
<delight-nashorn-sandbox.version>0.1.16</delight-nashorn-sandbox.version>
|
||||||
<kafka.version>2.6.0</kafka.version>
|
<kafka.version>2.8.0</kafka.version>
|
||||||
<bucket4j.version>4.1.1</bucket4j.version>
|
<bucket4j.version>4.1.1</bucket4j.version>
|
||||||
<fst.version>2.57</fst.version>
|
<fst.version>2.57</fst.version>
|
||||||
<antlr.version>2.7.7</antlr.version>
|
<antlr.version>2.7.7</antlr.version>
|
||||||
|
|||||||
@ -46,9 +46,9 @@ public interface MailService {
|
|||||||
|
|
||||||
void sendAccountLockoutEmail(String lockoutEmail, String email, Integer maxFailedLoginAttempts) throws ThingsboardException;
|
void sendAccountLockoutEmail(String lockoutEmail, String email, Integer maxFailedLoginAttempts) throws ThingsboardException;
|
||||||
|
|
||||||
void send(TenantId tenantId, CustomerId customerId, String from, String to, String cc, String bcc, String subject, String body, boolean isHtml, Map<String, String> images) throws ThingsboardException;
|
void send(TenantId tenantId, CustomerId customerId, TbEmail tbEmail) throws ThingsboardException;
|
||||||
|
|
||||||
void send(TenantId tenantId, CustomerId customerId, String from, String to, String cc, String bcc, String subject, String body, boolean isHtml, Map<String, String> images, JavaMailSender javaMailSender) throws ThingsboardException;
|
void send(TenantId tenantId, CustomerId customerId, TbEmail tbEmail, JavaMailSender javaMailSender) throws ThingsboardException;
|
||||||
|
|
||||||
void sendApiFeatureStateEmail(ApiFeature apiFeature, ApiUsageStateValue stateValue, String email, ApiUsageStateMailMessage msg) throws ThingsboardException;
|
void sendApiFeatureStateEmail(ApiFeature apiFeature, ApiUsageStateValue stateValue, String email, ApiUsageStateMailMessage msg) throws ThingsboardException;
|
||||||
|
|
||||||
|
|||||||
@ -13,7 +13,7 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.thingsboard.rule.engine.mail;
|
package org.thingsboard.rule.engine.api;
|
||||||
|
|
||||||
import lombok.Builder;
|
import lombok.Builder;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
@ -22,7 +22,7 @@ import java.util.Map;
|
|||||||
|
|
||||||
@Data
|
@Data
|
||||||
@Builder
|
@Builder
|
||||||
class EmailPojo {
|
public class TbEmail {
|
||||||
|
|
||||||
private final String from;
|
private final String from;
|
||||||
private final String to;
|
private final String to;
|
||||||
@ -22,6 +22,7 @@ import lombok.extern.slf4j.Slf4j;
|
|||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
import org.thingsboard.rule.engine.api.RuleNode;
|
import org.thingsboard.rule.engine.api.RuleNode;
|
||||||
import org.thingsboard.rule.engine.api.TbContext;
|
import org.thingsboard.rule.engine.api.TbContext;
|
||||||
|
import org.thingsboard.rule.engine.api.TbEmail;
|
||||||
import org.thingsboard.rule.engine.api.TbNode;
|
import org.thingsboard.rule.engine.api.TbNode;
|
||||||
import org.thingsboard.rule.engine.api.TbNodeConfiguration;
|
import org.thingsboard.rule.engine.api.TbNodeConfiguration;
|
||||||
import org.thingsboard.rule.engine.api.TbNodeException;
|
import org.thingsboard.rule.engine.api.TbNodeException;
|
||||||
@ -65,7 +66,7 @@ public class TbMsgToEmailNode implements TbNode {
|
|||||||
@Override
|
@Override
|
||||||
public void onMsg(TbContext ctx, TbMsg msg) {
|
public void onMsg(TbContext ctx, TbMsg msg) {
|
||||||
try {
|
try {
|
||||||
EmailPojo email = convert(msg);
|
TbEmail email = convert(msg);
|
||||||
TbMsg emailMsg = buildEmailMsg(ctx, msg, email);
|
TbMsg emailMsg = buildEmailMsg(ctx, msg, email);
|
||||||
ctx.tellNext(emailMsg, SUCCESS);
|
ctx.tellNext(emailMsg, SUCCESS);
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
@ -74,13 +75,13 @@ public class TbMsgToEmailNode implements TbNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private TbMsg buildEmailMsg(TbContext ctx, TbMsg msg, EmailPojo email) throws JsonProcessingException {
|
private TbMsg buildEmailMsg(TbContext ctx, TbMsg msg, TbEmail email) throws JsonProcessingException {
|
||||||
String emailJson = MAPPER.writeValueAsString(email);
|
String emailJson = MAPPER.writeValueAsString(email);
|
||||||
return ctx.transformMsg(msg, SEND_EMAIL_TYPE, msg.getOriginator(), msg.getMetaData().copy(), emailJson);
|
return ctx.transformMsg(msg, SEND_EMAIL_TYPE, msg.getOriginator(), msg.getMetaData().copy(), emailJson);
|
||||||
}
|
}
|
||||||
|
|
||||||
private EmailPojo convert(TbMsg msg) throws IOException {
|
private TbEmail convert(TbMsg msg) throws IOException {
|
||||||
EmailPojo.EmailPojoBuilder builder = EmailPojo.builder();
|
TbEmail.TbEmailBuilder builder = TbEmail.builder();
|
||||||
builder.from(fromTemplate(this.config.getFromTemplate(), msg));
|
builder.from(fromTemplate(this.config.getFromTemplate(), msg));
|
||||||
builder.to(fromTemplate(this.config.getToTemplate(), msg));
|
builder.to(fromTemplate(this.config.getToTemplate(), msg));
|
||||||
builder.cc(fromTemplate(this.config.getCcTemplate(), msg));
|
builder.cc(fromTemplate(this.config.getCcTemplate(), msg));
|
||||||
|
|||||||
@ -21,6 +21,7 @@ import org.apache.commons.lang3.StringUtils;
|
|||||||
import org.springframework.mail.javamail.JavaMailSenderImpl;
|
import org.springframework.mail.javamail.JavaMailSenderImpl;
|
||||||
import org.thingsboard.rule.engine.api.RuleNode;
|
import org.thingsboard.rule.engine.api.RuleNode;
|
||||||
import org.thingsboard.rule.engine.api.TbContext;
|
import org.thingsboard.rule.engine.api.TbContext;
|
||||||
|
import org.thingsboard.rule.engine.api.TbEmail;
|
||||||
import org.thingsboard.rule.engine.api.TbNode;
|
import org.thingsboard.rule.engine.api.TbNode;
|
||||||
import org.thingsboard.rule.engine.api.TbNodeConfiguration;
|
import org.thingsboard.rule.engine.api.TbNodeConfiguration;
|
||||||
import org.thingsboard.rule.engine.api.TbNodeException;
|
import org.thingsboard.rule.engine.api.TbNodeException;
|
||||||
@ -71,7 +72,7 @@ public class TbSendEmailNode implements TbNode {
|
|||||||
public void onMsg(TbContext ctx, TbMsg msg) {
|
public void onMsg(TbContext ctx, TbMsg msg) {
|
||||||
try {
|
try {
|
||||||
validateType(msg.getType());
|
validateType(msg.getType());
|
||||||
EmailPojo email = getEmail(msg);
|
TbEmail email = getEmail(msg);
|
||||||
withCallback(ctx.getMailExecutor().executeAsync(() -> {
|
withCallback(ctx.getMailExecutor().executeAsync(() -> {
|
||||||
sendEmail(ctx, msg, email);
|
sendEmail(ctx, msg, email);
|
||||||
return null;
|
return null;
|
||||||
@ -83,18 +84,16 @@ public class TbSendEmailNode implements TbNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void sendEmail(TbContext ctx, TbMsg msg, EmailPojo email) throws Exception {
|
private void sendEmail(TbContext ctx, TbMsg msg, TbEmail email) throws Exception {
|
||||||
if (this.config.isUseSystemSmtpSettings()) {
|
if (this.config.isUseSystemSmtpSettings()) {
|
||||||
ctx.getMailService().send(ctx.getTenantId(), msg.getCustomerId(), email.getFrom(), email.getTo(), email.getCc(),
|
ctx.getMailService().send(ctx.getTenantId(), msg.getCustomerId(), email);
|
||||||
email.getBcc(), email.getSubject(), email.getBody(), email.isHtml(), email.getImages());
|
|
||||||
} else {
|
} else {
|
||||||
ctx.getMailService().send(ctx.getTenantId(), msg.getCustomerId(), email.getFrom(), email.getTo(), email.getCc(),
|
ctx.getMailService().send(ctx.getTenantId(), msg.getCustomerId(), email, this.mailSender);
|
||||||
email.getBcc(), email.getSubject(), email.getBody(), email.isHtml(), email.getImages(), this.mailSender);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private EmailPojo getEmail(TbMsg msg) throws IOException {
|
private TbEmail getEmail(TbMsg msg) throws IOException {
|
||||||
EmailPojo email = MAPPER.readValue(msg.getData(), EmailPojo.class);
|
TbEmail email = MAPPER.readValue(msg.getData(), TbEmail.class);
|
||||||
if (StringUtils.isBlank(email.getTo())) {
|
if (StringUtils.isBlank(email.getTo())) {
|
||||||
throw new IllegalStateException("Email destination can not be blank [" + email.getTo() + "]");
|
throw new IllegalStateException("Email destination can not be blank [" + email.getTo() + "]");
|
||||||
}
|
}
|
||||||
|
|||||||
@ -81,7 +81,7 @@ public class TbSendRPCRequestNode implements TbNode {
|
|||||||
tmp = msg.getMetaData().getValue("oneway");
|
tmp = msg.getMetaData().getValue("oneway");
|
||||||
boolean oneway = !StringUtils.isEmpty(tmp) && Boolean.parseBoolean(tmp);
|
boolean oneway = !StringUtils.isEmpty(tmp) && Boolean.parseBoolean(tmp);
|
||||||
|
|
||||||
tmp = msg.getMetaData().getValue("persisted");
|
tmp = msg.getMetaData().getValue(DataConstants.PERSISTENT);
|
||||||
boolean persisted = !StringUtils.isEmpty(tmp) && Boolean.parseBoolean(tmp);
|
boolean persisted = !StringUtils.isEmpty(tmp) && Boolean.parseBoolean(tmp);
|
||||||
|
|
||||||
tmp = msg.getMetaData().getValue("requestUUID");
|
tmp = msg.getMetaData().getValue("requestUUID");
|
||||||
|
|||||||
@ -23,6 +23,7 @@ import org.mockito.ArgumentCaptor;
|
|||||||
import org.mockito.Mock;
|
import org.mockito.Mock;
|
||||||
import org.mockito.junit.MockitoJUnitRunner;
|
import org.mockito.junit.MockitoJUnitRunner;
|
||||||
import org.thingsboard.rule.engine.api.TbContext;
|
import org.thingsboard.rule.engine.api.TbContext;
|
||||||
|
import org.thingsboard.rule.engine.api.TbEmail;
|
||||||
import org.thingsboard.rule.engine.api.TbNodeConfiguration;
|
import org.thingsboard.rule.engine.api.TbNodeConfiguration;
|
||||||
import org.thingsboard.rule.engine.api.TbNodeException;
|
import org.thingsboard.rule.engine.api.TbNodeException;
|
||||||
import org.thingsboard.server.common.data.id.DeviceId;
|
import org.thingsboard.server.common.data.id.DeviceId;
|
||||||
@ -79,9 +80,9 @@ public class TbMsgToEmailNodeTest {
|
|||||||
assertEquals("oreo", metadataCaptor.getValue().getValue("username"));
|
assertEquals("oreo", metadataCaptor.getValue().getValue("username"));
|
||||||
assertNotSame(metaData, metadataCaptor.getValue());
|
assertNotSame(metaData, metadataCaptor.getValue());
|
||||||
|
|
||||||
EmailPojo actual = new ObjectMapper().readValue(dataCaptor.getValue().getBytes(), EmailPojo.class);
|
TbEmail actual = new ObjectMapper().readValue(dataCaptor.getValue().getBytes(), TbEmail.class);
|
||||||
|
|
||||||
EmailPojo expected = new EmailPojo.EmailPojoBuilder()
|
TbEmail expected = TbEmail.builder()
|
||||||
.from("test@mail.org")
|
.from("test@mail.org")
|
||||||
.to("user@email.io")
|
.to("user@email.io")
|
||||||
.subject("Hi oreo there")
|
.subject("Hi oreo there")
|
||||||
|
|||||||
@ -69,8 +69,8 @@ export interface WidgetSubscriptionApi {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface RpcApi {
|
export interface RpcApi {
|
||||||
sendOneWayCommand: (method: string, params?: any, timeout?: number, requestUUID?: string) => Observable<any>;
|
sendOneWayCommand: (method: string, params?: any, timeout?: number, persistent?: boolean, requestUUID?: string) => Observable<any>;
|
||||||
sendTwoWayCommand: (method: string, params?: any, timeout?: number, requestUUID?: string) => Observable<any>;
|
sendTwoWayCommand: (method: string, params?: any, timeout?: number, persistent?: boolean, requestUUID?: string) => Observable<any>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IWidgetUtils {
|
export interface IWidgetUtils {
|
||||||
@ -299,8 +299,8 @@ export interface IWidgetSubscription {
|
|||||||
onResetTimewindow(): void;
|
onResetTimewindow(): void;
|
||||||
updateTimewindowConfig(newTimewindow: Timewindow): void;
|
updateTimewindowConfig(newTimewindow: Timewindow): void;
|
||||||
|
|
||||||
sendOneWayCommand(method: string, params?: any, timeout?: number, requestUUID?: string): Observable<any>;
|
sendOneWayCommand(method: string, params?: any, timeout?: number, persistent?: boolean, requestUUID?: string): Observable<any>;
|
||||||
sendTwoWayCommand(method: string, params?: any, timeout?: number, requestUUID?: string): Observable<any>;
|
sendTwoWayCommand(method: string, params?: any, timeout?: number, persistent?: boolean, requestUUID?: string): Observable<any>;
|
||||||
clearRpcError(): void;
|
clearRpcError(): void;
|
||||||
|
|
||||||
subscribe(): void;
|
subscribe(): void;
|
||||||
|
|||||||
@ -644,12 +644,12 @@ export class WidgetSubscription implements IWidgetSubscription {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sendOneWayCommand(method: string, params?: any, timeout?: number, requestUUID?: string): Observable<any> {
|
sendOneWayCommand(method: string, params?: any, timeout?: number, persistent?: boolean, requestUUID?: string): Observable<any> {
|
||||||
return this.sendCommand(true, method, params, timeout, requestUUID);
|
return this.sendCommand(true, method, params, timeout, persistent, requestUUID);
|
||||||
}
|
}
|
||||||
|
|
||||||
sendTwoWayCommand(method: string, params?: any, timeout?: number, requestUUID?: string): Observable<any> {
|
sendTwoWayCommand(method: string, params?: any, timeout?: number, persistent?: boolean, requestUUID?: string): Observable<any> {
|
||||||
return this.sendCommand(false, method, params, timeout, requestUUID);
|
return this.sendCommand(false, method, params, timeout, persistent, requestUUID);
|
||||||
}
|
}
|
||||||
|
|
||||||
clearRpcError(): void {
|
clearRpcError(): void {
|
||||||
@ -658,7 +658,8 @@ export class WidgetSubscription implements IWidgetSubscription {
|
|||||||
this.callbacks.onRpcErrorCleared(this);
|
this.callbacks.onRpcErrorCleared(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
sendCommand(oneWayElseTwoWay: boolean, method: string, params?: any, timeout?: number, requestUUID?: string): Observable<any> {
|
sendCommand(oneWayElseTwoWay: boolean, method: string, params?: any,
|
||||||
|
timeout?: number, persistent?: boolean, requestUUID?: string): Observable<any> {
|
||||||
if (!this.rpcEnabled) {
|
if (!this.rpcEnabled) {
|
||||||
return throwError(new Error('Rpc disabled!'));
|
return throwError(new Error('Rpc disabled!'));
|
||||||
} else {
|
} else {
|
||||||
@ -670,6 +671,7 @@ export class WidgetSubscription implements IWidgetSubscription {
|
|||||||
const requestBody: any = {
|
const requestBody: any = {
|
||||||
method,
|
method,
|
||||||
params,
|
params,
|
||||||
|
persistent,
|
||||||
requestUUID
|
requestUUID
|
||||||
};
|
};
|
||||||
if (timeout && timeout > 0) {
|
if (timeout && timeout > 0) {
|
||||||
|
|||||||
@ -167,6 +167,17 @@
|
|||||||
</mat-option>
|
</mat-option>
|
||||||
</mat-select>
|
</mat-select>
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
|
<mat-form-field class="mat-block" fxFlex *ngIf="lwm2mDeviceProfileFormGroup.get('clientLwM2mSettings.powerMode').value === 'E_DRX'">
|
||||||
|
<mat-label>{{ 'device-profile.edrx-cycle' | translate }}</mat-label>
|
||||||
|
<input matInput type="number" min="0" formControlName="edrxCycle" required>
|
||||||
|
<mat-error *ngIf="lwm2mDeviceProfileFormGroup.get('clientLwM2mSettings.edrxCycle').hasError('required')">
|
||||||
|
{{ 'device-profile.edrx-cycle-required' | translate }}
|
||||||
|
</mat-error>
|
||||||
|
<mat-error *ngIf="lwm2mDeviceProfileFormGroup.get('clientLwM2mSettings.edrxCycle').hasError('pattern') ||
|
||||||
|
lwm2mDeviceProfileFormGroup.get('clientLwM2mSettings.edrxCycle').hasError('min')">
|
||||||
|
{{ 'device-profile.edrx-cycle-pattern' | translate }}
|
||||||
|
</mat-error>
|
||||||
|
</mat-form-field>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
<mat-slide-toggle class="mat-slider"
|
<mat-slide-toggle class="mat-slider"
|
||||||
formControlName="compositeOperationsSupport">{{ 'device-profile.lwm2m.composite-operations-support' | translate }}</mat-slide-toggle>
|
formControlName="compositeOperationsSupport">{{ 'device-profile.lwm2m.composite-operations-support' | translate }}</mat-slide-toggle>
|
||||||
|
|||||||
@ -116,6 +116,7 @@ export class Lwm2mDeviceProfileTransportConfigurationComponent implements Contro
|
|||||||
fwUpdateResource: [{value: '', disabled: true}, []],
|
fwUpdateResource: [{value: '', disabled: true}, []],
|
||||||
swUpdateResource: [{value: '', disabled: true}, []],
|
swUpdateResource: [{value: '', disabled: true}, []],
|
||||||
powerMode: [PowerMode.DRX, Validators.required],
|
powerMode: [PowerMode.DRX, Validators.required],
|
||||||
|
edrxCycle: [0],
|
||||||
compositeOperationsSupport: [false]
|
compositeOperationsSupport: [false]
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
@ -150,6 +151,20 @@ export class Lwm2mDeviceProfileTransportConfigurationComponent implements Contro
|
|||||||
}
|
}
|
||||||
this.otaUpdateSwStrategyValidate(true);
|
this.otaUpdateSwStrategyValidate(true);
|
||||||
});
|
});
|
||||||
|
this.lwm2mDeviceProfileFormGroup.get('clientLwM2mSettings.powerMode').valueChanges.pipe(
|
||||||
|
takeUntil(this.destroy$)
|
||||||
|
).subscribe((powerMode: PowerMode) => {
|
||||||
|
if (powerMode === PowerMode.E_DRX) {
|
||||||
|
this.lwm2mDeviceProfileFormGroup.get('clientLwM2mSettings.edrxCycle').enable({emitEvent: false});
|
||||||
|
this.lwm2mDeviceProfileFormGroup.get('clientLwM2mSettings.edrxCycle').patchValue(0, {emitEvent: false});
|
||||||
|
this.lwm2mDeviceProfileFormGroup.get('clientLwM2mSettings.edrxCycle')
|
||||||
|
.setValidators([Validators.required, Validators.min(0), Validators.pattern('[0-9]*')]);
|
||||||
|
} else {
|
||||||
|
this.lwm2mDeviceProfileFormGroup.get('clientLwM2mSettings.edrxCycle').disable({emitEvent: false});
|
||||||
|
this.lwm2mDeviceProfileFormGroup.get('clientLwM2mSettings.edrxCycle').clearValidators();
|
||||||
|
}
|
||||||
|
this.lwm2mDeviceProfileFormGroup.get('clientLwM2mSettings.edrxCycle').updateValueAndValidity({emitEvent: false});
|
||||||
|
});
|
||||||
this.lwm2mDeviceProfileFormGroup.valueChanges.pipe(
|
this.lwm2mDeviceProfileFormGroup.valueChanges.pipe(
|
||||||
takeUntil(this.destroy$)
|
takeUntil(this.destroy$)
|
||||||
).subscribe((value) => {
|
).subscribe((value) => {
|
||||||
@ -256,10 +271,13 @@ export class Lwm2mDeviceProfileTransportConfigurationComponent implements Contro
|
|||||||
fwUpdateResource: fwResource,
|
fwUpdateResource: fwResource,
|
||||||
swUpdateResource: swResource,
|
swUpdateResource: swResource,
|
||||||
powerMode: this.configurationValue.clientLwM2mSettings.powerMode || PowerMode.DRX,
|
powerMode: this.configurationValue.clientLwM2mSettings.powerMode || PowerMode.DRX,
|
||||||
|
edrxCycle: this.configurationValue.clientLwM2mSettings.edrxCycle || 0,
|
||||||
compositeOperationsSupport: this.configurationValue.clientLwM2mSettings.compositeOperationsSupport || false
|
compositeOperationsSupport: this.configurationValue.clientLwM2mSettings.compositeOperationsSupport || false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{emitEvent: false});
|
{emitEvent: false});
|
||||||
|
this.lwm2mDeviceProfileFormGroup.get('clientLwM2mSettings.powerMode')
|
||||||
|
.patchValue(this.configurationValue.clientLwM2mSettings.powerMode || PowerMode.DRX, {emitEvent: false, onlySelf: true});
|
||||||
this.configurationValue.clientLwM2mSettings.fwUpdateResource = fwResource;
|
this.configurationValue.clientLwM2mSettings.fwUpdateResource = fwResource;
|
||||||
this.configurationValue.clientLwM2mSettings.swUpdateResource = swResource;
|
this.configurationValue.clientLwM2mSettings.swUpdateResource = swResource;
|
||||||
this.isFwUpdateStrategy = this.configurationValue.clientLwM2mSettings.fwUpdateStrategy === 2;
|
this.isFwUpdateStrategy = this.configurationValue.clientLwM2mSettings.fwUpdateStrategy === 2;
|
||||||
|
|||||||
@ -169,6 +169,7 @@ export interface ClientLwM2mSettings {
|
|||||||
fwUpdateResource: string;
|
fwUpdateResource: string;
|
||||||
swUpdateResource: string;
|
swUpdateResource: string;
|
||||||
powerMode: PowerMode;
|
powerMode: PowerMode;
|
||||||
|
edrxCycle?: number;
|
||||||
compositeOperationsSupport: boolean;
|
compositeOperationsSupport: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -189,16 +189,16 @@ export class WidgetContext {
|
|||||||
};
|
};
|
||||||
|
|
||||||
controlApi: RpcApi = {
|
controlApi: RpcApi = {
|
||||||
sendOneWayCommand: (method, params, timeout, requestUUID) => {
|
sendOneWayCommand: (method, params, timeout, persistent, requestUUID) => {
|
||||||
if (this.defaultSubscription) {
|
if (this.defaultSubscription) {
|
||||||
return this.defaultSubscription.sendOneWayCommand(method, params, timeout, requestUUID);
|
return this.defaultSubscription.sendOneWayCommand(method, params, timeout, persistent, requestUUID);
|
||||||
} else {
|
} else {
|
||||||
return of(null);
|
return of(null);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
sendTwoWayCommand: (method, params, timeout, requestUUID) => {
|
sendTwoWayCommand: (method, params, timeout, persistent, requestUUID) => {
|
||||||
if (this.defaultSubscription) {
|
if (this.defaultSubscription) {
|
||||||
return this.defaultSubscription.sendTwoWayCommand(method, params, timeout, requestUUID);
|
return this.defaultSubscription.sendTwoWayCommand(method, params, timeout, persistent, requestUUID);
|
||||||
} else {
|
} else {
|
||||||
return of(null);
|
return of(null);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -25,4 +25,15 @@
|
|||||||
</mat-option>
|
</mat-option>
|
||||||
</mat-select>
|
</mat-select>
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
|
<mat-form-field class="mat-block" fxFlex *ngIf="lwm2mDeviceTransportConfigurationFormGroup.get('powerMode').value === 'E_DRX'">
|
||||||
|
<mat-label>{{ 'device-profile.edrx-cycle' | translate }}</mat-label>
|
||||||
|
<input matInput type="number" min="0" formControlName="edrxCycle" required>
|
||||||
|
<mat-error *ngIf="lwm2mDeviceTransportConfigurationFormGroup.get('edrxCycle').hasError('required')">
|
||||||
|
{{ 'device-profile.edrx-cycle-required' | translate }}
|
||||||
|
</mat-error>
|
||||||
|
<mat-error *ngIf="lwm2mDeviceTransportConfigurationFormGroup.get('edrxCycle').hasError('pattern') ||
|
||||||
|
lwm2mDeviceTransportConfigurationFormGroup.get('edrxCycle').hasError('min')">
|
||||||
|
{{ 'device-profile.edrx-cycle-pattern' | translate }}
|
||||||
|
</mat-error>
|
||||||
|
</mat-form-field>
|
||||||
</form>
|
</form>
|
||||||
|
|||||||
@ -14,16 +14,16 @@
|
|||||||
/// limitations under the License.
|
/// limitations under the License.
|
||||||
///
|
///
|
||||||
|
|
||||||
import { Component, forwardRef, Input, OnInit } from '@angular/core';
|
import { Component, forwardRef, Input, OnDestroy, OnInit } from '@angular/core';
|
||||||
import { ControlValueAccessor, FormBuilder, FormGroup, NG_VALUE_ACCESSOR, Validators } from '@angular/forms';
|
import { ControlValueAccessor, FormBuilder, FormGroup, NG_VALUE_ACCESSOR, Validators } from '@angular/forms';
|
||||||
import { Store } from '@ngrx/store';
|
import { Store } from '@ngrx/store';
|
||||||
import { AppState } from '@app/core/core.state';
|
import { AppState } from '@app/core/core.state';
|
||||||
import { coerceBooleanProperty } from '@angular/cdk/coercion';
|
import { coerceBooleanProperty } from '@angular/cdk/coercion';
|
||||||
import {
|
import { DeviceTransportConfiguration, Lwm2mDeviceTransportConfiguration } from '@shared/models/device.models';
|
||||||
DeviceTransportConfiguration,
|
import { PowerMode, PowerModeTranslationMap } from '@home/components/profile/device/lwm2m/lwm2m-profile-config.models';
|
||||||
DeviceTransportType, Lwm2mDeviceTransportConfiguration
|
import { takeUntil } from 'rxjs/operators';
|
||||||
} from '@shared/models/device.models';
|
import { Subject } from 'rxjs';
|
||||||
import {PowerMode, PowerModeTranslationMap} from "@home/components/profile/device/lwm2m/lwm2m-profile-config.models";
|
import { isDefinedAndNotNull } from '@core/utils';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'tb-lwm2m-device-transport-configuration',
|
selector: 'tb-lwm2m-device-transport-configuration',
|
||||||
@ -35,7 +35,7 @@ import {PowerMode, PowerModeTranslationMap} from "@home/components/profile/devic
|
|||||||
multi: true
|
multi: true
|
||||||
}]
|
}]
|
||||||
})
|
})
|
||||||
export class Lwm2mDeviceTransportConfigurationComponent implements ControlValueAccessor, OnInit {
|
export class Lwm2mDeviceTransportConfigurationComponent implements ControlValueAccessor, OnInit, OnDestroy {
|
||||||
|
|
||||||
lwm2mDeviceTransportConfigurationFormGroup: FormGroup;
|
lwm2mDeviceTransportConfigurationFormGroup: FormGroup;
|
||||||
powerMods = Object.values(PowerMode);
|
powerMods = Object.values(PowerMode);
|
||||||
@ -53,6 +53,7 @@ export class Lwm2mDeviceTransportConfigurationComponent implements ControlValueA
|
|||||||
@Input()
|
@Input()
|
||||||
disabled: boolean;
|
disabled: boolean;
|
||||||
|
|
||||||
|
private destroy$ = new Subject();
|
||||||
private propagateChange = (v: any) => { };
|
private propagateChange = (v: any) => { };
|
||||||
|
|
||||||
constructor(private store: Store<AppState>,
|
constructor(private store: Store<AppState>,
|
||||||
@ -68,13 +69,35 @@ export class Lwm2mDeviceTransportConfigurationComponent implements ControlValueA
|
|||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
this.lwm2mDeviceTransportConfigurationFormGroup = this.fb.group({
|
this.lwm2mDeviceTransportConfigurationFormGroup = this.fb.group({
|
||||||
powerMode: [null]
|
powerMode: [null],
|
||||||
|
edrxCycle: [0]
|
||||||
});
|
});
|
||||||
this.lwm2mDeviceTransportConfigurationFormGroup.valueChanges.subscribe(() => {
|
this.lwm2mDeviceTransportConfigurationFormGroup.get('powerMode').valueChanges.pipe(
|
||||||
|
takeUntil(this.destroy$)
|
||||||
|
).subscribe((powerMode: PowerMode) => {
|
||||||
|
if (powerMode === PowerMode.E_DRX) {
|
||||||
|
this.lwm2mDeviceTransportConfigurationFormGroup.get('edrxCycle').enable({emitEvent: false});
|
||||||
|
this.lwm2mDeviceTransportConfigurationFormGroup.get('edrxCycle').patchValue(0, {emitEvent: false});
|
||||||
|
this.lwm2mDeviceTransportConfigurationFormGroup.get('edrxCycle')
|
||||||
|
.setValidators([Validators.required, Validators.min(0), Validators.pattern('[0-9]*')]);
|
||||||
|
} else {
|
||||||
|
this.lwm2mDeviceTransportConfigurationFormGroup.get('edrxCycle').disable({emitEvent: false});
|
||||||
|
this.lwm2mDeviceTransportConfigurationFormGroup.get('edrxCycle').clearValidators();
|
||||||
|
}
|
||||||
|
this.lwm2mDeviceTransportConfigurationFormGroup.get('edrxCycle').updateValueAndValidity({emitEvent: false});
|
||||||
|
});
|
||||||
|
this.lwm2mDeviceTransportConfigurationFormGroup.valueChanges.pipe(
|
||||||
|
takeUntil(this.destroy$)
|
||||||
|
).subscribe(() => {
|
||||||
this.updateModel();
|
this.updateModel();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ngOnDestroy() {
|
||||||
|
this.destroy$.next();
|
||||||
|
this.destroy$.complete();
|
||||||
|
}
|
||||||
|
|
||||||
setDisabledState(isDisabled: boolean): void {
|
setDisabledState(isDisabled: boolean): void {
|
||||||
this.disabled = isDisabled;
|
this.disabled = isDisabled;
|
||||||
if (this.disabled) {
|
if (this.disabled) {
|
||||||
@ -85,13 +108,18 @@ export class Lwm2mDeviceTransportConfigurationComponent implements ControlValueA
|
|||||||
}
|
}
|
||||||
|
|
||||||
writeValue(value: Lwm2mDeviceTransportConfiguration | null): void {
|
writeValue(value: Lwm2mDeviceTransportConfiguration | null): void {
|
||||||
this.lwm2mDeviceTransportConfigurationFormGroup.patchValue(value, {emitEvent: false});
|
if (isDefinedAndNotNull(value)) {
|
||||||
|
this.lwm2mDeviceTransportConfigurationFormGroup.get('powerMode').patchValue(value.powerMode, {emitEvent: false, onlySelf: true});
|
||||||
|
this.lwm2mDeviceTransportConfigurationFormGroup.get('edrxCycle').patchValue(value.edrxCycle || 0, {emitEvent: false});
|
||||||
|
} else {
|
||||||
|
this.lwm2mDeviceTransportConfigurationFormGroup.patchValue({powerMode: null, edrxCycle: 0}, {emitEvent: false});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private updateModel() {
|
private updateModel() {
|
||||||
let configuration: DeviceTransportConfiguration = null;
|
let configuration: DeviceTransportConfiguration = null;
|
||||||
if (this.lwm2mDeviceTransportConfigurationFormGroup.valid) {
|
if (this.lwm2mDeviceTransportConfigurationFormGroup.valid) {
|
||||||
configuration = this.lwm2mDeviceTransportConfigurationFormGroup.getRawValue();
|
configuration = this.lwm2mDeviceTransportConfigurationFormGroup.value;
|
||||||
// configuration.type = DeviceTransportType.LWM2M;
|
// configuration.type = DeviceTransportType.LWM2M;
|
||||||
}
|
}
|
||||||
this.propagateChange(configuration);
|
this.propagateChange(configuration);
|
||||||
|
|||||||
@ -126,7 +126,7 @@ export const timewindowCompletion: TbEditorCompletion = {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
export const widgetContextCompletions: TbEditorCompletions = {
|
export const widgetContextCompletions: TbEditorCompletions = {
|
||||||
ctx: {
|
ctx: {
|
||||||
@ -465,6 +465,12 @@ export const widgetContextCompletions: TbEditorCompletions = {
|
|||||||
description: 'Maximum delay in milliseconds to wait until response/acknowledgement is received.',
|
description: 'Maximum delay in milliseconds to wait until response/acknowledgement is received.',
|
||||||
type: 'number',
|
type: 'number',
|
||||||
optional: true
|
optional: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'persistent',
|
||||||
|
description: 'RPC request persistent',
|
||||||
|
type: 'boolean',
|
||||||
|
optional: true
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
return: {
|
return: {
|
||||||
@ -492,6 +498,12 @@ export const widgetContextCompletions: TbEditorCompletions = {
|
|||||||
description: 'Maximum delay in milliseconds to wait until response/acknowledgement is received.',
|
description: 'Maximum delay in milliseconds to wait until response/acknowledgement is received.',
|
||||||
type: 'number',
|
type: 'number',
|
||||||
optional: true
|
optional: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'persistent',
|
||||||
|
description: 'RPC request persistent',
|
||||||
|
type: 'boolean',
|
||||||
|
optional: true
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
return: {
|
return: {
|
||||||
@ -657,4 +669,4 @@ export const widgetContextCompletions: TbEditorCompletions = {
|
|||||||
...serviceCompletions
|
...serviceCompletions
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|||||||
@ -30,6 +30,7 @@ import { AbstractControl, ValidationErrors } from '@angular/forms';
|
|||||||
import { OtaPackageId } from '@shared/models/id/ota-package-id';
|
import { OtaPackageId } from '@shared/models/id/ota-package-id';
|
||||||
import { DashboardId } from '@shared/models/id/dashboard-id';
|
import { DashboardId } from '@shared/models/id/dashboard-id';
|
||||||
import { DataType } from '@shared/models/constants';
|
import { DataType } from '@shared/models/constants';
|
||||||
|
import { PowerMode } from '@home/components/profile/device/lwm2m/lwm2m-profile-config.models';
|
||||||
|
|
||||||
export enum DeviceProfileType {
|
export enum DeviceProfileType {
|
||||||
DEFAULT = 'DEFAULT',
|
DEFAULT = 'DEFAULT',
|
||||||
@ -573,6 +574,8 @@ export interface CoapDeviceTransportConfiguration {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface Lwm2mDeviceTransportConfiguration {
|
export interface Lwm2mDeviceTransportConfiguration {
|
||||||
|
powerMode?: PowerMode | null;
|
||||||
|
edrxCycle?: number;
|
||||||
[key: string]: any;
|
[key: string]: any;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1222,6 +1222,9 @@
|
|||||||
"drx": "Discontinuous Reception (DRX)",
|
"drx": "Discontinuous Reception (DRX)",
|
||||||
"edrx": "Extended Discontinuous Reception (eDRX)"
|
"edrx": "Extended Discontinuous Reception (eDRX)"
|
||||||
},
|
},
|
||||||
|
"edrx-cycle": "eDRX cycle in milliseconds",
|
||||||
|
"edrx-cycle-required": "eDRX cycle is required.",
|
||||||
|
"edrx-cycle-pattern": "eDRX cycle must be a positive integer.",
|
||||||
"lwm2m": {
|
"lwm2m": {
|
||||||
"object-list": "Object list",
|
"object-list": "Object list",
|
||||||
"object-list-empty": "No objects selected.",
|
"object-list-empty": "No objects selected.",
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user