Default Dashboard and Rule Chain
This commit is contained in:
parent
6b212bb5d7
commit
1510fe8448
1236
application/src/main/data/json/demo/dashboards/theromstats.json
Normal file
1236
application/src/main/data/json/demo/dashboards/theromstats.json
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,146 @@
|
||||
{
|
||||
"ruleChain": {
|
||||
"additionalInfo": null,
|
||||
"name": "Root Rule Chain",
|
||||
"firstRuleNodeId": null,
|
||||
"root": false,
|
||||
"debugMode": false,
|
||||
"configuration": null
|
||||
},
|
||||
"metadata": {
|
||||
"firstNodeIndex": 2,
|
||||
"nodes": [
|
||||
{
|
||||
"additionalInfo": {
|
||||
"layoutX": 824,
|
||||
"layoutY": 156
|
||||
},
|
||||
"type": "org.thingsboard.rule.engine.telemetry.TbMsgTimeseriesNode",
|
||||
"name": "Save Timeseries",
|
||||
"debugMode": false,
|
||||
"configuration": {
|
||||
"defaultTTL": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"additionalInfo": {
|
||||
"layoutX": 825,
|
||||
"layoutY": 52
|
||||
},
|
||||
"type": "org.thingsboard.rule.engine.telemetry.TbMsgAttributesNode",
|
||||
"name": "Save Client Attributes",
|
||||
"debugMode": false,
|
||||
"configuration": {
|
||||
"scope": "CLIENT_SCOPE"
|
||||
}
|
||||
},
|
||||
{
|
||||
"additionalInfo": {
|
||||
"layoutX": 347,
|
||||
"layoutY": 149
|
||||
},
|
||||
"type": "org.thingsboard.rule.engine.filter.TbMsgTypeSwitchNode",
|
||||
"name": "Message Type Switch",
|
||||
"debugMode": false,
|
||||
"configuration": {
|
||||
"version": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"additionalInfo": {
|
||||
"layoutX": 825,
|
||||
"layoutY": 266
|
||||
},
|
||||
"type": "org.thingsboard.rule.engine.action.TbLogNode",
|
||||
"name": "Log RPC from Device",
|
||||
"debugMode": false,
|
||||
"configuration": {
|
||||
"jsScript": "return '\\nIncoming message:\\n' + JSON.stringify(msg) + '\\nIncoming metadata:\\n' + JSON.stringify(metadata);"
|
||||
}
|
||||
},
|
||||
{
|
||||
"additionalInfo": {
|
||||
"layoutX": 825,
|
||||
"layoutY": 379
|
||||
},
|
||||
"type": "org.thingsboard.rule.engine.action.TbLogNode",
|
||||
"name": "Log Other",
|
||||
"debugMode": false,
|
||||
"configuration": {
|
||||
"jsScript": "return '\\nIncoming message:\\n' + JSON.stringify(msg) + '\\nIncoming metadata:\\n' + JSON.stringify(metadata);"
|
||||
}
|
||||
},
|
||||
{
|
||||
"additionalInfo": {
|
||||
"layoutX": 825,
|
||||
"layoutY": 468
|
||||
},
|
||||
"type": "org.thingsboard.rule.engine.rpc.TbSendRPCRequestNode",
|
||||
"name": "RPC Call Request",
|
||||
"debugMode": false,
|
||||
"configuration": {
|
||||
"timeoutInSeconds": 60
|
||||
}
|
||||
},
|
||||
{
|
||||
"additionalInfo": {
|
||||
"layoutX": 1069,
|
||||
"layoutY": 90
|
||||
},
|
||||
"type": "org.thingsboard.rule.engine.filter.TbJsFilterNode",
|
||||
"name": "Is Thermostat?",
|
||||
"debugMode": false,
|
||||
"configuration": {
|
||||
"jsScript": "return metadata[\"deviceType\"] === \"thermostat\";"
|
||||
}
|
||||
}
|
||||
],
|
||||
"connections": [
|
||||
{
|
||||
"fromIndex": 0,
|
||||
"toIndex": 6,
|
||||
"type": "Success"
|
||||
},
|
||||
{
|
||||
"fromIndex": 2,
|
||||
"toIndex": 4,
|
||||
"type": "Other"
|
||||
},
|
||||
{
|
||||
"fromIndex": 2,
|
||||
"toIndex": 1,
|
||||
"type": "Post attributes"
|
||||
},
|
||||
{
|
||||
"fromIndex": 2,
|
||||
"toIndex": 0,
|
||||
"type": "Post telemetry"
|
||||
},
|
||||
{
|
||||
"fromIndex": 2,
|
||||
"toIndex": 3,
|
||||
"type": "RPC Request from Device"
|
||||
},
|
||||
{
|
||||
"fromIndex": 2,
|
||||
"toIndex": 5,
|
||||
"type": "RPC Request to Device"
|
||||
}
|
||||
],
|
||||
"ruleChainConnections": [
|
||||
{
|
||||
"fromIndex": 6,
|
||||
"targetRuleChainId": {
|
||||
"entityType": "RULE_CHAIN",
|
||||
"id": "83d42540-85fd-11ea-aee2-794850541ced"
|
||||
},
|
||||
"additionalInfo": {
|
||||
"layoutX": 1088,
|
||||
"layoutY": 203,
|
||||
"ruleChainNodeId": "rule-chain-node-9"
|
||||
},
|
||||
"type": "True"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,137 @@
|
||||
{
|
||||
"ruleChain": {
|
||||
"additionalInfo": null,
|
||||
"name": "Thermostat Alarms",
|
||||
"firstRuleNodeId": null,
|
||||
"root": false,
|
||||
"debugMode": false,
|
||||
"configuration": null
|
||||
},
|
||||
"metadata": {
|
||||
"firstNodeIndex": 5,
|
||||
"nodes": [
|
||||
{
|
||||
"additionalInfo": {
|
||||
"layoutX": 929,
|
||||
"layoutY": 67
|
||||
},
|
||||
"type": "org.thingsboard.rule.engine.action.TbCreateAlarmNode",
|
||||
"name": "Create Temp Alarm",
|
||||
"debugMode": false,
|
||||
"configuration": {
|
||||
"alarmType": "High Temperature",
|
||||
"alarmDetailsBuildJs": "var details = {};\nif (metadata.prevAlarmDetails) {\n details = JSON.parse(metadata.prevAlarmDetails);\n}\ndetails.triggerValue = msg.temperature;\nreturn details;",
|
||||
"severity": "MAJOR",
|
||||
"propagate": true,
|
||||
"useMessageAlarmData": false,
|
||||
"relationTypes": []
|
||||
}
|
||||
},
|
||||
{
|
||||
"additionalInfo": {
|
||||
"layoutX": 930,
|
||||
"layoutY": 201
|
||||
},
|
||||
"type": "org.thingsboard.rule.engine.action.TbClearAlarmNode",
|
||||
"name": "Clear Temp Alarm",
|
||||
"debugMode": false,
|
||||
"configuration": {
|
||||
"alarmType": "High Temperature",
|
||||
"alarmDetailsBuildJs": "var details = {};\nif (metadata.prevAlarmDetails) {\n details = JSON.parse(metadata.prevAlarmDetails);\n}\nreturn details;"
|
||||
}
|
||||
},
|
||||
{
|
||||
"additionalInfo": {
|
||||
"layoutX": 930,
|
||||
"layoutY": 131
|
||||
},
|
||||
"type": "org.thingsboard.rule.engine.action.TbCreateAlarmNode",
|
||||
"name": "Create Humidity Alarm",
|
||||
"debugMode": false,
|
||||
"configuration": {
|
||||
"alarmType": "Low Humidity",
|
||||
"alarmDetailsBuildJs": "var details = {};\nif (metadata.prevAlarmDetails) {\n details = JSON.parse(metadata.prevAlarmDetails);\n}\ndetails.triggerValue = msg.humidity;\nreturn details;",
|
||||
"severity": "MINOR",
|
||||
"propagate": true,
|
||||
"useMessageAlarmData": false,
|
||||
"relationTypes": []
|
||||
}
|
||||
},
|
||||
{
|
||||
"additionalInfo": {
|
||||
"layoutX": 929,
|
||||
"layoutY": 275
|
||||
},
|
||||
"type": "org.thingsboard.rule.engine.action.TbClearAlarmNode",
|
||||
"name": "Clear Humidity Alarm",
|
||||
"debugMode": false,
|
||||
"configuration": {
|
||||
"alarmType": "Low Humidity",
|
||||
"alarmDetailsBuildJs": "var details = {};\nif (metadata.prevAlarmDetails) {\n details = JSON.parse(metadata.prevAlarmDetails);\n}\nreturn details;"
|
||||
}
|
||||
},
|
||||
{
|
||||
"additionalInfo": {
|
||||
"layoutX": 586,
|
||||
"layoutY": 148
|
||||
},
|
||||
"type": "org.thingsboard.rule.engine.filter.TbJsSwitchNode",
|
||||
"name": "Check Alarms",
|
||||
"debugMode": true,
|
||||
"configuration": {
|
||||
"jsScript": "var relations = [];\nif(metadata[\"ss_alarmTemperature\"] === \"true\"){\n if(msg.temperature > metadata[\"ss_thresholdTemperature\"]){\n relations.push(\"NewTempAlarm\");\n } else {\n relations.push(\"ClearTempAlarm\");\n }\n}\nif(metadata[\"ss_alarmHumidity\"] === \"true\"){\n if(msg.humidity < metadata[\"ss_thresholdHumidity\"]){\n relations.push(\"NewHumidityAlarm\");\n } else {\n relations.push(\"ClearHumidityAlarm\");\n }\n}\n\nreturn relations;"
|
||||
}
|
||||
},
|
||||
{
|
||||
"additionalInfo": {
|
||||
"layoutX": 321,
|
||||
"layoutY": 149
|
||||
},
|
||||
"type": "org.thingsboard.rule.engine.metadata.TbGetAttributesNode",
|
||||
"name": "Fetch Configuration",
|
||||
"debugMode": true,
|
||||
"configuration": {
|
||||
"clientAttributeNames": [],
|
||||
"sharedAttributeNames": [],
|
||||
"serverAttributeNames": [
|
||||
"alarmTemperature",
|
||||
"thresholdTemperature",
|
||||
"alarmHumidity",
|
||||
"thresholdHumidity"
|
||||
],
|
||||
"latestTsKeyNames": [],
|
||||
"tellFailureIfAbsent": false,
|
||||
"getLatestValueWithTs": false
|
||||
}
|
||||
}
|
||||
],
|
||||
"connections": [
|
||||
{
|
||||
"fromIndex": 4,
|
||||
"toIndex": 0,
|
||||
"type": "NewTempAlarm"
|
||||
},
|
||||
{
|
||||
"fromIndex": 4,
|
||||
"toIndex": 1,
|
||||
"type": "ClearTempAlarm"
|
||||
},
|
||||
{
|
||||
"fromIndex": 4,
|
||||
"toIndex": 2,
|
||||
"type": "NewHumidityAlarm"
|
||||
},
|
||||
{
|
||||
"fromIndex": 4,
|
||||
"toIndex": 3,
|
||||
"type": "ClearHumidityAlarm"
|
||||
},
|
||||
{
|
||||
"fromIndex": 5,
|
||||
"toIndex": 4,
|
||||
"type": "Success"
|
||||
}
|
||||
],
|
||||
"ruleChainConnections": null
|
||||
}
|
||||
}
|
||||
@ -5,7 +5,7 @@
|
||||
* 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
|
||||
* 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,
|
||||
@ -25,24 +25,32 @@ import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.thingsboard.server.common.data.AdminSettings;
|
||||
import org.thingsboard.server.common.data.Customer;
|
||||
import org.thingsboard.server.common.data.DataConstants;
|
||||
import org.thingsboard.server.common.data.Device;
|
||||
import org.thingsboard.server.common.data.Tenant;
|
||||
import org.thingsboard.server.common.data.User;
|
||||
import org.thingsboard.server.common.data.id.CustomerId;
|
||||
import org.thingsboard.server.common.data.id.DeviceId;
|
||||
import org.thingsboard.server.common.data.id.TenantId;
|
||||
import org.thingsboard.server.common.data.kv.BaseAttributeKvEntry;
|
||||
import org.thingsboard.server.common.data.kv.BooleanDataEntry;
|
||||
import org.thingsboard.server.common.data.kv.DoubleDataEntry;
|
||||
import org.thingsboard.server.common.data.kv.LongDataEntry;
|
||||
import org.thingsboard.server.common.data.security.Authority;
|
||||
import org.thingsboard.server.common.data.security.DeviceCredentials;
|
||||
import org.thingsboard.server.common.data.security.UserCredentials;
|
||||
import org.thingsboard.server.common.data.widget.WidgetsBundle;
|
||||
import org.thingsboard.server.dao.attributes.AttributesService;
|
||||
import org.thingsboard.server.dao.customer.CustomerService;
|
||||
import org.thingsboard.server.dao.device.DeviceCredentialsService;
|
||||
import org.thingsboard.server.dao.device.DeviceService;
|
||||
import org.thingsboard.server.dao.model.ModelConstants;
|
||||
import org.thingsboard.server.dao.settings.AdminSettingsService;
|
||||
import org.thingsboard.server.dao.tenant.TenantService;
|
||||
import org.thingsboard.server.dao.user.UserService;
|
||||
import org.thingsboard.server.dao.widget.WidgetsBundleService;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
@Service
|
||||
@Profile("install")
|
||||
@Slf4j
|
||||
@ -76,6 +84,9 @@ public class DefaultSystemDataLoaderService implements SystemDataLoaderService {
|
||||
@Autowired
|
||||
private DeviceService deviceService;
|
||||
|
||||
@Autowired
|
||||
private AttributesService attributesService;
|
||||
|
||||
@Autowired
|
||||
private DeviceCredentialsService deviceCredentialsService;
|
||||
|
||||
@ -120,7 +131,7 @@ public class DefaultSystemDataLoaderService implements SystemDataLoaderService {
|
||||
demoTenant.setRegion("Global");
|
||||
demoTenant.setTitle("Tenant");
|
||||
demoTenant = tenantService.saveTenant(demoTenant);
|
||||
installScripts.createDefaultRuleChains(demoTenant.getId());
|
||||
installScripts.loadDemoRuleChains(demoTenant.getId());
|
||||
createUser(Authority.TENANT_ADMIN, demoTenant.getId(), null, "tenant@thingsboard.org", "tenant");
|
||||
|
||||
Customer customerA = new Customer();
|
||||
@ -152,6 +163,25 @@ public class DefaultSystemDataLoaderService implements SystemDataLoaderService {
|
||||
createDevice(demoTenant.getId(), null, DEFAULT_DEVICE_TYPE, "Raspberry Pi Demo Device", "RASPBERRY_PI_DEMO_TOKEN", "Demo device that is used in " +
|
||||
"Raspberry Pi GPIO control sample application");
|
||||
|
||||
DeviceId t1Id = createDevice(demoTenant.getId(), null, "thermostat", "Thermostat T1", "T1_TEST_TOKEN", "Demo device for Thermostats dashboard").getId();
|
||||
DeviceId t2Id = createDevice(demoTenant.getId(), null, "thermostat", "Thermostat T2", "T2_TEST_TOKEN", "Demo device for Thermostats dashboard").getId();
|
||||
|
||||
attributesService.save(demoTenant.getId(), t1Id, DataConstants.SERVER_SCOPE,
|
||||
Arrays.asList(new BaseAttributeKvEntry(System.currentTimeMillis(), new DoubleDataEntry("latitude", 37.3948)),
|
||||
new BaseAttributeKvEntry(System.currentTimeMillis(), new DoubleDataEntry("longitude", -122.1503)),
|
||||
new BaseAttributeKvEntry(System.currentTimeMillis(), new BooleanDataEntry("alarmTemperature", true)),
|
||||
new BaseAttributeKvEntry(System.currentTimeMillis(), new BooleanDataEntry("alarmHumidity", true)),
|
||||
new BaseAttributeKvEntry(System.currentTimeMillis(), new LongDataEntry("thresholdTemperature", (long) 20)),
|
||||
new BaseAttributeKvEntry(System.currentTimeMillis(), new LongDataEntry("thresholdHumidity", (long) 50))));
|
||||
|
||||
attributesService.save(demoTenant.getId(), t2Id, DataConstants.SERVER_SCOPE,
|
||||
Arrays.asList(new BaseAttributeKvEntry(System.currentTimeMillis(), new DoubleDataEntry("latitude", 37.493801)),
|
||||
new BaseAttributeKvEntry(System.currentTimeMillis(), new DoubleDataEntry("longitude", -121.948769)),
|
||||
new BaseAttributeKvEntry(System.currentTimeMillis(), new BooleanDataEntry("alarmTemperature", true)),
|
||||
new BaseAttributeKvEntry(System.currentTimeMillis(), new BooleanDataEntry("alarmHumidity", true)),
|
||||
new BaseAttributeKvEntry(System.currentTimeMillis(), new LongDataEntry("thresholdTemperature", (long) 25)),
|
||||
new BaseAttributeKvEntry(System.currentTimeMillis(), new LongDataEntry("thresholdHumidity", (long) 30))));
|
||||
|
||||
installScripts.loadDashboards(demoTenant.getId(), null);
|
||||
}
|
||||
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
* 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
|
||||
* 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,
|
||||
@ -24,6 +24,7 @@ import org.springframework.util.StringUtils;
|
||||
import org.thingsboard.server.common.data.Dashboard;
|
||||
import org.thingsboard.server.common.data.id.CustomerId;
|
||||
import org.thingsboard.server.common.data.id.EntityId;
|
||||
import org.thingsboard.server.common.data.id.RuleChainId;
|
||||
import org.thingsboard.server.common.data.id.TenantId;
|
||||
import org.thingsboard.server.common.data.rule.RuleChain;
|
||||
import org.thingsboard.server.common.data.rule.RuleChainMetaData;
|
||||
@ -182,4 +183,54 @@ public class InstallScripts {
|
||||
}
|
||||
|
||||
|
||||
public void loadDemoRuleChains(TenantId tenantId) throws Exception {
|
||||
Path ruleChainsDir = Paths.get(getDataDir(), JSON_DIR, DEMO_DIR, RULE_CHAINS_DIR);
|
||||
try {
|
||||
JsonNode ruleChainJson = objectMapper.readTree(ruleChainsDir.resolve("thermostat_alarms.json").toFile());
|
||||
RuleChain ruleChain = objectMapper.treeToValue(ruleChainJson.get("ruleChain"), RuleChain.class);
|
||||
RuleChainMetaData ruleChainMetaData = objectMapper.treeToValue(ruleChainJson.get("metadata"), RuleChainMetaData.class);
|
||||
ruleChain.setTenantId(tenantId);
|
||||
ruleChain = ruleChainService.saveRuleChain(ruleChain);
|
||||
ruleChainMetaData.setRuleChainId(ruleChain.getId());
|
||||
ruleChainService.saveRuleChainMetaData(new TenantId(EntityId.NULL_UUID), ruleChainMetaData);
|
||||
|
||||
JsonNode rootChainJson = objectMapper.readTree(ruleChainsDir.resolve("root_rule_chain.json").toFile());
|
||||
RuleChain rootChain = objectMapper.treeToValue(rootChainJson.get("ruleChain"), RuleChain.class);
|
||||
RuleChainMetaData rootChainMetaData = objectMapper.treeToValue(rootChainJson.get("metadata"), RuleChainMetaData.class);
|
||||
|
||||
RuleChainId thermostatsRuleChainId = ruleChain.getId();
|
||||
rootChainMetaData.getRuleChainConnections().forEach(connection -> connection.setTargetRuleChainId(thermostatsRuleChainId));
|
||||
rootChain.setTenantId(tenantId);
|
||||
rootChain = ruleChainService.saveRuleChain(rootChain);
|
||||
rootChainMetaData.setRuleChainId(rootChain.getId());
|
||||
ruleChainService.saveRuleChainMetaData(new TenantId(EntityId.NULL_UUID), rootChainMetaData);
|
||||
} catch (Exception e) {
|
||||
log.error("Unable to load dashboard from json", e);
|
||||
throw new RuntimeException("Unable to load dashboard from json", e);
|
||||
}
|
||||
|
||||
try (DirectoryStream<Path> dirStream = Files.newDirectoryStream(ruleChainsDir, path -> path.toString().endsWith(JSON_EXT))) {
|
||||
dirStream.forEach(
|
||||
path -> {
|
||||
try {
|
||||
JsonNode ruleChainJson = objectMapper.readTree(path.toFile());
|
||||
RuleChain ruleChain = objectMapper.treeToValue(ruleChainJson.get("ruleChain"), RuleChain.class);
|
||||
RuleChainMetaData ruleChainMetaData = objectMapper.treeToValue(ruleChainJson.get("metadata"), RuleChainMetaData.class);
|
||||
|
||||
ruleChain.setTenantId(tenantId);
|
||||
if (ruleChain.getName().equals("Root Rule Chain")) {
|
||||
ruleChain.setRoot(true);
|
||||
}
|
||||
ruleChain = ruleChainService.saveRuleChain(ruleChain);
|
||||
|
||||
ruleChainMetaData.setRuleChainId(ruleChain.getId());
|
||||
ruleChainService.saveRuleChainMetaData(new TenantId(EntityId.NULL_UUID), ruleChainMetaData);
|
||||
} catch (Exception e) {
|
||||
log.error("Unable to load dashboard from json: [{}]", path.toString());
|
||||
throw new RuntimeException("Unable to load dashboard from json", e);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user