Browse Source

Merge branch 'master' of github.com:thingsboard/thingsboard into edqs

pull/12818/head
ViacheslavKlimov 1 year ago
parent
commit
2a72516106
  1. 9
      application/src/main/data/json/edge/rule_chains/edge_root_rule_chain.json
  2. 548
      application/src/main/data/json/system/scada_symbols/3-phase-voltage-relay-hp.svg
  3. 344
      application/src/main/data/json/system/scada_symbols/apartments-hp.svg
  4. 473
      application/src/main/data/json/system/scada_symbols/battery-hp.svg
  5. 346
      application/src/main/data/json/system/scada_symbols/bottom-light-bulb-hp.svg
  6. 346
      application/src/main/data/json/system/scada_symbols/consumers-hp.svg
  7. 444
      application/src/main/data/json/system/scada_symbols/curcuit-breaker-hp.svg
  8. 332
      application/src/main/data/json/system/scada_symbols/electrical-distribution-board-hp.svg
  9. 482
      application/src/main/data/json/system/scada_symbols/energy-meter-hp.svg
  10. 876
      application/src/main/data/json/system/scada_symbols/four-rate-energy-meter-hp.svg
  11. 359
      application/src/main/data/json/system/scada_symbols/fuel-generator-hp.svg
  12. 297
      application/src/main/data/json/system/scada_symbols/high-voltage-tower-hp.svg
  13. 439
      application/src/main/data/json/system/scada_symbols/horizontal-curcuit-breaker-hp.svg
  14. 378
      application/src/main/data/json/system/scada_symbols/horizontal-energy-system-controller-hp.svg
  15. 349
      application/src/main/data/json/system/scada_symbols/house-hp.svg
  16. 358
      application/src/main/data/json/system/scada_symbols/industrial-fuel-generator-hp.svg
  17. 578
      application/src/main/data/json/system/scada_symbols/inverter-hp.svg
  18. 578
      application/src/main/data/json/system/scada_symbols/large-inverter-hp.svg
  19. 278
      application/src/main/data/json/system/scada_symbols/low-voltage-tower-hp.svg
  20. 334
      application/src/main/data/json/system/scada_symbols/low-voltage-transformer-tower-hp.svg
  21. 344
      application/src/main/data/json/system/scada_symbols/manufacture-hp.svg
  22. 371
      application/src/main/data/json/system/scada_symbols/power-socket-hp.svg
  23. 359
      application/src/main/data/json/system/scada_symbols/power-transformer-hp.svg
  24. 373
      application/src/main/data/json/system/scada_symbols/single-key-switch-hp.svg
  25. 359
      application/src/main/data/json/system/scada_symbols/small-power-transformer-hp.svg
  26. 353
      application/src/main/data/json/system/scada_symbols/solar-panel-hp.svg
  27. 357
      application/src/main/data/json/system/scada_symbols/stand-solar-panel-hp.svg
  28. 747
      application/src/main/data/json/system/scada_symbols/three-rate-energy-meter-hp.svg
  29. 346
      application/src/main/data/json/system/scada_symbols/top-light-bulb-hp.svg
  30. 489
      application/src/main/data/json/system/scada_symbols/two-key-switch-hp.svg
  31. 618
      application/src/main/data/json/system/scada_symbols/two-rate-energy-meter-hp.svg
  32. 378
      application/src/main/data/json/system/scada_symbols/vertical-energy-system-controller-hp.svg
  33. 439
      application/src/main/data/json/system/scada_symbols/voltage-relay-hp.svg
  34. 584
      application/src/main/data/json/system/scada_symbols/voltage-stabilizer-hp.svg
  35. 370
      application/src/main/data/json/system/scada_symbols/wind-turbine-cluster-hp.svg
  36. 360
      application/src/main/data/json/system/scada_symbols/wind-turbine-hp.svg
  37. 6
      application/src/main/data/json/system/widget_bundles/general_high_performance_scada_symbols.json
  38. 48
      application/src/main/data/json/system/widget_bundles/high_performance_scada_energy_system.json
  39. 2
      application/src/main/data/json/system/widget_types/update_device_attribute.json
  40. 9
      application/src/main/data/json/tenant/device_profile/rule_chain_template.json
  41. 7
      application/src/main/data/json/tenant/rule_chains/root_rule_chain.json
  42. 228
      application/src/main/data/upgrade/basic/schema_update.sql
  43. 2
      application/src/main/java/org/thingsboard/server/actors/device/DeviceActorMessageProcessor.java
  44. 25
      application/src/main/java/org/thingsboard/server/config/SwaggerConfiguration.java
  45. 19
      application/src/main/java/org/thingsboard/server/install/ThingsboardInstallService.java
  46. 62
      application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/dashboard/BaseDashboardProcessor.java
  47. 6
      application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/dashboard/DashboardEdgeProcessor.java
  48. 3
      application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/dashboard/DashboardEdgeProcessorV1.java
  49. 3
      application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/resource/BaseResourceProcessor.java
  50. 8
      application/src/main/java/org/thingsboard/server/service/entitiy/dashboard/DashboardSyncService.java
  51. 2
      application/src/main/java/org/thingsboard/server/service/entitiy/entityview/DefaultTbEntityViewService.java
  52. 42
      application/src/main/java/org/thingsboard/server/service/install/DefaultDatabaseSchemaSettingsService.java
  53. 20
      application/src/main/java/org/thingsboard/server/service/install/InstallScripts.java
  54. 29
      application/src/main/java/org/thingsboard/server/service/install/ProjectInfo.java
  55. 4
      application/src/main/java/org/thingsboard/server/service/install/update/DefaultDataUpdateService.java
  56. 5
      application/src/main/java/org/thingsboard/server/service/rpc/DefaultTbRuleEngineRpcService.java
  57. 27
      application/src/main/java/org/thingsboard/server/service/telemetry/DefaultTelemetrySubscriptionService.java
  58. 90
      application/src/main/java/org/thingsboard/server/service/update/DeprecationService.java
  59. 2
      application/src/main/resources/thingsboard.yml
  60. 15
      application/src/test/java/org/thingsboard/server/edge/DashboardEdgeTest.java
  61. 76
      application/src/test/java/org/thingsboard/server/edge/ResourceEdgeTest.java
  62. 107
      application/src/test/java/org/thingsboard/server/service/entitiy/entityview/DefaultTbEntityViewServiceTest.java
  63. 373
      application/src/test/java/org/thingsboard/server/service/telemetry/DefaultTelemetrySubscriptionServiceTest.java
  64. 49
      common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/DefaultTransportMBeanConfiguration.java
  65. 188
      common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/HashMapObserver.java
  66. 38
      common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/HashMapObserverMBean.java
  67. 2
      common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/MqttTransportHandler.java
  68. 4
      common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/session/AbstractGatewayDeviceSessionContext.java
  69. 26
      common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/session/AbstractGatewaySessionHandler.java
  70. 2
      common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/session/GatewayDeviceSessionContext.java
  71. 2
      common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/session/MqttDeviceAwareSessionContext.java
  72. 6
      common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/service/DefaultTransportService.java
  73. 2
      common/version-control/src/main/java/org/thingsboard/server/service/sync/vc/GitRepository.java
  74. 19
      dao/src/main/java/org/thingsboard/server/dao/notification/DefaultNotifications.java
  75. 26
      monitoring/src/main/resources/root_rule_chain.json
  76. 8
      msa/black-box-tests/src/test/resources/MqttRuleNodeTestMetadata.json
  77. 2
      rule-engine/rule-engine-api/src/main/java/org/thingsboard/rule/engine/api/NotificationCenter.java
  78. 27
      rule-engine/rule-engine-api/src/main/java/org/thingsboard/rule/engine/api/TimeseriesSaveRequest.java
  79. 51
      rule-engine/rule-engine-api/src/test/java/org/thingsboard/rule/engine/api/TimeseriesSaveRequestTest.java
  80. 2
      rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rest/TbHttpClient.java
  81. 132
      rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/telemetry/TbMsgTimeseriesNode.java
  82. 66
      rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/telemetry/TbMsgTimeseriesNodeConfiguration.java
  83. 89
      rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/telemetry/strategy/DeduplicateProcessingStrategy.java
  84. 38
      rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/telemetry/strategy/OnEveryMessageProcessingStrategy.java
  85. 49
      rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/telemetry/strategy/ProcessingStrategy.java
  86. 38
      rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/telemetry/strategy/SkipProcessingStrategy.java
  87. 4
      rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/math/TbMathNodeTest.java
  88. 449
      rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/telemetry/TbMsgTimeseriesNodeTest.java
  89. 260
      rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/telemetry/strategy/DeduplicateProcessingStrategyTest.java
  90. 48
      rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/telemetry/strategy/OnEveryMessageProcessingStrategyTest.java
  91. 55
      rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/telemetry/strategy/ProcessingStrategyTest.java
  92. 48
      rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/telemetry/strategy/SkipProcessingStrategyTest.java
  93. 4
      ui-ngx/src/app/core/api/entity-data-subscription.ts
  94. 3
      ui-ngx/src/app/core/http/rule-chain.service.ts
  95. 42
      ui-ngx/src/app/core/http/widget.service.ts
  96. 5
      ui-ngx/src/app/core/services/resources.service.ts
  97. 2
      ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-object-list.component.ts
  98. 10
      ui-ngx/src/app/modules/home/components/rule-node/action/action-rule-node-config.module.ts
  99. 40
      ui-ngx/src/app/modules/home/components/rule-node/action/advanced-persistence-setting-row.component.html
  100. 114
      ui-ngx/src/app/modules/home/components/rule-node/action/advanced-persistence-setting-row.component.ts

9
application/src/main/data/json/edge/rule_chains/edge_root_rule_chain.json

@ -33,8 +33,13 @@
},
"type": "org.thingsboard.rule.engine.telemetry.TbMsgTimeseriesNode",
"name": "Save Timeseries",
"configurationVersion": 1,
"configuration": {
"defaultTTL": 0
"defaultTTL": 0,
"useServerTs": false,
"processingSettings": {
"type": "ON_EVERY_MESSAGE"
}
},
"externalId": null
},
@ -185,4 +190,4 @@
],
"ruleChainConnections": null
}
}
}

548
application/src/main/data/json/system/scada_symbols/3-phase-voltage-relay-hp.svg

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 25 KiB

344
application/src/main/data/json/system/scada_symbols/apartments-hp.svg

@ -0,0 +1,344 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:tb="https://thingsboard.io/svg" width="400" height="400" fill="none" version="1.1" viewBox="0 0 400 400"><tb:metadata xmlns=""><![CDATA[{
"title": "HP Apartments",
"description": "Apartments with various states.",
"searchTags": [
"power",
"energy",
"consumer"
],
"widgetSizeX": 2,
"widgetSizeY": 2,
"tags": [
{
"tag": "background",
"stateRenderFunction": "var color = ctx.properties.stoppedColor;\nif (ctx.values.running) {\n color = ctx.properties.runningColor;\n}\nelement.attr({fill: color});",
"actions": null
},
{
"tag": "clickArea",
"stateRenderFunction": null,
"actions": {
"click": {
"actionFunction": "ctx.api.callAction(event, 'click');"
}
}
},
{
"tag": "critical",
"stateRenderFunction": "element.attr({fill: ctx.properties.criticalColor});\nif (ctx.values.critical) {\n element.show();\n} else {\n element.hide();\n}\n\nvar elementCriticalAnimation = element.remember('criticalAnimation');\nvar criticalAnimation = ctx.values.critical && ctx.values.criticalAnimation;\n\nif (elementCriticalAnimation !== criticalAnimation) {\n element.remember('criticalAnimation', criticalAnimation);\n if (criticalAnimation) {\n ctx.api.cssAnimate(element, 500).attr({opacity: 0.15}).loop(0, true);\n } else {\n ctx.api.resetCssAnimation(element);\n }\n}\n\n",
"actions": {
"click": {
"actionFunction": "ctx.api.callAction(event, 'criticalClick');"
}
}
},
{
"tag": "warning",
"stateRenderFunction": "element.attr({fill: ctx.properties.warningColor});\nvar warning = ctx.values.warning && !(ctx.values.warning && ctx.values.critical)\nif (warning) {\n element.show();\n} else {\n element.hide();\n}\n\nvar elementCriticalAnimation = element.remember('criticalAnimation');\nvar criticalAnimation = warning && ctx.values.criticalAnimation;\n\nif (elementCriticalAnimation !== criticalAnimation) {\n element.remember('criticalAnimation', criticalAnimation);\n if (criticalAnimation) {\n ctx.api.cssAnimate(element, 500).attr({opacity: 0.15}).loop(0, true);\n } else {\n ctx.api.resetCssAnimation(element);\n }\n}\n",
"actions": {
"click": {
"actionFunction": "ctx.api.callAction(event, 'warningClick');"
}
}
}
],
"behavior": [
{
"id": "running",
"name": "{i18n:scada.symbol.running}",
"hint": "{i18n:scada.symbol.running-hint}",
"group": null,
"type": "value",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": "{i18n:scada.symbol.running}",
"defaultGetValueSettings": {
"action": "GET_ATTRIBUTE",
"defaultValue": false,
"executeRpc": {
"method": "getState",
"requestTimeout": 5000,
"requestPersistent": false,
"persistentPollingInterval": 1000
},
"getAttribute": {
"scope": "SHARED_SCOPE",
"key": "running"
},
"getTimeSeries": {
"key": "state"
},
"getAlarmStatus": {
"severityList": null,
"typeList": null
},
"dataToValue": {
"type": "NONE",
"dataToValueFunction": "/* Should return boolean value */\nreturn data;",
"compareToValue": true
}
},
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": null
},
{
"id": "warning",
"name": "{i18n:scada.symbol.warning}",
"hint": "{i18n:scada.symbol.warning-state-hint}",
"group": "{i18n:scada.symbol.warning-state}",
"type": "value",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": "{i18n:scada.symbol.warning}",
"defaultGetValueSettings": {
"action": "GET_ALARM_STATUS",
"defaultValue": false,
"executeRpc": {
"method": "getState",
"requestTimeout": 5000,
"requestPersistent": false,
"persistentPollingInterval": 1000
},
"getAttribute": {
"scope": null,
"key": "state"
},
"getTimeSeries": {
"key": "state"
},
"getAlarmStatus": {
"severityList": [
"MAJOR",
"MINOR",
"WARNING",
"INDETERMINATE"
],
"typeList": null
},
"dataToValue": {
"type": "NONE",
"dataToValueFunction": "/* Should return boolean value */\nreturn data;",
"compareToValue": true
}
},
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": null
},
{
"id": "warningClick",
"name": "{i18n:scada.symbol.warning-click}",
"hint": "{i18n:scada.symbol.on-click-hint}",
"group": "{i18n:scada.symbol.warning-state}",
"type": "widgetAction",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": null,
"defaultGetValueSettings": null,
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": {
"type": "doNothing",
"targetDashboardStateId": null,
"openRightLayout": false,
"setEntityId": false,
"stateEntityParamName": null
}
},
{
"id": "critical",
"name": "{i18n:scada.symbol.critical}",
"hint": "{i18n:scada.symbol.critical-state-hint}",
"group": "{i18n:scada.symbol.critical-state}",
"type": "value",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": "{i18n:scada.symbol.critical}",
"defaultGetValueSettings": {
"action": "GET_ALARM_STATUS",
"defaultValue": false,
"executeRpc": {
"method": "getState",
"requestTimeout": 5000,
"requestPersistent": false,
"persistentPollingInterval": 1000
},
"getAttribute": {
"scope": null,
"key": "state"
},
"getTimeSeries": {
"key": "state"
},
"getAlarmStatus": {
"severityList": [
"CRITICAL"
],
"typeList": null
},
"dataToValue": {
"type": "NONE",
"dataToValueFunction": "/* Should return boolean value */\nreturn data;",
"compareToValue": true
}
},
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": null
},
{
"id": "criticalClick",
"name": "{i18n:scada.symbol.critical-click}",
"hint": "{i18n:scada.symbol.on-click-hint}",
"group": "{i18n:scada.symbol.critical-state}",
"type": "widgetAction",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": null,
"defaultGetValueSettings": null,
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": {
"type": "doNothing",
"targetDashboardStateId": null,
"openRightLayout": false,
"setEntityId": false,
"stateEntityParamName": null
}
},
{
"id": "criticalAnimation",
"name": "{i18n:scada.symbol.warning-critical-state-animation}",
"hint": "{i18n:scada.symbol.warning-critical-state-animation-hint}",
"group": null,
"type": "value",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": "{i18n:scada.symbol.animation}",
"defaultGetValueSettings": {
"action": "DO_NOTHING",
"defaultValue": false,
"executeRpc": {
"method": "getState",
"requestTimeout": 5000,
"requestPersistent": false,
"persistentPollingInterval": 1000
},
"getAttribute": {
"key": "state",
"scope": null
},
"getTimeSeries": {
"key": "state"
},
"dataToValue": {
"type": "NONE",
"compareToValue": true,
"dataToValueFunction": "/* Should return boolean value */\nreturn data;"
}
},
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": null
},
{
"id": "click",
"name": "{i18n:scada.symbol.on-click}",
"hint": "{i18n:scada.symbol.on-click-hint}",
"group": null,
"type": "widgetAction",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": null,
"defaultGetValueSettings": null,
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": {
"type": "doNothing",
"targetDashboardStateId": null,
"openRightLayout": false,
"setEntityId": false,
"stateEntityParamName": null
}
}
],
"properties": [
{
"id": "runningColor",
"name": "{i18n:scada.symbol.colors}",
"type": "color",
"default": "#FFFFFF",
"required": null,
"subLabel": "{i18n:scada.symbol.running}",
"divider": true,
"fieldSuffix": null,
"disableOnProperty": null,
"rowClass": "",
"fieldClass": "",
"min": null,
"max": null,
"step": null
},
{
"id": "stoppedColor",
"name": "{i18n:scada.symbol.colors}",
"type": "color",
"default": "#666666",
"required": null,
"subLabel": "{i18n:scada.symbol.stopped}",
"divider": null,
"fieldSuffix": null,
"disableOnProperty": null,
"rowClass": "",
"fieldClass": "",
"min": null,
"max": null,
"step": null
},
{
"id": "warningColor",
"name": "{i18n:scada.symbol.alarm-colors}",
"type": "color",
"default": "#FAA405",
"required": null,
"subLabel": "{i18n:scada.symbol.warning}",
"divider": true,
"fieldSuffix": null,
"disableOnProperty": null,
"rowClass": "",
"fieldClass": "",
"min": null,
"max": null,
"step": null
},
{
"id": "criticalColor",
"name": "{i18n:scada.symbol.alarm-colors}",
"type": "color",
"default": "#D12730",
"required": null,
"subLabel": "{i18n:scada.symbol.critical}",
"divider": null,
"fieldSuffix": null,
"disableOnProperty": null,
"rowClass": "",
"fieldClass": "",
"min": null,
"max": null,
"step": null
}
]
}]]></tb:metadata>
<path d="m25 106c0-2.761 2.2386-5 5-5h210c2.761 0 5 2.239 5 5v266c0 2.761-2.239 5-5 5h-210c-2.7614 0-5-2.239-5-5v-266z" fill="#fff" stroke="#1A1A1A" stroke-width="2" tb:tag="background"/><rect x="143" y="146" width="86" height="36" rx="1" fill="#999" stroke="#1A1A1A" stroke-width="2"/><rect x="143" y="254" width="86" height="36" rx="1" fill="#999" stroke="#1A1A1A" stroke-width="2"/><rect x="143" y="200" width="86" height="36" rx="1" fill="#999" stroke="#1A1A1A" stroke-width="2"/><rect x="143" y="308" width="86" height="36" rx="1" fill="#999" stroke="#1A1A1A" stroke-width="2"/><path d="m155 6c0-2.7614 2.239-5 5-5h210c2.761 0 5 2.2386 5 5v366c0 2.761-2.239 5-5 5h-210c-2.761 0-5-2.239-5-5v-366z" fill="#fff" stroke="#1A1A1A" stroke-width="2" tb:tag="background"/><rect x="269" y="57" width="86" height="36" rx="1" fill="#999" stroke="#1A1A1A" stroke-width="2"/><rect x="269" y="165" width="86" height="36" rx="1" fill="#999" stroke="#1A1A1A" stroke-width="2"/><rect x="269" y="111" width="86" height="36" rx="1" fill="#999" stroke="#1A1A1A" stroke-width="2"/><rect x="269" y="219" width="86" height="36" rx="1" fill="#999" stroke="#1A1A1A" stroke-width="2"/><rect x="175" y="57" width="86" height="36" rx="1" fill="#999" stroke="#1A1A1A" stroke-width="2"/><rect x="175" y="165" width="86" height="36" rx="1" fill="#999" stroke="#1A1A1A" stroke-width="2"/><rect x="175" y="111" width="86" height="36" rx="1" fill="#999" stroke="#1A1A1A" stroke-width="2"/><rect x="175" y="219" width="86" height="36" rx="1" fill="#999" stroke="#1A1A1A" stroke-width="2"/><rect x="216" y="286" width="98" height="91" rx="1" fill="#999" stroke="#1A1A1A" stroke-width="2"/><rect x="49" y="146" width="86" height="36" rx="1" fill="#999" stroke="#1A1A1A" stroke-width="2"/><rect x="49" y="254" width="86" height="36" rx="1" fill="#999" stroke="#1A1A1A" stroke-width="2"/><rect x="49" y="200" width="86" height="36" rx="1" fill="#999" stroke="#1A1A1A" stroke-width="2"/><rect x="49" y="308" width="86" height="36" rx="1" fill="#999" stroke="#1A1A1A" stroke-width="2"/><rect x="1" y="377" width="398" height="22" rx="5" fill="#fff" stroke="#1A1A1A" stroke-width="2" tb:tag="background"/><path d="m134.53 0s-134.53 0-134.53 67v328.36c0 2.6512 3.5818 4.6403 8 4.6403h384c4.418 0 8-1.9892 8-4.6403v-328.36c0-67-132.14-67-132.14-67h-67.86zm134.14 81.2c-2.5774 0-4.6666 1.2536-4.6666 2.8v300.4c0 1.5464 2.0894 2.8 4.6666 2.8h29.332c2.5774 0 4.6666-1.2536 4.6666-2.8v-300.4c0-1.5464-2.0894-2.8-4.6666-2.8z" fill-opacity="0" style="stroke-width:1.4784" tb:tag="clickArea"/><g transform="translate(0,316)" fill="#d12730" style="display: none;" tb:tag="critical">
<rect width="84" height="84" rx="4" fill="#fff" style=""/>
<rect width="84" height="84" rx="4" style=""/>
<rect x="2" y="2" width="80" height="80" rx="2" stroke="#000" stroke-opacity=".87" stroke-width="4" style=""/>
<path d="m44.559 27.562-0.4688 20.059h-4.0234l-0.4883-20.059zm-5.1172 26.211c0-0.7161 0.2344-1.3151 0.7031-1.7968 0.4818-0.4948 1.1459-0.7422 1.9922-0.7422 0.8334 0 1.4909 0.2474 1.9727 0.7422 0.4817 0.4817 0.7226 1.0807 0.7226 1.7968 0 0.6901-0.2409 1.2826-0.7226 1.7774-0.4818 0.4818-1.1393 0.7226-1.9727 0.7226-0.8463 0-1.5104-0.2408-1.9922-0.7226-0.4687-0.4948-0.7031-1.0873-0.7031-1.7774z" fill="#000" fill-opacity=".87" style=""/>
</g><g transform="translate(0 320.94)" fill="#faa405" style="display: none;" tb:tag="warning">
<path d="m35.955 2.2112c1.4741-2.9482 5.6813-2.9482 7.1554 0l35.528 71.056c1.3298 2.6596-0.6042 5.7889-3.5777 5.7889h-71.056c-2.9735 0-4.9075-3.1292-3.5777-5.7889z" fill="#fff" style=""/>
<path d="m35.955 2.2112c1.4741-2.9482 5.6813-2.9482 7.1554 0l35.528 71.056c1.3298 2.6596-0.6042 5.7889-3.5777 5.7889h-71.056c-2.9735 0-4.9075-3.1292-3.5777-5.7889z" style=""/>
<path d="m37.72 3.1061c0.7371-1.4741 2.8407-1.4741 3.5778-1e-5l35.528 71.056c0.6649 1.3298-0.3021 2.8944-1.7888 2.8944h-71.056c-1.4868 0-2.4538-1.5646-1.7889-2.8944z" stroke="#000" stroke-opacity=".87" stroke-width="4" style=""/>
<path d="m42.092 32.618-0.4688 20.059h-4.0234l-0.4883-20.059zm-5.1172 26.211c0-0.7161 0.2344-1.3151 0.7031-1.7968 0.4818-0.4948 1.1459-0.7422 1.9922-0.7422 0.8334 0 1.4909 0.2474 1.9727 0.7422 0.4817 0.4817 0.7226 1.0807 0.7226 1.7968 0 0.6901-0.2409 1.2826-0.7226 1.7774-0.4818 0.4818-1.1393 0.7226-1.9727 0.7226-0.8463 0-1.5104-0.2408-1.9922-0.7226-0.4687-0.4948-0.7031-1.0873-0.7031-1.7774z" fill="#000" fill-opacity=".87" style=""/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 15 KiB

473
application/src/main/data/json/system/scada_symbols/battery-hp.svg

@ -0,0 +1,473 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:tb="https://thingsboard.io/svg" width="600" height="200" fill="none" version="1.1" viewBox="0 0 600 200"><tb:metadata xmlns=""><![CDATA[{
"title": "HP Battery",
"description": "Battery with various states and scalable quantity.",
"searchTags": [
"energy",
"power",
"rechargeable",
"storage",
"lithium-ion",
"ev"
],
"widgetSizeX": 3,
"widgetSizeY": 1,
"tags": [
{
"tag": "background",
"stateRenderFunction": "var color = ctx.properties.stoppedColor;\nif (ctx.values.running) {\n color = ctx.properties.runningColor;\n}\nelement.attr({fill: color});",
"actions": null
},
{
"tag": "clickArea",
"stateRenderFunction": null,
"actions": {
"click": {
"actionFunction": "ctx.api.callAction(event, 'click');"
}
}
},
{
"tag": "critical",
"stateRenderFunction": "element.attr({fill: ctx.properties.criticalColor});\nif (ctx.values.critical) {\n element.show();\n} else {\n element.hide();\n}\n\nvar elementCriticalAnimation = element.remember('criticalAnimation');\nvar criticalAnimation = ctx.values.critical && ctx.values.criticalAnimation;\n\nif (elementCriticalAnimation !== criticalAnimation) {\n element.remember('criticalAnimation', criticalAnimation);\n if (criticalAnimation) {\n ctx.api.cssAnimate(element, 500).attr({opacity: 0.15}).loop(0, true);\n } else {\n ctx.api.resetCssAnimation(element);\n }\n}\n\n",
"actions": {
"click": {
"actionFunction": "ctx.api.callAction(event, 'criticalClick');"
}
}
},
{
"tag": "indicator",
"stateRenderFunction": "if (ctx.values.running) {\n element.fill(ctx.properties.runningIndicatorColor);\n} else {\n element.fill(ctx.properties.stoppedIndicatorColor);\n}",
"actions": null
},
{
"tag": "label",
"stateRenderFunction": "ctx.api.font(element, ctx.properties.labelFont, ctx.properties.labelColor);\nctx.api.text(element, ctx.properties.label);",
"actions": null
},
{
"tag": "left-bottom-connector",
"stateRenderFunction": "if (!ctx.properties.leftBottomConnector) {\n element.hide();\n}",
"actions": null
},
{
"tag": "left-connector",
"stateRenderFunction": "if (!ctx.properties.leftConnector) {\n element.hide();\n}",
"actions": null
},
{
"tag": "left-top-connector",
"stateRenderFunction": "if (!ctx.properties.leftTopConnector) {\n element.hide();\n}",
"actions": null
},
{
"tag": "right-bottom-connector",
"stateRenderFunction": "if (!ctx.properties.rightBottomConnector) {\n element.hide();\n}",
"actions": null
},
{
"tag": "right-connector",
"stateRenderFunction": "if (!ctx.properties.rightConnector) {\n element.hide();\n}",
"actions": null
},
{
"tag": "right-top-connector",
"stateRenderFunction": "if (!ctx.properties.rightTopConnector) {\n element.hide();\n}",
"actions": null
},
{
"tag": "warning",
"stateRenderFunction": "element.attr({fill: ctx.properties.warningColor});\nvar warning = ctx.values.warning && !(ctx.values.warning && ctx.values.critical)\nif (warning) {\n element.show();\n} else {\n element.hide();\n}\n\nvar elementCriticalAnimation = element.remember('criticalAnimation');\nvar criticalAnimation = warning && ctx.values.criticalAnimation;\n\nif (elementCriticalAnimation !== criticalAnimation) {\n element.remember('criticalAnimation', criticalAnimation);\n if (criticalAnimation) {\n ctx.api.cssAnimate(element, 500).attr({opacity: 0.15}).loop(0, true);\n } else {\n ctx.api.resetCssAnimation(element);\n }\n}\n",
"actions": {
"click": {
"actionFunction": "ctx.api.callAction(event, 'warningClick');"
}
}
}
],
"behavior": [
{
"id": "running",
"name": "{i18n:scada.symbol.running}",
"hint": "{i18n:scada.symbol.running-hint}",
"group": null,
"type": "value",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": "{i18n:scada.symbol.running}",
"defaultGetValueSettings": {
"action": "GET_ATTRIBUTE",
"defaultValue": false,
"executeRpc": {
"method": "getState",
"requestTimeout": 5000,
"requestPersistent": false,
"persistentPollingInterval": 1000
},
"getAttribute": {
"scope": "SHARED_SCOPE",
"key": "running"
},
"getTimeSeries": {
"key": "state"
},
"getAlarmStatus": {
"severityList": null,
"typeList": null
},
"dataToValue": {
"type": "NONE",
"dataToValueFunction": "/* Should return boolean value */\nreturn data;",
"compareToValue": true
}
},
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": null
},
{
"id": "warning",
"name": "{i18n:scada.symbol.warning}",
"hint": "{i18n:scada.symbol.warning-state-hint}",
"group": "{i18n:scada.symbol.warning-state}",
"type": "value",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": "{i18n:scada.symbol.warning}",
"defaultGetValueSettings": {
"action": "GET_ALARM_STATUS",
"defaultValue": false,
"executeRpc": {
"method": "getState",
"requestTimeout": 5000,
"requestPersistent": false,
"persistentPollingInterval": 1000
},
"getAttribute": {
"scope": null,
"key": "state"
},
"getTimeSeries": {
"key": "state"
},
"getAlarmStatus": {
"severityList": [
"MAJOR",
"MINOR",
"WARNING",
"INDETERMINATE"
],
"typeList": null
},
"dataToValue": {
"type": "NONE",
"dataToValueFunction": "/* Should return boolean value */\nreturn data;",
"compareToValue": true
}
},
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": null
},
{
"id": "warningClick",
"name": "{i18n:scada.symbol.warning-click}",
"hint": "{i18n:scada.symbol.on-click-hint}",
"group": "{i18n:scada.symbol.warning-state}",
"type": "widgetAction",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": null,
"defaultGetValueSettings": null,
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": {
"type": "doNothing",
"targetDashboardStateId": null,
"openRightLayout": false,
"setEntityId": false,
"stateEntityParamName": null
}
},
{
"id": "critical",
"name": "{i18n:scada.symbol.critical}",
"hint": "{i18n:scada.symbol.critical-state-hint}",
"group": "{i18n:scada.symbol.critical-state}",
"type": "value",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": "{i18n:scada.symbol.critical}",
"defaultGetValueSettings": {
"action": "GET_ALARM_STATUS",
"defaultValue": false,
"executeRpc": {
"method": "getState",
"requestTimeout": 5000,
"requestPersistent": false,
"persistentPollingInterval": 1000
},
"getAttribute": {
"scope": null,
"key": "state"
},
"getTimeSeries": {
"key": "state"
},
"getAlarmStatus": {
"severityList": [
"CRITICAL"
],
"typeList": null
},
"dataToValue": {
"type": "NONE",
"dataToValueFunction": "/* Should return boolean value */\nreturn data;",
"compareToValue": true
}
},
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": null
},
{
"id": "criticalClick",
"name": "{i18n:scada.symbol.critical-click}",
"hint": "{i18n:scada.symbol.on-click-hint}",
"group": "{i18n:scada.symbol.critical-state}",
"type": "widgetAction",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": null,
"defaultGetValueSettings": null,
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": {
"type": "doNothing",
"targetDashboardStateId": null,
"openRightLayout": false,
"setEntityId": false,
"stateEntityParamName": null
}
},
{
"id": "criticalAnimation",
"name": "{i18n:scada.symbol.warning-critical-state-animation}",
"hint": "{i18n:scada.symbol.warning-critical-state-animation-hint}",
"group": null,
"type": "value",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": "{i18n:scada.symbol.animation}",
"defaultGetValueSettings": {
"action": "DO_NOTHING",
"defaultValue": false,
"executeRpc": {
"method": "getState",
"requestTimeout": 5000,
"requestPersistent": false,
"persistentPollingInterval": 1000
},
"getAttribute": {
"key": "state",
"scope": null
},
"getTimeSeries": {
"key": "state"
},
"dataToValue": {
"type": "NONE",
"compareToValue": true,
"dataToValueFunction": "/* Should return boolean value */\nreturn data;"
}
},
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": null
},
{
"id": "click",
"name": "{i18n:scada.symbol.on-click}",
"hint": "{i18n:scada.symbol.on-click-hint}",
"group": null,
"type": "widgetAction",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": null,
"defaultGetValueSettings": null,
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": {
"type": "doNothing",
"targetDashboardStateId": null,
"openRightLayout": false,
"setEntityId": false,
"stateEntityParamName": null
}
}
],
"properties": [
{
"id": "runningColor",
"name": "{i18n:scada.symbol.colors}",
"type": "color",
"default": "#FFFFFF",
"subLabel": "{i18n:scada.symbol.running}",
"divider": true,
"disabled": false,
"visible": true
},
{
"id": "stoppedColor",
"name": "{i18n:scada.symbol.colors}",
"type": "color",
"default": "#666666",
"subLabel": "{i18n:scada.symbol.stopped}",
"disabled": false,
"visible": true
},
{
"id": "warningColor",
"name": "{i18n:scada.symbol.alarm-colors}",
"type": "color",
"default": "#FAA405",
"subLabel": "{i18n:scada.symbol.warning}",
"divider": true,
"disabled": false,
"visible": true
},
{
"id": "criticalColor",
"name": "{i18n:scada.symbol.alarm-colors}",
"type": "color",
"default": "#D12730",
"subLabel": "{i18n:scada.symbol.critical}",
"disabled": false,
"visible": true
},
{
"id": "runningIndicatorColor",
"name": "{i18n:scada.symbol.indicator-colors}",
"type": "color",
"default": "#198038",
"subLabel": "{i18n:scada.symbol.running}",
"divider": true,
"disabled": false,
"visible": true
},
{
"id": "stoppedIndicatorColor",
"name": "{i18n:scada.symbol.indicator-colors}",
"type": "color",
"default": "#DEDEDE",
"subLabel": "{i18n:scada.symbol.stopped}",
"disabled": false,
"visible": true
},
{
"id": "label",
"name": "{i18n:scada.symbol.label}",
"type": "text",
"default": "ON",
"fieldClass": "medium-width",
"disabled": false,
"visible": true
},
{
"id": "labelFont",
"name": "{i18n:scada.symbol.label}",
"type": "font",
"default": {
"size": 30,
"sizeUnit": "px",
"family": "Roboto",
"weight": "400",
"style": "normal"
},
"disabled": false,
"visible": true
},
{
"id": "labelColor",
"name": "{i18n:scada.symbol.label}",
"type": "color",
"default": "#1A1A1A",
"disabled": false,
"visible": true
},
{
"id": "leftConnector",
"name": "{i18n:scada.symbol.left-connector}",
"group": "{i18n:scada.symbol.connectors-positions}",
"type": "switch",
"default": false,
"disabled": false,
"visible": true
},
{
"id": "leftTopConnector",
"name": "{i18n:scada.symbol.left-top-connector}",
"group": "{i18n:scada.symbol.connectors-positions}",
"type": "switch",
"default": false,
"disabled": false,
"visible": true
},
{
"id": "leftBottomConnector",
"name": "{i18n:scada.symbol.left-bottom-connector}",
"group": "{i18n:scada.symbol.connectors-positions}",
"type": "switch",
"default": false,
"disabled": false,
"visible": true
},
{
"id": "rightConnector",
"name": "{i18n:scada.symbol.right-connector}",
"group": "{i18n:scada.symbol.connectors-positions}",
"type": "switch",
"default": false,
"disabled": false,
"visible": true
},
{
"id": "rightTopConnector",
"name": "{i18n:scada.symbol.right-top-connector}",
"group": "{i18n:scada.symbol.connectors-positions}",
"type": "switch",
"default": false,
"disabled": false,
"visible": true
},
{
"id": "rightBottomConnector",
"name": "{i18n:scada.symbol.right-bottom-connector}",
"group": "{i18n:scada.symbol.connectors-positions}",
"type": "switch",
"default": false,
"disabled": false,
"visible": true
}
]
}]]></tb:metadata>
<g fill="#fff" tb:tag="background">
<rect x="1" y="41" width="598" height="120" rx="6" stroke="#000" stroke-width="2"/>
<circle cx="468" cy="102.5" r="12"/>
<circle cx="468" cy="101.5" r="11" stroke="#000" stroke-opacity=".87" stroke-width="2"/>
<circle cx="84" cy="101.5" r="11" stroke="#1a1a1a" stroke-width="2"/>
<circle cx="516" cy="102.5" r="12"/>
<circle cx="516" cy="101.5" r="11" stroke="#000" stroke-opacity=".87" stroke-width="2"/>
<circle cx="132" cy="101.5" r="11" stroke="#1a1a1a" stroke-width="2"/>
</g><circle cx="204" cy="102" r="10" fill="#198038" tb:tag="indicator"/><text x="221" y="105.37933" fill="#000000" font-family="Roboto" font-size="30px" font-weight="400" tb:tag="label" xml:space="preserve"><tspan dominant-baseline="middle">ON</tspan></text><path d="m103 200h-6s7.858-27.047 14-44c6.324-17.455 18-44 18-44h6s-11.676 26.545-18 44c-6.142 16.953-14 44-14 44z" fill="#1a1a1a" tb:tag="left-bottom-connector"/><path d="m103 0h-6s-6.4394 26.077-9.5 43c-3.2977 18.234-6.5 47-6.5 47h6s2.7023-26.766 6-45c3.0606-16.923 10-45 10-45z" fill="#1a1a1a" tb:tag="left-top-connector"/><path d="m497 0h6s6.439 26.077 9.5 43c3.298 18.234 6.5 47 6.5 47h-6s-2.702-26.766-6-45c-3.061-16.923-10-45-10-45z" fill="#1a1a1a" tb:tag="right-top-connector"/><path d="m0 100h73" stroke="#1a1a1a" stroke-width="6" tb:tag="left-connector"/><path d="m527 100h73" stroke="#1a1a1a" stroke-width="6" tb:tag="right-connector"/><path d="m497 200h6s-7.858-27.047-14-44c-6.324-17.455-18-44-18-44h-6s11.676 26.545 18 44c6.142 16.953 14 44 14 44z" fill="#1a1a1a" tb:tag="right-bottom-connector"/><path d="m201.8 40s-201.8 0-201.8 20.435v100.15c0 0.80861 5.3727 1.4153 12 1.4153h576c6.627 0 12-0.60671 12-1.4153v-100.15c0-20.435-198.21-20.435-198.21-20.435h-101.79zm201.21 24.766c-3.8661 0-6.9999 0.38235-6.9999 0.854v91.622c0 0.47165 3.1341 0.854 6.9999 0.854h43.998c3.8661 0 6.9999-0.38235 6.9999-0.854v-91.622c0-0.47165-3.1341-0.854-6.9999-0.854z" fill="#000" fill-opacity="0" tb:tag="clickArea"/><g fill="#d12730" style="display: none;" tb:tag="critical">
<rect width="84" height="84" rx="4" fill="#fff" style=""/>
<rect width="84" height="84" rx="4" style=""/>
<rect x="2" y="2" width="80" height="80" rx="2" stroke="#000" stroke-opacity=".87" stroke-width="4" style=""/>
<path d="m44.559 27.562-0.4688 20.059h-4.0234l-0.4883-20.059zm-5.1172 26.211c0-0.7161 0.2344-1.3151 0.7031-1.7968 0.4818-0.4948 1.1459-0.7422 1.9922-0.7422 0.8334 0 1.4909 0.2474 1.9727 0.7422 0.4817 0.4817 0.7226 1.0807 0.7226 1.7968 0 0.6901-0.2409 1.2826-0.7226 1.7774-0.4818 0.4818-1.1393 0.7226-1.9727 0.7226-0.8463 0-1.5104-0.2408-1.9922-0.7226-0.4687-0.4948-0.7031-1.0873-0.7031-1.7774z" fill="#000" fill-opacity=".87" style=""/>
</g><g fill="#faa405" style="display: none;" tb:tag="warning">
<path d="m35.955 2.2112c1.4741-2.9482 5.6813-2.9482 7.1554 0l35.528 71.056c1.3298 2.6596-0.6042 5.7889-3.5777 5.7889h-71.056c-2.9735 0-4.9075-3.1292-3.5777-5.7889z" fill="#fff" style=""/>
<path d="m35.955 2.2112c1.4741-2.9482 5.6813-2.9482 7.1554 0l35.528 71.056c1.3298 2.6596-0.6042 5.7889-3.5777 5.7889h-71.056c-2.9735 0-4.9075-3.1292-3.5777-5.7889z" style=""/>
<path d="m37.72 3.1061c0.7371-1.4741 2.8407-1.4741 3.5778-1e-5l35.528 71.056c0.6649 1.3298-0.3021 2.8944-1.7888 2.8944h-71.056c-1.4868 0-2.4538-1.5646-1.7889-2.8944z" stroke="#000" stroke-opacity=".87" stroke-width="4" style=""/>
<path d="m42.092 32.618-0.4688 20.059h-4.0234l-0.4883-20.059zm-5.1172 26.211c0-0.7161 0.2344-1.3151 0.7031-1.7968 0.4818-0.4948 1.1459-0.7422 1.9922-0.7422 0.8334 0 1.4909 0.2474 1.9727 0.7422 0.4817 0.4817 0.7226 1.0807 0.7226 1.7968 0 0.6901-0.2409 1.2826-0.7226 1.7774-0.4818 0.4818-1.1393 0.7226-1.9727 0.7226-0.8463 0-1.5104-0.2408-1.9922-0.7226-0.4687-0.4948-0.7031-1.0873-0.7031-1.7774z" fill="#000" fill-opacity=".87" style=""/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 18 KiB

346
application/src/main/data/json/system/scada_symbols/bottom-light-bulb-hp.svg

@ -0,0 +1,346 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:tb="https://thingsboard.io/svg" width="200" height="200" fill="none" version="1.1" viewBox="0 0 200 200"><tb:metadata xmlns=""><![CDATA[{
"title": "HP Bottom light bulb",
"description": "Bottom light bulb with various states.",
"searchTags": [
"energy"
],
"widgetSizeX": 1,
"widgetSizeY": 1,
"tags": [
{
"tag": "background",
"stateRenderFunction": "var color = ctx.properties.stoppedColor;\nif (ctx.values.running) {\n color = ctx.properties.runningColor;\n}\nelement.attr({fill: color});",
"actions": null
},
{
"tag": "clickArea",
"stateRenderFunction": null,
"actions": {
"click": {
"actionFunction": "ctx.api.callAction(event, 'click');"
}
}
},
{
"tag": "critical",
"stateRenderFunction": "element.attr({fill: ctx.properties.criticalColor});\nif (ctx.values.critical) {\n element.show();\n} else {\n element.hide();\n}\n\nvar elementCriticalAnimation = element.remember('criticalAnimation');\nvar criticalAnimation = ctx.values.critical && ctx.values.criticalAnimation;\n\nif (elementCriticalAnimation !== criticalAnimation) {\n element.remember('criticalAnimation', criticalAnimation);\n if (criticalAnimation) {\n ctx.api.cssAnimate(element, 500).attr({opacity: 0.15}).loop(0, true);\n } else {\n ctx.api.resetCssAnimation(element);\n }\n}\n\n",
"actions": {
"click": {
"actionFunction": "ctx.api.callAction(event, 'criticalClick');"
}
}
},
{
"tag": "warning",
"stateRenderFunction": "element.attr({fill: ctx.properties.warningColor});\nvar warning = ctx.values.warning && !(ctx.values.warning && ctx.values.critical)\nif (warning) {\n element.show();\n} else {\n element.hide();\n}\n\nvar elementCriticalAnimation = element.remember('criticalAnimation');\nvar criticalAnimation = warning && ctx.values.criticalAnimation;\n\nif (elementCriticalAnimation !== criticalAnimation) {\n element.remember('criticalAnimation', criticalAnimation);\n if (criticalAnimation) {\n ctx.api.cssAnimate(element, 500).attr({opacity: 0.15}).loop(0, true);\n } else {\n ctx.api.resetCssAnimation(element);\n }\n}\n",
"actions": {
"click": {
"actionFunction": "ctx.api.callAction(event, 'warningClick');"
}
}
}
],
"behavior": [
{
"id": "running",
"name": "{i18n:scada.symbol.running}",
"hint": "{i18n:scada.symbol.running-hint}",
"group": null,
"type": "value",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": "{i18n:scada.symbol.running}",
"defaultGetValueSettings": {
"action": "GET_ATTRIBUTE",
"defaultValue": false,
"executeRpc": {
"method": "getState",
"requestTimeout": 5000,
"requestPersistent": false,
"persistentPollingInterval": 1000
},
"getAttribute": {
"scope": "SHARED_SCOPE",
"key": "running"
},
"getTimeSeries": {
"key": "state"
},
"getAlarmStatus": {
"severityList": null,
"typeList": null
},
"dataToValue": {
"type": "NONE",
"dataToValueFunction": "/* Should return boolean value */\nreturn data;",
"compareToValue": true
}
},
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": null
},
{
"id": "warning",
"name": "{i18n:scada.symbol.warning}",
"hint": "{i18n:scada.symbol.warning-state-hint}",
"group": "{i18n:scada.symbol.warning-state}",
"type": "value",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": "{i18n:scada.symbol.warning}",
"defaultGetValueSettings": {
"action": "GET_ALARM_STATUS",
"defaultValue": false,
"executeRpc": {
"method": "getState",
"requestTimeout": 5000,
"requestPersistent": false,
"persistentPollingInterval": 1000
},
"getAttribute": {
"scope": null,
"key": "state"
},
"getTimeSeries": {
"key": "state"
},
"getAlarmStatus": {
"severityList": [
"MAJOR",
"MINOR",
"WARNING",
"INDETERMINATE"
],
"typeList": null
},
"dataToValue": {
"type": "NONE",
"dataToValueFunction": "/* Should return boolean value */\nreturn data;",
"compareToValue": true
}
},
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": null
},
{
"id": "warningClick",
"name": "{i18n:scada.symbol.warning-click}",
"hint": "{i18n:scada.symbol.on-click-hint}",
"group": "{i18n:scada.symbol.warning-state}",
"type": "widgetAction",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": null,
"defaultGetValueSettings": null,
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": {
"type": "doNothing",
"targetDashboardStateId": null,
"openRightLayout": false,
"setEntityId": false,
"stateEntityParamName": null
}
},
{
"id": "critical",
"name": "{i18n:scada.symbol.critical}",
"hint": "{i18n:scada.symbol.critical-state-hint}",
"group": "{i18n:scada.symbol.critical-state}",
"type": "value",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": "{i18n:scada.symbol.critical}",
"defaultGetValueSettings": {
"action": "GET_ALARM_STATUS",
"defaultValue": false,
"executeRpc": {
"method": "getState",
"requestTimeout": 5000,
"requestPersistent": false,
"persistentPollingInterval": 1000
},
"getAttribute": {
"scope": null,
"key": "state"
},
"getTimeSeries": {
"key": "state"
},
"getAlarmStatus": {
"severityList": [
"CRITICAL"
],
"typeList": null
},
"dataToValue": {
"type": "NONE",
"dataToValueFunction": "/* Should return boolean value */\nreturn data;",
"compareToValue": true
}
},
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": null
},
{
"id": "criticalClick",
"name": "{i18n:scada.symbol.critical-click}",
"hint": "{i18n:scada.symbol.on-click-hint}",
"group": "{i18n:scada.symbol.critical-state}",
"type": "widgetAction",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": null,
"defaultGetValueSettings": null,
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": {
"type": "doNothing",
"targetDashboardStateId": null,
"openRightLayout": false,
"setEntityId": false,
"stateEntityParamName": null
}
},
{
"id": "criticalAnimation",
"name": "{i18n:scada.symbol.warning-critical-state-animation}",
"hint": "{i18n:scada.symbol.warning-critical-state-animation-hint}",
"group": null,
"type": "value",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": "{i18n:scada.symbol.animation}",
"defaultGetValueSettings": {
"action": "DO_NOTHING",
"defaultValue": false,
"executeRpc": {
"method": "getState",
"requestTimeout": 5000,
"requestPersistent": false,
"persistentPollingInterval": 1000
},
"getAttribute": {
"key": "state",
"scope": null
},
"getTimeSeries": {
"key": "state"
},
"dataToValue": {
"type": "NONE",
"compareToValue": true,
"dataToValueFunction": "/* Should return boolean value */\nreturn data;"
}
},
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": null
},
{
"id": "click",
"name": "{i18n:scada.symbol.on-click}",
"hint": "{i18n:scada.symbol.on-click-hint}",
"group": null,
"type": "widgetAction",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": null,
"defaultGetValueSettings": null,
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": {
"type": "doNothing",
"targetDashboardStateId": null,
"openRightLayout": false,
"setEntityId": false,
"stateEntityParamName": null
}
}
],
"properties": [
{
"id": "runningColor",
"name": "{i18n:scada.symbol.colors}",
"type": "color",
"default": "#FFFFFF",
"required": null,
"subLabel": "{i18n:scada.symbol.running}",
"divider": true,
"fieldSuffix": null,
"disableOnProperty": null,
"rowClass": "",
"fieldClass": "",
"min": null,
"max": null,
"step": null
},
{
"id": "stoppedColor",
"name": "{i18n:scada.symbol.colors}",
"type": "color",
"default": "#666666",
"required": null,
"subLabel": "{i18n:scada.symbol.stopped}",
"divider": null,
"fieldSuffix": null,
"disableOnProperty": null,
"rowClass": "",
"fieldClass": "",
"min": null,
"max": null,
"step": null
},
{
"id": "warningColor",
"name": "{i18n:scada.symbol.alarm-colors}",
"type": "color",
"default": "#FAA405",
"required": null,
"subLabel": "{i18n:scada.symbol.warning}",
"divider": true,
"fieldSuffix": null,
"disableOnProperty": null,
"rowClass": "",
"fieldClass": "",
"min": null,
"max": null,
"step": null
},
{
"id": "criticalColor",
"name": "{i18n:scada.symbol.alarm-colors}",
"type": "color",
"default": "#D12730",
"required": null,
"subLabel": "{i18n:scada.symbol.critical}",
"divider": null,
"fieldSuffix": null,
"disableOnProperty": null,
"rowClass": "",
"fieldClass": "",
"min": null,
"max": null,
"step": null
}
]
}]]></tb:metadata>
<g fill="#fff" stroke="#1A1A1A" stroke-width="2" tb:tag="background">
<path d="m77.22 69 1.6-8h42.36l1.6 8h-45.56z"/>
<path d="m77.117 69h45.742c0.108 0.2569 0.244 0.5047 0.385 0.7358 0.342 0.5586 0.824 1.1869 1.403 1.8699 1.16 1.3677 2.802 3.0619 4.738 5.0193 0.519 0.5244 1.059 1.0689 1.62 1.6328 3.641 3.6659 8.098 8.154 12.557 13.274 10.326 11.856 20.438 26.862 20.438 42.468 0 21.266-7.121 37.489-18.622 48.399-11.511 10.92-27.5 16.601-45.378 16.601-17.878 0-33.867-5.681-45.378-16.601-11.502-10.91-18.622-27.133-18.622-48.399 0-15.606 10.106-30.612 20.426-42.468 4.456-5.1195 8.9107-9.6073 12.55-13.273 0.5601-0.5643 1.1009-1.1091 1.6194-1.6337 1.9344-1.9574 3.576-3.6516 4.735-5.0193 0.5788-0.683 1.0604-1.3114 1.4022-1.87 0.1413-0.231 0.2771-0.4787 0.3847-0.7355z"/>
<path d="m80.13 5.9751c1.5245-3.049 4.6409-4.9751 8.0498-4.9751h23.64c3.409 0 6.525 1.926 8.05 4.9751l6.18 12.361c0.625 1.2497 0.95 2.6277 0.95 4.0249v38.639h-54v-38.639c0-1.3972 0.3253-2.7752 0.9502-4.0249l6.1803-12.361z"/>
</g><path d="m73 53h54" stroke="#1A1A1A" stroke-width="2"/><path d="m73 21h54" stroke="#1A1A1A" stroke-width="2"/><path d="m67.265 0s-67.265 0-67.265 33.5v164.18c0 1.3256 1.7909 2.3202 4 2.3202h192c2.209 0 4-0.9946 4-2.3202v-164.18c0-33.5-66.07-33.5-66.07-33.5h-33.93zm67.07 40.6c-1.2887 0-2.3333 0.6268-2.3333 1.4v150.2c0 0.7732 1.0447 1.4 2.3333 1.4h14.666c1.2887 0 2.3333-0.6268 2.3333-1.4v-150.2c0-0.7732-1.0447-1.4-2.3333-1.4z" fill-opacity="0" tb:tag="clickArea"/><g fill="#d12730" style="display: none;" tb:tag="critical">
<rect width="84" height="84" rx="4" fill="#fff" style=""/>
<rect width="84" height="84" rx="4" style=""/>
<rect x="2" y="2" width="80" height="80" rx="2" stroke="#000" stroke-opacity=".87" stroke-width="4" style=""/>
<path d="m44.559 27.562-0.4688 20.059h-4.0234l-0.4883-20.059zm-5.1172 26.211c0-0.7161 0.2344-1.3151 0.7031-1.7968 0.4818-0.4948 1.1459-0.7422 1.9922-0.7422 0.8334 0 1.4909 0.2474 1.9727 0.7422 0.4817 0.4817 0.7226 1.0807 0.7226 1.7968 0 0.6901-0.2409 1.2826-0.7226 1.7774-0.4818 0.4818-1.1393 0.7226-1.9727 0.7226-0.8463 0-1.5104-0.2408-1.9922-0.7226-0.4687-0.4948-0.7031-1.0873-0.7031-1.7774z" fill="#000" fill-opacity=".87" style=""/>
</g><g fill="#faa405" style="display: none;" tb:tag="warning">
<path d="m35.955 2.2112c1.4741-2.9482 5.6813-2.9482 7.1554 0l35.528 71.056c1.3298 2.6596-0.6042 5.7889-3.5777 5.7889h-71.056c-2.9735 0-4.9075-3.1292-3.5777-5.7889z" fill="#fff" style=""/>
<path d="m35.955 2.2112c1.4741-2.9482 5.6813-2.9482 7.1554 0l35.528 71.056c1.3298 2.6596-0.6042 5.7889-3.5777 5.7889h-71.056c-2.9735 0-4.9075-3.1292-3.5777-5.7889z" style=""/>
<path d="m37.72 3.1061c0.7371-1.4741 2.8407-1.4741 3.5778-1e-5l35.528 71.056c0.6649 1.3298-0.3021 2.8944-1.7888 2.8944h-71.056c-1.4868 0-2.4538-1.5646-1.7889-2.8944z" stroke="#000" stroke-opacity=".87" stroke-width="4" style=""/>
<path d="m42.092 32.618-0.4688 20.059h-4.0234l-0.4883-20.059zm-5.1172 26.211c0-0.7161 0.2344-1.3151 0.7031-1.7968 0.4818-0.4948 1.1459-0.7422 1.9922-0.7422 0.8334 0 1.4909 0.2474 1.9727 0.7422 0.4817 0.4817 0.7226 1.0807 0.7226 1.7968 0 0.6901-0.2409 1.2826-0.7226 1.7774-0.4818 0.4818-1.1393 0.7226-1.9727 0.7226-0.8463 0-1.5104-0.2408-1.9922-0.7226-0.4687-0.4948-0.7031-1.0873-0.7031-1.7774z" fill="#000" fill-opacity=".87" style=""/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 14 KiB

346
application/src/main/data/json/system/scada_symbols/consumers-hp.svg

@ -0,0 +1,346 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:tb="https://thingsboard.io/svg" width="600" height="400" fill="none" version="1.1" viewBox="0 0 600 400"><tb:metadata xmlns=""><![CDATA[{
"title": "HP Consumers",
"description": "Consumers with various states.",
"searchTags": [
"power",
"energy"
],
"widgetSizeX": 3,
"widgetSizeY": 2,
"tags": [
{
"tag": "background",
"stateRenderFunction": "var color = ctx.properties.stoppedColor;\nif (ctx.values.running) {\n color = ctx.properties.runningColor;\n}\nelement.attr({fill: color});",
"actions": null
},
{
"tag": "clickArea",
"stateRenderFunction": null,
"actions": {
"click": {
"actionFunction": "ctx.api.callAction(event, 'click');"
}
}
},
{
"tag": "critical",
"stateRenderFunction": "element.attr({fill: ctx.properties.criticalColor});\nif (ctx.values.critical) {\n element.show();\n} else {\n element.hide();\n}\n\nvar elementCriticalAnimation = element.remember('criticalAnimation');\nvar criticalAnimation = ctx.values.critical && ctx.values.criticalAnimation;\n\nif (elementCriticalAnimation !== criticalAnimation) {\n element.remember('criticalAnimation', criticalAnimation);\n if (criticalAnimation) {\n ctx.api.cssAnimate(element, 500).attr({opacity: 0.15}).loop(0, true);\n } else {\n ctx.api.resetCssAnimation(element);\n }\n}\n\n",
"actions": {
"click": {
"actionFunction": "ctx.api.callAction(event, 'criticalClick');"
}
}
},
{
"tag": "warning",
"stateRenderFunction": "element.attr({fill: ctx.properties.warningColor});\nvar warning = ctx.values.warning && !(ctx.values.warning && ctx.values.critical)\nif (warning) {\n element.show();\n} else {\n element.hide();\n}\n\nvar elementCriticalAnimation = element.remember('criticalAnimation');\nvar criticalAnimation = warning && ctx.values.criticalAnimation;\n\nif (elementCriticalAnimation !== criticalAnimation) {\n element.remember('criticalAnimation', criticalAnimation);\n if (criticalAnimation) {\n ctx.api.cssAnimate(element, 500).attr({opacity: 0.15}).loop(0, true);\n } else {\n ctx.api.resetCssAnimation(element);\n }\n}\n",
"actions": {
"click": {
"actionFunction": "ctx.api.callAction(event, 'warningClick');"
}
}
}
],
"behavior": [
{
"id": "running",
"name": "{i18n:scada.symbol.running}",
"hint": "{i18n:scada.symbol.running-hint}",
"group": null,
"type": "value",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": "{i18n:scada.symbol.running}",
"defaultGetValueSettings": {
"action": "GET_ATTRIBUTE",
"defaultValue": false,
"executeRpc": {
"method": "getState",
"requestTimeout": 5000,
"requestPersistent": false,
"persistentPollingInterval": 1000
},
"getAttribute": {
"scope": "SHARED_SCOPE",
"key": "running"
},
"getTimeSeries": {
"key": "state"
},
"getAlarmStatus": {
"severityList": null,
"typeList": null
},
"dataToValue": {
"type": "NONE",
"dataToValueFunction": "/* Should return boolean value */\nreturn data;",
"compareToValue": true
}
},
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": null
},
{
"id": "warning",
"name": "{i18n:scada.symbol.warning}",
"hint": "{i18n:scada.symbol.warning-state-hint}",
"group": "{i18n:scada.symbol.warning-state}",
"type": "value",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": "{i18n:scada.symbol.warning}",
"defaultGetValueSettings": {
"action": "GET_ALARM_STATUS",
"defaultValue": false,
"executeRpc": {
"method": "getState",
"requestTimeout": 5000,
"requestPersistent": false,
"persistentPollingInterval": 1000
},
"getAttribute": {
"scope": null,
"key": "state"
},
"getTimeSeries": {
"key": "state"
},
"getAlarmStatus": {
"severityList": [
"MAJOR",
"MINOR",
"WARNING",
"INDETERMINATE"
],
"typeList": null
},
"dataToValue": {
"type": "NONE",
"dataToValueFunction": "/* Should return boolean value */\nreturn data;",
"compareToValue": true
}
},
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": null
},
{
"id": "warningClick",
"name": "{i18n:scada.symbol.warning-click}",
"hint": "{i18n:scada.symbol.on-click-hint}",
"group": "{i18n:scada.symbol.warning-state}",
"type": "widgetAction",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": null,
"defaultGetValueSettings": null,
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": {
"type": "doNothing",
"targetDashboardStateId": null,
"openRightLayout": false,
"setEntityId": false,
"stateEntityParamName": null
}
},
{
"id": "critical",
"name": "{i18n:scada.symbol.critical}",
"hint": "{i18n:scada.symbol.critical-state-hint}",
"group": "{i18n:scada.symbol.critical-state}",
"type": "value",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": "{i18n:scada.symbol.critical}",
"defaultGetValueSettings": {
"action": "GET_ALARM_STATUS",
"defaultValue": false,
"executeRpc": {
"method": "getState",
"requestTimeout": 5000,
"requestPersistent": false,
"persistentPollingInterval": 1000
},
"getAttribute": {
"scope": null,
"key": "state"
},
"getTimeSeries": {
"key": "state"
},
"getAlarmStatus": {
"severityList": [
"CRITICAL"
],
"typeList": null
},
"dataToValue": {
"type": "NONE",
"dataToValueFunction": "/* Should return boolean value */\nreturn data;",
"compareToValue": true
}
},
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": null
},
{
"id": "criticalClick",
"name": "{i18n:scada.symbol.critical-click}",
"hint": "{i18n:scada.symbol.on-click-hint}",
"group": "{i18n:scada.symbol.critical-state}",
"type": "widgetAction",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": null,
"defaultGetValueSettings": null,
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": {
"type": "doNothing",
"targetDashboardStateId": null,
"openRightLayout": false,
"setEntityId": false,
"stateEntityParamName": null
}
},
{
"id": "criticalAnimation",
"name": "{i18n:scada.symbol.warning-critical-state-animation}",
"hint": "{i18n:scada.symbol.warning-critical-state-animation-hint}",
"group": null,
"type": "value",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": "{i18n:scada.symbol.animation}",
"defaultGetValueSettings": {
"action": "DO_NOTHING",
"defaultValue": false,
"executeRpc": {
"method": "getState",
"requestTimeout": 5000,
"requestPersistent": false,
"persistentPollingInterval": 1000
},
"getAttribute": {
"key": "state",
"scope": null
},
"getTimeSeries": {
"key": "state"
},
"dataToValue": {
"type": "NONE",
"compareToValue": true,
"dataToValueFunction": "/* Should return boolean value */\nreturn data;"
}
},
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": null
},
{
"id": "click",
"name": "{i18n:scada.symbol.on-click}",
"hint": "{i18n:scada.symbol.on-click-hint}",
"group": null,
"type": "widgetAction",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": null,
"defaultGetValueSettings": null,
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": {
"type": "doNothing",
"targetDashboardStateId": null,
"openRightLayout": false,
"setEntityId": false,
"stateEntityParamName": null
}
}
],
"properties": [
{
"id": "runningColor",
"name": "{i18n:scada.symbol.colors}",
"type": "color",
"default": "#FFFFFF",
"required": null,
"subLabel": "{i18n:scada.symbol.running}",
"divider": true,
"fieldSuffix": null,
"disableOnProperty": null,
"rowClass": "",
"fieldClass": "",
"min": null,
"max": null,
"step": null
},
{
"id": "stoppedColor",
"name": "{i18n:scada.symbol.colors}",
"type": "color",
"default": "#666666",
"required": null,
"subLabel": "{i18n:scada.symbol.stopped}",
"divider": null,
"fieldSuffix": null,
"disableOnProperty": null,
"rowClass": "",
"fieldClass": "",
"min": null,
"max": null,
"step": null
},
{
"id": "warningColor",
"name": "{i18n:scada.symbol.alarm-colors}",
"type": "color",
"default": "#FAA405",
"required": null,
"subLabel": "{i18n:scada.symbol.warning}",
"divider": true,
"fieldSuffix": null,
"disableOnProperty": null,
"rowClass": "",
"fieldClass": "",
"min": null,
"max": null,
"step": null
},
{
"id": "criticalColor",
"name": "{i18n:scada.symbol.alarm-colors}",
"type": "color",
"default": "#D12730",
"required": null,
"subLabel": "{i18n:scada.symbol.critical}",
"divider": null,
"fieldSuffix": null,
"disableOnProperty": null,
"rowClass": "",
"fieldClass": "",
"min": null,
"max": null,
"step": null
}
]
}]]></tb:metadata>
<g fill="#fff" stroke="#1A1A1A" stroke-width="2" tb:tag="background">
<path d="m21 240.65c0-1.409 0.5943-2.752 1.6366-3.699l104-94.546c1.907-1.734 4.819-1.734 6.726 0l104 94.546c1.043 0.947 1.637 2.29 1.637 3.699v131.35c0 2.761-2.239 5-5 5h-208c-2.7614 0-5-2.239-5-5v-131.35z"/>
<path d="m130.68 141.26-0.678-0.626-0.678 0.626-112.38 103.74h-14.385l127.44-117.64 127.44 117.64h-14.384l-112.38-103.74z"/>
</g><rect x="56" y="307" width="44" height="70" rx="1" fill="#999" stroke="#1A1A1A" stroke-width="2"/><path d="m80 240c0-0.552 0.4477-1 1-1h18c0.5523 0 1 0.448 1 1v44c0 0.552-0.4477 1-1 1h-18c-0.5523 0-1-0.448-1-1v-44z" fill="#999" stroke="#1A1A1A" stroke-width="2"/><path d="m170 240c0-0.552 0.448-1 1-1h18c0.552 0 1 0.448 1 1v44c0 0.552-0.448 1-1 1h-18c-0.552 0-1-0.448-1-1v-44z" fill="#999" stroke="#1A1A1A" stroke-width="2"/><path d="m170 308c0-0.552 0.448-1 1-1h18c0.552 0 1 0.448 1 1v44c0 0.552-0.448 1-1 1h-18c-0.552 0-1-0.448-1-1v-44z" fill="#999" stroke="#1A1A1A" stroke-width="2"/><path d="m56 240c0-0.552 0.4477-1 1-1h18c0.5523 0 1 0.448 1 1v44c0 0.552-0.4477 1-1 1h-18c-0.5523 0-1-0.448-1-1v-44z" fill="#999" stroke="#1A1A1A" stroke-width="2"/><path d="m146 240c0-0.552 0.448-1 1-1h18c0.552 0 1 0.448 1 1v44c0 0.552-0.448 1-1 1h-18c-0.552 0-1-0.448-1-1v-44z" fill="#999" stroke="#1A1A1A" stroke-width="2"/><rect transform="rotate(-90 194 285)" x="194" y="285" width="46" height="20" rx="1" fill="#999" stroke="#1A1A1A" stroke-width="2"/><path d="m146 308c0-0.552 0.448-1 1-1h18c0.552 0 1 0.448 1 1v44c0 0.552-0.448 1-1 1h-18c-0.552 0-1-0.448-1-1v-44z" fill="#999" stroke="#1A1A1A" stroke-width="2"/><rect transform="rotate(-90 194 353)" x="194" y="353" width="46" height="20" rx="1" fill="#999" stroke="#1A1A1A" stroke-width="2"/><path d="m129.26 178.32c0.397-0.442 1.089-0.442 1.486 0l0.744-0.669-0.744 0.669 13.51 15.01c0.579 0.644 0.122 1.669-0.744 1.669h-27.018c-0.866 0-1.323-1.025-0.744-1.669l13.51-15.01z" fill="#999" stroke="#1A1A1A" stroke-width="2"/><path d="m425 176v1.804l1.53-0.956 60.94-38.088c0.666-0.416 1.53 0.063 1.53 0.848v37.392h85c2.761 0 5 2.239 5 5v190c0 2.761-2.239 5-5 5h-217c-2.761 0-5-2.239-5-5v-194.8c0-0.369 0.204-0.709 0.529-0.882l71-37.867c0.667-0.355 1.471 0.127 1.471 0.882v36.667z" fill="#fff" stroke="#1A1A1A" stroke-width="2" tb:tag="background"/><path d="m519.88 19.938c0.033-0.527 0.47-0.9376 0.998-0.9376h30.242c0.528 0 0.965 0.4106 0.998 0.9376l9.75 156c0.036 0.575-0.421 1.062-0.998 1.062h-49.742c-0.577 0-1.034-0.487-0.998-1.062l9.75-156z" fill="#999" stroke="#1A1A1A" stroke-width="2"/><rect x="429" y="236" width="38" height="38" rx="1" fill="#999" stroke="#1A1A1A" stroke-width="2"/><rect x="385" y="236" width="38" height="38" rx="1" fill="#999" stroke="#1A1A1A" stroke-width="2"/><rect x="429" y="280" width="38" height="38" rx="1" fill="#999" stroke="#1A1A1A" stroke-width="2"/><rect x="385" y="280" width="38" height="38" rx="1" fill="#999" stroke="#1A1A1A" stroke-width="2"/><rect x="473" y="236" width="38" height="38" rx="1" fill="#999" stroke="#1A1A1A" stroke-width="2"/><rect x="473" y="280" width="38" height="38" rx="1" fill="#999" stroke="#1A1A1A" stroke-width="2"/><rect x="517" y="236" width="38" height="38" rx="1" fill="#999" stroke="#1A1A1A" stroke-width="2"/><rect x="517" y="280" width="38" height="38" rx="1" fill="#999" stroke="#1A1A1A" stroke-width="2"/><path d="m190 6c0-2.7614 2.239-5 5-5h210c2.761 0 5 2.2386 5 5v366c0 2.761-2.239 5-5 5h-210c-2.761 0-5-2.239-5-5v-366z" fill="#fff" stroke="#1A1A1A" stroke-width="2" tb:tag="background"/><rect x="304" y="57" width="86" height="36" rx="1" fill="#999" stroke="#1A1A1A" stroke-width="2"/><rect x="304" y="165" width="86" height="36" rx="1" fill="#999" stroke="#1A1A1A" stroke-width="2"/><rect x="304" y="111" width="86" height="36" rx="1" fill="#999" stroke="#1A1A1A" stroke-width="2"/><rect x="304" y="219" width="86" height="36" rx="1" fill="#999" stroke="#1A1A1A" stroke-width="2"/><rect x="210" y="57" width="86" height="36" rx="1" fill="#999" stroke="#1A1A1A" stroke-width="2"/><rect x="210" y="165" width="86" height="36" rx="1" fill="#999" stroke="#1A1A1A" stroke-width="2"/><rect x="210" y="111" width="86" height="36" rx="1" fill="#999" stroke="#1A1A1A" stroke-width="2"/><rect x="210" y="219" width="86" height="36" rx="1" fill="#999" stroke="#1A1A1A" stroke-width="2"/><rect x="251" y="286" width="98" height="91" rx="1" fill="#999" stroke="#1A1A1A" stroke-width="2"/><rect x="1" y="377" width="598" height="22" rx="5" fill="#fff" stroke="#1A1A1A" stroke-width="2" tb:tag="background"/><path d="m201.8 0s-201.8 0-201.8 67v328.36c0 2.6512 5.3727 4.6403 12 4.6403h576c6.627 0 12-1.9892 12-4.6403v-328.36c0-67-198.21-67-198.21-67h-101.79zm201.21 81.2c-3.8661 0-6.9999 1.2536-6.9999 2.8v300.4c0 1.5464 3.1341 2.8 6.9999 2.8h43.998c3.8661 0 6.9999-1.2536 6.9999-2.8v-300.4c0-1.5464-3.1341-2.8-6.9999-2.8z" fill-opacity="0" style="stroke-width:1.8107" tb:tag="clickArea"/><g transform="translate(0,316)" fill="#d12730" style="display: none;" tb:tag="critical">
<rect width="84" height="84" rx="4" fill="#fff" style=""/>
<rect width="84" height="84" rx="4" style=""/>
<rect x="2" y="2" width="80" height="80" rx="2" stroke="#000" stroke-opacity=".87" stroke-width="4" style=""/>
<path d="m44.559 27.562-0.4688 20.059h-4.0234l-0.4883-20.059zm-5.1172 26.211c0-0.7161 0.2344-1.3151 0.7031-1.7968 0.4818-0.4948 1.1459-0.7422 1.9922-0.7422 0.8334 0 1.4909 0.2474 1.9727 0.7422 0.4817 0.4817 0.7226 1.0807 0.7226 1.7968 0 0.6901-0.2409 1.2826-0.7226 1.7774-0.4818 0.4818-1.1393 0.7226-1.9727 0.7226-0.8463 0-1.5104-0.2408-1.9922-0.7226-0.4687-0.4948-0.7031-1.0873-0.7031-1.7774z" fill="#000" fill-opacity=".87" style=""/>
</g><g transform="translate(0 320.94)" fill="#faa405" style="display: none;" tb:tag="warning">
<path d="m35.955 2.2112c1.4741-2.9482 5.6813-2.9482 7.1554 0l35.528 71.056c1.3298 2.6596-0.6042 5.7889-3.5777 5.7889h-71.056c-2.9735 0-4.9075-3.1292-3.5777-5.7889z" fill="#fff" style=""/>
<path d="m35.955 2.2112c1.4741-2.9482 5.6813-2.9482 7.1554 0l35.528 71.056c1.3298 2.6596-0.6042 5.7889-3.5777 5.7889h-71.056c-2.9735 0-4.9075-3.1292-3.5777-5.7889z" style=""/>
<path d="m37.72 3.1061c0.7371-1.4741 2.8407-1.4741 3.5778-1e-5l35.528 71.056c0.6649 1.3298-0.3021 2.8944-1.7888 2.8944h-71.056c-1.4868 0-2.4538-1.5646-1.7889-2.8944z" stroke="#000" stroke-opacity=".87" stroke-width="4" style=""/>
<path d="m42.092 32.618-0.4688 20.059h-4.0234l-0.4883-20.059zm-5.1172 26.211c0-0.7161 0.2344-1.3151 0.7031-1.7968 0.4818-0.4948 1.1459-0.7422 1.9922-0.7422 0.8334 0 1.4909 0.2474 1.9727 0.7422 0.4817 0.4817 0.7226 1.0807 0.7226 1.7968 0 0.6901-0.2409 1.2826-0.7226 1.7774-0.4818 0.4818-1.1393 0.7226-1.9727 0.7226-0.8463 0-1.5104-0.2408-1.9922-0.7226-0.4687-0.4948-0.7031-1.0873-0.7031-1.7774z" fill="#000" fill-opacity=".87" style=""/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 17 KiB

444
application/src/main/data/json/system/scada_symbols/curcuit-breaker-hp.svg

@ -0,0 +1,444 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:tb="https://thingsboard.io/svg" width="200" height="400" fill="none" version="1.1" viewBox="0 0 200 400"><tb:metadata xmlns=""><![CDATA[{
"title": "HP Circuit breaker",
"description": "Circuit breaker with various states.",
"searchTags": [
"energy",
"power",
"ev",
"switch"
],
"widgetSizeX": 1,
"widgetSizeY": 2,
"tags": [
{
"tag": "background",
"stateRenderFunction": "element.attr({fill: ctx.properties.backgroundColor});",
"actions": null
},
{
"tag": "breaker",
"stateRenderFunction": null,
"actions": {
"click": {
"actionFunction": "var initial = ctx.values.initialState;\nvar action = initial ? 'offUpdateState' : 'onUpdateState';\n\nctx.api.callAction(event, action, undefined, {\n next: () => {\n ctx.api.setValue('initialState', !initial);\n }\n});"
}
}
},
{
"tag": "breaker-trigger",
"stateRenderFunction": "element.fill(ctx.properties.disabledColor);\nif (ctx.values.initialState) {\n element.transform({translateY: 0});\n} else {\n element.transform({translateY: 160});\n}",
"actions": null
},
{
"tag": "critical",
"stateRenderFunction": "element.attr({fill: ctx.properties.criticalColor});\nif (ctx.values.critical) {\n element.show();\n} else {\n element.hide();\n}\n\nvar elementCriticalAnimation = element.remember('criticalAnimation');\nvar criticalAnimation = ctx.values.critical && ctx.values.criticalAnimation;\n\nif (elementCriticalAnimation !== criticalAnimation) {\n element.remember('criticalAnimation', criticalAnimation);\n if (criticalAnimation) {\n ctx.api.cssAnimate(element, 500).attr({opacity: 0.15}).loop(0, true);\n } else {\n ctx.api.resetCssAnimation(element);\n }\n}\n\n",
"actions": {
"click": {
"actionFunction": "ctx.api.callAction(event, 'criticalClick');"
}
}
},
{
"tag": "label",
"stateRenderFunction": "if (ctx.properties.label) {\n element.show();\n var label = ctx.values.initialState ? ctx.properties.onLabel : ctx.properties.offLabel;\n ctx.api.font(element, ctx.properties.labelFont, ctx.properties.labelColor);\n ctx.api.text(element, label);\n} else {\n element.hide();\n}",
"actions": null
},
{
"tag": "label-box",
"stateRenderFunction": "var color = ctx.properties.disabledColor;\nif (ctx.values.initialState) {\n color = ctx.properties.enabledColor;\n}\nelement.attr({fill: color});",
"actions": null
},
{
"tag": "warning",
"stateRenderFunction": "element.attr({fill: ctx.properties.warningColor});\nvar warning = ctx.values.warning && !(ctx.values.warning && ctx.values.critical)\nif (warning) {\n element.show();\n} else {\n element.hide();\n}\n\nvar elementCriticalAnimation = element.remember('criticalAnimation');\nvar criticalAnimation = warning && ctx.values.criticalAnimation;\n\nif (elementCriticalAnimation !== criticalAnimation) {\n element.remember('criticalAnimation', criticalAnimation);\n if (criticalAnimation) {\n ctx.api.cssAnimate(element, 500).attr({opacity: 0.15}).loop(0, true);\n } else {\n ctx.api.resetCssAnimation(element);\n }\n}\n",
"actions": {
"click": {
"actionFunction": "ctx.api.callAction(event, 'warningClick');"
}
}
}
],
"behavior": [
{
"id": "initialState",
"name": "{i18n:scada.symbol.on-off-state}",
"hint": "{i18n:scada.symbol.on-off-state-hint}",
"group": null,
"type": "value",
"valueType": "BOOLEAN",
"trueLabel": "{i18n:scada.symbol.on}",
"falseLabel": "{i18n:scada.symbol.off}",
"stateLabel": "",
"defaultGetValueSettings": {
"action": "GET_ATTRIBUTE",
"defaultValue": false,
"executeRpc": {
"method": "getState",
"requestTimeout": 5000,
"requestPersistent": false,
"persistentPollingInterval": 1000
},
"getAttribute": {
"scope": "SHARED_SCOPE",
"key": "state"
},
"getTimeSeries": {
"key": "state"
},
"getAlarmStatus": {
"severityList": null,
"typeList": null
},
"dataToValue": {
"type": "NONE",
"dataToValueFunction": "/* Should return boolean value */\nreturn data;",
"compareToValue": true
}
},
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": null
},
{
"id": "onUpdateState",
"name": "{i18n:scada.symbol.on-update-state}",
"hint": "{i18n:scada.symbol.on-update-state-hint}",
"group": null,
"type": "action",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": null,
"defaultGetValueSettings": null,
"defaultSetValueSettings": {
"action": "EXECUTE_RPC",
"executeRpc": {
"method": "setState",
"requestTimeout": 5000,
"requestPersistent": false,
"persistentPollingInterval": 1000
},
"setAttribute": {
"scope": "SERVER_SCOPE",
"key": "state"
},
"putTimeSeries": {
"key": "state"
},
"valueToData": {
"type": "CONSTANT",
"constantValue": true,
"valueToDataFunction": "/* Convert input boolean value to RPC parameters or attribute/time-series value */\nreturn value;"
}
},
"defaultWidgetActionSettings": null
},
{
"id": "offUpdateState",
"name": "{i18n:scada.symbol.off-update-state}",
"hint": "{i18n:scada.symbol.off-update-state-hint}",
"group": null,
"type": "action",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": null,
"defaultGetValueSettings": null,
"defaultSetValueSettings": {
"action": "EXECUTE_RPC",
"executeRpc": {
"method": "setState",
"requestTimeout": 5000,
"requestPersistent": false,
"persistentPollingInterval": 1000
},
"setAttribute": {
"key": "state",
"scope": "SERVER_SCOPE"
},
"putTimeSeries": {
"key": "state"
},
"valueToData": {
"type": "CONSTANT",
"constantValue": false,
"valueToDataFunction": "/* Convert input boolean value to RPC parameters or attribute/time-series value */\nreturn value;"
}
},
"defaultWidgetActionSettings": null
},
{
"id": "warning",
"name": "{i18n:scada.symbol.warning}",
"hint": "{i18n:scada.symbol.warning-state-hint}",
"group": "{i18n:scada.symbol.warning-state}",
"type": "value",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": "{i18n:scada.symbol.warning}",
"defaultGetValueSettings": {
"action": "GET_ALARM_STATUS",
"defaultValue": false,
"executeRpc": {
"method": "getState",
"requestTimeout": 5000,
"requestPersistent": false,
"persistentPollingInterval": 1000
},
"getAttribute": {
"scope": null,
"key": "state"
},
"getTimeSeries": {
"key": "state"
},
"getAlarmStatus": {
"severityList": [
"MAJOR",
"MINOR",
"WARNING",
"INDETERMINATE"
],
"typeList": null
},
"dataToValue": {
"type": "NONE",
"dataToValueFunction": "/* Should return boolean value */\nreturn data;",
"compareToValue": true
}
},
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": null
},
{
"id": "warningClick",
"name": "{i18n:scada.symbol.warning-click}",
"hint": "{i18n:scada.symbol.on-click-hint}",
"group": "{i18n:scada.symbol.warning-state}",
"type": "widgetAction",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": null,
"defaultGetValueSettings": null,
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": {
"type": "doNothing",
"targetDashboardStateId": null,
"openRightLayout": false,
"setEntityId": false,
"stateEntityParamName": null
}
},
{
"id": "critical",
"name": "{i18n:scada.symbol.critical}",
"hint": "{i18n:scada.symbol.critical-state-hint}",
"group": "{i18n:scada.symbol.critical-state}",
"type": "value",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": "{i18n:scada.symbol.critical}",
"defaultGetValueSettings": {
"action": "GET_ALARM_STATUS",
"defaultValue": false,
"executeRpc": {
"method": "getState",
"requestTimeout": 5000,
"requestPersistent": false,
"persistentPollingInterval": 1000
},
"getAttribute": {
"scope": null,
"key": "state"
},
"getTimeSeries": {
"key": "state"
},
"getAlarmStatus": {
"severityList": [
"CRITICAL"
],
"typeList": null
},
"dataToValue": {
"type": "NONE",
"dataToValueFunction": "/* Should return boolean value */\nreturn data;",
"compareToValue": true
}
},
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": null
},
{
"id": "criticalClick",
"name": "{i18n:scada.symbol.critical-click}",
"hint": "{i18n:scada.symbol.on-click-hint}",
"group": "{i18n:scada.symbol.critical-state}",
"type": "widgetAction",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": null,
"defaultGetValueSettings": null,
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": {
"type": "doNothing",
"targetDashboardStateId": null,
"openRightLayout": false,
"setEntityId": false,
"stateEntityParamName": null
}
},
{
"id": "criticalAnimation",
"name": "{i18n:scada.symbol.warning-critical-state-animation}",
"hint": "{i18n:scada.symbol.warning-critical-state-animation-hint}",
"group": null,
"type": "value",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": "{i18n:scada.symbol.animation}",
"defaultGetValueSettings": {
"action": "DO_NOTHING",
"defaultValue": false,
"executeRpc": {
"method": "getState",
"requestTimeout": 5000,
"requestPersistent": false,
"persistentPollingInterval": 1000
},
"getAttribute": {
"key": "state",
"scope": null
},
"getTimeSeries": {
"key": "state"
},
"dataToValue": {
"type": "NONE",
"compareToValue": true,
"dataToValueFunction": "/* Should return boolean value */\nreturn data;"
}
},
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": null
}
],
"properties": [
{
"id": "label",
"name": "{i18n:scada.symbol.label}",
"type": "switch",
"default": true,
"disabled": false,
"visible": true
},
{
"id": "onLabel",
"name": "{i18n:scada.symbol.label}",
"type": "text",
"default": "ON",
"disabled": false,
"visible": true
},
{
"id": "offLabel",
"name": "{i18n:scada.symbol.label}",
"type": "text",
"default": "OFF",
"disabled": false,
"visible": true
},
{
"id": "labelFont",
"name": "{i18n:scada.symbol.label}",
"type": "font",
"default": {
"size": 42,
"sizeUnit": "px",
"family": "Roboto",
"weight": "400",
"style": "normal"
},
"disabled": false,
"visible": true
},
{
"id": "labelColor",
"name": "{i18n:scada.symbol.label}",
"type": "color",
"default": "#1A1A1A",
"disabled": false,
"visible": true
},
{
"id": "backgroundColor",
"name": "{i18n:scada.symbol.background-color}",
"type": "color",
"default": "#FFFFFF",
"disabled": false,
"visible": true
},
{
"id": "enabledColor",
"name": "{i18n:scada.symbol.colors}",
"type": "color",
"default": "#FFFFFF",
"subLabel": "{i18n:scada.symbol.enabled}",
"divider": true,
"disabled": false,
"visible": true
},
{
"id": "disabledColor",
"name": "{i18n:scada.symbol.colors}",
"type": "color",
"default": "#666666",
"subLabel": "{i18n:scada.symbol.disabled}",
"disabled": false,
"visible": true
},
{
"id": "warningColor",
"name": "{i18n:scada.symbol.alarm-colors}",
"type": "color",
"default": "#FAA405",
"subLabel": "{i18n:scada.symbol.warning}",
"divider": true,
"disabled": false,
"visible": true
},
{
"id": "criticalColor",
"name": "{i18n:scada.symbol.alarm-colors}",
"type": "color",
"default": "#D12730",
"subLabel": "{i18n:scada.symbol.critical}",
"disabled": false,
"visible": true
}
]
}]]></tb:metadata>
<rect width="200" height="400" fill="#fff" tb:tag="background"/><rect x="1" y="1" width="198" height="398" stroke="#000" stroke-opacity=".87" stroke-width="2"/><g tb:tag="breaker">
<path d="m50 100h100v198c0 1.105-0.895 2-2 2h-96c-1.1046 0-2-0.895-2-2v-198z"/>
<path d="m51 101h98v197c0 0.552-0.448 1-1 1h-96c-0.5523 0-1-0.448-1-1v-197z" stroke="#000" stroke-opacity=".87" stroke-width="2" tb:tag="label-box"/>
<text x="100" y="201.65533" fill="#000000" font-family="Roboto" font-size="40px" font-weight="400" text-anchor="middle" tb:tag="label" xml:space="preserve"><tspan dominant-baseline="start">ON</tspan></text>
<g tb:tag="breaker-trigger">
<rect x="24" y="100" width="152" height="40" rx="2" fill="#999"/>
<rect x="25" y="101" width="150" height="38" rx="1" stroke="#000" stroke-opacity=".87" stroke-width="2"/>
</g>
</g><circle cx="100" cy="50" r="20" fill="#fff"/><circle cx="100" cy="50" r="19" stroke="#000" stroke-opacity=".87" stroke-width="2"/><circle cx="100" cy="350" r="20" fill="#fff"/><circle cx="100" cy="350" r="19" stroke="#000" stroke-opacity=".87" stroke-width="2"/><path d="m100 0v31" stroke="#1a1a1a" stroke-width="6"/><path d="m100 369v31" stroke="#1a1a1a" stroke-width="6"/><g fill="#d12730" style="display: none;" tb:tag="critical">
<rect width="84" height="84" rx="4" fill="#fff" style=""/>
<rect width="84" height="84" rx="4" style=""/>
<rect x="2" y="2" width="80" height="80" rx="2" stroke="#000" stroke-opacity=".87" stroke-width="4" style=""/>
<path d="m44.559 27.562-0.4688 20.059h-4.0234l-0.4883-20.059zm-5.1172 26.211c0-0.7161 0.2344-1.3151 0.7031-1.7968 0.4818-0.4948 1.1459-0.7422 1.9922-0.7422 0.8334 0 1.4909 0.2474 1.9727 0.7422 0.4817 0.4817 0.7226 1.0807 0.7226 1.7968 0 0.6901-0.2409 1.2826-0.7226 1.7774-0.4818 0.4818-1.1393 0.7226-1.9727 0.7226-0.8463 0-1.5104-0.2408-1.9922-0.7226-0.4687-0.4948-0.7031-1.0873-0.7031-1.7774z" fill="#000" fill-opacity=".87" style=""/>
</g><g fill="#faa405" style="display: none;" tb:tag="warning">
<path d="m35.955 2.2112c1.4741-2.9482 5.6813-2.9482 7.1554 0l35.528 71.056c1.3298 2.6596-0.6042 5.7889-3.5777 5.7889h-71.056c-2.9735 0-4.9075-3.1292-3.5777-5.7889z" fill="#fff" style=""/>
<path d="m35.955 2.2112c1.4741-2.9482 5.6813-2.9482 7.1554 0l35.528 71.056c1.3298 2.6596-0.6042 5.7889-3.5777 5.7889h-71.056c-2.9735 0-4.9075-3.1292-3.5777-5.7889z" style=""/>
<path d="m37.72 3.1061c0.7371-1.4741 2.8407-1.4741 3.5778-1e-5l35.528 71.056c0.6649 1.3298-0.3021 2.8944-1.7888 2.8944h-71.056c-1.4868 0-2.4538-1.5646-1.7889-2.8944z" stroke="#000" stroke-opacity=".87" stroke-width="4" style=""/>
<path d="m42.092 32.618-0.4688 20.059h-4.0234l-0.4883-20.059zm-5.1172 26.211c0-0.7161 0.2344-1.3151 0.7031-1.7968 0.4818-0.4948 1.1459-0.7422 1.9922-0.7422 0.8334 0 1.4909 0.2474 1.9727 0.7422 0.4817 0.4817 0.7226 1.0807 0.7226 1.7968 0 0.6901-0.2409 1.2826-0.7226 1.7774-0.4818 0.4818-1.1393 0.7226-1.9727 0.7226-0.8463 0-1.5104-0.2408-1.9922-0.7226-0.4687-0.4948-0.7031-1.0873-0.7031-1.7774z" fill="#000" fill-opacity=".87" style=""/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 16 KiB

332
application/src/main/data/json/system/scada_symbols/electrical-distribution-board-hp.svg

@ -0,0 +1,332 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:tb="https://thingsboard.io/svg" width="400" height="600" fill="none" version="1.1" viewBox="0 0 400 600"><tb:metadata xmlns=""><![CDATA[{
"title": "HP Electrical distribution board",
"description": "Electrical distribution board with various states.",
"searchTags": [
"energy",
"power",
"fuse",
"panel"
],
"widgetSizeX": 2,
"widgetSizeY": 3,
"tags": [
{
"tag": "background",
"stateRenderFunction": "element.attr({fill: ctx.properties.backgroundColor});",
"actions": null
},
{
"tag": "clickArea",
"stateRenderFunction": null,
"actions": {
"click": {
"actionFunction": "ctx.api.callAction(event, 'click');"
}
}
},
{
"tag": "critical",
"stateRenderFunction": "element.attr({fill: ctx.properties.criticalColor});\nif (ctx.values.critical) {\n element.show();\n} else {\n element.hide();\n}\n\nvar elementCriticalAnimation = element.remember('criticalAnimation');\nvar criticalAnimation = ctx.values.critical && ctx.values.criticalAnimation;\n\nif (elementCriticalAnimation !== criticalAnimation) {\n element.remember('criticalAnimation', criticalAnimation);\n if (criticalAnimation) {\n ctx.api.cssAnimate(element, 500).attr({opacity: 0.15}).loop(0, true);\n } else {\n ctx.api.resetCssAnimation(element);\n }\n}\n\n",
"actions": {
"click": {
"actionFunction": "ctx.api.callAction(event, 'criticalClick');"
}
}
},
{
"tag": "icon",
"stateRenderFunction": "var showIcon = ctx.properties.showIcon;\nvar showLabel = ctx.properties.label;\nif (showIcon) {\n element.show();\n var icon = ctx.properties.icon;\n var iconSize = ctx.properties.iconSize;\n var iconColor = ctx.properties.iconColor;\n ctx.api.icon(element, icon, iconSize, iconColor, true);\n if (!showLabel) {\n element.transform({translateX: 200, translateY: 310});\n }\n} else {\n element.hide()\n}",
"actions": null
},
{
"tag": "triangle",
"stateRenderFunction": "if (ctx.properties.showTriangle) {\n element.show();\n element.stroke(ctx.properties.triangleColor);\n} else {\n element.hide();\n}",
"actions": null
},
{
"tag": "warning",
"stateRenderFunction": "element.attr({fill: ctx.properties.warningColor});\nvar warning = ctx.values.warning && !(ctx.values.warning && ctx.values.critical)\nif (warning) {\n element.show();\n} else {\n element.hide();\n}\n\nvar elementCriticalAnimation = element.remember('criticalAnimation');\nvar criticalAnimation = warning && ctx.values.criticalAnimation;\n\nif (elementCriticalAnimation !== criticalAnimation) {\n element.remember('criticalAnimation', criticalAnimation);\n if (criticalAnimation) {\n ctx.api.cssAnimate(element, 500).attr({opacity: 0.15}).loop(0, true);\n } else {\n ctx.api.resetCssAnimation(element);\n }\n}\n",
"actions": {
"click": {
"actionFunction": "ctx.api.callAction(event, 'warningClick');"
}
}
}
],
"behavior": [
{
"id": "warning",
"name": "{i18n:scada.symbol.warning}",
"hint": "{i18n:scada.symbol.warning-state-hint}",
"group": "{i18n:scada.symbol.warning-state}",
"type": "value",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": "{i18n:scada.symbol.warning}",
"defaultGetValueSettings": {
"action": "GET_ALARM_STATUS",
"defaultValue": false,
"executeRpc": {
"method": "getState",
"requestTimeout": 5000,
"requestPersistent": false,
"persistentPollingInterval": 1000
},
"getAttribute": {
"scope": null,
"key": "state"
},
"getTimeSeries": {
"key": "state"
},
"getAlarmStatus": {
"severityList": [
"MAJOR",
"MINOR",
"WARNING",
"INDETERMINATE"
],
"typeList": null
},
"dataToValue": {
"type": "NONE",
"dataToValueFunction": "/* Should return boolean value */\nreturn data;",
"compareToValue": true
}
},
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": null
},
{
"id": "warningClick",
"name": "{i18n:scada.symbol.warning-click}",
"hint": "{i18n:scada.symbol.on-click-hint}",
"group": "{i18n:scada.symbol.warning-state}",
"type": "widgetAction",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": null,
"defaultGetValueSettings": null,
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": {
"type": "doNothing",
"targetDashboardStateId": null,
"openRightLayout": false,
"setEntityId": false,
"stateEntityParamName": null
}
},
{
"id": "critical",
"name": "{i18n:scada.symbol.critical}",
"hint": "{i18n:scada.symbol.critical-state-hint}",
"group": "{i18n:scada.symbol.critical-state}",
"type": "value",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": "{i18n:scada.symbol.critical}",
"defaultGetValueSettings": {
"action": "GET_ALARM_STATUS",
"defaultValue": false,
"executeRpc": {
"method": "getState",
"requestTimeout": 5000,
"requestPersistent": false,
"persistentPollingInterval": 1000
},
"getAttribute": {
"scope": null,
"key": "state"
},
"getTimeSeries": {
"key": "state"
},
"getAlarmStatus": {
"severityList": [
"CRITICAL"
],
"typeList": null
},
"dataToValue": {
"type": "NONE",
"dataToValueFunction": "/* Should return boolean value */\nreturn data;",
"compareToValue": true
}
},
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": null
},
{
"id": "criticalClick",
"name": "{i18n:scada.symbol.critical-click}",
"hint": "{i18n:scada.symbol.on-click-hint}",
"group": "{i18n:scada.symbol.critical-state}",
"type": "widgetAction",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": null,
"defaultGetValueSettings": null,
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": {
"type": "doNothing",
"targetDashboardStateId": null,
"openRightLayout": false,
"setEntityId": false,
"stateEntityParamName": null
}
},
{
"id": "criticalAnimation",
"name": "{i18n:scada.symbol.warning-critical-state-animation}",
"hint": "{i18n:scada.symbol.warning-critical-state-animation-hint}",
"group": null,
"type": "value",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": "{i18n:scada.symbol.animation}",
"defaultGetValueSettings": {
"action": "DO_NOTHING",
"defaultValue": false,
"executeRpc": {
"method": "getState",
"requestTimeout": 5000,
"requestPersistent": false,
"persistentPollingInterval": 1000
},
"getAttribute": {
"key": "state",
"scope": null
},
"getTimeSeries": {
"key": "state"
},
"dataToValue": {
"type": "NONE",
"compareToValue": true,
"dataToValueFunction": "/* Should return boolean value */\nreturn data;"
}
},
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": null
},
{
"id": "click",
"name": "{i18n:scada.symbol.on-click}",
"hint": "{i18n:scada.symbol.on-click-hint}",
"group": null,
"type": "widgetAction",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": null,
"defaultGetValueSettings": null,
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": {
"type": "doNothing",
"targetDashboardStateId": null,
"openRightLayout": false,
"setEntityId": false,
"stateEntityParamName": null
}
}
],
"properties": [
{
"id": "showIcon",
"name": "{i18n:scada.symbol.icon}",
"type": "switch",
"default": true,
"disabled": false,
"visible": true
},
{
"id": "iconSize",
"name": "{i18n:scada.symbol.icon}",
"type": "number",
"default": 44,
"fieldSuffix": "px",
"min": 0,
"disabled": false,
"visible": true
},
{
"id": "icon",
"name": "{i18n:scada.symbol.icon}",
"type": "icon",
"default": "bolt",
"disabled": false,
"visible": true
},
{
"id": "showTriangle",
"name": "{i18n:scada.symbol.triangle}",
"type": "switch",
"default": true,
"disabled": false,
"visible": true
},
{
"id": "triangleColor",
"name": "{i18n:scada.symbol.triangle}",
"type": "color",
"default": "#D12730",
"disabled": false,
"visible": true
},
{
"id": "iconColor",
"name": "{i18n:scada.symbol.icon}",
"type": "color",
"default": "#000",
"disabled": false,
"visible": true
},
{
"id": "backgroundColor",
"name": "{i18n:scada.symbol.background-color}",
"type": "color",
"default": "#FFFFFF",
"divider": false,
"disabled": false,
"visible": true
},
{
"id": "warningColor",
"name": "{i18n:scada.symbol.alarm-colors}",
"type": "color",
"default": "#FAA405",
"subLabel": "{i18n:scada.symbol.warning}",
"divider": true,
"disabled": false,
"visible": true
},
{
"id": "criticalColor",
"name": "{i18n:scada.symbol.alarm-colors}",
"type": "color",
"default": "#D12730",
"subLabel": "{i18n:scada.symbol.critical}",
"disabled": false,
"visible": true
}
]
}]]></tb:metadata>
<rect x="1" y="1" width="398" height="598" rx="3" fill="#fff" stroke="#1a1a1a" stroke-width="2" tb:tag="background"/><path d="m150.82 344.75c-1.541 0-2.503-1.669-1.731-3.002l49.176-84.942c0.771-1.33 2.692-1.33 3.462 0l49.177 84.942c0.772 1.333-0.19 3.002-1.731 3.002h-98.353z" stroke="#D12730" stroke-width="8" tb:tag="triangle"/><g transform="translate(200,310)" tb:tag="icon">
<path d="m4.3731-15.914-16.841 15.085c-1.041 0.943-0.455 2.682 0.943 2.812l13.151 1.268-7.884 10.989c-0.358 0.504-0.309 1.203 0.13 1.642 0.487 0.488 1.251 0.504 1.755 0.033l16.841-15.086c1.041-0.943 0.455-2.682-0.943-2.812l-13.151-1.268 7.885-10.989c0.357-0.504 0.308-1.203-0.131-1.642-0.487-0.488-1.251-0.504-1.755-0.032z" fill="#1a1a1a"/>
</g><path d="m134.53 0s-134.53 0-134.53 100.5v492.54c0 3.9768 3.5818 6.9606 8 6.9606h384c4.418 0 8-2.9838 8-6.9606v-492.54c0-100.5-132.14-100.5-132.14-100.5h-67.86zm134.14 121.8c-2.5774 0-4.6666 1.8804-4.6666 4.2v450.6c0 2.3196 2.0894 4.2 4.6666 4.2h29.332c2.5774 0 4.6666-1.8804 4.6666-4.2v-450.6c0-2.3196-2.0894-4.2-4.6666-4.2z" fill-opacity="0" tb:tag="clickArea"/><g fill="#d12730" style="display: none;" tb:tag="critical">
<rect width="84" height="84" rx="4" fill="#fff" style=""/>
<rect width="84" height="84" rx="4" style=""/>
<rect x="2" y="2" width="80" height="80" rx="2" stroke="#000" stroke-opacity=".87" stroke-width="4" style=""/>
<path d="m44.559 27.562-0.4688 20.059h-4.0234l-0.4883-20.059zm-5.1172 26.211c0-0.7161 0.2344-1.3151 0.7031-1.7968 0.4818-0.4948 1.1459-0.7422 1.9922-0.7422 0.8334 0 1.4909 0.2474 1.9727 0.7422 0.4817 0.4817 0.7226 1.0807 0.7226 1.7968 0 0.6901-0.2409 1.2826-0.7226 1.7774-0.4818 0.4818-1.1393 0.7226-1.9727 0.7226-0.8463 0-1.5104-0.2408-1.9922-0.7226-0.4687-0.4948-0.7031-1.0873-0.7031-1.7774z" fill="#000" fill-opacity=".87" style=""/>
</g><g fill="#faa405" style="display: none;" tb:tag="warning">
<path d="m35.955 2.2112c1.4741-2.9482 5.6813-2.9482 7.1554 0l35.528 71.056c1.3298 2.6596-0.6042 5.7889-3.5777 5.7889h-71.056c-2.9735 0-4.9075-3.1292-3.5777-5.7889z" fill="#fff" style=""/>
<path d="m35.955 2.2112c1.4741-2.9482 5.6813-2.9482 7.1554 0l35.528 71.056c1.3298 2.6596-0.6042 5.7889-3.5777 5.7889h-71.056c-2.9735 0-4.9075-3.1292-3.5777-5.7889z" style=""/>
<path d="m37.72 3.1061c0.7371-1.4741 2.8407-1.4741 3.5778-1e-5l35.528 71.056c0.6649 1.3298-0.3021 2.8944-1.7888 2.8944h-71.056c-1.4868 0-2.4538-1.5646-1.7889-2.8944z" stroke="#000" stroke-opacity=".87" stroke-width="4" style=""/>
<path d="m42.092 32.618-0.4688 20.059h-4.0234l-0.4883-20.059zm-5.1172 26.211c0-0.7161 0.2344-1.3151 0.7031-1.7968 0.4818-0.4948 1.1459-0.7422 1.9922-0.7422 0.8334 0 1.4909 0.2474 1.9727 0.7422 0.4817 0.4817 0.7226 1.0807 0.7226 1.7968 0 0.6901-0.2409 1.2826-0.7226 1.7774-0.4818 0.4818-1.1393 0.7226-1.9727 0.7226-0.8463 0-1.5104-0.2408-1.9922-0.7226-0.4687-0.4948-0.7031-1.0873-0.7031-1.7774z" fill="#000" fill-opacity=".87" style=""/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 13 KiB

482
application/src/main/data/json/system/scada_symbols/energy-meter-hp.svg

@ -0,0 +1,482 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:tb="https://thingsboard.io/svg" width="400" height="400" fill="none" version="1.1" viewBox="0 0 400 400"><tb:metadata xmlns=""><![CDATA[{
"title": "HP Energy meter",
"description": "Energy meter with various states.",
"searchTags": [
"power",
"energy"
],
"widgetSizeX": 2,
"widgetSizeY": 2,
"tags": [
{
"tag": "background",
"stateRenderFunction": "var color = ctx.properties.stoppedColor;\nif (ctx.values.running) {\n color = ctx.properties.runningColor;\n}\nelement.attr({fill: color});",
"actions": null
},
{
"tag": "clickArea",
"stateRenderFunction": null,
"actions": {
"click": {
"actionFunction": "ctx.api.callAction(event, 'click');"
}
}
},
{
"tag": "critical",
"stateRenderFunction": "element.attr({fill: ctx.properties.criticalColor});\nif (ctx.values.critical) {\n element.show();\n} else {\n element.hide();\n}\n\nvar elementCriticalAnimation = element.remember('criticalAnimation');\nvar criticalAnimation = ctx.values.critical && ctx.values.criticalAnimation;\n\nif (elementCriticalAnimation !== criticalAnimation) {\n element.remember('criticalAnimation', criticalAnimation);\n if (criticalAnimation) {\n ctx.api.cssAnimate(element, 500).attr({opacity: 0.15}).loop(0, true);\n } else {\n ctx.api.resetCssAnimation(element);\n }\n}\n\n",
"actions": {
"click": {
"actionFunction": "ctx.api.callAction(event, 'criticalClick');"
}
}
},
{
"tag": "label",
"stateRenderFunction": "if (ctx.properties.showLabel) {\n element.show();\n ctx.api.font(element, ctx.properties.labelFont, ctx.properties.labelColor);\n ctx.api.text(element, ctx.properties.label);\n} else {\n element.hide();\n}",
"actions": null
},
{
"tag": "units",
"stateRenderFunction": "if (ctx.properties.showUnits) {\n element.show();\n ctx.api.font(element, ctx.properties.unitsFont, ctx.properties.unitsColor);\n ctx.api.text(element, ctx.properties.units);\n} else {\n element.hide();\n}",
"actions": null
},
{
"tag": "value",
"stateRenderFunction": "ctx.api.font(element, ctx.properties.valueFont, ctx.properties.valueColor);\nctx.api.text(element, ctx.api.formatValue(ctx.values.measured, 0, null, 0));",
"actions": null
},
{
"tag": "value-box",
"stateRenderFunction": "var color = ctx.properties.stoppedColor;\nif (ctx.values.running) {\n color = ctx.properties.valueBoxBackground;\n}\nelement.attr({fill: color});",
"actions": null
},
{
"tag": "warning",
"stateRenderFunction": "element.attr({fill: ctx.properties.warningColor});\nvar warning = ctx.values.warning && !(ctx.values.warning && ctx.values.critical)\nif (warning) {\n element.show();\n} else {\n element.hide();\n}\n\nvar elementCriticalAnimation = element.remember('criticalAnimation');\nvar criticalAnimation = warning && ctx.values.criticalAnimation;\n\nif (elementCriticalAnimation !== criticalAnimation) {\n element.remember('criticalAnimation', criticalAnimation);\n if (criticalAnimation) {\n ctx.api.cssAnimate(element, 500).attr({opacity: 0.15}).loop(0, true);\n } else {\n ctx.api.resetCssAnimation(element);\n }\n}\n",
"actions": {
"click": {
"actionFunction": "ctx.api.callAction(event, 'warningClick');"
}
}
}
],
"behavior": [
{
"id": "running",
"name": "{i18n:scada.symbol.running}",
"hint": "{i18n:scada.symbol.running-hint}",
"group": null,
"type": "value",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": "{i18n:scada.symbol.running}",
"defaultGetValueSettings": {
"action": "GET_ATTRIBUTE",
"defaultValue": false,
"executeRpc": {
"method": "getState",
"requestTimeout": 5000,
"requestPersistent": false,
"persistentPollingInterval": 1000
},
"getAttribute": {
"scope": "SHARED_SCOPE",
"key": "running"
},
"getTimeSeries": {
"key": "state"
},
"getAlarmStatus": {
"severityList": null,
"typeList": null
},
"dataToValue": {
"type": "NONE",
"dataToValueFunction": "/* Should return boolean value */\nreturn data;",
"compareToValue": true
}
},
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": null
},
{
"id": "measured",
"name": "{i18n:scada.symbol.measured}",
"hint": "{i18n:scada.symbol.measured-hint}",
"group": null,
"type": "value",
"valueType": "DOUBLE",
"trueLabel": null,
"falseLabel": null,
"stateLabel": null,
"defaultGetValueSettings": {
"action": "GET_TIME_SERIES",
"defaultValue": null,
"executeRpc": {
"method": "getState",
"requestTimeout": 5000,
"requestPersistent": false,
"persistentPollingInterval": 1000
},
"getAttribute": {
"scope": null,
"key": "state"
},
"getTimeSeries": {
"key": "measured"
},
"getAlarmStatus": {
"severityList": null,
"typeList": null
},
"dataToValue": {
"type": "NONE",
"dataToValueFunction": "/* Should return boolean value */\nreturn data;"
}
},
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": null
},
{
"id": "warning",
"name": "{i18n:scada.symbol.warning}",
"hint": "{i18n:scada.symbol.warning-state-hint}",
"group": "{i18n:scada.symbol.warning-state}",
"type": "value",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": "{i18n:scada.symbol.warning}",
"defaultGetValueSettings": {
"action": "GET_ALARM_STATUS",
"defaultValue": false,
"executeRpc": {
"method": "getState",
"requestTimeout": 5000,
"requestPersistent": false,
"persistentPollingInterval": 1000
},
"getAttribute": {
"scope": null,
"key": "state"
},
"getTimeSeries": {
"key": "state"
},
"getAlarmStatus": {
"severityList": [
"MAJOR",
"MINOR",
"WARNING",
"INDETERMINATE"
],
"typeList": null
},
"dataToValue": {
"type": "NONE",
"dataToValueFunction": "/* Should return boolean value */\nreturn data;",
"compareToValue": true
}
},
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": null
},
{
"id": "warningClick",
"name": "{i18n:scada.symbol.warning-click}",
"hint": "{i18n:scada.symbol.on-click-hint}",
"group": "{i18n:scada.symbol.warning-state}",
"type": "widgetAction",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": null,
"defaultGetValueSettings": null,
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": {
"type": "doNothing",
"targetDashboardStateId": null,
"openRightLayout": false,
"setEntityId": false,
"stateEntityParamName": null
}
},
{
"id": "critical",
"name": "{i18n:scada.symbol.critical}",
"hint": "{i18n:scada.symbol.critical-state-hint}",
"group": "{i18n:scada.symbol.critical-state}",
"type": "value",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": "{i18n:scada.symbol.critical}",
"defaultGetValueSettings": {
"action": "GET_ALARM_STATUS",
"defaultValue": false,
"executeRpc": {
"method": "getState",
"requestTimeout": 5000,
"requestPersistent": false,
"persistentPollingInterval": 1000
},
"getAttribute": {
"scope": null,
"key": "state"
},
"getTimeSeries": {
"key": "state"
},
"getAlarmStatus": {
"severityList": [
"CRITICAL"
],
"typeList": null
},
"dataToValue": {
"type": "NONE",
"dataToValueFunction": "/* Should return boolean value */\nreturn data;",
"compareToValue": true
}
},
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": null
},
{
"id": "criticalClick",
"name": "{i18n:scada.symbol.critical-click}",
"hint": "{i18n:scada.symbol.on-click-hint}",
"group": "{i18n:scada.symbol.critical-state}",
"type": "widgetAction",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": null,
"defaultGetValueSettings": null,
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": {
"type": "doNothing",
"targetDashboardStateId": null,
"openRightLayout": false,
"setEntityId": false,
"stateEntityParamName": null
}
},
{
"id": "criticalAnimation",
"name": "{i18n:scada.symbol.warning-critical-state-animation}",
"hint": "{i18n:scada.symbol.warning-critical-state-animation-hint}",
"group": null,
"type": "value",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": "{i18n:scada.symbol.animation}",
"defaultGetValueSettings": {
"action": "DO_NOTHING",
"defaultValue": false,
"executeRpc": {
"method": "getState",
"requestTimeout": 5000,
"requestPersistent": false,
"persistentPollingInterval": 1000
},
"getAttribute": {
"key": "state",
"scope": null
},
"getTimeSeries": {
"key": "state"
},
"dataToValue": {
"type": "NONE",
"compareToValue": true,
"dataToValueFunction": "/* Should return boolean value */\nreturn data;"
}
},
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": null
},
{
"id": "click",
"name": "{i18n:scada.symbol.on-click}",
"hint": "{i18n:scada.symbol.on-click-hint}",
"group": null,
"type": "widgetAction",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": null,
"defaultGetValueSettings": null,
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": {
"type": "doNothing",
"targetDashboardStateId": null,
"openRightLayout": false,
"setEntityId": false,
"stateEntityParamName": null
}
}
],
"properties": [
{
"id": "runningColor",
"name": "{i18n:scada.symbol.colors}",
"type": "color",
"default": "#FFFFFF",
"subLabel": "{i18n:scada.symbol.running}",
"divider": true,
"disabled": false,
"visible": true
},
{
"id": "stoppedColor",
"name": "{i18n:scada.symbol.colors}",
"type": "color",
"default": "#666666",
"subLabel": "{i18n:scada.symbol.stopped}",
"disabled": false,
"visible": true
},
{
"id": "showLabel",
"name": "{i18n:scada.symbol.label}",
"type": "switch",
"default": true,
"disabled": false,
"visible": true
},
{
"id": "label",
"name": "{i18n:scada.symbol.label}",
"type": "text",
"default": "T1",
"fieldClass": "medium-width",
"disabled": false,
"visible": true
},
{
"id": "labelFont",
"name": "{i18n:scada.symbol.label}",
"type": "font",
"default": {
"size": 36,
"sizeUnit": "px",
"family": "Roboto",
"weight": "400",
"style": "normal"
},
"disabled": false,
"visible": true
},
{
"id": "labelColor",
"name": "{i18n:scada.symbol.label}",
"type": "color",
"default": "#000",
"disabled": false,
"visible": true
},
{
"id": "showUnits",
"name": "{i18n:scada.symbol.units}",
"type": "switch",
"default": true,
"disabled": false,
"visible": true
},
{
"id": "units",
"name": "{i18n:scada.symbol.units}",
"type": "units",
"default": "kWh",
"disabled": false,
"visible": true
},
{
"id": "unitsFont",
"name": "{i18n:scada.symbol.units}",
"type": "font",
"default": {
"size": 36,
"sizeUnit": "px",
"family": "Roboto",
"weight": "500",
"style": "normal"
},
"disabled": false,
"visible": true
},
{
"id": "unitsColor",
"name": "{i18n:scada.symbol.units}",
"type": "color",
"default": "#000",
"disabled": false,
"visible": true
},
{
"id": "valueFont",
"name": "{i18n:scada.symbol.value}",
"type": "font",
"default": {
"size": 48,
"sizeUnit": "px",
"family": "Roboto",
"weight": "500",
"style": "normal"
},
"disabled": false,
"visible": true
},
{
"id": "valueColor",
"name": "{i18n:scada.symbol.value}",
"type": "color",
"default": "#002878",
"disabled": false,
"visible": true
},
{
"id": "valueBoxBackground",
"name": "{i18n:scada.symbol.value-box-background}",
"type": "color",
"default": "#DEDEDE",
"disabled": false,
"visible": true
},
{
"id": "warningColor",
"name": "{i18n:scada.symbol.alarm-colors}",
"type": "color",
"default": "#FAA405",
"subLabel": "{i18n:scada.symbol.warning}",
"divider": true,
"disabled": false,
"visible": true
},
{
"id": "criticalColor",
"name": "{i18n:scada.symbol.alarm-colors}",
"type": "color",
"default": "#D12730",
"subLabel": "{i18n:scada.symbol.critical}",
"disabled": false,
"visible": true
}
]
}]]></tb:metadata>
<rect x="1" y="1" width="398" height="398" fill="#fff" stroke="#1A1A1A" stroke-width="2" tb:tag="background"/><rect x="49" y="143" width="302" height="114" rx="3" fill="#DEDEDE" stroke="#1A1A1A" stroke-width="2" tb:tag="value-box"/><text x="199.83594" y="217.64844" fill="#002878" font-family="Roboto" font-size="48px" font-weight="400" text-anchor="middle" tb:tag="value" xml:space="preserve"><tspan dominant-baseline="start">000023</tspan></text><text x="199.89453" y="341.65625" fill="#000000" font-family="Roboto" font-size="36px" font-weight="400" text-anchor="middle" tb:tag="units" xml:space="preserve"><tspan dominant-baseline="start">kWh</tspan></text><text x="199.70117" y="83.648438" fill="#000000" font-family="Roboto" font-size="34px" font-weight="400" text-anchor="middle" tb:tag="label" xml:space="default"><tspan dominant-baseline="start">T1</tspan></text><path d="m134.53-2e-4s-134.53 0-134.53 67v328.36c0 2.6512 3.5818 4.6404 8 4.6404h384c4.418 0 8-1.9892 8-4.6404v-328.36c0-67-132.14-67-132.14-67h-67.858zm134.14 81.2c-2.5774 0-4.6666 1.2536-4.6666 2.8v300.4c0 1.5464 2.0894 2.8 4.6666 2.8h29.332c2.5774 0 4.6666-1.2536 4.6666-2.8v-300.4c0-1.5464-2.0894-2.8-4.6666-2.8z" fill="#000" fill-opacity="0" tb:tag="clickArea"/><g fill="#d12730" style="display: none;" tb:tag="critical">
<rect width="84" height="84" rx="4" fill="#fff" style=""/>
<rect width="84" height="84" rx="4" style=""/>
<rect x="2" y="2" width="80" height="80" rx="2" stroke="#000" stroke-opacity=".87" stroke-width="4" style=""/>
<path d="m44.559 27.562-0.4688 20.059h-4.0234l-0.4883-20.059zm-5.1172 26.211c0-0.7161 0.2344-1.3151 0.7031-1.7968 0.4818-0.4948 1.1459-0.7422 1.9922-0.7422 0.8334 0 1.4909 0.2474 1.9727 0.7422 0.4817 0.4817 0.7226 1.0807 0.7226 1.7968 0 0.6901-0.2409 1.2826-0.7226 1.7774-0.4818 0.4818-1.1393 0.7226-1.9727 0.7226-0.8463 0-1.5104-0.2408-1.9922-0.7226-0.4687-0.4948-0.7031-1.0873-0.7031-1.7774z" fill="#000" fill-opacity=".87" style=""/>
</g><g fill="#faa405" style="display: none;" tb:tag="warning">
<path d="m35.955 2.2112c1.4741-2.9482 5.6813-2.9482 7.1554 0l35.528 71.056c1.3298 2.6596-0.6042 5.7889-3.5777 5.7889h-71.056c-2.9735 0-4.9075-3.1292-3.5777-5.7889z" fill="#fff" style=""/>
<path d="m35.955 2.2112c1.4741-2.9482 5.6813-2.9482 7.1554 0l35.528 71.056c1.3298 2.6596-0.6042 5.7889-3.5777 5.7889h-71.056c-2.9735 0-4.9075-3.1292-3.5777-5.7889z" style=""/>
<path d="m37.72 3.1061c0.7371-1.4741 2.8407-1.4741 3.5778-1e-5l35.528 71.056c0.6649 1.3298-0.3021 2.8944-1.7888 2.8944h-71.056c-1.4868 0-2.4538-1.5646-1.7889-2.8944z" stroke="#000" stroke-opacity=".87" stroke-width="4" style=""/>
<path d="m42.092 32.618-0.4688 20.059h-4.0234l-0.4883-20.059zm-5.1172 26.211c0-0.7161 0.2344-1.3151 0.7031-1.7968 0.4818-0.4948 1.1459-0.7422 1.9922-0.7422 0.8334 0 1.4909 0.2474 1.9727 0.7422 0.4817 0.4817 0.7226 1.0807 0.7226 1.7968 0 0.6901-0.2409 1.2826-0.7226 1.7774-0.4818 0.4818-1.1393 0.7226-1.9727 0.7226-0.8463 0-1.5104-0.2408-1.9922-0.7226-0.4687-0.4948-0.7031-1.0873-0.7031-1.7774z" fill="#000" fill-opacity=".87" style=""/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 17 KiB

876
application/src/main/data/json/system/scada_symbols/four-rate-energy-meter-hp.svg

@ -0,0 +1,876 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:tb="https://thingsboard.io/svg" width="600" height="400" fill="none" version="1.1" viewBox="0 0 600 400"><tb:metadata xmlns=""><![CDATA[{
"title": "HP Four-rate energy meter",
"description": "Four-rate energy meter with various states.",
"searchTags": [
"power",
"energy"
],
"widgetSizeX": 3,
"widgetSizeY": 2,
"tags": [
{
"tag": "background",
"stateRenderFunction": "var color = ctx.properties.stoppedColor;\nif (ctx.values.running) {\n color = ctx.properties.runningColor;\n}\nelement.attr({fill: color});",
"actions": null
},
{
"tag": "clickArea",
"stateRenderFunction": null,
"actions": {
"click": {
"actionFunction": "ctx.api.callAction(event, 'click');"
}
}
},
{
"tag": "critical",
"stateRenderFunction": "element.attr({fill: ctx.properties.criticalColor});\nif (ctx.values.critical) {\n element.show();\n} else {\n element.hide();\n}\n\nvar elementCriticalAnimation = element.remember('criticalAnimation');\nvar criticalAnimation = ctx.values.critical && ctx.values.criticalAnimation;\n\nif (elementCriticalAnimation !== criticalAnimation) {\n element.remember('criticalAnimation', criticalAnimation);\n if (criticalAnimation) {\n ctx.api.cssAnimate(element, 500).attr({opacity: 0.15}).loop(0, true);\n } else {\n ctx.api.resetCssAnimation(element);\n }\n}\n\n",
"actions": {
"click": {
"actionFunction": "ctx.api.callAction(event, 'criticalClick');"
}
}
},
{
"tag": "export-label",
"stateRenderFunction": "if (ctx.properties.showExportLabel) {\n element.show();\n ctx.api.font(element, ctx.properties.exportLabelFont, ctx.properties.exportLabelColor);\n ctx.api.text(element, ctx.properties.exportLabel);\n} else {\n element.hide();\n}",
"actions": null
},
{
"tag": "export-rate",
"stateRenderFunction": "ctx.api.font(element, ctx.properties.exportValueFont, ctx.properties.exportValueColor);\nctx.api.text(element, ctx.api.formatValue(ctx.values.exportRate, 0, null, 0));",
"actions": null
},
{
"tag": "night-label",
"stateRenderFunction": "if (ctx.properties.showNightLabel) {\n element.show();\n ctx.api.font(element, ctx.properties.nightLabelFont, ctx.properties.nightLabelColor);\n ctx.api.text(element, ctx.properties.nightLabel);\n} else {\n element.hide();\n}",
"actions": null
},
{
"tag": "night-rate",
"stateRenderFunction": "ctx.api.font(element, ctx.properties.nightValueFont, ctx.properties.nightValueColor);\nctx.api.text(element, ctx.api.formatValue(ctx.values.nightRate, 0, null, 0));",
"actions": null
},
{
"tag": "off-peak-label",
"stateRenderFunction": "if (ctx.properties.showOffPeakLabel) {\n element.show();\n ctx.api.font(element, ctx.properties.offPeakLabelFont, ctx.properties.offPeakLabelColor);\n ctx.api.text(element, ctx.properties.offPeakLabel);\n} else {\n element.hide();\n}",
"actions": null
},
{
"tag": "off-peak-rate",
"stateRenderFunction": "ctx.api.font(element, ctx.properties.offPeakValueFont, ctx.properties.offPeakValueColor);\nctx.api.text(element, ctx.api.formatValue(ctx.values.offPeakRate, 0, null, 0));",
"actions": null
},
{
"tag": "peak-label",
"stateRenderFunction": "if (ctx.properties.showPeakLabel) {\n element.show();\n ctx.api.font(element, ctx.properties.peakLabelFont, ctx.properties.peakLabelColor);\n ctx.api.text(element, ctx.properties.peakLabel);\n} else {\n element.hide();\n}",
"actions": null
},
{
"tag": "peak-rate",
"stateRenderFunction": "ctx.api.font(element, ctx.properties.peakValueFont, ctx.properties.peakValueColor);\nctx.api.text(element, ctx.api.formatValue(ctx.values.peakRate, 0, null, 0));",
"actions": null
},
{
"tag": "units",
"stateRenderFunction": "if (ctx.properties.showUnits) {\n element.show();\n ctx.api.font(element, ctx.properties.unitsFont, ctx.properties.unitsColor);\n ctx.api.text(element, ctx.properties.units);\n} else {\n element.hide();\n}",
"actions": null
},
{
"tag": "value-box-export",
"stateRenderFunction": "var color = ctx.properties.stoppedColor;\nif (ctx.values.running) {\n color = ctx.properties.exportValueBoxBackground;\n}\nelement.attr({fill: color});",
"actions": null
},
{
"tag": "value-box-night",
"stateRenderFunction": "var color = ctx.properties.stoppedColor;\nif (ctx.values.running) {\n color = ctx.properties.nightValueBoxBackground;\n}\nelement.attr({fill: color});",
"actions": null
},
{
"tag": "value-box-off-peak",
"stateRenderFunction": "var color = ctx.properties.stoppedColor;\nif (ctx.values.running) {\n color = ctx.properties.offPeakValueBoxBackground;\n}\nelement.attr({fill: color});",
"actions": null
},
{
"tag": "value-box-peak",
"stateRenderFunction": "var color = ctx.properties.stoppedColor;\nif (ctx.values.running) {\n color = ctx.properties.peakValueBoxBackground;\n}\nelement.attr({fill: color});",
"actions": null
},
{
"tag": "warning",
"stateRenderFunction": "element.attr({fill: ctx.properties.warningColor});\nvar warning = ctx.values.warning && !(ctx.values.warning && ctx.values.critical)\nif (warning) {\n element.show();\n} else {\n element.hide();\n}\n\nvar elementCriticalAnimation = element.remember('criticalAnimation');\nvar criticalAnimation = warning && ctx.values.criticalAnimation;\n\nif (elementCriticalAnimation !== criticalAnimation) {\n element.remember('criticalAnimation', criticalAnimation);\n if (criticalAnimation) {\n ctx.api.cssAnimate(element, 500).attr({opacity: 0.15}).loop(0, true);\n } else {\n ctx.api.resetCssAnimation(element);\n }\n}\n",
"actions": {
"click": {
"actionFunction": "ctx.api.callAction(event, 'warningClick');"
}
}
}
],
"behavior": [
{
"id": "running",
"name": "{i18n:scada.symbol.running}",
"hint": "{i18n:scada.symbol.running-hint}",
"group": null,
"type": "value",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": "{i18n:scada.symbol.running}",
"defaultGetValueSettings": {
"action": "GET_ATTRIBUTE",
"defaultValue": false,
"executeRpc": {
"method": "getState",
"requestTimeout": 5000,
"requestPersistent": false,
"persistentPollingInterval": 1000
},
"getAttribute": {
"scope": "SHARED_SCOPE",
"key": "running"
},
"getTimeSeries": {
"key": "state"
},
"getAlarmStatus": {
"severityList": null,
"typeList": null
},
"dataToValue": {
"type": "NONE",
"dataToValueFunction": "/* Should return boolean value */\nreturn data;",
"compareToValue": true
}
},
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": null
},
{
"id": "offPeakRate",
"name": "{i18n:scada.symbol.off-peak-rate}",
"hint": "{i18n:scada.symbol.measured-hint}",
"group": null,
"type": "value",
"valueType": "DOUBLE",
"trueLabel": null,
"falseLabel": null,
"stateLabel": null,
"defaultGetValueSettings": {
"action": "GET_TIME_SERIES",
"defaultValue": null,
"executeRpc": {
"method": "getState",
"requestTimeout": 5000,
"requestPersistent": false,
"persistentPollingInterval": 1000
},
"getAttribute": {
"scope": null,
"key": "state"
},
"getTimeSeries": {
"key": "offPeakRate"
},
"getAlarmStatus": {
"severityList": null,
"typeList": null
},
"dataToValue": {
"type": "NONE",
"dataToValueFunction": "/* Should return boolean value */\nreturn data;"
}
},
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": null
},
{
"id": "nightRate",
"name": "{i18n:scada.symbol.night-rate}",
"hint": "{i18n:scada.symbol.measured-hint}",
"group": null,
"type": "value",
"valueType": "DOUBLE",
"trueLabel": null,
"falseLabel": null,
"stateLabel": null,
"defaultGetValueSettings": {
"action": "GET_TIME_SERIES",
"defaultValue": null,
"executeRpc": {
"method": "getState",
"requestTimeout": 5000,
"requestPersistent": false,
"persistentPollingInterval": 1000
},
"getAttribute": {
"scope": null,
"key": "state"
},
"getTimeSeries": {
"key": "nightRate"
},
"getAlarmStatus": {
"severityList": null,
"typeList": null
},
"dataToValue": {
"type": "NONE",
"dataToValueFunction": "/* Should return boolean value */\nreturn data;"
}
},
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": null
},
{
"id": "peakRate",
"name": "{i18n:scada.symbol.peak-rate}",
"hint": "{i18n:scada.symbol.measured-hint}",
"group": null,
"type": "value",
"valueType": "DOUBLE",
"trueLabel": null,
"falseLabel": null,
"stateLabel": null,
"defaultGetValueSettings": {
"action": "GET_TIME_SERIES",
"defaultValue": null,
"executeRpc": {
"method": "getState",
"requestTimeout": 5000,
"requestPersistent": false,
"persistentPollingInterval": 1000
},
"getAttribute": {
"scope": null,
"key": "state"
},
"getTimeSeries": {
"key": "peakRate"
},
"getAlarmStatus": {
"severityList": null,
"typeList": null
},
"dataToValue": {
"type": "NONE",
"dataToValueFunction": "/* Should return boolean value */\nreturn data;"
}
},
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": null
},
{
"id": "exportRate",
"name": "{i18n:scada.symbol.export-rate}",
"hint": "{i18n:scada.symbol.measured-hint}",
"group": null,
"type": "value",
"valueType": "DOUBLE",
"trueLabel": null,
"falseLabel": null,
"stateLabel": null,
"defaultGetValueSettings": {
"action": "GET_TIME_SERIES",
"defaultValue": null,
"executeRpc": {
"method": "getState",
"requestTimeout": 5000,
"requestPersistent": false,
"persistentPollingInterval": 1000
},
"getAttribute": {
"scope": null,
"key": "state"
},
"getTimeSeries": {
"key": "exportRate"
},
"getAlarmStatus": {
"severityList": null,
"typeList": null
},
"dataToValue": {
"type": "NONE",
"dataToValueFunction": "/* Should return boolean value */\nreturn data;"
}
},
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": null
},
{
"id": "warning",
"name": "{i18n:scada.symbol.warning}",
"hint": "{i18n:scada.symbol.warning-state-hint}",
"group": "{i18n:scada.symbol.warning-state}",
"type": "value",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": "{i18n:scada.symbol.warning}",
"defaultGetValueSettings": {
"action": "GET_ALARM_STATUS",
"defaultValue": false,
"executeRpc": {
"method": "getState",
"requestTimeout": 5000,
"requestPersistent": false,
"persistentPollingInterval": 1000
},
"getAttribute": {
"scope": null,
"key": "state"
},
"getTimeSeries": {
"key": "state"
},
"getAlarmStatus": {
"severityList": [
"MAJOR",
"MINOR",
"WARNING",
"INDETERMINATE"
],
"typeList": null
},
"dataToValue": {
"type": "NONE",
"dataToValueFunction": "/* Should return boolean value */\nreturn data;",
"compareToValue": true
}
},
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": null
},
{
"id": "warningClick",
"name": "{i18n:scada.symbol.warning-click}",
"hint": "{i18n:scada.symbol.on-click-hint}",
"group": "{i18n:scada.symbol.warning-state}",
"type": "widgetAction",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": null,
"defaultGetValueSettings": null,
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": {
"type": "doNothing",
"targetDashboardStateId": null,
"openRightLayout": false,
"setEntityId": false,
"stateEntityParamName": null
}
},
{
"id": "critical",
"name": "{i18n:scada.symbol.critical}",
"hint": "{i18n:scada.symbol.critical-state-hint}",
"group": "{i18n:scada.symbol.critical-state}",
"type": "value",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": "{i18n:scada.symbol.critical}",
"defaultGetValueSettings": {
"action": "GET_ALARM_STATUS",
"defaultValue": false,
"executeRpc": {
"method": "getState",
"requestTimeout": 5000,
"requestPersistent": false,
"persistentPollingInterval": 1000
},
"getAttribute": {
"scope": null,
"key": "state"
},
"getTimeSeries": {
"key": "state"
},
"getAlarmStatus": {
"severityList": [
"CRITICAL"
],
"typeList": null
},
"dataToValue": {
"type": "NONE",
"dataToValueFunction": "/* Should return boolean value */\nreturn data;",
"compareToValue": true
}
},
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": null
},
{
"id": "criticalClick",
"name": "{i18n:scada.symbol.critical-click}",
"hint": "{i18n:scada.symbol.on-click-hint}",
"group": "{i18n:scada.symbol.critical-state}",
"type": "widgetAction",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": null,
"defaultGetValueSettings": null,
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": {
"type": "doNothing",
"targetDashboardStateId": null,
"openRightLayout": false,
"setEntityId": false,
"stateEntityParamName": null
}
},
{
"id": "criticalAnimation",
"name": "{i18n:scada.symbol.warning-critical-state-animation}",
"hint": "{i18n:scada.symbol.warning-critical-state-animation-hint}",
"group": null,
"type": "value",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": "{i18n:scada.symbol.animation}",
"defaultGetValueSettings": {
"action": "DO_NOTHING",
"defaultValue": false,
"executeRpc": {
"method": "getState",
"requestTimeout": 5000,
"requestPersistent": false,
"persistentPollingInterval": 1000
},
"getAttribute": {
"key": "state",
"scope": null
},
"getTimeSeries": {
"key": "state"
},
"dataToValue": {
"type": "NONE",
"compareToValue": true,
"dataToValueFunction": "/* Should return boolean value */\nreturn data;"
}
},
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": null
},
{
"id": "click",
"name": "{i18n:scada.symbol.on-click}",
"hint": "{i18n:scada.symbol.on-click-hint}",
"group": null,
"type": "widgetAction",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": null,
"defaultGetValueSettings": null,
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": {
"type": "doNothing",
"targetDashboardStateId": null,
"openRightLayout": false,
"setEntityId": false,
"stateEntityParamName": null
}
}
],
"properties": [
{
"id": "runningColor",
"name": "{i18n:scada.symbol.colors}",
"type": "color",
"default": "#FFFFFF",
"subLabel": "{i18n:scada.symbol.running}",
"divider": true,
"disabled": false,
"visible": true
},
{
"id": "stoppedColor",
"name": "{i18n:scada.symbol.colors}",
"type": "color",
"default": "#666666",
"subLabel": "{i18n:scada.symbol.stopped}",
"disabled": false,
"visible": true
},
{
"id": "warningColor",
"name": "{i18n:scada.symbol.alarm-colors}",
"type": "color",
"default": "#FAA405",
"subLabel": "{i18n:scada.symbol.warning}",
"divider": true,
"disabled": false,
"visible": true
},
{
"id": "criticalColor",
"name": "{i18n:scada.symbol.alarm-colors}",
"type": "color",
"default": "#D12730",
"subLabel": "{i18n:scada.symbol.critical}",
"disabled": false,
"visible": true
},
{
"id": "showOffPeakLabel",
"name": "{i18n:scada.symbol.label}",
"group": "{i18n:scada.symbol.off-peak-rate}",
"type": "switch",
"default": true,
"disabled": false,
"visible": true
},
{
"id": "offPeakLabel",
"name": "{i18n:scada.symbol.label}",
"group": "{i18n:scada.symbol.off-peak-rate}",
"type": "text",
"default": "T1",
"fieldClass": "medium-width",
"disabled": false,
"visible": true
},
{
"id": "offPeakLabelFont",
"name": "{i18n:scada.symbol.label}",
"group": "{i18n:scada.symbol.off-peak-rate}",
"type": "font",
"default": {
"size": 36,
"sizeUnit": "px",
"family": "Roboto",
"weight": "normal",
"style": "normal"
},
"disabled": false,
"visible": true
},
{
"id": "offPeakLabelColor",
"name": "{i18n:scada.symbol.label}",
"group": "{i18n:scada.symbol.off-peak-rate}",
"type": "color",
"default": "#000000",
"disabled": false,
"visible": true
},
{
"id": "offPeakValueFont",
"name": "{i18n:scada.symbol.value}",
"group": "{i18n:scada.symbol.off-peak-rate}",
"type": "font",
"default": {
"size": 48,
"sizeUnit": "px",
"family": "Roboto",
"weight": "normal",
"style": "normal"
},
"disabled": false,
"visible": true
},
{
"id": "offPeakValueColor",
"name": "{i18n:scada.symbol.value}",
"group": "{i18n:scada.symbol.off-peak-rate}",
"type": "color",
"default": "#002878",
"disabled": false,
"visible": true
},
{
"id": "offPeakValueBoxBackground",
"name": "{i18n:scada.symbol.value-box-background}",
"group": "{i18n:scada.symbol.off-peak-rate}",
"type": "color",
"default": "#DEDEDE",
"disabled": false,
"visible": true
},
{
"id": "showNightLabel",
"name": "{i18n:scada.symbol.label}",
"group": "{i18n:scada.symbol.night-rate}",
"type": "switch",
"default": true,
"disabled": false,
"visible": true
},
{
"id": "nightLabel",
"name": "{i18n:scada.symbol.label}",
"group": "{i18n:scada.symbol.night-rate}",
"type": "text",
"default": "T2",
"fieldClass": "medium-width",
"disabled": false,
"visible": true
},
{
"id": "nightLabelFont",
"name": "{i18n:scada.symbol.label}",
"group": "{i18n:scada.symbol.night-rate}",
"type": "font",
"default": {
"size": 36,
"sizeUnit": "px",
"family": "Roboto",
"weight": "normal",
"style": "normal"
},
"disabled": false,
"visible": true
},
{
"id": "nightLabelColor",
"name": "{i18n:scada.symbol.label}",
"group": "{i18n:scada.symbol.night-rate}",
"type": "color",
"default": "#000",
"disabled": false,
"visible": true
},
{
"id": "nightValueFont",
"name": "{i18n:scada.symbol.value}",
"group": "{i18n:scada.symbol.night-rate}",
"type": "font",
"default": {
"size": 48,
"sizeUnit": "px",
"family": "Roboto",
"weight": "normal",
"style": "normal"
},
"disabled": false,
"visible": true
},
{
"id": "nightValueColor",
"name": "{i18n:scada.symbol.value}",
"group": "{i18n:scada.symbol.night-rate}",
"type": "color",
"default": "#002878",
"disabled": false,
"visible": true
},
{
"id": "nightValueBoxBackground",
"name": "{i18n:scada.symbol.value-box-background}",
"group": "{i18n:scada.symbol.night-rate}",
"type": "color",
"default": "#DEDEDE",
"disabled": false,
"visible": true
},
{
"id": "showPeakLabel",
"name": "{i18n:scada.symbol.label}",
"group": "{i18n:scada.symbol.peak-rate}",
"type": "switch",
"default": true,
"disabled": false,
"visible": true
},
{
"id": "peakLabel",
"name": "{i18n:scada.symbol.label}",
"group": "{i18n:scada.symbol.peak-rate}",
"type": "text",
"default": "T3",
"fieldClass": "medium-width",
"disabled": false,
"visible": true
},
{
"id": "peakLabelFont",
"name": "{i18n:scada.symbol.label}",
"group": "{i18n:scada.symbol.peak-rate}",
"type": "font",
"default": {
"size": 36,
"sizeUnit": "px",
"family": "Roboto",
"weight": "normal",
"style": "normal"
},
"disabled": false,
"visible": true
},
{
"id": "peakLabelColor",
"name": "{i18n:scada.symbol.label}",
"group": "{i18n:scada.symbol.peak-rate}",
"type": "color",
"default": "#000",
"disabled": false,
"visible": true
},
{
"id": "peakValueFont",
"name": "{i18n:scada.symbol.value}",
"group": "{i18n:scada.symbol.peak-rate}",
"type": "font",
"default": {
"size": 48,
"sizeUnit": "px",
"family": "Roboto",
"weight": "normal",
"style": "normal"
},
"disabled": false,
"visible": true
},
{
"id": "peakValueColor",
"name": "{i18n:scada.symbol.value}",
"group": "{i18n:scada.symbol.peak-rate}",
"type": "color",
"default": "#002878",
"disabled": false,
"visible": true
},
{
"id": "peakValueBoxBackground",
"name": "{i18n:scada.symbol.value-box-background}",
"group": "{i18n:scada.symbol.peak-rate}",
"type": "color",
"default": "#DEDEDE",
"disabled": false,
"visible": true
},
{
"id": "showExportLabel",
"name": "{i18n:scada.symbol.label}",
"group": "{i18n:scada.symbol.export-rate}",
"type": "switch",
"default": true,
"disabled": false,
"visible": true
},
{
"id": "exportLabel",
"name": "{i18n:scada.symbol.label}",
"group": "{i18n:scada.symbol.export-rate}",
"type": "text",
"default": "Export",
"fieldClass": "medium-width",
"disabled": false,
"visible": true
},
{
"id": "exportLabelFont",
"name": "{i18n:scada.symbol.label}",
"group": "{i18n:scada.symbol.export-rate}",
"type": "font",
"default": {
"size": 36,
"sizeUnit": "px",
"family": "Roboto",
"weight": "normal",
"style": "normal"
},
"disabled": false,
"visible": true
},
{
"id": "exportLabelColor",
"name": "{i18n:scada.symbol.label}",
"group": "{i18n:scada.symbol.export-rate}",
"type": "color",
"default": "#000",
"disabled": false,
"visible": true
},
{
"id": "exportValueFont",
"name": "{i18n:scada.symbol.value}",
"group": "{i18n:scada.symbol.export-rate}",
"type": "font",
"default": {
"size": 48,
"sizeUnit": "px",
"family": "Roboto",
"weight": "normal",
"style": "normal"
},
"disabled": false,
"visible": true
},
{
"id": "exportValueColor",
"name": "{i18n:scada.symbol.value}",
"group": "{i18n:scada.symbol.export-rate}",
"type": "color",
"default": "#002878",
"disabled": false,
"visible": true
},
{
"id": "exportValueBoxBackground",
"name": "{i18n:scada.symbol.value-box-background}",
"group": "{i18n:scada.symbol.export-rate}",
"type": "color",
"default": "#DEDEDE",
"disabled": false,
"visible": true
},
{
"id": "showUnits",
"name": "{i18n:scada.symbol.units}",
"type": "switch",
"default": true,
"disabled": false,
"visible": true
},
{
"id": "units",
"name": "{i18n:scada.symbol.units}",
"type": "units",
"default": "kWh",
"disabled": false,
"visible": true
},
{
"id": "unitsFont",
"name": "{i18n:scada.symbol.units}",
"type": "font",
"default": {
"size": 36,
"sizeUnit": "px",
"family": "Roboto",
"weight": "normal",
"style": "normal"
},
"disabled": false,
"visible": true
},
{
"id": "unitsColor",
"name": "{i18n:scada.symbol.units}",
"type": "color",
"default": "#000",
"disabled": false,
"visible": true
}
]
}]]></tb:metadata>
<rect x="1" y="1" width="598" height="398" fill="#fff" stroke="#1A1A1A" stroke-width="2" tb:tag="background"/><rect x="49" y="81" width="238" height="82" rx="3" fill="#dedede" stroke="#1a1a1a" stroke-width="2" tb:tag="value-box-off-peak"/><rect x="313" y="81" width="238" height="82" rx="3" fill="#dedede" stroke="#1a1a1a" stroke-width="2" tb:tag="value-box-night"/><rect x="49" y="237" width="238" height="82" rx="3" fill="#dedede" stroke="#1a1a1a" stroke-width="2" tb:tag="value-box-peak"/><rect x="313" y="237" width="238" height="82" rx="3" fill="#dedede" stroke="#1a1a1a" stroke-width="2" tb:tag="value-box-export"/><text x="171.2998" y="58.286133" fill="#000000" font-family="Roboto" font-size="34px" font-weight="400" text-anchor="middle" tb:tag="off-peak-label" xml:space="default"><tspan dominant-baseline="start">T1</tspan></text><text x="433.2998" y="58.734375" fill="#000000" font-family="Roboto" font-size="34px" font-weight="400" text-anchor="middle" tb:tag="night-label"><tspan dominant-baseline="start">T2</tspan></text><text x="169.2998" y="214.23438" fill="#000000" font-family="Roboto" font-size="34px" font-weight="400" text-anchor="middle" tb:tag="peak-label" xml:space="default"><tspan dominant-baseline="start">T3</tspan></text><text x="432.31152" y="213.78613" fill="#000000" font-family="Roboto" font-size="34px" font-weight="400" text-anchor="middle" tb:tag="export-label" xml:space="default"><tspan dominant-baseline="start">Export</tspan></text><text x="169.45312" y="139.625" fill="#002878" font-family="Roboto" font-size="48px" font-weight="400" text-anchor="middle" tb:tag="off-peak-rate" xml:space="default"><tspan dominant-baseline="start">000223</tspan></text><text x="433.45312" y="139.625" fill="#002878" font-family="Roboto" font-size="48px" font-weight="400" text-anchor="middle" tb:tag="night-rate" xml:space="default"><tspan dominant-baseline="start">000223</tspan></text><text x="169.45312" y="295.625" fill="#002878" font-family="Roboto" font-size="48px" font-weight="400" text-anchor="middle" tb:tag="peak-rate" xml:space="default"><tspan dominant-baseline="start">000223</tspan></text><text x="433.45312" y="295.625" fill="#002878" font-family="Roboto" font-size="48px" font-weight="400" text-anchor="middle" tb:tag="export-rate" xml:space="default"><tspan dominant-baseline="start">000223</tspan></text><text x="299.89453" y="371.67578" fill="#000000" font-family="Roboto" font-size="36px" font-weight="400" text-anchor="middle" tb:tag="units" xml:space="preserve"><tspan dominant-baseline="start">kWh</tspan></text><path d="m201.8-2e-4s-201.8 0-201.8 67v328.36c0 2.6512 5.3727 4.6404 12 4.6404h576c6.627 0 12-1.9892 12-4.6404v-328.36c0-67-198.21-67-198.21-67h-101.79zm201.21 81.2c-3.8661 0-6.9999 1.2536-6.9999 2.8v300.4c0 1.5464 3.1341 2.8 6.9999 2.8h43.998c3.8661 0 6.9999-1.2536 6.9999-2.8v-300.4c0-1.5464-3.1341-2.8-6.9999-2.8z" fill-opacity="0" tb:tag="clickArea"/><g fill="#d12730" style="display: none;" tb:tag="critical">
<rect width="84" height="84" rx="4" fill="#fff" style=""/>
<rect width="84" height="84" rx="4" style=""/>
<rect x="2" y="2" width="80" height="80" rx="2" stroke="#000" stroke-opacity=".87" stroke-width="4" style=""/>
<path d="m44.559 27.562-0.4688 20.059h-4.0234l-0.4883-20.059zm-5.1172 26.211c0-0.7161 0.2344-1.3151 0.7031-1.7968 0.4818-0.4948 1.1459-0.7422 1.9922-0.7422 0.8334 0 1.4909 0.2474 1.9727 0.7422 0.4817 0.4817 0.7226 1.0807 0.7226 1.7968 0 0.6901-0.2409 1.2826-0.7226 1.7774-0.4818 0.4818-1.1393 0.7226-1.9727 0.7226-0.8463 0-1.5104-0.2408-1.9922-0.7226-0.4687-0.4948-0.7031-1.0873-0.7031-1.7774z" fill="#000" fill-opacity=".87" style=""/>
</g><g fill="#faa405" style="display: none;" tb:tag="warning">
<path d="m35.955 2.2112c1.4741-2.9482 5.6813-2.9482 7.1554 0l35.528 71.056c1.3298 2.6596-0.6042 5.7889-3.5777 5.7889h-71.056c-2.9735 0-4.9075-3.1292-3.5777-5.7889z" fill="#fff" style=""/>
<path d="m35.955 2.2112c1.4741-2.9482 5.6813-2.9482 7.1554 0l35.528 71.056c1.3298 2.6596-0.6042 5.7889-3.5777 5.7889h-71.056c-2.9735 0-4.9075-3.1292-3.5777-5.7889z" style=""/>
<path d="m37.72 3.1061c0.7371-1.4741 2.8407-1.4741 3.5778-1e-5l35.528 71.056c0.6649 1.3298-0.3021 2.8944-1.7888 2.8944h-71.056c-1.4868 0-2.4538-1.5646-1.7889-2.8944z" stroke="#000" stroke-opacity=".87" stroke-width="4" style=""/>
<path d="m42.092 32.618-0.4688 20.059h-4.0234l-0.4883-20.059zm-5.1172 26.211c0-0.7161 0.2344-1.3151 0.7031-1.7968 0.4818-0.4948 1.1459-0.7422 1.9922-0.7422 0.8334 0 1.4909 0.2474 1.9727 0.7422 0.4817 0.4817 0.7226 1.0807 0.7226 1.7968 0 0.6901-0.2409 1.2826-0.7226 1.7774-0.4818 0.4818-1.1393 0.7226-1.9727 0.7226-0.8463 0-1.5104-0.2408-1.9922-0.7226-0.4687-0.4948-0.7031-1.0873-0.7031-1.7774z" fill="#000" fill-opacity=".87" style=""/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 30 KiB

359
application/src/main/data/json/system/scada_symbols/fuel-generator-hp.svg

@ -0,0 +1,359 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:tb="https://thingsboard.io/svg" width="600" height="400" fill="none" version="1.1" viewBox="0 0 600 400"><tb:metadata xmlns=""><![CDATA[{
"title": "HP Fuel generator",
"description": "Fuel generator with various states.",
"searchTags": [
"power",
"energy",
"fuel",
"generation"
],
"widgetSizeX": 1,
"widgetSizeY": 1,
"tags": [
{
"tag": "background",
"stateRenderFunction": "var color = ctx.properties.stoppedColor;\nif (ctx.values.running) {\n color = ctx.properties.runningColor;\n}\nelement.attr({fill: color});",
"actions": null
},
{
"tag": "clickArea",
"stateRenderFunction": null,
"actions": {
"click": {
"actionFunction": "ctx.api.callAction(event, 'click');"
}
}
},
{
"tag": "critical",
"stateRenderFunction": "element.attr({fill: ctx.properties.criticalColor});\nif (ctx.values.critical) {\n element.show();\n} else {\n element.hide();\n}\n\nvar elementCriticalAnimation = element.remember('criticalAnimation');\nvar criticalAnimation = ctx.values.critical && ctx.values.criticalAnimation;\n\nif (elementCriticalAnimation !== criticalAnimation) {\n element.remember('criticalAnimation', criticalAnimation);\n if (criticalAnimation) {\n ctx.api.cssAnimate(element, 500).attr({opacity: 0.15}).loop(0, true);\n } else {\n ctx.api.resetCssAnimation(element);\n }\n}\n\n",
"actions": {
"click": {
"actionFunction": "ctx.api.callAction(event, 'criticalClick');"
}
}
},
{
"tag": "warning",
"stateRenderFunction": "element.attr({fill: ctx.properties.warningColor});\nvar warning = ctx.values.warning && !(ctx.values.warning && ctx.values.critical)\nif (warning) {\n element.show();\n} else {\n element.hide();\n}\n\nvar elementCriticalAnimation = element.remember('criticalAnimation');\nvar criticalAnimation = warning && ctx.values.criticalAnimation;\n\nif (elementCriticalAnimation !== criticalAnimation) {\n element.remember('criticalAnimation', criticalAnimation);\n if (criticalAnimation) {\n ctx.api.cssAnimate(element, 500).attr({opacity: 0.15}).loop(0, true);\n } else {\n ctx.api.resetCssAnimation(element);\n }\n}\n",
"actions": {
"click": {
"actionFunction": "ctx.api.callAction(event, 'warningClick');"
}
}
}
],
"behavior": [
{
"id": "running",
"name": "{i18n:scada.symbol.running}",
"hint": "{i18n:scada.symbol.running-hint}",
"group": null,
"type": "value",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": "{i18n:scada.symbol.running}",
"defaultGetValueSettings": {
"action": "GET_ATTRIBUTE",
"defaultValue": false,
"executeRpc": {
"method": "getState",
"requestTimeout": 5000,
"requestPersistent": false,
"persistentPollingInterval": 1000
},
"getAttribute": {
"scope": "SHARED_SCOPE",
"key": "running"
},
"getTimeSeries": {
"key": "state"
},
"getAlarmStatus": {
"severityList": null,
"typeList": null
},
"dataToValue": {
"type": "NONE",
"dataToValueFunction": "/* Should return boolean value */\nreturn data;",
"compareToValue": true
}
},
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": null
},
{
"id": "warning",
"name": "{i18n:scada.symbol.warning}",
"hint": "{i18n:scada.symbol.warning-state-hint}",
"group": "{i18n:scada.symbol.warning-state}",
"type": "value",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": "{i18n:scada.symbol.warning}",
"defaultGetValueSettings": {
"action": "GET_ALARM_STATUS",
"defaultValue": false,
"executeRpc": {
"method": "getState",
"requestTimeout": 5000,
"requestPersistent": false,
"persistentPollingInterval": 1000
},
"getAttribute": {
"scope": null,
"key": "state"
},
"getTimeSeries": {
"key": "state"
},
"getAlarmStatus": {
"severityList": [
"MAJOR",
"MINOR",
"WARNING",
"INDETERMINATE"
],
"typeList": null
},
"dataToValue": {
"type": "NONE",
"dataToValueFunction": "/* Should return boolean value */\nreturn data;",
"compareToValue": true
}
},
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": null
},
{
"id": "warningClick",
"name": "{i18n:scada.symbol.warning-click}",
"hint": "{i18n:scada.symbol.on-click-hint}",
"group": "{i18n:scada.symbol.warning-state}",
"type": "widgetAction",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": null,
"defaultGetValueSettings": null,
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": {
"type": "doNothing",
"targetDashboardStateId": null,
"openRightLayout": false,
"setEntityId": false,
"stateEntityParamName": null
}
},
{
"id": "critical",
"name": "{i18n:scada.symbol.critical}",
"hint": "{i18n:scada.symbol.critical-state-hint}",
"group": "{i18n:scada.symbol.critical-state}",
"type": "value",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": "{i18n:scada.symbol.critical}",
"defaultGetValueSettings": {
"action": "GET_ALARM_STATUS",
"defaultValue": false,
"executeRpc": {
"method": "getState",
"requestTimeout": 5000,
"requestPersistent": false,
"persistentPollingInterval": 1000
},
"getAttribute": {
"scope": null,
"key": "state"
},
"getTimeSeries": {
"key": "state"
},
"getAlarmStatus": {
"severityList": [
"CRITICAL"
],
"typeList": null
},
"dataToValue": {
"type": "NONE",
"dataToValueFunction": "/* Should return boolean value */\nreturn data;",
"compareToValue": true
}
},
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": null
},
{
"id": "criticalClick",
"name": "{i18n:scada.symbol.critical-click}",
"hint": "{i18n:scada.symbol.on-click-hint}",
"group": "{i18n:scada.symbol.critical-state}",
"type": "widgetAction",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": null,
"defaultGetValueSettings": null,
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": {
"type": "doNothing",
"targetDashboardStateId": null,
"openRightLayout": false,
"setEntityId": false,
"stateEntityParamName": null
}
},
{
"id": "criticalAnimation",
"name": "{i18n:scada.symbol.warning-critical-state-animation}",
"hint": "{i18n:scada.symbol.warning-critical-state-animation-hint}",
"group": null,
"type": "value",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": "{i18n:scada.symbol.animation}",
"defaultGetValueSettings": {
"action": "DO_NOTHING",
"defaultValue": false,
"executeRpc": {
"method": "getState",
"requestTimeout": 5000,
"requestPersistent": false,
"persistentPollingInterval": 1000
},
"getAttribute": {
"key": "state",
"scope": null
},
"getTimeSeries": {
"key": "state"
},
"dataToValue": {
"type": "NONE",
"compareToValue": true,
"dataToValueFunction": "/* Should return boolean value */\nreturn data;"
}
},
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": null
},
{
"id": "click",
"name": "{i18n:scada.symbol.on-click}",
"hint": "{i18n:scada.symbol.on-click-hint}",
"group": null,
"type": "widgetAction",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": null,
"defaultGetValueSettings": null,
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": {
"type": "doNothing",
"targetDashboardStateId": null,
"openRightLayout": false,
"setEntityId": false,
"stateEntityParamName": null
}
}
],
"properties": [
{
"id": "runningColor",
"name": "{i18n:scada.symbol.colors}",
"type": "color",
"default": "#FFFFFF",
"required": null,
"subLabel": "{i18n:scada.symbol.running}",
"divider": true,
"fieldSuffix": null,
"disableOnProperty": null,
"rowClass": "",
"fieldClass": "",
"min": null,
"max": null,
"step": null,
"disabled": false,
"visible": true
},
{
"id": "stoppedColor",
"name": "{i18n:scada.symbol.colors}",
"type": "color",
"default": "#666666",
"required": null,
"subLabel": "{i18n:scada.symbol.stopped}",
"divider": null,
"fieldSuffix": null,
"disableOnProperty": null,
"rowClass": "",
"fieldClass": "",
"min": null,
"max": null,
"step": null,
"disabled": false,
"visible": true
},
{
"id": "warningColor",
"name": "{i18n:scada.symbol.alarm-colors}",
"type": "color",
"default": "#FAA405",
"required": null,
"subLabel": "{i18n:scada.symbol.warning}",
"divider": true,
"fieldSuffix": null,
"disableOnProperty": null,
"rowClass": "",
"fieldClass": "",
"min": null,
"max": null,
"step": null,
"disabled": false,
"visible": true
},
{
"id": "criticalColor",
"name": "{i18n:scada.symbol.alarm-colors}",
"type": "color",
"default": "#D12730",
"required": null,
"subLabel": "{i18n:scada.symbol.critical}",
"divider": null,
"fieldSuffix": null,
"disableOnProperty": null,
"rowClass": "",
"fieldClass": "",
"min": null,
"max": null,
"step": null,
"disabled": false,
"visible": true
}
]
}]]></tb:metadata>
<g fill="#fff" stroke="#1A1A1A" stroke-width="2" tb:tag="background">
<path d="m1 24c0-12.702 10.298-23 23-23h95c12.703 0 23 10.298 23 23v37c0 3.866-3.134 7-7 7h-14c-3.866 0-7-3.134-7-7v-21c0-6.0751-4.925-11-11-11h-63c-6.0751 0-11 4.9249-11 11v282c0 6.075 4.9249 11 11 11h520c6.075 0 11-4.925 11-11v-314c0-3.866 3.134-7 7-7h14c3.866 0 7 3.134 7 7v330c0 12.703-10.297 23-23 23h-552c-12.702 0-23-10.297-23-23v-314z"/>
<path d="m29 78c0-12.702 10.298-23 23-23h496c12.703 0 23 10.298 23 23v244c0 6.075-4.925 11-11 11h-520c-6.0751 0-11-4.925-11-11v-244z"/>
<circle cx="478" cy="350" r="49"/>
<path d="m60 361h30v33c0 2.761-2.2386 5-5 5h-20c-2.7614 0-5-2.239-5-5v-33z"/>
<path d="m221 44c0-12.702 10.297-23 23-23h272c12.703 0 23 10.298 23 23v11h-318v-11z"/>
</g><line x1="87" x2="181" y1="211" y2="211" stroke="#1A1A1A" stroke-linecap="round" stroke-width="6"/><line x1="87" x2="181" y1="243" y2="243" stroke="#1A1A1A" stroke-linecap="round" stroke-width="6"/><line x1="87" x2="181" y1="275" y2="275" stroke="#1A1A1A" stroke-linecap="round" stroke-width="6"/><line x1="203" x2="297" y1="211" y2="211" stroke="#1A1A1A" stroke-linecap="round" stroke-width="6"/><line x1="203" x2="297" y1="243" y2="243" stroke="#1A1A1A" stroke-linecap="round" stroke-width="6"/><line x1="203" x2="297" y1="275" y2="275" stroke="#1A1A1A" stroke-linecap="round" stroke-width="6"/><path d="m201.8 0s-201.8 0-201.8 67v328.36c0 2.6512 5.3727 4.6403 12 4.6403h576c6.627 0 12-1.9892 12-4.6403v-328.36c0-67-198.21-67-198.21-67h-101.79zm201.21 81.2c-3.8661 0-6.9999 1.2536-6.9999 2.8v300.4c0 1.5464 3.1341 2.8 6.9999 2.8h43.998c3.8661 0 6.9999-1.2536 6.9999-2.8v-300.4c0-1.5464-3.1341-2.8-6.9999-2.8z" fill="#000" fill-opacity="0" tb:tag="clickArea"/><g fill="#d12730" style="display: none;" tb:tag="critical">
<rect width="84" height="84" rx="4" fill="#fff" style=""/>
<rect width="84" height="84" rx="4" style=""/>
<rect x="2" y="2" width="80" height="80" rx="2" stroke="#000" stroke-opacity=".87" stroke-width="4" style=""/>
<path d="m44.559 27.562-0.4688 20.059h-4.0234l-0.4883-20.059zm-5.1172 26.211c0-0.7161 0.2344-1.3151 0.7031-1.7968 0.4818-0.4948 1.1459-0.7422 1.9922-0.7422 0.8334 0 1.4909 0.2474 1.9727 0.7422 0.4817 0.4817 0.7226 1.0807 0.7226 1.7968 0 0.6901-0.2409 1.2826-0.7226 1.7774-0.4818 0.4818-1.1393 0.7226-1.9727 0.7226-0.8463 0-1.5104-0.2408-1.9922-0.7226-0.4687-0.4948-0.7031-1.0873-0.7031-1.7774z" fill="#000" fill-opacity=".87" style=""/>
</g><g fill="#faa405" style="display: none;" tb:tag="warning">
<path d="m35.955 2.2112c1.4741-2.9482 5.6813-2.9482 7.1554 0l35.528 71.056c1.3298 2.6596-0.6042 5.7889-3.5777 5.7889h-71.056c-2.9735 0-4.9075-3.1292-3.5777-5.7889z" fill="#fff" style=""/>
<path d="m35.955 2.2112c1.4741-2.9482 5.6813-2.9482 7.1554 0l35.528 71.056c1.3298 2.6596-0.6042 5.7889-3.5777 5.7889h-71.056c-2.9735 0-4.9075-3.1292-3.5777-5.7889z" style=""/>
<path d="m37.72 3.1061c0.7371-1.4741 2.8407-1.4741 3.5778-1e-5l35.528 71.056c0.6649 1.3298-0.3021 2.8944-1.7888 2.8944h-71.056c-1.4868 0-2.4538-1.5646-1.7889-2.8944z" stroke="#000" stroke-opacity=".87" stroke-width="4" style=""/>
<path d="m42.092 32.618-0.4688 20.059h-4.0234l-0.4883-20.059zm-5.1172 26.211c0-0.7161 0.2344-1.3151 0.7031-1.7968 0.4818-0.4948 1.1459-0.7422 1.9922-0.7422 0.8334 0 1.4909 0.2474 1.9727 0.7422 0.4817 0.4817 0.7226 1.0807 0.7226 1.7968 0 0.6901-0.2409 1.2826-0.7226 1.7774-0.4818 0.4818-1.1393 0.7226-1.9727 0.7226-0.8463 0-1.5104-0.2408-1.9922-0.7226-0.4687-0.4948-0.7031-1.0873-0.7031-1.7774z" fill="#000" fill-opacity=".87" style=""/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 14 KiB

297
application/src/main/data/json/system/scada_symbols/high-voltage-tower-hp.svg

@ -0,0 +1,297 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:tb="https://thingsboard.io/svg" width="400" height="800" fill="none" version="1.1" viewBox="0 0 400 800"><tb:metadata xmlns=""><![CDATA[{
"title": "HP High voltage tower",
"description": "High voltage tower with various states.",
"searchTags": [
"power",
"energy"
],
"widgetSizeX": 2,
"widgetSizeY": 4,
"tags": [
{
"tag": "background",
"stateRenderFunction": "element.attr({fill: ctx.properties.backgroundColor});",
"actions": null
},
{
"tag": "clickArea",
"stateRenderFunction": null,
"actions": {
"click": {
"actionFunction": "ctx.api.callAction(event, 'click');"
}
}
},
{
"tag": "critical",
"stateRenderFunction": "element.attr({fill: ctx.properties.criticalColor});\nif (ctx.values.critical) {\n element.show();\n} else {\n element.hide();\n}\n\nvar elementCriticalAnimation = element.remember('criticalAnimation');\nvar criticalAnimation = ctx.values.critical && ctx.values.criticalAnimation;\n\nif (elementCriticalAnimation !== criticalAnimation) {\n element.remember('criticalAnimation', criticalAnimation);\n if (criticalAnimation) {\n ctx.api.cssAnimate(element, 500).attr({opacity: 0.15}).loop(0, true);\n } else {\n ctx.api.resetCssAnimation(element);\n }\n}\n\n",
"actions": {
"click": {
"actionFunction": "ctx.api.callAction(event, 'criticalClick');"
}
}
},
{
"tag": "warning",
"stateRenderFunction": "element.attr({fill: ctx.properties.warningColor});\nvar warning = ctx.values.warning && !(ctx.values.warning && ctx.values.critical)\nif (warning) {\n element.show();\n} else {\n element.hide();\n}\n\nvar elementCriticalAnimation = element.remember('criticalAnimation');\nvar criticalAnimation = warning && ctx.values.criticalAnimation;\n\nif (elementCriticalAnimation !== criticalAnimation) {\n element.remember('criticalAnimation', criticalAnimation);\n if (criticalAnimation) {\n ctx.api.cssAnimate(element, 500).attr({opacity: 0.15}).loop(0, true);\n } else {\n ctx.api.resetCssAnimation(element);\n }\n}\n",
"actions": {
"click": {
"actionFunction": "ctx.api.callAction(event, 'warningClick');"
}
}
}
],
"behavior": [
{
"id": "warning",
"name": "{i18n:scada.symbol.warning}",
"hint": "{i18n:scada.symbol.warning-state-hint}",
"group": "{i18n:scada.symbol.warning-state}",
"type": "value",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": "{i18n:scada.symbol.warning}",
"defaultGetValueSettings": {
"action": "GET_ALARM_STATUS",
"defaultValue": false,
"executeRpc": {
"method": "getState",
"requestTimeout": 5000,
"requestPersistent": false,
"persistentPollingInterval": 1000
},
"getAttribute": {
"scope": null,
"key": "state"
},
"getTimeSeries": {
"key": "state"
},
"getAlarmStatus": {
"severityList": [
"MAJOR",
"MINOR",
"WARNING",
"INDETERMINATE"
],
"typeList": null
},
"dataToValue": {
"type": "NONE",
"dataToValueFunction": "/* Should return boolean value */\nreturn data;",
"compareToValue": true
}
},
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": null
},
{
"id": "warningClick",
"name": "{i18n:scada.symbol.warning-click}",
"hint": "{i18n:scada.symbol.on-click-hint}",
"group": "{i18n:scada.symbol.warning-state}",
"type": "widgetAction",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": null,
"defaultGetValueSettings": null,
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": {
"type": "doNothing",
"targetDashboardStateId": null,
"openRightLayout": false,
"setEntityId": false,
"stateEntityParamName": null
}
},
{
"id": "critical",
"name": "{i18n:scada.symbol.critical}",
"hint": "{i18n:scada.symbol.critical-state-hint}",
"group": "{i18n:scada.symbol.critical-state}",
"type": "value",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": "{i18n:scada.symbol.critical}",
"defaultGetValueSettings": {
"action": "GET_ALARM_STATUS",
"defaultValue": false,
"executeRpc": {
"method": "getState",
"requestTimeout": 5000,
"requestPersistent": false,
"persistentPollingInterval": 1000
},
"getAttribute": {
"scope": null,
"key": "state"
},
"getTimeSeries": {
"key": "state"
},
"getAlarmStatus": {
"severityList": [
"CRITICAL"
],
"typeList": null
},
"dataToValue": {
"type": "NONE",
"dataToValueFunction": "/* Should return boolean value */\nreturn data;",
"compareToValue": true
}
},
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": null
},
{
"id": "criticalClick",
"name": "{i18n:scada.symbol.critical-click}",
"hint": "{i18n:scada.symbol.on-click-hint}",
"group": "{i18n:scada.symbol.critical-state}",
"type": "widgetAction",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": null,
"defaultGetValueSettings": null,
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": {
"type": "doNothing",
"targetDashboardStateId": null,
"openRightLayout": false,
"setEntityId": false,
"stateEntityParamName": null
}
},
{
"id": "criticalAnimation",
"name": "{i18n:scada.symbol.warning-critical-state-animation}",
"hint": "{i18n:scada.symbol.warning-critical-state-animation-hint}",
"group": null,
"type": "value",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": "{i18n:scada.symbol.animation}",
"defaultGetValueSettings": {
"action": "DO_NOTHING",
"defaultValue": false,
"executeRpc": {
"method": "getState",
"requestTimeout": 5000,
"requestPersistent": false,
"persistentPollingInterval": 1000
},
"getAttribute": {
"key": "state",
"scope": null
},
"getTimeSeries": {
"key": "state"
},
"dataToValue": {
"type": "NONE",
"compareToValue": true,
"dataToValueFunction": "/* Should return boolean value */\nreturn data;"
}
},
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": null
},
{
"id": "click",
"name": "{i18n:scada.symbol.on-click}",
"hint": "{i18n:scada.symbol.on-click-hint}",
"group": null,
"type": "widgetAction",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": null,
"defaultGetValueSettings": null,
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": {
"type": "doNothing",
"targetDashboardStateId": null,
"openRightLayout": false,
"setEntityId": false,
"stateEntityParamName": null
}
}
],
"properties": [
{
"id": "backgroundColor",
"name": "{i18n:scada.symbol.background-color}",
"type": "color",
"default": "#999999",
"divider": false
},
{
"id": "warningColor",
"name": "{i18n:scada.symbol.alarm-colors}",
"type": "color",
"default": "#FAA405",
"subLabel": "{i18n:scada.symbol.warning}",
"divider": true,
"disabled": false,
"visible": true
},
{
"id": "criticalColor",
"name": "{i18n:scada.symbol.alarm-colors}",
"type": "color",
"default": "#D12730",
"subLabel": "{i18n:scada.symbol.critical}",
"disabled": false,
"visible": true
}
]
}]]></tb:metadata>
<g fill="#999" stroke="#1a1a1a" tb:tag="background">
<path d="m140 300h120" stroke-width="2"/>
<path d="m397 240v63" stroke-width="6"/>
<path d="m312 100v50" stroke-width="2"/>
<path d="m88 100v50" stroke-width="2"/>
<path d="m3 240v63" stroke-width="6"/>
<path d="m294 150h36" stroke-width="2"/>
<path d="m70 150h36" stroke-width="2"/>
<path d="m259.73 61 66.5 38h-252.47l66.5-38z" stroke-width="2"/>
<path d="m399.62 239h-399.23l139.46-58h120.32z" stroke-width="2.0004"/>
<path d="m259.02 299.7 99.599 497.5-158.17-79.085-0.447-0.224-0.447 0.224-158.17 79.085 99.599-497.5 0.019-0.097v-238.19l59-59.983 59 59.983v238.19z" stroke-width="2"/>
<path d="m200.08 718.22-130.08-67.22" stroke-width="2.0033"/>
<path d="m200.08 584-129.08 67.226" stroke-width="2.0006"/>
<path d="m200 718.22 130.08-67.22" stroke-width="2.0033"/>
<path d="m200 584 129.08 67.226" stroke-width="2.0006"/>
<path d="m200 584.22 105.08-54.222" stroke-width="2.0009"/>
<path d="m200 476 105.08 54.222" stroke-width="2.0009"/>
<path d="m200 476.52 85.077-44.225" stroke-width="2.0013"/>
<path d="m200 387.29 85.073 44.215" stroke-width="2.0113"/>
<path d="m200 387.22 69.098-35.23" stroke-width="1.9864"/>
<path d="m200.09 387.22-69.098-35.23" stroke-width="1.9864"/>
<path d="m200.09 475.5-85.094-43.216" stroke-width="2.0007"/>
<path d="m200.09 387.28-85.094 43.216" stroke-width="2.0007"/>
<path d="m200.08 584.22-105.08-54.222" stroke-width="2.0009"/>
<path d="m200.08 476-105.08 54.219" stroke-width="2.004"/>
<path d="m141 300h118" stroke-width="2"/>
<path d="m141 61h118" stroke-width="2"/>
<path d="m141 181h118" stroke-width="2"/>
<path d="m141 239h118" stroke-width="2"/>
<path d="m141 99h118" stroke-width="2"/>
<path d="m141 61h118" stroke-width="2"/>
</g><path d="m134.53 0s-134.53 0-134.53 134v656.72c0 5.3024 3.5818 9.2806 8 9.2806h384c4.418 0 8-3.9784 8-9.2806v-656.72c0-134-132.14-134-132.14-134h-67.86zm134.14 162.4c-2.5774 0-4.6666 2.5072-4.6666 5.6v600.8c0 3.0928 2.0894 5.6 4.6666 5.6h29.332c2.5774 0 4.6666-2.5072 4.6666-5.6v-600.8c0-3.0928-2.0894-5.6-4.6666-5.6z" fill-opacity="0" tb:tag="clickArea"/><g transform="translate(0,716)" fill="#d12730" style="display: none;" tb:tag="critical">
<rect width="84" height="84" rx="4" fill="#fff" style=""/>
<rect width="84" height="84" rx="4" style=""/>
<rect x="2" y="2" width="80" height="80" rx="2" stroke="#000" stroke-opacity=".87" stroke-width="4" style=""/>
<path d="m44.559 27.562-0.4688 20.059h-4.0234l-0.4883-20.059zm-5.1172 26.211c0-0.7161 0.2344-1.3151 0.7031-1.7968 0.4818-0.4948 1.1459-0.7422 1.9922-0.7422 0.8334 0 1.4909 0.2474 1.9727 0.7422 0.4817 0.4817 0.7226 1.0807 0.7226 1.7968 0 0.6901-0.2409 1.2826-0.7226 1.7774-0.4818 0.4818-1.1393 0.7226-1.9727 0.7226-0.8463 0-1.5104-0.2408-1.9922-0.7226-0.4687-0.4948-0.7031-1.0873-0.7031-1.7774z" fill="#000" fill-opacity=".87" style=""/>
</g><g transform="translate(0 720.94)" fill="#faa405" style="display: none;" tb:tag="warning">
<path d="m35.955 2.2112c1.4741-2.9482 5.6813-2.9482 7.1554 0l35.528 71.056c1.3298 2.6596-0.6042 5.7889-3.5777 5.7889h-71.056c-2.9735 0-4.9075-3.1292-3.5777-5.7889z" fill="#fff" style=""/>
<path d="m35.955 2.2112c1.4741-2.9482 5.6813-2.9482 7.1554 0l35.528 71.056c1.3298 2.6596-0.6042 5.7889-3.5777 5.7889h-71.056c-2.9735 0-4.9075-3.1292-3.5777-5.7889z" style=""/>
<path d="m37.72 3.1061c0.7371-1.4741 2.8407-1.4741 3.5778-1e-5l35.528 71.056c0.6649 1.3298-0.3021 2.8944-1.7888 2.8944h-71.056c-1.4868 0-2.4538-1.5646-1.7889-2.8944z" stroke="#000" stroke-opacity=".87" stroke-width="4" style=""/>
<path d="m42.092 32.618-0.4688 20.059h-4.0234l-0.4883-20.059zm-5.1172 26.211c0-0.7161 0.2344-1.3151 0.7031-1.7968 0.4818-0.4948 1.1459-0.7422 1.9922-0.7422 0.8334 0 1.4909 0.2474 1.9727 0.7422 0.4817 0.4817 0.7226 1.0807 0.7226 1.7968 0 0.6901-0.2409 1.2826-0.7226 1.7774-0.4818 0.4818-1.1393 0.7226-1.9727 0.7226-0.8463 0-1.5104-0.2408-1.9922-0.7226-0.4687-0.4948-0.7031-1.0873-0.7031-1.7774z" fill="#000" fill-opacity=".87" style=""/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 12 KiB

439
application/src/main/data/json/system/scada_symbols/horizontal-curcuit-breaker-hp.svg

@ -0,0 +1,439 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:tb="https://thingsboard.io/svg" width="400" height="200" fill="none" version="1.1" viewBox="0 0 400 200"><tb:metadata xmlns=""><![CDATA[{
"title": "HP Horizontal circuit breaker",
"description": "Horizontal circuit breaker with various states.",
"searchTags": [
"energy",
"power",
"ev"
],
"widgetSizeX": 2,
"widgetSizeY": 1,
"tags": [
{
"tag": "background",
"stateRenderFunction": "element.attr({fill: ctx.properties.backgroundColor});",
"actions": null
},
{
"tag": "breaker",
"stateRenderFunction": null,
"actions": {
"click": {
"actionFunction": "var initial = ctx.values.initialState;\nvar action = initial ? 'offUpdateState' : 'onUpdateState';\n\nctx.api.callAction(event, action, undefined, {\n next: () => {\n ctx.api.setValue('initialState', !initial);\n }\n});"
}
}
},
{
"tag": "breaker-trigger",
"stateRenderFunction": "element.fill(ctx.properties.disabledColor);\nif (ctx.values.initialState) {\n element.transform({translateX: 0});\n} else {\n element.transform({translateX: -160});\n}",
"actions": null
},
{
"tag": "critical",
"stateRenderFunction": "element.attr({fill: ctx.properties.criticalColor});\nif (ctx.values.critical) {\n element.show();\n} else {\n element.hide();\n}\n\nvar elementCriticalAnimation = element.remember('criticalAnimation');\nvar criticalAnimation = ctx.values.critical && ctx.values.criticalAnimation;\n\nif (elementCriticalAnimation !== criticalAnimation) {\n element.remember('criticalAnimation', criticalAnimation);\n if (criticalAnimation) {\n ctx.api.cssAnimate(element, 500).attr({opacity: 0.15}).loop(0, true);\n } else {\n ctx.api.resetCssAnimation(element);\n }\n}\n\n",
"actions": {
"click": {
"actionFunction": "ctx.api.callAction(event, 'criticalClick');"
}
}
},
{
"tag": "label",
"stateRenderFunction": "if (ctx.properties.label) {\n element.show();\n var label = ctx.values.initialState ? ctx.properties.onLabel : ctx.properties.offLabel;\n ctx.api.font(element, ctx.properties.labelFont, ctx.properties.labelColor);\n ctx.api.text(element, label);\n} else {\n element.hide();\n}",
"actions": null
},
{
"tag": "label-box",
"stateRenderFunction": "var color = ctx.properties.disabledColor;\nif (ctx.values.initialState) {\n color = ctx.properties.enabledColor;\n}\nelement.attr({fill: color});",
"actions": null
},
{
"tag": "warning",
"stateRenderFunction": "element.attr({fill: ctx.properties.warningColor});\nvar warning = ctx.values.warning && !(ctx.values.warning && ctx.values.critical)\nif (warning) {\n element.show();\n} else {\n element.hide();\n}\n\nvar elementCriticalAnimation = element.remember('criticalAnimation');\nvar criticalAnimation = warning && ctx.values.criticalAnimation;\n\nif (elementCriticalAnimation !== criticalAnimation) {\n element.remember('criticalAnimation', criticalAnimation);\n if (criticalAnimation) {\n ctx.api.cssAnimate(element, 500).attr({opacity: 0.15}).loop(0, true);\n } else {\n ctx.api.resetCssAnimation(element);\n }\n}\n",
"actions": {
"click": {
"actionFunction": "ctx.api.callAction(event, 'warningClick');"
}
}
}
],
"behavior": [
{
"id": "initialState",
"name": "{i18n:scada.symbol.on-off-state}",
"hint": "{i18n:scada.symbol.on-off-state-hint}",
"group": null,
"type": "value",
"valueType": "BOOLEAN",
"trueLabel": "{i18n:scada.symbol.on}",
"falseLabel": "{i18n:scada.symbol.off}",
"stateLabel": "",
"defaultGetValueSettings": {
"action": "GET_ATTRIBUTE",
"defaultValue": false,
"executeRpc": {
"method": "getState",
"requestTimeout": 5000,
"requestPersistent": false,
"persistentPollingInterval": 1000
},
"getAttribute": {
"scope": "SHARED_SCOPE",
"key": "state"
},
"getTimeSeries": {
"key": "state"
},
"getAlarmStatus": {
"severityList": null,
"typeList": null
},
"dataToValue": {
"type": "NONE",
"dataToValueFunction": "/* Should return boolean value */\nreturn data;",
"compareToValue": true
}
},
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": null
},
{
"id": "onUpdateState",
"name": "{i18n:scada.symbol.on-update-state}",
"hint": "{i18n:scada.symbol.on-update-state-hint}",
"group": null,
"type": "action",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": null,
"defaultGetValueSettings": null,
"defaultSetValueSettings": {
"action": "EXECUTE_RPC",
"executeRpc": {
"method": "setState",
"requestTimeout": 5000,
"requestPersistent": false,
"persistentPollingInterval": 1000
},
"setAttribute": {
"scope": "SERVER_SCOPE",
"key": "state"
},
"putTimeSeries": {
"key": "state"
},
"valueToData": {
"type": "CONSTANT",
"constantValue": true,
"valueToDataFunction": "/* Convert input boolean value to RPC parameters or attribute/time-series value */\nreturn value;"
}
},
"defaultWidgetActionSettings": null
},
{
"id": "offUpdateState",
"name": "{i18n:scada.symbol.off-update-state}",
"hint": "{i18n:scada.symbol.off-update-state-hint}",
"group": null,
"type": "action",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": null,
"defaultGetValueSettings": null,
"defaultSetValueSettings": {
"action": "EXECUTE_RPC",
"executeRpc": {
"method": "setState",
"requestTimeout": 5000,
"requestPersistent": false,
"persistentPollingInterval": 1000
},
"setAttribute": {
"key": "state",
"scope": "SERVER_SCOPE"
},
"putTimeSeries": {
"key": "state"
},
"valueToData": {
"type": "CONSTANT",
"constantValue": false,
"valueToDataFunction": "/* Convert input boolean value to RPC parameters or attribute/time-series value */\nreturn value;"
}
},
"defaultWidgetActionSettings": null
},
{
"id": "warning",
"name": "{i18n:scada.symbol.warning}",
"hint": "{i18n:scada.symbol.warning-state-hint}",
"group": "{i18n:scada.symbol.warning-state}",
"type": "value",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": "{i18n:scada.symbol.warning}",
"defaultGetValueSettings": {
"action": "GET_ALARM_STATUS",
"defaultValue": false,
"executeRpc": {
"method": "getState",
"requestTimeout": 5000,
"requestPersistent": false,
"persistentPollingInterval": 1000
},
"getAttribute": {
"scope": null,
"key": "state"
},
"getTimeSeries": {
"key": "state"
},
"getAlarmStatus": {
"severityList": [
"MAJOR",
"MINOR",
"WARNING",
"INDETERMINATE"
],
"typeList": null
},
"dataToValue": {
"type": "NONE",
"dataToValueFunction": "/* Should return boolean value */\nreturn data;",
"compareToValue": true
}
},
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": null
},
{
"id": "warningClick",
"name": "{i18n:scada.symbol.warning-click}",
"hint": "{i18n:scada.symbol.on-click-hint}",
"group": "{i18n:scada.symbol.warning-state}",
"type": "widgetAction",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": null,
"defaultGetValueSettings": null,
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": {
"type": "doNothing",
"targetDashboardStateId": null,
"openRightLayout": false,
"setEntityId": false,
"stateEntityParamName": null
}
},
{
"id": "critical",
"name": "{i18n:scada.symbol.critical}",
"hint": "{i18n:scada.symbol.critical-state-hint}",
"group": "{i18n:scada.symbol.critical-state}",
"type": "value",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": "{i18n:scada.symbol.critical}",
"defaultGetValueSettings": {
"action": "GET_ALARM_STATUS",
"defaultValue": false,
"executeRpc": {
"method": "getState",
"requestTimeout": 5000,
"requestPersistent": false,
"persistentPollingInterval": 1000
},
"getAttribute": {
"scope": null,
"key": "state"
},
"getTimeSeries": {
"key": "state"
},
"getAlarmStatus": {
"severityList": [
"CRITICAL"
],
"typeList": null
},
"dataToValue": {
"type": "NONE",
"dataToValueFunction": "/* Should return boolean value */\nreturn data;",
"compareToValue": true
}
},
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": null
},
{
"id": "criticalClick",
"name": "{i18n:scada.symbol.critical-click}",
"hint": "{i18n:scada.symbol.on-click-hint}",
"group": "{i18n:scada.symbol.critical-state}",
"type": "widgetAction",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": null,
"defaultGetValueSettings": null,
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": {
"type": "doNothing",
"targetDashboardStateId": null,
"openRightLayout": false,
"setEntityId": false,
"stateEntityParamName": null
}
},
{
"id": "criticalAnimation",
"name": "{i18n:scada.symbol.warning-critical-state-animation}",
"hint": "{i18n:scada.symbol.warning-critical-state-animation-hint}",
"group": null,
"type": "value",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": "{i18n:scada.symbol.animation}",
"defaultGetValueSettings": {
"action": "DO_NOTHING",
"defaultValue": false,
"executeRpc": {
"method": "getState",
"requestTimeout": 5000,
"requestPersistent": false,
"persistentPollingInterval": 1000
},
"getAttribute": {
"key": "state",
"scope": null
},
"getTimeSeries": {
"key": "state"
},
"dataToValue": {
"type": "NONE",
"compareToValue": true,
"dataToValueFunction": "/* Should return boolean value */\nreturn data;"
}
},
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": null
}
],
"properties": [
{
"id": "label",
"name": "{i18n:scada.symbol.label}",
"type": "switch",
"default": true,
"disabled": false,
"visible": true
},
{
"id": "onLabel",
"name": "{i18n:scada.symbol.label}",
"type": "text",
"default": "ON",
"disabled": false,
"visible": true
},
{
"id": "offLabel",
"name": "{i18n:scada.symbol.label}",
"type": "text",
"default": "OFF",
"disabled": false,
"visible": true
},
{
"id": "labelFont",
"name": "{i18n:scada.symbol.label}",
"type": "font",
"default": {
"size": 42,
"sizeUnit": "px",
"family": "Roboto",
"weight": "400",
"style": "normal"
},
"disabled": false,
"visible": true
},
{
"id": "labelColor",
"name": "{i18n:scada.symbol.label}",
"type": "color",
"default": "#1A1A1A",
"disabled": false,
"visible": true
},
{
"id": "backgroundColor",
"name": "{i18n:scada.symbol.background-color}",
"type": "color",
"default": "#FFFFFF",
"disabled": false,
"visible": true
},
{
"id": "enabledColor",
"name": "{i18n:scada.symbol.colors}",
"type": "color",
"default": "#FFFFFF",
"subLabel": "{i18n:scada.symbol.enabled}",
"divider": true,
"disabled": false,
"visible": true
},
{
"id": "disabledColor",
"name": "{i18n:scada.symbol.colors}",
"type": "color",
"default": "#666666",
"subLabel": "{i18n:scada.symbol.disabled}",
"disabled": false,
"visible": true
},
{
"id": "warningColor",
"name": "{i18n:scada.symbol.alarm-colors}",
"type": "color",
"default": "#FAA405",
"subLabel": "{i18n:scada.symbol.warning}",
"divider": true,
"disabled": false,
"visible": true
},
{
"id": "criticalColor",
"name": "{i18n:scada.symbol.alarm-colors}",
"type": "color",
"default": "#D12730",
"subLabel": "{i18n:scada.symbol.critical}",
"disabled": false,
"visible": true
}
]
}]]></tb:metadata>
<rect x="1" y="1" width="398" height="198" fill="#fff" stroke="#1A1A1A" stroke-width="2" tb:tag="background"/><circle cx="49" cy="100" r="19" stroke="#1a1a1a" stroke-width="2"/><circle cx="351" cy="100" r="19" stroke="#1a1a1a" stroke-width="2"/><path d="m0 100h31" stroke="#1A1A1A" stroke-width="6"/><path d="m369 100h31" stroke="#1A1A1A" stroke-width="6"/><g tb:tag="breaker">
<path d="m101 51h198v97c0 0.552-0.448 1-1 1h-196c-0.552 0-1-0.448-1-1v-97z" fill="#fff" stroke="#1A1A1A" stroke-width="2" tb:tag="label-box"/>
<text x="200.83984" y="114.56055" fill="#000000" font-family="Roboto" font-size="40px" font-weight="400" text-anchor="middle" tb:tag="label" xml:space="preserve"><tspan dominant-baseline="start">ON</tspan></text>
<rect x="261" y="25" width="38" height="150" rx="1" fill="#999" stroke="#1A1A1A" stroke-width="2" tb:tag="breaker-trigger"/>
</g><g fill="#d12730" style="display: none;" tb:tag="critical">
<rect width="84" height="84" rx="4" fill="#fff" style=""/>
<rect width="84" height="84" rx="4" style=""/>
<rect x="2" y="2" width="80" height="80" rx="2" stroke="#000" stroke-opacity=".87" stroke-width="4" style=""/>
<path d="m44.559 27.562-0.4688 20.059h-4.0234l-0.4883-20.059zm-5.1172 26.211c0-0.7161 0.2344-1.3151 0.7031-1.7968 0.4818-0.4948 1.1459-0.7422 1.9922-0.7422 0.8334 0 1.4909 0.2474 1.9727 0.7422 0.4817 0.4817 0.7226 1.0807 0.7226 1.7968 0 0.6901-0.2409 1.2826-0.7226 1.7774-0.4818 0.4818-1.1393 0.7226-1.9727 0.7226-0.8463 0-1.5104-0.2408-1.9922-0.7226-0.4687-0.4948-0.7031-1.0873-0.7031-1.7774z" fill="#000" fill-opacity=".87" style=""/>
</g><g fill="#faa405" style="display: none;" tb:tag="warning">
<path d="m35.955 2.2112c1.4741-2.9482 5.6813-2.9482 7.1554 0l35.528 71.056c1.3298 2.6596-0.6042 5.7889-3.5777 5.7889h-71.056c-2.9735 0-4.9075-3.1292-3.5777-5.7889z" fill="#fff" style=""/>
<path d="m35.955 2.2112c1.4741-2.9482 5.6813-2.9482 7.1554 0l35.528 71.056c1.3298 2.6596-0.6042 5.7889-3.5777 5.7889h-71.056c-2.9735 0-4.9075-3.1292-3.5777-5.7889z" style=""/>
<path d="m37.72 3.1061c0.7371-1.4741 2.8407-1.4741 3.5778-1e-5l35.528 71.056c0.6649 1.3298-0.3021 2.8944-1.7888 2.8944h-71.056c-1.4868 0-2.4538-1.5646-1.7889-2.8944z" stroke="#000" stroke-opacity=".87" stroke-width="4" style=""/>
<path d="m42.092 32.618-0.4688 20.059h-4.0234l-0.4883-20.059zm-5.1172 26.211c0-0.7161 0.2344-1.3151 0.7031-1.7968 0.4818-0.4948 1.1459-0.7422 1.9922-0.7422 0.8334 0 1.4909 0.2474 1.9727 0.7422 0.4817 0.4817 0.7226 1.0807 0.7226 1.7968 0 0.6901-0.2409 1.2826-0.7226 1.7774-0.4818 0.4818-1.1393 0.7226-1.9727 0.7226-0.8463 0-1.5104-0.2408-1.9922-0.7226-0.4687-0.4948-0.7031-1.0873-0.7031-1.7774z" fill="#000" fill-opacity=".87" style=""/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 16 KiB

378
application/src/main/data/json/system/scada_symbols/horizontal-energy-system-controller-hp.svg

@ -0,0 +1,378 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:tb="https://thingsboard.io/svg" width="600" height="400" fill="none" version="1.1" viewBox="0 0 600 400"><tb:metadata xmlns=""><![CDATA[{
"title": "HP Horizontal energy systems controller",
"description": "Horizontal energy systems controller with various states.",
"searchTags": [
"energy",
"power",
"monitoring"
],
"widgetSizeX": 3,
"widgetSizeY": 2,
"tags": [
{
"tag": "background",
"stateRenderFunction": "var color = ctx.properties.disconnectedColor;\nif (ctx.values.connected) {\n color = ctx.properties.connectedColor;\n}\nelement.attr({fill: color});",
"actions": null
},
{
"tag": "clickArea",
"stateRenderFunction": null,
"actions": {
"click": {
"actionFunction": "ctx.api.callAction(event, 'click');"
}
}
},
{
"tag": "critical",
"stateRenderFunction": "element.attr({fill: ctx.properties.criticalColor});\nif (ctx.values.critical) {\n element.show();\n} else {\n element.hide();\n}\n\nvar elementCriticalAnimation = element.remember('criticalAnimation');\nvar criticalAnimation = ctx.values.critical && ctx.values.criticalAnimation;\n\nif (elementCriticalAnimation !== criticalAnimation) {\n element.remember('criticalAnimation', criticalAnimation);\n if (criticalAnimation) {\n ctx.api.cssAnimate(element, 500).attr({opacity: 0.15}).loop(0, true);\n } else {\n ctx.api.resetCssAnimation(element);\n }\n}\n\n",
"actions": {
"click": {
"actionFunction": "ctx.api.callAction(event, 'criticalClick');"
}
}
},
{
"tag": "indicator",
"stateRenderFunction": "var color = ctx.properties.disconnectedIndicatorColor;\nif (ctx.values.connected) {\n color = ctx.properties.connectedIndicatorColor;\n}\nelement.attr({fill: color});",
"actions": null
},
{
"tag": "label",
"stateRenderFunction": "ctx.api.font(element, ctx.properties.labelFont, ctx.properties.labelColor);\n ctx.api.text(element, ctx.properties.label);",
"actions": null
},
{
"tag": "warning",
"stateRenderFunction": "element.attr({fill: ctx.properties.warningColor});\nvar warning = ctx.values.warning && !(ctx.values.warning && ctx.values.critical)\nif (warning) {\n element.show();\n} else {\n element.hide();\n}\n\nvar elementCriticalAnimation = element.remember('criticalAnimation');\nvar criticalAnimation = warning && ctx.values.criticalAnimation;\n\nif (elementCriticalAnimation !== criticalAnimation) {\n element.remember('criticalAnimation', criticalAnimation);\n if (criticalAnimation) {\n ctx.api.cssAnimate(element, 500).attr({opacity: 0.15}).loop(0, true);\n } else {\n ctx.api.resetCssAnimation(element);\n }\n}\n",
"actions": {
"click": {
"actionFunction": "ctx.api.callAction(event, 'warningClick');"
}
}
}
],
"behavior": [
{
"id": "connected",
"name": "{i18n:scada.symbol.connected}",
"hint": "{i18n:scada.symbol.connected-hint}",
"group": null,
"type": "value",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": "{i18n:scada.symbol.connected}",
"defaultGetValueSettings": {
"action": "GET_ATTRIBUTE",
"defaultValue": false,
"executeRpc": {
"method": "getState",
"requestTimeout": 5000,
"requestPersistent": false,
"persistentPollingInterval": 1000
},
"getAttribute": {
"scope": "SHARED_SCOPE",
"key": "connected"
},
"getTimeSeries": {
"key": "state"
},
"getAlarmStatus": {
"severityList": null,
"typeList": null
},
"dataToValue": {
"type": "NONE",
"dataToValueFunction": "/* Should return boolean value */\nreturn data;",
"compareToValue": true
}
},
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": null
},
{
"id": "warning",
"name": "{i18n:scada.symbol.warning}",
"hint": "{i18n:scada.symbol.warning-state-hint}",
"group": "{i18n:scada.symbol.warning-state}",
"type": "value",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": "{i18n:scada.symbol.warning}",
"defaultGetValueSettings": {
"action": "GET_ALARM_STATUS",
"defaultValue": false,
"executeRpc": {
"method": "getState",
"requestTimeout": 5000,
"requestPersistent": false,
"persistentPollingInterval": 1000
},
"getAttribute": {
"scope": null,
"key": "state"
},
"getTimeSeries": {
"key": "state"
},
"getAlarmStatus": {
"severityList": [
"MAJOR",
"MINOR",
"WARNING",
"INDETERMINATE"
],
"typeList": null
},
"dataToValue": {
"type": "NONE",
"dataToValueFunction": "/* Should return boolean value */\nreturn data;",
"compareToValue": true
}
},
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": null
},
{
"id": "warningClick",
"name": "{i18n:scada.symbol.warning-click}",
"hint": "{i18n:scada.symbol.on-click-hint}",
"group": "{i18n:scada.symbol.warning-state}",
"type": "widgetAction",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": null,
"defaultGetValueSettings": null,
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": {
"type": "doNothing",
"targetDashboardStateId": null,
"openRightLayout": false,
"setEntityId": false,
"stateEntityParamName": null
}
},
{
"id": "critical",
"name": "{i18n:scada.symbol.critical}",
"hint": "{i18n:scada.symbol.critical-state-hint}",
"group": "{i18n:scada.symbol.critical-state}",
"type": "value",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": "{i18n:scada.symbol.critical}",
"defaultGetValueSettings": {
"action": "GET_ALARM_STATUS",
"defaultValue": false,
"executeRpc": {
"method": "getState",
"requestTimeout": 5000,
"requestPersistent": false,
"persistentPollingInterval": 1000
},
"getAttribute": {
"scope": null,
"key": "state"
},
"getTimeSeries": {
"key": "state"
},
"getAlarmStatus": {
"severityList": [
"CRITICAL"
],
"typeList": null
},
"dataToValue": {
"type": "NONE",
"dataToValueFunction": "/* Should return boolean value */\nreturn data;",
"compareToValue": true
}
},
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": null
},
{
"id": "criticalClick",
"name": "{i18n:scada.symbol.critical-click}",
"hint": "{i18n:scada.symbol.on-click-hint}",
"group": "{i18n:scada.symbol.critical-state}",
"type": "widgetAction",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": null,
"defaultGetValueSettings": null,
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": {
"type": "doNothing",
"targetDashboardStateId": null,
"openRightLayout": false,
"setEntityId": false,
"stateEntityParamName": null
}
},
{
"id": "criticalAnimation",
"name": "{i18n:scada.symbol.warning-critical-state-animation}",
"hint": "{i18n:scada.symbol.warning-critical-state-animation-hint}",
"group": null,
"type": "value",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": "{i18n:scada.symbol.animation}",
"defaultGetValueSettings": {
"action": "DO_NOTHING",
"defaultValue": false,
"executeRpc": {
"method": "getState",
"requestTimeout": 5000,
"requestPersistent": false,
"persistentPollingInterval": 1000
},
"getAttribute": {
"key": "state",
"scope": null
},
"getTimeSeries": {
"key": "state"
},
"dataToValue": {
"type": "NONE",
"compareToValue": true,
"dataToValueFunction": "/* Should return boolean value */\nreturn data;"
}
},
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": null
},
{
"id": "click",
"name": "{i18n:scada.symbol.on-click}",
"hint": "{i18n:scada.symbol.on-click-hint}",
"group": null,
"type": "widgetAction",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": null,
"defaultGetValueSettings": null,
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": {
"type": "doNothing",
"targetDashboardStateId": null,
"openRightLayout": false,
"setEntityId": false,
"stateEntityParamName": null
}
}
],
"properties": [
{
"id": "connectedColor",
"name": "{i18n:scada.symbol.colors}",
"type": "color",
"default": "#FFFFFF",
"subLabel": "{i18n:scada.symbol.connected}",
"divider": true,
"disabled": false,
"visible": true
},
{
"id": "disconnectedColor",
"name": "{i18n:scada.symbol.colors}",
"type": "color",
"default": "#666666",
"subLabel": "{i18n:scada.symbol.disconnected}",
"disabled": false,
"visible": true
},
{
"id": "connectedIndicatorColor",
"name": "{i18n:scada.symbol.indicator}",
"type": "color",
"default": "#198038",
"subLabel": "{i18n:scada.symbol.connected}",
"divider": true,
"disabled": false,
"visible": true
},
{
"id": "disconnectedIndicatorColor",
"name": "{i18n:scada.symbol.indicator}",
"type": "color",
"default": "#DEDEDE",
"subLabel": "{i18n:scada.symbol.disconnected}",
"disabled": false,
"visible": true
},
{
"id": "label",
"name": "{i18n:scada.symbol.label}",
"type": "text",
"default": "Connected",
"fieldClass": "medium-width",
"disabled": false,
"visible": true
},
{
"id": "labelFont",
"name": "{i18n:scada.symbol.label}",
"type": "font",
"default": {
"size": 30,
"sizeUnit": "px",
"family": "Roboto",
"weight": "normal",
"style": "normal"
},
"disabled": false,
"visible": true
},
{
"id": "labelColor",
"name": "{i18n:scada.symbol.label}",
"type": "color",
"default": "#000",
"disabled": false,
"visible": true
},
{
"id": "warningColor",
"name": "{i18n:scada.symbol.alarm-colors}",
"type": "color",
"default": "#FAA405",
"subLabel": "{i18n:scada.symbol.warning}",
"divider": true,
"disabled": false,
"visible": true
},
{
"id": "criticalColor",
"name": "{i18n:scada.symbol.alarm-colors}",
"type": "color",
"default": "#D12730",
"subLabel": "{i18n:scada.symbol.critical}",
"disabled": false,
"visible": true
}
]
}]]></tb:metadata>
<rect x="1" y="17" width="598" height="366" rx="5" fill="#fff" stroke="#000" stroke-opacity=".87" stroke-width="2" tb:tag="background"/><rect x="26" y="1" width="148" height="16" rx="1" fill="#999" stroke="#000" stroke-opacity=".87" stroke-width="2"/><rect x="26" y="383" width="148" height="16" rx="1" fill="#999" stroke="#000" stroke-opacity=".87" stroke-width="2"/><rect x="426" y="383" width="148" height="16" rx="1" fill="#999" stroke="#000" stroke-opacity=".87" stroke-width="2"/><rect x="226" y="1" width="148" height="16" rx="1" fill="#999" stroke="#000" stroke-opacity=".87" stroke-width="2"/><rect x="426" y="1" width="148" height="16" rx="1" fill="#999" stroke="#000" stroke-opacity=".87" stroke-width="2"/><circle cx="66" cy="88" r="10" fill="#198038" tb:tag="indicator"/><text x="83.31543" y="91.589844" fill="#000000" font-family="Roboto" font-size="30px" font-weight="400" tb:tag="label" xml:space="preserve"><tspan dominant-baseline="middle">Connected</tspan></text><path d="m201.8 0s-201.8 0-201.8 67v328.36c0 2.6512 5.3727 4.6403 12 4.6403h576c6.627 0 12-1.9892 12-4.6403v-328.36c0-67-198.21-67-198.21-67h-101.79zm201.21 81.2c-3.8661 0-6.9999 1.2536-6.9999 2.8v300.4c0 1.5464 3.1341 2.8 6.9999 2.8h43.998c3.8661 0 6.9999-1.2536 6.9999-2.8v-300.4c0-1.5464-3.1341-2.8-6.9999-2.8z" fill-opacity="0" tb:tag="clickArea"/><g transform="translate(0,316)" fill="#d12730" style="display: none;" tb:tag="critical">
<rect width="84" height="84" rx="4" fill="#fff" style=""/>
<rect width="84" height="84" rx="4" style=""/>
<rect x="2" y="2" width="80" height="80" rx="2" stroke="#000" stroke-opacity=".87" stroke-width="4" style=""/>
<path d="m44.559 27.562-0.4688 20.059h-4.0234l-0.4883-20.059zm-5.1172 26.211c0-0.7161 0.2344-1.3151 0.7031-1.7968 0.4818-0.4948 1.1459-0.7422 1.9922-0.7422 0.8334 0 1.4909 0.2474 1.9727 0.7422 0.4817 0.4817 0.7226 1.0807 0.7226 1.7968 0 0.6901-0.2409 1.2826-0.7226 1.7774-0.4818 0.4818-1.1393 0.7226-1.9727 0.7226-0.8463 0-1.5104-0.2408-1.9922-0.7226-0.4687-0.4948-0.7031-1.0873-0.7031-1.7774z" fill="#000" fill-opacity=".87" style=""/>
</g><g transform="translate(0 320.94)" fill="#faa405" style="display: none;" tb:tag="warning">
<path d="m35.955 2.2112c1.4741-2.9482 5.6813-2.9482 7.1554 0l35.528 71.056c1.3298 2.6596-0.6042 5.7889-3.5777 5.7889h-71.056c-2.9735 0-4.9075-3.1292-3.5777-5.7889z" fill="#fff" style=""/>
<path d="m35.955 2.2112c1.4741-2.9482 5.6813-2.9482 7.1554 0l35.528 71.056c1.3298 2.6596-0.6042 5.7889-3.5777 5.7889h-71.056c-2.9735 0-4.9075-3.1292-3.5777-5.7889z" style=""/>
<path d="m37.72 3.1061c0.7371-1.4741 2.8407-1.4741 3.5778-1e-5l35.528 71.056c0.6649 1.3298-0.3021 2.8944-1.7888 2.8944h-71.056c-1.4868 0-2.4538-1.5646-1.7889-2.8944z" stroke="#000" stroke-opacity=".87" stroke-width="4" style=""/>
<path d="m42.092 32.618-0.4688 20.059h-4.0234l-0.4883-20.059zm-5.1172 26.211c0-0.7161 0.2344-1.3151 0.7031-1.7968 0.4818-0.4948 1.1459-0.7422 1.9922-0.7422 0.8334 0 1.4909 0.2474 1.9727 0.7422 0.4817 0.4817 0.7226 1.0807 0.7226 1.7968 0 0.6901-0.2409 1.2826-0.7226 1.7774-0.4818 0.4818-1.1393 0.7226-1.9727 0.7226-0.8463 0-1.5104-0.2408-1.9922-0.7226-0.4687-0.4948-0.7031-1.0873-0.7031-1.7774z" fill="#000" fill-opacity=".87" style=""/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 15 KiB

349
application/src/main/data/json/system/scada_symbols/house-hp.svg

@ -0,0 +1,349 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:tb="https://thingsboard.io/svg" width="400" height="400" fill="none" version="1.1" viewBox="0 0 400 400"><tb:metadata xmlns=""><![CDATA[{
"title": "HP House",
"description": "House with various states.",
"searchTags": [
"power",
"energy",
"consumer"
],
"widgetSizeX": 2,
"widgetSizeY": 2,
"tags": [
{
"tag": "background",
"stateRenderFunction": "var color = ctx.properties.stoppedColor;\nif (ctx.values.running) {\n color = ctx.properties.runningColor;\n}\nelement.attr({fill: color});",
"actions": null
},
{
"tag": "clickArea",
"stateRenderFunction": null,
"actions": {
"click": {
"actionFunction": "ctx.api.callAction(event, 'click');"
}
}
},
{
"tag": "critical",
"stateRenderFunction": "element.attr({fill: ctx.properties.criticalColor});\nif (ctx.values.critical) {\n element.show();\n} else {\n element.hide();\n}\n\nvar elementCriticalAnimation = element.remember('criticalAnimation');\nvar criticalAnimation = ctx.values.critical && ctx.values.criticalAnimation;\n\nif (elementCriticalAnimation !== criticalAnimation) {\n element.remember('criticalAnimation', criticalAnimation);\n if (criticalAnimation) {\n ctx.api.cssAnimate(element, 500).attr({opacity: 0.15}).loop(0, true);\n } else {\n ctx.api.resetCssAnimation(element);\n }\n}\n\n",
"actions": {
"click": {
"actionFunction": "ctx.api.callAction(event, 'criticalClick');"
}
}
},
{
"tag": "warning",
"stateRenderFunction": "element.attr({fill: ctx.properties.warningColor});\nvar warning = ctx.values.warning && !(ctx.values.warning && ctx.values.critical)\nif (warning) {\n element.show();\n} else {\n element.hide();\n}\n\nvar elementCriticalAnimation = element.remember('criticalAnimation');\nvar criticalAnimation = warning && ctx.values.criticalAnimation;\n\nif (elementCriticalAnimation !== criticalAnimation) {\n element.remember('criticalAnimation', criticalAnimation);\n if (criticalAnimation) {\n ctx.api.cssAnimate(element, 500).attr({opacity: 0.15}).loop(0, true);\n } else {\n ctx.api.resetCssAnimation(element);\n }\n}\n",
"actions": {
"click": {
"actionFunction": "ctx.api.callAction(event, 'warningClick');"
}
}
}
],
"behavior": [
{
"id": "running",
"name": "{i18n:scada.symbol.running}",
"hint": "{i18n:scada.symbol.running-hint}",
"group": null,
"type": "value",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": "{i18n:scada.symbol.running}",
"defaultGetValueSettings": {
"action": "GET_ATTRIBUTE",
"defaultValue": false,
"executeRpc": {
"method": "getState",
"requestTimeout": 5000,
"requestPersistent": false,
"persistentPollingInterval": 1000
},
"getAttribute": {
"scope": "SHARED_SCOPE",
"key": "running"
},
"getTimeSeries": {
"key": "state"
},
"getAlarmStatus": {
"severityList": null,
"typeList": null
},
"dataToValue": {
"type": "NONE",
"dataToValueFunction": "/* Should return boolean value */\nreturn data;",
"compareToValue": true
}
},
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": null
},
{
"id": "warning",
"name": "{i18n:scada.symbol.warning}",
"hint": "{i18n:scada.symbol.warning-state-hint}",
"group": "{i18n:scada.symbol.warning-state}",
"type": "value",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": "{i18n:scada.symbol.warning}",
"defaultGetValueSettings": {
"action": "GET_ALARM_STATUS",
"defaultValue": false,
"executeRpc": {
"method": "getState",
"requestTimeout": 5000,
"requestPersistent": false,
"persistentPollingInterval": 1000
},
"getAttribute": {
"scope": null,
"key": "state"
},
"getTimeSeries": {
"key": "state"
},
"getAlarmStatus": {
"severityList": [
"MAJOR",
"MINOR",
"WARNING",
"INDETERMINATE"
],
"typeList": null
},
"dataToValue": {
"type": "NONE",
"dataToValueFunction": "/* Should return boolean value */\nreturn data;",
"compareToValue": true
}
},
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": null
},
{
"id": "warningClick",
"name": "{i18n:scada.symbol.warning-click}",
"hint": "{i18n:scada.symbol.on-click-hint}",
"group": "{i18n:scada.symbol.warning-state}",
"type": "widgetAction",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": null,
"defaultGetValueSettings": null,
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": {
"type": "doNothing",
"targetDashboardStateId": null,
"openRightLayout": false,
"setEntityId": false,
"stateEntityParamName": null
}
},
{
"id": "critical",
"name": "{i18n:scada.symbol.critical}",
"hint": "{i18n:scada.symbol.critical-state-hint}",
"group": "{i18n:scada.symbol.critical-state}",
"type": "value",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": "{i18n:scada.symbol.critical}",
"defaultGetValueSettings": {
"action": "GET_ALARM_STATUS",
"defaultValue": false,
"executeRpc": {
"method": "getState",
"requestTimeout": 5000,
"requestPersistent": false,
"persistentPollingInterval": 1000
},
"getAttribute": {
"scope": null,
"key": "state"
},
"getTimeSeries": {
"key": "state"
},
"getAlarmStatus": {
"severityList": [
"CRITICAL"
],
"typeList": null
},
"dataToValue": {
"type": "NONE",
"dataToValueFunction": "/* Should return boolean value */\nreturn data;",
"compareToValue": true
}
},
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": null
},
{
"id": "criticalClick",
"name": "{i18n:scada.symbol.critical-click}",
"hint": "{i18n:scada.symbol.on-click-hint}",
"group": "{i18n:scada.symbol.critical-state}",
"type": "widgetAction",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": null,
"defaultGetValueSettings": null,
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": {
"type": "doNothing",
"targetDashboardStateId": null,
"openRightLayout": false,
"setEntityId": false,
"stateEntityParamName": null
}
},
{
"id": "criticalAnimation",
"name": "{i18n:scada.symbol.warning-critical-state-animation}",
"hint": "{i18n:scada.symbol.warning-critical-state-animation-hint}",
"group": null,
"type": "value",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": "{i18n:scada.symbol.animation}",
"defaultGetValueSettings": {
"action": "DO_NOTHING",
"defaultValue": false,
"executeRpc": {
"method": "getState",
"requestTimeout": 5000,
"requestPersistent": false,
"persistentPollingInterval": 1000
},
"getAttribute": {
"key": "state",
"scope": null
},
"getTimeSeries": {
"key": "state"
},
"dataToValue": {
"type": "NONE",
"compareToValue": true,
"dataToValueFunction": "/* Should return boolean value */\nreturn data;"
}
},
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": null
},
{
"id": "click",
"name": "{i18n:scada.symbol.on-click}",
"hint": "{i18n:scada.symbol.on-click-hint}",
"group": null,
"type": "widgetAction",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": null,
"defaultGetValueSettings": null,
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": {
"type": "doNothing",
"targetDashboardStateId": null,
"openRightLayout": false,
"setEntityId": false,
"stateEntityParamName": null
}
}
],
"properties": [
{
"id": "runningColor",
"name": "{i18n:scada.symbol.colors}",
"type": "color",
"default": "#FFFFFF",
"required": null,
"subLabel": "{i18n:scada.symbol.running}",
"divider": true,
"fieldSuffix": null,
"disableOnProperty": null,
"rowClass": "",
"fieldClass": "",
"min": null,
"max": null,
"step": null
},
{
"id": "stoppedColor",
"name": "{i18n:scada.symbol.colors}",
"type": "color",
"default": "#666666",
"required": null,
"subLabel": "{i18n:scada.symbol.stopped}",
"divider": null,
"fieldSuffix": null,
"disableOnProperty": null,
"rowClass": "",
"fieldClass": "",
"min": null,
"max": null,
"step": null
},
{
"id": "warningColor",
"name": "{i18n:scada.symbol.alarm-colors}",
"type": "color",
"default": "#FAA405",
"required": null,
"subLabel": "{i18n:scada.symbol.warning}",
"divider": true,
"fieldSuffix": null,
"disableOnProperty": null,
"rowClass": "",
"fieldClass": "",
"min": null,
"max": null,
"step": null
},
{
"id": "criticalColor",
"name": "{i18n:scada.symbol.alarm-colors}",
"type": "color",
"default": "#D12730",
"required": null,
"subLabel": "{i18n:scada.symbol.critical}",
"divider": null,
"fieldSuffix": null,
"disableOnProperty": null,
"rowClass": "",
"fieldClass": "",
"min": null,
"max": null,
"step": null
}
]
}]]></tb:metadata>
<g fill="#fff" stroke="#1A1A1A" stroke-width="2" tb:tag="background">
<path d="m370 377h-340c-2.7614 0-5-2.239-5-5v-185.42c0-1.372 0.5635-2.683 1.5584-3.627l170-161.31c1.93-1.8306 4.954-1.8306 6.884 0l170 161.31c0.995 0.944 1.558 2.255 1.558 3.627v185.42c0 2.761-2.239 5-5 5z"/>
<path d="m287 60c0-2.7614 2.239-5 5-5h54.5c2.761 0 5 2.2386 5 5v86.08c0 4.322-5.113 6.609-8.334 3.727l-54.5-48.763c-1.06-0.949-1.666-2.3042-1.666-3.7267v-37.317z"/>
<rect x="1" y="377" width="398" height="22" rx="5"/>
<path d="m29.655 185h-24.568c-0.9085 0-1.3463-1.114-0.68102-1.732l193.55-180c1.151-1.0709 2.935-1.0709 4.086 0l193.55 180c0.665 0.618 0.227 1.732-0.681 1.732h-24.568c-1.256 0-2.467-0.473-3.39-1.325l-164.92-152.16c-1.149-1.0601-2.919-1.0601-4.068 0l-164.92 152.16c-0.9235 0.852-2.1339 1.325-3.3904 1.325z"/>
</g><rect x="89" y="187" width="30" height="63" rx="1" fill="#999" stroke="#1A1A1A" stroke-width="2"/><rect x="221" y="187" width="30" height="63" rx="1" fill="#999" stroke="#1A1A1A" stroke-width="2"/><rect x="221" y="286" width="30" height="63" rx="1" fill="#999" stroke="#1A1A1A" stroke-width="2"/><rect x="89" y="286" width="64" height="91" rx="1" fill="#999" stroke="#1A1A1A" stroke-width="2"/><rect x="123" y="187" width="30" height="63" rx="1" fill="#999" stroke="#1A1A1A" stroke-width="2"/><rect x="255" y="187" width="30" height="63" rx="1" fill="#999" stroke="#1A1A1A" stroke-width="2"/><rect x="255" y="286" width="30" height="63" rx="1" fill="#999" stroke="#1A1A1A" stroke-width="2"/><rect x="289" y="187" width="30" height="63" rx="1" fill="#999" stroke="#1A1A1A" stroke-width="2"/><rect x="289" y="286" width="30" height="63" rx="1" fill="#999" stroke="#1A1A1A" stroke-width="2"/><path d="m200.7 104.07 27.061 26.216c0.645 0.625 0.203 1.718-0.696 1.718h-54.122c-0.899 0-1.341-1.093-0.696-1.718l27.061-26.216c0.388-0.375 1.004-0.375 1.392 0z" fill="#999" stroke="#1A1A1A" stroke-width="2"/><path d="m134.53 0s-134.53 0-134.53 67v328.36c0 2.6512 3.5818 4.6403 8 4.6403h384c4.418 0 8-1.9892 8-4.6403v-328.36c0-67-132.14-67-132.14-67h-67.86zm134.14 81.2c-2.5774 0-4.6666 1.2536-4.6666 2.8v300.4c0 1.5464 2.0894 2.8 4.6666 2.8h29.332c2.5774 0 4.6666-1.2536 4.6666-2.8v-300.4c0-1.5464-2.0894-2.8-4.6666-2.8z" fill-opacity="0" tb:tag="clickArea"/><g transform="translate(0,316)" fill="#d12730" style="display: none;" tb:tag="critical">
<rect width="84" height="84" rx="4" fill="#fff" style=""/>
<rect width="84" height="84" rx="4" style=""/>
<rect x="2" y="2" width="80" height="80" rx="2" stroke="#000" stroke-opacity=".87" stroke-width="4" style=""/>
<path d="m44.559 27.562-0.4688 20.059h-4.0234l-0.4883-20.059zm-5.1172 26.211c0-0.7161 0.2344-1.3151 0.7031-1.7968 0.4818-0.4948 1.1459-0.7422 1.9922-0.7422 0.8334 0 1.4909 0.2474 1.9727 0.7422 0.4817 0.4817 0.7226 1.0807 0.7226 1.7968 0 0.6901-0.2409 1.2826-0.7226 1.7774-0.4818 0.4818-1.1393 0.7226-1.9727 0.7226-0.8463 0-1.5104-0.2408-1.9922-0.7226-0.4687-0.4948-0.7031-1.0873-0.7031-1.7774z" fill="#000" fill-opacity=".87" style=""/>
</g><g transform="translate(0 320.94)" fill="#faa405" style="display: none;" tb:tag="warning">
<path d="m35.955 2.2112c1.4741-2.9482 5.6813-2.9482 7.1554 0l35.528 71.056c1.3298 2.6596-0.6042 5.7889-3.5777 5.7889h-71.056c-2.9735 0-4.9075-3.1292-3.5777-5.7889z" fill="#fff" style=""/>
<path d="m35.955 2.2112c1.4741-2.9482 5.6813-2.9482 7.1554 0l35.528 71.056c1.3298 2.6596-0.6042 5.7889-3.5777 5.7889h-71.056c-2.9735 0-4.9075-3.1292-3.5777-5.7889z" style=""/>
<path d="m37.72 3.1061c0.7371-1.4741 2.8407-1.4741 3.5778-1e-5l35.528 71.056c0.6649 1.3298-0.3021 2.8944-1.7888 2.8944h-71.056c-1.4868 0-2.4538-1.5646-1.7889-2.8944z" stroke="#000" stroke-opacity=".87" stroke-width="4" style=""/>
<path d="m42.092 32.618-0.4688 20.059h-4.0234l-0.4883-20.059zm-5.1172 26.211c0-0.7161 0.2344-1.3151 0.7031-1.7968 0.4818-0.4948 1.1459-0.7422 1.9922-0.7422 0.8334 0 1.4909 0.2474 1.9727 0.7422 0.4817 0.4817 0.7226 1.0807 0.7226 1.7968 0 0.6901-0.2409 1.2826-0.7226 1.7774-0.4818 0.4818-1.1393 0.7226-1.9727 0.7226-0.8463 0-1.5104-0.2408-1.9922-0.7226-0.4687-0.4948-0.7031-1.0873-0.7031-1.7774z" fill="#000" fill-opacity=".87" style=""/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 14 KiB

358
application/src/main/data/json/system/scada_symbols/industrial-fuel-generator-hp.svg

@ -0,0 +1,358 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:tb="https://thingsboard.io/svg" width="1000" height="600" fill="none" version="1.1" viewBox="0 0 1000 600"><tb:metadata xmlns=""><![CDATA[{
"title": "HP Industrial fuel generator",
"description": "Industrial fuel generator with various states.",
"searchTags": [
"power",
"energy",
"fuel",
"generation"
],
"widgetSizeX": 5,
"widgetSizeY": 3,
"tags": [
{
"tag": "background",
"stateRenderFunction": "var color = ctx.properties.stoppedColor;\nif (ctx.values.running) {\n color = ctx.properties.runningColor;\n}\nelement.attr({fill: color});",
"actions": null
},
{
"tag": "clickArea",
"stateRenderFunction": null,
"actions": {
"click": {
"actionFunction": "ctx.api.callAction(event, 'click');"
}
}
},
{
"tag": "critical",
"stateRenderFunction": "element.attr({fill: ctx.properties.criticalColor});\nif (ctx.values.critical) {\n element.show();\n} else {\n element.hide();\n}\n\nvar elementCriticalAnimation = element.remember('criticalAnimation');\nvar criticalAnimation = ctx.values.critical && ctx.values.criticalAnimation;\n\nif (elementCriticalAnimation !== criticalAnimation) {\n element.remember('criticalAnimation', criticalAnimation);\n if (criticalAnimation) {\n ctx.api.cssAnimate(element, 500).attr({opacity: 0.15}).loop(0, true);\n } else {\n ctx.api.resetCssAnimation(element);\n }\n}\n\n",
"actions": {
"click": {
"actionFunction": "ctx.api.callAction(event, 'criticalClick');"
}
}
},
{
"tag": "sub-background",
"stateRenderFunction": "var color = ctx.properties.stoppedColor;\nif (ctx.values.running) {\n color = '#999999';\n}\nelement.attr({fill: color});",
"actions": null
},
{
"tag": "warning",
"stateRenderFunction": "element.attr({fill: ctx.properties.warningColor});\nvar warning = ctx.values.warning && !(ctx.values.warning && ctx.values.critical)\nif (warning) {\n element.show();\n} else {\n element.hide();\n}\n\nvar elementCriticalAnimation = element.remember('criticalAnimation');\nvar criticalAnimation = warning && ctx.values.criticalAnimation;\n\nif (elementCriticalAnimation !== criticalAnimation) {\n element.remember('criticalAnimation', criticalAnimation);\n if (criticalAnimation) {\n ctx.api.cssAnimate(element, 500).attr({opacity: 0.15}).loop(0, true);\n } else {\n ctx.api.resetCssAnimation(element);\n }\n}\n",
"actions": {
"click": {
"actionFunction": "ctx.api.callAction(event, 'warningClick');"
}
}
}
],
"behavior": [
{
"id": "running",
"name": "{i18n:scada.symbol.running}",
"hint": "{i18n:scada.symbol.running-hint}",
"group": null,
"type": "value",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": "{i18n:scada.symbol.running}",
"defaultGetValueSettings": {
"action": "GET_ATTRIBUTE",
"defaultValue": false,
"executeRpc": {
"method": "getState",
"requestTimeout": 5000,
"requestPersistent": false,
"persistentPollingInterval": 1000
},
"getAttribute": {
"scope": "SHARED_SCOPE",
"key": "running"
},
"getTimeSeries": {
"key": "state"
},
"getAlarmStatus": {
"severityList": null,
"typeList": null
},
"dataToValue": {
"type": "NONE",
"dataToValueFunction": "/* Should return boolean value */\nreturn data;",
"compareToValue": true
}
},
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": null
},
{
"id": "warning",
"name": "{i18n:scada.symbol.warning}",
"hint": "{i18n:scada.symbol.warning-state-hint}",
"group": "{i18n:scada.symbol.warning-state}",
"type": "value",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": "{i18n:scada.symbol.warning}",
"defaultGetValueSettings": {
"action": "GET_ALARM_STATUS",
"defaultValue": false,
"executeRpc": {
"method": "getState",
"requestTimeout": 5000,
"requestPersistent": false,
"persistentPollingInterval": 1000
},
"getAttribute": {
"scope": null,
"key": "state"
},
"getTimeSeries": {
"key": "state"
},
"getAlarmStatus": {
"severityList": [
"MAJOR",
"MINOR",
"WARNING",
"INDETERMINATE"
],
"typeList": null
},
"dataToValue": {
"type": "NONE",
"dataToValueFunction": "/* Should return boolean value */\nreturn data;",
"compareToValue": true
}
},
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": null
},
{
"id": "warningClick",
"name": "{i18n:scada.symbol.warning-click}",
"hint": "{i18n:scada.symbol.on-click-hint}",
"group": "{i18n:scada.symbol.warning-state}",
"type": "widgetAction",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": null,
"defaultGetValueSettings": null,
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": {
"type": "doNothing",
"targetDashboardStateId": null,
"openRightLayout": false,
"setEntityId": false,
"stateEntityParamName": null
}
},
{
"id": "critical",
"name": "{i18n:scada.symbol.critical}",
"hint": "{i18n:scada.symbol.critical-state-hint}",
"group": "{i18n:scada.symbol.critical-state}",
"type": "value",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": "{i18n:scada.symbol.critical}",
"defaultGetValueSettings": {
"action": "GET_ALARM_STATUS",
"defaultValue": false,
"executeRpc": {
"method": "getState",
"requestTimeout": 5000,
"requestPersistent": false,
"persistentPollingInterval": 1000
},
"getAttribute": {
"scope": null,
"key": "state"
},
"getTimeSeries": {
"key": "state"
},
"getAlarmStatus": {
"severityList": [
"CRITICAL"
],
"typeList": null
},
"dataToValue": {
"type": "NONE",
"dataToValueFunction": "/* Should return boolean value */\nreturn data;",
"compareToValue": true
}
},
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": null
},
{
"id": "criticalClick",
"name": "{i18n:scada.symbol.critical-click}",
"hint": "{i18n:scada.symbol.on-click-hint}",
"group": "{i18n:scada.symbol.critical-state}",
"type": "widgetAction",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": null,
"defaultGetValueSettings": null,
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": {
"type": "doNothing",
"targetDashboardStateId": null,
"openRightLayout": false,
"setEntityId": false,
"stateEntityParamName": null
}
},
{
"id": "criticalAnimation",
"name": "{i18n:scada.symbol.warning-critical-state-animation}",
"hint": "{i18n:scada.symbol.warning-critical-state-animation-hint}",
"group": null,
"type": "value",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": "{i18n:scada.symbol.animation}",
"defaultGetValueSettings": {
"action": "DO_NOTHING",
"defaultValue": false,
"executeRpc": {
"method": "getState",
"requestTimeout": 5000,
"requestPersistent": false,
"persistentPollingInterval": 1000
},
"getAttribute": {
"key": "state",
"scope": null
},
"getTimeSeries": {
"key": "state"
},
"dataToValue": {
"type": "NONE",
"compareToValue": true,
"dataToValueFunction": "/* Should return boolean value */\nreturn data;"
}
},
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": null
},
{
"id": "click",
"name": "{i18n:scada.symbol.on-click}",
"hint": "{i18n:scada.symbol.on-click-hint}",
"group": null,
"type": "widgetAction",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": null,
"defaultGetValueSettings": null,
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": {
"type": "doNothing",
"targetDashboardStateId": null,
"openRightLayout": false,
"setEntityId": false,
"stateEntityParamName": null
}
}
],
"properties": [
{
"id": "runningColor",
"name": "{i18n:scada.symbol.colors}",
"type": "color",
"default": "#FFFFFF",
"required": null,
"subLabel": "{i18n:scada.symbol.running}",
"divider": true,
"fieldSuffix": null,
"disableOnProperty": null,
"rowClass": "",
"fieldClass": "",
"min": null,
"max": null,
"step": null,
"disabled": false,
"visible": true
},
{
"id": "stoppedColor",
"name": "{i18n:scada.symbol.colors}",
"type": "color",
"default": "#666666",
"required": null,
"subLabel": "{i18n:scada.symbol.stopped}",
"divider": null,
"fieldSuffix": null,
"disableOnProperty": null,
"rowClass": "",
"fieldClass": "",
"min": null,
"max": null,
"step": null,
"disabled": false,
"visible": true
},
{
"id": "warningColor",
"name": "{i18n:scada.symbol.alarm-colors}",
"type": "color",
"default": "#FAA405",
"required": null,
"subLabel": "{i18n:scada.symbol.warning}",
"divider": true,
"fieldSuffix": null,
"disableOnProperty": null,
"rowClass": "",
"fieldClass": "",
"min": null,
"max": null,
"step": null,
"disabled": false,
"visible": true
},
{
"id": "criticalColor",
"name": "{i18n:scada.symbol.alarm-colors}",
"type": "color",
"default": "#D12730",
"required": null,
"subLabel": "{i18n:scada.symbol.critical}",
"divider": null,
"fieldSuffix": null,
"disableOnProperty": null,
"rowClass": "",
"fieldClass": "",
"min": null,
"max": null,
"step": null,
"disabled": false,
"visible": true
}
]
}]]></tb:metadata>
<rect x="1" y="1" width="998" height="598" fill="#fff" stroke="#1A1A1A" stroke-width="2" tb:tag="background"/><rect x="1" y="1" width="998" height="28" stroke="#1A1A1A" stroke-width="2"/><line x1="858" x2="952" y1="361" y2="361" stroke="#1A1A1A" stroke-linecap="round" stroke-width="6"/><line x1="858" x2="952" y1="393" y2="393" stroke="#1A1A1A" stroke-linecap="round" stroke-width="6"/><line x1="858" x2="952" y1="425" y2="425" stroke="#1A1A1A" stroke-linecap="round" stroke-width="6"/><line x1="858" x2="952" y1="457" y2="457" stroke="#1A1A1A" stroke-linecap="round" stroke-width="6"/><line x1="858" x2="952" y1="67" y2="67" stroke="#1A1A1A" stroke-linecap="round" stroke-width="6"/><line x1="858" x2="952" y1="99" y2="99" stroke="#1A1A1A" stroke-linecap="round" stroke-width="6"/><line x1="858" x2="952" y1="131" y2="131" stroke="#1A1A1A" stroke-linecap="round" stroke-width="6"/><line x1="858" x2="952" y1="163" y2="163" stroke="#1A1A1A" stroke-linecap="round" stroke-width="6"/><rect x="79" y="96" width="278" height="338" rx="3" stroke="#1A1A1A" stroke-width="2"/><rect x="479" y="96" width="278" height="338" rx="3" stroke="#1A1A1A" stroke-width="2"/><circle cx="418" cy="278" r="19" stroke="#1A1A1A" stroke-width="2"/><circle cx="418" cy="278" r="7" fill="#1A1A1A"/><rect x="1" y="501" width="998" height="98" fill="#999" stroke="#1A1A1A" stroke-width="2" tb:tag="sub-background"/><path d="m336.32 0s-336.32 0-336.32 100.5v492.54c0 3.9768 8.9545 6.9604 20 6.9604h960c11.045 0 20-2.9838 20-6.9604v-492.54c0-100.5-330.35-100.5-330.35-100.5h-169.65zm335.35 121.8c-6.4435 0-11.666 1.8804-11.666 4.2v450.6c0 2.3196 5.2235 4.2 11.666 4.2h73.33c6.4435 0 11.666-1.8804 11.666-4.2v-450.6c0-2.3196-5.2235-4.2-11.666-4.2z" fill-opacity="0" style="stroke-width:2.8629" tb:tag="clickArea"/><g fill="#d12730" style="display: none;" tb:tag="critical">
<rect width="84" height="84" rx="4" fill="#fff" style=""/>
<rect width="84" height="84" rx="4" style=""/>
<rect x="2" y="2" width="80" height="80" rx="2" stroke="#000" stroke-opacity=".87" stroke-width="4" style=""/>
<path d="m44.559 27.562-0.4688 20.059h-4.0234l-0.4883-20.059zm-5.1172 26.211c0-0.7161 0.2344-1.3151 0.7031-1.7968 0.4818-0.4948 1.1459-0.7422 1.9922-0.7422 0.8334 0 1.4909 0.2474 1.9727 0.7422 0.4817 0.4817 0.7226 1.0807 0.7226 1.7968 0 0.6901-0.2409 1.2826-0.7226 1.7774-0.4818 0.4818-1.1393 0.7226-1.9727 0.7226-0.8463 0-1.5104-0.2408-1.9922-0.7226-0.4687-0.4948-0.7031-1.0873-0.7031-1.7774z" fill="#000" fill-opacity=".87" style=""/>
</g><g fill="#faa405" style="display: none;" tb:tag="warning">
<path d="m35.955 2.2112c1.4741-2.9482 5.6813-2.9482 7.1554 0l35.528 71.056c1.3298 2.6596-0.6042 5.7889-3.5777 5.7889h-71.056c-2.9735 0-4.9075-3.1292-3.5777-5.7889z" fill="#fff" style=""/>
<path d="m35.955 2.2112c1.4741-2.9482 5.6813-2.9482 7.1554 0l35.528 71.056c1.3298 2.6596-0.6042 5.7889-3.5777 5.7889h-71.056c-2.9735 0-4.9075-3.1292-3.5777-5.7889z" style=""/>
<path d="m37.72 3.1061c0.7371-1.4741 2.8407-1.4741 3.5778-1e-5l35.528 71.056c0.6649 1.3298-0.3021 2.8944-1.7888 2.8944h-71.056c-1.4868 0-2.4538-1.5646-1.7889-2.8944z" stroke="#000" stroke-opacity=".87" stroke-width="4" style=""/>
<path d="m42.092 32.618-0.4688 20.059h-4.0234l-0.4883-20.059zm-5.1172 26.211c0-0.7161 0.2344-1.3151 0.7031-1.7968 0.4818-0.4948 1.1459-0.7422 1.9922-0.7422 0.8334 0 1.4909 0.2474 1.9727 0.7422 0.4817 0.4817 0.7226 1.0807 0.7226 1.7968 0 0.6901-0.2409 1.2826-0.7226 1.7774-0.4818 0.4818-1.1393 0.7226-1.9727 0.7226-0.8463 0-1.5104-0.2408-1.9922-0.7226-0.4687-0.4948-0.7031-1.0873-0.7031-1.7774z" fill="#000" fill-opacity=".87" style=""/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 14 KiB

578
application/src/main/data/json/system/scada_symbols/inverter-hp.svg

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 67 KiB

578
application/src/main/data/json/system/scada_symbols/large-inverter-hp.svg

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 68 KiB

278
application/src/main/data/json/system/scada_symbols/low-voltage-tower-hp.svg

@ -0,0 +1,278 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:tb="https://thingsboard.io/svg" width="400" height="800" fill="none" version="1.1" viewBox="0 0 400 800"><tb:metadata xmlns=""><![CDATA[{
"title": "HP Low voltage tower",
"description": "Low voltage tower with various states.",
"searchTags": [
"power",
"energy"
],
"widgetSizeX": 2,
"widgetSizeY": 4,
"tags": [
{
"tag": "background",
"stateRenderFunction": "element.attr({fill: ctx.properties.backgroundColor});",
"actions": null
},
{
"tag": "clickArea",
"stateRenderFunction": null,
"actions": {
"click": {
"actionFunction": "ctx.api.callAction(event, 'click');"
}
}
},
{
"tag": "critical",
"stateRenderFunction": "element.attr({fill: ctx.properties.criticalColor});\nif (ctx.values.critical) {\n element.show();\n} else {\n element.hide();\n}\n\nvar elementCriticalAnimation = element.remember('criticalAnimation');\nvar criticalAnimation = ctx.values.critical && ctx.values.criticalAnimation;\n\nif (elementCriticalAnimation !== criticalAnimation) {\n element.remember('criticalAnimation', criticalAnimation);\n if (criticalAnimation) {\n ctx.api.cssAnimate(element, 500).attr({opacity: 0.15}).loop(0, true);\n } else {\n ctx.api.resetCssAnimation(element);\n }\n}\n\n",
"actions": {
"click": {
"actionFunction": "ctx.api.callAction(event, 'criticalClick');"
}
}
},
{
"tag": "warning",
"stateRenderFunction": "element.attr({fill: ctx.properties.warningColor});\nvar warning = ctx.values.warning && !(ctx.values.warning && ctx.values.critical)\nif (warning) {\n element.show();\n} else {\n element.hide();\n}\n\nvar elementCriticalAnimation = element.remember('criticalAnimation');\nvar criticalAnimation = warning && ctx.values.criticalAnimation;\n\nif (elementCriticalAnimation !== criticalAnimation) {\n element.remember('criticalAnimation', criticalAnimation);\n if (criticalAnimation) {\n ctx.api.cssAnimate(element, 500).attr({opacity: 0.15}).loop(0, true);\n } else {\n ctx.api.resetCssAnimation(element);\n }\n}\n",
"actions": {
"click": {
"actionFunction": "ctx.api.callAction(event, 'warningClick');"
}
}
}
],
"behavior": [
{
"id": "warning",
"name": "{i18n:scada.symbol.warning}",
"hint": "{i18n:scada.symbol.warning-state-hint}",
"group": "{i18n:scada.symbol.warning-state}",
"type": "value",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": "{i18n:scada.symbol.warning}",
"defaultGetValueSettings": {
"action": "GET_ALARM_STATUS",
"defaultValue": false,
"executeRpc": {
"method": "getState",
"requestTimeout": 5000,
"requestPersistent": false,
"persistentPollingInterval": 1000
},
"getAttribute": {
"scope": null,
"key": "state"
},
"getTimeSeries": {
"key": "state"
},
"getAlarmStatus": {
"severityList": [
"MAJOR",
"MINOR",
"WARNING",
"INDETERMINATE"
],
"typeList": null
},
"dataToValue": {
"type": "NONE",
"dataToValueFunction": "/* Should return boolean value */\nreturn data;",
"compareToValue": true
}
},
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": null
},
{
"id": "warningClick",
"name": "{i18n:scada.symbol.warning-click}",
"hint": "{i18n:scada.symbol.on-click-hint}",
"group": "{i18n:scada.symbol.warning-state}",
"type": "widgetAction",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": null,
"defaultGetValueSettings": null,
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": {
"type": "doNothing",
"targetDashboardStateId": null,
"openRightLayout": false,
"setEntityId": false,
"stateEntityParamName": null
}
},
{
"id": "critical",
"name": "{i18n:scada.symbol.critical}",
"hint": "{i18n:scada.symbol.critical-state-hint}",
"group": "{i18n:scada.symbol.critical-state}",
"type": "value",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": "{i18n:scada.symbol.critical}",
"defaultGetValueSettings": {
"action": "GET_ALARM_STATUS",
"defaultValue": false,
"executeRpc": {
"method": "getState",
"requestTimeout": 5000,
"requestPersistent": false,
"persistentPollingInterval": 1000
},
"getAttribute": {
"scope": null,
"key": "state"
},
"getTimeSeries": {
"key": "state"
},
"getAlarmStatus": {
"severityList": [
"CRITICAL"
],
"typeList": null
},
"dataToValue": {
"type": "NONE",
"dataToValueFunction": "/* Should return boolean value */\nreturn data;",
"compareToValue": true
}
},
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": null
},
{
"id": "criticalClick",
"name": "{i18n:scada.symbol.critical-click}",
"hint": "{i18n:scada.symbol.on-click-hint}",
"group": "{i18n:scada.symbol.critical-state}",
"type": "widgetAction",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": null,
"defaultGetValueSettings": null,
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": {
"type": "doNothing",
"targetDashboardStateId": null,
"openRightLayout": false,
"setEntityId": false,
"stateEntityParamName": null
}
},
{
"id": "criticalAnimation",
"name": "{i18n:scada.symbol.warning-critical-state-animation}",
"hint": "{i18n:scada.symbol.warning-critical-state-animation-hint}",
"group": null,
"type": "value",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": "{i18n:scada.symbol.animation}",
"defaultGetValueSettings": {
"action": "DO_NOTHING",
"defaultValue": false,
"executeRpc": {
"method": "getState",
"requestTimeout": 5000,
"requestPersistent": false,
"persistentPollingInterval": 1000
},
"getAttribute": {
"key": "state",
"scope": null
},
"getTimeSeries": {
"key": "state"
},
"dataToValue": {
"type": "NONE",
"compareToValue": true,
"dataToValueFunction": "/* Should return boolean value */\nreturn data;"
}
},
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": null
},
{
"id": "click",
"name": "{i18n:scada.symbol.on-click}",
"hint": "{i18n:scada.symbol.on-click-hint}",
"group": null,
"type": "widgetAction",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": null,
"defaultGetValueSettings": null,
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": {
"type": "doNothing",
"targetDashboardStateId": null,
"openRightLayout": false,
"setEntityId": false,
"stateEntityParamName": null
}
}
],
"properties": [
{
"id": "backgroundColor",
"name": "{i18n:scada.symbol.background-color}",
"type": "color",
"default": "#999999",
"divider": false,
"disabled": false,
"visible": true
},
{
"id": "warningColor",
"name": "{i18n:scada.symbol.alarm-colors}",
"type": "color",
"default": "#FAA405",
"subLabel": "{i18n:scada.symbol.warning}",
"divider": true,
"disabled": false,
"visible": true
},
{
"id": "criticalColor",
"name": "{i18n:scada.symbol.alarm-colors}",
"type": "color",
"default": "#D12730",
"subLabel": "{i18n:scada.symbol.critical}",
"disabled": false,
"visible": true
}
]
}]]></tb:metadata>
<g fill="#999" stroke="#1a1a1a" tb:tag="background">
<path d="m397 352v-55" stroke-width="6"/>
<path d="m3 352v-55" stroke-width="6"/>
<path d="m397 152v-55" stroke-width="6"/>
<path d="m3 152v-55" stroke-width="6"/>
<rect transform="matrix(-4.3711e-8 1 1 4.3711e-8 -4.3711e-8 150)" x="1" y="1" width="46" height="184" rx="1" stroke-width="2"/>
<rect transform="matrix(-4.3711e-8 1 1 4.3711e-8 214 150)" x="1" y="1" width="46" height="184" rx="1" stroke-width="2"/>
<rect transform="matrix(-4.3711e-8 1 1 4.3711e-8 -4.3711e-8 350)" x="1" y="1" width="46" height="184" rx="1" stroke-width="2"/>
<rect transform="matrix(-4.3711e-8 1 1 4.3711e-8 214 350)" x="1" y="1" width="46" height="184" rx="1" stroke-width="2"/>
<rect x="185" y="1" width="30" height="798" rx="5" stroke-width="2"/>
</g><path d="m134.53 0s-134.53 0-134.53 134v656.72c0 5.3024 3.5818 9.2806 8 9.2806h384c4.418 0 8-3.9784 8-9.2806v-656.72c0-134-132.14-134-132.14-134h-67.86zm134.14 162.4c-2.5774 0-4.6666 2.5072-4.6666 5.6v600.8c0 3.0928 2.0894 5.6 4.6666 5.6h29.332c2.5774 0 4.6666-2.5072 4.6666-5.6v-600.8c0-3.0928-2.0894-5.6-4.6666-5.6z" fill-opacity="0" style="stroke-width:2.0908" tb:tag="clickArea"/><g fill="#d12730" style="display: none;" tb:tag="critical">
<rect width="84" height="84" rx="4" fill="#fff" style=""/>
<rect width="84" height="84" rx="4" style=""/>
<rect x="2" y="2" width="80" height="80" rx="2" stroke="#000" stroke-opacity=".87" stroke-width="4" style=""/>
<path d="m44.559 27.562-0.4688 20.059h-4.0234l-0.4883-20.059zm-5.1172 26.211c0-0.7161 0.2344-1.3151 0.7031-1.7968 0.4818-0.4948 1.1459-0.7422 1.9922-0.7422 0.8334 0 1.4909 0.2474 1.9727 0.7422 0.4817 0.4817 0.7226 1.0807 0.7226 1.7968 0 0.6901-0.2409 1.2826-0.7226 1.7774-0.4818 0.4818-1.1393 0.7226-1.9727 0.7226-0.8463 0-1.5104-0.2408-1.9922-0.7226-0.4687-0.4948-0.7031-1.0873-0.7031-1.7774z" fill="#000" fill-opacity=".87" style=""/>
</g><g fill="#faa405" style="display: none;" tb:tag="warning">
<path d="m35.955 2.2112c1.4741-2.9482 5.6813-2.9482 7.1554 0l35.528 71.056c1.3298 2.6596-0.6042 5.7889-3.5777 5.7889h-71.056c-2.9735 0-4.9075-3.1292-3.5777-5.7889z" fill="#fff" style=""/>
<path d="m35.955 2.2112c1.4741-2.9482 5.6813-2.9482 7.1554 0l35.528 71.056c1.3298 2.6596-0.6042 5.7889-3.5777 5.7889h-71.056c-2.9735 0-4.9075-3.1292-3.5777-5.7889z" style=""/>
<path d="m37.72 3.1061c0.7371-1.4741 2.8407-1.4741 3.5778-1e-5l35.528 71.056c0.6649 1.3298-0.3021 2.8944-1.7888 2.8944h-71.056c-1.4868 0-2.4538-1.5646-1.7889-2.8944z" stroke="#000" stroke-opacity=".87" stroke-width="4" style=""/>
<path d="m42.092 32.618-0.4688 20.059h-4.0234l-0.4883-20.059zm-5.1172 26.211c0-0.7161 0.2344-1.3151 0.7031-1.7968 0.4818-0.4948 1.1459-0.7422 1.9922-0.7422 0.8334 0 1.4909 0.2474 1.9727 0.7422 0.4817 0.4817 0.7226 1.0807 0.7226 1.7968 0 0.6901-0.2409 1.2826-0.7226 1.7774-0.4818 0.4818-1.1393 0.7226-1.9727 0.7226-0.8463 0-1.5104-0.2408-1.9922-0.7226-0.4687-0.4948-0.7031-1.0873-0.7031-1.7774z" fill="#000" fill-opacity=".87" style=""/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 11 KiB

334
application/src/main/data/json/system/scada_symbols/low-voltage-transformer-tower-hp.svg

@ -0,0 +1,334 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:tb="https://thingsboard.io/svg" width="400" height="800" fill="none" version="1.1" viewBox="0 0 400 800"><tb:metadata xmlns=""><![CDATA[{
"title": "HP Low voltage transformer tower",
"description": "Low voltage transformer tower with various states.",
"searchTags": [
"power",
"energy"
],
"widgetSizeX": 2,
"widgetSizeY": 4,
"tags": [
{
"tag": "background",
"stateRenderFunction": "element.attr({fill: ctx.properties.backgroundColor});",
"actions": null
},
{
"tag": "clickArea",
"stateRenderFunction": null,
"actions": {
"click": {
"actionFunction": "ctx.api.callAction(event, 'click');"
}
}
},
{
"tag": "critical",
"stateRenderFunction": "element.attr({fill: ctx.properties.criticalColor});\nif (ctx.values.critical) {\n element.show();\n} else {\n element.hide();\n}\n\nvar elementCriticalAnimation = element.remember('criticalAnimation');\nvar criticalAnimation = ctx.values.critical && ctx.values.criticalAnimation;\n\nif (elementCriticalAnimation !== criticalAnimation) {\n element.remember('criticalAnimation', criticalAnimation);\n if (criticalAnimation) {\n ctx.api.cssAnimate(element, 500).attr({opacity: 0.15}).loop(0, true);\n } else {\n ctx.api.resetCssAnimation(element);\n }\n}\n\n",
"actions": {
"click": {
"actionFunction": "ctx.api.callAction(event, 'criticalClick');"
}
}
},
{
"tag": "transformer",
"stateRenderFunction": "var color = ctx.properties.stoppedColor;\nif (ctx.values.running) {\n color = ctx.properties.runningColor;\n}\nelement.attr({fill: color});",
"actions": null
},
{
"tag": "warning",
"stateRenderFunction": "element.attr({fill: ctx.properties.warningColor});\nvar warning = ctx.values.warning && !(ctx.values.warning && ctx.values.critical)\nif (warning) {\n element.show();\n} else {\n element.hide();\n}\n\nvar elementCriticalAnimation = element.remember('criticalAnimation');\nvar criticalAnimation = warning && ctx.values.criticalAnimation;\n\nif (elementCriticalAnimation !== criticalAnimation) {\n element.remember('criticalAnimation', criticalAnimation);\n if (criticalAnimation) {\n ctx.api.cssAnimate(element, 500).attr({opacity: 0.15}).loop(0, true);\n } else {\n ctx.api.resetCssAnimation(element);\n }\n}\n",
"actions": {
"click": {
"actionFunction": "ctx.api.callAction(event, 'warningClick');"
}
}
}
],
"behavior": [
{
"id": "running",
"name": "{i18n:scada.symbol.running}",
"hint": "{i18n:scada.symbol.running-hint}",
"group": null,
"type": "value",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": "{i18n:scada.symbol.running}",
"defaultGetValueSettings": {
"action": "GET_ATTRIBUTE",
"defaultValue": false,
"executeRpc": {
"method": "getState",
"requestTimeout": 5000,
"requestPersistent": false,
"persistentPollingInterval": 1000
},
"getAttribute": {
"scope": "SHARED_SCOPE",
"key": "running"
},
"getTimeSeries": {
"key": "state"
},
"getAlarmStatus": {
"severityList": null,
"typeList": null
},
"dataToValue": {
"type": "NONE",
"dataToValueFunction": "/* Should return boolean value */\nreturn data;",
"compareToValue": true
}
},
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": null
},
{
"id": "warning",
"name": "{i18n:scada.symbol.warning}",
"hint": "{i18n:scada.symbol.warning-state-hint}",
"group": "{i18n:scada.symbol.warning-state}",
"type": "value",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": "{i18n:scada.symbol.warning}",
"defaultGetValueSettings": {
"action": "GET_ALARM_STATUS",
"defaultValue": false,
"executeRpc": {
"method": "getState",
"requestTimeout": 5000,
"requestPersistent": false,
"persistentPollingInterval": 1000
},
"getAttribute": {
"scope": null,
"key": "state"
},
"getTimeSeries": {
"key": "state"
},
"getAlarmStatus": {
"severityList": [
"MAJOR",
"MINOR",
"WARNING",
"INDETERMINATE"
],
"typeList": null
},
"dataToValue": {
"type": "NONE",
"dataToValueFunction": "/* Should return boolean value */\nreturn data;",
"compareToValue": true
}
},
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": null
},
{
"id": "warningClick",
"name": "{i18n:scada.symbol.warning-click}",
"hint": "{i18n:scada.symbol.on-click-hint}",
"group": "{i18n:scada.symbol.warning-state}",
"type": "widgetAction",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": null,
"defaultGetValueSettings": null,
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": {
"type": "doNothing",
"targetDashboardStateId": null,
"openRightLayout": false,
"setEntityId": false,
"stateEntityParamName": null
}
},
{
"id": "critical",
"name": "{i18n:scada.symbol.critical}",
"hint": "{i18n:scada.symbol.critical-state-hint}",
"group": "{i18n:scada.symbol.critical-state}",
"type": "value",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": "{i18n:scada.symbol.critical}",
"defaultGetValueSettings": {
"action": "GET_ALARM_STATUS",
"defaultValue": false,
"executeRpc": {
"method": "getState",
"requestTimeout": 5000,
"requestPersistent": false,
"persistentPollingInterval": 1000
},
"getAttribute": {
"scope": null,
"key": "state"
},
"getTimeSeries": {
"key": "state"
},
"getAlarmStatus": {
"severityList": [
"CRITICAL"
],
"typeList": null
},
"dataToValue": {
"type": "NONE",
"dataToValueFunction": "/* Should return boolean value */\nreturn data;",
"compareToValue": true
}
},
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": null
},
{
"id": "criticalClick",
"name": "{i18n:scada.symbol.critical-click}",
"hint": "{i18n:scada.symbol.on-click-hint}",
"group": "{i18n:scada.symbol.critical-state}",
"type": "widgetAction",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": null,
"defaultGetValueSettings": null,
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": {
"type": "doNothing",
"targetDashboardStateId": null,
"openRightLayout": false,
"setEntityId": false,
"stateEntityParamName": null
}
},
{
"id": "criticalAnimation",
"name": "{i18n:scada.symbol.warning-critical-state-animation}",
"hint": "{i18n:scada.symbol.warning-critical-state-animation-hint}",
"group": null,
"type": "value",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": "{i18n:scada.symbol.animation}",
"defaultGetValueSettings": {
"action": "DO_NOTHING",
"defaultValue": false,
"executeRpc": {
"method": "getState",
"requestTimeout": 5000,
"requestPersistent": false,
"persistentPollingInterval": 1000
},
"getAttribute": {
"key": "state",
"scope": null
},
"getTimeSeries": {
"key": "state"
},
"dataToValue": {
"type": "NONE",
"compareToValue": true,
"dataToValueFunction": "/* Should return boolean value */\nreturn data;"
}
},
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": null
},
{
"id": "click",
"name": "{i18n:scada.symbol.on-click}",
"hint": "{i18n:scada.symbol.on-click-hint}",
"group": null,
"type": "widgetAction",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": null,
"defaultGetValueSettings": null,
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": {
"type": "doNothing",
"targetDashboardStateId": null,
"openRightLayout": false,
"setEntityId": false,
"stateEntityParamName": null
}
}
],
"properties": [
{
"id": "backgroundColor",
"name": "{i18n:scada.symbol.background-color}",
"type": "color",
"default": "#999999"
},
{
"id": "runningColor",
"name": "{i18n:scada.symbol.colors}",
"type": "color",
"default": "#FFFFFF",
"subLabel": "{i18n:scada.symbol.running}",
"divider": true
},
{
"id": "stoppedColor",
"name": "{i18n:scada.symbol.colors}",
"type": "color",
"default": "#666666",
"subLabel": "{i18n:scada.symbol.stopped}"
},
{
"id": "warningColor",
"name": "{i18n:scada.symbol.alarm-colors}",
"type": "color",
"default": "#FAA405",
"subLabel": "{i18n:scada.symbol.warning}",
"divider": true
},
{
"id": "criticalColor",
"name": "{i18n:scada.symbol.alarm-colors}",
"type": "color",
"default": "#D12730",
"subLabel": "{i18n:scada.symbol.critical}"
}
]
}]]></tb:metadata>
<g fill="#999" stroke="#1A1A1A" tb:tag="background">
<rect x="1" y="351" width="398" height="46" rx="1" stroke-width="2"/>
<rect x="1" y="151" width="398" height="46" rx="1" stroke-width="2"/>
<rect x="185" y="1" width="30" height="798" rx="5" stroke-width="2"/>
<path d="m3 97v55" stroke-width="6"/>
<path d="m3 297v55" stroke-width="6"/>
<path d="m397 97v55" stroke-width="6"/>
<path d="m397 297v55" stroke-width="6"/>
</g><g fill="#fff" tb:tag="transformer">
<rect x="131" y="501" width="138" height="134" stroke="#1A1A1A" stroke-width="2"/>
<rect x="121" y="479" width="158" height="22" rx="1" stroke="#1A1A1A" stroke-width="2"/>
<rect x="121" y="635" width="158" height="22" rx="1" stroke="#1A1A1A" stroke-width="2"/>
<path d="m162.17 602.42c-1.185 0-1.925-1.284-1.331-2.31l37.828-65.339c0.592-1.024 2.07-1.024 2.663 0l37.828 65.339c0.594 1.026-0.146 2.31-1.331 2.31h-75.657z" stroke="#1A1A1A" stroke-width="6.1538"/>
<path d="m203.36 565.96-12.954 11.604c-0.801 0.725-0.351 2.063 0.725 2.163l10.116 0.976-6.065 8.453c-0.275 0.387-0.237 0.925 0.1 1.262 0.375 0.376 0.963 0.388 1.351 0.025l12.954-11.604c0.801-0.725 0.351-2.063-0.725-2.163l-10.116-0.975 6.065-8.453c0.275-0.388 0.237-0.926-0.1-1.263-0.375-0.375-0.963-0.388-1.351-0.025z" fill="#1A1A1A"/>
</g><path d="m134.53 0s-134.53 0-134.53 134v656.72c0 5.3024 3.5818 9.2806 8 9.2806h384c4.418 0 8-3.9784 8-9.2806v-656.72c0-134-132.14-134-132.14-134h-67.86zm134.14 162.4c-2.5774 0-4.6666 2.5072-4.6666 5.6v600.8c0 3.0928 2.0894 5.6 4.6666 5.6h29.332c2.5774 0 4.6666-2.5072 4.6666-5.6v-600.8c0-3.0928-2.0894-5.6-4.6666-5.6z" fill-opacity="0" style="stroke-width:2.0908" tb:tag="clickArea"/><g fill="#d12730" style="display: none;" tb:tag="critical">
<rect width="84" height="84" rx="4" fill="#fff" style=""/>
<rect width="84" height="84" rx="4" style=""/>
<rect x="2" y="2" width="80" height="80" rx="2" stroke="#000" stroke-opacity=".87" stroke-width="4" style=""/>
<path d="m44.559 27.562-0.4688 20.059h-4.0234l-0.4883-20.059zm-5.1172 26.211c0-0.7161 0.2344-1.3151 0.7031-1.7968 0.4818-0.4948 1.1459-0.7422 1.9922-0.7422 0.8334 0 1.4909 0.2474 1.9727 0.7422 0.4817 0.4817 0.7226 1.0807 0.7226 1.7968 0 0.6901-0.2409 1.2826-0.7226 1.7774-0.4818 0.4818-1.1393 0.7226-1.9727 0.7226-0.8463 0-1.5104-0.2408-1.9922-0.7226-0.4687-0.4948-0.7031-1.0873-0.7031-1.7774z" fill="#000" fill-opacity=".87" style=""/>
</g><g fill="#faa405" style="display: none;" tb:tag="warning">
<path d="m35.955 2.2112c1.4741-2.9482 5.6813-2.9482 7.1554 0l35.528 71.056c1.3298 2.6596-0.6042 5.7889-3.5777 5.7889h-71.056c-2.9735 0-4.9075-3.1292-3.5777-5.7889z" fill="#fff" style=""/>
<path d="m35.955 2.2112c1.4741-2.9482 5.6813-2.9482 7.1554 0l35.528 71.056c1.3298 2.6596-0.6042 5.7889-3.5777 5.7889h-71.056c-2.9735 0-4.9075-3.1292-3.5777-5.7889z" style=""/>
<path d="m37.72 3.1061c0.7371-1.4741 2.8407-1.4741 3.5778-1e-5l35.528 71.056c0.6649 1.3298-0.3021 2.8944-1.7888 2.8944h-71.056c-1.4868 0-2.4538-1.5646-1.7889-2.8944z" stroke="#000" stroke-opacity=".87" stroke-width="4" style=""/>
<path d="m42.092 32.618-0.4688 20.059h-4.0234l-0.4883-20.059zm-5.1172 26.211c0-0.7161 0.2344-1.3151 0.7031-1.7968 0.4818-0.4948 1.1459-0.7422 1.9922-0.7422 0.8334 0 1.4909 0.2474 1.9727 0.7422 0.4817 0.4817 0.7226 1.0807 0.7226 1.7968 0 0.6901-0.2409 1.2826-0.7226 1.7774-0.4818 0.4818-1.1393 0.7226-1.9727 0.7226-0.8463 0-1.5104-0.2408-1.9922-0.7226-0.4687-0.4948-0.7031-1.0873-0.7031-1.7774z" fill="#000" fill-opacity=".87" style=""/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 13 KiB

344
application/src/main/data/json/system/scada_symbols/manufacture-hp.svg

@ -0,0 +1,344 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:tb="https://thingsboard.io/svg" width="400" height="400" fill="none" version="1.1" viewBox="0 0 400 400"><tb:metadata xmlns=""><![CDATA[{
"title": "HP Manufacture",
"description": "Manufacture with various states.",
"searchTags": [
"power",
"energy",
"consumer"
],
"widgetSizeX": 2,
"widgetSizeY": 2,
"tags": [
{
"tag": "background",
"stateRenderFunction": "var color = ctx.properties.stoppedColor;\nif (ctx.values.running) {\n color = ctx.properties.runningColor;\n}\nelement.attr({fill: color});",
"actions": null
},
{
"tag": "clickArea",
"stateRenderFunction": null,
"actions": {
"click": {
"actionFunction": "ctx.api.callAction(event, 'click');"
}
}
},
{
"tag": "critical",
"stateRenderFunction": "element.attr({fill: ctx.properties.criticalColor});\nif (ctx.values.critical) {\n element.show();\n} else {\n element.hide();\n}\n\nvar elementCriticalAnimation = element.remember('criticalAnimation');\nvar criticalAnimation = ctx.values.critical && ctx.values.criticalAnimation;\n\nif (elementCriticalAnimation !== criticalAnimation) {\n element.remember('criticalAnimation', criticalAnimation);\n if (criticalAnimation) {\n ctx.api.cssAnimate(element, 500).attr({opacity: 0.15}).loop(0, true);\n } else {\n ctx.api.resetCssAnimation(element);\n }\n}\n\n",
"actions": {
"click": {
"actionFunction": "ctx.api.callAction(event, 'criticalClick');"
}
}
},
{
"tag": "warning",
"stateRenderFunction": "element.attr({fill: ctx.properties.warningColor});\nvar warning = ctx.values.warning && !(ctx.values.warning && ctx.values.critical)\nif (warning) {\n element.show();\n} else {\n element.hide();\n}\n\nvar elementCriticalAnimation = element.remember('criticalAnimation');\nvar criticalAnimation = warning && ctx.values.criticalAnimation;\n\nif (elementCriticalAnimation !== criticalAnimation) {\n element.remember('criticalAnimation', criticalAnimation);\n if (criticalAnimation) {\n ctx.api.cssAnimate(element, 500).attr({opacity: 0.15}).loop(0, true);\n } else {\n ctx.api.resetCssAnimation(element);\n }\n}\n",
"actions": {
"click": {
"actionFunction": "ctx.api.callAction(event, 'warningClick');"
}
}
}
],
"behavior": [
{
"id": "running",
"name": "{i18n:scada.symbol.running}",
"hint": "{i18n:scada.symbol.running-hint}",
"group": null,
"type": "value",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": "{i18n:scada.symbol.running}",
"defaultGetValueSettings": {
"action": "GET_ATTRIBUTE",
"defaultValue": false,
"executeRpc": {
"method": "getState",
"requestTimeout": 5000,
"requestPersistent": false,
"persistentPollingInterval": 1000
},
"getAttribute": {
"scope": "SHARED_SCOPE",
"key": "running"
},
"getTimeSeries": {
"key": "state"
},
"getAlarmStatus": {
"severityList": null,
"typeList": null
},
"dataToValue": {
"type": "NONE",
"dataToValueFunction": "/* Should return boolean value */\nreturn data;",
"compareToValue": true
}
},
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": null
},
{
"id": "warning",
"name": "{i18n:scada.symbol.warning}",
"hint": "{i18n:scada.symbol.warning-state-hint}",
"group": "{i18n:scada.symbol.warning-state}",
"type": "value",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": "{i18n:scada.symbol.warning}",
"defaultGetValueSettings": {
"action": "GET_ALARM_STATUS",
"defaultValue": false,
"executeRpc": {
"method": "getState",
"requestTimeout": 5000,
"requestPersistent": false,
"persistentPollingInterval": 1000
},
"getAttribute": {
"scope": null,
"key": "state"
},
"getTimeSeries": {
"key": "state"
},
"getAlarmStatus": {
"severityList": [
"MAJOR",
"MINOR",
"WARNING",
"INDETERMINATE"
],
"typeList": null
},
"dataToValue": {
"type": "NONE",
"dataToValueFunction": "/* Should return boolean value */\nreturn data;",
"compareToValue": true
}
},
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": null
},
{
"id": "warningClick",
"name": "{i18n:scada.symbol.warning-click}",
"hint": "{i18n:scada.symbol.on-click-hint}",
"group": "{i18n:scada.symbol.warning-state}",
"type": "widgetAction",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": null,
"defaultGetValueSettings": null,
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": {
"type": "doNothing",
"targetDashboardStateId": null,
"openRightLayout": false,
"setEntityId": false,
"stateEntityParamName": null
}
},
{
"id": "critical",
"name": "{i18n:scada.symbol.critical}",
"hint": "{i18n:scada.symbol.critical-state-hint}",
"group": "{i18n:scada.symbol.critical-state}",
"type": "value",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": "{i18n:scada.symbol.critical}",
"defaultGetValueSettings": {
"action": "GET_ALARM_STATUS",
"defaultValue": false,
"executeRpc": {
"method": "getState",
"requestTimeout": 5000,
"requestPersistent": false,
"persistentPollingInterval": 1000
},
"getAttribute": {
"scope": null,
"key": "state"
},
"getTimeSeries": {
"key": "state"
},
"getAlarmStatus": {
"severityList": [
"CRITICAL"
],
"typeList": null
},
"dataToValue": {
"type": "NONE",
"dataToValueFunction": "/* Should return boolean value */\nreturn data;",
"compareToValue": true
}
},
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": null
},
{
"id": "criticalClick",
"name": "{i18n:scada.symbol.critical-click}",
"hint": "{i18n:scada.symbol.on-click-hint}",
"group": "{i18n:scada.symbol.critical-state}",
"type": "widgetAction",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": null,
"defaultGetValueSettings": null,
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": {
"type": "doNothing",
"targetDashboardStateId": null,
"openRightLayout": false,
"setEntityId": false,
"stateEntityParamName": null
}
},
{
"id": "criticalAnimation",
"name": "{i18n:scada.symbol.warning-critical-state-animation}",
"hint": "{i18n:scada.symbol.warning-critical-state-animation-hint}",
"group": null,
"type": "value",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": "{i18n:scada.symbol.animation}",
"defaultGetValueSettings": {
"action": "DO_NOTHING",
"defaultValue": false,
"executeRpc": {
"method": "getState",
"requestTimeout": 5000,
"requestPersistent": false,
"persistentPollingInterval": 1000
},
"getAttribute": {
"key": "state",
"scope": null
},
"getTimeSeries": {
"key": "state"
},
"dataToValue": {
"type": "NONE",
"compareToValue": true,
"dataToValueFunction": "/* Should return boolean value */\nreturn data;"
}
},
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": null
},
{
"id": "click",
"name": "{i18n:scada.symbol.on-click}",
"hint": "{i18n:scada.symbol.on-click-hint}",
"group": null,
"type": "widgetAction",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": null,
"defaultGetValueSettings": null,
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": {
"type": "doNothing",
"targetDashboardStateId": null,
"openRightLayout": false,
"setEntityId": false,
"stateEntityParamName": null
}
}
],
"properties": [
{
"id": "runningColor",
"name": "{i18n:scada.symbol.colors}",
"type": "color",
"default": "#FFFFFF",
"required": null,
"subLabel": "{i18n:scada.symbol.running}",
"divider": true,
"fieldSuffix": null,
"disableOnProperty": null,
"rowClass": "",
"fieldClass": "",
"min": null,
"max": null,
"step": null
},
{
"id": "stoppedColor",
"name": "{i18n:scada.symbol.colors}",
"type": "color",
"default": "#666666",
"required": null,
"subLabel": "{i18n:scada.symbol.stopped}",
"divider": null,
"fieldSuffix": null,
"disableOnProperty": null,
"rowClass": "",
"fieldClass": "",
"min": null,
"max": null,
"step": null
},
{
"id": "warningColor",
"name": "{i18n:scada.symbol.alarm-colors}",
"type": "color",
"default": "#FAA405",
"required": null,
"subLabel": "{i18n:scada.symbol.warning}",
"divider": true,
"fieldSuffix": null,
"disableOnProperty": null,
"rowClass": "",
"fieldClass": "",
"min": null,
"max": null,
"step": null
},
{
"id": "criticalColor",
"name": "{i18n:scada.symbol.alarm-colors}",
"type": "color",
"default": "#D12730",
"required": null,
"subLabel": "{i18n:scada.symbol.critical}",
"divider": null,
"fieldSuffix": null,
"disableOnProperty": null,
"rowClass": "",
"fieldClass": "",
"min": null,
"max": null,
"step": null
}
]
}]]></tb:metadata>
<path d="m294.35 1.9284c0.037-0.52316 0.473-0.92842 0.997-0.92842h35.314c0.524 0 0.96 0.40526 0.997 0.92843l11.195 156c0.041 0.579-0.417 1.072-0.998 1.072h-57.702c-0.581 0-1.039-0.493-0.998-1.072l11.195-156z" fill="#999" stroke="#1A1A1A" stroke-width="2"/><path d="m94.682 136.73 73.318-68.43v70l1.682-1.57 73.318-68.43v68.699h132c2.761 0 5 2.239 5 5v230c0 2.761-2.239 5-5 5h-350c-2.7614 0-5-2.239-5-5v-235.13c0-0.277 0.115-0.542 0.3177-0.731l72.682-67.837v70l1.6823-1.57z" fill="#fff" stroke="#1A1A1A" stroke-width="2" tb:tag="background"/><rect x="72" y="203" width="58" height="58" rx="1" fill="#999" stroke="#1A1A1A" stroke-width="2"/><rect x="138" y="203" width="58" height="58" rx="1" fill="#999" stroke="#1A1A1A" stroke-width="2"/><rect x="204" y="203" width="58" height="58" rx="1" fill="#999" stroke="#1A1A1A" stroke-width="2"/><rect x="270" y="203" width="58" height="58" rx="1" fill="#999" stroke="#1A1A1A" stroke-width="2"/><rect x="72" y="269" width="58" height="58" rx="1" fill="#999" stroke="#1A1A1A" stroke-width="2"/><rect x="138" y="269" width="58" height="58" rx="1" fill="#999" stroke="#1A1A1A" stroke-width="2"/><rect x="204" y="269" width="58" height="58" rx="1" fill="#999" stroke="#1A1A1A" stroke-width="2"/><rect x="270" y="269" width="58" height="58" rx="1" fill="#999" stroke="#1A1A1A" stroke-width="2"/><rect x="1" y="377" width="398" height="22" rx="5" fill="#fff" stroke="#1A1A1A" stroke-width="2" tb:tag="background"/><path d="m134.53 0s-134.53 0-134.53 67v328.36c0 2.6512 3.5818 4.6403 8 4.6403h384c4.418 0 8-1.9892 8-4.6403v-328.36c0-67-132.14-67-132.14-67h-67.86zm134.14 81.2c-2.5774 0-4.6666 1.2536-4.6666 2.8v300.4c0 1.5464 2.0894 2.8 4.6666 2.8h29.332c2.5774 0 4.6666-1.2536 4.6666-2.8v-300.4c0-1.5464-2.0894-2.8-4.6666-2.8z" fill-opacity="0" style="stroke-width:1.4784" tb:tag="clickArea"/><g transform="translate(0,316)" fill="#d12730" style="display: none;" tb:tag="critical">
<rect width="84" height="84" rx="4" fill="#fff" style=""/>
<rect width="84" height="84" rx="4" style=""/>
<rect x="2" y="2" width="80" height="80" rx="2" stroke="#000" stroke-opacity=".87" stroke-width="4" style=""/>
<path d="m44.559 27.562-0.4688 20.059h-4.0234l-0.4883-20.059zm-5.1172 26.211c0-0.7161 0.2344-1.3151 0.7031-1.7968 0.4818-0.4948 1.1459-0.7422 1.9922-0.7422 0.8334 0 1.4909 0.2474 1.9727 0.7422 0.4817 0.4817 0.7226 1.0807 0.7226 1.7968 0 0.6901-0.2409 1.2826-0.7226 1.7774-0.4818 0.4818-1.1393 0.7226-1.9727 0.7226-0.8463 0-1.5104-0.2408-1.9922-0.7226-0.4687-0.4948-0.7031-1.0873-0.7031-1.7774z" fill="#000" fill-opacity=".87" style=""/>
</g><g transform="translate(0 320.94)" fill="#faa405" style="display: none;" tb:tag="warning">
<path d="m35.955 2.2112c1.4741-2.9482 5.6813-2.9482 7.1554 0l35.528 71.056c1.3298 2.6596-0.6042 5.7889-3.5777 5.7889h-71.056c-2.9735 0-4.9075-3.1292-3.5777-5.7889z" fill="#fff" style=""/>
<path d="m35.955 2.2112c1.4741-2.9482 5.6813-2.9482 7.1554 0l35.528 71.056c1.3298 2.6596-0.6042 5.7889-3.5777 5.7889h-71.056c-2.9735 0-4.9075-3.1292-3.5777-5.7889z" style=""/>
<path d="m37.72 3.1061c0.7371-1.4741 2.8407-1.4741 3.5778-1e-5l35.528 71.056c0.6649 1.3298-0.3021 2.8944-1.7888 2.8944h-71.056c-1.4868 0-2.4538-1.5646-1.7889-2.8944z" stroke="#000" stroke-opacity=".87" stroke-width="4" style=""/>
<path d="m42.092 32.618-0.4688 20.059h-4.0234l-0.4883-20.059zm-5.1172 26.211c0-0.7161 0.2344-1.3151 0.7031-1.7968 0.4818-0.4948 1.1459-0.7422 1.9922-0.7422 0.8334 0 1.4909 0.2474 1.9727 0.7422 0.4817 0.4817 0.7226 1.0807 0.7226 1.7968 0 0.6901-0.2409 1.2826-0.7226 1.7774-0.4818 0.4818-1.1393 0.7226-1.9727 0.7226-0.8463 0-1.5104-0.2408-1.9922-0.7226-0.4687-0.4948-0.7031-1.0873-0.7031-1.7774z" fill="#000" fill-opacity=".87" style=""/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 14 KiB

371
application/src/main/data/json/system/scada_symbols/power-socket-hp.svg

@ -0,0 +1,371 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:tb="https://thingsboard.io/svg" width="200" height="200" fill="none" version="1.1" viewBox="0 0 200 200"><tb:metadata xmlns=""><![CDATA[{
"title": "HP Power socket",
"description": "Power socket with various states.",
"searchTags": [
"EU socket",
"US socket",
"Middle East socket",
"energy"
],
"widgetSizeX": 1,
"widgetSizeY": 1,
"tags": [
{
"tag": "background",
"stateRenderFunction": "var color = ctx.properties.stoppedColor;\nif (ctx.values.running) {\n color = ctx.properties.runningColor;\n}\nelement.attr({fill: color});",
"actions": null
},
{
"tag": "clickArea",
"stateRenderFunction": null,
"actions": {
"click": {
"actionFunction": "ctx.api.callAction(event, 'click');"
}
}
},
{
"tag": "critical",
"stateRenderFunction": "element.attr({fill: ctx.properties.criticalColor});\nif (ctx.values.critical) {\n element.show();\n} else {\n element.hide();\n}\n\nvar elementCriticalAnimation = element.remember('criticalAnimation');\nvar criticalAnimation = ctx.values.critical && ctx.values.criticalAnimation;\n\nif (elementCriticalAnimation !== criticalAnimation) {\n element.remember('criticalAnimation', criticalAnimation);\n if (criticalAnimation) {\n ctx.api.cssAnimate(element, 500).attr({opacity: 0.15}).loop(0, true);\n } else {\n ctx.api.resetCssAnimation(element);\n }\n}\n\n",
"actions": {
"click": {
"actionFunction": "ctx.api.callAction(event, 'criticalClick');"
}
}
},
{
"tag": "eu-socket",
"stateRenderFunction": "if (ctx.properties.socketType === 'eu') {\n element.show();\n} else {\n element.hide();\n}",
"actions": null
},
{
"tag": "middle-east-socket",
"stateRenderFunction": "if (ctx.properties.socketType === 'middleEast') {\n element.show();\n} else {\n element.hide();\n}",
"actions": null
},
{
"tag": "us-socket",
"stateRenderFunction": "if (ctx.properties.socketType === 'us') {\n element.show();\n} else {\n element.hide();\n}",
"actions": null
},
{
"tag": "warning",
"stateRenderFunction": "element.attr({fill: ctx.properties.warningColor});\nvar warning = ctx.values.warning && !(ctx.values.warning && ctx.values.critical)\nif (warning) {\n element.show();\n} else {\n element.hide();\n}\n\nvar elementCriticalAnimation = element.remember('criticalAnimation');\nvar criticalAnimation = warning && ctx.values.criticalAnimation;\n\nif (elementCriticalAnimation !== criticalAnimation) {\n element.remember('criticalAnimation', criticalAnimation);\n if (criticalAnimation) {\n ctx.api.cssAnimate(element, 500).attr({opacity: 0.15}).loop(0, true);\n } else {\n ctx.api.resetCssAnimation(element);\n }\n}\n",
"actions": {
"click": {
"actionFunction": "ctx.api.callAction(event, 'warningClick');"
}
}
}
],
"behavior": [
{
"id": "running",
"name": "{i18n:scada.symbol.running}",
"hint": "{i18n:scada.symbol.running-hint}",
"group": null,
"type": "value",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": "{i18n:scada.symbol.running}",
"defaultGetValueSettings": {
"action": "GET_ATTRIBUTE",
"defaultValue": false,
"executeRpc": {
"method": "getState",
"requestTimeout": 5000,
"requestPersistent": false,
"persistentPollingInterval": 1000
},
"getAttribute": {
"scope": "SHARED_SCOPE",
"key": "running"
},
"getTimeSeries": {
"key": "state"
},
"getAlarmStatus": {
"severityList": null,
"typeList": null
},
"dataToValue": {
"type": "NONE",
"dataToValueFunction": "/* Should return boolean value */\nreturn data;",
"compareToValue": true
}
},
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": null
},
{
"id": "warning",
"name": "{i18n:scada.symbol.warning}",
"hint": "{i18n:scada.symbol.warning-state-hint}",
"group": "{i18n:scada.symbol.warning-state}",
"type": "value",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": "{i18n:scada.symbol.warning}",
"defaultGetValueSettings": {
"action": "GET_ALARM_STATUS",
"defaultValue": false,
"executeRpc": {
"method": "getState",
"requestTimeout": 5000,
"requestPersistent": false,
"persistentPollingInterval": 1000
},
"getAttribute": {
"scope": null,
"key": "state"
},
"getTimeSeries": {
"key": "state"
},
"getAlarmStatus": {
"severityList": [
"MAJOR",
"MINOR",
"WARNING",
"INDETERMINATE"
],
"typeList": null
},
"dataToValue": {
"type": "NONE",
"dataToValueFunction": "/* Should return boolean value */\nreturn data;",
"compareToValue": true
}
},
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": null
},
{
"id": "warningClick",
"name": "{i18n:scada.symbol.warning-click}",
"hint": "{i18n:scada.symbol.on-click-hint}",
"group": "{i18n:scada.symbol.warning-state}",
"type": "widgetAction",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": null,
"defaultGetValueSettings": null,
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": {
"type": "doNothing",
"targetDashboardStateId": null,
"openRightLayout": false,
"setEntityId": false,
"stateEntityParamName": null
}
},
{
"id": "critical",
"name": "{i18n:scada.symbol.critical}",
"hint": "{i18n:scada.symbol.critical-state-hint}",
"group": "{i18n:scada.symbol.critical-state}",
"type": "value",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": "{i18n:scada.symbol.critical}",
"defaultGetValueSettings": {
"action": "GET_ALARM_STATUS",
"defaultValue": false,
"executeRpc": {
"method": "getState",
"requestTimeout": 5000,
"requestPersistent": false,
"persistentPollingInterval": 1000
},
"getAttribute": {
"scope": null,
"key": "state"
},
"getTimeSeries": {
"key": "state"
},
"getAlarmStatus": {
"severityList": [
"CRITICAL"
],
"typeList": null
},
"dataToValue": {
"type": "NONE",
"dataToValueFunction": "/* Should return boolean value */\nreturn data;",
"compareToValue": true
}
},
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": null
},
{
"id": "criticalClick",
"name": "{i18n:scada.symbol.critical-click}",
"hint": "{i18n:scada.symbol.on-click-hint}",
"group": "{i18n:scada.symbol.critical-state}",
"type": "widgetAction",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": null,
"defaultGetValueSettings": null,
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": {
"type": "doNothing",
"targetDashboardStateId": null,
"openRightLayout": false,
"setEntityId": false,
"stateEntityParamName": null
}
},
{
"id": "criticalAnimation",
"name": "{i18n:scada.symbol.warning-critical-state-animation}",
"hint": "{i18n:scada.symbol.warning-critical-state-animation-hint}",
"group": null,
"type": "value",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": "{i18n:scada.symbol.animation}",
"defaultGetValueSettings": {
"action": "DO_NOTHING",
"defaultValue": false,
"executeRpc": {
"method": "getState",
"requestTimeout": 5000,
"requestPersistent": false,
"persistentPollingInterval": 1000
},
"getAttribute": {
"key": "state",
"scope": null
},
"getTimeSeries": {
"key": "state"
},
"dataToValue": {
"type": "NONE",
"compareToValue": true,
"dataToValueFunction": "/* Should return boolean value */\nreturn data;"
}
},
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": null
},
{
"id": "click",
"name": "{i18n:scada.symbol.on-click}",
"hint": "{i18n:scada.symbol.on-click-hint}",
"group": null,
"type": "widgetAction",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": null,
"defaultGetValueSettings": null,
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": {
"type": "doNothing",
"targetDashboardStateId": null,
"openRightLayout": false,
"setEntityId": false,
"stateEntityParamName": null
}
}
],
"properties": [
{
"id": "socketType",
"name": "{i18n:scada.symbol.socket}",
"type": "select",
"default": "eu",
"fieldClass": "flex",
"items": [
{
"value": "eu",
"label": "EU"
},
{
"value": "us",
"label": "US"
},
{
"value": "middleEast",
"label": "Middle East"
}
],
"disabled": false,
"visible": true
},
{
"id": "runningColor",
"name": "{i18n:scada.symbol.colors}",
"type": "color",
"default": "#FFFFFF",
"subLabel": "{i18n:scada.symbol.running}",
"divider": true,
"disabled": false,
"visible": true
},
{
"id": "stoppedColor",
"name": "{i18n:scada.symbol.colors}",
"type": "color",
"default": "#666666",
"subLabel": "{i18n:scada.symbol.stopped}",
"disabled": false,
"visible": true
},
{
"id": "warningColor",
"name": "{i18n:scada.symbol.alarm-colors}",
"type": "color",
"default": "#FAA405",
"subLabel": "{i18n:scada.symbol.warning}",
"divider": true,
"disabled": false,
"visible": true
},
{
"id": "criticalColor",
"name": "{i18n:scada.symbol.alarm-colors}",
"type": "color",
"default": "#D12730",
"subLabel": "{i18n:scada.symbol.critical}",
"disabled": false,
"visible": true
}
]
}]]></tb:metadata>
<rect x="1" y="1" width="198" height="198" fill="#fff" stroke="#1A1A1A" stroke-width="2" tb:tag="background"/><g tb:tag="eu-socket">
<circle cx="100" cy="100" r="69" stroke="#1A1A1A" stroke-width="2"/>
<circle cx="100" cy="64" r="7" stroke="#727171" stroke-width="2"/>
<circle cx="129" cy="100" r="8" fill="#1A1A1A"/>
<circle cx="71" cy="100" r="8" fill="#1A1A1A"/>
</g><g style="display: none;" tb:tag="us-socket">
<rect x="74" y="84" width="6" height="32" rx="1" fill="#1a1a1a" style=""/>
<rect x="120" y="84" width="6" height="32" rx="1" fill="#1a1a1a" style=""/>
<rect x="31" y="31" width="138" height="138" rx="3" stroke="#1a1a1a" stroke-width="2" style=""/>
</g><g style="display: none;" tb:tag="middle-east-socket">
<rect x="31" y="31" width="138" height="138" rx="3" stroke="#1a1a1a" stroke-width="2" style=""/>
<rect transform="rotate(90,85,124)" x="85" y="124" width="6" height="24" rx="1" fill="#1a1a1a" style=""/>
<rect transform="rotate(-90,115,130)" x="115" y="130" width="6" height="24" rx="1" fill="#1a1a1a" style=""/>
<rect x="95" y="70" width="10" height="24" rx="1" fill="#1a1a1a" style=""/>
</g><path d="m67.267 0s-67.267 0-67.267 33.5v164.18c0 1.3256 1.7909 2.3202 4 2.3202h192c2.209 0 4-0.9946 4-2.3202v-164.18c0-33.5-66.07-33.5-66.07-33.5h-33.93zm67.07 40.6c-1.2887 0-2.3333 0.6268-2.3333 1.4v150.2c0 0.7732 1.0447 1.4 2.3333 1.4h14.666c1.2887 0 2.3333-0.6268 2.3333-1.4v-150.2c0-0.7732-1.0447-1.4-2.3333-1.4z" fill-opacity="0" tb:tag="clickArea"/><g fill="#d12730" style="display: none;" tb:tag="critical">
<rect width="84" height="84" rx="4" fill="#fff" style=""/>
<rect width="84" height="84" rx="4" style=""/>
<rect x="2" y="2" width="80" height="80" rx="2" stroke="#000" stroke-opacity=".87" stroke-width="4" style=""/>
<path d="m44.559 27.562-0.4688 20.059h-4.0234l-0.4883-20.059zm-5.1172 26.211c0-0.7161 0.2344-1.3151 0.7031-1.7968 0.4818-0.4948 1.1459-0.7422 1.9922-0.7422 0.8334 0 1.4909 0.2474 1.9727 0.7422 0.4817 0.4817 0.7226 1.0807 0.7226 1.7968 0 0.6901-0.2409 1.2826-0.7226 1.7774-0.4818 0.4818-1.1393 0.7226-1.9727 0.7226-0.8463 0-1.5104-0.2408-1.9922-0.7226-0.4687-0.4948-0.7031-1.0873-0.7031-1.7774z" fill="#000" fill-opacity=".87" style=""/>
</g><g fill="#faa405" style="display: none;" tb:tag="warning">
<path d="m35.955 2.2112c1.4741-2.9482 5.6813-2.9482 7.1554 0l35.528 71.056c1.3298 2.6596-0.6042 5.7889-3.5777 5.7889h-71.056c-2.9735 0-4.9075-3.1292-3.5777-5.7889z" fill="#fff" style=""/>
<path d="m35.955 2.2112c1.4741-2.9482 5.6813-2.9482 7.1554 0l35.528 71.056c1.3298 2.6596-0.6042 5.7889-3.5777 5.7889h-71.056c-2.9735 0-4.9075-3.1292-3.5777-5.7889z" style=""/>
<path d="m37.72 3.1061c0.7371-1.4741 2.8407-1.4741 3.5778-1e-5l35.528 71.056c0.6649 1.3298-0.3021 2.8944-1.7888 2.8944h-71.056c-1.4868 0-2.4538-1.5646-1.7889-2.8944z" stroke="#000" stroke-opacity=".87" stroke-width="4" style=""/>
<path d="m42.092 32.618-0.4688 20.059h-4.0234l-0.4883-20.059zm-5.1172 26.211c0-0.7161 0.2344-1.3151 0.7031-1.7968 0.4818-0.4948 1.1459-0.7422 1.9922-0.7422 0.8334 0 1.4909 0.2474 1.9727 0.7422 0.4817 0.4817 0.7226 1.0807 0.7226 1.7968 0 0.6901-0.2409 1.2826-0.7226 1.7774-0.4818 0.4818-1.1393 0.7226-1.9727 0.7226-0.8463 0-1.5104-0.2408-1.9922-0.7226-0.4687-0.4948-0.7031-1.0873-0.7031-1.7774z" fill="#000" fill-opacity=".87" style=""/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 14 KiB

359
application/src/main/data/json/system/scada_symbols/power-transformer-hp.svg

@ -0,0 +1,359 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:tb="https://thingsboard.io/svg" width="400" height="600" fill="none" version="1.1" viewBox="0 0 400 600"><tb:metadata xmlns=""><![CDATA[{
"title": "HP Power transformer",
"description": "Power transformer with various states.",
"searchTags": [
"power",
"energy"
],
"widgetSizeX": 2,
"widgetSizeY": 3,
"tags": [
{
"tag": "background",
"stateRenderFunction": "var color = ctx.properties.stoppedColor;\nif (ctx.values.running) {\n color = ctx.properties.runningColor;\n}\nelement.attr({fill: color});",
"actions": null
},
{
"tag": "clickArea",
"stateRenderFunction": null,
"actions": {
"click": {
"actionFunction": "ctx.api.callAction(event, 'click');"
}
}
},
{
"tag": "critical",
"stateRenderFunction": "element.attr({fill: ctx.properties.criticalColor});\nif (ctx.values.critical) {\n element.show();\n} else {\n element.hide();\n}\n\nvar elementCriticalAnimation = element.remember('criticalAnimation');\nvar criticalAnimation = ctx.values.critical && ctx.values.criticalAnimation;\n\nif (elementCriticalAnimation !== criticalAnimation) {\n element.remember('criticalAnimation', criticalAnimation);\n if (criticalAnimation) {\n ctx.api.cssAnimate(element, 500).attr({opacity: 0.15}).loop(0, true);\n } else {\n ctx.api.resetCssAnimation(element);\n }\n}\n\n",
"actions": {
"click": {
"actionFunction": "ctx.api.callAction(event, 'criticalClick');"
}
}
},
{
"tag": "warning",
"stateRenderFunction": "element.attr({fill: ctx.properties.warningColor});\nvar warning = ctx.values.warning && !(ctx.values.warning && ctx.values.critical)\nif (warning) {\n element.show();\n} else {\n element.hide();\n}\n\nvar elementCriticalAnimation = element.remember('criticalAnimation');\nvar criticalAnimation = warning && ctx.values.criticalAnimation;\n\nif (elementCriticalAnimation !== criticalAnimation) {\n element.remember('criticalAnimation', criticalAnimation);\n if (criticalAnimation) {\n ctx.api.cssAnimate(element, 500).attr({opacity: 0.15}).loop(0, true);\n } else {\n ctx.api.resetCssAnimation(element);\n }\n}\n",
"actions": {
"click": {
"actionFunction": "ctx.api.callAction(event, 'warningClick');"
}
}
}
],
"behavior": [
{
"id": "running",
"name": "{i18n:scada.symbol.running}",
"hint": "{i18n:scada.symbol.running-hint}",
"group": null,
"type": "value",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": "{i18n:scada.symbol.running}",
"defaultGetValueSettings": {
"action": "GET_ATTRIBUTE",
"defaultValue": false,
"executeRpc": {
"method": "getState",
"requestTimeout": 5000,
"requestPersistent": false,
"persistentPollingInterval": 1000
},
"getAttribute": {
"scope": "SHARED_SCOPE",
"key": "running"
},
"getTimeSeries": {
"key": "state"
},
"getAlarmStatus": {
"severityList": null,
"typeList": null
},
"dataToValue": {
"type": "NONE",
"dataToValueFunction": "/* Should return boolean value */\nreturn data;",
"compareToValue": true
}
},
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": null
},
{
"id": "warning",
"name": "{i18n:scada.symbol.warning}",
"hint": "{i18n:scada.symbol.warning-state-hint}",
"group": "{i18n:scada.symbol.warning-state}",
"type": "value",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": "{i18n:scada.symbol.warning}",
"defaultGetValueSettings": {
"action": "GET_ALARM_STATUS",
"defaultValue": false,
"executeRpc": {
"method": "getState",
"requestTimeout": 5000,
"requestPersistent": false,
"persistentPollingInterval": 1000
},
"getAttribute": {
"scope": null,
"key": "state"
},
"getTimeSeries": {
"key": "state"
},
"getAlarmStatus": {
"severityList": [
"MAJOR",
"MINOR",
"WARNING",
"INDETERMINATE"
],
"typeList": null
},
"dataToValue": {
"type": "NONE",
"dataToValueFunction": "/* Should return boolean value */\nreturn data;",
"compareToValue": true
}
},
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": null
},
{
"id": "warningClick",
"name": "{i18n:scada.symbol.warning-click}",
"hint": "{i18n:scada.symbol.on-click-hint}",
"group": "{i18n:scada.symbol.warning-state}",
"type": "widgetAction",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": null,
"defaultGetValueSettings": null,
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": {
"type": "doNothing",
"targetDashboardStateId": null,
"openRightLayout": false,
"setEntityId": false,
"stateEntityParamName": null
}
},
{
"id": "critical",
"name": "{i18n:scada.symbol.critical}",
"hint": "{i18n:scada.symbol.critical-state-hint}",
"group": "{i18n:scada.symbol.critical-state}",
"type": "value",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": "{i18n:scada.symbol.critical}",
"defaultGetValueSettings": {
"action": "GET_ALARM_STATUS",
"defaultValue": false,
"executeRpc": {
"method": "getState",
"requestTimeout": 5000,
"requestPersistent": false,
"persistentPollingInterval": 1000
},
"getAttribute": {
"scope": null,
"key": "state"
},
"getTimeSeries": {
"key": "state"
},
"getAlarmStatus": {
"severityList": [
"CRITICAL"
],
"typeList": null
},
"dataToValue": {
"type": "NONE",
"dataToValueFunction": "/* Should return boolean value */\nreturn data;",
"compareToValue": true
}
},
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": null
},
{
"id": "criticalClick",
"name": "{i18n:scada.symbol.critical-click}",
"hint": "{i18n:scada.symbol.on-click-hint}",
"group": "{i18n:scada.symbol.critical-state}",
"type": "widgetAction",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": null,
"defaultGetValueSettings": null,
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": {
"type": "doNothing",
"targetDashboardStateId": null,
"openRightLayout": false,
"setEntityId": false,
"stateEntityParamName": null
}
},
{
"id": "criticalAnimation",
"name": "{i18n:scada.symbol.warning-critical-state-animation}",
"hint": "{i18n:scada.symbol.warning-critical-state-animation-hint}",
"group": null,
"type": "value",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": "{i18n:scada.symbol.animation}",
"defaultGetValueSettings": {
"action": "DO_NOTHING",
"defaultValue": false,
"executeRpc": {
"method": "getState",
"requestTimeout": 5000,
"requestPersistent": false,
"persistentPollingInterval": 1000
},
"getAttribute": {
"key": "state",
"scope": null
},
"getTimeSeries": {
"key": "state"
},
"dataToValue": {
"type": "NONE",
"compareToValue": true,
"dataToValueFunction": "/* Should return boolean value */\nreturn data;"
}
},
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": null
},
{
"id": "click",
"name": "{i18n:scada.symbol.on-click}",
"hint": "{i18n:scada.symbol.on-click-hint}",
"group": null,
"type": "widgetAction",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": null,
"defaultGetValueSettings": null,
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": {
"type": "doNothing",
"targetDashboardStateId": null,
"openRightLayout": false,
"setEntityId": false,
"stateEntityParamName": null
}
}
],
"properties": [
{
"id": "runningColor",
"name": "{i18n:scada.symbol.colors}",
"type": "color",
"default": "#FFFFFF",
"required": null,
"subLabel": "{i18n:scada.symbol.running}",
"divider": true,
"fieldSuffix": null,
"disableOnProperty": null,
"rowClass": "",
"fieldClass": "",
"min": null,
"max": null,
"step": null
},
{
"id": "stoppedColor",
"name": "{i18n:scada.symbol.colors}",
"type": "color",
"default": "#666666",
"required": null,
"subLabel": "{i18n:scada.symbol.stopped}",
"divider": null,
"fieldSuffix": null,
"disableOnProperty": null,
"rowClass": "",
"fieldClass": "",
"min": null,
"max": null,
"step": null
},
{
"id": "warningColor",
"name": "{i18n:scada.symbol.alarm-colors}",
"type": "color",
"default": "#FAA405",
"required": null,
"subLabel": "{i18n:scada.symbol.warning}",
"divider": true,
"fieldSuffix": null,
"disableOnProperty": null,
"rowClass": "",
"fieldClass": "",
"min": null,
"max": null,
"step": null
},
{
"id": "criticalColor",
"name": "{i18n:scada.symbol.alarm-colors}",
"type": "color",
"default": "#D12730",
"required": null,
"subLabel": "{i18n:scada.symbol.critical}",
"divider": null,
"fieldSuffix": null,
"disableOnProperty": null,
"rowClass": "",
"fieldClass": "",
"min": null,
"max": null,
"step": null
}
]
}]]></tb:metadata>
<g fill="#fff" stroke-width="2" tb:tag="background">
<rect x="17" y="161" width="366" height="398" rx="5" stroke="#1a1a1a"/>
<rect x="1" y="559" width="398" height="40" rx="5" stroke="#1a1a1a"/>
<path d="m67 35.406c0-3.4797 1.5105-6.788 4.1398-9.0673l5.4938-4.7625c5.6366-4.8862 12.846-7.576 20.306-7.576h6.1218c7.459 0 14.669 2.6899 20.305 7.576l5.494 4.7625c2.63 2.2793 4.14 5.5876 4.14 9.0673v2.3965c0 5.0878-3.208 9.6226-8.006 11.316l-2.189 0.7724c-3.955 1.3961-8.119 2.1094-12.314 2.1094h-20.982c-4.1947 0-8.3588-0.7133-12.314-2.1094l-2.1886-0.7724c-4.7978-1.6933-8.0062-6.2281-8.0062-11.316v-2.3965z" stroke="#1A1A1A"/>
<path d="m67 73.406c0-3.4797 1.5105-6.788 4.1398-9.0673l5.4938-4.7625c5.6366-4.8862 12.846-7.576 20.306-7.576h6.1218c7.459 0 14.669 2.6899 20.305 7.576l5.494 4.7625c2.63 2.2793 4.14 5.5876 4.14 9.0673v2.3965c0 5.0878-3.208 9.6226-8.006 11.316l-2.189 0.7724c-3.955 1.3961-8.119 2.1094-12.314 2.1094h-20.982c-4.1947 0-8.3588-0.7133-12.314-2.1094l-2.1886-0.7724c-4.7978-1.6933-8.0062-6.2281-8.0062-11.316v-2.3965z" stroke="#1A1A1A"/>
<path d="m67 111.41c0-3.48 1.5105-6.788 4.1398-9.068l5.4938-4.762c5.6366-4.8862 12.846-7.576 20.306-7.576h6.1218c7.459 0 14.669 2.6899 20.305 7.576l5.494 4.762c2.63 2.28 4.14 5.588 4.14 9.068v2.396c0 5.088-3.208 9.623-8.006 11.316l-2.189 0.773c-3.955 1.396-8.119 2.109-12.314 2.109h-20.982c-4.1947 0-8.3588-0.713-12.314-2.109l-2.1886-0.773c-4.7978-1.693-8.0062-6.228-8.0062-11.316v-2.396z" stroke="#1A1A1A"/>
<rect x="85" y="128" width="30" height="11" rx="1" stroke="#1A1A1A"/>
<path d="m267 35.406c0-3.4797 1.51-6.788 4.14-9.0673l5.494-4.7625c5.636-4.8862 12.846-7.576 20.305-7.576h6.122c7.459 0 14.669 2.6899 20.305 7.576l5.494 4.7625c2.63 2.2793 4.14 5.5876 4.14 9.0673v2.3965c0 5.0878-3.208 9.6226-8.006 11.316l-2.189 0.7724c-3.955 1.3961-8.119 2.1094-12.314 2.1094h-20.982c-4.195 0-8.359-0.7133-12.314-2.1094l-2.189-0.7724c-4.798-1.6933-8.006-6.2281-8.006-11.316z" stroke="#1a1a1a"/>
<path d="m267 73.406c0-3.4797 1.51-6.788 4.14-9.0673l5.494-4.7625c5.636-4.8862 12.846-7.576 20.305-7.576h6.122c7.459 0 14.669 2.6899 20.305 7.576l5.494 4.7625c2.63 2.2793 4.14 5.5876 4.14 9.0673v2.3965c0 5.0878-3.208 9.6226-8.006 11.316l-2.189 0.7724c-3.955 1.3961-8.119 2.1094-12.314 2.1094h-20.982c-4.195 0-8.359-0.7133-12.314-2.1094l-2.189-0.7724c-4.798-1.6933-8.006-6.2281-8.006-11.316z" stroke="#1a1a1a"/>
<path d="m267 111.41c0-3.48 1.51-6.788 4.14-9.068l5.494-4.762c5.636-4.8862 12.846-7.576 20.305-7.576h6.122c7.459 0 14.669 2.6899 20.305 7.576l5.494 4.762c2.63 2.28 4.14 5.588 4.14 9.068v2.396c0 5.088-3.208 9.623-8.006 11.316l-2.189 0.773c-3.955 1.396-8.119 2.109-12.314 2.109h-20.982c-4.195 0-8.359-0.713-12.314-2.109l-2.189-0.773c-4.798-1.693-8.006-6.228-8.006-11.316z" stroke="#1a1a1a"/>
<rect x="285" y="128" width="30" height="11" rx="1" stroke="#1a1a1a"/>
<path d="m167 35.406c0-3.4797 1.51-6.788 4.14-9.0673l5.494-4.7625c5.636-4.8862 12.846-7.576 20.305-7.576h6.122c7.459 0 14.669 2.6899 20.305 7.576l5.494 4.7625c2.63 2.2793 4.14 5.5876 4.14 9.0673v2.3965c0 5.0878-3.208 9.6226-8.006 11.316l-2.189 0.7724c-3.955 1.3961-8.119 2.1094-12.314 2.1094h-20.982c-4.195 0-8.359-0.7133-12.314-2.1094l-2.189-0.7724c-4.798-1.6933-8.006-6.2281-8.006-11.316z" stroke="#1a1a1a"/>
<path d="m167 73.406c0-3.4797 1.51-6.788 4.14-9.0673l5.494-4.7625c5.636-4.8862 12.846-7.576 20.305-7.576h6.122c7.459 0 14.669 2.6899 20.305 7.576l5.494 4.7625c2.63 2.2793 4.14 5.5876 4.14 9.0673v2.3965c0 5.0878-3.208 9.6226-8.006 11.316l-2.189 0.7724c-3.955 1.3961-8.119 2.1094-12.314 2.1094h-20.982c-4.195 0-8.359-0.7133-12.314-2.1094l-2.189-0.7724c-4.798-1.6933-8.006-6.2281-8.006-11.316z" stroke="#1a1a1a"/>
<path d="m167 111.41c0-3.48 1.51-6.788 4.14-9.068l5.494-4.762c5.636-4.8862 12.846-7.576 20.305-7.576h6.122c7.459 0 14.669 2.6899 20.305 7.576l5.494 4.762c2.63 2.28 4.14 5.588 4.14 9.068v2.396c0 5.088-3.208 9.623-8.006 11.316l-2.189 0.773c-3.955 1.396-8.119 2.109-12.314 2.109h-20.982c-4.195 0-8.359-0.713-12.314-2.109l-2.189-0.773c-4.798-1.693-8.006-6.228-8.006-11.316z" stroke="#1a1a1a"/>
<rect x="185" y="128" width="30" height="11" rx="1" stroke="#1a1a1a"/>
<rect x="1" y="139" width="398" height="22" rx="5" stroke="#1A1A1A"/>
</g><path d="m150.82 410.75c-1.541 0-2.503-1.669-1.731-3.002l49.176-84.942c0.771-1.33 2.692-1.33 3.462 0l49.177 84.942c0.772 1.333-0.19 3.002-1.731 3.002h-98.353z" stroke="#1A1A1A" stroke-width="8"/><path d="m204.37 363.34-16.841 15.085c-1.041 0.943-0.455 2.682 0.943 2.812l13.151 1.268-7.884 10.989c-0.358 0.504-0.309 1.203 0.13 1.642 0.487 0.488 1.251 0.504 1.755 0.033l16.841-15.086c1.041-0.943 0.455-2.682-0.943-2.812l-13.151-1.268 7.885-10.989c0.357-0.504 0.308-1.203-0.131-1.642-0.487-0.488-1.251-0.504-1.755-0.032z" fill="#1A1A1A"/><rect x="90" width="20" height="15" rx="2" fill="#1A1A1A"/><rect x="290" width="20" height="15" rx="2" fill="#1a1a1a"/><rect x="190" width="20" height="15" rx="2" fill="#1a1a1a"/><path d="m134.53 0s-134.53 0-134.53 100.5v492.54c0 3.9768 3.5818 6.9605 8 6.9605h384c4.418 0 8-2.9838 8-6.9605v-492.54c0-100.5-132.14-100.5-132.14-100.5h-67.86zm134.14 121.8c-2.5774 0-4.6666 1.8804-4.6666 4.2v450.6c0 2.3196 2.0894 4.2 4.6666 4.2h29.332c2.5774 0 4.6666-1.8804 4.6666-4.2v-450.6c0-2.3196-2.0894-4.2-4.6666-4.2z" fill="#000" fill-opacity="0" tb:tag="clickArea"/><g transform="translate(0,516)" fill="#d12730" style="display: none;" tb:tag="critical">
<rect width="84" height="84" rx="4" fill="#fff" style=""/>
<rect width="84" height="84" rx="4" style=""/>
<rect x="2" y="2" width="80" height="80" rx="2" stroke="#000" stroke-opacity=".87" stroke-width="4" style=""/>
<path d="m44.559 27.562-0.4688 20.059h-4.0234l-0.4883-20.059zm-5.1172 26.211c0-0.7161 0.2344-1.3151 0.7031-1.7968 0.4818-0.4948 1.1459-0.7422 1.9922-0.7422 0.8334 0 1.4909 0.2474 1.9727 0.7422 0.4817 0.4817 0.7226 1.0807 0.7226 1.7968 0 0.6901-0.2409 1.2826-0.7226 1.7774-0.4818 0.4818-1.1393 0.7226-1.9727 0.7226-0.8463 0-1.5104-0.2408-1.9922-0.7226-0.4687-0.4948-0.7031-1.0873-0.7031-1.7774z" fill="#000" fill-opacity=".87" style=""/>
</g><g transform="translate(0 520.94)" fill="#faa405" style="display: none;" tb:tag="warning">
<path d="m35.955 2.2112c1.4741-2.9482 5.6813-2.9482 7.1554 0l35.528 71.056c1.3298 2.6596-0.6042 5.7889-3.5777 5.7889h-71.056c-2.9735 0-4.9075-3.1292-3.5777-5.7889z" fill="#fff" style=""/>
<path d="m35.955 2.2112c1.4741-2.9482 5.6813-2.9482 7.1554 0l35.528 71.056c1.3298 2.6596-0.6042 5.7889-3.5777 5.7889h-71.056c-2.9735 0-4.9075-3.1292-3.5777-5.7889z" style=""/>
<path d="m37.72 3.1061c0.7371-1.4741 2.8407-1.4741 3.5778-1e-5l35.528 71.056c0.6649 1.3298-0.3021 2.8944-1.7888 2.8944h-71.056c-1.4868 0-2.4538-1.5646-1.7889-2.8944z" stroke="#000" stroke-opacity=".87" stroke-width="4" style=""/>
<path d="m42.092 32.618-0.4688 20.059h-4.0234l-0.4883-20.059zm-5.1172 26.211c0-0.7161 0.2344-1.3151 0.7031-1.7968 0.4818-0.4948 1.1459-0.7422 1.9922-0.7422 0.8334 0 1.4909 0.2474 1.9727 0.7422 0.4817 0.4817 0.7226 1.0807 0.7226 1.7968 0 0.6901-0.2409 1.2826-0.7226 1.7774-0.4818 0.4818-1.1393 0.7226-1.9727 0.7226-0.8463 0-1.5104-0.2408-1.9922-0.7226-0.4687-0.4948-0.7031-1.0873-0.7031-1.7774z" fill="#000" fill-opacity=".87" style=""/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 17 KiB

373
application/src/main/data/json/system/scada_symbols/single-key-switch-hp.svg

@ -0,0 +1,373 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:tb="https://thingsboard.io/svg" width="200" height="200" fill="none" version="1.1" viewBox="0 0 200 200"><tb:metadata xmlns=""><![CDATA[{
"title": "HP Single-key switch",
"description": "Single-key switch with various states.",
"searchTags": [
"energy",
"power"
],
"widgetSizeX": 1,
"widgetSizeY": 1,
"tags": [
{
"tag": "background",
"stateRenderFunction": "element.attr({fill: ctx.properties.backgroundColor});",
"actions": null
},
{
"tag": "button",
"stateRenderFunction": "var color = ctx.properties.disabledColor;\nif (ctx.values.initialState) {\n color = ctx.properties.enabledColor;\n}\nelement.attr({fill: color});",
"actions": {
"click": {
"actionFunction": "var initial = ctx.values.initialState;\nvar action = initial ? 'offUpdateState' : 'onUpdateState';\n\nctx.api.callAction(event, action, undefined, {\n next: () => {\n ctx.api.setValue('initialState', !initial);\n }\n});"
}
}
},
{
"tag": "critical",
"stateRenderFunction": "element.attr({fill: ctx.properties.criticalColor});\nif (ctx.values.critical) {\n element.show();\n} else {\n element.hide();\n}\n\nvar elementCriticalAnimation = element.remember('criticalAnimation');\nvar criticalAnimation = ctx.values.critical && ctx.values.criticalAnimation;\n\nif (elementCriticalAnimation !== criticalAnimation) {\n element.remember('criticalAnimation', criticalAnimation);\n if (criticalAnimation) {\n ctx.api.cssAnimate(element, 500).attr({opacity: 0.15}).loop(0, true);\n } else {\n ctx.api.resetCssAnimation(element);\n }\n}\n\n",
"actions": {
"click": {
"actionFunction": "ctx.api.callAction(event, 'criticalClick');"
}
}
},
{
"tag": "warning",
"stateRenderFunction": "element.attr({fill: ctx.properties.warningColor});\nvar warning = ctx.values.warning && !(ctx.values.warning && ctx.values.critical)\nif (warning) {\n element.show();\n} else {\n element.hide();\n}\n\nvar elementCriticalAnimation = element.remember('criticalAnimation');\nvar criticalAnimation = warning && ctx.values.criticalAnimation;\n\nif (elementCriticalAnimation !== criticalAnimation) {\n element.remember('criticalAnimation', criticalAnimation);\n if (criticalAnimation) {\n ctx.api.cssAnimate(element, 500).attr({opacity: 0.15}).loop(0, true);\n } else {\n ctx.api.resetCssAnimation(element);\n }\n}\n",
"actions": {
"click": {
"actionFunction": "ctx.api.callAction(event, 'warningClick');"
}
}
}
],
"behavior": [
{
"id": "initialState",
"name": "{i18n:scada.symbol.on-off-state}",
"hint": "{i18n:scada.symbol.on-off-state-hint}",
"group": null,
"type": "value",
"valueType": "BOOLEAN",
"trueLabel": "{i18n:scada.symbol.on}",
"falseLabel": "{i18n:scada.symbol.off}",
"stateLabel": "",
"defaultGetValueSettings": {
"action": "GET_ATTRIBUTE",
"defaultValue": false,
"executeRpc": {
"method": "getState",
"requestTimeout": 5000,
"requestPersistent": false,
"persistentPollingInterval": 1000
},
"getAttribute": {
"scope": "SHARED_SCOPE",
"key": "state"
},
"getTimeSeries": {
"key": "state"
},
"getAlarmStatus": {
"severityList": null,
"typeList": null
},
"dataToValue": {
"type": "NONE",
"dataToValueFunction": "/* Should return boolean value */\nreturn data;",
"compareToValue": true
}
},
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": null
},
{
"id": "onUpdateState",
"name": "{i18n:scada.symbol.on-update-state}",
"hint": "{i18n:scada.symbol.on-update-state-hint}",
"group": null,
"type": "action",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": null,
"defaultGetValueSettings": null,
"defaultSetValueSettings": {
"action": "EXECUTE_RPC",
"executeRpc": {
"method": "setState",
"requestTimeout": 5000,
"requestPersistent": false,
"persistentPollingInterval": 1000
},
"setAttribute": {
"scope": "SERVER_SCOPE",
"key": "state"
},
"putTimeSeries": {
"key": "state"
},
"valueToData": {
"type": "CONSTANT",
"constantValue": true,
"valueToDataFunction": "/* Convert input boolean value to RPC parameters or attribute/time-series value */\nreturn value;"
}
},
"defaultWidgetActionSettings": null
},
{
"id": "offUpdateState",
"name": "{i18n:scada.symbol.off-update-state}",
"hint": "{i18n:scada.symbol.off-update-state-hint}",
"group": null,
"type": "action",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": null,
"defaultGetValueSettings": null,
"defaultSetValueSettings": {
"action": "EXECUTE_RPC",
"executeRpc": {
"method": "setState",
"requestTimeout": 5000,
"requestPersistent": false,
"persistentPollingInterval": 1000
},
"setAttribute": {
"key": "state",
"scope": "SERVER_SCOPE"
},
"putTimeSeries": {
"key": "state"
},
"valueToData": {
"type": "CONSTANT",
"constantValue": false,
"valueToDataFunction": "/* Convert input boolean value to RPC parameters or attribute/time-series value */\nreturn value;"
}
},
"defaultWidgetActionSettings": null
},
{
"id": "warning",
"name": "{i18n:scada.symbol.warning}",
"hint": "{i18n:scada.symbol.warning-state-hint}",
"group": "{i18n:scada.symbol.warning-state}",
"type": "value",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": "{i18n:scada.symbol.warning}",
"defaultGetValueSettings": {
"action": "GET_ALARM_STATUS",
"defaultValue": false,
"executeRpc": {
"method": "getState",
"requestTimeout": 5000,
"requestPersistent": false,
"persistentPollingInterval": 1000
},
"getAttribute": {
"scope": null,
"key": "state"
},
"getTimeSeries": {
"key": "state"
},
"getAlarmStatus": {
"severityList": [
"MAJOR",
"MINOR",
"WARNING",
"INDETERMINATE"
],
"typeList": null
},
"dataToValue": {
"type": "NONE",
"dataToValueFunction": "/* Should return boolean value */\nreturn data;",
"compareToValue": true
}
},
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": null
},
{
"id": "warningClick",
"name": "{i18n:scada.symbol.warning-click}",
"hint": "{i18n:scada.symbol.on-click-hint}",
"group": "{i18n:scada.symbol.warning-state}",
"type": "widgetAction",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": null,
"defaultGetValueSettings": null,
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": {
"type": "doNothing",
"targetDashboardStateId": null,
"openRightLayout": false,
"setEntityId": false,
"stateEntityParamName": null
}
},
{
"id": "critical",
"name": "{i18n:scada.symbol.critical}",
"hint": "{i18n:scada.symbol.critical-state-hint}",
"group": "{i18n:scada.symbol.critical-state}",
"type": "value",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": "{i18n:scada.symbol.critical}",
"defaultGetValueSettings": {
"action": "GET_ALARM_STATUS",
"defaultValue": false,
"executeRpc": {
"method": "getState",
"requestTimeout": 5000,
"requestPersistent": false,
"persistentPollingInterval": 1000
},
"getAttribute": {
"scope": null,
"key": "state"
},
"getTimeSeries": {
"key": "state"
},
"getAlarmStatus": {
"severityList": [
"CRITICAL"
],
"typeList": null
},
"dataToValue": {
"type": "NONE",
"dataToValueFunction": "/* Should return boolean value */\nreturn data;",
"compareToValue": true
}
},
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": null
},
{
"id": "criticalClick",
"name": "{i18n:scada.symbol.critical-click}",
"hint": "{i18n:scada.symbol.on-click-hint}",
"group": "{i18n:scada.symbol.critical-state}",
"type": "widgetAction",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": null,
"defaultGetValueSettings": null,
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": {
"type": "doNothing",
"targetDashboardStateId": null,
"openRightLayout": false,
"setEntityId": false,
"stateEntityParamName": null
}
},
{
"id": "criticalAnimation",
"name": "{i18n:scada.symbol.warning-critical-state-animation}",
"hint": "{i18n:scada.symbol.warning-critical-state-animation-hint}",
"group": null,
"type": "value",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": "{i18n:scada.symbol.animation}",
"defaultGetValueSettings": {
"action": "DO_NOTHING",
"defaultValue": false,
"executeRpc": {
"method": "getState",
"requestTimeout": 5000,
"requestPersistent": false,
"persistentPollingInterval": 1000
},
"getAttribute": {
"key": "state",
"scope": null
},
"getTimeSeries": {
"key": "state"
},
"dataToValue": {
"type": "NONE",
"compareToValue": true,
"dataToValueFunction": "/* Should return boolean value */\nreturn data;"
}
},
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": null
}
],
"properties": [
{
"id": "backgroundColor",
"name": "{i18n:scada.symbol.background-color}",
"type": "color",
"default": "#FFFFFF",
"disabled": false,
"visible": true
},
{
"id": "enabledColor",
"name": "{i18n:scada.symbol.colors}",
"type": "color",
"default": "#FFFFFF",
"subLabel": "{i18n:scada.symbol.enabled}",
"divider": true,
"disabled": false,
"visible": true
},
{
"id": "disabledColor",
"name": "{i18n:scada.symbol.colors}",
"type": "color",
"default": "#666666",
"subLabel": "{i18n:scada.symbol.disabled}",
"disabled": false,
"visible": true
},
{
"id": "warningColor",
"name": "{i18n:scada.symbol.alarm-colors}",
"type": "color",
"default": "#FAA405",
"subLabel": "{i18n:scada.symbol.warning}",
"divider": true,
"disabled": false,
"visible": true
},
{
"id": "criticalColor",
"name": "{i18n:scada.symbol.alarm-colors}",
"type": "color",
"default": "#D12730",
"subLabel": "{i18n:scada.symbol.critical}",
"disabled": false,
"visible": true
}
]
}]]></tb:metadata>
<rect x="1" y="1" width="198" height="198" fill="#fff" stroke="#1A1A1A" stroke-width="2" tb:tag="background"/><path d="m26 29c0-1.6569 1.3431-3 3-3h142c1.657 0 3 1.3431 3 3v142c0 1.657-1.343 3-3 3h-142c-1.6569 0-3-1.343-3-3v-142z" fill="#fff" stroke="#1A1A1A" stroke-width="2" tb:tag="button"/><g fill="#d12730" style="display: none;" tb:tag="critical">
<rect width="84" height="84" rx="4" fill="#fff" style=""/>
<rect width="84" height="84" rx="4" style=""/>
<rect x="2" y="2" width="80" height="80" rx="2" stroke="#000" stroke-opacity=".87" stroke-width="4" style=""/>
<path d="m44.559 27.562-0.4688 20.059h-4.0234l-0.4883-20.059zm-5.1172 26.211c0-0.7161 0.2344-1.3151 0.7031-1.7968 0.4818-0.4948 1.1459-0.7422 1.9922-0.7422 0.8334 0 1.4909 0.2474 1.9727 0.7422 0.4817 0.4817 0.7226 1.0807 0.7226 1.7968 0 0.6901-0.2409 1.2826-0.7226 1.7774-0.4818 0.4818-1.1393 0.7226-1.9727 0.7226-0.8463 0-1.5104-0.2408-1.9922-0.7226-0.4687-0.4948-0.7031-1.0873-0.7031-1.7774z" fill="#000" fill-opacity=".87" style=""/>
</g><g fill="#faa405" style="display: none;" tb:tag="warning">
<path d="m35.955 2.2112c1.4741-2.9482 5.6813-2.9482 7.1554 0l35.528 71.056c1.3298 2.6596-0.6042 5.7889-3.5777 5.7889h-71.056c-2.9735 0-4.9075-3.1292-3.5777-5.7889z" fill="#fff" style=""/>
<path d="m35.955 2.2112c1.4741-2.9482 5.6813-2.9482 7.1554 0l35.528 71.056c1.3298 2.6596-0.6042 5.7889-3.5777 5.7889h-71.056c-2.9735 0-4.9075-3.1292-3.5777-5.7889z" style=""/>
<path d="m37.72 3.1061c0.7371-1.4741 2.8407-1.4741 3.5778-1e-5l35.528 71.056c0.6649 1.3298-0.3021 2.8944-1.7888 2.8944h-71.056c-1.4868 0-2.4538-1.5646-1.7889-2.8944z" stroke="#000" stroke-opacity=".87" stroke-width="4" style=""/>
<path d="m42.092 32.618-0.4688 20.059h-4.0234l-0.4883-20.059zm-5.1172 26.211c0-0.7161 0.2344-1.3151 0.7031-1.7968 0.4818-0.4948 1.1459-0.7422 1.9922-0.7422 0.8334 0 1.4909 0.2474 1.9727 0.7422 0.4817 0.4817 0.7226 1.0807 0.7226 1.7968 0 0.6901-0.2409 1.2826-0.7226 1.7774-0.4818 0.4818-1.1393 0.7226-1.9727 0.7226-0.8463 0-1.5104-0.2408-1.9922-0.7226-0.4687-0.4948-0.7031-1.0873-0.7031-1.7774z" fill="#000" fill-opacity=".87" style=""/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 14 KiB

359
application/src/main/data/json/system/scada_symbols/small-power-transformer-hp.svg

@ -0,0 +1,359 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:tb="https://thingsboard.io/svg" width="400" height="400" fill="none" version="1.1" viewBox="0 0 400 400"><tb:metadata xmlns=""><![CDATA[{
"title": "HP Small power transformer",
"description": "Small power transformer with various states.",
"searchTags": [
"power",
"energy"
],
"widgetSizeX": 2,
"widgetSizeY": 2,
"tags": [
{
"tag": "background",
"stateRenderFunction": "var color = ctx.properties.stoppedColor;\nif (ctx.values.running) {\n color = ctx.properties.runningColor;\n}\nelement.attr({fill: color});",
"actions": null
},
{
"tag": "clickArea",
"stateRenderFunction": null,
"actions": {
"click": {
"actionFunction": "ctx.api.callAction(event, 'click');"
}
}
},
{
"tag": "critical",
"stateRenderFunction": "element.attr({fill: ctx.properties.criticalColor});\nif (ctx.values.critical) {\n element.show();\n} else {\n element.hide();\n}\n\nvar elementCriticalAnimation = element.remember('criticalAnimation');\nvar criticalAnimation = ctx.values.critical && ctx.values.criticalAnimation;\n\nif (elementCriticalAnimation !== criticalAnimation) {\n element.remember('criticalAnimation', criticalAnimation);\n if (criticalAnimation) {\n ctx.api.cssAnimate(element, 500).attr({opacity: 0.15}).loop(0, true);\n } else {\n ctx.api.resetCssAnimation(element);\n }\n}\n\n",
"actions": {
"click": {
"actionFunction": "ctx.api.callAction(event, 'criticalClick');"
}
}
},
{
"tag": "warning",
"stateRenderFunction": "element.attr({fill: ctx.properties.warningColor});\nvar warning = ctx.values.warning && !(ctx.values.warning && ctx.values.critical)\nif (warning) {\n element.show();\n} else {\n element.hide();\n}\n\nvar elementCriticalAnimation = element.remember('criticalAnimation');\nvar criticalAnimation = warning && ctx.values.criticalAnimation;\n\nif (elementCriticalAnimation !== criticalAnimation) {\n element.remember('criticalAnimation', criticalAnimation);\n if (criticalAnimation) {\n ctx.api.cssAnimate(element, 500).attr({opacity: 0.15}).loop(0, true);\n } else {\n ctx.api.resetCssAnimation(element);\n }\n}\n",
"actions": {
"click": {
"actionFunction": "ctx.api.callAction(event, 'warningClick');"
}
}
}
],
"behavior": [
{
"id": "running",
"name": "{i18n:scada.symbol.running}",
"hint": "{i18n:scada.symbol.running-hint}",
"group": null,
"type": "value",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": "{i18n:scada.symbol.running}",
"defaultGetValueSettings": {
"action": "GET_ATTRIBUTE",
"defaultValue": false,
"executeRpc": {
"method": "getState",
"requestTimeout": 5000,
"requestPersistent": false,
"persistentPollingInterval": 1000
},
"getAttribute": {
"scope": "SHARED_SCOPE",
"key": "running"
},
"getTimeSeries": {
"key": "state"
},
"getAlarmStatus": {
"severityList": null,
"typeList": null
},
"dataToValue": {
"type": "NONE",
"dataToValueFunction": "/* Should return boolean value */\nreturn data;",
"compareToValue": true
}
},
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": null
},
{
"id": "warning",
"name": "{i18n:scada.symbol.warning}",
"hint": "{i18n:scada.symbol.warning-state-hint}",
"group": "{i18n:scada.symbol.warning-state}",
"type": "value",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": "{i18n:scada.symbol.warning}",
"defaultGetValueSettings": {
"action": "GET_ALARM_STATUS",
"defaultValue": false,
"executeRpc": {
"method": "getState",
"requestTimeout": 5000,
"requestPersistent": false,
"persistentPollingInterval": 1000
},
"getAttribute": {
"scope": null,
"key": "state"
},
"getTimeSeries": {
"key": "state"
},
"getAlarmStatus": {
"severityList": [
"MAJOR",
"MINOR",
"WARNING",
"INDETERMINATE"
],
"typeList": null
},
"dataToValue": {
"type": "NONE",
"dataToValueFunction": "/* Should return boolean value */\nreturn data;",
"compareToValue": true
}
},
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": null
},
{
"id": "warningClick",
"name": "{i18n:scada.symbol.warning-click}",
"hint": "{i18n:scada.symbol.on-click-hint}",
"group": "{i18n:scada.symbol.warning-state}",
"type": "widgetAction",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": null,
"defaultGetValueSettings": null,
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": {
"type": "doNothing",
"targetDashboardStateId": null,
"openRightLayout": false,
"setEntityId": false,
"stateEntityParamName": null
}
},
{
"id": "critical",
"name": "{i18n:scada.symbol.critical}",
"hint": "{i18n:scada.symbol.critical-state-hint}",
"group": "{i18n:scada.symbol.critical-state}",
"type": "value",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": "{i18n:scada.symbol.critical}",
"defaultGetValueSettings": {
"action": "GET_ALARM_STATUS",
"defaultValue": false,
"executeRpc": {
"method": "getState",
"requestTimeout": 5000,
"requestPersistent": false,
"persistentPollingInterval": 1000
},
"getAttribute": {
"scope": null,
"key": "state"
},
"getTimeSeries": {
"key": "state"
},
"getAlarmStatus": {
"severityList": [
"CRITICAL"
],
"typeList": null
},
"dataToValue": {
"type": "NONE",
"dataToValueFunction": "/* Should return boolean value */\nreturn data;",
"compareToValue": true
}
},
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": null
},
{
"id": "criticalClick",
"name": "{i18n:scada.symbol.critical-click}",
"hint": "{i18n:scada.symbol.on-click-hint}",
"group": "{i18n:scada.symbol.critical-state}",
"type": "widgetAction",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": null,
"defaultGetValueSettings": null,
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": {
"type": "doNothing",
"targetDashboardStateId": null,
"openRightLayout": false,
"setEntityId": false,
"stateEntityParamName": null
}
},
{
"id": "criticalAnimation",
"name": "{i18n:scada.symbol.warning-critical-state-animation}",
"hint": "{i18n:scada.symbol.warning-critical-state-animation-hint}",
"group": null,
"type": "value",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": "{i18n:scada.symbol.animation}",
"defaultGetValueSettings": {
"action": "DO_NOTHING",
"defaultValue": false,
"executeRpc": {
"method": "getState",
"requestTimeout": 5000,
"requestPersistent": false,
"persistentPollingInterval": 1000
},
"getAttribute": {
"key": "state",
"scope": null
},
"getTimeSeries": {
"key": "state"
},
"dataToValue": {
"type": "NONE",
"compareToValue": true,
"dataToValueFunction": "/* Should return boolean value */\nreturn data;"
}
},
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": null
},
{
"id": "click",
"name": "{i18n:scada.symbol.on-click}",
"hint": "{i18n:scada.symbol.on-click-hint}",
"group": null,
"type": "widgetAction",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": null,
"defaultGetValueSettings": null,
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": {
"type": "doNothing",
"targetDashboardStateId": null,
"openRightLayout": false,
"setEntityId": false,
"stateEntityParamName": null
}
}
],
"properties": [
{
"id": "runningColor",
"name": "{i18n:scada.symbol.colors}",
"type": "color",
"default": "#FFFFFF",
"required": null,
"subLabel": "{i18n:scada.symbol.running}",
"divider": true,
"fieldSuffix": null,
"disableOnProperty": null,
"rowClass": "",
"fieldClass": "",
"min": null,
"max": null,
"step": null
},
{
"id": "stoppedColor",
"name": "{i18n:scada.symbol.colors}",
"type": "color",
"default": "#666666",
"required": null,
"subLabel": "{i18n:scada.symbol.stopped}",
"divider": null,
"fieldSuffix": null,
"disableOnProperty": null,
"rowClass": "",
"fieldClass": "",
"min": null,
"max": null,
"step": null
},
{
"id": "warningColor",
"name": "{i18n:scada.symbol.alarm-colors}",
"type": "color",
"default": "#FAA405",
"required": null,
"subLabel": "{i18n:scada.symbol.warning}",
"divider": true,
"fieldSuffix": null,
"disableOnProperty": null,
"rowClass": "",
"fieldClass": "",
"min": null,
"max": null,
"step": null
},
{
"id": "criticalColor",
"name": "{i18n:scada.symbol.alarm-colors}",
"type": "color",
"default": "#D12730",
"required": null,
"subLabel": "{i18n:scada.symbol.critical}",
"divider": null,
"fieldSuffix": null,
"disableOnProperty": null,
"rowClass": "",
"fieldClass": "",
"min": null,
"max": null,
"step": null
}
]
}]]></tb:metadata>
<g fill="#fff" stroke="#1A1A1A" stroke-width="2" tb:tag="background">
<path d="m67 35.406c0-3.4797 1.5105-6.788 4.1398-9.0673l5.4938-4.7625c5.6366-4.8862 12.846-7.576 20.306-7.576h6.1218c7.459 0 14.669 2.6899 20.305 7.576l5.494 4.7625c2.63 2.2793 4.14 5.5876 4.14 9.0673v2.3965c0 5.0878-3.208 9.6226-8.006 11.316l-2.189 0.7724c-3.955 1.3961-8.119 2.1094-12.314 2.1094h-20.982c-4.1947 0-8.3588-0.7133-12.314-2.1094l-2.1886-0.7724c-4.7978-1.6933-8.0062-6.2281-8.0062-11.316v-2.3965z"/>
<path d="m67 73.406c0-3.4797 1.5105-6.788 4.1398-9.0673l5.4938-4.7625c5.6366-4.8862 12.846-7.576 20.306-7.576h6.1218c7.459 0 14.669 2.6899 20.305 7.576l5.494 4.7625c2.63 2.2793 4.14 5.5876 4.14 9.0673v2.3965c0 5.0878-3.208 9.6226-8.006 11.316l-2.189 0.7724c-3.955 1.3961-8.119 2.1094-12.314 2.1094h-20.982c-4.1947 0-8.3588-0.7133-12.314-2.1094l-2.1886-0.7724c-4.7978-1.6933-8.0062-6.2281-8.0062-11.316v-2.3965z"/>
<path d="m67 111.41c0-3.48 1.5105-6.788 4.1398-9.068l5.4938-4.762c5.6366-4.8862 12.846-7.576 20.306-7.576h6.1218c7.459 0 14.669 2.6899 20.305 7.576l5.494 4.762c2.63 2.28 4.14 5.588 4.14 9.068v2.396c0 5.088-3.208 9.623-8.006 11.316l-2.189 0.773c-3.955 1.396-8.119 2.109-12.314 2.109h-20.982c-4.1947 0-8.3588-0.713-12.314-2.109l-2.1886-0.773c-4.7978-1.693-8.0062-6.228-8.0062-11.316v-2.396z"/>
<rect x="85" y="128" width="30" height="11" rx="1"/>
<path d="m267 35.406c0-3.4797 1.51-6.788 4.14-9.0673l5.494-4.7625c5.636-4.8862 12.846-7.576 20.305-7.576h6.122c7.459 0 14.669 2.6899 20.305 7.576l5.494 4.7625c2.63 2.2793 4.14 5.5876 4.14 9.0673v2.3965c0 5.0878-3.208 9.6226-8.006 11.316l-2.189 0.7724c-3.955 1.3961-8.119 2.1094-12.314 2.1094h-20.982c-4.195 0-8.359-0.7133-12.314-2.1094l-2.189-0.7724c-4.798-1.6933-8.006-6.2281-8.006-11.316v-2.3965z"/>
<path d="m267 73.406c0-3.4797 1.51-6.788 4.14-9.0673l5.494-4.7625c5.636-4.8862 12.846-7.576 20.305-7.576h6.122c7.459 0 14.669 2.6899 20.305 7.576l5.494 4.7625c2.63 2.2793 4.14 5.5876 4.14 9.0673v2.3965c0 5.0878-3.208 9.6226-8.006 11.316l-2.189 0.7724c-3.955 1.3961-8.119 2.1094-12.314 2.1094h-20.982c-4.195 0-8.359-0.7133-12.314-2.1094l-2.189-0.7724c-4.798-1.6933-8.006-6.2281-8.006-11.316v-2.3965z"/>
<path d="m267 111.41c0-3.48 1.51-6.788 4.14-9.068l5.494-4.762c5.636-4.8862 12.846-7.576 20.305-7.576h6.122c7.459 0 14.669 2.6899 20.305 7.576l5.494 4.762c2.63 2.28 4.14 5.588 4.14 9.068v2.396c0 5.088-3.208 9.623-8.006 11.316l-2.189 0.773c-3.955 1.396-8.119 2.109-12.314 2.109h-20.982c-4.195 0-8.359-0.713-12.314-2.109l-2.189-0.773c-4.798-1.693-8.006-6.228-8.006-11.316v-2.396z"/>
<rect x="285" y="128" width="30" height="11" rx="1"/>
<path d="m167 35.406c0-3.4797 1.51-6.788 4.14-9.0673l5.494-4.7625c5.636-4.8862 12.846-7.576 20.305-7.576h6.122c7.459 0 14.669 2.6899 20.305 7.576l5.494 4.7625c2.63 2.2793 4.14 5.5876 4.14 9.0673v2.3965c0 5.0878-3.208 9.6226-8.006 11.316l-2.189 0.7724c-3.955 1.3961-8.119 2.1094-12.314 2.1094h-20.982c-4.195 0-8.359-0.7133-12.314-2.1094l-2.189-0.7724c-4.798-1.6933-8.006-6.2281-8.006-11.316v-2.3965z"/>
<path d="m167 73.406c0-3.4797 1.51-6.788 4.14-9.0673l5.494-4.7625c5.636-4.8862 12.846-7.576 20.305-7.576h6.122c7.459 0 14.669 2.6899 20.305 7.576l5.494 4.7625c2.63 2.2793 4.14 5.5876 4.14 9.0673v2.3965c0 5.0878-3.208 9.6226-8.006 11.316l-2.189 0.7724c-3.955 1.3961-8.119 2.1094-12.314 2.1094h-20.982c-4.195 0-8.359-0.7133-12.314-2.1094l-2.189-0.7724c-4.798-1.6933-8.006-6.2281-8.006-11.316v-2.3965z"/>
<path d="m167 111.41c0-3.48 1.51-6.788 4.14-9.068l5.494-4.762c5.636-4.8862 12.846-7.576 20.305-7.576h6.122c7.459 0 14.669 2.6899 20.305 7.576l5.494 4.762c2.63 2.28 4.14 5.588 4.14 9.068v2.396c0 5.088-3.208 9.623-8.006 11.316l-2.189 0.773c-3.955 1.396-8.119 2.109-12.314 2.109h-20.982c-4.195 0-8.359-0.713-12.314-2.109l-2.189-0.773c-4.798-1.693-8.006-6.228-8.006-11.316v-2.396z"/>
<rect x="185" y="128" width="30" height="11" rx="1"/>
<rect x="17" y="160" width="366" height="217" rx="5"/>
<rect x="1" y="138" width="398" height="22" rx="5"/>
<rect x="1" y="377" width="398" height="22" rx="5"/>
</g><path d="m204.37 266.34-16.841 15.085c-1.041 0.943-0.455 2.682 0.943 2.812l13.151 1.268-7.884 10.989c-0.358 0.504-0.309 1.203 0.13 1.642 0.487 0.488 1.251 0.504 1.755 0.033l16.841-15.086c1.041-0.943 0.455-2.682-0.943-2.812l-13.151-1.268 7.885-10.989c0.357-0.504 0.308-1.203-0.131-1.642-0.487-0.488-1.251-0.504-1.755-0.032z" fill="#1A1A1A"/><path d="m150.82 313.75c-1.541 0-2.503-1.669-1.731-3.002l49.176-84.942c0.771-1.33 2.692-1.33 3.462 0l49.177 84.942c0.772 1.333-0.19 3.002-1.731 3.002h-98.353z" stroke="#1A1A1A" stroke-width="8"/><rect x="90" width="20" height="15" rx="2" fill="#1A1A1A"/><rect x="290" width="20" height="15" rx="2" fill="#1A1A1A"/><rect x="190" width="20" height="15" rx="2" fill="#1A1A1A"/><path d="m134.53 0s-134.53 0-134.53 67v328.36c0 2.6512 3.5818 4.6403 8 4.6403h384c4.418 0 8-1.9892 8-4.6403v-328.36c0-67-132.14-67-132.14-67h-67.86zm134.14 81.2c-2.5774 0-4.6666 1.2536-4.6666 2.8v300.4c0 1.5464 2.0894 2.8 4.6666 2.8h29.332c2.5774 0 4.6666-1.2536 4.6666-2.8v-300.4c0-1.5464-2.0894-2.8-4.6666-2.8z" fill="#000" fill-opacity="0" tb:tag="clickArea"/><g transform="translate(0,316)" fill="#d12730" style="display: none;" tb:tag="critical">
<rect width="84" height="84" rx="4" fill="#fff" style=""/>
<rect width="84" height="84" rx="4" style=""/>
<rect x="2" y="2" width="80" height="80" rx="2" stroke="#000" stroke-opacity=".87" stroke-width="4" style=""/>
<path d="m44.559 27.562-0.4688 20.059h-4.0234l-0.4883-20.059zm-5.1172 26.211c0-0.7161 0.2344-1.3151 0.7031-1.7968 0.4818-0.4948 1.1459-0.7422 1.9922-0.7422 0.8334 0 1.4909 0.2474 1.9727 0.7422 0.4817 0.4817 0.7226 1.0807 0.7226 1.7968 0 0.6901-0.2409 1.2826-0.7226 1.7774-0.4818 0.4818-1.1393 0.7226-1.9727 0.7226-0.8463 0-1.5104-0.2408-1.9922-0.7226-0.4687-0.4948-0.7031-1.0873-0.7031-1.7774z" fill="#000" fill-opacity=".87" style=""/>
</g><g transform="translate(0 320.94)" fill="#faa405" style="display: none;" tb:tag="warning">
<path d="m35.955 2.2112c1.4741-2.9482 5.6813-2.9482 7.1554 0l35.528 71.056c1.3298 2.6596-0.6042 5.7889-3.5777 5.7889h-71.056c-2.9735 0-4.9075-3.1292-3.5777-5.7889z" fill="#fff" style=""/>
<path d="m35.955 2.2112c1.4741-2.9482 5.6813-2.9482 7.1554 0l35.528 71.056c1.3298 2.6596-0.6042 5.7889-3.5777 5.7889h-71.056c-2.9735 0-4.9075-3.1292-3.5777-5.7889z" style=""/>
<path d="m37.72 3.1061c0.7371-1.4741 2.8407-1.4741 3.5778-1e-5l35.528 71.056c0.6649 1.3298-0.3021 2.8944-1.7888 2.8944h-71.056c-1.4868 0-2.4538-1.5646-1.7889-2.8944z" stroke="#000" stroke-opacity=".87" stroke-width="4" style=""/>
<path d="m42.092 32.618-0.4688 20.059h-4.0234l-0.4883-20.059zm-5.1172 26.211c0-0.7161 0.2344-1.3151 0.7031-1.7968 0.4818-0.4948 1.1459-0.7422 1.9922-0.7422 0.8334 0 1.4909 0.2474 1.9727 0.7422 0.4817 0.4817 0.7226 1.0807 0.7226 1.7968 0 0.6901-0.2409 1.2826-0.7226 1.7774-0.4818 0.4818-1.1393 0.7226-1.9727 0.7226-0.8463 0-1.5104-0.2408-1.9922-0.7226-0.4687-0.4948-0.7031-1.0873-0.7031-1.7774z" fill="#000" fill-opacity=".87" style=""/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 17 KiB

353
application/src/main/data/json/system/scada_symbols/solar-panel-hp.svg

@ -0,0 +1,353 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:tb="https://thingsboard.io/svg" width="200" height="400" fill="none" version="1.1" viewBox="0 0 200 400"><tb:metadata xmlns=""><![CDATA[{
"title": "HP Solar panel",
"description": "Solar panel with various states.",
"searchTags": [
"energy",
"power",
"renewable",
"generation"
],
"widgetSizeX": 1,
"widgetSizeY": 2,
"tags": [
{
"tag": "background",
"stateRenderFunction": "var color = ctx.properties.stoppedColor;\nif (ctx.values.running) {\n color = ctx.properties.runningColor;\n}\nelement.attr({fill: color});",
"actions": null
},
{
"tag": "clickArea",
"stateRenderFunction": null,
"actions": {
"click": {
"actionFunction": "ctx.api.callAction(event, 'click');"
}
}
},
{
"tag": "critical",
"stateRenderFunction": "element.attr({fill: ctx.properties.criticalColor});\nif (ctx.values.critical) {\n element.show();\n} else {\n element.hide();\n}\n\nvar elementCriticalAnimation = element.remember('criticalAnimation');\nvar criticalAnimation = ctx.values.critical && ctx.values.criticalAnimation;\n\nif (elementCriticalAnimation !== criticalAnimation) {\n element.remember('criticalAnimation', criticalAnimation);\n if (criticalAnimation) {\n ctx.api.cssAnimate(element, 500).attr({opacity: 0.15}).loop(0, true);\n } else {\n ctx.api.resetCssAnimation(element);\n }\n}\n\n",
"actions": {
"click": {
"actionFunction": "ctx.api.callAction(event, 'criticalClick');"
}
}
},
{
"tag": "warning",
"stateRenderFunction": "element.attr({fill: ctx.properties.warningColor});\nvar warning = ctx.values.warning && !(ctx.values.warning && ctx.values.critical)\nif (warning) {\n element.show();\n} else {\n element.hide();\n}\n\nvar elementCriticalAnimation = element.remember('criticalAnimation');\nvar criticalAnimation = warning && ctx.values.criticalAnimation;\n\nif (elementCriticalAnimation !== criticalAnimation) {\n element.remember('criticalAnimation', criticalAnimation);\n if (criticalAnimation) {\n ctx.api.cssAnimate(element, 500).attr({opacity: 0.15}).loop(0, true);\n } else {\n ctx.api.resetCssAnimation(element);\n }\n}\n",
"actions": {
"click": {
"actionFunction": "ctx.api.callAction(event, 'warningClick');"
}
}
}
],
"behavior": [
{
"id": "running",
"name": "{i18n:scada.symbol.running}",
"hint": "{i18n:scada.symbol.running-hint}",
"group": null,
"type": "value",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": "{i18n:scada.symbol.running}",
"defaultGetValueSettings": {
"action": "GET_ATTRIBUTE",
"defaultValue": false,
"executeRpc": {
"method": "getState",
"requestTimeout": 5000,
"requestPersistent": false,
"persistentPollingInterval": 1000
},
"getAttribute": {
"scope": "SHARED_SCOPE",
"key": "running"
},
"getTimeSeries": {
"key": "state"
},
"getAlarmStatus": {
"severityList": null,
"typeList": null
},
"dataToValue": {
"type": "NONE",
"dataToValueFunction": "/* Should return boolean value */\nreturn data;",
"compareToValue": true
}
},
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": null
},
{
"id": "warning",
"name": "{i18n:scada.symbol.warning}",
"hint": "{i18n:scada.symbol.warning-state-hint}",
"group": "{i18n:scada.symbol.warning-state}",
"type": "value",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": "{i18n:scada.symbol.warning}",
"defaultGetValueSettings": {
"action": "GET_ALARM_STATUS",
"defaultValue": false,
"executeRpc": {
"method": "getState",
"requestTimeout": 5000,
"requestPersistent": false,
"persistentPollingInterval": 1000
},
"getAttribute": {
"scope": null,
"key": "state"
},
"getTimeSeries": {
"key": "state"
},
"getAlarmStatus": {
"severityList": [
"MAJOR",
"MINOR",
"WARNING",
"INDETERMINATE"
],
"typeList": null
},
"dataToValue": {
"type": "NONE",
"dataToValueFunction": "/* Should return boolean value */\nreturn data;",
"compareToValue": true
}
},
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": null
},
{
"id": "warningClick",
"name": "{i18n:scada.symbol.warning-click}",
"hint": "{i18n:scada.symbol.on-click-hint}",
"group": "{i18n:scada.symbol.warning-state}",
"type": "widgetAction",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": null,
"defaultGetValueSettings": null,
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": {
"type": "doNothing",
"targetDashboardStateId": null,
"openRightLayout": false,
"setEntityId": false,
"stateEntityParamName": null
}
},
{
"id": "critical",
"name": "{i18n:scada.symbol.critical}",
"hint": "{i18n:scada.symbol.critical-state-hint}",
"group": "{i18n:scada.symbol.critical-state}",
"type": "value",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": "{i18n:scada.symbol.critical}",
"defaultGetValueSettings": {
"action": "GET_ALARM_STATUS",
"defaultValue": false,
"executeRpc": {
"method": "getState",
"requestTimeout": 5000,
"requestPersistent": false,
"persistentPollingInterval": 1000
},
"getAttribute": {
"scope": null,
"key": "state"
},
"getTimeSeries": {
"key": "state"
},
"getAlarmStatus": {
"severityList": [
"CRITICAL"
],
"typeList": null
},
"dataToValue": {
"type": "NONE",
"dataToValueFunction": "/* Should return boolean value */\nreturn data;",
"compareToValue": true
}
},
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": null
},
{
"id": "criticalClick",
"name": "{i18n:scada.symbol.critical-click}",
"hint": "{i18n:scada.symbol.on-click-hint}",
"group": "{i18n:scada.symbol.critical-state}",
"type": "widgetAction",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": null,
"defaultGetValueSettings": null,
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": {
"type": "doNothing",
"targetDashboardStateId": null,
"openRightLayout": false,
"setEntityId": false,
"stateEntityParamName": null
}
},
{
"id": "criticalAnimation",
"name": "{i18n:scada.symbol.warning-critical-state-animation}",
"hint": "{i18n:scada.symbol.warning-critical-state-animation-hint}",
"group": null,
"type": "value",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": "{i18n:scada.symbol.animation}",
"defaultGetValueSettings": {
"action": "DO_NOTHING",
"defaultValue": false,
"executeRpc": {
"method": "getState",
"requestTimeout": 5000,
"requestPersistent": false,
"persistentPollingInterval": 1000
},
"getAttribute": {
"key": "state",
"scope": null
},
"getTimeSeries": {
"key": "state"
},
"dataToValue": {
"type": "NONE",
"compareToValue": true,
"dataToValueFunction": "/* Should return boolean value */\nreturn data;"
}
},
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": null
},
{
"id": "click",
"name": "{i18n:scada.symbol.on-click}",
"hint": "{i18n:scada.symbol.on-click-hint}",
"group": null,
"type": "widgetAction",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": null,
"defaultGetValueSettings": null,
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": {
"type": "doNothing",
"targetDashboardStateId": null,
"openRightLayout": false,
"setEntityId": false,
"stateEntityParamName": null
}
}
],
"properties": [
{
"id": "runningColor",
"name": "{i18n:scada.symbol.colors}",
"type": "color",
"default": "#FFFFFF",
"required": null,
"subLabel": "{i18n:scada.symbol.running}",
"divider": true,
"fieldSuffix": null,
"disableOnProperty": null,
"rowClass": "",
"fieldClass": "",
"min": null,
"max": null,
"step": null,
"disabled": false,
"visible": true
},
{
"id": "stoppedColor",
"name": "{i18n:scada.symbol.colors}",
"type": "color",
"default": "#666666",
"required": null,
"subLabel": "{i18n:scada.symbol.stopped}",
"divider": null,
"fieldSuffix": null,
"disableOnProperty": null,
"rowClass": "",
"fieldClass": "",
"min": null,
"max": null,
"step": null,
"disabled": false,
"visible": true
},
{
"id": "warningColor",
"name": "{i18n:scada.symbol.alarm-colors}",
"type": "color",
"default": "#FAA405",
"required": null,
"subLabel": "{i18n:scada.symbol.warning}",
"divider": true,
"fieldSuffix": null,
"disableOnProperty": null,
"rowClass": "",
"fieldClass": "",
"min": null,
"max": null,
"step": null,
"disabled": false,
"visible": true
},
{
"id": "criticalColor",
"name": "{i18n:scada.symbol.alarm-colors}",
"type": "color",
"default": "#D12730",
"required": null,
"subLabel": "{i18n:scada.symbol.critical}",
"divider": null,
"fieldSuffix": null,
"disableOnProperty": null,
"rowClass": "",
"fieldClass": "",
"min": null,
"max": null,
"step": null,
"disabled": false,
"visible": true
}
]
}]]></tb:metadata>
<path d="M21 1H199V359H21V1Z" fill="#fff" stroke="#1A1A1A" stroke-width="2" tb:tag="background"/><path d="m65 0v40" stroke="#1A1A1A" stroke-width="2"/><path d="m110 0v40" stroke="#1A1A1A" stroke-width="2"/><path d="m155 0v40" stroke="#1A1A1A" stroke-width="2"/><path d="m180 180h20" stroke="#1A1A1A" stroke-width="2"/><path d="m180 90h20" stroke="#1A1A1A" stroke-width="2"/><path d="m180 270h20" stroke="#1A1A1A" stroke-width="2"/><rect x="1" y="41" width="178" height="358" fill="#fff" stroke="#1A1A1A" stroke-width="2" tb:tag="background"/><path d="m45 40v360" stroke="#1A1A1A" stroke-width="2"/><path d="m90 40v360" stroke="#1A1A1A" stroke-width="2"/><path d="m135 40v360" stroke="#1A1A1A" stroke-width="2"/><path d="m0 220h180" stroke="#1A1A1A" stroke-width="2"/><path d="m0 130h180" stroke="#1A1A1A" stroke-width="2"/><path d="m0 310h180" stroke="#1A1A1A" stroke-width="2"/><path d="m67.265 0s-67.265 0-67.265 67v328.36c0 2.6512 1.7909 4.6404 4 4.6404h192c2.209 0 4-1.9892 4-4.6404v-328.36c0-67-66.07-67-66.07-67h-33.929zm67.07 81.2c-1.2887 0-2.3333 1.2536-2.3333 2.8v300.4c0 1.5464 1.0447 2.8 2.3333 2.8h14.666c1.2887 0 2.3333-1.2536 2.3333-2.8v-300.4c0-1.5464-1.0447-2.8-2.3333-2.8z" fill="#000" fill-opacity="0" tb:tag="clickArea"/><g fill="#d12730" style="display: none;" tb:tag="critical">
<rect width="84" height="84" rx="4" fill="#fff" style=""/>
<rect width="84" height="84" rx="4" style=""/>
<rect x="2" y="2" width="80" height="80" rx="2" stroke="#000" stroke-opacity=".87" stroke-width="4" style=""/>
<path d="m44.559 27.562-0.4688 20.059h-4.0234l-0.4883-20.059zm-5.1172 26.211c0-0.7161 0.2344-1.3151 0.7031-1.7968 0.4818-0.4948 1.1459-0.7422 1.9922-0.7422 0.8334 0 1.4909 0.2474 1.9727 0.7422 0.4817 0.4817 0.7226 1.0807 0.7226 1.7968 0 0.6901-0.2409 1.2826-0.7226 1.7774-0.4818 0.4818-1.1393 0.7226-1.9727 0.7226-0.8463 0-1.5104-0.2408-1.9922-0.7226-0.4687-0.4948-0.7031-1.0873-0.7031-1.7774z" fill="#000" fill-opacity=".87" style=""/>
</g><g fill="#faa405" style="display: none;" tb:tag="warning">
<path d="m35.955 2.2112c1.4741-2.9482 5.6813-2.9482 7.1554 0l35.528 71.056c1.3298 2.6596-0.6042 5.7889-3.5777 5.7889h-71.056c-2.9735 0-4.9075-3.1292-3.5777-5.7889z" fill="#fff" style=""/>
<path d="m35.955 2.2112c1.4741-2.9482 5.6813-2.9482 7.1554 0l35.528 71.056c1.3298 2.6596-0.6042 5.7889-3.5777 5.7889h-71.056c-2.9735 0-4.9075-3.1292-3.5777-5.7889z" style=""/>
<path d="m37.72 3.1061c0.7371-1.4741 2.8407-1.4741 3.5778-1e-5l35.528 71.056c0.6649 1.3298-0.3021 2.8944-1.7888 2.8944h-71.056c-1.4868 0-2.4538-1.5646-1.7889-2.8944z" stroke="#000" stroke-opacity=".87" stroke-width="4" style=""/>
<path d="m42.092 32.618-0.4688 20.059h-4.0234l-0.4883-20.059zm-5.1172 26.211c0-0.7161 0.2344-1.3151 0.7031-1.7968 0.4818-0.4948 1.1459-0.7422 1.9922-0.7422 0.8334 0 1.4909 0.2474 1.9727 0.7422 0.4817 0.4817 0.7226 1.0807 0.7226 1.7968 0 0.6901-0.2409 1.2826-0.7226 1.7774-0.4818 0.4818-1.1393 0.7226-1.9727 0.7226-0.8463 0-1.5104-0.2408-1.9922-0.7226-0.4687-0.4948-0.7031-1.0873-0.7031-1.7774z" fill="#000" fill-opacity=".87" style=""/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 14 KiB

357
application/src/main/data/json/system/scada_symbols/stand-solar-panel-hp.svg

@ -0,0 +1,357 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:tb="https://thingsboard.io/svg" width="600" height="400" fill="none" version="1.1" viewBox="0 0 600 400"><tb:metadata xmlns=""><![CDATA[{
"title": "HP Stand solar panel",
"description": "Stand solar panel with various states.",
"searchTags": [
"energy",
"power",
"renewable",
"generation"
],
"widgetSizeX": 3,
"widgetSizeY": 2,
"tags": [
{
"tag": "background",
"stateRenderFunction": "var color = ctx.properties.stoppedColor;\nif (ctx.values.running) {\n color = ctx.properties.runningColor;\n}\nelement.attr({fill: color});",
"actions": null
},
{
"tag": "clickArea",
"stateRenderFunction": null,
"actions": {
"click": {
"actionFunction": "ctx.api.callAction(event, 'click');"
}
}
},
{
"tag": "critical",
"stateRenderFunction": "element.attr({fill: ctx.properties.criticalColor});\nif (ctx.values.critical) {\n element.show();\n} else {\n element.hide();\n}\n\nvar elementCriticalAnimation = element.remember('criticalAnimation');\nvar criticalAnimation = ctx.values.critical && ctx.values.criticalAnimation;\n\nif (elementCriticalAnimation !== criticalAnimation) {\n element.remember('criticalAnimation', criticalAnimation);\n if (criticalAnimation) {\n ctx.api.cssAnimate(element, 500).attr({opacity: 0.15}).loop(0, true);\n } else {\n ctx.api.resetCssAnimation(element);\n }\n}\n\n",
"actions": {
"click": {
"actionFunction": "ctx.api.callAction(event, 'criticalClick');"
}
}
},
{
"tag": "warning",
"stateRenderFunction": "element.attr({fill: ctx.properties.warningColor});\nvar warning = ctx.values.warning && !(ctx.values.warning && ctx.values.critical)\nif (warning) {\n element.show();\n} else {\n element.hide();\n}\n\nvar elementCriticalAnimation = element.remember('criticalAnimation');\nvar criticalAnimation = warning && ctx.values.criticalAnimation;\n\nif (elementCriticalAnimation !== criticalAnimation) {\n element.remember('criticalAnimation', criticalAnimation);\n if (criticalAnimation) {\n ctx.api.cssAnimate(element, 500).attr({opacity: 0.15}).loop(0, true);\n } else {\n ctx.api.resetCssAnimation(element);\n }\n}\n",
"actions": {
"click": {
"actionFunction": "ctx.api.callAction(event, 'warningClick');"
}
}
}
],
"behavior": [
{
"id": "running",
"name": "{i18n:scada.symbol.running}",
"hint": "{i18n:scada.symbol.running-hint}",
"group": null,
"type": "value",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": "{i18n:scada.symbol.running}",
"defaultGetValueSettings": {
"action": "GET_ATTRIBUTE",
"defaultValue": false,
"executeRpc": {
"method": "getState",
"requestTimeout": 5000,
"requestPersistent": false,
"persistentPollingInterval": 1000
},
"getAttribute": {
"scope": "SHARED_SCOPE",
"key": "running"
},
"getTimeSeries": {
"key": "state"
},
"getAlarmStatus": {
"severityList": null,
"typeList": null
},
"dataToValue": {
"type": "NONE",
"dataToValueFunction": "/* Should return boolean value */\nreturn data;",
"compareToValue": true
}
},
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": null
},
{
"id": "warning",
"name": "{i18n:scada.symbol.warning}",
"hint": "{i18n:scada.symbol.warning-state-hint}",
"group": "{i18n:scada.symbol.warning-state}",
"type": "value",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": "{i18n:scada.symbol.warning}",
"defaultGetValueSettings": {
"action": "GET_ALARM_STATUS",
"defaultValue": false,
"executeRpc": {
"method": "getState",
"requestTimeout": 5000,
"requestPersistent": false,
"persistentPollingInterval": 1000
},
"getAttribute": {
"scope": null,
"key": "state"
},
"getTimeSeries": {
"key": "state"
},
"getAlarmStatus": {
"severityList": [
"MAJOR",
"MINOR",
"WARNING",
"INDETERMINATE"
],
"typeList": null
},
"dataToValue": {
"type": "NONE",
"dataToValueFunction": "/* Should return boolean value */\nreturn data;",
"compareToValue": true
}
},
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": null
},
{
"id": "warningClick",
"name": "{i18n:scada.symbol.warning-click}",
"hint": "{i18n:scada.symbol.on-click-hint}",
"group": "{i18n:scada.symbol.warning-state}",
"type": "widgetAction",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": null,
"defaultGetValueSettings": null,
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": {
"type": "doNothing",
"targetDashboardStateId": null,
"openRightLayout": false,
"setEntityId": false,
"stateEntityParamName": null
}
},
{
"id": "critical",
"name": "{i18n:scada.symbol.critical}",
"hint": "{i18n:scada.symbol.critical-state-hint}",
"group": "{i18n:scada.symbol.critical-state}",
"type": "value",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": "{i18n:scada.symbol.critical}",
"defaultGetValueSettings": {
"action": "GET_ALARM_STATUS",
"defaultValue": false,
"executeRpc": {
"method": "getState",
"requestTimeout": 5000,
"requestPersistent": false,
"persistentPollingInterval": 1000
},
"getAttribute": {
"scope": null,
"key": "state"
},
"getTimeSeries": {
"key": "state"
},
"getAlarmStatus": {
"severityList": [
"CRITICAL"
],
"typeList": null
},
"dataToValue": {
"type": "NONE",
"dataToValueFunction": "/* Should return boolean value */\nreturn data;",
"compareToValue": true
}
},
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": null
},
{
"id": "criticalClick",
"name": "{i18n:scada.symbol.critical-click}",
"hint": "{i18n:scada.symbol.on-click-hint}",
"group": "{i18n:scada.symbol.critical-state}",
"type": "widgetAction",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": null,
"defaultGetValueSettings": null,
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": {
"type": "doNothing",
"targetDashboardStateId": null,
"openRightLayout": false,
"setEntityId": false,
"stateEntityParamName": null
}
},
{
"id": "criticalAnimation",
"name": "{i18n:scada.symbol.warning-critical-state-animation}",
"hint": "{i18n:scada.symbol.warning-critical-state-animation-hint}",
"group": null,
"type": "value",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": "{i18n:scada.symbol.animation}",
"defaultGetValueSettings": {
"action": "DO_NOTHING",
"defaultValue": false,
"executeRpc": {
"method": "getState",
"requestTimeout": 5000,
"requestPersistent": false,
"persistentPollingInterval": 1000
},
"getAttribute": {
"key": "state",
"scope": null
},
"getTimeSeries": {
"key": "state"
},
"dataToValue": {
"type": "NONE",
"compareToValue": true,
"dataToValueFunction": "/* Should return boolean value */\nreturn data;"
}
},
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": null
},
{
"id": "click",
"name": "{i18n:scada.symbol.on-click}",
"hint": "{i18n:scada.symbol.on-click-hint}",
"group": null,
"type": "widgetAction",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": null,
"defaultGetValueSettings": null,
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": {
"type": "doNothing",
"targetDashboardStateId": null,
"openRightLayout": false,
"setEntityId": false,
"stateEntityParamName": null
}
}
],
"properties": [
{
"id": "runningColor",
"name": "{i18n:scada.symbol.colors}",
"type": "color",
"default": "#FFFFFF",
"required": null,
"subLabel": "{i18n:scada.symbol.running}",
"divider": true,
"fieldSuffix": null,
"disableOnProperty": null,
"rowClass": "",
"fieldClass": "",
"min": null,
"max": null,
"step": null,
"disabled": false,
"visible": true
},
{
"id": "stoppedColor",
"name": "{i18n:scada.symbol.colors}",
"type": "color",
"default": "#666666",
"required": null,
"subLabel": "{i18n:scada.symbol.stopped}",
"divider": null,
"fieldSuffix": null,
"disableOnProperty": null,
"rowClass": "",
"fieldClass": "",
"min": null,
"max": null,
"step": null,
"disabled": false,
"visible": true
},
{
"id": "warningColor",
"name": "{i18n:scada.symbol.alarm-colors}",
"type": "color",
"default": "#FAA405",
"required": null,
"subLabel": "{i18n:scada.symbol.warning}",
"divider": true,
"fieldSuffix": null,
"disableOnProperty": null,
"rowClass": "",
"fieldClass": "",
"min": null,
"max": null,
"step": null,
"disabled": false,
"visible": true
},
{
"id": "criticalColor",
"name": "{i18n:scada.symbol.alarm-colors}",
"type": "color",
"default": "#D12730",
"required": null,
"subLabel": "{i18n:scada.symbol.critical}",
"divider": null,
"fieldSuffix": null,
"disableOnProperty": null,
"rowClass": "",
"fieldClass": "",
"min": null,
"max": null,
"step": null,
"disabled": false,
"visible": true
}
]
}]]></tb:metadata>
<g fill="#fff" stroke="#1A1A1A" stroke-width="2" tb:tag="background">
<path d="m116.44 357 33.471-33h299.17l32.528 33h-365.17z"/>
<path d="m1.3942 324 109.32-323h378.57l109.32 323h-597.21z"/>
<rect x="56" y="357" width="478" height="42" rx="5"/>
</g><path d="M450 324L395 1" stroke="#1A1A1A" stroke-width="2"/><path d="M150 324L205 1" stroke="#1A1A1A" stroke-width="2"/><path d="M300 324V1" stroke="#1A1A1A" stroke-width="2"/><path d="m57 162h486" stroke="#1A1A1A" stroke-width="2"/><path d="m201.8 0s-201.8 0-201.8 67v328.36c0 2.6512 5.3727 4.6404 12 4.6404h576c6.627 0 12-1.9892 12-4.6404v-328.36c0-67-198.21-67-198.21-67h-101.79zm201.21 81.2c-3.8661 0-6.9999 1.2536-6.9999 2.8v300.4c0 1.5464 3.1341 2.8 6.9999 2.8h43.998c3.8661 0 6.9999-1.2536 6.9999-2.8v-300.4c0-1.5464-3.1341-2.8-6.9999-2.8z" fill="#000" fill-opacity="0" style="stroke-width:1.732" tb:tag="clickArea"/><g transform="translate(0,316)" fill="#d12730" style="display: none;" tb:tag="critical">
<rect width="84" height="84" rx="4" fill="#fff" style=""/>
<rect width="84" height="84" rx="4" style=""/>
<rect x="2" y="2" width="80" height="80" rx="2" stroke="#000" stroke-opacity=".87" stroke-width="4" style=""/>
<path d="m44.559 27.562-0.4688 20.059h-4.0234l-0.4883-20.059zm-5.1172 26.211c0-0.7161 0.2344-1.3151 0.7031-1.7968 0.4818-0.4948 1.1459-0.7422 1.9922-0.7422 0.8334 0 1.4909 0.2474 1.9727 0.7422 0.4817 0.4817 0.7226 1.0807 0.7226 1.7968 0 0.6901-0.2409 1.2826-0.7226 1.7774-0.4818 0.4818-1.1393 0.7226-1.9727 0.7226-0.8463 0-1.5104-0.2408-1.9922-0.7226-0.4687-0.4948-0.7031-1.0873-0.7031-1.7774z" fill="#000" fill-opacity=".87" style=""/>
</g><g transform="translate(0 320.94)" fill="#faa405" style="display: none;" tb:tag="warning">
<path d="m35.955 2.2112c1.4741-2.9482 5.6813-2.9482 7.1554 0l35.528 71.056c1.3298 2.6596-0.6042 5.7889-3.5777 5.7889h-71.056c-2.9735 0-4.9075-3.1292-3.5777-5.7889z" fill="#fff" style=""/>
<path d="m35.955 2.2112c1.4741-2.9482 5.6813-2.9482 7.1554 0l35.528 71.056c1.3298 2.6596-0.6042 5.7889-3.5777 5.7889h-71.056c-2.9735 0-4.9075-3.1292-3.5777-5.7889z" style=""/>
<path d="m37.72 3.1061c0.7371-1.4741 2.8407-1.4741 3.5778-1e-5l35.528 71.056c0.6649 1.3298-0.3021 2.8944-1.7888 2.8944h-71.056c-1.4868 0-2.4538-1.5646-1.7889-2.8944z" stroke="#000" stroke-opacity=".87" stroke-width="4" style=""/>
<path d="m42.092 32.618-0.4688 20.059h-4.0234l-0.4883-20.059zm-5.1172 26.211c0-0.7161 0.2344-1.3151 0.7031-1.7968 0.4818-0.4948 1.1459-0.7422 1.9922-0.7422 0.8334 0 1.4909 0.2474 1.9727 0.7422 0.4817 0.4817 0.7226 1.0807 0.7226 1.7968 0 0.6901-0.2409 1.2826-0.7226 1.7774-0.4818 0.4818-1.1393 0.7226-1.9727 0.7226-0.8463 0-1.5104-0.2408-1.9922-0.7226-0.4687-0.4948-0.7031-1.0873-0.7031-1.7774z" fill="#000" fill-opacity=".87" style=""/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 13 KiB

747
application/src/main/data/json/system/scada_symbols/three-rate-energy-meter-hp.svg

@ -0,0 +1,747 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:tb="https://thingsboard.io/svg" width="600" height="400" fill="none" version="1.1" viewBox="0 0 600 400"><tb:metadata xmlns=""><![CDATA[{
"title": "HP Three-rate energy meter",
"description": "Three-rate energy meter with various states.",
"searchTags": [
"power",
"energy"
],
"widgetSizeX": 3,
"widgetSizeY": 2,
"tags": [
{
"tag": "background",
"stateRenderFunction": "var color = ctx.properties.stoppedColor;\nif (ctx.values.running) {\n color = ctx.properties.runningColor;\n}\nelement.attr({fill: color});",
"actions": null
},
{
"tag": "clickArea",
"stateRenderFunction": null,
"actions": {
"click": {
"actionFunction": "ctx.api.callAction(event, 'click');"
}
}
},
{
"tag": "critical",
"stateRenderFunction": "element.attr({fill: ctx.properties.criticalColor});\nif (ctx.values.critical) {\n element.show();\n} else {\n element.hide();\n}\n\nvar elementCriticalAnimation = element.remember('criticalAnimation');\nvar criticalAnimation = ctx.values.critical && ctx.values.criticalAnimation;\n\nif (elementCriticalAnimation !== criticalAnimation) {\n element.remember('criticalAnimation', criticalAnimation);\n if (criticalAnimation) {\n ctx.api.cssAnimate(element, 500).attr({opacity: 0.15}).loop(0, true);\n } else {\n ctx.api.resetCssAnimation(element);\n }\n}\n\n",
"actions": {
"click": {
"actionFunction": "ctx.api.callAction(event, 'criticalClick');"
}
}
},
{
"tag": "night-label",
"stateRenderFunction": "if (ctx.properties.showNightLabel) {\n element.show();\n ctx.api.font(element, ctx.properties.nightLabelFont, ctx.properties.nightLabelColor);\n ctx.api.text(element, ctx.properties.nightLabel);\n} else {\n element.hide();\n}",
"actions": null
},
{
"tag": "night-rate",
"stateRenderFunction": "ctx.api.font(element, ctx.properties.nightValueFont, ctx.properties.nightValueColor);\nctx.api.text(element, ctx.api.formatValue(ctx.values.nightRate, 0, null, 0));",
"actions": null
},
{
"tag": "off-peak-label",
"stateRenderFunction": "if (ctx.properties.showOffPeakLabel) {\n element.show();\n ctx.api.font(element, ctx.properties.offPeakLabelFont, ctx.properties.offPeakLabelColor);\n ctx.api.text(element, ctx.properties.offPeakLabel);\n} else {\n element.hide();\n}",
"actions": null
},
{
"tag": "off-peak-rate",
"stateRenderFunction": "ctx.api.font(element, ctx.properties.offPeakValueFont, ctx.properties.offPeakValueColor);\nctx.api.text(element, ctx.api.formatValue(ctx.values.offPeakRate, 0, null, 0));",
"actions": null
},
{
"tag": "peak-label",
"stateRenderFunction": "if (ctx.properties.showPeakLabel) {\n element.show();\n ctx.api.font(element, ctx.properties.peakLabelFont, ctx.properties.peakLabelColor);\n ctx.api.text(element, ctx.properties.peakLabel);\n} else {\n element.hide();\n}",
"actions": null
},
{
"tag": "peak-rate",
"stateRenderFunction": "ctx.api.font(element, ctx.properties.peakValueFont, ctx.properties.peakValueColor);\nctx.api.text(element, ctx.api.formatValue(ctx.values.peakRate, 0, null, 0));",
"actions": null
},
{
"tag": "units",
"stateRenderFunction": "if (ctx.properties.showUnits) {\n element.show();\n ctx.api.font(element, ctx.properties.unitsFont, ctx.properties.unitsColor);\n ctx.api.text(element, ctx.properties.units);\n} else {\n element.hide();\n}",
"actions": null
},
{
"tag": "value-box-night",
"stateRenderFunction": "var color = ctx.properties.stoppedColor;\nif (ctx.values.running) {\n color = ctx.properties.nightValueBoxBackground;\n}\nelement.attr({fill: color});",
"actions": null
},
{
"tag": "value-box-off-peak",
"stateRenderFunction": "var color = ctx.properties.stoppedColor;\nif (ctx.values.running) {\n color = ctx.properties.offPeakValueBoxBackground;\n}\nelement.attr({fill: color});",
"actions": null
},
{
"tag": "value-box-peak",
"stateRenderFunction": "var color = ctx.properties.stoppedColor;\nif (ctx.values.running) {\n color = ctx.properties.peakValueBoxBackground;\n}\nelement.attr({fill: color});",
"actions": null
},
{
"tag": "warning",
"stateRenderFunction": "element.attr({fill: ctx.properties.warningColor});\nvar warning = ctx.values.warning && !(ctx.values.warning && ctx.values.critical)\nif (warning) {\n element.show();\n} else {\n element.hide();\n}\n\nvar elementCriticalAnimation = element.remember('criticalAnimation');\nvar criticalAnimation = warning && ctx.values.criticalAnimation;\n\nif (elementCriticalAnimation !== criticalAnimation) {\n element.remember('criticalAnimation', criticalAnimation);\n if (criticalAnimation) {\n ctx.api.cssAnimate(element, 500).attr({opacity: 0.15}).loop(0, true);\n } else {\n ctx.api.resetCssAnimation(element);\n }\n}\n",
"actions": {
"click": {
"actionFunction": "ctx.api.callAction(event, 'warningClick');"
}
}
}
],
"behavior": [
{
"id": "running",
"name": "{i18n:scada.symbol.running}",
"hint": "{i18n:scada.symbol.running-hint}",
"group": null,
"type": "value",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": "{i18n:scada.symbol.running}",
"defaultGetValueSettings": {
"action": "GET_ATTRIBUTE",
"defaultValue": false,
"executeRpc": {
"method": "getState",
"requestTimeout": 5000,
"requestPersistent": false,
"persistentPollingInterval": 1000
},
"getAttribute": {
"scope": "SHARED_SCOPE",
"key": "running"
},
"getTimeSeries": {
"key": "state"
},
"getAlarmStatus": {
"severityList": null,
"typeList": null
},
"dataToValue": {
"type": "NONE",
"dataToValueFunction": "/* Should return boolean value */\nreturn data;",
"compareToValue": true
}
},
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": null
},
{
"id": "offPeakRate",
"name": "{i18n:scada.symbol.off-peak-rate}",
"hint": "{i18n:scada.symbol.measured-hint}",
"group": null,
"type": "value",
"valueType": "DOUBLE",
"trueLabel": null,
"falseLabel": null,
"stateLabel": null,
"defaultGetValueSettings": {
"action": "GET_TIME_SERIES",
"defaultValue": null,
"executeRpc": {
"method": "getState",
"requestTimeout": 5000,
"requestPersistent": false,
"persistentPollingInterval": 1000
},
"getAttribute": {
"scope": null,
"key": "state"
},
"getTimeSeries": {
"key": "offPeakRate"
},
"getAlarmStatus": {
"severityList": null,
"typeList": null
},
"dataToValue": {
"type": "NONE",
"dataToValueFunction": "/* Should return boolean value */\nreturn data;"
}
},
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": null
},
{
"id": "nightRate",
"name": "{i18n:scada.symbol.night-rate}",
"hint": "{i18n:scada.symbol.measured-hint}",
"group": null,
"type": "value",
"valueType": "DOUBLE",
"trueLabel": null,
"falseLabel": null,
"stateLabel": null,
"defaultGetValueSettings": {
"action": "GET_TIME_SERIES",
"defaultValue": null,
"executeRpc": {
"method": "getState",
"requestTimeout": 5000,
"requestPersistent": false,
"persistentPollingInterval": 1000
},
"getAttribute": {
"scope": null,
"key": "state"
},
"getTimeSeries": {
"key": "nightRate"
},
"getAlarmStatus": {
"severityList": null,
"typeList": null
},
"dataToValue": {
"type": "NONE",
"dataToValueFunction": "/* Should return boolean value */\nreturn data;"
}
},
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": null
},
{
"id": "peakRate",
"name": "{i18n:scada.symbol.peak-rate}",
"hint": "{i18n:scada.symbol.measured-hint}",
"group": null,
"type": "value",
"valueType": "DOUBLE",
"trueLabel": null,
"falseLabel": null,
"stateLabel": null,
"defaultGetValueSettings": {
"action": "GET_TIME_SERIES",
"defaultValue": null,
"executeRpc": {
"method": "getState",
"requestTimeout": 5000,
"requestPersistent": false,
"persistentPollingInterval": 1000
},
"getAttribute": {
"scope": null,
"key": "state"
},
"getTimeSeries": {
"key": "peakRate"
},
"getAlarmStatus": {
"severityList": null,
"typeList": null
},
"dataToValue": {
"type": "NONE",
"dataToValueFunction": "/* Should return boolean value */\nreturn data;"
}
},
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": null
},
{
"id": "warning",
"name": "{i18n:scada.symbol.warning}",
"hint": "{i18n:scada.symbol.warning-state-hint}",
"group": "{i18n:scada.symbol.warning-state}",
"type": "value",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": "{i18n:scada.symbol.warning}",
"defaultGetValueSettings": {
"action": "GET_ALARM_STATUS",
"defaultValue": false,
"executeRpc": {
"method": "getState",
"requestTimeout": 5000,
"requestPersistent": false,
"persistentPollingInterval": 1000
},
"getAttribute": {
"scope": null,
"key": "state"
},
"getTimeSeries": {
"key": "state"
},
"getAlarmStatus": {
"severityList": [
"MAJOR",
"MINOR",
"WARNING",
"INDETERMINATE"
],
"typeList": null
},
"dataToValue": {
"type": "NONE",
"dataToValueFunction": "/* Should return boolean value */\nreturn data;",
"compareToValue": true
}
},
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": null
},
{
"id": "warningClick",
"name": "{i18n:scada.symbol.warning-click}",
"hint": "{i18n:scada.symbol.on-click-hint}",
"group": "{i18n:scada.symbol.warning-state}",
"type": "widgetAction",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": null,
"defaultGetValueSettings": null,
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": {
"type": "doNothing",
"targetDashboardStateId": null,
"openRightLayout": false,
"setEntityId": false,
"stateEntityParamName": null
}
},
{
"id": "critical",
"name": "{i18n:scada.symbol.critical}",
"hint": "{i18n:scada.symbol.critical-state-hint}",
"group": "{i18n:scada.symbol.critical-state}",
"type": "value",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": "{i18n:scada.symbol.critical}",
"defaultGetValueSettings": {
"action": "GET_ALARM_STATUS",
"defaultValue": false,
"executeRpc": {
"method": "getState",
"requestTimeout": 5000,
"requestPersistent": false,
"persistentPollingInterval": 1000
},
"getAttribute": {
"scope": null,
"key": "state"
},
"getTimeSeries": {
"key": "state"
},
"getAlarmStatus": {
"severityList": [
"CRITICAL"
],
"typeList": null
},
"dataToValue": {
"type": "NONE",
"dataToValueFunction": "/* Should return boolean value */\nreturn data;",
"compareToValue": true
}
},
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": null
},
{
"id": "criticalClick",
"name": "{i18n:scada.symbol.critical-click}",
"hint": "{i18n:scada.symbol.on-click-hint}",
"group": "{i18n:scada.symbol.critical-state}",
"type": "widgetAction",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": null,
"defaultGetValueSettings": null,
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": {
"type": "doNothing",
"targetDashboardStateId": null,
"openRightLayout": false,
"setEntityId": false,
"stateEntityParamName": null
}
},
{
"id": "criticalAnimation",
"name": "{i18n:scada.symbol.warning-critical-state-animation}",
"hint": "{i18n:scada.symbol.warning-critical-state-animation-hint}",
"group": null,
"type": "value",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": "{i18n:scada.symbol.animation}",
"defaultGetValueSettings": {
"action": "DO_NOTHING",
"defaultValue": false,
"executeRpc": {
"method": "getState",
"requestTimeout": 5000,
"requestPersistent": false,
"persistentPollingInterval": 1000
},
"getAttribute": {
"key": "state",
"scope": null
},
"getTimeSeries": {
"key": "state"
},
"dataToValue": {
"type": "NONE",
"compareToValue": true,
"dataToValueFunction": "/* Should return boolean value */\nreturn data;"
}
},
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": null
},
{
"id": "click",
"name": "{i18n:scada.symbol.on-click}",
"hint": "{i18n:scada.symbol.on-click-hint}",
"group": null,
"type": "widgetAction",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": null,
"defaultGetValueSettings": null,
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": {
"type": "doNothing",
"targetDashboardStateId": null,
"openRightLayout": false,
"setEntityId": false,
"stateEntityParamName": null
}
}
],
"properties": [
{
"id": "runningColor",
"name": "{i18n:scada.symbol.colors}",
"type": "color",
"default": "#FFFFFF",
"subLabel": "{i18n:scada.symbol.running}",
"divider": true,
"disabled": false,
"visible": true
},
{
"id": "stoppedColor",
"name": "{i18n:scada.symbol.colors}",
"type": "color",
"default": "#666666",
"subLabel": "{i18n:scada.symbol.stopped}",
"disabled": false,
"visible": true
},
{
"id": "warningColor",
"name": "{i18n:scada.symbol.alarm-colors}",
"type": "color",
"default": "#FAA405",
"subLabel": "{i18n:scada.symbol.warning}",
"divider": true,
"disabled": false,
"visible": true
},
{
"id": "criticalColor",
"name": "{i18n:scada.symbol.alarm-colors}",
"type": "color",
"default": "#D12730",
"subLabel": "{i18n:scada.symbol.critical}",
"disabled": false,
"visible": true
},
{
"id": "showOffPeakLabel",
"name": "{i18n:scada.symbol.label}",
"group": "{i18n:scada.symbol.off-peak-rate}",
"type": "switch",
"default": true,
"disabled": false,
"visible": true
},
{
"id": "offPeakLabel",
"name": "{i18n:scada.symbol.label}",
"group": "{i18n:scada.symbol.off-peak-rate}",
"type": "text",
"default": "T1",
"fieldClass": "medium-width",
"disabled": false,
"visible": true
},
{
"id": "offPeakLabelFont",
"name": "{i18n:scada.symbol.label}",
"group": "{i18n:scada.symbol.off-peak-rate}",
"type": "font",
"default": {
"size": 36,
"sizeUnit": "px",
"family": "Roboto",
"weight": "normal",
"style": "normal"
},
"disabled": false,
"visible": true
},
{
"id": "offPeakLabelColor",
"name": "{i18n:scada.symbol.label}",
"group": "{i18n:scada.symbol.off-peak-rate}",
"type": "color",
"default": "#000000",
"disabled": false,
"visible": true
},
{
"id": "offPeakValueFont",
"name": "{i18n:scada.symbol.value}",
"group": "{i18n:scada.symbol.off-peak-rate}",
"type": "font",
"default": {
"size": 48,
"sizeUnit": "px",
"family": "Roboto",
"weight": "normal",
"style": "normal"
},
"disabled": false,
"visible": true
},
{
"id": "offPeakValueColor",
"name": "{i18n:scada.symbol.value}",
"group": "{i18n:scada.symbol.off-peak-rate}",
"type": "color",
"default": "#002878",
"disabled": false,
"visible": true
},
{
"id": "offPeakValueBoxBackground",
"name": "{i18n:scada.symbol.value-box-background}",
"group": "{i18n:scada.symbol.off-peak-rate}",
"type": "color",
"default": "#DEDEDE",
"disabled": false,
"visible": true
},
{
"id": "showNightLabel",
"name": "{i18n:scada.symbol.label}",
"group": "{i18n:scada.symbol.night-rate}",
"type": "switch",
"default": true,
"disabled": false,
"visible": true
},
{
"id": "nightLabel",
"name": "{i18n:scada.symbol.label}",
"group": "{i18n:scada.symbol.night-rate}",
"type": "text",
"default": "T2",
"fieldClass": "medium-width",
"disabled": false,
"visible": true
},
{
"id": "nightLabelFont",
"name": "{i18n:scada.symbol.label}",
"group": "{i18n:scada.symbol.night-rate}",
"type": "font",
"default": {
"size": 36,
"sizeUnit": "px",
"family": "Roboto",
"weight": "normal",
"style": "normal"
},
"disabled": false,
"visible": true
},
{
"id": "nightLabelColor",
"name": "{i18n:scada.symbol.label}",
"group": "{i18n:scada.symbol.night-rate}",
"type": "color",
"default": "#000",
"disabled": false,
"visible": true
},
{
"id": "nightValueFont",
"name": "{i18n:scada.symbol.value}",
"group": "{i18n:scada.symbol.night-rate}",
"type": "font",
"default": {
"size": 48,
"sizeUnit": "px",
"family": "Roboto",
"weight": "normal",
"style": "normal"
},
"disabled": false,
"visible": true
},
{
"id": "nightValueColor",
"name": "{i18n:scada.symbol.value}",
"group": "{i18n:scada.symbol.night-rate}",
"type": "color",
"default": "#002878",
"disabled": false,
"visible": true
},
{
"id": "nightValueBoxBackground",
"name": "{i18n:scada.symbol.value-box-background}",
"group": "{i18n:scada.symbol.night-rate}",
"type": "color",
"default": "#DEDEDE",
"disabled": false,
"visible": true
},
{
"id": "showPeakLabel",
"name": "{i18n:scada.symbol.label}",
"group": "{i18n:scada.symbol.peak-rate}",
"type": "switch",
"default": true,
"disabled": false,
"visible": true
},
{
"id": "peakLabel",
"name": "{i18n:scada.symbol.label}",
"group": "{i18n:scada.symbol.peak-rate}",
"type": "text",
"default": "T3",
"fieldClass": "medium-width",
"disabled": false,
"visible": true
},
{
"id": "peakLabelFont",
"name": "{i18n:scada.symbol.label}",
"group": "{i18n:scada.symbol.peak-rate}",
"type": "font",
"default": {
"size": 36,
"sizeUnit": "px",
"family": "Roboto",
"weight": "normal",
"style": "normal"
},
"disabled": false,
"visible": true
},
{
"id": "peakLabelColor",
"name": "{i18n:scada.symbol.label}",
"group": "{i18n:scada.symbol.peak-rate}",
"type": "color",
"default": "#000",
"disabled": false,
"visible": true
},
{
"id": "peakValueFont",
"name": "{i18n:scada.symbol.value}",
"group": "{i18n:scada.symbol.peak-rate}",
"type": "font",
"default": {
"size": 48,
"sizeUnit": "px",
"family": "Roboto",
"weight": "normal",
"style": "normal"
},
"disabled": false,
"visible": true
},
{
"id": "peakValueColor",
"name": "{i18n:scada.symbol.value}",
"group": "{i18n:scada.symbol.peak-rate}",
"type": "color",
"default": "#002878",
"disabled": false,
"visible": true
},
{
"id": "peakValueBoxBackground",
"name": "{i18n:scada.symbol.value-box-background}",
"group": "{i18n:scada.symbol.peak-rate}",
"type": "color",
"default": "#DEDEDE",
"disabled": false,
"visible": true
},
{
"id": "showUnits",
"name": "{i18n:scada.symbol.units}",
"type": "switch",
"default": true,
"disabled": false,
"visible": true
},
{
"id": "units",
"name": "{i18n:scada.symbol.units}",
"type": "units",
"default": "kWh",
"disabled": false,
"visible": true
},
{
"id": "unitsFont",
"name": "{i18n:scada.symbol.units}",
"type": "font",
"default": {
"size": 36,
"sizeUnit": "px",
"family": "Roboto",
"weight": "normal",
"style": "normal"
},
"disabled": false,
"visible": true
},
{
"id": "unitsColor",
"name": "{i18n:scada.symbol.units}",
"type": "color",
"default": "#000",
"disabled": false,
"visible": true
}
]
}]]></tb:metadata>
<rect x="1" y="1" width="598" height="398" fill="#fff" stroke="#1A1A1A" stroke-width="2" tb:tag="background"/><rect x="49" y="81" width="238" height="82" rx="3" fill="#DEDEDE" stroke="#1A1A1A" stroke-width="2" tb:tag="value-box-off-peak"/><rect x="313" y="81" width="238" height="82" rx="3" fill="#DEDEDE" stroke="#1A1A1A" stroke-width="2" tb:tag="value-box-night"/><rect x="181" y="237" width="238" height="82" rx="3" fill="#DEDEDE" stroke="#1A1A1A" stroke-width="2" tb:tag="value-box-peak"/><text x="171.2998" y="58.286133" fill="#000000" font-family="Roboto" font-size="34px" font-weight="400" text-anchor="middle" tb:tag="off-peak-label" xml:space="default"><tspan dominant-baseline="start">T1</tspan></text><text x="432.2998" y="58.734375" fill="#000000" font-family="Roboto" font-size="34px" font-weight="400" text-anchor="middle" tb:tag="night-label"><tspan dominant-baseline="start">T2</tspan></text><text x="301.61865" y="214.39307" fill="#000000" font-family="Roboto" font-size="34px" font-weight="400" text-anchor="middle" tb:tag="peak-label" xml:space="default"><tspan dominant-baseline="start">T3</tspan></text><text x="170.09232" y="139.47266" fill="#002878" font-family="Roboto" font-size="48px" font-weight="400" text-anchor="middle" tb:tag="off-peak-rate" xml:space="default"><tspan dominant-baseline="start">000223</tspan></text><text x="434.09232" y="139.47266" fill="#002878" font-family="Roboto" font-size="48px" font-weight="400" text-anchor="middle" tb:tag="night-rate" xml:space="default"><tspan dominant-baseline="start">000223</tspan></text><text x="302.09232" y="295.47266" fill="#002878" font-family="Roboto" font-size="48px" font-weight="400" text-anchor="middle" tb:tag="peak-rate" xml:space="default"><tspan dominant-baseline="start">000223</tspan></text><text x="299.89453" y="371.67578" fill="#000000" font-family="Roboto" font-size="36px" font-weight="400" text-anchor="middle" tb:tag="units" xml:space="preserve"><tspan dominant-baseline="start">kWh</tspan></text><path d="m201.8-2e-4s-201.8 0-201.8 67v328.36c0 2.6512 5.3727 4.6404 12 4.6404h576c6.627 0 12-1.9892 12-4.6404v-328.36c0-67-198.21-67-198.21-67h-101.79zm201.21 81.2c-3.8661 0-6.9999 1.2536-6.9999 2.8v300.4c0 1.5464 3.1341 2.8 6.9999 2.8h43.998c3.8661 0 6.9999-1.2536 6.9999-2.8v-300.4c0-1.5464-3.1341-2.8-6.9999-2.8z" fill-opacity="0" tb:tag="clickArea"/><g fill="#d12730" style="display: none;" tb:tag="critical">
<rect width="84" height="84" rx="4" fill="#fff" style=""/>
<rect width="84" height="84" rx="4" style=""/>
<rect x="2" y="2" width="80" height="80" rx="2" stroke="#000" stroke-opacity=".87" stroke-width="4" style=""/>
<path d="m44.559 27.562-0.4688 20.059h-4.0234l-0.4883-20.059zm-5.1172 26.211c0-0.7161 0.2344-1.3151 0.7031-1.7968 0.4818-0.4948 1.1459-0.7422 1.9922-0.7422 0.8334 0 1.4909 0.2474 1.9727 0.7422 0.4817 0.4817 0.7226 1.0807 0.7226 1.7968 0 0.6901-0.2409 1.2826-0.7226 1.7774-0.4818 0.4818-1.1393 0.7226-1.9727 0.7226-0.8463 0-1.5104-0.2408-1.9922-0.7226-0.4687-0.4948-0.7031-1.0873-0.7031-1.7774z" fill="#000" fill-opacity=".87" style=""/>
</g><g fill="#faa405" style="display: none;" tb:tag="warning">
<path d="m35.955 2.2112c1.4741-2.9482 5.6813-2.9482 7.1554 0l35.528 71.056c1.3298 2.6596-0.6042 5.7889-3.5777 5.7889h-71.056c-2.9735 0-4.9075-3.1292-3.5777-5.7889z" fill="#fff" style=""/>
<path d="m35.955 2.2112c1.4741-2.9482 5.6813-2.9482 7.1554 0l35.528 71.056c1.3298 2.6596-0.6042 5.7889-3.5777 5.7889h-71.056c-2.9735 0-4.9075-3.1292-3.5777-5.7889z" style=""/>
<path d="m37.72 3.1061c0.7371-1.4741 2.8407-1.4741 3.5778-1e-5l35.528 71.056c0.6649 1.3298-0.3021 2.8944-1.7888 2.8944h-71.056c-1.4868 0-2.4538-1.5646-1.7889-2.8944z" stroke="#000" stroke-opacity=".87" stroke-width="4" style=""/>
<path d="m42.092 32.618-0.4688 20.059h-4.0234l-0.4883-20.059zm-5.1172 26.211c0-0.7161 0.2344-1.3151 0.7031-1.7968 0.4818-0.4948 1.1459-0.7422 1.9922-0.7422 0.8334 0 1.4909 0.2474 1.9727 0.7422 0.4817 0.4817 0.7226 1.0807 0.7226 1.7968 0 0.6901-0.2409 1.2826-0.7226 1.7774-0.4818 0.4818-1.1393 0.7226-1.9727 0.7226-0.8463 0-1.5104-0.2408-1.9922-0.7226-0.4687-0.4948-0.7031-1.0873-0.7031-1.7774z" fill="#000" fill-opacity=".87" style=""/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 26 KiB

346
application/src/main/data/json/system/scada_symbols/top-light-bulb-hp.svg

@ -0,0 +1,346 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:tb="https://thingsboard.io/svg" width="200" height="200" fill="none" version="1.1" viewBox="0 0 200 200"><tb:metadata xmlns=""><![CDATA[{
"title": "HP Top light bulb",
"description": "Top light bulb with various states.",
"searchTags": [
"energy"
],
"widgetSizeX": 1,
"widgetSizeY": 1,
"tags": [
{
"tag": "background",
"stateRenderFunction": "var color = ctx.properties.stoppedColor;\nif (ctx.values.running) {\n color = ctx.properties.runningColor;\n}\nelement.attr({fill: color});",
"actions": null
},
{
"tag": "clickArea",
"stateRenderFunction": null,
"actions": {
"click": {
"actionFunction": "ctx.api.callAction(event, 'click');"
}
}
},
{
"tag": "critical",
"stateRenderFunction": "element.attr({fill: ctx.properties.criticalColor});\nif (ctx.values.critical) {\n element.show();\n} else {\n element.hide();\n}\n\nvar elementCriticalAnimation = element.remember('criticalAnimation');\nvar criticalAnimation = ctx.values.critical && ctx.values.criticalAnimation;\n\nif (elementCriticalAnimation !== criticalAnimation) {\n element.remember('criticalAnimation', criticalAnimation);\n if (criticalAnimation) {\n ctx.api.cssAnimate(element, 500).attr({opacity: 0.15}).loop(0, true);\n } else {\n ctx.api.resetCssAnimation(element);\n }\n}\n\n",
"actions": {
"click": {
"actionFunction": "ctx.api.callAction(event, 'criticalClick');"
}
}
},
{
"tag": "warning",
"stateRenderFunction": "element.attr({fill: ctx.properties.warningColor});\nvar warning = ctx.values.warning && !(ctx.values.warning && ctx.values.critical)\nif (warning) {\n element.show();\n} else {\n element.hide();\n}\n\nvar elementCriticalAnimation = element.remember('criticalAnimation');\nvar criticalAnimation = warning && ctx.values.criticalAnimation;\n\nif (elementCriticalAnimation !== criticalAnimation) {\n element.remember('criticalAnimation', criticalAnimation);\n if (criticalAnimation) {\n ctx.api.cssAnimate(element, 500).attr({opacity: 0.15}).loop(0, true);\n } else {\n ctx.api.resetCssAnimation(element);\n }\n}\n",
"actions": {
"click": {
"actionFunction": "ctx.api.callAction(event, 'warningClick');"
}
}
}
],
"behavior": [
{
"id": "running",
"name": "{i18n:scada.symbol.running}",
"hint": "{i18n:scada.symbol.running-hint}",
"group": null,
"type": "value",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": "{i18n:scada.symbol.running}",
"defaultGetValueSettings": {
"action": "GET_ATTRIBUTE",
"defaultValue": false,
"executeRpc": {
"method": "getState",
"requestTimeout": 5000,
"requestPersistent": false,
"persistentPollingInterval": 1000
},
"getAttribute": {
"scope": "SHARED_SCOPE",
"key": "running"
},
"getTimeSeries": {
"key": "state"
},
"getAlarmStatus": {
"severityList": null,
"typeList": null
},
"dataToValue": {
"type": "NONE",
"dataToValueFunction": "/* Should return boolean value */\nreturn data;",
"compareToValue": true
}
},
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": null
},
{
"id": "warning",
"name": "{i18n:scada.symbol.warning}",
"hint": "{i18n:scada.symbol.warning-state-hint}",
"group": "{i18n:scada.symbol.warning-state}",
"type": "value",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": "{i18n:scada.symbol.warning}",
"defaultGetValueSettings": {
"action": "GET_ALARM_STATUS",
"defaultValue": false,
"executeRpc": {
"method": "getState",
"requestTimeout": 5000,
"requestPersistent": false,
"persistentPollingInterval": 1000
},
"getAttribute": {
"scope": null,
"key": "state"
},
"getTimeSeries": {
"key": "state"
},
"getAlarmStatus": {
"severityList": [
"MAJOR",
"MINOR",
"WARNING",
"INDETERMINATE"
],
"typeList": null
},
"dataToValue": {
"type": "NONE",
"dataToValueFunction": "/* Should return boolean value */\nreturn data;",
"compareToValue": true
}
},
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": null
},
{
"id": "warningClick",
"name": "{i18n:scada.symbol.warning-click}",
"hint": "{i18n:scada.symbol.on-click-hint}",
"group": "{i18n:scada.symbol.warning-state}",
"type": "widgetAction",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": null,
"defaultGetValueSettings": null,
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": {
"type": "doNothing",
"targetDashboardStateId": null,
"openRightLayout": false,
"setEntityId": false,
"stateEntityParamName": null
}
},
{
"id": "critical",
"name": "{i18n:scada.symbol.critical}",
"hint": "{i18n:scada.symbol.critical-state-hint}",
"group": "{i18n:scada.symbol.critical-state}",
"type": "value",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": "{i18n:scada.symbol.critical}",
"defaultGetValueSettings": {
"action": "GET_ALARM_STATUS",
"defaultValue": false,
"executeRpc": {
"method": "getState",
"requestTimeout": 5000,
"requestPersistent": false,
"persistentPollingInterval": 1000
},
"getAttribute": {
"scope": null,
"key": "state"
},
"getTimeSeries": {
"key": "state"
},
"getAlarmStatus": {
"severityList": [
"CRITICAL"
],
"typeList": null
},
"dataToValue": {
"type": "NONE",
"dataToValueFunction": "/* Should return boolean value */\nreturn data;",
"compareToValue": true
}
},
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": null
},
{
"id": "criticalClick",
"name": "{i18n:scada.symbol.critical-click}",
"hint": "{i18n:scada.symbol.on-click-hint}",
"group": "{i18n:scada.symbol.critical-state}",
"type": "widgetAction",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": null,
"defaultGetValueSettings": null,
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": {
"type": "doNothing",
"targetDashboardStateId": null,
"openRightLayout": false,
"setEntityId": false,
"stateEntityParamName": null
}
},
{
"id": "criticalAnimation",
"name": "{i18n:scada.symbol.warning-critical-state-animation}",
"hint": "{i18n:scada.symbol.warning-critical-state-animation-hint}",
"group": null,
"type": "value",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": "{i18n:scada.symbol.animation}",
"defaultGetValueSettings": {
"action": "DO_NOTHING",
"defaultValue": false,
"executeRpc": {
"method": "getState",
"requestTimeout": 5000,
"requestPersistent": false,
"persistentPollingInterval": 1000
},
"getAttribute": {
"key": "state",
"scope": null
},
"getTimeSeries": {
"key": "state"
},
"dataToValue": {
"type": "NONE",
"compareToValue": true,
"dataToValueFunction": "/* Should return boolean value */\nreturn data;"
}
},
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": null
},
{
"id": "click",
"name": "{i18n:scada.symbol.on-click}",
"hint": "{i18n:scada.symbol.on-click-hint}",
"group": null,
"type": "widgetAction",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": null,
"defaultGetValueSettings": null,
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": {
"type": "doNothing",
"targetDashboardStateId": null,
"openRightLayout": false,
"setEntityId": false,
"stateEntityParamName": null
}
}
],
"properties": [
{
"id": "runningColor",
"name": "{i18n:scada.symbol.colors}",
"type": "color",
"default": "#FFFFFF",
"required": null,
"subLabel": "{i18n:scada.symbol.running}",
"divider": true,
"fieldSuffix": null,
"disableOnProperty": null,
"rowClass": "",
"fieldClass": "",
"min": null,
"max": null,
"step": null
},
{
"id": "stoppedColor",
"name": "{i18n:scada.symbol.colors}",
"type": "color",
"default": "#666666",
"required": null,
"subLabel": "{i18n:scada.symbol.stopped}",
"divider": null,
"fieldSuffix": null,
"disableOnProperty": null,
"rowClass": "",
"fieldClass": "",
"min": null,
"max": null,
"step": null
},
{
"id": "warningColor",
"name": "{i18n:scada.symbol.alarm-colors}",
"type": "color",
"default": "#FAA405",
"required": null,
"subLabel": "{i18n:scada.symbol.warning}",
"divider": true,
"fieldSuffix": null,
"disableOnProperty": null,
"rowClass": "",
"fieldClass": "",
"min": null,
"max": null,
"step": null
},
{
"id": "criticalColor",
"name": "{i18n:scada.symbol.alarm-colors}",
"type": "color",
"default": "#D12730",
"required": null,
"subLabel": "{i18n:scada.symbol.critical}",
"divider": null,
"fieldSuffix": null,
"disableOnProperty": null,
"rowClass": "",
"fieldClass": "",
"min": null,
"max": null,
"step": null
}
]
}]]></tb:metadata>
<g fill="#fff" stroke="#1A1A1A" stroke-width="2" tb:tag="background">
<path d="m77.22 131 1.6 8h42.36l1.6-8h-45.56z"/>
<path d="m77.117 131h45.742c0.108-0.257 0.244-0.505 0.385-0.736 0.342-0.558 0.824-1.187 1.403-1.87 1.16-1.367 2.802-3.062 4.738-5.019 0.519-0.524 1.059-1.069 1.62-1.633 3.641-3.666 8.098-8.154 12.557-13.274 10.326-11.856 20.438-26.862 20.438-42.468 0-21.266-7.121-37.489-18.622-48.4-11.511-10.919-27.5-16.6-45.378-16.6-17.878 0-33.867 5.6814-45.378 16.6-11.502 10.91-18.622 27.134-18.622 48.4 0 15.606 10.106 30.612 20.426 42.468 4.456 5.12 8.9107 9.608 12.55 13.274 0.5601 0.564 1.1009 1.109 1.6194 1.633 1.9344 1.958 3.576 3.652 4.735 5.02 0.5788 0.683 1.0604 1.311 1.4022 1.869 0.1413 0.231 0.2771 0.479 0.3847 0.736z"/>
<path d="m80.13 194.02c1.5245 3.049 4.6409 4.975 8.0498 4.975h23.64c3.409 0 6.525-1.926 8.05-4.975l6.18-12.361c0.625-1.249 0.95-2.627 0.95-4.025v-38.639h-54v38.639c0 1.398 0.3253 2.776 0.9502 4.025l6.1803 12.361z"/>
</g><path d="m73 147h54" stroke="#1A1A1A" stroke-width="2"/><path d="m73 179h54" stroke="#1A1A1A" stroke-width="2"/><path d="m67.265 0s-67.265 0-67.265 33.5v164.18c0 1.3256 1.7909 2.3202 4 2.3202h192c2.209 0 4-0.9946 4-2.3202v-164.18c0-33.5-66.07-33.5-66.07-33.5h-33.93zm67.07 40.6c-1.2887 0-2.3333 0.6268-2.3333 1.4v150.2c0 0.7732 1.0447 1.4 2.3333 1.4h14.666c1.2887 0 2.3333-0.6268 2.3333-1.4v-150.2c0-0.7732-1.0447-1.4-2.3333-1.4z" fill-opacity="0" tb:tag="clickArea"/><g fill="#d12730" style="display: none;" tb:tag="critical">
<rect width="84" height="84" rx="4" fill="#fff" style=""/>
<rect width="84" height="84" rx="4" style=""/>
<rect x="2" y="2" width="80" height="80" rx="2" stroke="#000" stroke-opacity=".87" stroke-width="4" style=""/>
<path d="m44.559 27.562-0.4688 20.059h-4.0234l-0.4883-20.059zm-5.1172 26.211c0-0.7161 0.2344-1.3151 0.7031-1.7968 0.4818-0.4948 1.1459-0.7422 1.9922-0.7422 0.8334 0 1.4909 0.2474 1.9727 0.7422 0.4817 0.4817 0.7226 1.0807 0.7226 1.7968 0 0.6901-0.2409 1.2826-0.7226 1.7774-0.4818 0.4818-1.1393 0.7226-1.9727 0.7226-0.8463 0-1.5104-0.2408-1.9922-0.7226-0.4687-0.4948-0.7031-1.0873-0.7031-1.7774z" fill="#000" fill-opacity=".87" style=""/>
</g><g fill="#faa405" style="display: none;" tb:tag="warning">
<path d="m35.955 2.2112c1.4741-2.9482 5.6813-2.9482 7.1554 0l35.528 71.056c1.3298 2.6596-0.6042 5.7889-3.5777 5.7889h-71.056c-2.9735 0-4.9075-3.1292-3.5777-5.7889z" fill="#fff" style=""/>
<path d="m35.955 2.2112c1.4741-2.9482 5.6813-2.9482 7.1554 0l35.528 71.056c1.3298 2.6596-0.6042 5.7889-3.5777 5.7889h-71.056c-2.9735 0-4.9075-3.1292-3.5777-5.7889z" style=""/>
<path d="m37.72 3.1061c0.7371-1.4741 2.8407-1.4741 3.5778-1e-5l35.528 71.056c0.6649 1.3298-0.3021 2.8944-1.7888 2.8944h-71.056c-1.4868 0-2.4538-1.5646-1.7889-2.8944z" stroke="#000" stroke-opacity=".87" stroke-width="4" style=""/>
<path d="m42.092 32.618-0.4688 20.059h-4.0234l-0.4883-20.059zm-5.1172 26.211c0-0.7161 0.2344-1.3151 0.7031-1.7968 0.4818-0.4948 1.1459-0.7422 1.9922-0.7422 0.8334 0 1.4909 0.2474 1.9727 0.7422 0.4817 0.4817 0.7226 1.0807 0.7226 1.7968 0 0.6901-0.2409 1.2826-0.7226 1.7774-0.4818 0.4818-1.1393 0.7226-1.9727 0.7226-0.8463 0-1.5104-0.2408-1.9922-0.7226-0.4687-0.4948-0.7031-1.0873-0.7031-1.7774z" fill="#000" fill-opacity=".87" style=""/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 14 KiB

489
application/src/main/data/json/system/scada_symbols/two-key-switch-hp.svg

@ -0,0 +1,489 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:tb="https://thingsboard.io/svg" width="200" height="200" fill="none" version="1.1" viewBox="0 0 200 200"><tb:metadata xmlns=""><![CDATA[{
"title": "HP Two-key switch",
"description": "Two-key switch with various states.",
"searchTags": [
"energy",
"power"
],
"widgetSizeX": 1,
"widgetSizeY": 1,
"tags": [
{
"tag": "background",
"stateRenderFunction": "element.attr({fill: ctx.properties.backgroundColor});",
"actions": null
},
{
"tag": "critical",
"stateRenderFunction": "element.attr({fill: ctx.properties.criticalColor});\nif (ctx.values.critical) {\n element.show();\n} else {\n element.hide();\n}\n\nvar elementCriticalAnimation = element.remember('criticalAnimation');\nvar criticalAnimation = ctx.values.critical && ctx.values.criticalAnimation;\n\nif (elementCriticalAnimation !== criticalAnimation) {\n element.remember('criticalAnimation', criticalAnimation);\n if (criticalAnimation) {\n ctx.api.cssAnimate(element, 500).attr({opacity: 0.15}).loop(0, true);\n } else {\n ctx.api.resetCssAnimation(element);\n }\n}\n\n",
"actions": {
"click": {
"actionFunction": "ctx.api.callAction(event, 'criticalClick');"
}
}
},
{
"tag": "left-button",
"stateRenderFunction": "var color = ctx.properties.disabledColor;\nif (ctx.values.initialStateLeftButton) {\n color = ctx.properties.enabledColor;\n}\nelement.attr({fill: color});",
"actions": {
"click": {
"actionFunction": "var initial = ctx.values.initialStateLeftButton;\nvar action = initial ? 'offUpdateStateLeftButton' : 'onUpdateStateLeftButton';\n\nctx.api.callAction(event, action, undefined, {\n next: () => {\n ctx.api.setValue('initialStateLeftButton', !initial);\n }\n});"
}
}
},
{
"tag": "right-button",
"stateRenderFunction": "var color = ctx.properties.disabledColor;\nif (ctx.values.initialStateRightButton) {\n color = ctx.properties.enabledColor;\n}\nelement.attr({fill: color});",
"actions": {
"click": {
"actionFunction": "var initial = ctx.values.initialStateRightButton;\nvar action = initial ? 'offUpdateStateRightButton' : 'onUpdateStateRightButton';\n\nctx.api.callAction(event, action, undefined, {\n next: () => {\n ctx.api.setValue('initialStateRightButton', !initial);\n }\n});"
}
}
},
{
"tag": "warning",
"stateRenderFunction": "element.attr({fill: ctx.properties.warningColor});\nvar warning = ctx.values.warning && !(ctx.values.warning && ctx.values.critical)\nif (warning) {\n element.show();\n} else {\n element.hide();\n}\n\nvar elementCriticalAnimation = element.remember('criticalAnimation');\nvar criticalAnimation = warning && ctx.values.criticalAnimation;\n\nif (elementCriticalAnimation !== criticalAnimation) {\n element.remember('criticalAnimation', criticalAnimation);\n if (criticalAnimation) {\n ctx.api.cssAnimate(element, 500).attr({opacity: 0.15}).loop(0, true);\n } else {\n ctx.api.resetCssAnimation(element);\n }\n}\n",
"actions": {
"click": {
"actionFunction": "ctx.api.callAction(event, 'warningClick');"
}
}
}
],
"behavior": [
{
"id": "initialStateLeftButton",
"name": "{i18n:scada.symbol.on-off-state}",
"hint": "{i18n:scada.symbol.on-off-state-hint}",
"group": "{i18n:scada.symbol.left-button}",
"type": "value",
"valueType": "BOOLEAN",
"trueLabel": "{i18n:scada.symbol.on}",
"falseLabel": "{i18n:scada.symbol.off}",
"stateLabel": "",
"defaultGetValueSettings": {
"action": "GET_ATTRIBUTE",
"defaultValue": false,
"executeRpc": {
"method": "getState",
"requestTimeout": 5000,
"requestPersistent": false,
"persistentPollingInterval": 1000
},
"getAttribute": {
"scope": "SHARED_SCOPE",
"key": "leftButton"
},
"getTimeSeries": {
"key": "state"
},
"getAlarmStatus": {
"severityList": null,
"typeList": null
},
"dataToValue": {
"type": "NONE",
"dataToValueFunction": "/* Should return boolean value */\nreturn data;",
"compareToValue": true
}
},
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": null
},
{
"id": "onUpdateStateLeftButton",
"name": "{i18n:scada.symbol.on-update-state}",
"hint": "{i18n:scada.symbol.on-update-state-hint}",
"group": "{i18n:scada.symbol.left-button}",
"type": "action",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": null,
"defaultGetValueSettings": null,
"defaultSetValueSettings": {
"action": "EXECUTE_RPC",
"executeRpc": {
"method": "setState",
"requestTimeout": 5000,
"requestPersistent": false,
"persistentPollingInterval": 1000
},
"setAttribute": {
"scope": "SERVER_SCOPE",
"key": "state"
},
"putTimeSeries": {
"key": "state"
},
"valueToData": {
"type": "CONSTANT",
"constantValue": true,
"valueToDataFunction": "/* Convert input boolean value to RPC parameters or attribute/time-series value */\nreturn value;"
}
},
"defaultWidgetActionSettings": null
},
{
"id": "offUpdateStateLeftButton",
"name": "{i18n:scada.symbol.off-update-state}",
"hint": "{i18n:scada.symbol.off-update-state-hint}",
"group": "{i18n:scada.symbol.left-button}",
"type": "action",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": null,
"defaultGetValueSettings": null,
"defaultSetValueSettings": {
"action": "EXECUTE_RPC",
"executeRpc": {
"method": "setState",
"requestTimeout": 5000,
"requestPersistent": false,
"persistentPollingInterval": 1000
},
"setAttribute": {
"key": "state",
"scope": "SERVER_SCOPE"
},
"putTimeSeries": {
"key": "state"
},
"valueToData": {
"type": "CONSTANT",
"constantValue": false,
"valueToDataFunction": "/* Convert input boolean value to RPC parameters or attribute/time-series value */\nreturn value;"
}
},
"defaultWidgetActionSettings": null
},
{
"id": "initialStateRightButton",
"name": "{i18n:scada.symbol.on-off-state}",
"hint": "{i18n:scada.symbol.on-off-state-hint}",
"group": "{i18n:scada.symbol.right-button}",
"type": "value",
"valueType": "BOOLEAN",
"trueLabel": "{i18n:scada.symbol.on}",
"falseLabel": "{i18n:scada.symbol.off}",
"stateLabel": null,
"defaultGetValueSettings": {
"action": "GET_ATTRIBUTE",
"defaultValue": false,
"executeRpc": {
"method": "getState",
"requestTimeout": 5000,
"requestPersistent": false,
"persistentPollingInterval": 1000
},
"getAttribute": {
"scope": "SHARED_SCOPE",
"key": "rightButton"
},
"getTimeSeries": {
"key": "state"
},
"getAlarmStatus": {
"severityList": null,
"typeList": null
},
"dataToValue": {
"type": "NONE",
"dataToValueFunction": "/* Should return boolean value */\nreturn data;",
"compareToValue": true
}
},
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": null
},
{
"id": "onUpdateStateRightButton",
"name": "{i18n:scada.symbol.on-update-state}",
"hint": "{i18n:scada.symbol.on-update-state-hint}",
"group": "{i18n:scada.symbol.right-button}",
"type": "action",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": null,
"defaultGetValueSettings": null,
"defaultSetValueSettings": {
"action": "EXECUTE_RPC",
"executeRpc": {
"method": "setState",
"requestTimeout": 5000,
"requestPersistent": false,
"persistentPollingInterval": 1000
},
"setAttribute": {
"scope": "SERVER_SCOPE",
"key": "state"
},
"putTimeSeries": {
"key": "state"
},
"valueToData": {
"type": "CONSTANT",
"constantValue": true,
"valueToDataFunction": "/* Convert input boolean value to RPC parameters or attribute/time-series value */\nreturn value;"
}
},
"defaultWidgetActionSettings": null
},
{
"id": "offUpdateStateRightButton",
"name": "{i18n:scada.symbol.off-update-state}",
"hint": "{i18n:scada.symbol.off-update-state-hint}",
"group": "{i18n:scada.symbol.right-button}",
"type": "action",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": null,
"defaultGetValueSettings": null,
"defaultSetValueSettings": {
"action": "EXECUTE_RPC",
"executeRpc": {
"method": "setState",
"requestTimeout": 5000,
"requestPersistent": false,
"persistentPollingInterval": 1000
},
"setAttribute": {
"key": "state",
"scope": "SERVER_SCOPE"
},
"putTimeSeries": {
"key": "state"
},
"valueToData": {
"type": "CONSTANT",
"constantValue": false,
"valueToDataFunction": "/* Convert input boolean value to RPC parameters or attribute/time-series value */\nreturn value;"
}
},
"defaultWidgetActionSettings": null
},
{
"id": "warning",
"name": "{i18n:scada.symbol.warning}",
"hint": "{i18n:scada.symbol.warning-state-hint}",
"group": "{i18n:scada.symbol.warning-state}",
"type": "value",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": "{i18n:scada.symbol.warning}",
"defaultGetValueSettings": {
"action": "GET_ALARM_STATUS",
"defaultValue": false,
"executeRpc": {
"method": "getState",
"requestTimeout": 5000,
"requestPersistent": false,
"persistentPollingInterval": 1000
},
"getAttribute": {
"scope": null,
"key": "state"
},
"getTimeSeries": {
"key": "state"
},
"getAlarmStatus": {
"severityList": [
"MAJOR",
"MINOR",
"WARNING",
"INDETERMINATE"
],
"typeList": null
},
"dataToValue": {
"type": "NONE",
"dataToValueFunction": "/* Should return boolean value */\nreturn data;",
"compareToValue": true
}
},
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": null
},
{
"id": "warningClick",
"name": "{i18n:scada.symbol.warning-click}",
"hint": "{i18n:scada.symbol.on-click-hint}",
"group": "{i18n:scada.symbol.warning-state}",
"type": "widgetAction",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": null,
"defaultGetValueSettings": null,
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": {
"type": "doNothing",
"targetDashboardStateId": null,
"openRightLayout": false,
"setEntityId": false,
"stateEntityParamName": null
}
},
{
"id": "critical",
"name": "{i18n:scada.symbol.critical}",
"hint": "{i18n:scada.symbol.critical-state-hint}",
"group": "{i18n:scada.symbol.critical-state}",
"type": "value",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": "{i18n:scada.symbol.critical}",
"defaultGetValueSettings": {
"action": "GET_ALARM_STATUS",
"defaultValue": false,
"executeRpc": {
"method": "getState",
"requestTimeout": 5000,
"requestPersistent": false,
"persistentPollingInterval": 1000
},
"getAttribute": {
"scope": null,
"key": "state"
},
"getTimeSeries": {
"key": "state"
},
"getAlarmStatus": {
"severityList": [
"CRITICAL"
],
"typeList": null
},
"dataToValue": {
"type": "NONE",
"dataToValueFunction": "/* Should return boolean value */\nreturn data;",
"compareToValue": true
}
},
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": null
},
{
"id": "criticalClick",
"name": "{i18n:scada.symbol.critical-click}",
"hint": "{i18n:scada.symbol.on-click-hint}",
"group": "{i18n:scada.symbol.critical-state}",
"type": "widgetAction",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": null,
"defaultGetValueSettings": null,
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": {
"type": "doNothing",
"targetDashboardStateId": null,
"openRightLayout": false,
"setEntityId": false,
"stateEntityParamName": null
}
},
{
"id": "criticalAnimation",
"name": "{i18n:scada.symbol.warning-critical-state-animation}",
"hint": "{i18n:scada.symbol.warning-critical-state-animation-hint}",
"group": null,
"type": "value",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": "{i18n:scada.symbol.animation}",
"defaultGetValueSettings": {
"action": "DO_NOTHING",
"defaultValue": false,
"executeRpc": {
"method": "getState",
"requestTimeout": 5000,
"requestPersistent": false,
"persistentPollingInterval": 1000
},
"getAttribute": {
"key": "state",
"scope": null
},
"getTimeSeries": {
"key": "state"
},
"dataToValue": {
"type": "NONE",
"compareToValue": true,
"dataToValueFunction": "/* Should return boolean value */\nreturn data;"
}
},
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": null
}
],
"properties": [
{
"id": "backgroundColor",
"name": "{i18n:scada.symbol.background-color}",
"type": "color",
"default": "#FFFFFF",
"disabled": false,
"visible": true
},
{
"id": "enabledColor",
"name": "{i18n:scada.symbol.colors}",
"type": "color",
"default": "#FFFFFF",
"subLabel": "{i18n:scada.symbol.enabled}",
"divider": true,
"disabled": false,
"visible": true
},
{
"id": "disabledColor",
"name": "{i18n:scada.symbol.colors}",
"type": "color",
"default": "#666666",
"subLabel": "{i18n:scada.symbol.disabled}",
"disabled": false,
"visible": true
},
{
"id": "warningColor",
"name": "{i18n:scada.symbol.alarm-colors}",
"type": "color",
"default": "#FAA405",
"subLabel": "{i18n:scada.symbol.warning}",
"divider": true,
"disabled": false,
"visible": true
},
{
"id": "criticalColor",
"name": "{i18n:scada.symbol.alarm-colors}",
"type": "color",
"default": "#D12730",
"subLabel": "{i18n:scada.symbol.critical}",
"disabled": false,
"visible": true
}
]
}]]></tb:metadata>
<rect x="1" y="1" width="198" height="198" fill="#fff" stroke="#1A1A1A" stroke-width="2" tb:tag="background"/><path d="m26 29c0-1.6569 1.3431-3 3-3h64c1.6569 0 3 1.3431 3 3v142c0 1.657-1.3431 3-3 3h-64c-1.6569 0-3-1.343-3-3v-142z" fill="#fff" stroke="#1A1A1A" stroke-width="2" tb:tag="left-button"/><path d="m104 29c0-1.6569 1.343-3 3-3h64c1.657 0 3 1.3431 3 3v142c0 1.657-1.343 3-3 3h-64c-1.657 0-3-1.343-3-3v-142z" fill="#fff" stroke="#1A1A1A" stroke-width="2" tb:tag="right-button"/><g fill="#d12730" style="display: none;" tb:tag="critical">
<rect width="84" height="84" rx="4" fill="#fff" style=""/>
<rect width="84" height="84" rx="4" style=""/>
<rect x="2" y="2" width="80" height="80" rx="2" stroke="#000" stroke-opacity=".87" stroke-width="4" style=""/>
<path d="m44.559 27.562-0.4688 20.059h-4.0234l-0.4883-20.059zm-5.1172 26.211c0-0.7161 0.2344-1.3151 0.7031-1.7968 0.4818-0.4948 1.1459-0.7422 1.9922-0.7422 0.8334 0 1.4909 0.2474 1.9727 0.7422 0.4817 0.4817 0.7226 1.0807 0.7226 1.7968 0 0.6901-0.2409 1.2826-0.7226 1.7774-0.4818 0.4818-1.1393 0.7226-1.9727 0.7226-0.8463 0-1.5104-0.2408-1.9922-0.7226-0.4687-0.4948-0.7031-1.0873-0.7031-1.7774z" fill="#000" fill-opacity=".87" style=""/>
</g><g fill="#faa405" style="display: none;" tb:tag="warning">
<path d="m35.955 2.2112c1.4741-2.9482 5.6813-2.9482 7.1554 0l35.528 71.056c1.3298 2.6596-0.6042 5.7889-3.5777 5.7889h-71.056c-2.9735 0-4.9075-3.1292-3.5777-5.7889z" fill="#fff" style=""/>
<path d="m35.955 2.2112c1.4741-2.9482 5.6813-2.9482 7.1554 0l35.528 71.056c1.3298 2.6596-0.6042 5.7889-3.5777 5.7889h-71.056c-2.9735 0-4.9075-3.1292-3.5777-5.7889z" style=""/>
<path d="m37.72 3.1061c0.7371-1.4741 2.8407-1.4741 3.5778-1e-5l35.528 71.056c0.6649 1.3298-0.3021 2.8944-1.7888 2.8944h-71.056c-1.4868 0-2.4538-1.5646-1.7889-2.8944z" stroke="#000" stroke-opacity=".87" stroke-width="4" style=""/>
<path d="m42.092 32.618-0.4688 20.059h-4.0234l-0.4883-20.059zm-5.1172 26.211c0-0.7161 0.2344-1.3151 0.7031-1.7968 0.4818-0.4948 1.1459-0.7422 1.9922-0.7422 0.8334 0 1.4909 0.2474 1.9727 0.7422 0.4817 0.4817 0.7226 1.0807 0.7226 1.7968 0 0.6901-0.2409 1.2826-0.7226 1.7774-0.4818 0.4818-1.1393 0.7226-1.9727 0.7226-0.8463 0-1.5104-0.2408-1.9922-0.7226-0.4687-0.4948-0.7031-1.0873-0.7031-1.7774z" fill="#000" fill-opacity=".87" style=""/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 18 KiB

618
application/src/main/data/json/system/scada_symbols/two-rate-energy-meter-hp.svg

@ -0,0 +1,618 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:tb="https://thingsboard.io/svg" width="400" height="400" fill="none" version="1.1" viewBox="0 0 400 400"><tb:metadata xmlns=""><![CDATA[{
"title": "HP Two-rate energy meter",
"description": "Two-rate energy meter with various states.",
"searchTags": [
"power",
"energy"
],
"widgetSizeX": 2,
"widgetSizeY": 2,
"tags": [
{
"tag": "background",
"stateRenderFunction": "var color = ctx.properties.stoppedColor;\nif (ctx.values.running) {\n color = ctx.properties.runningColor;\n}\nelement.attr({fill: color});",
"actions": null
},
{
"tag": "clickArea",
"stateRenderFunction": null,
"actions": {
"click": {
"actionFunction": "ctx.api.callAction(event, 'click');"
}
}
},
{
"tag": "critical",
"stateRenderFunction": "element.attr({fill: ctx.properties.criticalColor});\nif (ctx.values.critical) {\n element.show();\n} else {\n element.hide();\n}\n\nvar elementCriticalAnimation = element.remember('criticalAnimation');\nvar criticalAnimation = ctx.values.critical && ctx.values.criticalAnimation;\n\nif (elementCriticalAnimation !== criticalAnimation) {\n element.remember('criticalAnimation', criticalAnimation);\n if (criticalAnimation) {\n ctx.api.cssAnimate(element, 500).attr({opacity: 0.15}).loop(0, true);\n } else {\n ctx.api.resetCssAnimation(element);\n }\n}\n\n",
"actions": {
"click": {
"actionFunction": "ctx.api.callAction(event, 'criticalClick');"
}
}
},
{
"tag": "day-label",
"stateRenderFunction": "if (ctx.properties.showDayLabel) {\n element.show();\n ctx.api.font(element, ctx.properties.dayLabelFont, ctx.properties.dayLabelColor);\n ctx.api.text(element, ctx.properties.dayLabel);\n} else {\n element.hide();\n}",
"actions": null
},
{
"tag": "day-rate",
"stateRenderFunction": "ctx.api.font(element, ctx.properties.dayValueFont, ctx.properties.dayValueColor);\nctx.api.text(element, ctx.api.formatValue(ctx.values.dayRate, 0, null, 0));",
"actions": null
},
{
"tag": "night-label",
"stateRenderFunction": "if (ctx.properties.showNightLabel) {\n element.show();\n ctx.api.font(element, ctx.properties.nightLabelFont, ctx.properties.nightLabelColor);\n ctx.api.text(element, ctx.properties.nightLabel);\n} else {\n element.hide();\n}",
"actions": null
},
{
"tag": "night-rate",
"stateRenderFunction": "ctx.api.font(element, ctx.properties.nightValueFont, ctx.properties.nightValueColor);\nctx.api.text(element, ctx.api.formatValue(ctx.values.nightRate, 0, null, 0));",
"actions": null
},
{
"tag": "units",
"stateRenderFunction": "if (ctx.properties.showUnits) {\n element.show();\n ctx.api.font(element, ctx.properties.unitsFont, ctx.properties.unitsColor);\n ctx.api.text(element, ctx.properties.units);\n} else {\n element.hide();\n}",
"actions": null
},
{
"tag": "value-box-day",
"stateRenderFunction": "var color = ctx.properties.stoppedColor;\nif (ctx.values.running) {\n color = ctx.properties.dayValueBoxBackground;\n}\nelement.attr({fill: color});",
"actions": null
},
{
"tag": "value-box-night",
"stateRenderFunction": "var color = ctx.properties.stoppedColor;\nif (ctx.values.running) {\n color = ctx.properties.nightValueBoxBackground;\n}\nelement.attr({fill: color});",
"actions": null
},
{
"tag": "warning",
"stateRenderFunction": "element.attr({fill: ctx.properties.warningColor});\nvar warning = ctx.values.warning && !(ctx.values.warning && ctx.values.critical)\nif (warning) {\n element.show();\n} else {\n element.hide();\n}\n\nvar elementCriticalAnimation = element.remember('criticalAnimation');\nvar criticalAnimation = warning && ctx.values.criticalAnimation;\n\nif (elementCriticalAnimation !== criticalAnimation) {\n element.remember('criticalAnimation', criticalAnimation);\n if (criticalAnimation) {\n ctx.api.cssAnimate(element, 500).attr({opacity: 0.15}).loop(0, true);\n } else {\n ctx.api.resetCssAnimation(element);\n }\n}\n",
"actions": {
"click": {
"actionFunction": "ctx.api.callAction(event, 'warningClick');"
}
}
}
],
"behavior": [
{
"id": "running",
"name": "{i18n:scada.symbol.running}",
"hint": "{i18n:scada.symbol.running-hint}",
"group": null,
"type": "value",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": "{i18n:scada.symbol.running}",
"defaultGetValueSettings": {
"action": "GET_ATTRIBUTE",
"defaultValue": false,
"executeRpc": {
"method": "getState",
"requestTimeout": 5000,
"requestPersistent": false,
"persistentPollingInterval": 1000
},
"getAttribute": {
"scope": "SHARED_SCOPE",
"key": "running"
},
"getTimeSeries": {
"key": "state"
},
"getAlarmStatus": {
"severityList": null,
"typeList": null
},
"dataToValue": {
"type": "NONE",
"dataToValueFunction": "/* Should return boolean value */\nreturn data;",
"compareToValue": true
}
},
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": null
},
{
"id": "dayRate",
"name": "{i18n:scada.symbol.day-rate}",
"hint": "{i18n:scada.symbol.measured-hint}",
"group": null,
"type": "value",
"valueType": "DOUBLE",
"trueLabel": null,
"falseLabel": null,
"stateLabel": null,
"defaultGetValueSettings": {
"action": "GET_TIME_SERIES",
"defaultValue": null,
"executeRpc": {
"method": "getState",
"requestTimeout": 5000,
"requestPersistent": false,
"persistentPollingInterval": 1000
},
"getAttribute": {
"scope": null,
"key": "state"
},
"getTimeSeries": {
"key": "dayRate"
},
"getAlarmStatus": {
"severityList": null,
"typeList": null
},
"dataToValue": {
"type": "NONE",
"dataToValueFunction": "/* Should return boolean value */\nreturn data;"
}
},
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": null
},
{
"id": "nightRate",
"name": "{i18n:scada.symbol.night-rate}",
"hint": "{i18n:scada.symbol.measured-hint}",
"group": null,
"type": "value",
"valueType": "DOUBLE",
"trueLabel": null,
"falseLabel": null,
"stateLabel": null,
"defaultGetValueSettings": {
"action": "GET_TIME_SERIES",
"defaultValue": null,
"executeRpc": {
"method": "getState",
"requestTimeout": 5000,
"requestPersistent": false,
"persistentPollingInterval": 1000
},
"getAttribute": {
"scope": null,
"key": "state"
},
"getTimeSeries": {
"key": "nightRate"
},
"getAlarmStatus": {
"severityList": null,
"typeList": null
},
"dataToValue": {
"type": "NONE",
"dataToValueFunction": "/* Should return boolean value */\nreturn data;"
}
},
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": null
},
{
"id": "warning",
"name": "{i18n:scada.symbol.warning}",
"hint": "{i18n:scada.symbol.warning-state-hint}",
"group": "{i18n:scada.symbol.warning-state}",
"type": "value",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": "{i18n:scada.symbol.warning}",
"defaultGetValueSettings": {
"action": "GET_ALARM_STATUS",
"defaultValue": false,
"executeRpc": {
"method": "getState",
"requestTimeout": 5000,
"requestPersistent": false,
"persistentPollingInterval": 1000
},
"getAttribute": {
"scope": null,
"key": "state"
},
"getTimeSeries": {
"key": "state"
},
"getAlarmStatus": {
"severityList": [
"MAJOR",
"MINOR",
"WARNING",
"INDETERMINATE"
],
"typeList": null
},
"dataToValue": {
"type": "NONE",
"dataToValueFunction": "/* Should return boolean value */\nreturn data;",
"compareToValue": true
}
},
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": null
},
{
"id": "warningClick",
"name": "{i18n:scada.symbol.warning-click}",
"hint": "{i18n:scada.symbol.on-click-hint}",
"group": "{i18n:scada.symbol.warning-state}",
"type": "widgetAction",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": null,
"defaultGetValueSettings": null,
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": {
"type": "doNothing",
"targetDashboardStateId": null,
"openRightLayout": false,
"setEntityId": false,
"stateEntityParamName": null
}
},
{
"id": "critical",
"name": "{i18n:scada.symbol.critical}",
"hint": "{i18n:scada.symbol.critical-state-hint}",
"group": "{i18n:scada.symbol.critical-state}",
"type": "value",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": "{i18n:scada.symbol.critical}",
"defaultGetValueSettings": {
"action": "GET_ALARM_STATUS",
"defaultValue": false,
"executeRpc": {
"method": "getState",
"requestTimeout": 5000,
"requestPersistent": false,
"persistentPollingInterval": 1000
},
"getAttribute": {
"scope": null,
"key": "state"
},
"getTimeSeries": {
"key": "state"
},
"getAlarmStatus": {
"severityList": [
"CRITICAL"
],
"typeList": null
},
"dataToValue": {
"type": "NONE",
"dataToValueFunction": "/* Should return boolean value */\nreturn data;",
"compareToValue": true
}
},
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": null
},
{
"id": "criticalClick",
"name": "{i18n:scada.symbol.critical-click}",
"hint": "{i18n:scada.symbol.on-click-hint}",
"group": "{i18n:scada.symbol.critical-state}",
"type": "widgetAction",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": null,
"defaultGetValueSettings": null,
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": {
"type": "doNothing",
"targetDashboardStateId": null,
"openRightLayout": false,
"setEntityId": false,
"stateEntityParamName": null
}
},
{
"id": "criticalAnimation",
"name": "{i18n:scada.symbol.warning-critical-state-animation}",
"hint": "{i18n:scada.symbol.warning-critical-state-animation-hint}",
"group": null,
"type": "value",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": "{i18n:scada.symbol.animation}",
"defaultGetValueSettings": {
"action": "DO_NOTHING",
"defaultValue": false,
"executeRpc": {
"method": "getState",
"requestTimeout": 5000,
"requestPersistent": false,
"persistentPollingInterval": 1000
},
"getAttribute": {
"key": "state",
"scope": null
},
"getTimeSeries": {
"key": "state"
},
"dataToValue": {
"type": "NONE",
"compareToValue": true,
"dataToValueFunction": "/* Should return boolean value */\nreturn data;"
}
},
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": null
},
{
"id": "click",
"name": "{i18n:scada.symbol.on-click}",
"hint": "{i18n:scada.symbol.on-click-hint}",
"group": null,
"type": "widgetAction",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": null,
"defaultGetValueSettings": null,
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": {
"type": "doNothing",
"targetDashboardStateId": null,
"openRightLayout": false,
"setEntityId": false,
"stateEntityParamName": null
}
}
],
"properties": [
{
"id": "runningColor",
"name": "{i18n:scada.symbol.colors}",
"type": "color",
"default": "#FFFFFF",
"subLabel": "{i18n:scada.symbol.running}",
"divider": true,
"disabled": false,
"visible": true
},
{
"id": "stoppedColor",
"name": "{i18n:scada.symbol.colors}",
"type": "color",
"default": "#666666",
"subLabel": "{i18n:scada.symbol.stopped}",
"disabled": false,
"visible": true
},
{
"id": "warningColor",
"name": "{i18n:scada.symbol.alarm-colors}",
"type": "color",
"default": "#FAA405",
"subLabel": "{i18n:scada.symbol.warning}",
"divider": true,
"disabled": false,
"visible": true
},
{
"id": "criticalColor",
"name": "{i18n:scada.symbol.alarm-colors}",
"type": "color",
"default": "#D12730",
"subLabel": "{i18n:scada.symbol.critical}",
"disabled": false,
"visible": true
},
{
"id": "showDayLabel",
"name": "{i18n:scada.symbol.label}",
"group": "{i18n:scada.symbol.day-rate}",
"type": "switch",
"default": true,
"disabled": false,
"visible": true
},
{
"id": "dayLabel",
"name": "{i18n:scada.symbol.label}",
"group": "{i18n:scada.symbol.day-rate}",
"type": "text",
"default": "T1",
"fieldClass": "medium-width",
"disabled": false,
"visible": true
},
{
"id": "dayLabelFont",
"name": "{i18n:scada.symbol.label}",
"group": "{i18n:scada.symbol.day-rate}",
"type": "font",
"default": {
"size": 36,
"sizeUnit": "px",
"family": "Roboto",
"weight": "normal",
"style": "normal"
},
"disabled": false,
"visible": true
},
{
"id": "dayLabelColor",
"name": "{i18n:scada.symbol.label}",
"group": "{i18n:scada.symbol.day-rate}",
"type": "color",
"default": "#000000",
"disabled": false,
"visible": true
},
{
"id": "dayValueFont",
"name": "{i18n:scada.symbol.value}",
"group": "{i18n:scada.symbol.day-rate}",
"type": "font",
"default": {
"size": 48,
"sizeUnit": "px",
"family": "Roboto",
"weight": "normal",
"style": "normal"
},
"disabled": false,
"visible": true
},
{
"id": "dayValueColor",
"name": "{i18n:scada.symbol.value}",
"group": "{i18n:scada.symbol.day-rate}",
"type": "color",
"default": "#002878",
"disabled": false,
"visible": true
},
{
"id": "dayValueBoxBackground",
"name": "{i18n:scada.symbol.value-box-background}",
"group": "{i18n:scada.symbol.day-rate}",
"type": "color",
"default": "#DEDEDE",
"disabled": false,
"visible": true
},
{
"id": "showNightLabel",
"name": "{i18n:scada.symbol.label}",
"group": "{i18n:scada.symbol.night-rate}",
"type": "switch",
"default": true,
"disabled": false,
"visible": true
},
{
"id": "nightLabel",
"name": "{i18n:scada.symbol.label}",
"group": "{i18n:scada.symbol.night-rate}",
"type": "text",
"default": "T2",
"fieldClass": "medium-width",
"disabled": false,
"visible": true
},
{
"id": "nightLabelFont",
"name": "{i18n:scada.symbol.label}",
"group": "{i18n:scada.symbol.night-rate}",
"type": "font",
"default": {
"size": 36,
"sizeUnit": "px",
"family": "Roboto",
"weight": "normal",
"style": "normal"
},
"disabled": false,
"visible": true
},
{
"id": "nightLabelColor",
"name": "{i18n:scada.symbol.label}",
"group": "{i18n:scada.symbol.night-rate}",
"type": "color",
"default": "#000",
"disabled": false,
"visible": true
},
{
"id": "nightValueFont",
"name": "{i18n:scada.symbol.value}",
"group": "{i18n:scada.symbol.night-rate}",
"type": "font",
"default": {
"size": 48,
"sizeUnit": "px",
"family": "Roboto",
"weight": "normal",
"style": "normal"
},
"disabled": false,
"visible": true
},
{
"id": "nightValueColor",
"name": "{i18n:scada.symbol.value}",
"group": "{i18n:scada.symbol.night-rate}",
"type": "color",
"default": "#002878",
"disabled": false,
"visible": true
},
{
"id": "nightValueBoxBackground",
"name": "{i18n:scada.symbol.value-box-background}",
"group": "{i18n:scada.symbol.night-rate}",
"type": "color",
"default": "#DEDEDE",
"disabled": false,
"visible": true
},
{
"id": "showUnits",
"name": "{i18n:scada.symbol.units}",
"type": "switch",
"default": true,
"disabled": false,
"visible": true
},
{
"id": "units",
"name": "{i18n:scada.symbol.units}",
"type": "units",
"default": "kWh",
"disabled": false,
"visible": true
},
{
"id": "unitsFont",
"name": "{i18n:scada.symbol.units}",
"type": "font",
"default": {
"size": 36,
"sizeUnit": "px",
"family": "Roboto",
"weight": "normal",
"style": "normal"
},
"disabled": false,
"visible": true
},
{
"id": "unitsColor",
"name": "{i18n:scada.symbol.units}",
"type": "color",
"default": "#000",
"disabled": false,
"visible": true
}
]
}]]></tb:metadata>
<rect x="1" y="1" width="398" height="398" fill="#fff" stroke="#1A1A1A" stroke-width="2" tb:tag="background"/><rect x="49" y="237" width="302" height="82" rx="3" fill="#DEDEDE" stroke="#1A1A1A" stroke-width="2" tb:tag="value-box-night"/><rect x="49" y="81" width="302" height="82" rx="3" fill="#DEDEDE" stroke="#1A1A1A" stroke-width="2" tb:tag="value-box-day"/><text x="199.70117" y="58.076347" fill="#000000" font-family="Roboto" font-size="34px" font-weight="400" text-anchor="middle" tb:tag="day-label" xml:space="default"><tspan dominant-baseline="start">T1</tspan></text><text x="199.70117" y="214.37646" fill="#000000" font-family="Roboto" font-size="34px" font-weight="400" text-anchor="middle" tb:tag="night-label"><tspan dominant-baseline="start">T2</tspan></text><text x="200.33984" y="139.47266" fill="#002878" font-family="Roboto" font-size="48px" font-weight="400" text-anchor="middle" tb:tag="day-rate" xml:space="default"><tspan dominant-baseline="start">000023</tspan></text><text x="200.33984" y="295.47266" fill="#002878" font-family="Roboto" font-size="48px" font-weight="400" text-anchor="middle" tb:tag="night-rate" xml:space="default"><tspan dominant-baseline="start">000023</tspan></text><text x="199.89453" y="371.67578" fill="#000000" font-family="Roboto" font-size="36px" font-weight="400" text-anchor="middle" tb:tag="units" xml:space="preserve"><tspan dominant-baseline="start">kWh</tspan></text><path d="m134.53-2e-4s-134.53 0-134.53 67v328.36c0 2.6512 3.5818 4.6404 8 4.6404h384c4.418 0 8-1.9892 8-4.6404v-328.36c0-67-132.14-67-132.14-67h-67.858zm134.14 81.2c-2.5774 0-4.6666 1.2536-4.6666 2.8v300.4c0 1.5464 2.0894 2.8 4.6666 2.8h29.332c2.5774 0 4.6666-1.2536 4.6666-2.8v-300.4c0-1.5464-2.0894-2.8-4.6666-2.8z" fill-opacity="0" tb:tag="clickArea"/><g fill="#d12730" style="display: none;" tb:tag="critical">
<rect width="84" height="84" rx="4" fill="#fff" style=""/>
<rect width="84" height="84" rx="4" style=""/>
<rect x="2" y="2" width="80" height="80" rx="2" stroke="#000" stroke-opacity=".87" stroke-width="4" style=""/>
<path d="m44.559 27.562-0.4688 20.059h-4.0234l-0.4883-20.059zm-5.1172 26.211c0-0.7161 0.2344-1.3151 0.7031-1.7968 0.4818-0.4948 1.1459-0.7422 1.9922-0.7422 0.8334 0 1.4909 0.2474 1.9727 0.7422 0.4817 0.4817 0.7226 1.0807 0.7226 1.7968 0 0.6901-0.2409 1.2826-0.7226 1.7774-0.4818 0.4818-1.1393 0.7226-1.9727 0.7226-0.8463 0-1.5104-0.2408-1.9922-0.7226-0.4687-0.4948-0.7031-1.0873-0.7031-1.7774z" fill="#000" fill-opacity=".87" style=""/>
</g><g fill="#faa405" style="display: none;" tb:tag="warning">
<path d="m35.955 2.2112c1.4741-2.9482 5.6813-2.9482 7.1554 0l35.528 71.056c1.3298 2.6596-0.6042 5.7889-3.5777 5.7889h-71.056c-2.9735 0-4.9075-3.1292-3.5777-5.7889z" fill="#fff" style=""/>
<path d="m35.955 2.2112c1.4741-2.9482 5.6813-2.9482 7.1554 0l35.528 71.056c1.3298 2.6596-0.6042 5.7889-3.5777 5.7889h-71.056c-2.9735 0-4.9075-3.1292-3.5777-5.7889z" style=""/>
<path d="m37.72 3.1061c0.7371-1.4741 2.8407-1.4741 3.5778-1e-5l35.528 71.056c0.6649 1.3298-0.3021 2.8944-1.7888 2.8944h-71.056c-1.4868 0-2.4538-1.5646-1.7889-2.8944z" stroke="#000" stroke-opacity=".87" stroke-width="4" style=""/>
<path d="m42.092 32.618-0.4688 20.059h-4.0234l-0.4883-20.059zm-5.1172 26.211c0-0.7161 0.2344-1.3151 0.7031-1.7968 0.4818-0.4948 1.1459-0.7422 1.9922-0.7422 0.8334 0 1.4909 0.2474 1.9727 0.7422 0.4817 0.4817 0.7226 1.0807 0.7226 1.7968 0 0.6901-0.2409 1.2826-0.7226 1.7774-0.4818 0.4818-1.1393 0.7226-1.9727 0.7226-0.8463 0-1.5104-0.2408-1.9922-0.7226-0.4687-0.4948-0.7031-1.0873-0.7031-1.7774z" fill="#000" fill-opacity=".87" style=""/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 22 KiB

378
application/src/main/data/json/system/scada_symbols/vertical-energy-system-controller-hp.svg

@ -0,0 +1,378 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:tb="https://thingsboard.io/svg" width="400" height="600" fill="none" version="1.1" viewBox="0 0 400 600"><tb:metadata xmlns=""><![CDATA[{
"title": "HP Vertical energy systems controller",
"description": "Vertical energy systems controller with various states.",
"searchTags": [
"energy",
"power",
"monitoring"
],
"widgetSizeX": 2,
"widgetSizeY": 3,
"tags": [
{
"tag": "background",
"stateRenderFunction": "var color = ctx.properties.disconnectedColor;\nif (ctx.values.connected) {\n color = ctx.properties.connectedColor;\n}\nelement.attr({fill: color});",
"actions": null
},
{
"tag": "clickArea",
"stateRenderFunction": null,
"actions": {
"click": {
"actionFunction": "ctx.api.callAction(event, 'click');"
}
}
},
{
"tag": "critical",
"stateRenderFunction": "element.attr({fill: ctx.properties.criticalColor});\nif (ctx.values.critical) {\n element.show();\n} else {\n element.hide();\n}\n\nvar elementCriticalAnimation = element.remember('criticalAnimation');\nvar criticalAnimation = ctx.values.critical && ctx.values.criticalAnimation;\n\nif (elementCriticalAnimation !== criticalAnimation) {\n element.remember('criticalAnimation', criticalAnimation);\n if (criticalAnimation) {\n ctx.api.cssAnimate(element, 500).attr({opacity: 0.15}).loop(0, true);\n } else {\n ctx.api.resetCssAnimation(element);\n }\n}\n\n",
"actions": {
"click": {
"actionFunction": "ctx.api.callAction(event, 'criticalClick');"
}
}
},
{
"tag": "indicator",
"stateRenderFunction": "var color = ctx.properties.disconnectedIndicatorColor;\nif (ctx.values.connected) {\n color = ctx.properties.connectedIndicatorColor;\n}\nelement.attr({fill: color});",
"actions": null
},
{
"tag": "label",
"stateRenderFunction": "ctx.api.font(element, ctx.properties.labelFont, ctx.properties.labelColor);\n ctx.api.text(element, ctx.properties.label);",
"actions": null
},
{
"tag": "warning",
"stateRenderFunction": "element.attr({fill: ctx.properties.warningColor});\nvar warning = ctx.values.warning && !(ctx.values.warning && ctx.values.critical)\nif (warning) {\n element.show();\n} else {\n element.hide();\n}\n\nvar elementCriticalAnimation = element.remember('criticalAnimation');\nvar criticalAnimation = warning && ctx.values.criticalAnimation;\n\nif (elementCriticalAnimation !== criticalAnimation) {\n element.remember('criticalAnimation', criticalAnimation);\n if (criticalAnimation) {\n ctx.api.cssAnimate(element, 500).attr({opacity: 0.15}).loop(0, true);\n } else {\n ctx.api.resetCssAnimation(element);\n }\n}\n",
"actions": {
"click": {
"actionFunction": "ctx.api.callAction(event, 'warningClick');"
}
}
}
],
"behavior": [
{
"id": "connected",
"name": "{i18n:scada.symbol.connected}",
"hint": "{i18n:scada.symbol.connected-hint}",
"group": null,
"type": "value",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": "{i18n:scada.symbol.connected}",
"defaultGetValueSettings": {
"action": "GET_ATTRIBUTE",
"defaultValue": false,
"executeRpc": {
"method": "getState",
"requestTimeout": 5000,
"requestPersistent": false,
"persistentPollingInterval": 1000
},
"getAttribute": {
"scope": "SHARED_SCOPE",
"key": "connected"
},
"getTimeSeries": {
"key": "state"
},
"getAlarmStatus": {
"severityList": null,
"typeList": null
},
"dataToValue": {
"type": "NONE",
"dataToValueFunction": "/* Should return boolean value */\nreturn data;",
"compareToValue": true
}
},
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": null
},
{
"id": "warning",
"name": "{i18n:scada.symbol.warning}",
"hint": "{i18n:scada.symbol.warning-state-hint}",
"group": "{i18n:scada.symbol.warning-state}",
"type": "value",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": "{i18n:scada.symbol.warning}",
"defaultGetValueSettings": {
"action": "GET_ALARM_STATUS",
"defaultValue": false,
"executeRpc": {
"method": "getState",
"requestTimeout": 5000,
"requestPersistent": false,
"persistentPollingInterval": 1000
},
"getAttribute": {
"scope": null,
"key": "state"
},
"getTimeSeries": {
"key": "state"
},
"getAlarmStatus": {
"severityList": [
"MAJOR",
"MINOR",
"WARNING",
"INDETERMINATE"
],
"typeList": null
},
"dataToValue": {
"type": "NONE",
"dataToValueFunction": "/* Should return boolean value */\nreturn data;",
"compareToValue": true
}
},
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": null
},
{
"id": "warningClick",
"name": "{i18n:scada.symbol.warning-click}",
"hint": "{i18n:scada.symbol.on-click-hint}",
"group": "{i18n:scada.symbol.warning-state}",
"type": "widgetAction",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": null,
"defaultGetValueSettings": null,
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": {
"type": "doNothing",
"targetDashboardStateId": null,
"openRightLayout": false,
"setEntityId": false,
"stateEntityParamName": null
}
},
{
"id": "critical",
"name": "{i18n:scada.symbol.critical}",
"hint": "{i18n:scada.symbol.critical-state-hint}",
"group": "{i18n:scada.symbol.critical-state}",
"type": "value",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": "{i18n:scada.symbol.critical}",
"defaultGetValueSettings": {
"action": "GET_ALARM_STATUS",
"defaultValue": false,
"executeRpc": {
"method": "getState",
"requestTimeout": 5000,
"requestPersistent": false,
"persistentPollingInterval": 1000
},
"getAttribute": {
"scope": null,
"key": "state"
},
"getTimeSeries": {
"key": "state"
},
"getAlarmStatus": {
"severityList": [
"CRITICAL"
],
"typeList": null
},
"dataToValue": {
"type": "NONE",
"dataToValueFunction": "/* Should return boolean value */\nreturn data;",
"compareToValue": true
}
},
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": null
},
{
"id": "criticalClick",
"name": "{i18n:scada.symbol.critical-click}",
"hint": "{i18n:scada.symbol.on-click-hint}",
"group": "{i18n:scada.symbol.critical-state}",
"type": "widgetAction",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": null,
"defaultGetValueSettings": null,
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": {
"type": "doNothing",
"targetDashboardStateId": null,
"openRightLayout": false,
"setEntityId": false,
"stateEntityParamName": null
}
},
{
"id": "criticalAnimation",
"name": "{i18n:scada.symbol.warning-critical-state-animation}",
"hint": "{i18n:scada.symbol.warning-critical-state-animation-hint}",
"group": null,
"type": "value",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": "{i18n:scada.symbol.animation}",
"defaultGetValueSettings": {
"action": "DO_NOTHING",
"defaultValue": false,
"executeRpc": {
"method": "getState",
"requestTimeout": 5000,
"requestPersistent": false,
"persistentPollingInterval": 1000
},
"getAttribute": {
"key": "state",
"scope": null
},
"getTimeSeries": {
"key": "state"
},
"dataToValue": {
"type": "NONE",
"compareToValue": true,
"dataToValueFunction": "/* Should return boolean value */\nreturn data;"
}
},
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": null
},
{
"id": "click",
"name": "{i18n:scada.symbol.on-click}",
"hint": "{i18n:scada.symbol.on-click-hint}",
"group": null,
"type": "widgetAction",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": null,
"defaultGetValueSettings": null,
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": {
"type": "doNothing",
"targetDashboardStateId": null,
"openRightLayout": false,
"setEntityId": false,
"stateEntityParamName": null
}
}
],
"properties": [
{
"id": "connectedColor",
"name": "{i18n:scada.symbol.colors}",
"type": "color",
"default": "#FFFFFF",
"subLabel": "{i18n:scada.symbol.connected}",
"divider": true,
"disabled": false,
"visible": true
},
{
"id": "disconnectedColor",
"name": "{i18n:scada.symbol.colors}",
"type": "color",
"default": "#666666",
"subLabel": "{i18n:scada.symbol.disconnected}",
"disabled": false,
"visible": true
},
{
"id": "connectedIndicatorColor",
"name": "{i18n:scada.symbol.indicator}",
"type": "color",
"default": "#198038",
"subLabel": "{i18n:scada.symbol.connected}",
"divider": true,
"disabled": false,
"visible": true
},
{
"id": "disconnectedIndicatorColor",
"name": "{i18n:scada.symbol.indicator}",
"type": "color",
"default": "#DEDEDE",
"subLabel": "{i18n:scada.symbol.disconnected}",
"disabled": false,
"visible": true
},
{
"id": "label",
"name": "{i18n:scada.symbol.label}",
"type": "text",
"default": "Connected",
"fieldClass": "medium-width",
"disabled": false,
"visible": true
},
{
"id": "labelFont",
"name": "{i18n:scada.symbol.label}",
"type": "font",
"default": {
"size": 30,
"sizeUnit": "px",
"family": "Roboto",
"weight": "normal",
"style": "normal"
},
"disabled": false,
"visible": true
},
{
"id": "labelColor",
"name": "{i18n:scada.symbol.label}",
"type": "color",
"default": "#000",
"disabled": false,
"visible": true
},
{
"id": "warningColor",
"name": "{i18n:scada.symbol.alarm-colors}",
"type": "color",
"default": "#FAA405",
"subLabel": "{i18n:scada.symbol.warning}",
"divider": true,
"disabled": false,
"visible": true
},
{
"id": "criticalColor",
"name": "{i18n:scada.symbol.alarm-colors}",
"type": "color",
"default": "#D12730",
"subLabel": "{i18n:scada.symbol.critical}",
"disabled": false,
"visible": true
}
]
}]]></tb:metadata>
<rect x="17" y="1" width="366" height="598" rx="5" fill="#fff" stroke="#1A1A1A" stroke-width="2" tb:tag="background"/><rect transform="matrix(1 0 0 -1 382 173)" x="1" y="-1" width="16" height="148" rx="1" fill="#999" stroke="#1A1A1A" stroke-width="2"/><rect transform="matrix(1 0 0 -1 0 173)" x="1" y="-1" width="16" height="148" rx="1" fill="#999" stroke="#1A1A1A" stroke-width="2"/><rect transform="matrix(1 0 0 -1 382 373)" x="1" y="-1" width="16" height="148" rx="1" fill="#999" stroke="#1A1A1A" stroke-width="2"/><rect transform="matrix(1 0 0 -1 382 573)" x="1" y="-1" width="16" height="148" rx="1" fill="#999" stroke="#1A1A1A" stroke-width="2"/><rect transform="matrix(1 0 0 -1 0 573)" x="1" y="-1" width="16" height="148" rx="1" fill="#999" stroke="#1A1A1A" stroke-width="2"/><circle cx="66" cy="86" r="10" fill="#198038" tb:tag="indicator"/><text x="83.31543" y="89.589844" fill="#000000" font-family="Roboto" font-size="30px" font-weight="400" tb:tag="label" xml:space="preserve"><tspan dominant-baseline="middle">Connected</tspan></text><path d="m134.53 0s-134.53 0-134.53 100.5v492.54c0 3.9768 3.5818 6.9604 8 6.9604h384c4.418 0 8-2.9838 8-6.9604v-492.54c0-100.5-132.14-100.5-132.14-100.5h-67.86zm134.14 121.8c-2.5774 0-4.6666 1.8804-4.6666 4.2v450.6c0 2.3196 2.0894 4.2 4.6666 4.2h29.332c2.5774 0 4.6666-1.8804 4.6666-4.2v-450.6c0-2.3196-2.0894-4.2-4.6666-4.2z" fill-opacity="0" tb:tag="clickArea"/><g transform="translate(0,516)" fill="#d12730" style="display: none;" tb:tag="critical">
<rect width="84" height="84" rx="4" fill="#fff" style=""/>
<rect width="84" height="84" rx="4" style=""/>
<rect x="2" y="2" width="80" height="80" rx="2" stroke="#000" stroke-opacity=".87" stroke-width="4" style=""/>
<path d="m44.559 27.562-0.4688 20.059h-4.0234l-0.4883-20.059zm-5.1172 26.211c0-0.7161 0.2344-1.3151 0.7031-1.7968 0.4818-0.4948 1.1459-0.7422 1.9922-0.7422 0.8334 0 1.4909 0.2474 1.9727 0.7422 0.4817 0.4817 0.7226 1.0807 0.7226 1.7968 0 0.6901-0.2409 1.2826-0.7226 1.7774-0.4818 0.4818-1.1393 0.7226-1.9727 0.7226-0.8463 0-1.5104-0.2408-1.9922-0.7226-0.4687-0.4948-0.7031-1.0873-0.7031-1.7774z" fill="#000" fill-opacity=".87" style=""/>
</g><g transform="translate(0 520.94)" fill="#faa405" style="display: none;" tb:tag="warning">
<path d="m35.955 2.2112c1.4741-2.9482 5.6813-2.9482 7.1554 0l35.528 71.056c1.3298 2.6596-0.6042 5.7889-3.5777 5.7889h-71.056c-2.9735 0-4.9075-3.1292-3.5777-5.7889z" fill="#fff" style=""/>
<path d="m35.955 2.2112c1.4741-2.9482 5.6813-2.9482 7.1554 0l35.528 71.056c1.3298 2.6596-0.6042 5.7889-3.5777 5.7889h-71.056c-2.9735 0-4.9075-3.1292-3.5777-5.7889z" style=""/>
<path d="m37.72 3.1061c0.7371-1.4741 2.8407-1.4741 3.5778-1e-5l35.528 71.056c0.6649 1.3298-0.3021 2.8944-1.7888 2.8944h-71.056c-1.4868 0-2.4538-1.5646-1.7889-2.8944z" stroke="#000" stroke-opacity=".87" stroke-width="4" style=""/>
<path d="m42.092 32.618-0.4688 20.059h-4.0234l-0.4883-20.059zm-5.1172 26.211c0-0.7161 0.2344-1.3151 0.7031-1.7968 0.4818-0.4948 1.1459-0.7422 1.9922-0.7422 0.8334 0 1.4909 0.2474 1.9727 0.7422 0.4817 0.4817 0.7226 1.0807 0.7226 1.7968 0 0.6901-0.2409 1.2826-0.7226 1.7774-0.4818 0.4818-1.1393 0.7226-1.9727 0.7226-0.8463 0-1.5104-0.2408-1.9922-0.7226-0.4687-0.4948-0.7031-1.0873-0.7031-1.7774z" fill="#000" fill-opacity=".87" style=""/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 15 KiB

439
application/src/main/data/json/system/scada_symbols/voltage-relay-hp.svg

@ -0,0 +1,439 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:tb="https://thingsboard.io/svg" width="200" height="400" fill="none" version="1.1" viewBox="0 0 200 400"><tb:metadata xmlns=""><![CDATA[{
"title": "HP Voltage relay",
"description": "One phase voltage relay with various states.",
"searchTags": [
"energy",
"power",
"protection"
],
"widgetSizeX": 1,
"widgetSizeY": 2,
"tags": [
{
"tag": "background",
"stateRenderFunction": "var color = ctx.properties.stoppedColor;\nif (ctx.values.running) {\n color = ctx.properties.runningColor;\n}\nelement.attr({fill: color});",
"actions": null
},
{
"tag": "clickArea",
"stateRenderFunction": null,
"actions": {
"click": {
"actionFunction": "ctx.api.callAction(event, 'click');"
}
}
},
{
"tag": "critical",
"stateRenderFunction": "element.attr({fill: ctx.properties.criticalColor});\nif (ctx.values.critical) {\n element.show();\n} else {\n element.hide();\n}\n\nvar elementCriticalAnimation = element.remember('criticalAnimation');\nvar criticalAnimation = ctx.values.critical && ctx.values.criticalAnimation;\n\nif (elementCriticalAnimation !== criticalAnimation) {\n element.remember('criticalAnimation', criticalAnimation);\n if (criticalAnimation) {\n ctx.api.cssAnimate(element, 500).attr({opacity: 0.15}).loop(0, true);\n } else {\n ctx.api.resetCssAnimation(element);\n }\n}\n\n",
"actions": {
"click": {
"actionFunction": "ctx.api.callAction(event, 'criticalClick');"
}
}
},
{
"tag": "units",
"stateRenderFunction": "if (ctx.properties.showUnits) {\n element.show();\n ctx.api.font(element, ctx.properties.unitsFont, ctx.properties.unitsColor);\n ctx.api.text(element, ctx.properties.units);\n} else {\n element.hide();\n}",
"actions": null
},
{
"tag": "value",
"stateRenderFunction": "if (ctx.values.running) {\n element.show();\n ctx.api.font(element, ctx.properties.currentVoltageFont, ctx.properties.currentVoltageColor);\n ctx.api.text(element, ctx.api.formatValue(ctx.values.voltage, 0, null, 0));\n} else {\n element.hide();\n}",
"actions": null
},
{
"tag": "value-box",
"stateRenderFunction": "var color = ctx.properties.stoppedColor;\nif (ctx.values.running) {\n color = ctx.properties.valueBoxBackground;\n}\nelement.attr({fill: color});",
"actions": null
},
{
"tag": "warning",
"stateRenderFunction": "element.attr({fill: ctx.properties.warningColor});\nvar warning = ctx.values.warning && !(ctx.values.warning && ctx.values.critical)\nif (warning) {\n element.show();\n} else {\n element.hide();\n}\n\nvar elementCriticalAnimation = element.remember('criticalAnimation');\nvar criticalAnimation = warning && ctx.values.criticalAnimation;\n\nif (elementCriticalAnimation !== criticalAnimation) {\n element.remember('criticalAnimation', criticalAnimation);\n if (criticalAnimation) {\n ctx.api.cssAnimate(element, 500).attr({opacity: 0.15}).loop(0, true);\n } else {\n ctx.api.resetCssAnimation(element);\n }\n}\n",
"actions": {
"click": {
"actionFunction": "ctx.api.callAction(event, 'warningClick');"
}
}
}
],
"behavior": [
{
"id": "running",
"name": "{i18n:scada.symbol.running}",
"hint": "{i18n:scada.symbol.running-hint}",
"group": null,
"type": "value",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": "{i18n:scada.symbol.running}",
"defaultGetValueSettings": {
"action": "GET_ATTRIBUTE",
"defaultValue": false,
"executeRpc": {
"method": "getState",
"requestTimeout": 5000,
"requestPersistent": false,
"persistentPollingInterval": 1000
},
"getAttribute": {
"scope": "SHARED_SCOPE",
"key": "running"
},
"getTimeSeries": {
"key": "state"
},
"getAlarmStatus": {
"severityList": null,
"typeList": null
},
"dataToValue": {
"type": "NONE",
"dataToValueFunction": "/* Should return boolean value */\nreturn data;",
"compareToValue": true
}
},
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": null
},
{
"id": "voltage",
"name": "{i18n:scada.symbol.voltage}",
"hint": "{i18n:scada.symbol.voltage-hint}",
"group": null,
"type": "value",
"valueType": "DOUBLE",
"trueLabel": null,
"falseLabel": null,
"stateLabel": null,
"defaultGetValueSettings": {
"action": "GET_TIME_SERIES",
"defaultValue": null,
"executeRpc": {
"method": "getState",
"requestTimeout": 5000,
"requestPersistent": false,
"persistentPollingInterval": 1000
},
"getAttribute": {
"scope": null,
"key": "state"
},
"getTimeSeries": {
"key": "voltage"
},
"getAlarmStatus": {
"severityList": null,
"typeList": null
},
"dataToValue": {
"type": "NONE",
"dataToValueFunction": "/* Should return boolean value */\nreturn data;"
}
},
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": null
},
{
"id": "warning",
"name": "{i18n:scada.symbol.warning}",
"hint": "{i18n:scada.symbol.warning-state-hint}",
"group": "{i18n:scada.symbol.warning-state}",
"type": "value",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": "{i18n:scada.symbol.warning}",
"defaultGetValueSettings": {
"action": "GET_ALARM_STATUS",
"defaultValue": false,
"executeRpc": {
"method": "getState",
"requestTimeout": 5000,
"requestPersistent": false,
"persistentPollingInterval": 1000
},
"getAttribute": {
"scope": null,
"key": "state"
},
"getTimeSeries": {
"key": "state"
},
"getAlarmStatus": {
"severityList": [
"MAJOR",
"MINOR",
"WARNING",
"INDETERMINATE"
],
"typeList": null
},
"dataToValue": {
"type": "NONE",
"dataToValueFunction": "/* Should return boolean value */\nreturn data;",
"compareToValue": true
}
},
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": null
},
{
"id": "warningClick",
"name": "{i18n:scada.symbol.warning-click}",
"hint": "{i18n:scada.symbol.on-click-hint}",
"group": "{i18n:scada.symbol.warning-state}",
"type": "widgetAction",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": null,
"defaultGetValueSettings": null,
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": {
"type": "doNothing",
"targetDashboardStateId": null,
"openRightLayout": false,
"setEntityId": false,
"stateEntityParamName": null
}
},
{
"id": "critical",
"name": "{i18n:scada.symbol.critical}",
"hint": "{i18n:scada.symbol.critical-state-hint}",
"group": "{i18n:scada.symbol.critical-state}",
"type": "value",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": "{i18n:scada.symbol.critical}",
"defaultGetValueSettings": {
"action": "GET_ALARM_STATUS",
"defaultValue": false,
"executeRpc": {
"method": "getState",
"requestTimeout": 5000,
"requestPersistent": false,
"persistentPollingInterval": 1000
},
"getAttribute": {
"scope": null,
"key": "state"
},
"getTimeSeries": {
"key": "state"
},
"getAlarmStatus": {
"severityList": [
"CRITICAL"
],
"typeList": null
},
"dataToValue": {
"type": "NONE",
"dataToValueFunction": "/* Should return boolean value */\nreturn data;",
"compareToValue": true
}
},
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": null
},
{
"id": "criticalClick",
"name": "{i18n:scada.symbol.critical-click}",
"hint": "{i18n:scada.symbol.on-click-hint}",
"group": "{i18n:scada.symbol.critical-state}",
"type": "widgetAction",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": null,
"defaultGetValueSettings": null,
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": {
"type": "doNothing",
"targetDashboardStateId": null,
"openRightLayout": false,
"setEntityId": false,
"stateEntityParamName": null
}
},
{
"id": "criticalAnimation",
"name": "{i18n:scada.symbol.warning-critical-state-animation}",
"hint": "{i18n:scada.symbol.warning-critical-state-animation-hint}",
"group": null,
"type": "value",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": "{i18n:scada.symbol.animation}",
"defaultGetValueSettings": {
"action": "DO_NOTHING",
"defaultValue": false,
"executeRpc": {
"method": "getState",
"requestTimeout": 5000,
"requestPersistent": false,
"persistentPollingInterval": 1000
},
"getAttribute": {
"key": "state",
"scope": null
},
"getTimeSeries": {
"key": "state"
},
"dataToValue": {
"type": "NONE",
"compareToValue": true,
"dataToValueFunction": "/* Should return boolean value */\nreturn data;"
}
},
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": null
},
{
"id": "click",
"name": "{i18n:scada.symbol.on-click}",
"hint": "{i18n:scada.symbol.on-click-hint}",
"group": null,
"type": "widgetAction",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": null,
"defaultGetValueSettings": null,
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": {
"type": "doNothing",
"targetDashboardStateId": null,
"openRightLayout": false,
"setEntityId": false,
"stateEntityParamName": null
}
}
],
"properties": [
{
"id": "runningColor",
"name": "{i18n:scada.symbol.colors}",
"type": "color",
"default": "#FFFFFF",
"subLabel": "{i18n:scada.symbol.running}",
"divider": true,
"disabled": false,
"visible": true
},
{
"id": "stoppedColor",
"name": "{i18n:scada.symbol.colors}",
"type": "color",
"default": "#666666",
"subLabel": "{i18n:scada.symbol.stopped}",
"disabled": false,
"visible": true
},
{
"id": "valueBoxBackground",
"name": "{i18n:scada.symbol.value-box-background}",
"type": "color",
"default": "#DEDEDE",
"disabled": false,
"visible": true
},
{
"id": "currentVoltageFont",
"name": "{i18n:scada.symbol.current-voltage-color}",
"type": "font",
"default": {
"size": 32,
"sizeUnit": "px",
"family": "Roboto",
"weight": "400",
"style": "normal"
},
"disabled": false,
"visible": true
},
{
"id": "currentVoltageColor",
"name": "{i18n:scada.symbol.current-voltage-color}",
"type": "color",
"default": "#002878",
"disabled": false,
"visible": true
},
{
"id": "showUnits",
"name": "{i18n:scada.symbol.units}",
"type": "switch",
"default": true,
"disabled": false,
"visible": true
},
{
"id": "units",
"name": "{i18n:scada.symbol.units}",
"type": "units",
"default": "V",
"disabled": false,
"visible": true
},
{
"id": "unitsFont",
"name": "{i18n:scada.symbol.units}",
"type": "font",
"default": {
"size": 24,
"sizeUnit": "px",
"family": "Roboto",
"weight": "500",
"style": "normal"
},
"disabled": false,
"visible": true
},
{
"id": "unitsColor",
"name": "{i18n:scada.symbol.units}",
"type": "color",
"default": "#000000",
"disabled": false,
"visible": true
},
{
"id": "warningColor",
"name": "{i18n:scada.symbol.alarm-colors}",
"type": "color",
"default": "#FAA405",
"subLabel": "{i18n:scada.symbol.warning}",
"divider": true,
"disabled": false,
"visible": true
},
{
"id": "criticalColor",
"name": "{i18n:scada.symbol.alarm-colors}",
"type": "color",
"default": "#D12730",
"subLabel": "{i18n:scada.symbol.critical}",
"disabled": false,
"visible": true
}
]
}]]></tb:metadata>
<rect width="200" height="400" fill="#fff" tb:tag="background"/><rect x="1" y="1" width="198" height="398" stroke="#000" stroke-opacity=".87" stroke-width="2"/><circle cx="100" cy="50" r="19" stroke="#000" stroke-opacity=".87" stroke-width="2"/><circle cx="52" cy="50" r="19" stroke="#000" stroke-opacity=".87" stroke-width="2"/><circle cx="148" cy="50" r="19" stroke="#000" stroke-opacity=".87" stroke-width="2"/><circle cx="100" cy="350" r="19" stroke="#000" stroke-opacity=".87" stroke-width="2"/><circle cx="52" cy="350" r="19" stroke="#000" stroke-opacity=".87" stroke-width="2"/><circle cx="148" cy="350" r="19" stroke="#000" stroke-opacity=".87" stroke-width="2"/><rect x="36" y="137" width="128" height="80" rx="2" fill="#DEDEDE" tb:tag="value-box"/><rect x="37" y="138" width="126" height="78" rx="1" stroke="#000" stroke-opacity=".87" stroke-width="2"/><text x="99.890625" y="190.70906" fill="#002878" font-family="Roboto" font-size="32px" font-weight="400" text-anchor="middle" tb:tag="value" xml:space="preserve"><tspan dominant-baseline="start">220</tspan></text><text x="99.643097" y="257.79694" fill="black" font-family="Roboto" font-size="28px" font-weight="400" text-anchor="middle" tb:tag="units" xml:space="preserve"><tspan dominant-baseline="start">v</tspan></text><path d="m67.265 0s-67.265 0-67.265 67v328.36c0 2.6512 1.7909 4.6404 4 4.6404h192c2.209 0 4-1.9892 4-4.6404v-328.36c0-67-66.07-67-66.07-67h-33.929zm67.07 81.2c-1.2887 0-2.3333 1.2536-2.3333 2.8v300.4c0 1.5464 1.0447 2.8 2.3333 2.8h14.666c1.2887 0 2.3333-1.2536 2.3333-2.8v-300.4c0-1.5464-1.0447-2.8-2.3333-2.8z" fill="#000" fill-opacity="0" tb:tag="clickArea"/><g fill="#d12730" style="display: none;" tb:tag="critical">
<rect width="84" height="84" rx="4" fill="#fff" style=""/>
<rect width="84" height="84" rx="4" style=""/>
<rect x="2" y="2" width="80" height="80" rx="2" stroke="#000" stroke-opacity=".87" stroke-width="4" style=""/>
<path d="m44.559 27.562-0.4688 20.059h-4.0234l-0.4883-20.059zm-5.1172 26.211c0-0.7161 0.2344-1.3151 0.7031-1.7968 0.4818-0.4948 1.1459-0.7422 1.9922-0.7422 0.8334 0 1.4909 0.2474 1.9727 0.7422 0.4817 0.4817 0.7226 1.0807 0.7226 1.7968 0 0.6901-0.2409 1.2826-0.7226 1.7774-0.4818 0.4818-1.1393 0.7226-1.9727 0.7226-0.8463 0-1.5104-0.2408-1.9922-0.7226-0.4687-0.4948-0.7031-1.0873-0.7031-1.7774z" fill="#000" fill-opacity=".87" style=""/>
</g><g fill="#faa405" style="display: none;" tb:tag="warning">
<path d="m35.955 2.2112c1.4741-2.9482 5.6813-2.9482 7.1554 0l35.528 71.056c1.3298 2.6596-0.6042 5.7889-3.5777 5.7889h-71.056c-2.9735 0-4.9075-3.1292-3.5777-5.7889z" fill="#fff" style=""/>
<path d="m35.955 2.2112c1.4741-2.9482 5.6813-2.9482 7.1554 0l35.528 71.056c1.3298 2.6596-0.6042 5.7889-3.5777 5.7889h-71.056c-2.9735 0-4.9075-3.1292-3.5777-5.7889z" style=""/>
<path d="m37.72 3.1061c0.7371-1.4741 2.8407-1.4741 3.5778-1e-5l35.528 71.056c0.6649 1.3298-0.3021 2.8944-1.7888 2.8944h-71.056c-1.4868 0-2.4538-1.5646-1.7889-2.8944z" stroke="#000" stroke-opacity=".87" stroke-width="4" style=""/>
<path d="m42.092 32.618-0.4688 20.059h-4.0234l-0.4883-20.059zm-5.1172 26.211c0-0.7161 0.2344-1.3151 0.7031-1.7968 0.4818-0.4948 1.1459-0.7422 1.9922-0.7422 0.8334 0 1.4909 0.2474 1.9727 0.7422 0.4817 0.4817 0.7226 1.0807 0.7226 1.7968 0 0.6901-0.2409 1.2826-0.7226 1.7774-0.4818 0.4818-1.1393 0.7226-1.9727 0.7226-0.8463 0-1.5104-0.2408-1.9922-0.7226-0.4687-0.4948-0.7031-1.0873-0.7031-1.7774z" fill="#000" fill-opacity=".87" style=""/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 17 KiB

584
application/src/main/data/json/system/scada_symbols/voltage-stabilizer-hp.svg

@ -0,0 +1,584 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:tb="https://thingsboard.io/svg" width="400" height="200" fill="none" version="1.1" viewBox="0 0 400 200"><tb:metadata xmlns=""><![CDATA[{
"title": "HP Voltage stabilizer",
"description": "Voltage stabilizer with various states.",
"searchTags": [
"power",
"energy",
"protection"
],
"widgetSizeX": 2,
"widgetSizeY": 1,
"tags": [
{
"tag": "background",
"stateRenderFunction": "var color = ctx.properties.stoppedColor;\nif (ctx.values.operatingMode === 1) {\n color = ctx.properties.runningColor;\n} else if (ctx.values.operatingMode === 2) {\n color = ctx.properties.bypassColor;\n}\nelement.attr({fill: color});",
"actions": null
},
{
"tag": "clickArea",
"stateRenderFunction": null,
"actions": {
"click": {
"actionFunction": "ctx.api.callAction(event, 'click');"
}
}
},
{
"tag": "critical",
"stateRenderFunction": "element.attr({fill: ctx.properties.criticalColor});\nif (ctx.values.critical) {\n element.show();\n} else {\n element.hide();\n}\n\nvar elementCriticalAnimation = element.remember('criticalAnimation');\nvar criticalAnimation = ctx.values.critical && ctx.values.criticalAnimation;\n\nif (elementCriticalAnimation !== criticalAnimation) {\n element.remember('criticalAnimation', criticalAnimation);\n if (criticalAnimation) {\n ctx.api.cssAnimate(element, 500).attr({opacity: 0.15}).loop(0, true);\n } else {\n ctx.api.resetCssAnimation(element);\n }\n}\n\n",
"actions": {
"click": {
"actionFunction": "ctx.api.callAction(event, 'criticalClick');"
}
}
},
{
"tag": "in-label",
"stateRenderFunction": "if (ctx.properties.showInputLabel) {\n element.show();\n ctx.api.font(element, ctx.properties.inputLabelFont, ctx.properties.inputLabelColor);\n ctx.api.text(element, ctx.properties.inputLabel);\n} else {\n element.hide();\n}",
"actions": null
},
{
"tag": "in-value",
"stateRenderFunction": "if (ctx.values.operatingMode === 1) {\n element.show();\n ctx.api.font(element, ctx.properties.inputValutFont, ctx.properties.inputValueColor);\n ctx.api.text(element, ctx.api.formatValue(ctx.values.inputVoltage, 0, null, 0));\n} else {\n element.hide();\n}\n",
"actions": null
},
{
"tag": "in-value-box",
"stateRenderFunction": "var color = ctx.properties.stoppedColor;\nif (ctx.values.operatingMode === 1) {\n color = ctx.properties.inputValueBoxBackground;\n} else if (ctx.values.operatingMode === 2) {\n color = ctx.properties.bypassColor;\n}\nelement.attr({fill: color});",
"actions": null
},
{
"tag": "out-label",
"stateRenderFunction": "if (ctx.properties.showOutputLabel) {\n element.show();\n ctx.api.font(element, ctx.properties.outputLabelFont, ctx.properties.outputLabelColor);\n ctx.api.text(element, ctx.properties.outputLabel);\n} else {\n element.hide();\n}",
"actions": null
},
{
"tag": "out-value",
"stateRenderFunction": "if (ctx.values.operatingMode === 1) {\n element.show();\n ctx.api.font(element, ctx.properties.outputValueFont, ctx.properties.outputValueColor);\n ctx.api.text(element, ctx.api.formatValue(ctx.values.outputVoltage, 0, null, 0));\n} else {\n element.hide();\n}\n",
"actions": null
},
{
"tag": "out-value-box",
"stateRenderFunction": "var color = ctx.properties.stoppedColor;\nif (ctx.values.operatingMode === 1) {\n color = ctx.properties.outputValueBoxBackground;\n} else if (ctx.values.operatingMode === 2) {\n color = ctx.properties.bypassColor;\n}\nelement.attr({fill: color});",
"actions": null
},
{
"tag": "warning",
"stateRenderFunction": "element.attr({fill: ctx.properties.warningColor});\nvar warning = ctx.values.warning && !(ctx.values.warning && ctx.values.critical)\nif (warning) {\n element.show();\n} else {\n element.hide();\n}\n\nvar elementCriticalAnimation = element.remember('criticalAnimation');\nvar criticalAnimation = warning && ctx.values.criticalAnimation;\n\nif (elementCriticalAnimation !== criticalAnimation) {\n element.remember('criticalAnimation', criticalAnimation);\n if (criticalAnimation) {\n ctx.api.cssAnimate(element, 500).attr({opacity: 0.15}).loop(0, true);\n } else {\n ctx.api.resetCssAnimation(element);\n }\n}\n",
"actions": {
"click": {
"actionFunction": "ctx.api.callAction(event, 'warningClick');"
}
}
}
],
"behavior": [
{
"id": "operatingMode",
"name": "{i18n:scada.symbol.operating-mode}",
"hint": "{i18n:scada.symbol.operating-mode-hint}",
"group": null,
"type": "value",
"valueType": "INTEGER",
"trueLabel": null,
"falseLabel": null,
"stateLabel": null,
"defaultGetValueSettings": {
"action": "GET_ATTRIBUTE",
"defaultValue": null,
"executeRpc": {
"method": "getState",
"requestTimeout": 5000,
"requestPersistent": false,
"persistentPollingInterval": 1000
},
"getAttribute": {
"scope": "SHARED_SCOPE",
"key": "operatingMode"
},
"getTimeSeries": {
"key": "state"
},
"getAlarmStatus": {
"severityList": null,
"typeList": null
},
"dataToValue": {
"type": "NONE",
"dataToValueFunction": "/* Should return boolean value */\nreturn data;"
}
},
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": null
},
{
"id": "inputVoltage",
"name": "{i18n:scada.symbol.input-voltage}",
"hint": "{i18n:scada.symbol.input-voltage-hint}",
"group": null,
"type": "value",
"valueType": "DOUBLE",
"trueLabel": null,
"falseLabel": null,
"stateLabel": null,
"defaultGetValueSettings": {
"action": "GET_TIME_SERIES",
"defaultValue": null,
"executeRpc": {
"method": "getState",
"requestTimeout": 5000,
"requestPersistent": false,
"persistentPollingInterval": 1000
},
"getAttribute": {
"scope": null,
"key": "state"
},
"getTimeSeries": {
"key": "inputVoltage"
},
"getAlarmStatus": {
"severityList": null,
"typeList": null
},
"dataToValue": {
"type": "NONE",
"dataToValueFunction": "/* Should return boolean value */\nreturn data;"
}
},
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": null
},
{
"id": "outputVoltage",
"name": "{i18n:scada.symbol.output-voltage}",
"hint": "{i18n:scada.symbol.output-voltage-hint}",
"group": null,
"type": "value",
"valueType": "DOUBLE",
"trueLabel": null,
"falseLabel": null,
"stateLabel": null,
"defaultGetValueSettings": {
"action": "GET_TIME_SERIES",
"defaultValue": null,
"executeRpc": {
"method": "getState",
"requestTimeout": 5000,
"requestPersistent": false,
"persistentPollingInterval": 1000
},
"getAttribute": {
"scope": null,
"key": "state"
},
"getTimeSeries": {
"key": "outputVoltage"
},
"getAlarmStatus": {
"severityList": null,
"typeList": null
},
"dataToValue": {
"type": "NONE",
"dataToValueFunction": "/* Should return boolean value */\nreturn data;"
}
},
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": null
},
{
"id": "warning",
"name": "{i18n:scada.symbol.warning}",
"hint": "{i18n:scada.symbol.warning-state-hint}",
"group": "{i18n:scada.symbol.warning-state}",
"type": "value",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": "{i18n:scada.symbol.warning}",
"defaultGetValueSettings": {
"action": "GET_ALARM_STATUS",
"defaultValue": false,
"executeRpc": {
"method": "getState",
"requestTimeout": 5000,
"requestPersistent": false,
"persistentPollingInterval": 1000
},
"getAttribute": {
"scope": null,
"key": "state"
},
"getTimeSeries": {
"key": "state"
},
"getAlarmStatus": {
"severityList": [
"MAJOR",
"MINOR",
"WARNING",
"INDETERMINATE"
],
"typeList": null
},
"dataToValue": {
"type": "NONE",
"dataToValueFunction": "/* Should return boolean value */\nreturn data;",
"compareToValue": true
}
},
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": null
},
{
"id": "warningClick",
"name": "{i18n:scada.symbol.warning-click}",
"hint": "{i18n:scada.symbol.on-click-hint}",
"group": "{i18n:scada.symbol.warning-state}",
"type": "widgetAction",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": null,
"defaultGetValueSettings": null,
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": {
"type": "doNothing",
"targetDashboardStateId": null,
"openRightLayout": false,
"setEntityId": false,
"stateEntityParamName": null
}
},
{
"id": "critical",
"name": "{i18n:scada.symbol.critical}",
"hint": "{i18n:scada.symbol.critical-state-hint}",
"group": "{i18n:scada.symbol.critical-state}",
"type": "value",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": "{i18n:scada.symbol.critical}",
"defaultGetValueSettings": {
"action": "GET_ALARM_STATUS",
"defaultValue": false,
"executeRpc": {
"method": "getState",
"requestTimeout": 5000,
"requestPersistent": false,
"persistentPollingInterval": 1000
},
"getAttribute": {
"scope": null,
"key": "state"
},
"getTimeSeries": {
"key": "state"
},
"getAlarmStatus": {
"severityList": [
"CRITICAL"
],
"typeList": null
},
"dataToValue": {
"type": "NONE",
"dataToValueFunction": "/* Should return boolean value */\nreturn data;",
"compareToValue": true
}
},
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": null
},
{
"id": "criticalClick",
"name": "{i18n:scada.symbol.critical-click}",
"hint": "{i18n:scada.symbol.on-click-hint}",
"group": "{i18n:scada.symbol.critical-state}",
"type": "widgetAction",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": null,
"defaultGetValueSettings": null,
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": {
"type": "doNothing",
"targetDashboardStateId": null,
"openRightLayout": false,
"setEntityId": false,
"stateEntityParamName": null
}
},
{
"id": "criticalAnimation",
"name": "{i18n:scada.symbol.warning-critical-state-animation}",
"hint": "{i18n:scada.symbol.warning-critical-state-animation-hint}",
"group": null,
"type": "value",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": "{i18n:scada.symbol.animation}",
"defaultGetValueSettings": {
"action": "DO_NOTHING",
"defaultValue": false,
"executeRpc": {
"method": "getState",
"requestTimeout": 5000,
"requestPersistent": false,
"persistentPollingInterval": 1000
},
"getAttribute": {
"key": "state",
"scope": null
},
"getTimeSeries": {
"key": "state"
},
"dataToValue": {
"type": "NONE",
"compareToValue": true,
"dataToValueFunction": "/* Should return boolean value */\nreturn data;"
}
},
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": null
},
{
"id": "click",
"name": "{i18n:scada.symbol.on-click}",
"hint": "{i18n:scada.symbol.on-click-hint}",
"group": null,
"type": "widgetAction",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": null,
"defaultGetValueSettings": null,
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": {
"type": "doNothing",
"targetDashboardStateId": null,
"openRightLayout": false,
"setEntityId": false,
"stateEntityParamName": null
}
}
],
"properties": [
{
"id": "runningColor",
"name": "{i18n:scada.symbol.colors}",
"type": "color",
"default": "#FFFFFF",
"subLabel": "{i18n:scada.symbol.running}",
"divider": true,
"disabled": false,
"visible": true
},
{
"id": "bypassColor",
"name": "{i18n:scada.symbol.colors}",
"type": "color",
"default": "#DEDEDE",
"subLabel": "{i18n:scada.symbol.bypass-mode}",
"divider": true,
"disabled": false,
"visible": true
},
{
"id": "stoppedColor",
"name": "{i18n:scada.symbol.colors}",
"type": "color",
"default": "#666666",
"subLabel": "{i18n:scada.symbol.stopped}",
"divider": false,
"disabled": false,
"visible": true
},
{
"id": "warningColor",
"name": "{i18n:scada.symbol.alarm-colors}",
"type": "color",
"default": "#FAA405",
"subLabel": "{i18n:scada.symbol.warning}",
"divider": true,
"disabled": false,
"visible": true
},
{
"id": "criticalColor",
"name": "{i18n:scada.symbol.alarm-colors}",
"type": "color",
"default": "#D12730",
"subLabel": "{i18n:scada.symbol.critical}",
"disabled": false,
"visible": true
},
{
"id": "showInputLabel",
"name": "{i18n:scada.symbol.label}",
"group": "{i18n:scada.symbol.input-voltage}",
"type": "switch",
"default": true,
"disabled": false,
"visible": true
},
{
"id": "inputLabel",
"name": "{i18n:scada.symbol.label}",
"group": "{i18n:scada.symbol.input-voltage}",
"type": "text",
"default": "in",
"disabled": false,
"visible": true
},
{
"id": "inputLabelFont",
"name": "{i18n:scada.symbol.label}",
"group": "{i18n:scada.symbol.input-voltage}",
"type": "font",
"default": {
"size": 36,
"sizeUnit": "px",
"family": "Roboto",
"weight": "normal",
"style": "normal"
},
"disabled": false,
"visible": true
},
{
"id": "inputLabelColor",
"name": "{i18n:scada.symbol.label}",
"group": "{i18n:scada.symbol.input-voltage}",
"type": "color",
"default": "#000",
"disabled": false,
"visible": true
},
{
"id": "inputValutFont",
"name": "{i18n:scada.symbol.value}",
"group": "{i18n:scada.symbol.input-voltage}",
"type": "font",
"default": {
"size": 44,
"sizeUnit": "px",
"family": "Roboto",
"weight": "normal",
"style": "normal"
},
"disabled": false,
"visible": true
},
{
"id": "inputValueColor",
"name": "{i18n:scada.symbol.value}",
"group": "{i18n:scada.symbol.input-voltage}",
"type": "color",
"default": "#002878",
"disabled": false,
"visible": true
},
{
"id": "inputValueBoxBackground",
"name": "{i18n:scada.symbol.value-box-background}",
"group": "{i18n:scada.symbol.input-voltage}",
"type": "color",
"default": "#DEDEDE",
"disabled": false,
"visible": true
},
{
"id": "showOutputLabel",
"name": "{i18n:scada.symbol.label}",
"group": "{i18n:scada.symbol.output-voltage}",
"type": "switch",
"default": true,
"disabled": false,
"visible": true
},
{
"id": "outputLabel",
"name": "{i18n:scada.symbol.label}",
"group": "{i18n:scada.symbol.output-voltage}",
"type": "text",
"default": "out",
"disabled": false,
"visible": true
},
{
"id": "outputLabelFont",
"name": "{i18n:scada.symbol.label}",
"group": "{i18n:scada.symbol.output-voltage}",
"type": "font",
"default": {
"size": 36,
"sizeUnit": "px",
"family": "Roboto",
"weight": "normal",
"style": "normal"
},
"disabled": false,
"visible": true
},
{
"id": "outputLabelColor",
"name": "{i18n:scada.symbol.label}",
"group": "{i18n:scada.symbol.output-voltage}",
"type": "color",
"default": "#000",
"disabled": false,
"visible": true
},
{
"id": "outputValueFont",
"name": "{i18n:scada.symbol.value}",
"group": "{i18n:scada.symbol.output-voltage}",
"type": "font",
"default": {
"size": 44,
"sizeUnit": "px",
"family": "Roboto",
"weight": "normal",
"style": "normal"
},
"disabled": false,
"visible": true
},
{
"id": "outputValueColor",
"name": "{i18n:scada.symbol.value}",
"group": "{i18n:scada.symbol.output-voltage}",
"type": "color",
"default": "#002878",
"disabled": false,
"visible": true
},
{
"id": "outputValueBoxBackground",
"name": "{i18n:scada.symbol.value-box-background}",
"group": "{i18n:scada.symbol.output-voltage}",
"type": "color",
"default": "#DEDEDE",
"disabled": false,
"visible": true
}
]
}]]></tb:metadata>
<rect width="400" height="200" fill="#fff" tb:tag="background"/><rect x="1" y="1" width="398" height="198" stroke="#000" stroke-opacity=".87" stroke-width="2"/><rect x="213" y="81" width="126" height="78" rx="1" fill="#dedede" stroke="#000" stroke-opacity=".87" stroke-width="2" tb:tag="out-value-box"/><text x="275.76855" y="136.65625" fill="#002878" font-family="Roboto" font-size="44px" font-weight="400" text-anchor="middle" tb:tag="out-value" xml:space="default"><tspan dominant-baseline="start">220</tspan></text><rect x="61" y="81" width="126" height="78" rx="1" fill="#dedede" stroke="#000" stroke-opacity=".87" stroke-width="2" tb:tag="in-value-box"/><text x="123.76855" y="136.65625" fill="#002878" font-family="Roboto" font-size="44px" font-weight="400" text-anchor="middle" tb:tag="in-value" xml:space="default"><tspan dominant-baseline="start">230</tspan></text><text x="123.29346" y="57.832031" fill="#000000" font-family="Roboto" font-size="34px" font-weight="400" text-anchor="middle" tb:tag="in-label" xml:space="default"><tspan dominant-baseline="start">in</tspan></text><text x="275.96484" y="55.873047" fill="#000000" font-family="Roboto" font-size="34px" font-weight="400" text-anchor="middle" tb:tag="out-label" xml:space="default"><tspan dominant-baseline="start">out</tspan></text><path d="m134.53 0s-134.53 0-134.53 33.5v164.18c0 1.3256 3.5818 2.3202 8 2.3202h384c4.418 0 8-0.9946 8-2.3202v-164.18c0-33.5-132.14-33.5-132.14-33.5h-67.858zm134.14 40.6c-2.5774 0-4.6666 0.6268-4.6666 1.4v150.2c0 0.7732 2.0894 1.4 4.6666 1.4h29.332c2.5774 0 4.6666-0.6268 4.6666-1.4v-150.2c0-0.7732-2.0894-1.4-4.6666-1.4z" fill="#000" fill-opacity="0" style="stroke-width:.70711" tb:tag="clickArea"/><g fill="#d12730" style="display: none;" tb:tag="critical">
<rect width="84" height="84" rx="4" fill="#fff" style=""/>
<rect width="84" height="84" rx="4" style=""/>
<rect x="2" y="2" width="80" height="80" rx="2" stroke="#000" stroke-opacity=".87" stroke-width="4" style=""/>
<path d="m44.559 27.562-0.4688 20.059h-4.0234l-0.4883-20.059zm-5.1172 26.211c0-0.7161 0.2344-1.3151 0.7031-1.7968 0.4818-0.4948 1.1459-0.7422 1.9922-0.7422 0.8334 0 1.4909 0.2474 1.9727 0.7422 0.4817 0.4817 0.7226 1.0807 0.7226 1.7968 0 0.6901-0.2409 1.2826-0.7226 1.7774-0.4818 0.4818-1.1393 0.7226-1.9727 0.7226-0.8463 0-1.5104-0.2408-1.9922-0.7226-0.4687-0.4948-0.7031-1.0873-0.7031-1.7774z" fill="#000" fill-opacity=".87" style=""/>
</g><g fill="#faa405" style="display: none;" tb:tag="warning">
<path d="m35.955 2.2112c1.4741-2.9482 5.6813-2.9482 7.1554 0l35.528 71.056c1.3298 2.6596-0.6042 5.7889-3.5777 5.7889h-71.056c-2.9735 0-4.9075-3.1292-3.5777-5.7889z" fill="#fff" style=""/>
<path d="m35.955 2.2112c1.4741-2.9482 5.6813-2.9482 7.1554 0l35.528 71.056c1.3298 2.6596-0.6042 5.7889-3.5777 5.7889h-71.056c-2.9735 0-4.9075-3.1292-3.5777-5.7889z" style=""/>
<path d="m37.72 3.1061c0.7371-1.4741 2.8407-1.4741 3.5778-1e-5l35.528 71.056c0.6649 1.3298-0.3021 2.8944-1.7888 2.8944h-71.056c-1.4868 0-2.4538-1.5646-1.7889-2.8944z" stroke="#000" stroke-opacity=".87" stroke-width="4" style=""/>
<path d="m42.092 32.618-0.4688 20.059h-4.0234l-0.4883-20.059zm-5.1172 26.211c0-0.7161 0.2344-1.3151 0.7031-1.7968 0.4818-0.4948 1.1459-0.7422 1.9922-0.7422 0.8334 0 1.4909 0.2474 1.9727 0.7422 0.4817 0.4817 0.7226 1.0807 0.7226 1.7968 0 0.6901-0.2409 1.2826-0.7226 1.7774-0.4818 0.4818-1.1393 0.7226-1.9727 0.7226-0.8463 0-1.5104-0.2408-1.9922-0.7226-0.4687-0.4948-0.7031-1.0873-0.7031-1.7774z" fill="#000" fill-opacity=".87" style=""/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 21 KiB

370
application/src/main/data/json/system/scada_symbols/wind-turbine-cluster-hp.svg

@ -0,0 +1,370 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:tb="https://thingsboard.io/svg" width="600" height="800" fill="none" version="1.1" viewBox="0 0 600 800"><tb:metadata xmlns=""><![CDATA[{
"title": "HP Wind turbine cluster",
"description": "Wind turbine cluster with various states.",
"searchTags": [
"energy",
"power",
"renewable",
"generation"
],
"widgetSizeX": 3,
"widgetSizeY": 4,
"tags": [
{
"tag": "background",
"stateRenderFunction": "var color = ctx.properties.stoppedColor;\nif (ctx.values.running) {\n color = ctx.properties.runningColor;\n}\nelement.attr({fill: color});",
"actions": null
},
{
"tag": "clickArea",
"stateRenderFunction": null,
"actions": {
"click": {
"actionFunction": "ctx.api.callAction(event, 'click');"
}
}
},
{
"tag": "critical",
"stateRenderFunction": "element.attr({fill: ctx.properties.criticalColor});\nif (ctx.values.critical) {\n element.show();\n} else {\n element.hide();\n}\n\nvar elementCriticalAnimation = element.remember('criticalAnimation');\nvar criticalAnimation = ctx.values.critical && ctx.values.criticalAnimation;\n\nif (elementCriticalAnimation !== criticalAnimation) {\n element.remember('criticalAnimation', criticalAnimation);\n if (criticalAnimation) {\n ctx.api.cssAnimate(element, 500).attr({opacity: 0.15}).loop(0, true);\n } else {\n ctx.api.resetCssAnimation(element);\n }\n}\n\n",
"actions": {
"click": {
"actionFunction": "ctx.api.callAction(event, 'criticalClick');"
}
}
},
{
"tag": "warning",
"stateRenderFunction": "element.attr({fill: ctx.properties.warningColor});\nvar warning = ctx.values.warning && !(ctx.values.warning && ctx.values.critical)\nif (warning) {\n element.show();\n} else {\n element.hide();\n}\n\nvar elementCriticalAnimation = element.remember('criticalAnimation');\nvar criticalAnimation = warning && ctx.values.criticalAnimation;\n\nif (elementCriticalAnimation !== criticalAnimation) {\n element.remember('criticalAnimation', criticalAnimation);\n if (criticalAnimation) {\n ctx.api.cssAnimate(element, 500).attr({opacity: 0.15}).loop(0, true);\n } else {\n ctx.api.resetCssAnimation(element);\n }\n}\n",
"actions": {
"click": {
"actionFunction": "ctx.api.callAction(event, 'warningClick');"
}
}
}
],
"behavior": [
{
"id": "running",
"name": "{i18n:scada.symbol.running}",
"hint": "{i18n:scada.symbol.running-hint}",
"group": null,
"type": "value",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": "{i18n:scada.symbol.running}",
"defaultGetValueSettings": {
"action": "GET_ATTRIBUTE",
"defaultValue": false,
"executeRpc": {
"method": "getState",
"requestTimeout": 5000,
"requestPersistent": false,
"persistentPollingInterval": 1000
},
"getAttribute": {
"scope": "SHARED_SCOPE",
"key": "running"
},
"getTimeSeries": {
"key": "state"
},
"getAlarmStatus": {
"severityList": null,
"typeList": null
},
"dataToValue": {
"type": "NONE",
"dataToValueFunction": "/* Should return boolean value */\nreturn data;",
"compareToValue": true
}
},
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": null
},
{
"id": "warning",
"name": "{i18n:scada.symbol.warning}",
"hint": "{i18n:scada.symbol.warning-state-hint}",
"group": "{i18n:scada.symbol.warning-state}",
"type": "value",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": "{i18n:scada.symbol.warning}",
"defaultGetValueSettings": {
"action": "GET_ALARM_STATUS",
"defaultValue": false,
"executeRpc": {
"method": "getState",
"requestTimeout": 5000,
"requestPersistent": false,
"persistentPollingInterval": 1000
},
"getAttribute": {
"scope": null,
"key": "state"
},
"getTimeSeries": {
"key": "state"
},
"getAlarmStatus": {
"severityList": [
"MAJOR",
"MINOR",
"WARNING",
"INDETERMINATE"
],
"typeList": null
},
"dataToValue": {
"type": "NONE",
"dataToValueFunction": "/* Should return boolean value */\nreturn data;",
"compareToValue": true
}
},
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": null
},
{
"id": "warningClick",
"name": "{i18n:scada.symbol.warning-click}",
"hint": "{i18n:scada.symbol.on-click-hint}",
"group": "{i18n:scada.symbol.warning-state}",
"type": "widgetAction",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": null,
"defaultGetValueSettings": null,
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": {
"type": "doNothing",
"targetDashboardStateId": null,
"openRightLayout": false,
"setEntityId": false,
"stateEntityParamName": null
}
},
{
"id": "critical",
"name": "{i18n:scada.symbol.critical}",
"hint": "{i18n:scada.symbol.critical-state-hint}",
"group": "{i18n:scada.symbol.critical-state}",
"type": "value",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": "{i18n:scada.symbol.critical}",
"defaultGetValueSettings": {
"action": "GET_ALARM_STATUS",
"defaultValue": false,
"executeRpc": {
"method": "getState",
"requestTimeout": 5000,
"requestPersistent": false,
"persistentPollingInterval": 1000
},
"getAttribute": {
"scope": null,
"key": "state"
},
"getTimeSeries": {
"key": "state"
},
"getAlarmStatus": {
"severityList": [
"CRITICAL"
],
"typeList": null
},
"dataToValue": {
"type": "NONE",
"dataToValueFunction": "/* Should return boolean value */\nreturn data;",
"compareToValue": true
}
},
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": null
},
{
"id": "criticalClick",
"name": "{i18n:scada.symbol.critical-click}",
"hint": "{i18n:scada.symbol.on-click-hint}",
"group": "{i18n:scada.symbol.critical-state}",
"type": "widgetAction",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": null,
"defaultGetValueSettings": null,
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": {
"type": "doNothing",
"targetDashboardStateId": null,
"openRightLayout": false,
"setEntityId": false,
"stateEntityParamName": null
}
},
{
"id": "criticalAnimation",
"name": "{i18n:scada.symbol.warning-critical-state-animation}",
"hint": "{i18n:scada.symbol.warning-critical-state-animation-hint}",
"group": null,
"type": "value",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": "{i18n:scada.symbol.animation}",
"defaultGetValueSettings": {
"action": "DO_NOTHING",
"defaultValue": false,
"executeRpc": {
"method": "getState",
"requestTimeout": 5000,
"requestPersistent": false,
"persistentPollingInterval": 1000
},
"getAttribute": {
"key": "state",
"scope": null
},
"getTimeSeries": {
"key": "state"
},
"dataToValue": {
"type": "NONE",
"compareToValue": true,
"dataToValueFunction": "/* Should return boolean value */\nreturn data;"
}
},
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": null
},
{
"id": "click",
"name": "{i18n:scada.symbol.on-click}",
"hint": "{i18n:scada.symbol.on-click-hint}",
"group": null,
"type": "widgetAction",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": null,
"defaultGetValueSettings": null,
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": {
"type": "doNothing",
"targetDashboardStateId": null,
"openRightLayout": false,
"setEntityId": false,
"stateEntityParamName": null
}
}
],
"properties": [
{
"id": "runningColor",
"name": "{i18n:scada.symbol.colors}",
"type": "color",
"default": "#FFFFFF",
"required": null,
"subLabel": "{i18n:scada.symbol.running}",
"divider": true,
"fieldSuffix": null,
"disableOnProperty": null,
"rowClass": "",
"fieldClass": "",
"min": null,
"max": null,
"step": null,
"disabled": false,
"visible": true
},
{
"id": "stoppedColor",
"name": "{i18n:scada.symbol.colors}",
"type": "color",
"default": "#666666",
"required": null,
"subLabel": "{i18n:scada.symbol.stopped}",
"divider": null,
"fieldSuffix": null,
"disableOnProperty": null,
"rowClass": "",
"fieldClass": "",
"min": null,
"max": null,
"step": null,
"disabled": false,
"visible": true
},
{
"id": "warningColor",
"name": "{i18n:scada.symbol.alarm-colors}",
"type": "color",
"default": "#FAA405",
"required": null,
"subLabel": "{i18n:scada.symbol.warning}",
"divider": true,
"fieldSuffix": null,
"disableOnProperty": null,
"rowClass": "",
"fieldClass": "",
"min": null,
"max": null,
"step": null,
"disabled": false,
"visible": true
},
{
"id": "criticalColor",
"name": "{i18n:scada.symbol.alarm-colors}",
"type": "color",
"default": "#D12730",
"required": null,
"subLabel": "{i18n:scada.symbol.critical}",
"divider": null,
"fieldSuffix": null,
"disableOnProperty": null,
"rowClass": "",
"fieldClass": "",
"min": null,
"max": null,
"step": null,
"disabled": false,
"visible": true
}
]
}]]></tb:metadata>
<g fill="#fff" stroke="#1a1a1a" stroke-width="2" tb:tag="background">
<path d="m413.82 165.21c0.064-0.16596 0.125-0.32492 0.184-0.47689 0.059 0.15197 0.12 0.31093 0.184 0.47689 0.709 1.8416 1.722 4.5229 2.938 7.8751 2.433 6.7044 5.677 16.091 8.921 26.818 6.495 21.48 12.957 48.231 12.957 69.568 0 21.337-6.462 48.088-12.957 69.568-3.244 10.726-6.488 20.113-8.921 26.818-1.216 3.3522-2.229 6.0336-2.938 7.8751-0.064 0.16596-0.125 0.32493-0.184 0.47689-0.059-0.15196-0.12-0.31093-0.184-0.47689-0.709-1.8416-1.722-4.5229-2.938-7.8751-2.433-6.7044-5.677-16.091-8.921-26.818-6.495-21.48-12.957-48.231-12.957-69.568 0-21.337 6.462-48.088 12.957-69.568 3.244-10.726 6.488-20.113 8.921-26.818 1.216-3.3522 2.229-6.0336 2.938-7.8751z"/>
<path d="m186.82 165.21c0.064-0.16596 0.125-0.32492 0.184-0.47689 0.059 0.15197 0.12 0.31093 0.184 0.47689 0.709 1.8416 1.722 4.5229 2.938 7.8751 2.433 6.7044 5.677 16.091 8.921 26.818 6.495 21.48 12.957 48.231 12.957 69.568 0 21.337-6.462 48.088-12.957 69.568-3.244 10.726-6.488 20.113-8.921 26.818-1.216 3.3522-2.229 6.0336-2.938 7.8751-0.064 0.16596-0.125 0.32493-0.184 0.47689-0.059-0.15196-0.12-0.31093-0.184-0.47689-0.709-1.8416-1.722-4.5229-2.938-7.8751-2.433-6.7044-5.677-16.091-8.921-26.818-6.495-21.48-12.957-48.231-12.957-69.568 0-21.337 6.462-48.088 12.957-69.568 3.244-10.726 6.488-20.113 8.921-26.818 1.216-3.3522 2.229-6.0336 2.938-7.8751z"/>
<path d="m384.05 799 20.054-421h19.793l20.055 421z"/>
<path d="m157.05 799 20.054-421h19.793l20.055 421z"/>
<path d="m416.33 379.11c-0.11966-0.14937-0.23334-0.2917-0.34205-0.42803 0.17153 0.0261 0.35203 0.0542 0.53951 0.0831 1.9515 0.30172 4.7826 0.75682 8.2957 1.3713 7.0283 1.229 16.786 3.0904 27.702 5.6266 21.862 5.0772 48.264 12.83 66.722 23.542 18.457 10.713 38.337 29.821 53.642 46.313 7.6426 8.2358 14.125 15.799 18.698 21.302 2.2866 2.7526 4.0945 4.989 5.33 6.5367 0.11867 0.14936 0.23334 0.29171 0.34104 0.42804-0.17151-0.0261-0.35101-0.0542-0.53949-0.0833-1.9515-0.30171-4.7816-0.75782-8.2957-1.3713-7.0283-1.229-16.786-3.0914-27.702-5.6265-21.861-5.0772-48.263-12.83-66.721-23.543-18.458-10.712-38.337-29.82-53.642-46.312-7.6426-8.2358-14.126-15.799-18.699-21.303-2.2856-2.7516-4.0935-4.988-5.329-6.5357z"/>
<path d="m189.34 379.12c-0.11967-0.15082-0.23334-0.29458-0.34205-0.43225 0.17154 0.0264 0.35201 0.0546 0.5395 0.084 1.9516 0.30469 4.7827 0.76428 8.2959 1.3848 7.0284 1.2411 16.786 3.1209 27.703 5.682 21.862 5.1272 48.265 12.956 66.723 23.774 18.458 10.818 38.338 30.115 53.644 46.77 7.6427 8.317 14.126 15.955 18.698 21.512 2.2866 2.7797 4.0946 5.0382 5.3302 6.6011 0.11866 0.15082 0.23334 0.29458 0.34105 0.43224-0.17154-0.0264-0.35102-0.0546-0.5395-0.084-1.9516-0.30469-4.7817-0.76528-8.2959-1.3848-7.0284-1.2411-16.786-3.1219-27.703-5.682-21.861-5.1272-48.264-12.956-66.722-23.775-18.459-10.817-38.338-30.114-53.644-46.769-7.6427-8.317-14.127-15.955-18.699-21.513-2.2856-2.7787-4.0936-5.0371-5.3292-6.6001z"/>
<path d="m410.21 378.76c0.18845-0.0291 0.36793-0.0562 0.53942-0.0832-0.10768 0.13636-0.22135 0.27974-0.341 0.42913-1.2354 1.548-3.043 3.7849-5.3283 6.5371-4.5726 5.5054-11.055 13.07-18.696 21.308-15.303 16.496-35.181 35.608-53.635 46.322-18.456 10.715-44.854 18.469-66.713 23.547-10.915 2.5356-20.671 4.3985-27.699 5.6267-3.5127 0.61461-6.3434 1.0708-8.2946 1.3726-0.18745 0.0291-0.36793 0.0561-0.53941 0.0832 0.10868-0.13635 0.22234-0.27973 0.34199-0.42912 1.2354-1.548 3.0431-3.7849 5.3284-6.5371 4.5716-5.5054 11.055-13.07 18.696-21.307 15.303-16.497 35.18-35.608 53.635-46.323 18.456-10.715 44.854-18.469 66.712-23.547 10.915-2.5356 20.671-4.3985 27.699-5.6267 3.5137-0.6146 6.3444-1.0708 8.2946-1.3726z"/>
<path d="m183.22 378.76c0.18844-0.0291 0.36792-0.0561 0.53942-0.0832-0.10768 0.13634-0.22135 0.27971-0.34101 0.4291-1.2354 1.548-3.0431 3.7849-5.3285 6.537-4.5727 5.5054-11.055 13.07-18.696 21.308-15.303 16.496-35.181 35.608-53.637 46.322-18.456 10.715-44.855 18.469-66.714 23.547-10.915 2.5356-20.672 4.3985-27.699 5.6267-3.5134 0.6146-6.3438 1.0708-8.2948 1.3726-0.18807 0.0291-0.36798 0.0561-0.53953 0.0832 0.10838-0.13634 0.22218-0.27971 0.34129-0.42911 1.2356-1.548 3.0432-3.7849 5.329-6.537 4.5719-5.5054 11.055-13.07 18.696-21.306 15.303-16.497 35.181-35.608 53.637-46.323 18.456-10.715 44.855-18.469 66.713-23.547 10.915-2.5356 20.672-4.3985 27.699-5.6267 3.5138-0.6146 6.3445-1.0708 8.2948-1.3726z"/>
<circle cx="414" cy="378" r="27"/>
<circle cx="187" cy="378"/>
<path d="m299.84 3.9752c0.178-0.45587 0.34-0.87084 0.486-1.2433 0.147 0.37248 0.309 0.78745 0.486 1.2433 0.9 2.3145 2.187 5.6829 3.732 9.8942 3.089 8.4232 7.207 20.216 11.326 33.692 8.245 26.98 16.456 60.603 16.456 87.437s-8.211 60.457-16.456 87.437c-4.119 13.476-8.237 25.269-11.326 33.692-1.545 4.2111-2.832 7.5794-3.732 9.8939-0.177 0.4559-0.339 0.87081-0.486 1.2437-0.146-0.37292-0.308-0.78783-0.486-1.2437-0.9-2.3145-2.187-5.6828-3.731-9.8939-3.089-8.4232-7.208-20.216-11.326-33.692-8.246-26.98-16.457-60.603-16.457-87.437s8.211-60.457 16.457-87.437c4.118-13.476 8.237-25.269 11.326-33.692 1.544-4.2114 2.831-7.5797 3.731-9.8942z"/>
<path d="m261.38 799 25.902-528h26.096l25.902 528z"/>
<path d="m303.5 272.39c-0.30616-0.38092-0.58532-0.72884-0.83445-1.0418 0.39622 0.059 0.83645 0.12598 1.3207 0.20096 2.4564 0.37792 6.0193 0.94779 10.442 1.7156 8.8458 1.5376 21.127 3.8671 34.866 7.0394 27.508 6.3506 60.756 16.052 84.014 29.469 23.257 13.418 48.289 37.339 67.548 57.967 9.6182 10.304 17.779 19.767 23.534 26.653 2.8766 3.4422 5.1528 6.2406 6.7077 8.1772 0.30717 0.38191 0.58533 0.72984 0.83445 1.0428-0.39521-0.06-0.83645-0.12696-1.3197-0.20095-2.4563-0.37791-6.0203-0.94779-10.443-1.7166-8.8448-1.5367-21.127-3.8671-34.866-7.0384-27.508-6.3516-60.756-16.053-84.013-29.47-23.258-13.417-48.29-37.338-67.548-57.967-9.6192-10.304-17.78-19.766-23.535-26.652-2.8766-3.4432-5.1528-6.2406-6.7077-8.1782z"/>
<path d="m296.78 271.55c0.48325-0.075 0.92446-0.14197 1.3207-0.20096-0.25013 0.31293-0.52826 0.66085-0.83442 1.0418-1.5558 1.9366-3.8309 4.7349-6.7084 8.1781-5.7549 6.8864-13.914 16.348-23.533 26.652-19.258 20.629-44.289 44.55-67.545 57.967-23.257 13.417-56.503 23.119-84.01 29.469-13.739 3.1723-26.019 5.5027-34.864 7.0394-4.4223 0.76882-7.9852 1.3387-10.441 1.7166-0.48374 0.074-0.92456 0.14097-1.3206 0.20096 0.24953-0.31294 0.52796-0.66086 0.83442-1.0428 1.5555-1.9366 3.8309-4.7349 6.7081-8.1781 5.7547-6.8854 13.914-16.348 23.533-26.652 19.257-20.629 44.288-44.549 67.545-57.967 23.256-13.417 56.502-23.119 84.009-29.469 13.739-3.1723 26.02-5.5018 34.864-7.0394 4.4232-0.76782 7.986-1.3377 10.442-1.7156z"/>
<circle cx="300.33" cy="270" r="33"/>
<rect x="136.33" y="777" width="328" height="22" rx="1"/>
</g><path d="m201.8-4e-4s-201.8 0-201.8 134v656.72c0 5.3024 5.3727 9.2808 12 9.2808h576c6.627 0 12-3.9784 12-9.2808v-656.72c0-134-198.21-134-198.21-134h-101.79zm201.21 162.4c-3.8661 0-6.9999 2.5072-6.9999 5.6v600.8c0 3.0928 3.1341 5.6 6.9999 5.6h43.998c3.8661 0 6.9999-2.5072 6.9999-5.6v-600.8c0-3.0928-3.1341-5.6-6.9999-5.6z" fill-opacity="0" tb:tag="clickArea"/><g transform="translate(0,716)" fill="#d12730" style="display: none;" tb:tag="critical">
<rect width="84" height="84" rx="4" fill="#fff" style=""/>
<rect width="84" height="84" rx="4" style=""/>
<rect x="2" y="2" width="80" height="80" rx="2" stroke="#000" stroke-opacity=".87" stroke-width="4" style=""/>
<path d="m44.559 27.562-0.4688 20.059h-4.0234l-0.4883-20.059zm-5.1172 26.211c0-0.7161 0.2344-1.3151 0.7031-1.7968 0.4818-0.4948 1.1459-0.7422 1.9922-0.7422 0.8334 0 1.4909 0.2474 1.9727 0.7422 0.4817 0.4817 0.7226 1.0807 0.7226 1.7968 0 0.6901-0.2409 1.2826-0.7226 1.7774-0.4818 0.4818-1.1393 0.7226-1.9727 0.7226-0.8463 0-1.5104-0.2408-1.9922-0.7226-0.4687-0.4948-0.7031-1.0873-0.7031-1.7774z" fill="#000" fill-opacity=".87" style=""/>
</g><g transform="translate(0,720.94)" fill="#faa405" style="display: none;" tb:tag="warning">
<path d="m35.955 2.2112c1.4741-2.9482 5.6813-2.9482 7.1554 0l35.528 71.056c1.3298 2.6596-0.6042 5.7889-3.5777 5.7889h-71.056c-2.9735 0-4.9075-3.1292-3.5777-5.7889z" fill="#fff" style=""/>
<path d="m35.955 2.2112c1.4741-2.9482 5.6813-2.9482 7.1554 0l35.528 71.056c1.3298 2.6596-0.6042 5.7889-3.5777 5.7889h-71.056c-2.9735 0-4.9075-3.1292-3.5777-5.7889z" style=""/>
<path d="m37.72 3.1061c0.7371-1.4741 2.8407-1.4741 3.5778-1e-5l35.528 71.056c0.6649 1.3298-0.3021 2.8944-1.7888 2.8944h-71.056c-1.4868 0-2.4538-1.5646-1.7889-2.8944z" stroke="#000" stroke-opacity=".87" stroke-width="4" style=""/>
<path d="m42.092 32.618-0.4688 20.059h-4.0234l-0.4883-20.059zm-5.1172 26.211c0-0.7161 0.2344-1.3151 0.7031-1.7968 0.4818-0.4948 1.1459-0.7422 1.9922-0.7422 0.8334 0 1.4909 0.2474 1.9727 0.7422 0.4817 0.4817 0.7226 1.0807 0.7226 1.7968 0 0.6901-0.2409 1.2826-0.7226 1.7774-0.4818 0.4818-1.1393 0.7226-1.9727 0.7226-0.8463 0-1.5104-0.2408-1.9922-0.7226-0.4687-0.4948-0.7031-1.0873-0.7031-1.7774z" fill="#000" fill-opacity=".87" style=""/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 19 KiB

360
application/src/main/data/json/system/scada_symbols/wind-turbine-hp.svg

@ -0,0 +1,360 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:tb="https://thingsboard.io/svg" width="600" height="800" fill="none" version="1.1" viewBox="0 0 600 800"><tb:metadata xmlns=""><![CDATA[{
"title": "HP Wind turbine",
"description": "Wind turbine with various states.",
"searchTags": [
"energy",
"power",
"renewable",
"generation"
],
"widgetSizeX": 3,
"widgetSizeY": 4,
"tags": [
{
"tag": "background",
"stateRenderFunction": "var color = ctx.properties.stoppedColor;\nif (ctx.values.running) {\n color = ctx.properties.runningColor;\n}\nelement.attr({fill: color});",
"actions": null
},
{
"tag": "clickArea",
"stateRenderFunction": null,
"actions": {
"click": {
"actionFunction": "ctx.api.callAction(event, 'click');"
}
}
},
{
"tag": "critical",
"stateRenderFunction": "element.attr({fill: ctx.properties.criticalColor});\nif (ctx.values.critical) {\n element.show();\n} else {\n element.hide();\n}\n\nvar elementCriticalAnimation = element.remember('criticalAnimation');\nvar criticalAnimation = ctx.values.critical && ctx.values.criticalAnimation;\n\nif (elementCriticalAnimation !== criticalAnimation) {\n element.remember('criticalAnimation', criticalAnimation);\n if (criticalAnimation) {\n ctx.api.cssAnimate(element, 500).attr({opacity: 0.15}).loop(0, true);\n } else {\n ctx.api.resetCssAnimation(element);\n }\n}\n\n",
"actions": {
"click": {
"actionFunction": "ctx.api.callAction(event, 'criticalClick');"
}
}
},
{
"tag": "warning",
"stateRenderFunction": "element.attr({fill: ctx.properties.warningColor});\nvar warning = ctx.values.warning && !(ctx.values.warning && ctx.values.critical)\nif (warning) {\n element.show();\n} else {\n element.hide();\n}\n\nvar elementCriticalAnimation = element.remember('criticalAnimation');\nvar criticalAnimation = warning && ctx.values.criticalAnimation;\n\nif (elementCriticalAnimation !== criticalAnimation) {\n element.remember('criticalAnimation', criticalAnimation);\n if (criticalAnimation) {\n ctx.api.cssAnimate(element, 500).attr({opacity: 0.15}).loop(0, true);\n } else {\n ctx.api.resetCssAnimation(element);\n }\n}\n",
"actions": {
"click": {
"actionFunction": "ctx.api.callAction(event, 'warningClick');"
}
}
}
],
"behavior": [
{
"id": "running",
"name": "{i18n:scada.symbol.running}",
"hint": "{i18n:scada.symbol.running-hint}",
"group": null,
"type": "value",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": "{i18n:scada.symbol.running}",
"defaultGetValueSettings": {
"action": "GET_ATTRIBUTE",
"defaultValue": false,
"executeRpc": {
"method": "getState",
"requestTimeout": 5000,
"requestPersistent": false,
"persistentPollingInterval": 1000
},
"getAttribute": {
"scope": "SHARED_SCOPE",
"key": "running"
},
"getTimeSeries": {
"key": "state"
},
"getAlarmStatus": {
"severityList": null,
"typeList": null
},
"dataToValue": {
"type": "NONE",
"dataToValueFunction": "/* Should return boolean value */\nreturn data;",
"compareToValue": true
}
},
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": null
},
{
"id": "warning",
"name": "{i18n:scada.symbol.warning}",
"hint": "{i18n:scada.symbol.warning-state-hint}",
"group": "{i18n:scada.symbol.warning-state}",
"type": "value",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": "{i18n:scada.symbol.warning}",
"defaultGetValueSettings": {
"action": "GET_ALARM_STATUS",
"defaultValue": false,
"executeRpc": {
"method": "getState",
"requestTimeout": 5000,
"requestPersistent": false,
"persistentPollingInterval": 1000
},
"getAttribute": {
"scope": null,
"key": "state"
},
"getTimeSeries": {
"key": "state"
},
"getAlarmStatus": {
"severityList": [
"MAJOR",
"MINOR",
"WARNING",
"INDETERMINATE"
],
"typeList": null
},
"dataToValue": {
"type": "NONE",
"dataToValueFunction": "/* Should return boolean value */\nreturn data;",
"compareToValue": true
}
},
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": null
},
{
"id": "warningClick",
"name": "{i18n:scada.symbol.warning-click}",
"hint": "{i18n:scada.symbol.on-click-hint}",
"group": "{i18n:scada.symbol.warning-state}",
"type": "widgetAction",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": null,
"defaultGetValueSettings": null,
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": {
"type": "doNothing",
"targetDashboardStateId": null,
"openRightLayout": false,
"setEntityId": false,
"stateEntityParamName": null
}
},
{
"id": "critical",
"name": "{i18n:scada.symbol.critical}",
"hint": "{i18n:scada.symbol.critical-state-hint}",
"group": "{i18n:scada.symbol.critical-state}",
"type": "value",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": "{i18n:scada.symbol.critical}",
"defaultGetValueSettings": {
"action": "GET_ALARM_STATUS",
"defaultValue": false,
"executeRpc": {
"method": "getState",
"requestTimeout": 5000,
"requestPersistent": false,
"persistentPollingInterval": 1000
},
"getAttribute": {
"scope": null,
"key": "state"
},
"getTimeSeries": {
"key": "state"
},
"getAlarmStatus": {
"severityList": [
"CRITICAL"
],
"typeList": null
},
"dataToValue": {
"type": "NONE",
"dataToValueFunction": "/* Should return boolean value */\nreturn data;",
"compareToValue": true
}
},
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": null
},
{
"id": "criticalClick",
"name": "{i18n:scada.symbol.critical-click}",
"hint": "{i18n:scada.symbol.on-click-hint}",
"group": "{i18n:scada.symbol.critical-state}",
"type": "widgetAction",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": null,
"defaultGetValueSettings": null,
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": {
"type": "doNothing",
"targetDashboardStateId": null,
"openRightLayout": false,
"setEntityId": false,
"stateEntityParamName": null
}
},
{
"id": "criticalAnimation",
"name": "{i18n:scada.symbol.warning-critical-state-animation}",
"hint": "{i18n:scada.symbol.warning-critical-state-animation-hint}",
"group": null,
"type": "value",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": "{i18n:scada.symbol.animation}",
"defaultGetValueSettings": {
"action": "DO_NOTHING",
"defaultValue": false,
"executeRpc": {
"method": "getState",
"requestTimeout": 5000,
"requestPersistent": false,
"persistentPollingInterval": 1000
},
"getAttribute": {
"key": "state",
"scope": null
},
"getTimeSeries": {
"key": "state"
},
"dataToValue": {
"type": "NONE",
"compareToValue": true,
"dataToValueFunction": "/* Should return boolean value */\nreturn data;"
}
},
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": null
},
{
"id": "click",
"name": "{i18n:scada.symbol.on-click}",
"hint": "{i18n:scada.symbol.on-click-hint}",
"group": null,
"type": "widgetAction",
"valueType": "BOOLEAN",
"trueLabel": null,
"falseLabel": null,
"stateLabel": null,
"defaultGetValueSettings": null,
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": {
"type": "doNothing",
"targetDashboardStateId": null,
"openRightLayout": false,
"setEntityId": false,
"stateEntityParamName": null
}
}
],
"properties": [
{
"id": "runningColor",
"name": "{i18n:scada.symbol.colors}",
"type": "color",
"default": "#FFFFFF",
"required": null,
"subLabel": "{i18n:scada.symbol.running}",
"divider": true,
"fieldSuffix": null,
"disableOnProperty": null,
"rowClass": "",
"fieldClass": "",
"min": null,
"max": null,
"step": null,
"disabled": false,
"visible": true
},
{
"id": "stoppedColor",
"name": "{i18n:scada.symbol.colors}",
"type": "color",
"default": "#666666",
"required": null,
"subLabel": "{i18n:scada.symbol.stopped}",
"divider": null,
"fieldSuffix": null,
"disableOnProperty": null,
"rowClass": "",
"fieldClass": "",
"min": null,
"max": null,
"step": null,
"disabled": false,
"visible": true
},
{
"id": "warningColor",
"name": "{i18n:scada.symbol.alarm-colors}",
"type": "color",
"default": "#FAA405",
"required": null,
"subLabel": "{i18n:scada.symbol.warning}",
"divider": true,
"fieldSuffix": null,
"disableOnProperty": null,
"rowClass": "",
"fieldClass": "",
"min": null,
"max": null,
"step": null,
"disabled": false,
"visible": true
},
{
"id": "criticalColor",
"name": "{i18n:scada.symbol.alarm-colors}",
"type": "color",
"default": "#D12730",
"required": null,
"subLabel": "{i18n:scada.symbol.critical}",
"divider": null,
"fieldSuffix": null,
"disableOnProperty": null,
"rowClass": "",
"fieldClass": "",
"min": null,
"max": null,
"step": null,
"disabled": false,
"visible": true
}
]
}]]></tb:metadata>
<g fill="#fff" stroke="#000" tb:tag="background">
<path d="m299.54 4.8761c0.168-0.54602 0.322-1.0458 0.462-1.4976 0.14 0.4518 0.294 0.95157 0.462 1.4976 0.90101 2.9339 2.188 7.2028 3.734 12.54 3.09 10.674 7.211 25.619 11.332 42.697 8.247 34.178 16.472 76.822 16.472 110.89s-8.225 76.708-16.472 110.89c-4.121 17.079-8.242 32.023-11.332 42.698-1.546 5.3367-2.833 9.6057-3.734 12.54-0.168 0.54586-0.322 1.0457-0.462 1.4976-0.14-0.45189-0.294-0.95177-0.462-1.4976-0.90101-2.9343-2.188-7.2032-3.734-12.54-3.09-10.674-7.211-25.619-11.332-42.698-8.247-34.178-16.472-76.821-16.472-110.89s8.225-76.708 16.472-110.89c4.121-17.078 8.242-32.023 11.332-42.697 1.546-5.337 2.833-9.606 3.734-12.54z" stroke-width="2"/>
<path d="m594.35 510.77c0.38868 0.4189 0.74439 0.80179 1.0651 1.1497-0.46062-0.10497-0.97021-0.22094-1.5268-0.34891-2.9896-0.68682-7.328-1.7065-12.719-3.0372-10.783-2.6613-25.777-6.5663-42.618-11.537-33.703-9.9494-74.721-24.149-104.2-41.181-29.484-17.032-62.284-45.474-87.747-69.704-12.724-12.107-23.6-23.146-31.295-31.16-3.8479-4.0059-6.8994-7.2551-8.9887-9.5015-0.38868-0.4189-0.74439-0.80179-1.0651-1.1497 0.46063 0.10497 0.97021 0.22094 1.5268 0.34891 2.9896 0.68682 7.328 1.7065 12.72 3.0372 10.782 2.6613 25.776 6.5663 42.617 11.537 33.703 9.9494 74.721 24.149 104.21 41.181 29.483 17.032 62.283 45.474 87.746 69.704 12.724 12.107 23.6 23.146 31.295 31.16 3.8479 4.0059 6.8994 7.2551 8.9887 9.5015z" stroke-width="1.9997"/>
<path d="m8.8693 513.3c-0.55636 0.12796-1.066 0.24393-1.527 0.3489 0.32108-0.3479 0.67656-0.73081 1.0654-1.1497 2.0893-2.2464 5.1409-5.4956 8.9883-9.5025 7.695-8.0129 18.571-19.052 31.294-31.159 25.462-24.23 58.262-52.672 87.745-69.704 29.484-17.032 70.502-31.232 104.2-41.181 16.841-4.9707 31.835-8.8756 42.617-11.537 5.3916-1.3306 9.73-2.3504 12.72-3.0372 0.55655-0.12797 1.0661-0.24394 1.5267-0.34891-0.32074 0.34791-0.67644 0.73081-1.0651 1.1497-2.0893 2.2464-5.1408 5.4956-8.9886 9.5015-7.6947 8.0139-18.571 19.053-31.294 31.16-25.462 24.23-58.262 52.672-87.746 69.704-29.483 17.032-70.502 31.232-104.2 41.181-16.84 4.9707-31.834 8.8756-42.617 11.537-5.3914 1.3306-9.7295 2.3504-12.719 3.0372z" stroke-width="1.9997"/>
<path d="m261.06 799 25.887-456h26.11l25.887 456z" stroke-width="2"/>
<circle cx="300" cy="342" r="33" stroke-width="2"/>
<rect x="247" y="777" width="106" height="22" rx="1" stroke-width="2"/>
</g><path d="m201.8 0s-201.8 0-201.8 134v656.72c0 5.3024 5.3727 9.2808 12 9.2808h576c6.627 0 12-3.9784 12-9.2808v-656.72c0-134-198.21-134-198.21-134h-101.79zm201.21 162.4c-3.8661 0-6.9999 2.5072-6.9999 5.6v600.8c0 3.0928 3.1341 5.6 6.9999 5.6h43.998c3.8661 0 6.9999-2.5072 6.9999-5.6v-600.8c0-3.0928-3.1341-5.6-6.9999-5.6z" fill-opacity="0" tb:tag="clickArea"/><g transform="translate(0,716)" fill="#d12730" style="display: none;" tb:tag="critical">
<rect width="84" height="84" rx="4" fill="#fff" style=""/>
<rect width="84" height="84" rx="4" style=""/>
<rect x="2" y="2" width="80" height="80" rx="2" stroke="#000" stroke-opacity=".87" stroke-width="4" style=""/>
<path d="m44.559 27.562-0.4688 20.059h-4.0234l-0.4883-20.059zm-5.1172 26.211c0-0.7161 0.2344-1.3151 0.7031-1.7968 0.4818-0.4948 1.1459-0.7422 1.9922-0.7422 0.8334 0 1.4909 0.2474 1.9727 0.7422 0.4817 0.4817 0.7226 1.0807 0.7226 1.7968 0 0.6901-0.2409 1.2826-0.7226 1.7774-0.4818 0.4818-1.1393 0.7226-1.9727 0.7226-0.8463 0-1.5104-0.2408-1.9922-0.7226-0.4687-0.4948-0.7031-1.0873-0.7031-1.7774z" fill="#000" fill-opacity=".87" style=""/>
</g><g transform="translate(0 720.94)" fill="#faa405" style="display: none;" tb:tag="warning">
<path d="m35.955 2.2112c1.4741-2.9482 5.6813-2.9482 7.1554 0l35.528 71.056c1.3298 2.6596-0.6042 5.7889-3.5777 5.7889h-71.056c-2.9735 0-4.9075-3.1292-3.5777-5.7889z" fill="#fff" style=""/>
<path d="m35.955 2.2112c1.4741-2.9482 5.6813-2.9482 7.1554 0l35.528 71.056c1.3298 2.6596-0.6042 5.7889-3.5777 5.7889h-71.056c-2.9735 0-4.9075-3.1292-3.5777-5.7889z" style=""/>
<path d="m37.72 3.1061c0.7371-1.4741 2.8407-1.4741 3.5778-1e-5l35.528 71.056c0.6649 1.3298-0.3021 2.8944-1.7888 2.8944h-71.056c-1.4868 0-2.4538-1.5646-1.7889-2.8944z" stroke="#000" stroke-opacity=".87" stroke-width="4" style=""/>
<path d="m42.092 32.618-0.4688 20.059h-4.0234l-0.4883-20.059zm-5.1172 26.211c0-0.7161 0.2344-1.3151 0.7031-1.7968 0.4818-0.4948 1.1459-0.7422 1.9922-0.7422 0.8334 0 1.4909 0.2474 1.9727 0.7422 0.4817 0.4817 0.7226 1.0807 0.7226 1.7968 0 0.6901-0.2409 1.2826-0.7226 1.7774-0.4818 0.4818-1.1393 0.7226-1.9727 0.7226-0.8463 0-1.5104-0.2408-1.9922-0.7226-0.4687-0.4948-0.7031-1.0873-0.7031-1.7774z" fill="#000" fill-opacity=".87" style=""/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 15 KiB

6
application/src/main/data/json/system/widget_bundles/general_high_performance_scada_symbols.json

@ -28,6 +28,10 @@
"hp_left_tee_connector",
"hp_top_tee_connector",
"hp_drawwork",
"hp_crane"
"hp_crane",
"hp_consumers",
"hp_house",
"hp_apartments",
"hp_manufacture"
]
}

48
application/src/main/data/json/system/widget_bundles/high_performance_scada_energy_system.json

@ -0,0 +1,48 @@
{
"widgetsBundle": {
"alias": "high_performance_scada_energy_system",
"title": "High-performance SCADA energy system",
"image": "tb-image:aHBfc2NhZGFfZW5lcmd5X3N5c3RlbV9idW5kbGVfaW1hZ2UucG5n:IkhpZ2gtcGVyZm9ybWFuY2UgU0NBREEgZW5lcmd5IHN5c3RlbSIgc3lzdGVtIGJ1bmRsZSBpbWFnZQ==:SU1BR0U=;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAACgCAMAAAB+IdObAAAAllBMVEXe3t7b29vf398AAADf39/e3t7e3t7////Gxsbj4+OpqanFxcW5ubmtra2xsbGVlZWlpaWhoaHS0tLx8fG2trbU1NTBwcGvr6+MjIybm5twcHC+vr6jo6OYmJizs7Orq6vExMSZmZnCwsKdnZ2ampqRkZE3Nze7u7t+fn6EhIRjY2NVVVVsbGx5eXmJiYlEREQvLy8aGhprAy3xAAAABnRSTlPvIK8Av79l/pT7AAAJyElEQVR42uzVXW/aMBiGYWin57VjmyRmNGFLKOWjQACt/P8/t7yJQVMPrE62KkBcR88ZuokTD56HPwa4dU/D58Hw9jNabcYT7sIdHKve4F5C8Ai5No+Qa/MIuTaPkGvzCLk2QSHKIB6rFAIEhayniCc9fVx2c2ou++OUwi88ZGEtYrHbfZOf9/59r9w2f963Fj7hIUaOK0SSWyKSS8s7461rsOmk3TMNj/CQKVGBOJSiTsJNkpjcACjHxOYWHsEhCyJhEYWW1FkDeKNeDcD0c2LgERpi+McrxFFqIYQeaQCqnshWrQAUL7zFGh7BIVNq5YjDJm1Jnfd7lySrnQLT23aX8AgPWbjTG0VFTHKJyohlXLKZ8xy/wiMwxB3rsUEwd0yZ+ecdyQCs+yk1PAJDMuokiMFmxMZl/9W6PJ2EOlrBIzAkp84IUahym6yOG7D0WCarXQE2Oq6Scm3gERoyJxbrA5wJfiCV4l3zljVPu5R8IW7gERZy+fKPC0SgJu4e+XS0Ss+/FSkkI2eKQJ8vxOx7L8RXcjaI4W3GF2KhAKhU8CXYbTHjrZfwCAz5Tc4LohA/pVy7nbZRqds7IVYaHqEhc3ImFgGKkZM1TVO6XR4Oh9rtX+2uRo4BYodYQY7UCCDofwggdoiRdJYDuOEQYuFXYjEqk68qqwKIHZJHCoGQ9FVSgcUNSe8lxNBFBXarIVrSmQG71ZC/1Jpdc6sgEIbv3AXRIB9VE2OStmN6mpnT8/9/3RlSbGTxzmFC9yYTfV14wrIsRLQk/f4ikHDhM+ANVSD6BSB/VLg39SbDJKCyBxFst1o0tkEOsEP2ID20q/nXEFH2IK+Aai1tVVSUOYgrrnYrsx0VEQ2Zg3A6HVq/rlNRkzlI7U/jouMgutsyKmuQEulpHMYHdKW9X8kapIl//hHcIK2Isgbp4zWDRznr9C3KGuQAzkSQorSf60R0zhnEb9G1WF77K7AvYxETm0HYJ0sEUuko2V6lu/Zax6JhM8j+a58IZIjqkav13uuoaum3gtgJJkwDYqJ6ZARvZ0VFm0Nr4oC3NCBv3teBhJGzHS2I240g3MXVjScBEXTzcVm0S0WHbSBsYsAY+6fTgJDJLtOBdB2wzn0kD62yMYdew2z94dSIbaFFB2T/9Ql6YglA5kh6UxUf7X0cwNu9J/b1VCk5izaB7J1nt470t2TpVwup5pGwc/q1P0Q73ymzBYRPrqF7KzdMMEcYAHK79CpHDaDNUcHDEHFraE0ffLaPKUGJYizqwGldnAQKcyyuNrjO0YotIN3+YX2CEbno0OelKCofRgMLb/WiyLZolBYijqKZy5GakbudyhOkbHXM4Yt2UayQgCxzBMER1jiK2oOskZzb/EDqgvqTi7Kx8SJLRcfcQI60oWLwd16W5Qi+RCR5gYQcwYuSPKgiSxkNXE4glEO3D2cYvi6gBNXKfEAoB17oDv1loZaGkuQCQji0sG/0Pyu+BGFIHjjmASKDNrTr+VmRHmB4GoSchTM+B5CWLSisQOKrYvQwnvtiSy9n/PNBSvUYC/7hO4enWswgofNyd+Je33Hxw2KvzwYpR991I6wG9L44ADNVXYYgqhGSwY8I70/5b+fyuSBKAjDRCaPBmX4HZ8a3ik1dDt/OK7VrEVZEWvB3YQFG9VQQ+b+9c1tuGwTCcI+wIJCEhK26suW2aafpRfv+j9ehIgtZuQk20QRn8t9kRP7Y+5nDamUUDfbzr1AzWT2oDTQ65G+YQfiPYPqmBxD3TU0jh9tnHlo74CgGzHLRH5gKqUJ6xGBSTM6mLxwl1NMNrc1FPdLxexzsZq6iFONegCDBdJxPWgBNzvDgwrVnG5GqDavPBemkIBxM+ewHd4Rq/lEtTYREHLvn2njmJnJQB/Nq64sPtcWhFf34AswXjcd/JkvqrGcAoSey3xR+iauiX4sdjrBwTjwG00RIngGk2vJIdcUwRuMNNecCZDTC9pFJn/w0/kfSwjlqk0Eoh5Cdb67ji7o7AA4IEkwu+AFNgpCsKQpCxsQ0YLvDq9FkcdUCrtoKTTEtM1MGSS4Ijoj5KiJDWceFpmiyyz4Eacm2pzrq3WlVEgrSIQeM97deWayiPGzlffFkBm8Kqs3msRm/AgherIaBvOsco41NNk6I+46aUFVtgKNpJVGQnYOo5bB8xw5wZZWzyUfXyhF6nz0ATm986IysnWnHVhIF+dMcW92xpXxhC7EJws0KejoOf5xJeNMJdXq6GRqWqfydDyDIWRvAcgOdciZYcyrkg2hBzqMdmZOKTb0zFQ5CN2doDwJdbLoSkF5HDf2ySDBzzchWUz6IX3JjECzbqKlskNpvckA1WAJSk2HrKR/kK90c5IKmw61N3BxUGQVBzdmTSis4XApiKUjLvczS9JgU+X4rHQE/RMgDORAQMtwkmlJeDCVU6HhtHtbXLhPkBrNfFAztgGPiBwycT7XXPl7nJH9UQw4IjgZJyHzcxJQCgn+lRQQCKRe38kA0TePqBIjhTscUkPoUCKSA6DyQAUEiMjrcRm9KAWmn7SwAsFsvmSA7HjJAfIyGkDntqEmngPzu+cXqf2eA1HRL2ci9FF3JhhQQyTMkM0C2y4TopalpLBrEcqeJBO00UFN7BSBb0kA6AGZT0SDw34TYLkwlg3RAJzbQ/zCAaUCWDOJvBAVCFncAVr9QNIjAcjAiIx2gPEhVMIgWpBxUgl7qx+pXFA1CT7h1jyBVMF0NSK/jBhq38Q26YJA9TeMmAqGmkkFqWg7uA4imJlMwyFdaDtYcpWn1uy8YxD5w20WzMF0ByCFuoHFLNKWCbCRKcREdrAZyQ9O4XILg/SNtMogA1Ib30cFqIIqm8SNHHRamgoeWpuWg4ihLl+RjwSADBTEcJWn1q9LnyGfUrTtArQWCMZq4gcY9XlFCHEMDStEleSgYZEtXqImjDDWNySC9QPXxgVg9j0xx0DRue/byC59Qkm8+Ba0Oso3zCI0b7kwFDy2gSy1w1LQwlQuCFbqKG0gHAKyYEDfKKlB9Jkio0CEOmsQNAk1PDvJ9RpAiF0TgjtWogcStEKR6ahDZI1AeiBakHNQxSEfKeJEAouQZ+o7939+6Y3U5CP26T5N9xdiWBGL5eUKOsDtXZYL0OjTQuA0tfk8LnelC8DAk9WUge1rXNjGIWpoeVqXhLH2KmMBJmeoCkP1u90Pe6dfOCRtCGzG17FE1QogmeYrSpf0CkJZfoG0CCNb7yVUE/1JdN0jV4s3nhYIYlkiigHMx/mQ5IKa5QIYlvTBLVqUbxU7p9Rk9heoVpDS9gpSmV5DS9ApSml7Mg3XffGAvQu9ezkO037+9/sdov/n49v1fKIFpFaO3gooAAAAASUVORK5CYII=",
"scada": true,
"description": "Bundle with high-performance SCADA symbols for energy system",
"order": 9410,
"name": "High-performance SCADA energy system"
},
"widgetTypeFqns": [
"hp_solar_panel",
"hp_stand_solar_panel",
"hp_wind_turbine",
"hp_wind_turbine_cluster",
"hp_fuel_generator",
"hp_industrial_fuel_generator",
"hp_circuit_breaker2",
"hp_horizontal_circuit_breaker",
"hp_voltage_relay",
"hp_3_phase_voltage_relay",
"hp_voltage_stabilizer",
"hp_energy_meter",
"hp_two_rate_energy_meter",
"hp_three_rate_energy_meter",
"hp_four_rate_energy_meter",
"hp_electrical_distribution_board",
"hp_power_socket",
"hp_single_key_switch",
"hp_two_key_switch",
"hp_top_light_bulb",
"hp_bottom_light_bulb",
"hp_battery",
"hp_inverter",
"hp_large_inverter",
"hp_horizontal_energy_systems_controller",
"hp_vertical_energy_systems_controller",
"hp_small_power_transformer",
"hp_power_transformer",
"hp_low_voltage_transformer_tower",
"hp_low_voltage_tower",
"hp_high_voltage_tower",
"hp_consumers",
"hp_house",
"hp_apartments",
"hp_manufacture"
]
}

2
application/src/main/data/json/system/widget_types/update_device_attribute.json

@ -9,7 +9,7 @@
"sizeX": 4,
"sizeY": 2,
"resources": [],
"templateHtml": "<div class=\"tb-rpc-button flex flex-col\">\n <div class=\"title-container flex max-w-20% flex-full flex-row items-center justify-center\"\n [class.!hidden]=\"!showTitle\">\n <span class=\"button-title\">{{title}}</span>\n </div>\n <div class=\"button-container flex flex-full flex-col items-center justify-center\"\n [class]=\"{\n 'max-w-80%': showTitle,\n 'max-w-100%': !showTitle\n }\"\n [style.padding-top]=\"showTitle ? '5px': '10px'\">\n <div>\n <button mat-button (click)=\"sendCommand()\"\n [class.mat-mdc-raised-button]=\"styleButton?.isRaised\"\n [color]=\"styleButton?.isPrimary ? 'primary' : ''\"\n [style]=\"customStyle\">\n {{buttonLable}}\n </button>\n </div>\n </div>\n <div class=\"error-container flex flex-row items-center justify-center\" [style.background]=\"error?.length ? 'rgba(255,255,255,0.25)' : 'none'\">\n <span class=\"button-error\">{{ error }}</span>\n </div>\n</div>",
"templateHtml": "<div class=\"tb-rpc-button flex flex-col\">\n <div class=\"title-container flex max-w-20% flex-full flex-row items-center justify-center\"\n [class.!hidden]=\"!showTitle\">\n <span class=\"button-title\">{{title}}</span>\n </div>\n <div class=\"button-container flex flex-full flex-col items-center justify-center\"\n [class]=\"{\n 'max-w-80%': showTitle,\n 'max-w-100%': !showTitle\n }\"\n [style.padding-top]=\"showTitle ? '5px': '10px'\">\n <div>\n <button mat-button (click)=\"sendUpdate()\"\n [class.mat-mdc-raised-button]=\"styleButton?.isRaised\"\n [color]=\"styleButton?.isPrimary ? 'primary' : ''\"\n [style]=\"customStyle\">\n {{buttonLable}}\n </button>\n </div>\n </div>\n <div class=\"error-container flex flex-row items-center justify-center\" [style.background]=\"error?.length ? 'rgba(255,255,255,0.25)' : 'none'\">\n <span class=\"button-error\">{{ error }}</span>\n </div>\n</div>",
"templateCss": ".tb-rpc-button {\n width: 100%;\n height: 100%;\n}\n\n.tb-rpc-button .title-container {\n font-weight: 500;\n white-space: nowrap;\n margin: 10px 0;\n}\n\n.tb-rpc-button .button-container div{\n min-width: 80%\n}\n\n.tb-rpc-button .button-container .mat-mdc-button{\n width: 100%;\n margin: 0;\n}\n\n.tb-rpc-button .error-container {\n position: absolute;\n top: 2%;\n right: 0;\n left: 0;\n z-index: 4;\n height: 14px;\n}\n\n.tb-rpc-button .error-container .button-error {\n color: #ff3315;\n white-space: nowrap;\n}",
"controllerScript": "self.onInit = function() {\n self.ctx.ngZone.run(function() {\n init(); \n self.ctx.detectChanges();\n });\n};\n\nfunction init() {\n self.ctx.$scope.buttonLable = self.ctx.settings.buttonText;\n self.ctx.$scope.showTitle = self.ctx.settings.title &&\n self.ctx.settings.title.length ? true : false;\n self.ctx.$scope.title = self.ctx.settings.title;\n self.ctx.$scope.styleButton = self.ctx.settings.styleButton;\n let entityAttributeType = self.ctx.settings.entityAttributeType;\n let entityParameters = JSON.parse(self.ctx.settings.entityParameters);\n\n if (self.ctx.settings.styleButton.isPrimary ===\n false) {\n self.ctx.$scope.customStyle = {\n 'background-color': self.ctx.$scope.styleButton\n .bgColor,\n 'color': self.ctx.$scope.styleButton.textColor\n };\n }\n\n let attributeService = self.ctx.$scope.$injector.get(self.ctx.servicesMap.get('attributeService'));\n\n self.ctx.$scope.sendUpdate = function() {\n let attributes = [];\n for (let key in entityParameters) {\n attributes.push({\n \"key\": key,\n \"value\": entityParameters[key]\n });\n }\n \n let entityId = {\n entityType: \"DEVICE\",\n id: self.ctx.defaultSubscription.targetDeviceId\n };\n attributeService.saveEntityAttributes(entityId,\n entityAttributeType, attributes).subscribe(\n function success() {\n self.ctx.$scope.error = \"\";\n self.ctx.detectChanges();\n },\n function fail(rejection) {\n if (self.ctx.settings.showError) {\n self.ctx.$scope.error =\n rejection.status + \": \" +\n rejection.statusText;\n self.ctx.detectChanges();\n }\n }\n\n );\n };\n}\n",
"settingsSchema": "",

9
application/src/main/data/json/tenant/device_profile/rule_chain_template.json

@ -19,8 +19,13 @@
},
"type": "org.thingsboard.rule.engine.telemetry.TbMsgTimeseriesNode",
"name": "Save Timeseries",
"configurationVersion": 1,
"configuration": {
"defaultTTL": 0
"defaultTTL": 0,
"useServerTs": false,
"processingSettings": {
"type": "ON_EVERY_MESSAGE"
}
}
},
{
@ -134,4 +139,4 @@
],
"ruleChainConnections": null
}
}
}

7
application/src/main/data/json/tenant/rule_chains/root_rule_chain.json

@ -18,8 +18,13 @@
},
"type": "org.thingsboard.rule.engine.telemetry.TbMsgTimeseriesNode",
"name": "Save Timeseries",
"configurationVersion": 1,
"configuration": {
"defaultTTL": 0
"defaultTTL": 0,
"useServerTs": false,
"processingSettings": {
"type": "ON_EVERY_MESSAGE"
}
}
},
{

228
application/src/main/data/upgrade/basic/schema_update.sql

@ -14,198 +14,50 @@
-- limitations under the License.
--
ALTER TABLE user_credentials ADD COLUMN IF NOT EXISTS last_login_ts BIGINT;
UPDATE user_credentials c SET last_login_ts = (SELECT (additional_info::json ->> 'lastLoginTs')::bigint FROM tb_user u WHERE u.id = c.user_id)
WHERE last_login_ts IS NULL;
-- UPDATE SAVE TIME SERIES NODES START
ALTER TABLE user_credentials ADD COLUMN IF NOT EXISTS failed_login_attempts INT;
UPDATE user_credentials c SET failed_login_attempts = (SELECT (additional_info::json ->> 'failedLoginAttempts')::int FROM tb_user u WHERE u.id = c.user_id)
WHERE failed_login_attempts IS NULL;
UPDATE tb_user SET additional_info = (additional_info::jsonb - 'lastLoginTs' - 'failedLoginAttempts' - 'userCredentialsEnabled')::text
WHERE additional_info IS NOT NULL AND additional_info != 'null' AND jsonb_typeof(additional_info::jsonb) = 'object';
-- UPDATE RULE NODE DEBUG MODE TO DEBUG STRATEGY START
ALTER TABLE rule_node ADD COLUMN IF NOT EXISTS debug_settings varchar(1024) DEFAULT null;
DO
$$
BEGIN
IF EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'rule_node' AND column_name = 'debug_mode')
THEN
UPDATE rule_node SET debug_settings = '{"failuresEnabled": true, "allEnabledUntil": ' || cast((extract(epoch from now()) + 900) * 1000 as bigint) || '}' WHERE debug_mode = true; -- 15 minutes according to thingsboard.yml default settings.
ALTER TABLE rule_node DROP COLUMN debug_mode;
END IF;
END
$$;
-- UPDATE RULE NODE DEBUG MODE TO DEBUG STRATEGY END
-- CREATE MOBILE APP BUNDLES FROM EXISTING APPS
CREATE TABLE IF NOT EXISTS mobile_app_bundle (
id uuid NOT NULL CONSTRAINT mobile_app_bundle_pkey PRIMARY KEY,
created_time bigint NOT NULL,
tenant_id uuid,
title varchar(255),
description varchar(1024),
android_app_id uuid UNIQUE,
ios_app_id uuid UNIQUE,
layout_config varchar(16384),
oauth2_enabled boolean,
CONSTRAINT fk_android_app_id FOREIGN KEY (android_app_id) REFERENCES mobile_app(id) ON DELETE SET NULL,
CONSTRAINT fk_ios_app_id FOREIGN KEY (ios_app_id) REFERENCES mobile_app(id) ON DELETE SET NULL
);
CREATE INDEX IF NOT EXISTS mobile_app_bundle_tenant_id ON mobile_app_bundle(tenant_id);
ALTER TABLE mobile_app ADD COLUMN IF NOT EXISTS platform_type varchar(32),
ADD COLUMN IF NOT EXISTS status varchar(32),
ADD COLUMN IF NOT EXISTS version_info varchar(100000),
ADD COLUMN IF NOT EXISTS store_info varchar(16384),
DROP CONSTRAINT IF EXISTS mobile_app_pkg_name_key,
DROP CONSTRAINT IF EXISTS mobile_app_unq_key;
-- rename mobile_app_oauth2_client to mobile_app_bundle_oauth2_client
DO
$$
BEGIN
-- in case of running the upgrade script a second time
IF EXISTS(SELECT 1 FROM information_schema.tables WHERE table_name = 'mobile_app_oauth2_client') THEN
ALTER TABLE mobile_app_oauth2_client RENAME TO mobile_app_bundle_oauth2_client;
ALTER TABLE mobile_app_bundle_oauth2_client DROP CONSTRAINT IF EXISTS fk_domain;
ALTER TABLE mobile_app_bundle_oauth2_client RENAME COLUMN mobile_app_id TO mobile_app_bundle_id;
END IF;
END;
$$;
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
-- duplicate each mobile app and create mobile app bundle for the pair of android and ios app
DO
$$
DECLARE
generatedBundleId uuid;
iosAppId uuid;
mobileAppRecord RECORD;
DO $$
BEGIN
-- in case of running the upgrade script a second time
IF EXISTS(SELECT 1 FROM information_schema.columns WHERE table_name = 'mobile_app' and column_name = 'oauth2_enabled') THEN
UPDATE mobile_app SET platform_type = 'ANDROID' WHERE platform_type IS NULL;
UPDATE mobile_app SET status = 'DRAFT' WHERE mobile_app.status IS NULL;
FOR mobileAppRecord IN SELECT * FROM mobile_app
LOOP
-- duplicate app for iOS platform type
iosAppId := uuid_generate_v4();
INSERT INTO mobile_app(id, created_time, tenant_id, pkg_name, app_secret, platform_type, status)
VALUES (iosAppId, mobileAppRecord.created_time, mobileAppRecord.tenant_id, mobileAppRecord.pkg_name, mobileAppRecord.app_secret, 'IOS', mobileAppRecord.status)
ON CONFLICT DO NOTHING;
-- create bundle for android and iOS app
generatedBundleId := uuid_generate_v4();
INSERT INTO mobile_app_bundle(id, created_time, tenant_id, title, android_app_id, ios_app_id, oauth2_enabled)
VALUES (generatedBundleId, mobileAppRecord.created_time, mobileAppRecord.tenant_id,
mobileAppRecord.pkg_name || ' (autogenerated)', mobileAppRecord.id, iosAppId, mobileAppRecord.oauth2_enabled)
ON CONFLICT DO NOTHING;
UPDATE mobile_app_bundle_oauth2_client SET mobile_app_bundle_id = generatedBundleId WHERE mobile_app_bundle_id = mobileAppRecord.id;
END LOOP;
END IF;
IF NOT EXISTS(SELECT 1 FROM pg_constraint WHERE conname = 'fk_mobile_app_bundle_oauth2_client_bundle_id') THEN
ALTER TABLE mobile_app_bundle_oauth2_client ADD CONSTRAINT fk_mobile_app_bundle_oauth2_client_bundle_id
FOREIGN KEY (mobile_app_bundle_id) REFERENCES mobile_app_bundle(id) ON DELETE CASCADE;
END IF;
ALTER TABLE mobile_app DROP COLUMN IF EXISTS oauth2_enabled;
IF NOT EXISTS(SELECT 1 FROM pg_constraint WHERE conname = 'mobile_app_pkg_name_platform_unq_key') THEN
ALTER TABLE mobile_app ADD CONSTRAINT mobile_app_pkg_name_platform_unq_key UNIQUE (pkg_name, platform_type);
END IF;
END;
$$;
-- Check if the rule_node table exists
IF EXISTS (
SELECT 1
FROM information_schema.tables
WHERE table_name = 'rule_node'
) THEN
UPDATE rule_node
SET configuration = (
(configuration::jsonb - 'skipLatestPersistence')
|| jsonb_build_object(
'processingSettings', jsonb_build_object(
'type', 'ADVANCED',
'timeseries', jsonb_build_object('type', 'ON_EVERY_MESSAGE'),
'latest', jsonb_build_object('type', 'SKIP'),
'webSockets', jsonb_build_object('type', 'ON_EVERY_MESSAGE')
)
)
)::text,
configuration_version = 1
WHERE type = 'org.thingsboard.rule.engine.telemetry.TbMsgTimeseriesNode'
AND configuration_version = 0
AND configuration::jsonb ->> 'skipLatestPersistence' = 'true';
UPDATE rule_node
SET configuration = (
(configuration::jsonb - 'skipLatestPersistence')
|| jsonb_build_object(
'processingSettings', jsonb_build_object(
'type', 'ON_EVERY_MESSAGE'
)
)
)::text,
configuration_version = 1
WHERE type = 'org.thingsboard.rule.engine.telemetry.TbMsgTimeseriesNode'
AND configuration_version = 0
AND (configuration::jsonb ->> 'skipLatestPersistence' != 'true' OR configuration::jsonb ->> 'skipLatestPersistence' IS NULL);
ALTER TABLE IF EXISTS mobile_app_settings RENAME TO qr_code_settings;
ALTER TABLE qr_code_settings ADD COLUMN IF NOT EXISTS mobile_app_bundle_id uuid,
ADD COLUMN IF NOT EXISTS android_enabled boolean,
ADD COLUMN IF NOT EXISTS ios_enabled boolean;
-- migrate mobile apps from qr code settings to mobile_app, create mobile app bundle for the pair of apps
DO
$$
DECLARE
androidPkgName varchar;
iosPkgName varchar;
androidAppId uuid;
iosAppId uuid;
generatedBundleId uuid;
qrCodeRecord RECORD;
BEGIN
-- in case of running the upgrade script a second time
IF EXISTS(SELECT 1 FROM information_schema.columns WHERE table_name = 'qr_code_settings' AND column_name = 'android_config') THEN
FOR qrCodeRecord IN SELECT * FROM qr_code_settings
LOOP
generatedBundleId := NULL;
-- migrate android config
IF (qrCodeRecord.android_config::jsonb ->> 'appPackage' IS NOT NULL) THEN
androidPkgName := qrCodeRecord.android_config::jsonb ->> 'appPackage';
SELECT id into androidAppId FROM mobile_app WHERE pkg_name = androidPkgName AND platform_type = 'ANDROID';
IF androidAppId IS NULL THEN
androidAppId := uuid_generate_v4();
INSERT INTO mobile_app(id, created_time, tenant_id, pkg_name, platform_type, status, store_info)
VALUES (androidAppId, (extract(epoch from now()) * 1000), qrCodeRecord.tenant_id,
androidPkgName, 'ANDROID', 'DRAFT', qrCodeRecord.android_config::jsonb - 'appPackage' - 'enabled');
generatedBundleId := uuid_generate_v4();
INSERT INTO mobile_app_bundle(id, created_time, tenant_id, title, android_app_id)
VALUES (generatedBundleId, (extract(epoch from now()) * 1000), qrCodeRecord.tenant_id, androidPkgName || ' (autogenerated)', androidAppId);
UPDATE qr_code_settings SET mobile_app_bundle_id = generatedBundleId;
ELSE
UPDATE mobile_app SET store_info = qrCodeRecord.android_config::jsonb - 'appPackage' - 'enabled' WHERE id = androidAppId;
UPDATE qr_code_settings SET mobile_app_bundle_id = (SELECT id FROM mobile_app_bundle WHERE mobile_app_bundle.android_app_id = androidAppId);
END IF;
END IF;
UPDATE qr_code_settings SET android_enabled = (qrCodeRecord.android_config::jsonb ->> 'enabled')::boolean WHERE id = qrCodeRecord.id;
-- migrate ios config
IF (qrCodeRecord.ios_config::jsonb ->> 'appId' IS NOT NULL) THEN
iosPkgName := substring(qrCodeRecord.ios_config::jsonb ->> 'appId', strpos(qrCodeRecord.ios_config::jsonb ->> 'appId', '.') + 1);
SELECT id INTO iosAppId FROM mobile_app WHERE pkg_name = iosPkgName AND platform_type = 'IOS';
IF iosAppId IS NULL THEN
iosAppId := uuid_generate_v4();
INSERT INTO mobile_app(id, created_time, tenant_id, pkg_name, platform_type, status, store_info)
VALUES (iosAppId, (extract(epoch from now()) * 1000), qrCodeRecord.tenant_id,
iosPkgName, 'IOS', 'DRAFT', qrCodeRecord.ios_config::jsonb - 'enabled');
IF generatedBundleId IS NULL THEN
generatedBundleId := uuid_generate_v4();
INSERT INTO mobile_app_bundle(id, created_time, tenant_id, title, ios_app_id)
VALUES (generatedBundleId, (extract(epoch from now()) * 1000), qrCodeRecord.tenant_id, iosPkgName || ' (autogenerated)', iosAppId);
UPDATE qr_code_settings SET mobile_app_bundle_id = generatedBundleId;
ELSE
UPDATE mobile_app_bundle SET ios_app_id = iosAppId WHERE id = generatedBundleId;
END IF;
ELSE
UPDATE qr_code_settings SET mobile_app_bundle_id = (SELECT id FROM mobile_app_bundle WHERE mobile_app_bundle.ios_app_id = iosAppId);
UPDATE mobile_app SET store_info = qrCodeRecord.ios_config::jsonb - 'enabled' WHERE id = iosAppId;
END IF;
END IF;
UPDATE qr_code_settings SET ios_enabled = (qrCodeRecord.ios_config::jsonb -> 'enabled')::boolean WHERE id = qrCodeRecord.id;
END LOOP;
ALTER TABLE qr_code_settings RENAME CONSTRAINT mobile_app_settings_tenant_id_unq_key TO qr_code_settings_tenant_id_unq_key;
ALTER TABLE qr_code_settings RENAME CONSTRAINT mobile_app_settings_pkey TO qr_code_settings_pkey;
END IF;
ALTER TABLE qr_code_settings DROP COLUMN IF EXISTS android_config, DROP COLUMN IF EXISTS ios_config;
END;
$$;
-- update constraint name
DO
$$
BEGIN
ALTER TABLE domain DROP CONSTRAINT IF EXISTS domain_unq_key;
IF NOT EXISTS(SELECT 1 FROM pg_constraint WHERE conname = 'domain_name_key') THEN
ALTER TABLE domain ADD CONSTRAINT domain_name_key UNIQUE (name);
END IF;
END;
$$;
-- UPDATE RESOURCE JS_MODULE SUB TYPE START
UPDATE resource SET resource_sub_type = 'EXTENSION' WHERE resource_type = 'JS_MODULE' AND resource_sub_type IS NULL;
-- UPDATE RESOURCE JS_MODULE SUB TYPE END
-- UPDATE SAVE TIME SERIES NODES END

2
application/src/main/java/org/thingsboard/server/actors/device/DeviceActorMessageProcessor.java

@ -865,6 +865,8 @@ public class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcesso
}
private void notifyTransportAboutClosedSessionMaxSessionsLimit(UUID sessionId, SessionInfoMetaData sessionMd) {
attributeSubscriptions.remove(sessionId);
rpcSubscriptions.remove(sessionId);
notifyTransportAboutClosedSession(sessionId, sessionMd, TransportSessionCloseReason.MAX_CONCURRENT_SESSIONS_LIMIT_REACHED);
}

25
application/src/main/java/org/thingsboard/server/config/SwaggerConfiguration.java

@ -84,6 +84,7 @@ import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
public class SwaggerConfiguration {
public static final String LOGIN_ENDPOINT = "/api/auth/login";
public static final String REFRESH_TOKEN_ENDPOINT = "/api/auth/token";
private static final ApiResponses loginResponses = loginResponses();
private static final ApiResponses defaultErrorResponses = defaultErrorResponses(false);
@ -150,6 +151,7 @@ public class SwaggerConfiguration {
.info(info);
addDefaultSchemas(openApi);
addLoginOperation(openApi);
addRefreshTokenOperation(openApi);
return openApi;
}
@ -210,6 +212,29 @@ public class SwaggerConfiguration {
openAPI.path(LOGIN_ENDPOINT, pathItem);
}
private void addRefreshTokenOperation(OpenAPI openAPI) {
var operation = new Operation();
operation.summary("Refresh user JWT token data");
operation.description("""
Method to refresh JWT token. Provide a valid refresh token to get a new JWT token.
The response contains a new token that can be used for authorization.
`X-Authorization: Bearer $JWT_TOKEN_VALUE`""");
var requestBody = new RequestBody().description("Refresh token request")
.content(new Content().addMediaType(APPLICATION_JSON_VALUE,
new MediaType().schema(new Schema<JsonNode>().addProperty("refreshToken", new Schema<>().type("string")))));
operation.requestBody(requestBody);
operation.responses(loginResponses);
operation.addTagsItem("login-endpoint");
var pathItem = new PathItem().post(operation);
openAPI.path(REFRESH_TOKEN_ENDPOINT, pathItem);
}
@Bean
public GroupedOpenApi groupedApi(SpringDocParameterNameDiscoverer localSpringDocParameterNameDiscoverer) {
return GroupedOpenApi.builder()

19
application/src/main/java/org/thingsboard/server/install/ThingsboardInstallService.java

@ -35,8 +35,6 @@ import org.thingsboard.server.service.install.migrate.TsLatestMigrateService;
import org.thingsboard.server.service.install.update.CacheCleanupService;
import org.thingsboard.server.service.install.update.DataUpdateService;
import static org.thingsboard.server.service.install.update.DefaultDataUpdateService.getEnv;
@Service
@Profile("install")
@Slf4j
@ -99,8 +97,6 @@ public class ThingsboardInstallService {
if ("cassandra-latest-to-postgres".equals(upgradeFromVersion)) {
log.info("Migrating ThingsBoard latest timeseries data from cassandra to SQL database ...");
latestMigrateService.migrate();
} else if (upgradeFromVersion.equals("3.9.0-resources")) {
installScripts.updateResourcesUsage();
} else {
// TODO DON'T FORGET to update SUPPORTED_VERSIONS_FROM in DefaultDatabaseSchemaSettingsService
databaseSchemaVersionService.validateSchemaSettings();
@ -118,25 +114,16 @@ public class ThingsboardInstallService {
entityDatabaseSchemaService.createOrUpdateDeviceInfoView(persistToTelemetry);
// Creates missing indexes.
entityDatabaseSchemaService.createDatabaseIndexes();
// Runs upgrade scripts that are not possible in plain SQL.
// TODO: cleanup update code after each release
if (!getEnv("SKIP_RESOURCES_USAGE_MIGRATION", false)) {
installScripts.setUpdateResourcesUsage(true);
} else {
log.info("Skipping resources usage migration. Run the upgrade with fromVersion as '3.9.0-resources' to migrate");
}
if (installScripts.isUpdateResourcesUsage()) {
installScripts.updateResourcesUsage();
}
// Runs upgrade scripts that are not possible in plain SQL.
dataUpdateService.updateData();
log.info("Updating system data...");
dataUpdateService.upgradeRuleNodes();
systemDataLoaderService.loadSystemWidgets();
installScripts.loadSystemLwm2mResources();
installScripts.loadSystemImagesAndResources();
if (installScripts.isUpdateImages()) {
installScripts.updateImages();
}
databaseSchemaVersionService.updateSchemaVersion();
}
log.info("Upgrade finished successfully!");

62
application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/dashboard/BaseDashboardProcessor.java

@ -26,6 +26,7 @@ import org.thingsboard.server.dao.service.DataValidator;
import org.thingsboard.server.gen.edge.v1.DashboardUpdateMsg;
import org.thingsboard.server.service.edge.rpc.processor.BaseEdgeProcessor;
import java.util.HashSet;
import java.util.Set;
@Slf4j
@ -40,54 +41,63 @@ public abstract class BaseDashboardProcessor extends BaseEdgeProcessor {
if (dashboard == null) {
throw new RuntimeException("[{" + tenantId + "}] dashboardUpdateMsg {" + dashboardUpdateMsg + "} cannot be converted to dashboard");
}
Set<ShortCustomerInfo> assignedCustomers = null;
Set<ShortCustomerInfo> newAssignedCustomers = new HashSet<>(dashboard.getAssignedCustomers());
Dashboard dashboardById = edgeCtx.getDashboardService().findDashboardById(tenantId, dashboardId);
if (dashboardById == null) {
created = true;
dashboard.setId(null);
dashboard.setAssignedCustomers(null);
} else {
dashboard.setId(dashboardId);
assignedCustomers = filterNonExistingCustomers(tenantId, dashboardById.getAssignedCustomers());
dashboard.setAssignedCustomers(dashboardById.getAssignedCustomers());
}
dashboardValidator.validate(dashboard, Dashboard::getTenantId);
if (created) {
dashboard.setId(dashboardId);
}
Set<ShortCustomerInfo> msgAssignedCustomers = filterNonExistingCustomers(tenantId, dashboard.getAssignedCustomers());
if (msgAssignedCustomers != null) {
if (assignedCustomers == null) {
assignedCustomers = msgAssignedCustomers;
} else {
assignedCustomers.addAll(msgAssignedCustomers);
Dashboard savedDashboard = edgeCtx.getDashboardService().saveDashboard(dashboard, false);
updateDashboardAssignments(tenantId, dashboardById, savedDashboard, newAssignedCustomers);
return created;
}
private void updateDashboardAssignments(TenantId tenantId, Dashboard dashboardById, Dashboard savedDashboard, Set<ShortCustomerInfo> newAssignedCustomers) {
Set<ShortCustomerInfo> currentAssignedCustomers = new HashSet<>();
if (dashboardById != null) {
if (dashboardById.getAssignedCustomers() != null) {
currentAssignedCustomers.addAll(dashboardById.getAssignedCustomers());
}
}
dashboard.setAssignedCustomers(assignedCustomers);
Dashboard savedDashboard = edgeCtx.getDashboardService().saveDashboard(dashboard, false);
if (msgAssignedCustomers != null && !msgAssignedCustomers.isEmpty()) {
for (ShortCustomerInfo assignedCustomer : msgAssignedCustomers) {
if (assignedCustomer.getCustomerId().equals(customerId)) {
edgeCtx.getDashboardService().assignDashboardToCustomer(tenantId, savedDashboard.getId(), assignedCustomer.getCustomerId());
}
newAssignedCustomers = filterNonExistingCustomers(tenantId, currentAssignedCustomers, newAssignedCustomers);
Set<CustomerId> addedCustomerIds = new HashSet<>();
Set<CustomerId> removedCustomerIds = new HashSet<>();
for (ShortCustomerInfo newAssignedCustomer : newAssignedCustomers) {
if (!savedDashboard.isAssignedToCustomer(newAssignedCustomer.getCustomerId())) {
addedCustomerIds.add(newAssignedCustomer.getCustomerId());
}
} else {
unassignCustomersFromDashboard(tenantId, savedDashboard, customerId);
}
return created;
}
private void unassignCustomersFromDashboard(TenantId tenantId, Dashboard dashboard, CustomerId customerId) {
if (dashboard.getAssignedCustomers() != null && !dashboard.getAssignedCustomers().isEmpty()) {
for (ShortCustomerInfo assignedCustomer : dashboard.getAssignedCustomers()) {
if (assignedCustomer.getCustomerId().equals(customerId)) {
edgeCtx.getDashboardService().unassignDashboardFromCustomer(tenantId, dashboard.getId(), assignedCustomer.getCustomerId());
}
for (ShortCustomerInfo currentAssignedCustomer : currentAssignedCustomers) {
if (!newAssignedCustomers.contains(currentAssignedCustomer)) {
removedCustomerIds.add(currentAssignedCustomer.getCustomerId());
}
}
for (CustomerId customerIdToAdd : addedCustomerIds) {
edgeCtx.getDashboardService().assignDashboardToCustomer(tenantId, savedDashboard.getId(), customerIdToAdd);
}
for (CustomerId customerIdToRemove : removedCustomerIds) {
edgeCtx.getDashboardService().unassignDashboardFromCustomer(tenantId, savedDashboard.getId(), customerIdToRemove);
}
}
protected abstract Dashboard constructDashboardFromUpdateMsg(TenantId tenantId, DashboardId dashboardId, DashboardUpdateMsg dashboardUpdateMsg);
protected abstract Set<ShortCustomerInfo> filterNonExistingCustomers(TenantId tenantId, Set<ShortCustomerInfo> assignedCustomers);
protected abstract Set<ShortCustomerInfo> filterNonExistingCustomers(TenantId tenantId, Set<ShortCustomerInfo> currentAssignedCustomers, Set<ShortCustomerInfo> newAssignedCustomers);
}

6
application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/dashboard/DashboardEdgeProcessor.java

@ -128,9 +128,9 @@ public abstract class DashboardEdgeProcessor extends BaseDashboardProcessor impl
}
@Override
protected Set<ShortCustomerInfo> filterNonExistingCustomers(TenantId tenantId, Set<ShortCustomerInfo> assignedCustomers) {
// do nothing on cloud
return assignedCustomers;
protected Set<ShortCustomerInfo> filterNonExistingCustomers(TenantId tenantId, Set<ShortCustomerInfo> currentAssignedCustomers, Set<ShortCustomerInfo> newAssignedCustomers) {
newAssignedCustomers.addAll(currentAssignedCustomers);
return newAssignedCustomers;
}
}

3
application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/dashboard/DashboardEdgeProcessorV1.java

@ -26,6 +26,7 @@ import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.gen.edge.v1.DashboardUpdateMsg;
import org.thingsboard.server.queue.util.TbCoreComponent;
import java.util.HashSet;
import java.util.Set;
@Component
@ -44,7 +45,7 @@ public class DashboardEdgeProcessorV1 extends DashboardEdgeProcessor {
Set<ShortCustomerInfo> assignedCustomers;
if (dashboardUpdateMsg.hasAssignedCustomers()) {
assignedCustomers = JacksonUtil.fromString(dashboardUpdateMsg.getAssignedCustomers(), new TypeReference<>() {});
assignedCustomers = filterNonExistingCustomers(tenantId, assignedCustomers);
assignedCustomers = filterNonExistingCustomers(tenantId, new HashSet<>(), assignedCustomers);
dashboard.setAssignedCustomers(assignedCustomers);
}
dashboard.setMobileOrder(dashboardUpdateMsg.hasMobileOrder() ? dashboardUpdateMsg.getMobileOrder() : null);

3
application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/resource/BaseResourceProcessor.java

@ -53,6 +53,9 @@ public abstract class BaseResourceProcessor extends BaseEdgeProcessor {
}
String resourceKey = resource.getResourceKey();
ResourceType resourceType = resource.getResourceType();
if (!created && !resourceType.isUpdatable()) {
resource.setData(null);
}
PageDataIterable<TbResource> resourcesIterable = new PageDataIterable<>(
link -> edgeCtx.getResourceService().findTenantResourcesByResourceTypeAndPageLink(tenantId, resourceType, link), 1024);
for (TbResource tbResource : resourcesIterable) {

8
application/src/main/java/org/thingsboard/server/service/entitiy/dashboard/DashboardSyncService.java

@ -17,6 +17,7 @@ package org.thingsboard.server.service.entitiy.dashboard;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.stereotype.Service;
@ -30,6 +31,7 @@ import org.thingsboard.server.dao.widget.WidgetsBundleService;
import org.thingsboard.server.queue.discovery.PartitionService;
import org.thingsboard.server.queue.util.AfterStartUp;
import org.thingsboard.server.queue.util.TbCoreComponent;
import org.thingsboard.server.service.install.ProjectInfo;
import org.thingsboard.server.service.sync.GitSyncService;
import org.thingsboard.server.service.sync.vc.GitRepository.FileType;
import org.thingsboard.server.service.sync.vc.GitRepository.RepoFile;
@ -51,10 +53,11 @@ public class DashboardSyncService {
private final ImageService imageService;
private final WidgetsBundleService widgetsBundleService;
private final PartitionService partitionService;
private final ProjectInfo projectInfo;
@Value("${transport.gateway.dashboard.sync.repository_url:}")
private String repoUrl;
@Value("${transport.gateway.dashboard.sync.branch:main}")
@Value("${transport.gateway.dashboard.sync.branch:}")
private String branch;
@Value("${transport.gateway.dashboard.sync.fetch_frequency:24}")
private int fetchFrequencyHours;
@ -64,6 +67,9 @@ public class DashboardSyncService {
@AfterStartUp(order = AfterStartUp.REGULAR_SERVICE)
public void init() throws Exception {
if (StringUtils.isBlank(branch)) {
branch = "release/" + projectInfo.getProjectVersion();
}
gitSyncService.registerSync(REPO_KEY, repoUrl, branch, TimeUnit.HOURS.toMillis(fetchFrequencyHours), this::update);
}

2
application/src/main/java/org/thingsboard/server/service/entitiy/entityview/DefaultTbEntityViewService.java

@ -348,7 +348,7 @@ public class DefaultTbEntityViewService extends AbstractTbEntityService implemen
.tenantId(entityView.getTenantId())
.entityId(entityId)
.entries(latestValues)
.onlyLatest(true)
.strategy(TimeseriesSaveRequest.Strategy.LATEST_AND_WS)
.callback(new FutureCallback<Void>() {
@Override
public void onSuccess(@Nullable Void tmp) {

42
application/src/main/java/org/thingsboard/server/service/install/DefaultDatabaseSchemaSettingsService.java

@ -17,9 +17,6 @@ package org.thingsboard.server.service.install;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.info.BuildProperties;
import org.springframework.context.annotation.Profile;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
@ -33,37 +30,29 @@ import java.util.List;
@RequiredArgsConstructor
public class DefaultDatabaseSchemaSettingsService implements DatabaseSchemaSettingsService {
private static final String CURRENT_PRODUCT = "CE";
// This list should include all versions which are compatible for the upgrade.
// The compatibility cycle usually breaks when we have some scripts written in Java that may not work after new release.
private static final List<String> SUPPORTED_VERSIONS_FOR_UPGRADE = List.of("3.8.0", "3.8.1");
private static final List<String> SUPPORTED_VERSIONS_FOR_UPGRADE = List.of("3.9.0");
private final BuildProperties buildProperties;
private final ProjectInfo projectInfo;
private final JdbcTemplate jdbcTemplate;
@Value("${install.upgrade.from_version:}")
private String upgradeFromVersion;
private String packageSchemaVersion;
private String schemaVersionFromDb;
@Override
public void validateSchemaSettings() {
//TODO: remove after release (3.9.0)
createProductIfNotExists();
String dbSchemaVersion = getDbSchemaVersion();
if (DefaultDataUpdateService.getEnv("SKIP_SCHEMA_VERSION_CHECK", false)) {
log.info("Skipped DB schema version check due to SKIP_SCHEMA_VERSION_CHECK set to 'true'.");
return;
}
String product = getProductFromDb();
if (!CURRENT_PRODUCT.equals(product)) {
onSchemaSettingsError(String.format("Upgrade failed: can't upgrade ThingsBoard %s database using ThingsBoard %s.", product, CURRENT_PRODUCT));
if (!projectInfo.getProductType().equals(product)) {
onSchemaSettingsError(String.format("Upgrade failed: can't upgrade ThingsBoard %s database using ThingsBoard %s.", product, projectInfo.getProductType()));
}
String dbSchemaVersion = getDbSchemaVersion();
if (dbSchemaVersion.equals(getPackageSchemaVersion())) {
onSchemaSettingsError("Upgrade failed: database already upgraded to current version. You can set SKIP_SCHEMA_VERSION_CHECK to 'true' if force re-upgrade needed.");
}
@ -75,19 +64,11 @@ public class DefaultDatabaseSchemaSettingsService implements DatabaseSchemaSetti
}
}
@Deprecated(forRemoval = true, since = "3.9.0")
private void createProductIfNotExists() {
boolean isCommunityEdition = jdbcTemplate.queryForList(
"SELECT 1 FROM information_schema.tables WHERE table_name = 'integration'", Integer.class).isEmpty();
String product = isCommunityEdition ? "CE" : "PE";
jdbcTemplate.execute("ALTER TABLE tb_schema_settings ADD COLUMN IF NOT EXISTS product varchar(2) DEFAULT '" + product + "'");
}
@Override
public void createSchemaSettings() {
Long schemaVersion = getSchemaVersionFromDb();
if (schemaVersion == null) {
jdbcTemplate.execute("INSERT INTO tb_schema_settings (schema_version, product) VALUES (" + getPackageSchemaVersionForDb() + ", '" + CURRENT_PRODUCT + "')");
jdbcTemplate.execute("INSERT INTO tb_schema_settings (schema_version, product) VALUES (" + getPackageSchemaVersionForDb() + ", '" + projectInfo.getProductType() + "')");
}
}
@ -99,7 +80,7 @@ public class DefaultDatabaseSchemaSettingsService implements DatabaseSchemaSetti
@Override
public String getPackageSchemaVersion() {
if (packageSchemaVersion == null) {
packageSchemaVersion = buildProperties.getVersion().replaceAll("[^\\d.]", "");
packageSchemaVersion = projectInfo.getProjectVersion();
}
return packageSchemaVersion;
}
@ -107,15 +88,6 @@ public class DefaultDatabaseSchemaSettingsService implements DatabaseSchemaSetti
@Override
public String getDbSchemaVersion() {
if (schemaVersionFromDb == null) {
if (StringUtils.isNotBlank(upgradeFromVersion)) {
/*
* TODO - Remove after the release of 3.9.0:
* This a temporary workaround due to the issue that schema version in the
* tb_schema_settings was set as 3.6.4 during the install of 3.8.1.
* */
schemaVersionFromDb = upgradeFromVersion;
return schemaVersionFromDb;
}
Long version = getSchemaVersionFromDb();
if (version == null) {
onSchemaSettingsError("Upgrade failed: the database schema version is missing.");

20
application/src/main/java/org/thingsboard/server/service/install/InstallScripts.java

@ -17,8 +17,6 @@ package org.thingsboard.server.service.install;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
@ -120,11 +118,6 @@ public class InstallScripts {
@Autowired
private ResourcesUpdater resourcesUpdater;
@Getter @Setter
private boolean updateImages = false;
@Getter @Setter
private boolean updateResourcesUsage = false;
@Autowired
private ImageService imageService;
@ -395,14 +388,6 @@ public class InstallScripts {
}
}
public void updateImages() {
resourcesUpdater.updateWidgetsBundlesImages();
resourcesUpdater.updateWidgetTypesImages();
resourcesUpdater.updateDashboardsImages();
resourcesUpdater.updateDeviceProfilesImages();
resourcesUpdater.updateAssetProfilesImages();
}
public void loadSystemImagesAndResources() {
log.info("Loading system images and resources...");
Stream<Path> dashboardsFiles = Stream.concat(listDir(Paths.get(getDataDir(), JSON_DIR, DEMO_DIR, DASHBOARDS_DIR)),
@ -512,11 +497,6 @@ public class InstallScripts {
}
}
public void updateResourcesUsage() {
resourcesUpdater.updateDashboardsResources();
resourcesUpdater.updateWidgetsResources();
}
private void loadSystemResources(Path dir, ResourceType resourceType, ResourceSubType resourceSubType) {
listDir(dir).forEach(resourceFile -> {
String resourceKey = resourceFile.getFileName().toString();

29
ui-ngx/src/app/modules/home/components/rule-node/common/example-hint.component.scss → application/src/main/java/org/thingsboard/server/service/install/ProjectInfo.java

@ -13,19 +13,24 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
:host {
.space-between {
display: flex;
justify-content: space-between;
gap: 20px;
package org.thingsboard.server.service.install;
.see-example {
display: flex;
flex-shrink: 0;
import lombok.RequiredArgsConstructor;
import org.springframework.boot.info.BuildProperties;
import org.springframework.stereotype.Component;
@Component
@RequiredArgsConstructor
public class ProjectInfo {
private final BuildProperties buildProperties;
public String getProjectVersion() {
return buildProperties.getVersion().replaceAll("[^\\d.]", "");
}
public String getProductType() {
return "CE";
}
}
.hint-text {
width: 100%;
}
}

4
application/src/main/java/org/thingsboard/server/service/install/update/DefaultDataUpdateService.java

@ -34,7 +34,6 @@ import org.thingsboard.server.dao.rule.RuleChainService;
import org.thingsboard.server.dao.sql.JpaExecutorService;
import org.thingsboard.server.service.component.ComponentDiscoveryService;
import org.thingsboard.server.service.component.RuleNodeClassInfo;
import org.thingsboard.server.service.install.InstallScripts;
import org.thingsboard.server.utils.TbNodeUpgradeUtils;
import java.util.ArrayList;
@ -58,9 +57,6 @@ public class DefaultDataUpdateService implements DataUpdateService {
@Autowired
JpaExecutorService jpaExecutorService;
@Autowired
private InstallScripts installScripts;
@Override
public void updateData() throws Exception {
log.info("Updating data ...");

5
application/src/main/java/org/thingsboard/server/service/rpc/DefaultTbRuleEngineRpcService.java

@ -115,8 +115,9 @@ public class DefaultTbRuleEngineRpcService implements TbRuleEngineDeviceRpcServi
ToDeviceRpcRequest request = new ToDeviceRpcRequest(src.getRequestUUID(), src.getTenantId(), src.getDeviceId(),
src.isOneway(), src.getExpirationTime(), new ToDeviceRpcRequestBody(src.getMethod(), src.getBody()), src.isPersisted(), src.getRetries(), src.getAdditionalInfo());
forwardRpcRequestToDeviceActor(request, response -> {
if (src.isRestApiCall()) {
sendRpcResponseToTbCore(src.getOriginServiceId(), response);
String originServiceId = src.getOriginServiceId();
if (src.isRestApiCall() && originServiceId != null) {
sendRpcResponseToTbCore(originServiceId, response);
}
consumer.accept(RuleEngineDeviceRpcResponse.builder()
.deviceId(src.getDeviceId())

27
application/src/main/java/org/thingsboard/server/service/telemetry/DefaultTelemetrySubscriptionService.java

@ -118,10 +118,10 @@ public class DefaultTelemetrySubscriptionService extends AbstractSubscriptionSer
EntityId entityId = request.getEntityId();
checkInternalEntity(entityId);
boolean sysTenant = TenantId.SYS_TENANT_ID.equals(tenantId) || tenantId == null;
if (sysTenant || request.isOnlyLatest() || apiUsageStateService.getApiUsageState(tenantId).isDbStorageEnabled()) {
if (sysTenant || !request.getStrategy().saveTimeseries() || apiUsageStateService.getApiUsageState(tenantId).isDbStorageEnabled()) {
KvUtils.validate(request.getEntries(), valueNoXssValidation);
ListenableFuture<Integer> future = saveTimeseriesInternal(request);
if (!request.isOnlyLatest()) {
if (request.getStrategy().saveTimeseries()) {
FutureCallback<Integer> callback = getApiUsageCallback(tenantId, request.getCustomerId(), sysTenant, request.getCallback());
Futures.addCallback(future, callback, tsCallBackExecutor);
}
@ -134,19 +134,24 @@ public class DefaultTelemetrySubscriptionService extends AbstractSubscriptionSer
public ListenableFuture<Integer> saveTimeseriesInternal(TimeseriesSaveRequest request) {
TenantId tenantId = request.getTenantId();
EntityId entityId = request.getEntityId();
TimeseriesSaveRequest.Strategy strategy = request.getStrategy();
ListenableFuture<Integer> saveFuture;
if (request.isOnlyLatest()) {
saveFuture = Futures.transform(tsService.saveLatest(tenantId, entityId, request.getEntries()), result -> 0, MoreExecutors.directExecutor());
} else if (request.isSaveLatest()) {
if (strategy.saveTimeseries() && strategy.saveLatest()) {
saveFuture = tsService.save(tenantId, entityId, request.getEntries(), request.getTtl());
} else {
} else if (strategy.saveLatest()) {
saveFuture = Futures.transform(tsService.saveLatest(tenantId, entityId, request.getEntries()), result -> 0, MoreExecutors.directExecutor());
} else if (strategy.saveTimeseries()) {
saveFuture = tsService.saveWithoutLatest(tenantId, entityId, request.getEntries(), request.getTtl());
} else {
saveFuture = Futures.immediateFuture(0);
}
addMainCallback(saveFuture, request.getCallback());
addWsCallback(saveFuture, success -> onTimeSeriesUpdate(tenantId, entityId, request.getEntries()));
if (request.isSaveLatest() && !request.isOnlyLatest()) {
addEntityViewCallback(tenantId, entityId, request.getEntries());
if (strategy.sendWsUpdate()) {
addWsCallback(saveFuture, success -> onTimeSeriesUpdate(tenantId, entityId, request.getEntries()));
}
if (strategy.saveLatest()) {
copyLatestToEntityViews(tenantId, entityId, request.getEntries());
}
return saveFuture;
}
@ -201,7 +206,7 @@ public class DefaultTelemetrySubscriptionService extends AbstractSubscriptionSer
}
}
private void addEntityViewCallback(TenantId tenantId, EntityId entityId, List<TsKvEntry> ts) {
private void copyLatestToEntityViews(TenantId tenantId, EntityId entityId, List<TsKvEntry> ts) {
if (EntityType.DEVICE.equals(entityId.getEntityType()) || EntityType.ASSET.equals(entityId.getEntityType())) {
Futures.addCallback(this.tbEntityViewService.findEntityViewsByTenantIdAndEntityIdAsync(tenantId, entityId),
new FutureCallback<>() {
@ -232,7 +237,7 @@ public class DefaultTelemetrySubscriptionService extends AbstractSubscriptionSer
.tenantId(tenantId)
.entityId(entityView.getId())
.entries(entityViewLatest)
.onlyLatest(true)
.strategy(TimeseriesSaveRequest.Strategy.LATEST_AND_WS)
.callback(new FutureCallback<>() {
@Override
public void onSuccess(@Nullable Void tmp) {}

90
application/src/main/java/org/thingsboard/server/service/update/DeprecationService.java

@ -1,90 +0,0 @@
/**
* Copyright © 2016-2024 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.update;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.thingsboard.rule.engine.api.NotificationCenter;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.notification.info.GeneralNotificationInfo;
import org.thingsboard.server.common.data.notification.targets.platform.SystemAdministratorsFilter;
import org.thingsboard.server.dao.notification.DefaultNotifications;
import org.thingsboard.server.dao.notification.DefaultNotifications.DefaultNotification;
import org.thingsboard.server.queue.util.AfterStartUp;
import java.util.Map;
@Service
@Slf4j
@RequiredArgsConstructor
public class DeprecationService {
private final NotificationCenter notificationCenter;
@Value("${queue.type}")
private String queueType;
@Value("${database.ts.type}")
private String tsType;
@Value("${database.ts_latest.type}")
private String tsLatestType;
@AfterStartUp(order = Integer.MAX_VALUE)
public void checkDeprecation() {
checkQueueTypeDeprecation();
checkDatabaseTypeDeprecation();
}
private void checkQueueTypeDeprecation() {
String queueTypeName;
switch (queueType) {
case "aws-sqs" -> queueTypeName = "AWS SQS";
case "pubsub" -> queueTypeName = "PubSub";
case "service-bus" -> queueTypeName = "Azure Service Bus";
case "rabbitmq" -> queueTypeName = "RabbitMQ";
default -> {
return;
}
}
log.warn("WARNING: Starting with ThingsBoard 4.0, {} will no longer be supported as a message queue for microservices. " +
"Please migrate to Apache Kafka. This change will not impact any rule nodes", queueTypeName);
sendNotification(DefaultNotifications.queueTypeDeprecation, Map.of(
"queueType", queueTypeName
));
}
private void checkDatabaseTypeDeprecation() {
String deprecatedDatabaseType = "Timescale";
if (StringUtils.equalsAnyIgnoreCase(deprecatedDatabaseType, tsType, tsLatestType)) {
log.warn("WARNING: Starting with ThingsBoard 4.0, {} will no longer be supported as a storage provider. " +
"Please migrate to Cassandra or PostgreSQL.", deprecatedDatabaseType);
sendNotification(DefaultNotifications.databaseTypeDeprecation, Map.of(
"databaseType", deprecatedDatabaseType
));
}
}
private void sendNotification(DefaultNotification notification, Map<String, String> info) {
notificationCenter.sendGeneralWebNotification(TenantId.SYS_TENANT_ID, new SystemAdministratorsFilter(),
notification.toTemplate(), new GeneralNotificationInfo(info));
}
}

2
application/src/main/resources/thingsboard.yml

@ -1271,7 +1271,7 @@ transport:
# URL of gateways dashboard repository
repository_url: "${TB_GATEWAY_DASHBOARD_SYNC_REPOSITORY_URL:https://github.com/thingsboard/gateway-management-extensions-dist.git}"
# Branch of gateways dashboard repository to work with
branch: "${TB_GATEWAY_DASHBOARD_SYNC_BRANCH:main}"
branch: "${TB_GATEWAY_DASHBOARD_SYNC_BRANCH:}"
# Fetch frequency in hours for gateways dashboard repository
fetch_frequency: "${TB_GATEWAY_DASHBOARD_SYNC_FETCH_FREQUENCY:24}"

15
application/src/test/java/org/thingsboard/server/edge/DashboardEdgeTest.java

@ -16,6 +16,7 @@
package org.thingsboard.server.edge;
import com.fasterxml.jackson.core.type.TypeReference;
import com.google.common.collect.Sets;
import com.google.protobuf.AbstractMessage;
import org.junit.Assert;
import org.junit.Test;
@ -175,7 +176,11 @@ public class DashboardEdgeTest extends AbstractEdgeTest {
@Test
public void testSendDashboardToCloud() throws Exception {
Dashboard dashboard = buildDashboardForUplinkMsg();
Customer customer = new Customer();
customer.setTitle("Edge Customer");
Customer savedCustomer = doPost("/api/customer", customer, Customer.class);
Dashboard dashboard = buildDashboardForUplinkMsg(savedCustomer);
UplinkMsg.Builder uplinkMsgBuilder = UplinkMsg.newBuilder();
DashboardUpdateMsg.Builder dashboardUpdateMsgBuilder = DashboardUpdateMsg.newBuilder();
@ -196,6 +201,11 @@ public class DashboardEdgeTest extends AbstractEdgeTest {
Dashboard foundDashboard = doGet("/api/dashboard/" + dashboard.getUuidId(), Dashboard.class);
Assert.assertNotNull(foundDashboard);
Assert.assertEquals("Edge Test Dashboard", foundDashboard.getName());
PageData<DashboardInfo> pageData = doGetTypedWithPageLink("/api/customer/" + savedCustomer.getId().toString() + "/dashboards?",
new TypeReference<>() {}, new PageLink(100));
Assert.assertEquals(1, pageData.getData().size());
Assert.assertEquals("Edge Test Dashboard", pageData.getData().get(0).getTitle());
}
@Test
@ -242,11 +252,12 @@ public class DashboardEdgeTest extends AbstractEdgeTest {
return savedDashboard;
}
private Dashboard buildDashboardForUplinkMsg() {
private Dashboard buildDashboardForUplinkMsg(Customer savedCustomer) {
Dashboard dashboard = new Dashboard();
dashboard.setId(new DashboardId(UUID.randomUUID()));
dashboard.setTenantId(tenantId);
dashboard.setTitle("Edge Test Dashboard");
dashboard.setAssignedCustomers(Sets.newHashSet(new ShortCustomerInfo(savedCustomer.getId(), savedCustomer.getTitle(), savedCustomer.isPublic())));
return dashboard;
}

76
application/src/test/java/org/thingsboard/server/edge/ResourceEdgeTest.java

@ -17,6 +17,7 @@ package org.thingsboard.server.edge;
import com.datastax.oss.driver.api.core.uuid.Uuids;
import com.google.protobuf.AbstractMessage;
import com.google.protobuf.InvalidProtocolBufferException;
import org.junit.Assert;
import org.junit.Test;
import org.thingsboard.common.util.JacksonUtil;
@ -98,30 +99,23 @@ public class ResourceEdgeTest extends AbstractEdgeTest {
public void testSendResourceToCloud() throws Exception {
TbResource tbResource = createTbResource();
UUID uuid = Uuids.timeBased();
UplinkMsg uplinkMsg = getUplinkMsg(uuid, tbResource, UpdateMsgType.ENTITY_CREATED_RPC_MESSAGE);
UplinkMsg.Builder uplinkMsgBuilder = UplinkMsg.newBuilder();
ResourceUpdateMsg.Builder resourceUpdateMsgBuilder = ResourceUpdateMsg.newBuilder();
resourceUpdateMsgBuilder.setIdMSB(uuid.getMostSignificantBits());
resourceUpdateMsgBuilder.setIdLSB(uuid.getLeastSignificantBits());
resourceUpdateMsgBuilder.setEntity(JacksonUtil.toString(tbResource));
resourceUpdateMsgBuilder.setMsgType(UpdateMsgType.ENTITY_CREATED_RPC_MESSAGE);
testAutoGeneratedCodeByProtobuf(resourceUpdateMsgBuilder);
uplinkMsgBuilder.addResourceUpdateMsg(resourceUpdateMsgBuilder.build());
checkResourceOnCloud(uplinkMsg, uuid, tbResource.getTitle());
}
testAutoGeneratedCodeByProtobuf(uplinkMsgBuilder);
@Test
public void testUpdateResourceTitleOnCloud() throws Exception {
TbResource tbResource = createTbResource();
UUID uuid = Uuids.timeBased();
UplinkMsg uplinkMsg = getUplinkMsg(uuid, tbResource, UpdateMsgType.ENTITY_CREATED_RPC_MESSAGE);
edgeImitator.expectResponsesAmount(1);
edgeImitator.sendUplinkMsg(uplinkMsgBuilder.build());
checkResourceOnCloud(uplinkMsg, uuid, tbResource.getTitle());
Assert.assertTrue(edgeImitator.waitForResponses());
tbResource.setTitle("Updated Edge Test Resource");
UplinkMsg updatedUplinkMsg = getUplinkMsg(uuid, tbResource, UpdateMsgType.ENTITY_UPDATED_RPC_MESSAGE);
UplinkResponseMsg latestResponseMsg = edgeImitator.getLatestResponseMsg();
Assert.assertTrue(latestResponseMsg.getSuccess());
TbResource tb = doGet("/api/resource/" + uuid, TbResource.class);
Assert.assertNotNull(tb);
Assert.assertEquals("Edge Test Resource", tb.getName());
Assert.assertEquals(TEST_DATA, tb.getEncodedData());
checkResourceOnCloud(updatedUplinkMsg, uuid, tbResource.getTitle());
}
@Test
@ -134,21 +128,12 @@ public class ResourceEdgeTest extends AbstractEdgeTest {
UUID uuid = Uuids.timeBased();
UplinkMsg.Builder uplinkMsgBuilder = UplinkMsg.newBuilder();
ResourceUpdateMsg.Builder resourceUpdateMsgBuilder = ResourceUpdateMsg.newBuilder();
resourceUpdateMsgBuilder.setIdMSB(uuid.getMostSignificantBits());
resourceUpdateMsgBuilder.setIdLSB(uuid.getLeastSignificantBits());
resourceUpdateMsgBuilder.setEntity(JacksonUtil.toString(resource));
resourceUpdateMsgBuilder.setMsgType(UpdateMsgType.ENTITY_CREATED_RPC_MESSAGE);
testAutoGeneratedCodeByProtobuf(resourceUpdateMsgBuilder);
uplinkMsgBuilder.addResourceUpdateMsg(resourceUpdateMsgBuilder.build());
testAutoGeneratedCodeByProtobuf(uplinkMsgBuilder);
UplinkMsg uplinkMsg = getUplinkMsg(uuid, resource, UpdateMsgType.ENTITY_CREATED_RPC_MESSAGE);
edgeImitator.expectResponsesAmount(1);
edgeImitator.expectMessageAmount(1);
edgeImitator.sendUplinkMsg(uplinkMsgBuilder.build());
edgeImitator.sendUplinkMsg(uplinkMsg);
Assert.assertTrue(edgeImitator.waitForResponses());
Assert.assertTrue(edgeImitator.waitForMessages());
@ -177,4 +162,35 @@ public class ResourceEdgeTest extends AbstractEdgeTest {
tbResource.setEncodedData(TEST_DATA);
return tbResource;
}
private UplinkMsg getUplinkMsg(UUID uuid, TbResource tbResource, UpdateMsgType updateMsgType) throws InvalidProtocolBufferException {
UplinkMsg.Builder uplinkMsgBuilder = UplinkMsg.newBuilder();
ResourceUpdateMsg.Builder resourceUpdateMsgBuilder = ResourceUpdateMsg.newBuilder();
resourceUpdateMsgBuilder.setIdMSB(uuid.getMostSignificantBits());
resourceUpdateMsgBuilder.setIdLSB(uuid.getLeastSignificantBits());
resourceUpdateMsgBuilder.setEntity(JacksonUtil.toString(tbResource));
resourceUpdateMsgBuilder.setMsgType(updateMsgType);
testAutoGeneratedCodeByProtobuf(resourceUpdateMsgBuilder);
uplinkMsgBuilder.addResourceUpdateMsg(resourceUpdateMsgBuilder.build());
testAutoGeneratedCodeByProtobuf(uplinkMsgBuilder);
return uplinkMsgBuilder.build();
}
private void checkResourceOnCloud(UplinkMsg uplinkMsg, UUID uuid, String resourceTitle) throws Exception {
edgeImitator.expectResponsesAmount(1);
edgeImitator.sendUplinkMsg(uplinkMsg);
Assert.assertTrue(edgeImitator.waitForResponses());
UplinkResponseMsg latestResponseMsg = edgeImitator.getLatestResponseMsg();
Assert.assertTrue(latestResponseMsg.getSuccess());
TbResource tb = doGet("/api/resource/" + uuid, TbResource.class);
Assert.assertNotNull(tb);
Assert.assertEquals(resourceTitle, tb.getName());
Assert.assertEquals(TEST_DATA, tb.getEncodedData());
}
}

107
application/src/test/java/org/thingsboard/server/service/entitiy/entityview/DefaultTbEntityViewServiceTest.java

@ -0,0 +1,107 @@
/**
* Copyright © 2016-2024 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.entitiy.entityview;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import org.thingsboard.rule.engine.api.TimeseriesSaveRequest;
import org.thingsboard.server.common.data.EntityView;
import org.thingsboard.server.common.data.id.DeviceId;
import org.thingsboard.server.common.data.id.EntityId;
import org.thingsboard.server.common.data.id.EntityViewId;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.kv.BasicTsKvEntry;
import org.thingsboard.server.common.data.kv.DoubleDataEntry;
import org.thingsboard.server.common.data.kv.TsKvEntry;
import org.thingsboard.server.common.data.objects.AttributesEntityView;
import org.thingsboard.server.common.data.objects.TelemetryEntityView;
import org.thingsboard.server.dao.attributes.AttributesService;
import org.thingsboard.server.dao.entityview.EntityViewService;
import org.thingsboard.server.dao.timeseries.TimeseriesService;
import org.thingsboard.server.service.telemetry.TelemetrySubscriptionService;
import java.util.List;
import java.util.UUID;
import static com.google.common.util.concurrent.Futures.immediateFuture;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.anyList;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.BDDMockito.given;
import static org.mockito.BDDMockito.then;
@ExtendWith(MockitoExtension.class)
class DefaultTbEntityViewServiceTest {
final TenantId tenantId = TenantId.fromUUID(UUID.fromString("f09c8180-686c-11ef-9471-a71d33080e9c"));
final EntityId entityId = DeviceId.fromString("782aaab0-c7a8-11ef-a668-79582e785d5f");
@Mock
EntityViewService entityViewService;
@Mock
AttributesService attributesService;
@Mock
TelemetrySubscriptionService tsSubService;
@Mock
TimeseriesService tsService;
DefaultTbEntityViewService defaultTbEntityViewService;
@BeforeEach
void setup() {
defaultTbEntityViewService = new DefaultTbEntityViewService(entityViewService, attributesService, tsSubService, tsService);
}
@Test
void shouldNotSaveTimeseriesWhenCopyingLatestToEntityView() throws Exception {
// GIVEN
var entityView = new EntityView(new EntityViewId(UUID.randomUUID()));
entityView.setTenantId(tenantId);
entityView.setEntityId(entityId);
entityView.setKeys(new TelemetryEntityView(List.of("temperature"), new AttributesEntityView()));
List<TsKvEntry> latest = List.of(new BasicTsKvEntry(123L, new DoubleDataEntry("temperature", 22.3)));
given(tsService.findAll(eq(tenantId), eq(entityId), anyList())).willReturn(immediateFuture(latest));
// WHEN
defaultTbEntityViewService.updateEntityViewAttributes(tenantId, entityView, null, null);
// THEN
var captor = ArgumentCaptor.forClass(TimeseriesSaveRequest.class);
then(tsSubService).should().saveTimeseries(captor.capture());
var expectedCopyLatestRequest = TimeseriesSaveRequest.builder()
.tenantId(tenantId)
.entityId(entityView.getId())
.entries(latest)
.ttl(0L)
.strategy(TimeseriesSaveRequest.Strategy.LATEST_AND_WS)
.build();
var actualCopyLatestRequest = captor.getValue();
assertThat(actualCopyLatestRequest)
.usingRecursiveComparison()
.ignoringFields("callback")
.isEqualTo(expectedCopyLatestRequest);
}
}

373
application/src/test/java/org/thingsboard/server/service/telemetry/DefaultTelemetrySubscriptionServiceTest.java

@ -0,0 +1,373 @@
/**
* Copyright © 2016-2024 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.telemetry;
import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.MoreExecutors;
import com.google.common.util.concurrent.SettableFuture;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.test.util.ReflectionTestUtils;
import org.thingsboard.rule.engine.api.TimeseriesSaveRequest;
import org.thingsboard.server.cluster.TbClusterService;
import org.thingsboard.server.common.data.ApiUsageRecordKey;
import org.thingsboard.server.common.data.ApiUsageState;
import org.thingsboard.server.common.data.ApiUsageStateValue;
import org.thingsboard.server.common.data.EntityView;
import org.thingsboard.server.common.data.id.CustomerId;
import org.thingsboard.server.common.data.id.DeviceId;
import org.thingsboard.server.common.data.id.EntityId;
import org.thingsboard.server.common.data.id.EntityViewId;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.kv.BasicTsKvEntry;
import org.thingsboard.server.common.data.kv.DoubleDataEntry;
import org.thingsboard.server.common.data.kv.KvEntry;
import org.thingsboard.server.common.data.kv.TsKvEntry;
import org.thingsboard.server.common.data.objects.AttributesEntityView;
import org.thingsboard.server.common.data.objects.TelemetryEntityView;
import org.thingsboard.server.common.msg.queue.ServiceType;
import org.thingsboard.server.common.msg.queue.TbCallback;
import org.thingsboard.server.common.msg.queue.TopicPartitionInfo;
import org.thingsboard.server.common.stats.TbApiUsageReportClient;
import org.thingsboard.server.dao.attributes.AttributesService;
import org.thingsboard.server.dao.timeseries.TimeseriesService;
import org.thingsboard.server.queue.discovery.PartitionService;
import org.thingsboard.server.queue.discovery.QueueKey;
import org.thingsboard.server.queue.discovery.event.PartitionChangeEvent;
import org.thingsboard.server.service.apiusage.TbApiUsageStateService;
import org.thingsboard.server.service.entitiy.entityview.TbEntityViewService;
import org.thingsboard.server.service.subscription.SubscriptionManagerService;
import java.time.Duration;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.stream.LongStream;
import java.util.stream.Stream;
import static com.google.common.util.concurrent.Futures.immediateFuture;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.BDDMockito.given;
import static org.mockito.BDDMockito.then;
import static org.mockito.Mockito.lenient;
@ExtendWith(MockitoExtension.class)
class DefaultTelemetrySubscriptionServiceTest {
final TenantId tenantId = TenantId.fromUUID(UUID.fromString("a00ec470-c6b4-11ef-8c88-63b5533fb5bc"));
final CustomerId customerId = new CustomerId(UUID.fromString("7bdc9750-c775-11ef-8e03-ff69ed8da327"));
final EntityId entityId = DeviceId.fromString("cc51e450-53e1-11ee-883e-e56b48fd2088");
final long sampleTtl = 10_000L;
final List<TsKvEntry> sampleTelemetry = List.of(
new BasicTsKvEntry(100L, new DoubleDataEntry("temperature", 65.2)),
new BasicTsKvEntry(100L, new DoubleDataEntry("humidity", 33.1))
);
ApiUsageState apiUsageState;
final TopicPartitionInfo tpi = TopicPartitionInfo.builder()
.tenantId(tenantId)
.myPartition(true)
.build();
final FutureCallback<Void> emptyCallback = new FutureCallback<>() {
@Override
public void onSuccess(Void result) {}
@Override
public void onFailure(@NonNull Throwable t) {}
};
ExecutorService wsCallBackExecutor;
ExecutorService tsCallBackExecutor;
@Mock
TbClusterService clusterService;
@Mock
PartitionService partitionService;
@Mock
SubscriptionManagerService subscriptionManagerService;
@Mock
AttributesService attrService;
@Mock
TimeseriesService tsService;
@Mock
TbEntityViewService tbEntityViewService;
@Mock
TbApiUsageReportClient apiUsageClient;
@Mock
TbApiUsageStateService apiUsageStateService;
DefaultTelemetrySubscriptionService telemetryService;
@BeforeEach
void setup() {
telemetryService = new DefaultTelemetrySubscriptionService(attrService, tsService, tbEntityViewService, apiUsageClient, apiUsageStateService);
ReflectionTestUtils.setField(telemetryService, "clusterService", clusterService);
ReflectionTestUtils.setField(telemetryService, "partitionService", partitionService);
ReflectionTestUtils.setField(telemetryService, "subscriptionManagerService", Optional.of(subscriptionManagerService));
wsCallBackExecutor = MoreExecutors.newDirectExecutorService();
ReflectionTestUtils.setField(telemetryService, "wsCallBackExecutor", wsCallBackExecutor);
tsCallBackExecutor = MoreExecutors.newDirectExecutorService();
ReflectionTestUtils.setField(telemetryService, "tsCallBackExecutor", tsCallBackExecutor);
apiUsageState = new ApiUsageState();
apiUsageState.setDbStorageState(ApiUsageStateValue.ENABLED);
lenient().when(apiUsageStateService.getApiUsageState(tenantId)).thenReturn(apiUsageState);
lenient().when(partitionService.resolve(ServiceType.TB_CORE, tenantId, entityId)).thenReturn(tpi);
lenient().when(tsService.save(tenantId, entityId, sampleTelemetry, sampleTtl)).thenReturn(immediateFuture(sampleTelemetry.size()));
lenient().when(tsService.saveWithoutLatest(tenantId, entityId, sampleTelemetry, sampleTtl)).thenReturn(immediateFuture(sampleTelemetry.size()));
lenient().when(tsService.saveLatest(tenantId, entityId, sampleTelemetry)).thenReturn(immediateFuture(listOfNNumbers(sampleTelemetry.size())));
// mock no entity views
lenient().when(tbEntityViewService.findEntityViewsByTenantIdAndEntityIdAsync(tenantId, entityId)).thenReturn(immediateFuture(Collections.emptyList()));
// send partition change event so currentPartitions set is populated
telemetryService.onTbApplicationEvent(new PartitionChangeEvent(this, ServiceType.TB_CORE, Map.of(new QueueKey(ServiceType.TB_CORE), Set.of(tpi))));
}
@AfterEach
void cleanup() {
wsCallBackExecutor.shutdownNow();
tsCallBackExecutor.shutdownNow();
}
@Test
void shouldReportStorageDataPointsApiUsageWhenTimeSeriesIsSaved() {
// GIVEN
var request = TimeseriesSaveRequest.builder()
.tenantId(tenantId)
.customerId(customerId)
.entityId(entityId)
.entries(sampleTelemetry)
.ttl(sampleTtl)
.strategy(new TimeseriesSaveRequest.Strategy(true, false, false))
.callback(emptyCallback)
.build();
// WHEN
telemetryService.saveTimeseries(request);
// THEN
then(apiUsageClient).should().report(tenantId, customerId, ApiUsageRecordKey.STORAGE_DP_COUNT, sampleTelemetry.size());
}
@Test
void shouldNotReportStorageDataPointsApiUsageWhenTimeSeriesIsNotSaved() {
// GIVEN
var request = TimeseriesSaveRequest.builder()
.tenantId(tenantId)
.customerId(customerId)
.entityId(entityId)
.entries(sampleTelemetry)
.ttl(sampleTtl)
.strategy(TimeseriesSaveRequest.Strategy.LATEST_AND_WS)
.callback(emptyCallback)
.build();
// WHEN
telemetryService.saveTimeseries(request);
// THEN
then(apiUsageClient).shouldHaveNoInteractions();
}
@Test
void shouldThrowStorageDisabledWhenTimeSeriesIsSavedAndStorageIsDisabled() {
// GIVEN
apiUsageState.setDbStorageState(ApiUsageStateValue.DISABLED);
SettableFuture<Void> future = SettableFuture.create();
var request = TimeseriesSaveRequest.builder()
.tenantId(tenantId)
.customerId(customerId)
.entityId(entityId)
.entries(sampleTelemetry)
.ttl(sampleTtl)
.strategy(TimeseriesSaveRequest.Strategy.SAVE_ALL)
.future(future)
.build();
// WHEN
telemetryService.saveTimeseries(request);
// THEN
assertThat(future).failsWithin(Duration.ofSeconds(5))
.withThrowableOfType(ExecutionException.class)
.withCauseInstanceOf(RuntimeException.class)
.withMessageContaining("DB storage writes are disabled due to API limits!");
}
@Test
void shouldNotThrowStorageDisabledWhenTimeSeriesIsNotSavedAndStorageIsDisabled() {
// GIVEN
apiUsageState.setDbStorageState(ApiUsageStateValue.DISABLED);
SettableFuture<Void> future = SettableFuture.create();
var request = TimeseriesSaveRequest.builder()
.tenantId(tenantId)
.customerId(customerId)
.entityId(entityId)
.entries(sampleTelemetry)
.ttl(sampleTtl)
.strategy(TimeseriesSaveRequest.Strategy.LATEST_AND_WS)
.future(future)
.build();
// WHEN
telemetryService.saveTimeseries(request);
// THEN
assertThat(future).succeedsWithin(Duration.ofSeconds(5));
}
@Test
void shouldCopyLatestToEntityViewWhenLatestIsSavedOnMainEntity() {
// GIVEN
var entityView = new EntityView(new EntityViewId(UUID.randomUUID()));
entityView.setTenantId(tenantId);
entityView.setCustomerId(customerId);
entityView.setEntityId(entityId);
entityView.setKeys(new TelemetryEntityView(sampleTelemetry.stream().map(KvEntry::getKey).toList(), new AttributesEntityView()));
// mock that there is one entity view
given(tbEntityViewService.findEntityViewsByTenantIdAndEntityIdAsync(tenantId, entityId)).willReturn(immediateFuture(List.of(entityView)));
// mock that save latest call for entity view is successful
given(tsService.saveLatest(tenantId, entityView.getId(), sampleTelemetry)).willReturn(immediateFuture(listOfNNumbers(sampleTelemetry.size())));
// mock TPI for entity view
given(partitionService.resolve(ServiceType.TB_CORE, tenantId, entityView.getId())).willReturn(tpi);
var request = TimeseriesSaveRequest.builder()
.tenantId(tenantId)
.customerId(customerId)
.entityId(entityId)
.entries(sampleTelemetry)
.ttl(sampleTtl)
.strategy(new TimeseriesSaveRequest.Strategy(false, true, false))
.callback(emptyCallback)
.build();
// WHEN
telemetryService.saveTimeseries(request);
// THEN
// should save latest to both the main entity and it's entity view
then(tsService).should().saveLatest(tenantId, entityId, sampleTelemetry);
then(tsService).should().saveLatest(tenantId, entityView.getId(), sampleTelemetry);
then(tsService).shouldHaveNoMoreInteractions();
// should send WS update only for entity view (WS update for the main entity is disabled in the save request)
then(subscriptionManagerService).should().onTimeSeriesUpdate(tenantId, entityView.getId(), sampleTelemetry, TbCallback.EMPTY);
then(subscriptionManagerService).shouldHaveNoMoreInteractions();
}
@Test
void shouldNotCopyLatestToEntityViewWhenLatestIsNotSavedOnMainEntity() {
// GIVEN
var request = TimeseriesSaveRequest.builder()
.tenantId(tenantId)
.customerId(customerId)
.entityId(entityId)
.entries(sampleTelemetry)
.ttl(sampleTtl)
.strategy(new TimeseriesSaveRequest.Strategy(true, false, false))
.callback(emptyCallback)
.build();
// WHEN
telemetryService.saveTimeseries(request);
// THEN
// should save only time series for the main entity
then(tsService).should().saveWithoutLatest(tenantId, entityId, sampleTelemetry, sampleTtl);
then(tsService).shouldHaveNoMoreInteractions();
// should not send any WS updates
then(subscriptionManagerService).shouldHaveNoInteractions();
}
@ParameterizedTest
@MethodSource("booleanCombinations")
void shouldCallCorrectApiBasedOnBooleanFlagsInTheSaveRequest(boolean saveTimeseries, boolean saveLatest, boolean sendWsUpdate) {
// GIVEN
var request = TimeseriesSaveRequest.builder()
.tenantId(tenantId)
.customerId(customerId)
.entityId(entityId)
.entries(sampleTelemetry)
.ttl(sampleTtl)
.strategy(new TimeseriesSaveRequest.Strategy(saveTimeseries, saveLatest, sendWsUpdate))
.callback(emptyCallback)
.build();
// WHEN
telemetryService.saveTimeseries(request);
// THEN
if (saveTimeseries && saveLatest) {
then(tsService).should().save(tenantId, entityId, sampleTelemetry, sampleTtl);
} else if (saveLatest) {
then(tsService).should().saveLatest(tenantId, entityId, sampleTelemetry);
} else if (saveTimeseries) {
then(tsService).should().saveWithoutLatest(tenantId, entityId, sampleTelemetry, sampleTtl);
}
then(tsService).shouldHaveNoMoreInteractions();
if (sendWsUpdate) {
then(subscriptionManagerService).should().onTimeSeriesUpdate(tenantId, entityId, sampleTelemetry, TbCallback.EMPTY);
} else {
then(subscriptionManagerService).shouldHaveNoInteractions();
}
}
private static Stream<Arguments> booleanCombinations() {
return Stream.of(
Arguments.of(true, true, true),
Arguments.of(true, true, false),
Arguments.of(true, false, true),
Arguments.of(true, false, false),
Arguments.of(false, true, true),
Arguments.of(false, true, false),
Arguments.of(false, false, true),
Arguments.of(false, false, false)
);
}
// used to emulate sequence numbers returned by save latest API
private static List<Long> listOfNNumbers(int N) {
return LongStream.range(0, N).boxed().toList();
}
}

49
common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/DefaultTransportMBeanConfiguration.java

@ -0,0 +1,49 @@
/**
* Copyright © 2016-2024 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.transport.mqtt;
import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jmx.export.MBeanExporter;
import org.thingsboard.server.common.transport.service.DefaultTransportService;
import org.thingsboard.server.queue.util.TbTransportComponent;
import java.util.HashMap;
import java.util.Map;
@Configuration
@TbTransportComponent
@RequiredArgsConstructor
public class DefaultTransportMBeanConfiguration {
private final DefaultTransportService transportService;
@Bean
public HashMapObserver hashMapObserver() {
return new HashMapObserver(transportService.sessions);
}
@Bean
public MBeanExporter mBeanExporter() {
MBeanExporter exporter = new MBeanExporter();
Map<String, Object> beans = new HashMap<>();
beans.put("org.thingsboard:type=TransportSessionMapObserver", hashMapObserver());
exporter.setBeans(beans);
return exporter;
}
}

188
common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/HashMapObserver.java

@ -0,0 +1,188 @@
/**
* Copyright © 2016-2024 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.transport.mqtt;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.thingsboard.server.common.transport.service.SessionMetaData;
import org.thingsboard.server.common.transport.session.DeviceAwareSessionContext;
import org.thingsboard.server.transport.mqtt.session.GatewayDeviceSessionContext;
import java.util.Map;
import java.util.UUID;
@RequiredArgsConstructor
@Slf4j
public class HashMapObserver implements HashMapObserverMBean {
private final Map<UUID, SessionMetaData> map;
@Override
public int getSize() {
return map.size();
}
@Override
public long getGatewayCount(String unused) {
return map.values().stream().filter(v-> v.getSessionInfo() != null && v.getSessionInfo().getIsGateway()).count();
}
@Override
public long getNonGatewayCount(String unused) {
return map.values().stream().filter(v-> v.getSessionInfo() != null && !v.getSessionInfo().getIsGateway()).count();
}
@Override
public String getSessionByUUID(String uuid) {
return String.valueOf(map.get(UUID.fromString(uuid)));
}
void addContent(Object entry, int count, StringBuilder content) {
String lineContent = String.valueOf(entry).replaceAll(System.lineSeparator()," ");
log.info("{} content = {}", count, lineContent);
content.append(lineContent).append(System.lineSeparator());
}
@Override
public String getAllSessions(String unused) {
log.info("getAllSessions()");
StringBuilder content = new StringBuilder();
try {
int count = 0;
for (Map.Entry<UUID, SessionMetaData> entry : map.entrySet()) {
addContent(entry, ++count, content);
}
return content.toString();
} catch (Exception e) {
log.error(e.getMessage(), e);
throw e;
}
}
@Override
public String getSubscribedSessions(String unused) {
log.info("getSubscribedSessions()");
StringBuilder content = new StringBuilder();
try {
int count = 0;
for (Map.Entry<UUID, SessionMetaData> entry : map.entrySet()) {
boolean hasSubscription = entry.getValue().isSubscribedToRPC() || entry.getValue().isSubscribedToAttributes();
if (hasSubscription) {
addContent(entry, ++count, content);
}
}
return content.toString();
} catch (Exception e) {
log.error(e.getMessage(), e);
throw e;
}
}
@Override
public String getNonActiveSessions(String unused) {
log.info("getNonActiveSessions()");
StringBuilder content = new StringBuilder();
try {
int count = 0;
for (Map.Entry<UUID, SessionMetaData> entry : map.entrySet()) {
SessionMetaData sessionMetaData = entry.getValue();
if (sessionMetaData.getListener() instanceof MqttTransportHandler) {
MqttTransportHandler listener = (MqttTransportHandler) sessionMetaData.getListener();
if (!listener.deviceSessionCtx.getChannel().channel().isActive()) {
addContent(entry, ++count, content);
}
}
}
return content.toString();
} catch (Exception e) {
log.error(e.getMessage(), e);
throw e;
}
}
@Override
public String getActiveSessions(String unused) {
log.info("getActiveSessions()");
StringBuilder content = new StringBuilder();
try {
int count = 0;
for (Map.Entry<UUID, SessionMetaData> entry : map.entrySet()) {
SessionMetaData sessionMetaData = entry.getValue();
if (sessionMetaData.getListener() instanceof MqttTransportHandler) {
MqttTransportHandler listener = (MqttTransportHandler) sessionMetaData.getListener();
if (listener.deviceSessionCtx.getChannel().channel().isActive()) {
addContent(entry, ++count, content);
}
} else {
addContent(sessionMetaData.getListener().getClass(), ++count, content);
}
}
return content.toString();
} catch (Exception e) {
log.error(e.getMessage(), e);
throw e;
}
}
@Override
public String getGatewayDeviceSessionContextConnectedSessions(String unused) {
log.info("getGatewayDeviceSessionContextConnectedSessions()");
StringBuilder content = new StringBuilder();
try {
int count = 0;
for (Map.Entry<UUID, SessionMetaData> entry : map.entrySet()) {
SessionMetaData sessionMetaData = entry.getValue();
if (sessionMetaData.getListener() instanceof GatewayDeviceSessionContext) {
GatewayDeviceSessionContext listener = (GatewayDeviceSessionContext) sessionMetaData.getListener();
if (listener.isConnected()) {
addContent(entry, ++count, content);
}
}
}
addContent(count, count, content);
return content.toString();
} catch (Exception e) {
log.error(e.getMessage(), e);
throw e;
}
}
@Override
public String getDeviceAwareSessionContextNotConnectedSessions(String unused) {
log.info("getDeviceAwareSessionContextNotConnectedSessions()");
StringBuilder content = new StringBuilder();
try {
int count = 0;
for (Map.Entry<UUID, SessionMetaData> entry : map.entrySet()) {
SessionMetaData sessionMetaData = entry.getValue();
if (sessionMetaData.getListener() instanceof DeviceAwareSessionContext) {
DeviceAwareSessionContext listener = (DeviceAwareSessionContext) sessionMetaData.getListener();
if (!listener.isConnected()) {
addContent(entry, ++count, content);
}
}
}
addContent(count, count, content);
return content.toString();
} catch (Exception e) {
log.error(e.getMessage(), e);
throw e;
}
}
}
// 4a7d85c9-eb4b-4fbc-8f6c-deb158cc9ac7=SessionMetaData(sessionInfo=nodeId: "bestia.local" sessionIdMSB: 5367593433178001340 sessionIdLSB: -8111863975520724281 tenantIdMSB: -1954197196874116625 tenantIdLSB: -7022192637061768255 deviceIdMSB: -5222516332438875665 deviceIdLSB: -7338416368958642691 deviceName: "Demo Device" deviceType: "default" gwSessionIdMSB: 3730140660294699909 gwSessionIdLSB: -7918622346767288875 deviceProfileIdMSB: -1952135612572036625 deviceProfileIdLSB: -7022192637061768255 customerIdMSB: 1405474927960789426 customerIdLSB: -9187201950435737472 gatewayIdMSB: 164837549830312431 gatewayIdLSB: -7338416368958642691 , sessionType=ASYNC, listener=GatewayDeviceSessionContext(super=AbstractGatewayDeviceSessionContext(super=MqttDeviceAwareSessionContext(super=DeviceAwareSessionContext(sessionId=4a7d85c9-eb4b-4fbc-8f6c-deb158cc9ac7, deviceId=b785e510-d34e-11ef-9a28-b5316a4ee5fd, tenantId=e4e14c00-d341-11ef-9e8c-29007391dbc1, deviceInfo=TransportDeviceInfo(tenantId=e4e14c00-d341-11ef-9e8c-29007391dbc1, customerId=13814000-1dd2-11b2-8080-808080808080, deviceProfileId=e4e89f00-d341-11ef-9e8c-29007391dbc1, deviceId=b785e510-d34e-11ef-9a28-b5316a4ee5fd, deviceName=Demo Device, deviceType=default, powerMode=null, additionalInfo={"lastConnectedGateway":"02499ee0-d348-11ef-9a28-b5316a4ee5fd"}, edrxCycle=null, psmActivityTimer=null, pagingTransmissionWindow=null, gateway=false), deviceProfile=DeviceProfile(tenantId=e4e14c00-d341-11ef-9e8c-29007391dbc1, name=default, description=Default device profile, isDefault=true, type=DEFAULT, transportType=DEFAULT, provisionType=DISABLED, defaultRuleChainId=null, defaultDashboardId=null, defaultQueueName=null, profileData=DeviceProfileData(configuration=DefaultDeviceProfileConfiguration(), transportConfiguration=DefaultDeviceProfileTransportConfiguration(), provisionConfiguration=DisabledDeviceProfileProvisionConfiguration(provisionDeviceSecret=null), alarms=null), provisionDeviceKey=null, firmwareId=null, softwareId=null, defaultEdgeRuleChainId=null, externalId=null, version=1), sessionInfo=nodeId: "bestia.local" sessionIdMSB: 5367593433178001340 sessionIdLSB: -8111863975520724281 tenantIdMSB: -1954197196874116625 tenantIdLSB: -7022192637061768255 deviceIdMSB: -5222516332438875665 deviceIdLSB: -7338416368958642691 deviceName: "Demo Device" deviceType: "default" gwSessionIdMSB: 3730140660294699909 gwSessionIdLSB: -7918622346767288875 deviceProfileIdMSB: -1952135612572036625 deviceProfileIdLSB: -7022192637061768255 customerIdMSB: 1405474927960789426 customerIdLSB: -9187201950435737472 gatewayIdMSB: 164837549830312431 gatewayIdLSB: -7338416368958642691 , connected=true), mqttQoSMap={org.thingsboard.server.transport.mqtt.session.MqttTopicMatcher@697a7658=1, org.thingsboard.server.transport.mqtt.session.MqttTopicMatcher@d44c5be8=1, org.thingsboard.server.transport.mqtt.session.MqttTopicMatcher@e3a8acd0=1, org.thingsboard.server.transport.mqtt.session.MqttTopicMatcher@e3d2681a=1, org.thingsboard.server.transport.mqtt.session.MqttTopicMatcher@a65b8616=1, org.thingsboard.server.transport.mqtt.session.MqttTopicMatcher@133a8264=1, org.thingsboard.server.transport.mqtt.session.MqttTopicMatcher@12e92606=1}), parent=org.thingsboard.server.transport.mqtt.session.GatewaySessionHandler@3d4885c2, transportService=org.thingsboard.server.common.transport.service.DefaultTransportService@77c16f87)), scheduledFuture=null, subscribedToAttributes=true, subscribedToRPC=true, overwriteActivityTime=false)
//1

38
common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/HashMapObserverMBean.java

@ -0,0 +1,38 @@
/**
* Copyright © 2016-2024 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.transport.mqtt;
public interface HashMapObserverMBean {
int getSize();
long getGatewayCount(String unused);
long getNonGatewayCount(String unused);
String getSessionByUUID(String key);
String getAllSessions(String key);
String getSubscribedSessions(String unused);
String getNonActiveSessions(String unused);
String getActiveSessions(String unused);
String getGatewayDeviceSessionContextConnectedSessions(String unused);
String getDeviceAwareSessionContextNotConnectedSessions(String unused);
}

2
common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/MqttTransportHandler.java

@ -963,7 +963,7 @@ public class MqttTransportHandler extends ChannelInboundHandlerAdapter implement
unSubResults.add((short) MqttReasonCodes.UnsubAck.NO_SUBSCRIPTION_EXISTED.byteValue());
}
}
if (!activityReported) {
if (!activityReported && !deviceSessionCtx.isProvisionOnly()) {
transportService.recordActivity(deviceSessionCtx.getSessionInfo());
}
ctx.writeAndFlush(createUnSubAckMessage(mqttMsg.variableHeader().messageId(), unSubResults));

4
common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/session/AbstractGatewayDeviceSessionContext.java

@ -17,6 +17,8 @@ package org.thingsboard.server.transport.mqtt.session;
import io.netty.channel.ChannelFuture;
import io.netty.handler.codec.mqtt.MqttMessage;
import lombok.Getter;
import lombok.ToString;
import lombok.extern.slf4j.Slf4j;
import org.thingsboard.server.common.data.DeviceProfile;
import org.thingsboard.server.common.data.id.DeviceId;
@ -34,9 +36,11 @@ import java.util.concurrent.ConcurrentMap;
/**
* Created by ashvayka on 19.01.17.
*/
@ToString(callSuper = true)
@Slf4j
public abstract class AbstractGatewayDeviceSessionContext<T extends AbstractGatewaySessionHandler> extends MqttDeviceAwareSessionContext implements SessionMsgListener {
@Getter
protected final T parent;
private final TransportService transportService;

26
common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/session/AbstractGatewaySessionHandler.java

@ -16,8 +16,10 @@
package org.thingsboard.server.transport.mqtt.session;
import com.fasterxml.jackson.databind.JsonNode;
import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.MoreExecutors;
import com.google.common.util.concurrent.SettableFuture;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
@ -115,6 +117,7 @@ public abstract class AbstractGatewaySessionHandler<T extends AbstractGatewayDev
private final ConcurrentMap<String, T> devices;
private final ConcurrentMap<String, ListenableFuture<T>> deviceFutures;
protected final ConcurrentMap<MqttTopicMatcher, Integer> mqttQoSMap;
@Getter
protected final ChannelHandlerContext channel;
protected final DeviceSessionCtx deviceSessionCtx;
protected final GatewayMetricsService gatewayMetricsService;
@ -124,6 +127,7 @@ public abstract class AbstractGatewaySessionHandler<T extends AbstractGatewayDev
private boolean overwriteDevicesActivity = false;
public AbstractGatewaySessionHandler(DeviceSessionCtx deviceSessionCtx, UUID sessionId, boolean overwriteDevicesActivity) {
log.debug("[{}] Gateway connect [{}] session [{}]", deviceSessionCtx.getTenantId(), deviceSessionCtx.getDeviceId(), sessionId);
this.context = deviceSessionCtx.getContext();
this.transportService = context.getTransportService();
this.deviceSessionCtx = deviceSessionCtx;
@ -195,7 +199,27 @@ public abstract class AbstractGatewaySessionHandler<T extends AbstractGatewayDev
}
public void onDevicesDisconnect() {
devices.forEach(this::deregisterSession);
log.debug("[{}] Gateway disconnect [{}]", gateway.getTenantId(), gateway.getDeviceId());
try {
deviceFutures.forEach((name, future) -> {
Futures.addCallback(future, new FutureCallback<T>() {
@Override
public void onSuccess(T result) {
log.debug("[{}] Gateway disconnect [{}] device deregister callback [{}]", gateway.getTenantId(), gateway.getDeviceId(), name);
deregisterSession(name, result);
}
@Override
public void onFailure(Throwable t) {
}
}, MoreExecutors.directExecutor());
});
devices.forEach(this::deregisterSession);
} catch (Exception e) {
log.error("Gateway disconnect failure", e);
}
}
public void onDeviceDeleted(String deviceName) {

2
common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/session/GatewayDeviceSessionContext.java

@ -15,6 +15,7 @@
*/
package org.thingsboard.server.transport.mqtt.session;
import lombok.ToString;
import org.thingsboard.server.common.data.DeviceProfile;
import org.thingsboard.server.common.transport.TransportService;
import org.thingsboard.server.common.transport.auth.TransportDeviceInfo;
@ -24,6 +25,7 @@ import java.util.concurrent.ConcurrentMap;
/**
* Created by nickAS21 on 26.12.22
*/
@ToString(callSuper = true)
public class GatewayDeviceSessionContext extends AbstractGatewayDeviceSessionContext<GatewaySessionHandler> {
public GatewayDeviceSessionContext(GatewaySessionHandler parent,

2
common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/session/MqttDeviceAwareSessionContext.java

@ -16,6 +16,7 @@
package org.thingsboard.server.transport.mqtt.session;
import io.netty.handler.codec.mqtt.MqttQoS;
import lombok.ToString;
import org.thingsboard.server.common.transport.session.DeviceAwareSessionContext;
import java.util.List;
@ -27,6 +28,7 @@ import java.util.stream.Collectors;
/**
* Created by ashvayka on 30.08.18.
*/
@ToString(callSuper = true)
public abstract class MqttDeviceAwareSessionContext extends DeviceAwareSessionContext {
private final ConcurrentMap<MqttTopicMatcher, Integer> mqttQoSMap;

6
common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/service/DefaultTransportService.java

@ -735,7 +735,11 @@ public class DefaultTransportService extends TransportActivityManager implements
}
private void recordActivityInternal(TransportProtos.SessionInfoProto sessionInfo) {
onActivity(toSessionId(sessionInfo), sessionInfo, getCurrentTimeMillis());
if (sessionInfo != null) {
onActivity(toSessionId(sessionInfo), sessionInfo, getCurrentTimeMillis());
} else {
log.warn("Session info is missing, unable to record activity");
}
}
@Override

2
common/version-control/src/main/java/org/thingsboard/server/service/sync/vc/GitRepository.java

@ -450,7 +450,7 @@ public class GitRepository {
}
ObjectId result = git.getRepository().resolve(rev);
if (result == null) {
throw new IllegalArgumentException("Failed to parse git revision string: \"" + rev + "\"");
throw new IllegalArgumentException("Failed to resolve '" + rev + "'");
}
return result;
}

19
dao/src/main/java/org/thingsboard/server/dao/notification/DefaultNotifications.java

@ -372,25 +372,6 @@ public class DefaultNotifications {
.build())
.build();
public static final DefaultNotification queueTypeDeprecation = DefaultNotification.builder()
.name("Queue type deprecation")
.type(NotificationType.GENERAL)
.subject("WARNING: ${queueType} deprecation")
.text("Starting with ThingsBoard 4.0, ${queueType} will no longer be supported as a message queue for microservices. " +
"Please migrate to Apache Kafka. This change will not impact any rule nodes.")
.icon("warning").color(RED_COLOR)
.build();
public static final DefaultNotification databaseTypeDeprecation = DefaultNotification.builder()
.name("Database type deprecation")
.type(NotificationType.GENERAL)
.subject("WARNING: ${databaseType} deprecation")
.text("Starting with ThingsBoard 4.0, ${databaseType} will no longer be supported as a storage provider. " +
"Please migrate to Cassandra or PostgreSQL.")
.icon("warning")
.color(RED_COLOR)
.build();
private final NotificationTemplateService templateService;
private final NotificationRuleService ruleService;

26
monitoring/src/main/resources/root_rule_chain.json

@ -21,9 +21,13 @@
"type": "org.thingsboard.rule.engine.telemetry.TbMsgTimeseriesNode",
"name": "Save Timeseries",
"singletonMode": false,
"configurationVersion": 0,
"configurationVersion": 1,
"configuration": {
"defaultTTL": 0
"defaultTTL": 0,
"useServerTs": false,
"processingSettings": {
"type": "ON_EVERY_MESSAGE"
}
},
"externalId": null
},
@ -273,9 +277,13 @@
"type": "org.thingsboard.rule.engine.telemetry.TbMsgTimeseriesNode",
"name": "Save Timeseries",
"singletonMode": false,
"configurationVersion": 0,
"configurationVersion": 1,
"configuration": {
"defaultTTL": 0
"defaultTTL": 0,
"useServerTs": false,
"processingSettings": {
"type": "ON_EVERY_MESSAGE"
}
},
"externalId": null
},
@ -307,11 +315,13 @@
"type": "org.thingsboard.rule.engine.telemetry.TbMsgTimeseriesNode",
"name": "Save Timeseries with TTL",
"singletonMode": false,
"configurationVersion": 0,
"configurationVersion": 1,
"configuration": {
"defaultTTL": 180,
"skipLatestPersistence": null,
"useServerTs": null
"useServerTs": false,
"processingSettings": {
"type": "ON_EVERY_MESSAGE"
}
},
"externalId": null
}
@ -415,4 +425,4 @@
],
"ruleChainConnections": null
}
}
}

8
msa/black-box-tests/src/test/resources/MqttRuleNodeTestMetadata.json

@ -36,11 +36,13 @@
"type": "org.thingsboard.rule.engine.telemetry.TbMsgTimeseriesNode",
"name": "save timeseries",
"singletonMode": false,
"configurationVersion": 0,
"configurationVersion": 1,
"configuration": {
"defaultTTL": 0,
"skipLatestPersistence": false,
"useServerTs": false
"useServerTs": false,
"processingSettings": {
"type": "ON_EVERY_MESSAGE"
}
},
"externalId": null
},

2
rule-engine/rule-engine-api/src/main/java/org/thingsboard/rule/engine/api/NotificationCenter.java

@ -36,7 +36,7 @@ public interface NotificationCenter {
NotificationRequest processNotificationRequest(TenantId tenantId, NotificationRequest notificationRequest, FutureCallback<NotificationRequestStats> callback);
void sendGeneralWebNotification(TenantId tenantId, UsersFilter recipients, NotificationTemplate template, GeneralNotificationInfo info);
void sendGeneralWebNotification(TenantId tenantId, UsersFilter recipients, NotificationTemplate template, GeneralNotificationInfo info); // for future use
void sendSystemNotification(TenantId tenantId, NotificationTargetId targetId, NotificationType type, NotificationInfo info); // for future use and compatibility with PE

27
rule-engine/rule-engine-api/src/main/java/org/thingsboard/rule/engine/api/TimeseriesSaveRequest.java

@ -38,10 +38,18 @@ public class TimeseriesSaveRequest {
private final EntityId entityId;
private final List<TsKvEntry> entries;
private final long ttl;
private final boolean saveLatest;
private final boolean onlyLatest;
private final Strategy strategy;
private final FutureCallback<Void> callback;
public record Strategy(boolean saveTimeseries, boolean saveLatest, boolean sendWsUpdate) {
public static final Strategy SAVE_ALL = new Strategy(true, true, true);
public static final Strategy WS_ONLY = new Strategy(false, false, true);
public static final Strategy LATEST_AND_WS = new Strategy(false, true, true);
public static final Strategy SKIP_ALL = new Strategy(false, false, false);
}
public static Builder builder() {
return new Builder();
}
@ -53,9 +61,8 @@ public class TimeseriesSaveRequest {
private EntityId entityId;
private List<TsKvEntry> entries;
private long ttl;
private Strategy strategy = Strategy.SAVE_ALL;
private FutureCallback<Void> callback;
private boolean saveLatest = true;
private boolean onlyLatest;
Builder() {}
@ -92,14 +99,8 @@ public class TimeseriesSaveRequest {
return this;
}
public Builder saveLatest(boolean saveLatest) {
this.saveLatest = saveLatest;
return this;
}
public Builder onlyLatest(boolean onlyLatest) {
this.onlyLatest = onlyLatest;
this.saveLatest = true;
public Builder strategy(Strategy strategy) {
this.strategy = strategy;
return this;
}
@ -123,7 +124,7 @@ public class TimeseriesSaveRequest {
}
public TimeseriesSaveRequest build() {
return new TimeseriesSaveRequest(tenantId, customerId, entityId, entries, ttl, saveLatest, onlyLatest, callback);
return new TimeseriesSaveRequest(tenantId, customerId, entityId, entries, ttl, strategy, callback);
}
}

51
rule-engine/rule-engine-api/src/test/java/org/thingsboard/rule/engine/api/TimeseriesSaveRequestTest.java

@ -0,0 +1,51 @@
/**
* Copyright © 2016-2024 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.rule.engine.api;
import org.junit.jupiter.api.Test;
import static org.assertj.core.api.Assertions.assertThat;
class TimeseriesSaveRequestTest {
@Test
void testDefaultSaveStrategyIsSaveAll() {
var request = TimeseriesSaveRequest.builder().build();
assertThat(request.getStrategy()).isEqualTo(TimeseriesSaveRequest.Strategy.SAVE_ALL);
}
@Test
void testSaveAllStrategy() {
assertThat(TimeseriesSaveRequest.Strategy.SAVE_ALL).isEqualTo(new TimeseriesSaveRequest.Strategy(true, true, true));
}
@Test
void testWsOnlyStrategy() {
assertThat(TimeseriesSaveRequest.Strategy.WS_ONLY).isEqualTo(new TimeseriesSaveRequest.Strategy(false, false, true));
}
@Test
void testLatestAndWsStrategy() {
assertThat(TimeseriesSaveRequest.Strategy.LATEST_AND_WS).isEqualTo(new TimeseriesSaveRequest.Strategy(false, true, true));
}
@Test
void testSkipAllStrategy() {
assertThat(TimeseriesSaveRequest.Strategy.SKIP_ALL).isEqualTo(new TimeseriesSaveRequest.Strategy(false, false, false));
}
}

2
rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rest/TbHttpClient.java

@ -347,7 +347,7 @@ public class TbHttpClient {
if (CredentialsType.BASIC == credentials.getType()) {
BasicCredentials basicCredentials = (BasicCredentials) credentials;
String authString = basicCredentials.getUsername() + ":" + basicCredentials.getPassword();
String encodedAuthString = new String(Base64.getDecoder().decode(authString.getBytes(StandardCharsets.UTF_8)));
String encodedAuthString = new String(Base64.getEncoder().encode(authString.getBytes(StandardCharsets.UTF_8)));
headers.add("Authorization", "Basic " + encodedAuthString);
}
}

132
rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/telemetry/TbMsgTimeseriesNode.java

@ -15,8 +15,11 @@
*/
package org.thingsboard.rule.engine.telemetry;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.google.gson.JsonParser;
import lombok.extern.slf4j.Slf4j;
import org.thingsboard.common.util.JacksonUtil;
import org.thingsboard.rule.engine.api.RuleNode;
import org.thingsboard.rule.engine.api.TbContext;
import org.thingsboard.rule.engine.api.TbNode;
@ -24,6 +27,7 @@ import org.thingsboard.rule.engine.api.TbNodeConfiguration;
import org.thingsboard.rule.engine.api.TbNodeException;
import org.thingsboard.rule.engine.api.TimeseriesSaveRequest;
import org.thingsboard.rule.engine.api.util.TbNodeUtils;
import org.thingsboard.rule.engine.telemetry.strategy.ProcessingStrategy;
import org.thingsboard.server.common.adaptor.JsonConverter;
import org.thingsboard.server.common.data.StringUtils;
import org.thingsboard.server.common.data.TenantProfile;
@ -32,13 +36,20 @@ import org.thingsboard.server.common.data.kv.KvEntry;
import org.thingsboard.server.common.data.kv.TsKvEntry;
import org.thingsboard.server.common.data.plugin.ComponentType;
import org.thingsboard.server.common.data.tenant.profile.DefaultTenantProfileConfiguration;
import org.thingsboard.server.common.data.util.TbPair;
import org.thingsboard.server.common.msg.TbMsg;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
import static org.thingsboard.rule.engine.telemetry.TbMsgTimeseriesNodeConfiguration.ProcessingSettings;
import static org.thingsboard.rule.engine.telemetry.TbMsgTimeseriesNodeConfiguration.ProcessingSettings.Advanced;
import static org.thingsboard.rule.engine.telemetry.TbMsgTimeseriesNodeConfiguration.ProcessingSettings.Deduplicate;
import static org.thingsboard.rule.engine.telemetry.TbMsgTimeseriesNodeConfiguration.ProcessingSettings.OnEveryMessage;
import static org.thingsboard.rule.engine.telemetry.TbMsgTimeseriesNodeConfiguration.ProcessingSettings.WebSocketsOnly;
import static org.thingsboard.server.common.data.msg.TbMsgType.POST_TELEMETRY_REQUEST;
@Slf4j
@ -46,20 +57,52 @@ import static org.thingsboard.server.common.data.msg.TbMsgType.POST_TELEMETRY_RE
type = ComponentType.ACTION,
name = "save time series",
configClazz = TbMsgTimeseriesNodeConfiguration.class,
nodeDescription = "Saves time series data",
nodeDetails = "Saves time series telemetry data based on configurable TTL parameter. Expects messages with 'POST_TELEMETRY_REQUEST' message type. " +
"Timestamp in milliseconds will be taken from metadata.ts, otherwise 'now' message timestamp will be applied. " +
"Allows stopping updating values for incoming keys in the latest ts_kv table if 'skipLatestPersistence' is set to true.\n " +
"<br/>" +
"Enable 'useServerTs' param to use the timestamp of the message processing instead of the timestamp from the message. " +
"Useful for all sorts of sequential processing if you merge messages from multiple sources (devices, assets, etc).\n" +
"<br/>" +
"In the case of sequential processing, the platform guarantees that the messages are processed in the order of their submission to the queue. " +
"However, the timestamp of the messages originated by multiple devices/servers may be unsynchronized long before they are pushed to the queue. " +
"The DB layer has certain optimizations to ignore the updates of the \"attributes\" and \"latest values\" tables if the new record has a timestamp that is older than the previous record. " +
"So, to make sure that all the messages will be processed correctly, one should enable this parameter for sequential message processing scenarios.",
nodeDescription = """
Saves time series data with a configurable TTL and according to configured processing strategies.
""",
nodeDetails = """
Node performs three <strong>actions:</strong>
<ul>
<li><strong>Time series:</strong> save time series data to a <code>ts_kv</code> table in a DB.</li>
<li><strong>Latest values:</strong> save time series data to a <code>ts_kv_latest</code> table in a DB.</li>
<li><strong>WebSockets:</strong> notify WebSockets subscriptions about time series data updates.</li>
</ul>
For each <em>action</em>, three <strong>processing strategies</strong> are available:
<ul>
<li><strong>On every message:</strong> perform the action for every message.</li>
<li><strong>Deduplicate:</strong> perform the action only for the first message from a particular originator within a configurable interval.</li>
<li><strong>Skip:</strong> never perform the action.</li>
</ul>
<strong>Processing strategies</strong> are configured using <em>processing settings</em>, which support two modes:
<ul>
<li><strong>Basic</strong>
<ul>
<li><strong>On every message:</strong> applies the "On every message" strategy to all actions.</li>
<li><strong>Deduplicate:</strong> applies the "Deduplicate" strategy (with a specified interval) to all actions.</li>
<li><strong>WebSockets only:</strong> applies the "Skip" strategy to Time series and Latest values, and the "On every message" strategy to WebSockets.</li>
</ul>
</li>
<li><strong>Advanced:</strong> configure each actions strategy independently.</li>
</ul>
By default, the timestamp is taken from <code>metadata.ts</code>. You can enable
<em>Use server timestamp</em> to always use the current server time instead. This is particularly
useful in sequential processing scenarios where messages may arrive with out-of-order timestamps from
multiple sources. Note that the DB layer may ignore older records for attributes and latest values,
so enabling <em>Use server timestamp</em> can ensure correct ordering.
<br><br>
The TTL is taken first from <code>metadata.TTL</code>. If absent, the node configurations default
TTL is used. If neither is set, the tenant profile default applies.
<br><br>
This node expects messages of type <code>POST_TELEMETRY_REQUEST</code>.
<br><br>
Output connections: <code>Success</code>, <code>Failure</code>.
""",
configDirective = "tbActionNodeTimeseriesConfig",
icon = "file_upload"
icon = "file_upload",
version = 1
)
public class TbMsgTimeseriesNode implements TbNode {
@ -67,15 +110,18 @@ public class TbMsgTimeseriesNode implements TbNode {
private TbContext ctx;
private long tenantProfileDefaultStorageTtl;
private ProcessingSettings processingSettings;
@Override
public void init(TbContext ctx, TbNodeConfiguration configuration) throws TbNodeException {
this.config = TbNodeUtils.convert(configuration, TbMsgTimeseriesNodeConfiguration.class);
this.ctx = ctx;
ctx.addTenantProfileListener(this::onTenantProfileUpdate);
onTenantProfileUpdate(ctx.getTenantProfile());
processingSettings = config.getProcessingSettings();
}
void onTenantProfileUpdate(TenantProfile tenantProfile) {
private void onTenantProfileUpdate(TenantProfile tenantProfile) {
DefaultTenantProfileConfiguration configuration = (DefaultTenantProfileConfiguration) tenantProfile.getProfileData().getConfiguration();
tenantProfileDefaultStorageTtl = TimeUnit.DAYS.toSeconds(configuration.getDefaultStorageTtlDays());
}
@ -87,6 +133,15 @@ public class TbMsgTimeseriesNode implements TbNode {
return;
}
long ts = computeTs(msg, config.isUseServerTs());
TimeseriesSaveRequest.Strategy strategy = determineSaveStrategy(ts, msg.getOriginator().getId());
// short-circuit
if (!strategy.saveTimeseries() && !strategy.saveLatest() && !strategy.sendWsUpdate()) {
ctx.tellSuccess(msg);
return;
}
String src = msg.getData();
Map<Long, List<KvEntry>> tsKvMap = JsonConverter.convertToTelemetry(JsonParser.parseString(src), ts);
if (tsKvMap.isEmpty()) {
@ -110,7 +165,7 @@ public class TbMsgTimeseriesNode implements TbNode {
.entityId(msg.getOriginator())
.entries(tsKvEntryList)
.ttl(ttl)
.saveLatest(!config.isSkipLatestPersistence())
.strategy(strategy)
.callback(new TelemetryNodeCallback(ctx, msg))
.build());
}
@ -119,9 +174,56 @@ public class TbMsgTimeseriesNode implements TbNode {
return ignoreMetadataTs ? System.currentTimeMillis() : msg.getMetaDataTs();
}
private TimeseriesSaveRequest.Strategy determineSaveStrategy(long ts, UUID originatorUuid) {
if (processingSettings instanceof OnEveryMessage) {
return TimeseriesSaveRequest.Strategy.SAVE_ALL;
}
if (processingSettings instanceof WebSocketsOnly) {
return TimeseriesSaveRequest.Strategy.WS_ONLY;
}
if (processingSettings instanceof Deduplicate deduplicate) {
boolean isFirstMsgInInterval = deduplicate.getProcessingStrategy().shouldProcess(ts, originatorUuid);
return isFirstMsgInInterval ? TimeseriesSaveRequest.Strategy.SAVE_ALL : TimeseriesSaveRequest.Strategy.SKIP_ALL;
}
if (processingSettings instanceof Advanced advanced) {
return new TimeseriesSaveRequest.Strategy(
advanced.timeseries().shouldProcess(ts, originatorUuid),
advanced.latest().shouldProcess(ts, originatorUuid),
advanced.webSockets().shouldProcess(ts, originatorUuid)
);
}
// should not happen
throw new IllegalArgumentException("Unknown processing settings type: " + processingSettings.getClass().getSimpleName());
}
@Override
public void destroy() {
ctx.removeListeners();
}
@Override
public TbPair<Boolean, JsonNode> upgrade(int fromVersion, JsonNode oldConfiguration) throws TbNodeException {
boolean hasChanges = false;
switch (fromVersion) {
case 0:
hasChanges = true;
JsonNode skipLatestPersistence = oldConfiguration.get("skipLatestPersistence");
if (skipLatestPersistence != null && "true".equals(skipLatestPersistence.asText())) {
var skipLatestProcessingSettings = new Advanced(
ProcessingStrategy.onEveryMessage(),
ProcessingStrategy.skip(),
ProcessingStrategy.onEveryMessage()
);
((ObjectNode) oldConfiguration).set("processingSettings", JacksonUtil.valueToTree(skipLatestProcessingSettings));
} else {
((ObjectNode) oldConfiguration).set("processingSettings", JacksonUtil.valueToTree(new OnEveryMessage()));
}
((ObjectNode) oldConfiguration).remove("skipLatestPersistence");
break;
default:
break;
}
return new TbPair<>(hasChanges, oldConfiguration);
}
}

66
rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/telemetry/TbMsgTimeseriesNodeConfiguration.java

@ -15,22 +15,84 @@
*/
package org.thingsboard.rule.engine.telemetry;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonSubTypes;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import lombok.Getter;
import org.thingsboard.rule.engine.api.NodeConfiguration;
import org.thingsboard.rule.engine.telemetry.strategy.ProcessingStrategy;
import java.util.Objects;
import static org.thingsboard.rule.engine.telemetry.TbMsgTimeseriesNodeConfiguration.ProcessingSettings.Advanced;
import static org.thingsboard.rule.engine.telemetry.TbMsgTimeseriesNodeConfiguration.ProcessingSettings.Deduplicate;
import static org.thingsboard.rule.engine.telemetry.TbMsgTimeseriesNodeConfiguration.ProcessingSettings.OnEveryMessage;
import static org.thingsboard.rule.engine.telemetry.TbMsgTimeseriesNodeConfiguration.ProcessingSettings.WebSocketsOnly;
@Data
public class TbMsgTimeseriesNodeConfiguration implements NodeConfiguration<TbMsgTimeseriesNodeConfiguration> {
private long defaultTTL;
private boolean skipLatestPersistence;
private boolean useServerTs;
@NotNull
private TbMsgTimeseriesNodeConfiguration.ProcessingSettings processingSettings;
@Override
public TbMsgTimeseriesNodeConfiguration defaultConfiguration() {
TbMsgTimeseriesNodeConfiguration configuration = new TbMsgTimeseriesNodeConfiguration();
configuration.setDefaultTTL(0L);
configuration.setSkipLatestPersistence(false);
configuration.setUseServerTs(false);
configuration.setProcessingSettings(new OnEveryMessage());
return configuration;
}
@JsonTypeInfo(
use = JsonTypeInfo.Id.NAME,
include = JsonTypeInfo.As.PROPERTY,
property = "type"
)
@JsonSubTypes({
@JsonSubTypes.Type(value = OnEveryMessage.class, name = "ON_EVERY_MESSAGE"),
@JsonSubTypes.Type(value = WebSocketsOnly.class, name = "WEBSOCKETS_ONLY"),
@JsonSubTypes.Type(value = Deduplicate.class, name = "DEDUPLICATE"),
@JsonSubTypes.Type(value = Advanced.class, name = "ADVANCED")
})
sealed interface ProcessingSettings permits OnEveryMessage, Deduplicate, WebSocketsOnly, Advanced {
record OnEveryMessage() implements ProcessingSettings {}
record WebSocketsOnly() implements ProcessingSettings {}
@Getter
final class Deduplicate implements ProcessingSettings {
private final int deduplicationIntervalSecs;
@JsonIgnore
private final ProcessingStrategy processingStrategy;
@JsonCreator
Deduplicate(@JsonProperty("deduplicationIntervalSecs") int deduplicationIntervalSecs) {
this.deduplicationIntervalSecs = deduplicationIntervalSecs;
processingStrategy = ProcessingStrategy.deduplicate(deduplicationIntervalSecs);
}
}
record Advanced(ProcessingStrategy timeseries, ProcessingStrategy latest, ProcessingStrategy webSockets) implements ProcessingSettings {
public Advanced {
Objects.requireNonNull(timeseries);
Objects.requireNonNull(latest);
Objects.requireNonNull(webSockets);
}
}
}
}

89
rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/telemetry/strategy/DeduplicateProcessingStrategy.java

@ -0,0 +1,89 @@
/**
* Copyright © 2016-2024 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.rule.engine.telemetry.strategy;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.github.benmanes.caffeine.cache.Caffeine;
import com.github.benmanes.caffeine.cache.LoadingCache;
import com.google.common.collect.Sets;
import com.google.common.primitives.Longs;
import java.time.Duration;
import java.util.Set;
import java.util.UUID;
final class DeduplicateProcessingStrategy implements ProcessingStrategy {
private static final int MIN_DEDUPLICATION_INTERVAL_SECS = 1;
private static final int MAX_DEDUPLICATION_INTERVAL_SECS = (int) Duration.ofDays(1L).toSeconds();
private static final long MIN_INTERVAL_EXPIRY_MILLIS = Duration.ofMinutes(10L).toMillis();
private static final int INTERVAL_EXPIRY_FACTOR = 10;
private static final long MAX_INTERVAL_EXPIRY_MILLIS = Duration.ofDays(2L).toMillis();
private static final int MAX_TOTAL_INTERVALS_DURATION_SECS = (int) Duration.ofDays(2L).toSeconds();
private static final int MAX_NUMBER_OF_INTERVALS = 100;
private final long deduplicationIntervalMillis;
private final LoadingCache<Long, Set<UUID>> deduplicationCache;
@JsonCreator
public DeduplicateProcessingStrategy(@JsonProperty("deduplicationIntervalSecs") int deduplicationIntervalSecs) {
if (deduplicationIntervalSecs < MIN_DEDUPLICATION_INTERVAL_SECS || deduplicationIntervalSecs > MAX_DEDUPLICATION_INTERVAL_SECS) {
throw new IllegalArgumentException("Deduplication interval must be at least " + MIN_DEDUPLICATION_INTERVAL_SECS + " second(s) " +
"and at most " + MAX_DEDUPLICATION_INTERVAL_SECS + " second(s), was " + deduplicationIntervalSecs + " second(s)");
}
deduplicationIntervalMillis = Duration.ofSeconds(deduplicationIntervalSecs).toMillis();
deduplicationCache = Caffeine.newBuilder()
.softValues()
.expireAfterAccess(calculateExpireAfterAccess(deduplicationIntervalSecs))
.maximumSize(calculateMaxNumberOfDeduplicationIntervals(deduplicationIntervalSecs))
.build(__ -> Sets.newConcurrentHashSet());
}
/**
* Calculates the expire-after-access duration. By default, we keep each deduplication interval
* alive for 10 iterations (interval duration × 10). However, we never let this drop below
* 10 minutes to ensure adequate retention for small intervals, nor exceed 48 hours to prevent
* storing stale data in memory.
*/
private static Duration calculateExpireAfterAccess(int deduplicationIntervalSecs) {
long desiredExpiryMillis = Duration.ofSeconds(deduplicationIntervalSecs).toMillis() * INTERVAL_EXPIRY_FACTOR;
return Duration.ofMillis(Longs.constrainToRange(desiredExpiryMillis, MIN_INTERVAL_EXPIRY_MILLIS, MAX_INTERVAL_EXPIRY_MILLIS));
}
/**
* Calculates the maximum number of deduplication intervals we will store in the cache.
* We limit retention to two days to avoid stale data and cap it at 100 intervals to manage memory usage.
*/
private static long calculateMaxNumberOfDeduplicationIntervals(int deduplicationIntervalSecs) {
int numberOfDeduplicationIntervals = MAX_TOTAL_INTERVALS_DURATION_SECS / deduplicationIntervalSecs;
return Math.min(numberOfDeduplicationIntervals, MAX_NUMBER_OF_INTERVALS);
}
@JsonProperty("deduplicationIntervalSecs")
public long getDeduplicationIntervalSecs() {
return Duration.ofMillis(deduplicationIntervalMillis).toSeconds();
}
@Override
public boolean shouldProcess(long ts, UUID originatorUuid) {
long intervalNumber = ts / deduplicationIntervalMillis;
return deduplicationCache.get(intervalNumber).add(originatorUuid);
}
}

38
rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/telemetry/strategy/OnEveryMessageProcessingStrategy.java

@ -0,0 +1,38 @@
/**
* Copyright © 2016-2024 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.rule.engine.telemetry.strategy;
import com.fasterxml.jackson.annotation.JsonCreator;
import java.util.UUID;
final class OnEveryMessageProcessingStrategy implements ProcessingStrategy {
private static final OnEveryMessageProcessingStrategy INSTANCE = new OnEveryMessageProcessingStrategy();
private OnEveryMessageProcessingStrategy() {}
@JsonCreator
public static OnEveryMessageProcessingStrategy getInstance() {
return INSTANCE;
}
@Override
public boolean shouldProcess(long ts, UUID originatorUuid) {
return true;
}
}

49
rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/telemetry/strategy/ProcessingStrategy.java

@ -0,0 +1,49 @@
/**
* Copyright © 2016-2024 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.rule.engine.telemetry.strategy;
import com.fasterxml.jackson.annotation.JsonSubTypes;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import java.util.UUID;
@JsonTypeInfo(
use = JsonTypeInfo.Id.NAME,
include = JsonTypeInfo.As.PROPERTY,
property = "type"
)
@JsonSubTypes({
@JsonSubTypes.Type(value = OnEveryMessageProcessingStrategy.class, name = "ON_EVERY_MESSAGE"),
@JsonSubTypes.Type(value = DeduplicateProcessingStrategy.class, name = "DEDUPLICATE"),
@JsonSubTypes.Type(value = SkipProcessingStrategy.class, name = "SKIP")
})
public sealed interface ProcessingStrategy permits OnEveryMessageProcessingStrategy, DeduplicateProcessingStrategy, SkipProcessingStrategy {
static ProcessingStrategy onEveryMessage() {
return OnEveryMessageProcessingStrategy.getInstance();
}
static ProcessingStrategy deduplicate(int deduplicationIntervalSecs) {
return new DeduplicateProcessingStrategy(deduplicationIntervalSecs);
}
static ProcessingStrategy skip() {
return SkipProcessingStrategy.getInstance();
}
boolean shouldProcess(long ts, UUID originatorUuid);
}

38
rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/telemetry/strategy/SkipProcessingStrategy.java

@ -0,0 +1,38 @@
/**
* Copyright © 2016-2024 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.rule.engine.telemetry.strategy;
import com.fasterxml.jackson.annotation.JsonCreator;
import java.util.UUID;
final class SkipProcessingStrategy implements ProcessingStrategy {
private static final SkipProcessingStrategy INSTANCE = new SkipProcessingStrategy();
private SkipProcessingStrategy() {}
@JsonCreator
public static SkipProcessingStrategy getInstance() {
return INSTANCE;
}
@Override
public boolean shouldProcess(long ts, UUID originatorUuid) {
return false;
}
}

4
rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/math/TbMathNodeTest.java

@ -533,7 +533,7 @@ public class TbMathNodeTest {
verify(ctx, timeout(TIMEOUT)).tellSuccess(msgCaptor.capture());
verify(telemetryService, times(1)).saveTimeseries(assertArg(request -> {
assertThat(request.getEntries()).size().isOne();
assertThat(request.isSaveLatest()).isTrue();
assertThat(request.getStrategy()).isEqualTo(TimeseriesSaveRequest.Strategy.SAVE_ALL);
}));
TbMsg resultMsg = msgCaptor.getValue();
@ -569,7 +569,7 @@ public class TbMathNodeTest {
verify(ctx, timeout(TIMEOUT)).tellSuccess(msgCaptor.capture());
verify(telemetryService, times(1)).saveTimeseries(assertArg(request -> {
assertThat(request.getEntries()).size().isOne();
assertThat(request.isSaveLatest()).isTrue();
assertThat(request.getStrategy()).isEqualTo(TimeseriesSaveRequest.Strategy.SAVE_ALL);
}));
TbMsg resultMsg = msgCaptor.getValue();

449
rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/telemetry/TbMsgTimeseriesNodeTest.java

@ -25,20 +25,23 @@ import org.junit.jupiter.params.provider.EnumSource;
import org.junit.jupiter.params.provider.MethodSource;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.ThrowingConsumer;
import org.mockito.junit.jupiter.MockitoExtension;
import org.thingsboard.common.util.JacksonUtil;
import org.thingsboard.rule.engine.AbstractRuleNodeUpgradeTest;
import org.thingsboard.rule.engine.api.RuleEngineTelemetryService;
import org.thingsboard.rule.engine.api.TbContext;
import org.thingsboard.rule.engine.api.TbNode;
import org.thingsboard.rule.engine.api.TbNodeConfiguration;
import org.thingsboard.rule.engine.api.TbNodeException;
import org.thingsboard.rule.engine.api.TimeseriesSaveRequest;
import org.thingsboard.rule.engine.telemetry.strategy.ProcessingStrategy;
import org.thingsboard.server.common.adaptor.JsonConverter;
import org.thingsboard.server.common.data.TenantProfile;
import org.thingsboard.server.common.data.id.DeviceId;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.id.TenantProfileId;
import org.thingsboard.server.common.data.kv.BasicTsKvEntry;
import org.thingsboard.server.common.data.kv.DoubleDataEntry;
import org.thingsboard.server.common.data.kv.KvEntry;
import org.thingsboard.server.common.data.kv.TsKvEntry;
import org.thingsboard.server.common.data.msg.TbMsgType;
@ -46,6 +49,8 @@ import org.thingsboard.server.common.data.tenant.profile.DefaultTenantProfileCon
import org.thingsboard.server.common.data.tenant.profile.TenantProfileData;
import org.thingsboard.server.common.msg.TbMsg;
import org.thingsboard.server.common.msg.TbMsgMetaData;
import org.thingsboard.server.dao.exception.DataValidationException;
import org.thingsboard.server.dao.service.ConstraintValidator;
import java.util.ArrayList;
import java.util.List;
@ -55,24 +60,30 @@ import java.util.concurrent.TimeUnit;
import java.util.stream.Stream;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.assertArg;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.BDDMockito.then;
import static org.mockito.Mockito.clearInvocations;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.lenient;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.when;
@ExtendWith(MockitoExtension.class)
public class TbMsgTimeseriesNodeTest {
public class TbMsgTimeseriesNodeTest extends AbstractRuleNodeUpgradeTest {
private final TenantId TENANT_ID = TenantId.fromUUID(UUID.fromString("c8f34868-603a-4433-876a-7d356e5cf377"));
private final DeviceId DEVICE_ID = new DeviceId(UUID.fromString("e5095e9a-04f4-44c9-b443-1cf1b97d3384"));
private final TenantProfileId TENANT_PROFILE_ID = new TenantProfileId(UUID.fromString("ab78dd78-83d0-43fa-869f-d42ec9ed1744"));
private TenantProfile tenantProfile;
private TbMsgTimeseriesNode node;
private TbMsgTimeseriesNodeConfiguration config;
private long tenantProfileDefaultStorageTtl;
@Mock
private TbContext ctxMock;
@ -81,29 +92,68 @@ public class TbMsgTimeseriesNodeTest {
@BeforeEach
public void setUp() throws TbNodeException {
node = new TbMsgTimeseriesNode();
tenantProfile = new TenantProfile(new TenantProfileId(UUID.fromString("ab78dd78-83d0-43fa-869f-d42ec9ed1744")));
var tenantProfileConfiguration = new DefaultTenantProfileConfiguration();
tenantProfileConfiguration.setDefaultStorageTtlDays(5);
var tenantProfileData = new TenantProfileData();
tenantProfileData.setConfiguration(tenantProfileConfiguration);
tenantProfile.setProfileData(tenantProfileData);
lenient().when(ctxMock.getTenantProfile()).thenReturn(tenantProfile);
lenient().when(ctxMock.getTenantId()).thenReturn(TENANT_ID);
lenient().when(ctxMock.getTelemetryService()).thenReturn(telemetryServiceMock);
node = spy(new TbMsgTimeseriesNode());
config = new TbMsgTimeseriesNodeConfiguration().defaultConfiguration();
}
@Test
public void verifyDefaultConfig() {
assertThat(config.getDefaultTTL()).isEqualTo(0L);
assertThat(config.isSkipLatestPersistence()).isFalse();
assertThat(config.getProcessingSettings()).isInstanceOf(TbMsgTimeseriesNodeConfiguration.ProcessingSettings.OnEveryMessage.class);
assertThat(config.isUseServerTs()).isFalse();
}
@Test
public void whenInit_thenShouldAddTenantProfileListener() throws Exception {
// GIVEN-WHEN
node.init(ctxMock, new TbNodeConfiguration(JacksonUtil.valueToTree(config)));
// THEN
then(ctxMock).should().addTenantProfileListener(any());
}
@Test
public void givenProcessingSettingsAreNull_whenValidatingConstraints_thenThrowsException() {
// GIVEN
config.setProcessingSettings(null);
// WHEN-THEN
assertThatThrownBy(() -> ConstraintValidator.validateFields(config))
.isInstanceOf(DataValidationException.class)
.hasMessage("Validation error: processingSettings must not be null");
}
@ParameterizedTest
@EnumSource(TbMsgType.class)
public void givenMsgTypeAndEmptyMsgData_whenOnMsg_thenVerifyFailureMsg(TbMsgType msgType) throws TbNodeException {
init();
// GIVEN
node.init(ctxMock, new TbNodeConfiguration(JacksonUtil.valueToTree(config)));
TbMsg msg = TbMsg.newMsg()
.type(msgType)
.originator(DEVICE_ID)
.copyMetaData(TbMsgMetaData.EMPTY)
.data(TbMsg.EMPTY_JSON_ARRAY)
.build();
// WHEN
node.onMsg(ctxMock, msg);
// THEN
then(ctxMock).should().addTenantProfileListener(any());
then(ctxMock).should().getTenantProfile();
ArgumentCaptor<Throwable> throwableCaptor = ArgumentCaptor.forClass(Throwable.class);
verify(ctxMock).tellFailure(eq(msg), throwableCaptor.capture());
@ -117,9 +167,11 @@ public class TbMsgTimeseriesNodeTest {
}
@Test
public void givenTtlFromConfigIsZeroAndUseServiceTsIsTrue_whenOnMsg_thenSaveTimeseriesUsingTenantProfileDefaultTtl() throws TbNodeException {
public void givenTtlFromConfigIsZeroAndUseServerTsIsTrue_whenOnMsg_thenSaveTimeseriesUsingTenantProfileDefaultTtl() throws TbNodeException {
// GIVEN
config.setUseServerTs(true);
init();
node.init(ctxMock, new TbNodeConfiguration(JacksonUtil.valueToTree(config)));
String data = """
{
@ -134,24 +186,29 @@ public class TbMsgTimeseriesNodeTest {
.data(data)
.build();
when(ctxMock.getTelemetryService()).thenReturn(telemetryServiceMock);
when(ctxMock.getTenantId()).thenReturn(TENANT_ID);
doAnswer(invocation -> {
TimeseriesSaveRequest request = invocation.getArgument(0);
request.getCallback().onSuccess(null);
return null;
}).when(telemetryServiceMock).saveTimeseries(any(TimeseriesSaveRequest.class));
// WHEN
node.onMsg(ctxMock, msg);
// THEN
then(ctxMock).should().getTenantId();
then(ctxMock).should().getTelemetryService();
then(ctxMock).should().addTenantProfileListener(any());
then(ctxMock).should().getTenantProfile();
List<TsKvEntry> expectedList = getTsKvEntriesListWithTs(data, System.currentTimeMillis());
verify(telemetryServiceMock).saveTimeseries(assertArg(request -> {
assertThat(request.getTenantId()).isEqualTo(TENANT_ID);
assertThat(request.getCustomerId()).isNull();
assertThat(request.getEntityId()).isEqualTo(DEVICE_ID);
assertThat(request.getEntries()).usingRecursiveFieldByFieldElementComparatorIgnoringFields("ts").containsExactlyElementsOf(expectedList);
assertThat(request.getTtl()).isEqualTo(tenantProfileDefaultStorageTtl);
assertThat(request.isSaveLatest()).isTrue();
assertThat(request.getTtl()).isEqualTo(extractTtlAsSeconds(tenantProfile));
assertThat(request.getStrategy()).isEqualTo(TimeseriesSaveRequest.Strategy.SAVE_ALL);
assertThat(request.getCallback()).isInstanceOf(TelemetryNodeCallback.class);
}));
verify(ctxMock).tellSuccess(msg);
@ -159,11 +216,17 @@ public class TbMsgTimeseriesNodeTest {
}
@Test
public void givenSkipLatestPersistenceIsTrueAndTtlFromConfig_whenOnMsg_thenSaveTimeseriesUsingTtlFromConfig() throws TbNodeException {
long ttlFromConfig = 5L;
config.setDefaultTTL(ttlFromConfig);
config.setSkipLatestPersistence(true);
init();
public void givenSkipLatestProcessingSettingsAndTtlFromConfig_whenOnMsg_thenSaveTimeseriesUsingTtlFromConfig() throws TbNodeException {
// GIVEN
config.setDefaultTTL(10L);
var timeseriesStrategy = ProcessingStrategy.onEveryMessage();
var latestStrategy = ProcessingStrategy.skip();
var webSockets = ProcessingStrategy.onEveryMessage();
var processingSettings = new TbMsgTimeseriesNodeConfiguration.ProcessingSettings.Advanced(timeseriesStrategy, latestStrategy, webSockets);
config.setProcessingSettings(processingSettings);
node.init(ctxMock, new TbNodeConfiguration(JacksonUtil.valueToTree(config)));
String data = """
{
@ -180,24 +243,29 @@ public class TbMsgTimeseriesNodeTest {
.data(data)
.build();
when(ctxMock.getTelemetryService()).thenReturn(telemetryServiceMock);
when(ctxMock.getTenantId()).thenReturn(TENANT_ID);
doAnswer(invocation -> {
TimeseriesSaveRequest request = invocation.getArgument(0);
request.getCallback().onSuccess(null);
return null;
}).when(telemetryServiceMock).saveTimeseries(any(TimeseriesSaveRequest.class));
// WHEN
node.onMsg(ctxMock, msg);
// THEN
then(ctxMock).should().getTenantId();
then(ctxMock).should().getTelemetryService();
then(ctxMock).should().addTenantProfileListener(any());
then(ctxMock).should().getTenantProfile();
List<TsKvEntry> expectedList = getTsKvEntriesListWithTs(data, ts);
verify(telemetryServiceMock).saveTimeseries(assertArg(request -> {
assertThat(request.getTenantId()).isEqualTo(TENANT_ID);
assertThat(request.getCustomerId()).isNull();
assertThat(request.getEntityId()).isEqualTo(DEVICE_ID);
assertThat(request.getEntries()).containsExactlyElementsOf(expectedList);
assertThat(request.getTtl()).isEqualTo(ttlFromConfig);
assertThat(request.isSaveLatest()).isFalse();
assertThat(request.getTtl()).isEqualTo(config.getDefaultTTL());
assertThat(request.getStrategy()).isEqualTo(new TimeseriesSaveRequest.Strategy(true, false, true));
assertThat(request.getCallback()).isInstanceOf(TelemetryNodeCallback.class);
}));
verify(ctxMock).tellSuccess(msg);
@ -207,11 +275,10 @@ public class TbMsgTimeseriesNodeTest {
@ParameterizedTest
@MethodSource
public void givenTtlFromConfigAndTtlFromMd_whenOnMsg_thenVerifyTtl(String ttlFromMd, long ttlFromConfig, long expectedTtl) throws TbNodeException {
// GIVEN
config.setDefaultTTL(ttlFromConfig);
init();
when(ctxMock.getTelemetryService()).thenReturn(telemetryServiceMock);
when(ctxMock.getTenantId()).thenReturn(TENANT_ID);
node.init(ctxMock, new TbNodeConfiguration(JacksonUtil.valueToTree(config)));
String data = """
{
@ -227,14 +294,17 @@ public class TbMsgTimeseriesNodeTest {
.copyMetaData(metadata)
.data(data)
.build();
// WHEN
node.onMsg(ctxMock, msg);
// THEN
verify(telemetryServiceMock).saveTimeseries(assertArg(request -> {
assertThat(request.getTenantId()).isEqualTo(TENANT_ID);
assertThat(request.getCustomerId()).isNull();
assertThat(request.getEntityId()).isEqualTo(DEVICE_ID);
assertThat(request.getTtl()).isEqualTo(expectedTtl);
assertThat(request.isSaveLatest()).isTrue();
assertThat(request.getStrategy()).isEqualTo(TimeseriesSaveRequest.Strategy.SAVE_ALL);
assertThat(request.getCallback()).isInstanceOf(TelemetryNodeCallback.class);
}));
}
@ -251,26 +321,6 @@ public class TbMsgTimeseriesNodeTest {
);
}
private void init() throws TbNodeException {
var configuration = new TbNodeConfiguration(JacksonUtil.valueToTree(config));
var tenantProfile = getTenantProfile();
when(ctxMock.getTenantProfile()).thenReturn(tenantProfile);
tenantProfile.getProfileConfiguration().ifPresent(profileConfiguration ->
tenantProfileDefaultStorageTtl = TimeUnit.DAYS.toSeconds(profileConfiguration.getDefaultStorageTtlDays()));
node.init(ctxMock, configuration);
verify(ctxMock).addTenantProfileListener(any());
}
private TenantProfile getTenantProfile() {
var tenantProfile = new TenantProfile(TENANT_PROFILE_ID);
var tenantProfileData = new TenantProfileData();
var tenantProfileConfiguration = new DefaultTenantProfileConfiguration();
tenantProfileConfiguration.setDefaultStorageTtlDays(5);
tenantProfileData.setConfiguration(tenantProfileConfiguration);
tenantProfile.setProfileData(tenantProfileData);
return tenantProfile;
}
private static List<TsKvEntry> getTsKvEntriesListWithTs(String data, long ts) {
Map<Long, List<KvEntry>> tsKvMap = JsonConverter.convertToTelemetry(JsonParser.parseString(data), ts);
List<TsKvEntry> expectedList = new ArrayList<>();
@ -282,4 +332,309 @@ public class TbMsgTimeseriesNodeTest {
return expectedList;
}
@Test
public void givenOnEveryMessageProcessingSettingsAndSameMessageTwoTimes_whenOnMsg_thenPersistSameMessageTwoTimes() throws TbNodeException {
// GIVEN
config.setProcessingSettings(new TbMsgTimeseriesNodeConfiguration.ProcessingSettings.OnEveryMessage());
node.init(ctxMock, new TbNodeConfiguration(JacksonUtil.valueToTree(config)));
var msg = TbMsg.newMsg()
.type(TbMsgType.POST_TELEMETRY_REQUEST)
.originator(DEVICE_ID)
.data(JacksonUtil.newObjectNode().put("temperature", 22.3).toString())
.metaData(new TbMsgMetaData(Map.of("ts", "123")))
.build();
// WHEN-THEN
var expectedSaveRequest = TimeseriesSaveRequest.builder()
.tenantId(TENANT_ID)
.customerId(msg.getCustomerId())
.entityId(msg.getOriginator())
.entry(new BasicTsKvEntry(123L, new DoubleDataEntry("temperature", 22.3)))
.ttl(extractTtlAsSeconds(tenantProfile))
.strategy(TimeseriesSaveRequest.Strategy.SAVE_ALL)
.build();
node.onMsg(ctxMock, msg);
then(telemetryServiceMock).should(times(1)).saveTimeseries(assertArg(
actualSaveRequest -> assertThat(actualSaveRequest).usingRecursiveComparison().ignoringFields("callback").isEqualTo(expectedSaveRequest)
));
node.onMsg(ctxMock, msg);
then(telemetryServiceMock).should(times(2)).saveTimeseries(assertArg(
actualSaveRequest -> assertThat(actualSaveRequest).usingRecursiveComparison().ignoringFields("callback").isEqualTo(expectedSaveRequest)
));
}
@Test
public void givenDeduplicateProcessingSettingsAndSameMessageTwoTimes_whenOnMsg_thenPersistThisMessageOnlyFirstTime() throws TbNodeException {
// GIVEN
config.setProcessingSettings(new TbMsgTimeseriesNodeConfiguration.ProcessingSettings.Deduplicate(10));
node.init(ctxMock, new TbNodeConfiguration(JacksonUtil.valueToTree(config)));
var msg = TbMsg.newMsg()
.type(TbMsgType.POST_TELEMETRY_REQUEST)
.originator(DEVICE_ID)
.data(JacksonUtil.newObjectNode().put("temperature", 22.3).toString())
.metaData(new TbMsgMetaData(Map.of("ts", "123")))
.build();
// WHEN-THEN
var expectedSaveRequest = TimeseriesSaveRequest.builder()
.tenantId(TENANT_ID)
.customerId(msg.getCustomerId())
.entityId(msg.getOriginator())
.entry(new BasicTsKvEntry(123L, new DoubleDataEntry("temperature", 22.3)))
.ttl(extractTtlAsSeconds(tenantProfile))
.strategy(TimeseriesSaveRequest.Strategy.SAVE_ALL)
.build();
node.onMsg(ctxMock, msg);
then(telemetryServiceMock).should().saveTimeseries(assertArg(
actualSaveRequest -> assertThat(actualSaveRequest).usingRecursiveComparison().ignoringFields("callback").isEqualTo(expectedSaveRequest)
));
clearInvocations(telemetryServiceMock, ctxMock);
node.onMsg(ctxMock, msg);
then(telemetryServiceMock).should(never()).saveTimeseries(any());
}
@Test
public void givenWebSocketsOnlyProcessingSettingsAndSameMessageTwoTimes_whenOnMsg_thenSendsOnlyWsUpdateTwoTimes() throws TbNodeException {
// GIVEN
config.setProcessingSettings(new TbMsgTimeseriesNodeConfiguration.ProcessingSettings.WebSocketsOnly());
node.init(ctxMock, new TbNodeConfiguration(JacksonUtil.valueToTree(config)));
var msg = TbMsg.newMsg()
.type(TbMsgType.POST_TELEMETRY_REQUEST)
.originator(DEVICE_ID)
.data(JacksonUtil.newObjectNode().put("temperature", 22.3).toString())
.metaData(new TbMsgMetaData(Map.of("ts", "123")))
.build();
// WHEN-THEN
var expectedSaveRequest = TimeseriesSaveRequest.builder()
.tenantId(TENANT_ID)
.customerId(msg.getCustomerId())
.entityId(msg.getOriginator())
.entry(new BasicTsKvEntry(123L, new DoubleDataEntry("temperature", 22.3)))
.ttl(extractTtlAsSeconds(tenantProfile))
.strategy(TimeseriesSaveRequest.Strategy.WS_ONLY)
.build();
node.onMsg(ctxMock, msg);
then(telemetryServiceMock).should(times(1)).saveTimeseries(assertArg(
actualSaveRequest -> assertThat(actualSaveRequest).usingRecursiveComparison().ignoringFields("callback").isEqualTo(expectedSaveRequest)
));
node.onMsg(ctxMock, msg);
then(telemetryServiceMock).should(times(2)).saveTimeseries(assertArg(
actualSaveRequest -> assertThat(actualSaveRequest).usingRecursiveComparison().ignoringFields("callback").isEqualTo(expectedSaveRequest)
));
}
@Test
public void givenAdvancedProcessingSettingsWithOnEveryMessageStrategiesForAllActionsAndSameMessageTwoTimes_whenOnMsg_thenPersistSameMessageTwoTimes() throws TbNodeException {
// GIVEN
config.setProcessingSettings(new TbMsgTimeseriesNodeConfiguration.ProcessingSettings.Advanced(
ProcessingStrategy.onEveryMessage(),
ProcessingStrategy.onEveryMessage(),
ProcessingStrategy.onEveryMessage()
));
node.init(ctxMock, new TbNodeConfiguration(JacksonUtil.valueToTree(config)));
var msg = TbMsg.newMsg()
.type(TbMsgType.POST_TELEMETRY_REQUEST)
.originator(DEVICE_ID)
.data(JacksonUtil.newObjectNode().put("temperature", 22.3).toString())
.metaData(new TbMsgMetaData(Map.of("ts", "123")))
.build();
// WHEN-THEN
var expectedSaveRequest = TimeseriesSaveRequest.builder()
.tenantId(TENANT_ID)
.customerId(msg.getCustomerId())
.entityId(msg.getOriginator())
.entry(new BasicTsKvEntry(123L, new DoubleDataEntry("temperature", 22.3)))
.ttl(extractTtlAsSeconds(tenantProfile))
.strategy(TimeseriesSaveRequest.Strategy.SAVE_ALL)
.build();
node.onMsg(ctxMock, msg);
then(telemetryServiceMock).should(times(1)).saveTimeseries(assertArg(
actualSaveRequest -> assertThat(actualSaveRequest).usingRecursiveComparison().ignoringFields("callback").isEqualTo(expectedSaveRequest)
));
node.onMsg(ctxMock, msg);
then(telemetryServiceMock).should(times(2)).saveTimeseries(assertArg(
actualSaveRequest -> assertThat(actualSaveRequest).usingRecursiveComparison().ignoringFields("callback").isEqualTo(expectedSaveRequest)
));
}
@Test
public void givenAdvancedProcessingSettingsWithDifferentDeduplicateStrategyForEachAction_whenOnMsg_thenEvaluatesStrategiesForEachActionsIndependently() throws TbNodeException {
// GIVEN
config.setProcessingSettings(new TbMsgTimeseriesNodeConfiguration.ProcessingSettings.Advanced(
ProcessingStrategy.deduplicate(1),
ProcessingStrategy.deduplicate(2),
ProcessingStrategy.deduplicate(3)
));
node.init(ctxMock, new TbNodeConfiguration(JacksonUtil.valueToTree(config)));
long ts1 = 500L;
long ts2 = 1500L;
long ts3 = 2500L;
// WHEN-THEN
node.onMsg(ctxMock, TbMsg.newMsg()
.type(TbMsgType.POST_TELEMETRY_REQUEST)
.originator(DEVICE_ID)
.data(JacksonUtil.newObjectNode().put("temperature", 22.3).toString())
.metaData(new TbMsgMetaData(Map.of("ts", Long.toString(ts1))))
.build());
then(telemetryServiceMock).should().saveTimeseries(assertArg(
actualSaveRequest -> assertThat(actualSaveRequest.getStrategy()).isEqualTo(TimeseriesSaveRequest.Strategy.SAVE_ALL)
));
clearInvocations(telemetryServiceMock);
node.onMsg(ctxMock, TbMsg.newMsg()
.type(TbMsgType.POST_TELEMETRY_REQUEST)
.originator(DEVICE_ID)
.data(JacksonUtil.newObjectNode().put("temperature", 22.3).toString())
.metaData(new TbMsgMetaData(Map.of("ts", Long.toString(ts2))))
.build());
then(telemetryServiceMock).should().saveTimeseries(assertArg(
actualSaveRequest -> assertThat(actualSaveRequest.getStrategy()).isEqualTo(new TimeseriesSaveRequest.Strategy(true, false, false))
));
clearInvocations(telemetryServiceMock);
node.onMsg(ctxMock, TbMsg.newMsg()
.type(TbMsgType.POST_TELEMETRY_REQUEST)
.originator(DEVICE_ID)
.data(JacksonUtil.newObjectNode().put("temperature", 22.3).toString())
.metaData(new TbMsgMetaData(Map.of("ts", Long.toString(ts3))))
.build());
then(telemetryServiceMock).should().saveTimeseries(assertArg(
actualSaveRequest -> assertThat(actualSaveRequest.getStrategy()).isEqualTo(new TimeseriesSaveRequest.Strategy(true, true, false))
));
}
@Test
public void givenAdvancedProcessingSettingsWithSkipStrategiesForAllActionsAndSameMessageTwoTimes_whenOnMsg_thenSkipsSameMessageTwoTimes() throws TbNodeException {
// GIVEN
config.setProcessingSettings(new TbMsgTimeseriesNodeConfiguration.ProcessingSettings.Advanced(
ProcessingStrategy.skip(),
ProcessingStrategy.skip(),
ProcessingStrategy.skip()
));
node.init(ctxMock, new TbNodeConfiguration(JacksonUtil.valueToTree(config)));
var msg = TbMsg.newMsg()
.type(TbMsgType.POST_TELEMETRY_REQUEST)
.originator(DEVICE_ID)
.data(JacksonUtil.newObjectNode().put("temperature", 22.3).toString())
.metaData(new TbMsgMetaData(Map.of("ts", "123")))
.build();
// WHEN-THEN
node.onMsg(ctxMock, msg);
then(telemetryServiceMock).should(never()).saveTimeseries(any());
then(ctxMock).should(times(1)).tellSuccess(msg);
node.onMsg(ctxMock, msg);
then(telemetryServiceMock).should(never()).saveTimeseries(any());
then(ctxMock).should(times(2)).tellSuccess(msg);
}
private static long extractTtlAsSeconds(TenantProfile tenantProfile) {
return TimeUnit.DAYS.toSeconds(tenantProfile.getDefaultProfileConfiguration().getDefaultStorageTtlDays());
}
@Override
protected TbNode getTestNode() {
return node;
}
private static Stream<Arguments> givenFromVersionAndConfig_whenUpgrade_thenVerifyHasChangesAndConfig() {
return Stream.of(
Arguments.of(0, """
{
"defaultTTL": 0,
"useServerTs": false,
"skipLatestPersistence": false
}""",
true,
"""
{
"defaultTTL": 0,
"useServerTs": false,
"processingSettings": {
"type": "ON_EVERY_MESSAGE"
}
}"""),
Arguments.of(0, """
{
"defaultTTL": 0,
"useServerTs": false
}""",
true,
"""
{
"defaultTTL": 0,
"useServerTs": false,
"processingSettings": {
"type": "ON_EVERY_MESSAGE"
}
}"""),
Arguments.of(0, """
{
"defaultTTL": 0,
"useServerTs": false,
"skipLatestPersistence": null
}""",
true,
"""
{
"defaultTTL": 0,
"useServerTs": false,
"processingSettings": {
"type": "ON_EVERY_MESSAGE"
}
}"""),
Arguments.of(0, """
{
"defaultTTL": 0,
"useServerTs": false,
"skipLatestPersistence": true
}""",
true,
"""
{
"defaultTTL": 0,
"useServerTs": false,
"processingSettings": {
"type": "ADVANCED",
"timeseries": {
"type": "ON_EVERY_MESSAGE"
},
"latest": {
"type": "SKIP"
},
"webSockets": {
"type": "ON_EVERY_MESSAGE"
}
}
}""")
);
}
}

260
rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/telemetry/strategy/DeduplicateProcessingStrategyTest.java

@ -0,0 +1,260 @@
/**
* Copyright © 2016-2024 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.rule.engine.telemetry.strategy;
import com.github.benmanes.caffeine.cache.LoadingCache;
import com.github.benmanes.caffeine.cache.Policy;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.test.util.ReflectionTestUtils;
import java.time.Duration;
import java.util.Set;
import java.util.UUID;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
class DeduplicateProcessingStrategyTest {
final int deduplicationIntervalSecs = 10;
DeduplicateProcessingStrategy strategy;
@BeforeEach
void setup() {
strategy = new DeduplicateProcessingStrategy(deduplicationIntervalSecs);
}
@Test
void shouldThrowWhenDeduplicationIntervalIsLessThanOneSecond() {
assertThatThrownBy(() -> new DeduplicateProcessingStrategy(0))
.isInstanceOf(IllegalArgumentException.class)
.hasMessageContaining("Deduplication interval must be at least 1 second(s) and at most 86400 second(s), was 0 second(s)");
}
@Test
void shouldThrowWhenDeduplicationIntervalIsMoreThan24Hours() {
assertThatThrownBy(() -> new DeduplicateProcessingStrategy(86401))
.isInstanceOf(IllegalArgumentException.class)
.hasMessageContaining("Deduplication interval must be at least 1 second(s) and at most 86400 second(s), was 86401 second(s)");
}
@Test
void shouldUseAtLeastTenMinutesForExpireAfterAccess() {
// GIVEN
int deduplicationIntervalSecs = 1; // min deduplication interval duration
// WHEN
strategy = new DeduplicateProcessingStrategy(deduplicationIntervalSecs);
// THEN
var deduplicationCache = (LoadingCache<Long, Set<UUID>>) ReflectionTestUtils.getField(strategy, "deduplicationCache");
assertThat(deduplicationCache.policy().expireAfterAccess())
.isPresent()
.map(Policy.FixedExpiration::getExpiresAfter)
.hasValue(Duration.ofMinutes(10L));
}
@Test
void shouldCalculateExpireAfterAccessAsIntervalDurationMultipliedByTen() {
// GIVEN
int deduplicationIntervalSecs = (int) Duration.ofHours(1L).toSeconds(); // max deduplication interval duration
// WHEN
strategy = new DeduplicateProcessingStrategy(deduplicationIntervalSecs);
// THEN
var deduplicationCache = (LoadingCache<Long, Set<UUID>>) ReflectionTestUtils.getField(strategy, "deduplicationCache");
assertThat(deduplicationCache.policy().expireAfterAccess())
.isPresent()
.map(Policy.FixedExpiration::getExpiresAfter)
.hasValue(Duration.ofHours(10L));
}
@Test
void shouldUseAtMostTwoDaysForExpireAfterAccess() {
// GIVEN
int deduplicationIntervalSecs = (int) Duration.ofDays(1L).toSeconds(); // max deduplication interval duration
// WHEN
strategy = new DeduplicateProcessingStrategy(deduplicationIntervalSecs);
// THEN
var deduplicationCache = (LoadingCache<Long, Set<UUID>>) ReflectionTestUtils.getField(strategy, "deduplicationCache");
assertThat(deduplicationCache.policy().expireAfterAccess())
.isPresent()
.map(Policy.FixedExpiration::getExpiresAfter)
.hasValue(Duration.ofDays(2L));
}
@Test
void shouldNotAllowMoreThan100DeduplicationIntervals() {
// GIVEN
int deduplicationIntervalSecs = 1; // min deduplication interval duration
// WHEN
strategy = new DeduplicateProcessingStrategy(deduplicationIntervalSecs);
// THEN
var deduplicationCache = (LoadingCache<Long, Set<UUID>>) ReflectionTestUtils.getField(strategy, "deduplicationCache");
assertThat(deduplicationCache.policy().eviction())
.isPresent()
.map(Policy.Eviction::getMaximum)
.hasValue(100L);
}
@Test
void shouldCalculateMaxIntervalsAsTwoDaysDividedByIntervalDuration() {
// GIVEN
int deduplicationIntervalSecs = (int) Duration.ofHours(1L).toSeconds();
// WHEN
strategy = new DeduplicateProcessingStrategy(deduplicationIntervalSecs);
// THEN
var deduplicationCache = (LoadingCache<Long, Set<UUID>>) ReflectionTestUtils.getField(strategy, "deduplicationCache");
assertThat(deduplicationCache.policy().eviction())
.isPresent()
.map(Policy.Eviction::getMaximum)
.hasValue(48L);
}
@Test
void shouldKeepAtLeastTwoDeduplicationIntervals() {
// GIVEN
int deduplicationIntervalSecs = (int) Duration.ofDays(1L).toSeconds(); // max deduplication interval duration
// WHEN
strategy = new DeduplicateProcessingStrategy(deduplicationIntervalSecs);
// THEN
var deduplicationCache = (LoadingCache<Long, Set<UUID>>) ReflectionTestUtils.getField(strategy, "deduplicationCache");
assertThat(deduplicationCache.policy().eviction())
.isPresent()
.map(Policy.Eviction::getMaximum)
.hasValue(2L);
}
@Test
void shouldReturnTrueForFirstCallInInterval() {
long ts = 1_000_000L;
UUID originator = UUID.randomUUID();
assertThat(strategy.shouldProcess(ts, originator)).isTrue();
}
@Test
void shouldReturnFalseForSubsequentCallsInInterval() {
long baseTs = 1_000_000L;
UUID originator = UUID.randomUUID();
// Initial call should return true
assertThat(strategy.shouldProcess(baseTs, originator)).isTrue();
// Subsequent call within the same interval should return false for the same originator
long withinSameIntervalTs = baseTs + 1000L;
assertThat(strategy.shouldProcess(withinSameIntervalTs, originator)).isFalse();
}
@Test
void shouldHandleMultipleOriginatorsIndependently() {
long baseTs = 1_000_000L;
UUID originator1 = UUID.randomUUID();
UUID originator2 = UUID.randomUUID();
// First call for different originators in the same interval should return true independently
assertThat(strategy.shouldProcess(baseTs, originator1)).isTrue();
assertThat(strategy.shouldProcess(baseTs, originator2)).isTrue();
// Subsequent calls for the same originators within the same interval should return false
assertThat(strategy.shouldProcess(baseTs + 500L, originator1)).isFalse();
assertThat(strategy.shouldProcess(baseTs + 500L, originator2)).isFalse();
}
@Test
void shouldHandleEdgeCaseTimestamps() {
long minTs = Long.MIN_VALUE;
long maxTs = Long.MAX_VALUE;
UUID originator = UUID.randomUUID();
assertThat(strategy.shouldProcess(minTs, originator)).isTrue();
assertThat(strategy.shouldProcess(minTs + 1L, originator)).isFalse();
assertThat(strategy.shouldProcess(maxTs, originator)).isTrue();
assertThat(strategy.shouldProcess(maxTs - 1L, originator)).isFalse();
}
@Test
void shouldResetDeduplicationAtIntervalBoundaries() {
UUID originator = UUID.randomUUID();
// check 1st interval
long firstIntervalStart = 0L;
long firstIntervalEnd = firstIntervalStart + Duration.ofSeconds(deduplicationIntervalSecs).toMillis() - 1L;
long firstIntervalMiddle = calculateMiddle(firstIntervalStart, firstIntervalEnd);
assertThat(strategy.shouldProcess(firstIntervalStart, originator)).isTrue();
assertThat(strategy.shouldProcess(firstIntervalStart + 1, originator)).isFalse();
assertThat(strategy.shouldProcess(firstIntervalMiddle, originator)).isFalse();
assertThat(strategy.shouldProcess(firstIntervalEnd - 1, originator)).isFalse();
assertThat(strategy.shouldProcess(firstIntervalEnd, originator)).isFalse();
// check 2nd interval
long secondIntervalStart = firstIntervalEnd + 1L;
long secondIntervalEnd = secondIntervalStart + Duration.ofSeconds(deduplicationIntervalSecs).toMillis() - 1L;
long secondIntervalMiddle = calculateMiddle(secondIntervalStart, secondIntervalEnd);
assertThat(strategy.shouldProcess(secondIntervalStart, originator)).isTrue();
assertThat(strategy.shouldProcess(secondIntervalStart + 1, originator)).isFalse();
assertThat(strategy.shouldProcess(secondIntervalMiddle, originator)).isFalse();
assertThat(strategy.shouldProcess(secondIntervalEnd - 1, originator)).isFalse();
assertThat(strategy.shouldProcess(secondIntervalEnd, originator)).isFalse();
}
@Test
void shouldHandleMultipleOriginatorsOverMultipleIntervals() {
UUID originator1 = UUID.randomUUID();
UUID originator2 = UUID.randomUUID();
long baseTs = 0L;
// First interval for both originators
assertThat(strategy.shouldProcess(baseTs, originator1)).isTrue();
assertThat(strategy.shouldProcess(baseTs, originator2)).isTrue();
// Move to the next interval
long nextIntervalTs = baseTs + Duration.ofSeconds(10).toMillis();
// Each originator should be allowed again in the new interval
assertThat(strategy.shouldProcess(nextIntervalTs, originator1)).isTrue();
assertThat(strategy.shouldProcess(nextIntervalTs, originator2)).isTrue();
// Subsequent calls in the same new interval should return false
assertThat(strategy.shouldProcess(nextIntervalTs + 500L, originator1)).isFalse();
assertThat(strategy.shouldProcess(nextIntervalTs + 500L, originator2)).isFalse();
}
private static long calculateMiddle(long start, long end) {
return start + (end - start) / 2;
}
}

48
rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/telemetry/strategy/OnEveryMessageProcessingStrategyTest.java

@ -0,0 +1,48 @@
/**
* Copyright © 2016-2024 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.rule.engine.telemetry.strategy;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
import java.util.UUID;
import java.util.stream.Stream;
import static org.assertj.core.api.Assertions.assertThat;
class OnEveryMessageProcessingStrategyTest {
@ParameterizedTest
@MethodSource("edgeCaseProvider")
void shouldAlwaysReturnTrueForAnyInput(long timestamp, UUID originator) {
var onEveryMessage = OnEveryMessageProcessingStrategy.getInstance();
assertThat(onEveryMessage.shouldProcess(timestamp, originator)).isTrue();
}
private static Stream<Arguments> edgeCaseProvider() {
return Stream.of(
Arguments.of(Long.MIN_VALUE, new UUID(0L, 0L)),
Arguments.of(Long.MAX_VALUE, new UUID(Long.MAX_VALUE, Long.MAX_VALUE)),
Arguments.of(0L, new UUID(0L, 0L)),
Arguments.of(-1L, new UUID(-1L, -1L)),
Arguments.of(1L, new UUID(1L, 1L)),
Arguments.of(42L, UUID.randomUUID()),
Arguments.of(1000L, null)
);
}
}

55
rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/telemetry/strategy/ProcessingStrategyTest.java

@ -0,0 +1,55 @@
/**
* Copyright © 2016-2024 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.rule.engine.telemetry.strategy;
import org.junit.jupiter.api.Test;
import org.springframework.test.util.ReflectionTestUtils;
import java.time.Duration;
import static org.assertj.core.api.Assertions.assertThat;
class ProcessingStrategyTest {
@Test
void testOnEveryMessageReturnsCorrectInstance() {
ProcessingStrategy strategy = ProcessingStrategy.onEveryMessage();
assertThat(strategy)
.isNotNull()
.isInstanceOf(OnEveryMessageProcessingStrategy.class);
}
@Test
void testDeduplicateReturnsCorrectInstance() {
int validDeduplicationIntervalSecs = 5;
ProcessingStrategy strategy = ProcessingStrategy.deduplicate(validDeduplicationIntervalSecs);
assertThat(strategy)
.isNotNull()
.isInstanceOf(DeduplicateProcessingStrategy.class);
long actualDeduplicationIntervalMillis = (long) ReflectionTestUtils.getField(strategy, "deduplicationIntervalMillis");
assertThat(actualDeduplicationIntervalMillis).isEqualTo(Duration.ofSeconds(validDeduplicationIntervalSecs).toMillis());
}
@Test
void testSkipReturnsCorrectInstance() {
ProcessingStrategy strategy = ProcessingStrategy.skip();
assertThat(strategy)
.isNotNull()
.isInstanceOf(SkipProcessingStrategy.class);
}
}

48
rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/telemetry/strategy/SkipProcessingStrategyTest.java

@ -0,0 +1,48 @@
/**
* Copyright © 2016-2024 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.rule.engine.telemetry.strategy;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
import java.util.UUID;
import java.util.stream.Stream;
import static org.assertj.core.api.Assertions.assertThat;
class SkipProcessingStrategyTest {
@ParameterizedTest
@MethodSource("edgeCaseProvider")
void shouldAlwaysReturnFalseForAnyInput(long timestamp, UUID originator) {
var skipStrategy = SkipProcessingStrategy.getInstance();
assertThat(skipStrategy.shouldProcess(timestamp, originator)).isFalse();
}
private static Stream<Arguments> edgeCaseProvider() {
return Stream.of(
Arguments.of(Long.MIN_VALUE, new UUID(0L, 0L)),
Arguments.of(Long.MAX_VALUE, new UUID(Long.MAX_VALUE, Long.MAX_VALUE)),
Arguments.of(0L, new UUID(0L, 0L)),
Arguments.of(-1L, new UUID(-1L, -1L)),
Arguments.of(1L, new UUID(1L, 1L)),
Arguments.of(42L, UUID.randomUUID()),
Arguments.of(1000L, null)
);
}
}

4
ui-ngx/src/app/core/api/entity-data-subscription.ts

@ -685,7 +685,7 @@ export class EntityDataSubscription {
if (this.tsFields.length > 0) {
if (this.history) {
cmd.historyCmd = {
keys: this.tsFields.map(key => key.key),
keys: [... new Set(this.tsFields.map(key => key.key))],
startTs: this.subsTw.fixedWindow.startTimeMs,
endTs: this.subsTw.fixedWindow.endTimeMs,
interval: 0,
@ -702,7 +702,7 @@ export class EntityDataSubscription {
}
} else {
cmd.tsCmd = {
keys: this.tsFields.map(key => key.key),
keys: [... new Set(this.tsFields.map(key => key.key))],
startTs: this.subsTw.startTs,
timeWindow: this.subsTw.aggregation.timeWindow,
interval: 0,

3
ui-ngx/src/app/core/http/rule-chain.service.ts

@ -33,6 +33,7 @@ import {
LinkLabel,
RuleNodeComponentDescriptor,
RuleNodeConfiguration,
RuleNodeConfigurationComponent,
ScriptLanguage,
TestScriptInputParams,
TestScriptResult
@ -181,7 +182,7 @@ export class RuleChainService {
}
public registerSystemRuleNodeConfigModule(module: any) {
Object.assign(this.ruleNodeConfigComponents, this.resourcesService.extractComponentsFromModule<IRuleNodeConfigurationComponent>(module, true));
Object.assign(this.ruleNodeConfigComponents, this.resourcesService.extractComponentsFromModule<IRuleNodeConfigurationComponent>(module, RuleNodeConfigurationComponent, true));
}
private loadRuleNodeComponents(ruleChainType: RuleChainType, config?: RequestConfig): Observable<Array<RuleNodeComponentDescriptor>> {

42
ui-ngx/src/app/core/http/widget.service.ts

@ -14,7 +14,7 @@
/// limitations under the License.
///
import { Injectable } from '@angular/core';
import { Injectable, Type } from '@angular/core';
import { defaultHttpOptionsFromConfig, RequestConfig } from './http-utils';
import { Observable, of, ReplaySubject } from 'rxjs';
import { HttpClient } from '@angular/common/http';
@ -24,7 +24,10 @@ import { WidgetsBundle } from '@shared/models/widgets-bundle.model';
import {
BaseWidgetType,
DeprecatedFilter,
fullWidgetTypeFqn, migrateWidgetTypeToDynamicForms,
fullWidgetTypeFqn,
IWidgetSettingsComponent,
migrateWidgetTypeToDynamicForms,
WidgetSettingsComponent,
WidgetType,
widgetType,
WidgetTypeDetails,
@ -36,6 +39,11 @@ import { filter, map, mergeMap, tap } from 'rxjs/operators';
import { WidgetTypeId } from '@shared/models/id/widget-type-id';
import { NULL_UUID } from '@shared/models/id/has-uuid';
import { ActivationEnd, Router } from '@angular/router';
import {
BasicWidgetConfigComponent,
IBasicWidgetConfigComponent
} from '@home/components/widget/config/widget-config.component.models';
import { ResourcesService } from '@core/services/resources.service';
@Injectable({
providedIn: 'root'
@ -50,9 +58,13 @@ export class WidgetService {
private loadWidgetsBundleCacheSubject: ReplaySubject<void>;
private basicWidgetSettingsComponentsMap: { [key: string]: Type<IBasicWidgetConfigComponent> } = {};
private widgetSettingsComponentsMap: { [key: string]: Type<IWidgetSettingsComponent> } = {};
constructor(
private http: HttpClient,
private router: Router
private router: Router,
private resourcesService: ResourcesService,
) {
this.router.events.pipe(filter(event => event instanceof ActivationEnd)).subscribe(
() => {
@ -287,6 +299,30 @@ export class WidgetService {
this.widgetsInfoInMemoryCache.set(widgetInfo.fullFqn, widgetInfo);
}
public registerBasicWidgetConfigComponents(module: any) {
Object.assign(this.basicWidgetSettingsComponentsMap, this.resourcesService.extractComponentsFromModule<IBasicWidgetConfigComponent>(module, BasicWidgetConfigComponent));
}
public getBasicWidgetSettingsComponentBySelector(selector: string): Type<IBasicWidgetConfigComponent> {
return this.basicWidgetSettingsComponentsMap[selector];
}
public putBasicWidgetSettingsComponentToMap(selector: string, compType: Type<IBasicWidgetConfigComponent>) {
this.basicWidgetSettingsComponentsMap[selector] = compType;
}
public registerWidgetSettingsComponents(module: any) {
Object.assign(this.widgetSettingsComponentsMap, this.resourcesService.extractComponentsFromModule<IWidgetSettingsComponent>(module, WidgetSettingsComponent));
}
public getWidgetSettingsComponentTypeBySelector(selector: string): Type<IWidgetSettingsComponent> {
return this.widgetSettingsComponentsMap[selector];
}
public putWidgetSettingsComponentToMap(selector: string, compType: Type<IWidgetSettingsComponent>) {
this.widgetSettingsComponentsMap[selector] = compType;
}
private widgetTypeUpdated(updatedWidgetType: BaseWidgetType): void {
this.deleteWidgetInfoFromCache(fullWidgetTypeFqn(updatedWidgetType));
}

5
ui-ngx/src/app/core/services/resources.service.ts

@ -265,12 +265,15 @@ export class ResourcesService {
);
}
public extractComponentsFromModule<T>(module: any, isCamelCaseSelector = false): ComponentsSelectorMap<T> {
public extractComponentsFromModule<T>(module: any, instanceFilter?: any, isCamelCaseSelector = false): ComponentsSelectorMap<T> {
const modulesWithComponents = this.extractModulesWithComponents(module);
const componentMap: ComponentsSelectorMap<T> = {};
const processComponents = (components: Array<ɵComponentDef<T>>) => {
components.forEach(item => {
if (instanceFilter && !(item.type.prototype instanceof instanceFilter)) {
return;
}
let selector = extractSelectorFromComponent(item);
if (isCamelCaseSelector) {
selector = camelCase(selector);

2
ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-object-list.component.ts

@ -190,7 +190,7 @@ export class Lwm2mObjectListComponent implements ControlValueAccessor, OnInit, V
private fetchListObjects = (searchText: string): Observable<Array<ObjectLwM2M>> => {
this.searchText = searchText;
const pageLink = new PageLink(PAGE_SIZE_LIMIT, 0, this.searchText, {
property: 'id',
property: 'resourceKey',
direction: Direction.ASC
});
return this.deviceProfileService.getLwm2mObjectsPage(pageLink);

10
ui-ngx/src/app/modules/home/components/rule-node/action/action-rule-node-config.module.ts

@ -42,6 +42,12 @@ import { DeleteAttributesConfigComponent } from './delete-attributes-config.comp
import { MathFunctionConfigComponent } from './math-function-config.component';
import { DeviceStateConfigComponent } from './device-state-config.component';
import { SendRestApiCallReplyConfigComponent } from './send-rest-api-call-reply-config.component';
import {
AdvancedPersistenceSettingComponent
} from '@home/components/rule-node/action/advanced-persistence-setting.component';
import {
AdvancedPersistenceSettingRowComponent
} from '@home/components/rule-node/action/advanced-persistence-setting-row.component';
@NgModule({
declarations: [
@ -67,7 +73,9 @@ import { SendRestApiCallReplyConfigComponent } from './send-rest-api-call-reply-
PushToEdgeConfigComponent,
PushToCloudConfigComponent,
MathFunctionConfigComponent,
DeviceStateConfigComponent
DeviceStateConfigComponent,
AdvancedPersistenceSettingComponent,
AdvancedPersistenceSettingRowComponent,
],
imports: [
CommonModule,

40
ui-ngx/src/app/modules/home/components/rule-node/action/advanced-persistence-setting-row.component.html

@ -0,0 +1,40 @@
<!--
Copyright © 2016-2024 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.
-->
<section [formGroup]="persistenceSettingRowForm" class="tb-form-panel stroked no-gap no-padding-bottom">
<div class="tb-form-panel-title mb-4">{{ title }}</div>
<mat-form-field>
<mat-label translate>rule-node-config.save-time-series.strategy</mat-label>
<mat-select formControlName="type">
@for (strategy of persistenceStrategies; track strategy) {
<mat-option [value]="strategy">{{ PersistenceTypeTranslationMap.get(strategy) | translate }}</mat-option>
}
</mat-select>
</mat-form-field>
@if(persistenceSettingRowForm.get('type').value === PersistenceType.DEDUPLICATE) {
<tb-time-unit-input
required
labelText="{{ 'rule-node-config.save-time-series.deduplication-interval' | translate }}"
requiredText="{{ 'rule-node-config.save-time-series.deduplication-interval-required' | translate }}"
minErrorText="{{ 'rule-node-config.save-time-series.deduplication-interval-min-max-range' | translate }}"
maxErrorText="{{ 'rule-node-config.save-time-series.deduplication-interval-min-max-range' | translate }}"
[minTime]="1"
[maxTime]="maxDeduplicateTime"
formControlName="deduplicationIntervalSecs">
</tb-time-unit-input>
}
</section>

114
ui-ngx/src/app/modules/home/components/rule-node/action/advanced-persistence-setting-row.component.ts

@ -0,0 +1,114 @@
///
/// Copyright © 2016-2024 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.
///
import { Component, forwardRef, Input } from '@angular/core';
import {
ControlValueAccessor,
FormBuilder,
NG_VALIDATORS,
NG_VALUE_ACCESSOR,
ValidationErrors,
Validator
} from '@angular/forms';
import {
AdvancedProcessingConfig,
defaultAdvancedProcessingConfig,
maxDeduplicateTimeSecs,
ProcessingType,
ProcessingTypeTranslationMap
} from '@home/components/rule-node/action/timeseries-config.models';
import { isDefinedAndNotNull } from '@core/utils';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
@Component({
selector: 'tb-advanced-persistence-setting-row',
templateUrl: './advanced-persistence-setting-row.component.html',
providers: [{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => AdvancedPersistenceSettingRowComponent),
multi: true
},{
provide: NG_VALIDATORS,
useExisting: forwardRef(() => AdvancedPersistenceSettingRowComponent),
multi: true
}]
})
export class AdvancedPersistenceSettingRowComponent implements ControlValueAccessor, Validator {
@Input()
title: string;
persistenceSettingRowForm = this.fb.group({
type: [defaultAdvancedProcessingConfig.type],
deduplicationIntervalSecs: [{value: 60, disabled: true}]
});
PersistenceType = ProcessingType;
persistenceStrategies = [ProcessingType.ON_EVERY_MESSAGE, ProcessingType.DEDUPLICATE, ProcessingType.SKIP];
PersistenceTypeTranslationMap = ProcessingTypeTranslationMap;
maxDeduplicateTime = maxDeduplicateTimeSecs;
private propagateChange: (value: any) => void = () => {};
constructor(private fb: FormBuilder) {
this.persistenceSettingRowForm.get('type').valueChanges.pipe(
takeUntilDestroyed()
).subscribe(() => this.updatedValidation());
this.persistenceSettingRowForm.valueChanges.pipe(
takeUntilDestroyed()
).subscribe((value) => this.propagateChange(value));
}
registerOnChange(fn: any) {
this.propagateChange = fn;
}
registerOnTouched(_fn: any) {
}
setDisabledState(isDisabled: boolean) {
if (isDisabled) {
this.persistenceSettingRowForm.disable({emitEvent: false});
} else {
this.persistenceSettingRowForm.enable({emitEvent: false});
this.updatedValidation();
}
}
validate(): ValidationErrors | null {
return this.persistenceSettingRowForm.valid ? null : {
persistenceSettingRow: false
};
}
writeValue(value: AdvancedProcessingConfig) {
if (isDefinedAndNotNull(value)) {
this.persistenceSettingRowForm.patchValue(value, {emitEvent: false});
} else {
this.persistenceSettingRowForm.patchValue(defaultAdvancedProcessingConfig);
}
}
private updatedValidation() {
if (this.persistenceSettingRowForm.get('type').value === ProcessingType.DEDUPLICATE) {
this.persistenceSettingRowForm.get('deduplicationIntervalSecs').enable({emitEvent: false});
} else {
this.persistenceSettingRowForm.get('deduplicationIntervalSecs').disable({emitEvent: false})
}
}
}

Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save