Browse Source

Save time series strategies: merge with master

pull/12413/head
Dmytro Skarzhynets 2 years ago
parent
commit
f40c1d389e
  1. 346
      application/src/main/data/json/system/scada_symbols/crane-hp.svg
  2. 355
      application/src/main/data/json/system/scada_symbols/drawwork-hp.svg
  3. 354
      application/src/main/data/json/system/scada_symbols/drill-hp.svg
  4. 361
      application/src/main/data/json/system/scada_symbols/drilling-line-hp.svg
  5. 354
      application/src/main/data/json/system/scada_symbols/drilling-rig-hp.svg
  6. 293
      application/src/main/data/json/system/scada_symbols/hook-hp.svg
  7. 743
      application/src/main/data/json/system/scada_symbols/meter.svg
  8. 267
      application/src/main/data/json/system/scada_symbols/platform-hp.svg
  9. 343
      application/src/main/data/json/system/scada_symbols/preventer-hp.svg
  10. 346
      application/src/main/data/json/system/scada_symbols/rotor-hp.svg
  11. 717
      application/src/main/data/json/system/scada_symbols/small-left-meter.svg
  12. 688
      application/src/main/data/json/system/scada_symbols/small-meter.svg
  13. 717
      application/src/main/data/json/system/scada_symbols/small-right-center.svg
  14. 4
      application/src/main/data/json/system/widget_bundles/general_high_performance_scada_symbols.json
  15. 20
      application/src/main/data/json/system/widget_bundles/high_performance_scada_oil_gas.json
  16. 4
      application/src/main/data/json/system/widget_bundles/scada_fluid_system.json
  17. 10
      application/src/main/java/org/thingsboard/server/service/ttl/AlarmsCleanUpService.java
  18. 31
      application/src/test/java/org/thingsboard/server/controller/AbstractWebTest.java
  19. 2
      application/src/test/java/org/thingsboard/server/edge/DeviceProfileEdgeTest.java
  20. 15
      application/src/test/java/org/thingsboard/server/edge/imitator/EdgeImitator.java
  21. 5
      application/src/test/java/org/thingsboard/server/service/script/AbstractTbelInvokeTest.java
  22. 26
      application/src/test/java/org/thingsboard/server/service/script/TbelInvokeDocsIoTest.java
  23. 19
      application/src/test/java/org/thingsboard/server/service/script/TbelInvokeServiceTest.java
  24. 17
      application/src/test/java/org/thingsboard/server/service/ttl/AlarmsCleanUpServiceTest.java
  25. 8
      application/src/test/java/org/thingsboard/server/transport/coap/AbstractCoapIntegrationTest.java
  26. 2
      application/src/test/java/org/thingsboard/server/transport/coap/client/CoapClientIntegrationTest.java
  27. 291
      application/src/test/java/org/thingsboard/server/transport/coap/security/AbstractCoapSecurityIntegrationTest.java
  28. 44
      application/src/test/java/org/thingsboard/server/transport/coap/security/sql/CoapClientX509SecurityJksIntegrationTest.java
  29. 44
      application/src/test/java/org/thingsboard/server/transport/coap/security/sql/CoapClientX509SecurityPemIntegrationTest.java
  30. 3
      application/src/test/java/org/thingsboard/server/transport/coap/telemetry/attributes/CoapAttributesIntegrationTest.java
  31. 3
      application/src/test/java/org/thingsboard/server/transport/coap/telemetry/timeseries/AbstractCoapTimeseriesIntegrationTest.java
  32. 82
      application/src/test/java/org/thingsboard/server/transport/coap/x509/CertPrivateKey.java
  33. 239
      application/src/test/java/org/thingsboard/server/transport/coap/x509/CoapClientX509Test.java
  34. 129
      application/src/test/java/org/thingsboard/server/transport/coap/x509/TbAdvancedCertificateVerifier.java
  35. 38
      application/src/test/java/org/thingsboard/server/transport/lwm2m/AbstractLwM2MIntegrationTest.java
  36. 6
      application/src/test/java/org/thingsboard/server/transport/lwm2m/client/LwM2MTestClient.java
  37. 1
      application/src/test/java/org/thingsboard/server/transport/lwm2m/client/SimpleLwM2MDevice.java
  38. 2
      application/src/test/java/org/thingsboard/server/transport/lwm2m/ota/sql/Ota5LwM2MIntegrationTest.java
  39. 3
      application/src/test/java/org/thingsboard/server/transport/lwm2m/security/AbstractSecurityLwM2MIntegrationTest.java
  40. 81
      application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/PskLwm2mIntegrationTest.java
  41. 13
      application/src/test/resources/coap/credentials/client/cert.pem
  42. 14
      application/src/test/resources/coap/credentials/client/cert_01.pem
  43. 4
      application/src/test/resources/coap/credentials/client/key.pem
  44. 8
      application/src/test/resources/coap/credentials/client/key_01.pem
  45. BIN
      application/src/test/resources/coap/credentials/coapclientTest.jks
  46. BIN
      application/src/test/resources/coap/credentials/coapserverTest.jks
  47. 35
      application/src/test/resources/coap/credentials/server/cert.pem
  48. 3
      common/coap-server/src/main/java/org/thingsboard/server/coapserver/CoapServerService.java
  49. 2
      common/coap-server/src/main/java/org/thingsboard/server/coapserver/DefaultCoapServerService.java
  50. 5
      common/coap-server/src/main/java/org/thingsboard/server/coapserver/TbCoapDtlsCertificateVerifier.java
  51. 9
      common/coap-server/src/main/java/org/thingsboard/server/coapserver/TbCoapDtlsSessionInMemoryStorage.java
  52. 32
      common/coap-server/src/main/java/org/thingsboard/server/coapserver/TbCoapDtlsSessionKey.java
  53. 4
      common/data/src/main/java/org/thingsboard/server/common/data/mobile/app/StoreInfo.java
  54. 2
      common/edge-api/src/main/java/org/thingsboard/edge/rpc/EdgeGrpcClient.java
  55. 1
      common/edge-api/src/main/proto/edge.proto
  56. 96
      common/script/script-api/src/main/java/org/thingsboard/script/api/tbel/TbUtils.java
  57. 36
      common/script/script-api/src/test/java/org/thingsboard/script/api/tbel/TbUtilsTest.java
  58. 44
      common/transport/coap/src/main/java/org/thingsboard/server/transport/coap/CoapTransportResource.java
  59. 14
      common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/store/util/LwM2MClientSerDes.java
  60. 2
      common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/uplink/DefaultLwM2mUplinkMsgHandler.java
  61. 29
      common/transport/lwm2m/src/test/java/org/thingsboard/server/transport/lwm2m/server/store/util/LwM2MClientSerDesTest.java
  62. 10
      common/version-control/src/main/java/org/thingsboard/server/service/sync/vc/GitRepository.java
  63. 2
      dao/src/main/java/org/thingsboard/server/dao/mobile/QrCodeSettingServiceImpl.java
  64. 4
      dao/src/main/java/org/thingsboard/server/dao/model/ModelConstants.java
  65. 6
      dao/src/main/java/org/thingsboard/server/dao/model/sql/MobileAppEntity.java
  66. 16
      dao/src/main/java/org/thingsboard/server/dao/service/validator/MobileAppDataValidator.java
  67. 3
      packaging/java/scripts/control/template.service
  68. 1
      rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbAssignToCustomerNode.java
  69. 1
      rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbClearAlarmNode.java
  70. 1
      rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbCopyAttributesToEntityViewNode.java
  71. 1
      rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbCreateAlarmNode.java
  72. 1
      rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbCreateRelationNode.java
  73. 1
      rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbDeleteRelationNode.java
  74. 1
      rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbDeviceStateNode.java
  75. 1
      rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbLogNode.java
  76. 1
      rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbMsgCountNode.java
  77. 1
      rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbSaveToCustomCassandraTableNode.java
  78. 1
      rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbUnassignFromCustomerNode.java
  79. 1
      rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/aws/lambda/TbAwsLambdaNode.java
  80. 1
      rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/aws/sns/TbSnsNode.java
  81. 1
      rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/aws/sqs/TbSqsNode.java
  82. 1
      rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/debug/TbMsgGeneratorNode.java
  83. 3
      rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/deduplication/TbMsgDeduplicationNode.java
  84. 1
      rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/delay/TbMsgDelayNode.java
  85. 1
      rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/edge/TbMsgPushToCloudNode.java
  86. 1
      rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/edge/TbMsgPushToEdgeNode.java
  87. 1
      rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbAssetTypeSwitchNode.java
  88. 1
      rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbCheckAlarmStatusNode.java
  89. 1
      rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbCheckMessageNode.java
  90. 1
      rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbCheckRelationNode.java
  91. 1
      rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbDeviceTypeSwitchNode.java
  92. 1
      rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbJsFilterNode.java
  93. 1
      rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbJsSwitchNode.java
  94. 1
      rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbMsgTypeFilterNode.java
  95. 1
      rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbMsgTypeSwitchNode.java
  96. 1
      rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbOriginatorTypeFilterNode.java
  97. 1
      rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbOriginatorTypeSwitchNode.java
  98. 1
      rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/flow/TbAckNode.java
  99. 1
      rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/flow/TbCheckpointNode.java
  100. 1
      rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/flow/TbRuleChainInputNode.java

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

@ -0,0 +1,346 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:tb="https://thingsboard.io/svg" width="1e3" height="1200" fill="none" version="1.1" viewBox="0 0 1e3 1200"><tb:metadata xmlns=""><![CDATA[{
"title": "HP Crane",
"description": "Crane with various states.",
"searchTags": [
"crane"
],
"widgetSizeX": 5,
"widgetSizeY": 6,
"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="m999 1101h-518v98h518z"/>
<path d="m89 301h-88v38h88z"/>
<path d="m38.637 353.25c1.8257-2.795 3.0211-5.169 3.5801-7.616 0.4834-2.115 0.4778-4.225 0.0646-6.636h22.765c0.4236 2.76 0.5531 8.434-2.4543 17.437-1.0074 3.015-3.2478 5.918-6.1765 8.829-2.4452 2.43-5.2981 4.799-8.1981 7.207-0.57 0.473-1.1418 0.948-1.7126 1.425-3.4492 2.882-6.8589 5.843-9.4634 8.969s-4.4841 6.511-4.7352 10.25c-0.4781 7.123 1.5349 12.183 4.5904 15.755 3.0323 3.545 7.0211 5.546 10.381 6.711 2.6292 0.911 7.97 1.542 12.913-0.172 2.4934-0.865 4.9095-2.335 6.8093-4.687 1.9017-2.355 3.2394-5.537 3.6645-9.748 0.2685-2.66 0.4677-4.993 0.639-7.001 0.0914-1.07 0.1749-2.048 0.2566-2.933 0.2394-2.589 0.4634-4.351 0.8094-5.493 0.345-1.138 0.6919-1.294 0.9494-1.334 0.2122-0.033 0.5457-0.012 1.0684 0.146 0.5169 0.156 1.1513 0.424 1.9388 0.814 8.6238 4.272 11.837 11.217 12.524 18.027 0.6932 6.867-1.1952 13.571-2.7777 17.098-6.6047 14.722-20.145 23.7-37.326 23.7-10.333 0-18.218-1.819-24.553-5.103-6.3316-3.283-11.186-8.065-15.404-14.105-3.3703-4.826-6.7534-12.808-7.5927-21.713-0.83751-8.887 0.86149-18.628 7.5566-27.085 6.2949-7.951 12.501-11.818 17.718-14.561 0.9365-0.492 1.8598-0.957 2.7531-1.407 1.5646-0.788 3.0372-1.53 4.3284-2.291 2.0627-1.216 3.8384-2.576 5.0837-4.483z"/>
</g><path d="m559.64 1101-515.24-1098.3 341.87 221.97 538.94 876.28z" stroke="#1a1a1a" stroke-width="2"/><path d="m148 225h237" stroke="#1a1a1a" stroke-width="2"/><path d="m249 438h269" stroke="#1a1a1a" stroke-width="2"/><path d="m362 680h304" stroke="#1a1a1a" stroke-width="2"/><path d="m491 955h344" stroke="#1a1a1a" stroke-width="2"/><path d="m249 437.92 136.32-212.92" stroke="#1a1a1a" stroke-width="2"/><path d="m362 680.92 155.32-242.92" stroke="#1a1a1a" stroke-width="1.9997"/><path d="m492 954.92 175.31-274.92" stroke="#1a1a1a" stroke-width="2.0018"/><path d="m44 2v299" stroke="#1a1a1a" stroke-width="2"/><path d="m336.32 0s-336.32 0-336.32 201v985.08c0 7.9536 8.9545 13.921 20 13.921h960c11.045 0 20-5.9676 20-13.921v-985.08c0-201-330.35-201-330.35-201h-169.65zm335.35 243.6c-6.4435 0-11.667 3.7608-11.667 8.4v901.2c0 4.6392 5.2235 8.4 11.667 8.4h73.33c6.4435 0 11.667-3.7608 11.667-8.4v-901.2c0-4.6392-5.2235-8.4-11.667-8.4z" 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="m38.422 7.1554c1.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="m38.422 7.1554c1.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="m40.211 8.0498c0.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="m44.559 37.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>
</svg>

After

Width:  |  Height:  |  Size: 14 KiB

355
application/src/main/data/json/system/scada_symbols/drawwork-hp.svg

@ -0,0 +1,355 @@
<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 Drawwork",
"description": "Drawwork with various states.",
"searchTags": [
"drawwork"
],
"widgetSizeX": 3,
"widgetSizeY": 2,
"tags": [
{
"tag": "circle-background",
"stateRenderFunction": "var color = ctx.properties.stoppedColor;\nif (ctx.values.running) {\n color = '#dedede';\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": "drawwork-background",
"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": "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" tb:tag="drawwork-background">
<path d="m65.049 374 49.936-64h143.35l49.622 64z" stroke-width="2"/>
<rect x="24.777" y="374" width="324" height="24.999" rx="3.6512" stroke-width="2.0011"/>
<rect x="188" y="1" width="333" height="252" stroke-width="2"/>
<rect x="521" y="1" width="78" height="398" stroke-width="2"/>
<circle cx="187" cy="187" r="186" stroke-width="2"/>
</g><mask id="path-6-inside-1_4465_2848" fill="#ffffff">
<path d="m308.33 187c0 66.274-53.726 120-120 120s-120-53.726-120-120 53.726-120 120-120 120 53.726 120 120zm-221.31 0c0 55.95 45.357 101.31 101.31 101.31s101.31-45.357 101.31-101.31-45.357-101.31-101.31-101.31-101.31 45.357-101.31 101.31z"/>
</mask><path d="m308.33 187c0 66.274-53.726 120-120 120s-120-53.726-120-120 53.726-120 120-120 120 53.726 120 120zm-221.31 0c0 55.95 45.357 101.31 101.31 101.31s101.31-45.357 101.31-101.31-45.357-101.31-101.31-101.31-101.31 45.357-101.31 101.31z" fill="#dedede" mask="url(#path-6-inside-1_4465_2848)" stroke="#1a1a1a" stroke-width="4" tb:tag="circle-background"/><line x1="421.5" x2="421.5" y1="4.3711e-8" y2="254" stroke="#1a1a1a" stroke-width="2"/><line x1="442" x2="442" y1="4.3711e-8" y2="254" stroke="#1a1a1a" stroke-width="2"/><line x1="462" x2="462" y1="4.3711e-8" y2="254" stroke="#1a1a1a" stroke-width="2"/><line x1="482" x2="482" y1="4.3711e-8" y2="254" stroke="#1a1a1a" stroke-width="2"/><line x1="502" x2="502" y1="4.3711e-8" y2="254" stroke="#1a1a1a" stroke-width="2"/><path d="m201.79 0s-201.79 0-201.79 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" 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="m38.422 7.1554c1.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="m38.422 7.1554c1.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="m40.211 8.0498c0.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="m44.559 37.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>
</svg>

After

Width:  |  Height:  |  Size: 14 KiB

354
application/src/main/data/json/system/scada_symbols/drill-hp.svg

@ -0,0 +1,354 @@
<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 Drill",
"description": "Drill with various states.",
"searchTags": [
"drill",
"drilling"
],
"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>
<mask id="path-5-inside-1_4566_53869" fill="#ffffff">
<path d="m160 113.52v50.507h-20.5l-10.711-48.771c-13.492 6.47-22.789 20.101-22.789 35.871 0 22.024 18.132 39.877 40.5 39.877s40.5-17.853 40.5-39.877c0-17.362-11.27-32.133-27-37.607z" clip-rule="evenodd" fill-rule="evenodd"/>
</mask><mask id="path-7-inside-2_4566_53869" fill="#ffffff">
<path d="m40 113.52v50.507h20.5l10.711-48.771c13.492 6.47 22.789 20.101 22.789 35.871 0 22.024-18.132 39.877-40.5 39.877s-40.5-17.853-40.5-39.877c0-17.362 11.27-32.133 27-37.607z" clip-rule="evenodd" fill-rule="evenodd"/>
</mask><g fill="#fff" tb:tag="background">
<path d="m62.143 81 10.732-80h54.25l10.732 80z" stroke="#1a1a1a" stroke-width="2"/>
<path d="m70 81h60v103.02c-0.122 0.098-0.274 0.218-0.453 0.358-0.534 0.419-1.312 1.019-2.284 1.739-1.945 1.442-4.662 3.363-7.751 5.283-3.092 1.921-6.539 3.829-9.947 5.255-3.421 1.431-6.73 2.344-9.565 2.344-2.8349 0-6.1436-0.913-9.5652-2.344-3.4077-1.426-6.8551-3.334-9.9469-5.255-3.0891-1.92-5.806-3.841-7.7511-5.283-0.9721-0.72-1.7501-1.32-2.2841-1.739-0.179-0.14-0.3305-0.26-0.4527-0.358z" stroke="#1a1a1a" stroke-width="2"/>
<path d="m120.9 81.054c4e-3 -0.0183 8e-3 -0.0363 0.012-0.054h24.671l15.413 23.301v60.699h-22.222c-0.093-0.212-0.209-0.478-0.346-0.794-0.389-0.898-0.951-2.199-1.637-3.812-1.373-3.226-3.245-7.696-5.241-12.672-4.001-9.972-8.476-21.912-10.459-29.961-2.355-9.559-2.358-18.942-1.767-25.951 0.296-3.5009 0.739-6.4002 1.108-8.4209 0.184-1.0102 0.35-1.8002 0.468-2.3352z" stroke="#1a1a1a" stroke-width="2"/>
<path d="m79.096 81.054c-0.0041-0.0183-0.0081-0.0363-0.012-0.054h-24.67l-15.413 23.301v60.699h22.222c0.0926-0.212 0.2084-0.478 0.3456-0.794 0.3896-0.898 0.951-2.199 1.6373-3.812 1.3728-3.226 3.2446-7.696 5.2411-12.672 4.0007-9.972 8.4754-21.912 10.459-29.961 2.3552-9.559 2.3585-18.942 1.7667-25.951-0.2956-3.5009-0.7389-6.4002-1.1075-8.4209-0.1842-1.0102-0.3497-1.8002-0.4685-2.3352z" stroke="#1a1a1a" stroke-width="2"/>
<path d="m160 113.52v50.507h-20.5l-10.711-48.771c-13.492 6.47-22.789 20.101-22.789 35.871 0 22.024 18.132 39.877 40.5 39.877s40.5-17.853 40.5-39.877c0-17.362-11.27-32.133-27-37.607z" clip-rule="evenodd" fill-rule="evenodd"/>
<path d="m40 113.52v50.507h20.5l10.711-48.771c13.492 6.47 22.789 20.101 22.789 35.871 0 22.024-18.132 39.877-40.5 39.877s-40.5-17.853-40.5-39.877c0-17.362 11.27-32.133 27-37.607z" clip-rule="evenodd" fill-rule="evenodd"/>
</g><path d="m139.62 111.98 0.876 52.023-2 0.033-0.876-52.022zm20.376 1.533h-2v-2.814l2.657 0.925zm0 50.507h2v2h-2zm-20.5 0v2h-1.608l-0.345-1.571zm-10.711-48.771-0.865-1.804 2.277-1.091 0.541 2.466zm33.211-1.736v50.507h-4v-50.507zm-2 52.507h-20.5v-4h20.5zm-22.453-1.571-10.712-48.771 3.907-0.858 10.711 48.771zm-7.893-47.397c-12.836 6.156-21.654 19.109-21.654 34.068h-4c0-16.58 9.776-30.89 23.924-37.675zm-21.654 34.068c0 20.89 17.208 37.877 38.5 37.877v4c-23.443 0-42.5-18.72-42.5-41.877zm38.5 37.877c21.292 0 38.5-16.987 38.5-37.877h4c0 23.157-19.057 41.877-42.5 41.877zm38.5-37.877c0-16.469-10.69-30.51-25.657-35.719l1.314-3.777c16.494 5.739 28.343 21.24 28.343 39.496z" fill="#1a1a1a" mask="url(#path-5-inside-1_4566_53869)"/><path d="m59.5 111.84v52.183h2v-52.183zm-19.5 1.676h2v-2.814l-2.6574 0.925zm0 50.507h-2v2h2zm20.5 0v2h1.6084l0.345-1.571zm10.711-48.771 0.8648-1.804-2.2766-1.091-0.5417 2.466zm-33.211-1.736v50.507h4v-50.507zm2 52.507h20.5v-4h-20.5zm22.453-1.571 10.711-48.771-3.9069-0.858-10.711 48.771zm7.8931-47.397c12.836 6.156 21.654 19.109 21.654 34.068h4c0-16.58-9.7765-30.89-23.924-37.675zm21.654 34.068c0 20.89-17.208 37.877-38.5 37.877v4c23.443 0 42.5-18.72 42.5-41.877zm-38.5 37.877c-21.292 0-38.5-16.987-38.5-37.877h-4c0 23.157 19.057 41.877 42.5 41.877zm-38.5-37.877c0-16.469 10.69-30.51 25.657-35.719l-1.3148-3.777c-16.493 5.739-28.343 21.24-28.343 39.496z" fill="#1a1a1a" mask="url(#path-7-inside-2_4566_53869)"/><path d="m121.36 81.141 17.501 23.335" stroke="#1a1a1a" stroke-width="2"/><path d="m138.65 164.92v-61.051" stroke="#1a1a1a" stroke-width="2"/><path d="m138.59 104.21h22.274" stroke="#1a1a1a" stroke-width="2"/><path d="m79.019 81.141-17.854 23.246" stroke="#1a1a1a" stroke-width="2"/><path d="m61.342 164.58-0.17678-60.281" stroke="#1a1a1a" stroke-width="2"/><path d="m39.023 104.3 22.185 0.0442" stroke="#1a1a1a" stroke-width="2"/><path d="m67.264 0s-67.264 0-67.264 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.929zm67.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="#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="m38.422 7.1554c1.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="m38.422 7.1554c1.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="m40.211 8.0498c0.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="m44.559 37.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>
</svg>

After

Width:  |  Height:  |  Size: 17 KiB

361
application/src/main/data/json/system/scada_symbols/drilling-line-hp.svg

@ -0,0 +1,361 @@
<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 Drilling line",
"description": "Drilling line with various states.",
"searchTags": [
"drilling line"
],
"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": "secondary-background",
"stateRenderFunction": "var color = ctx.properties.stoppedColor;\nif (ctx.values.running) {\n color = '#dedede';\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
},
{
"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">
<path d="m63 121h74v240h-74z" stroke="#1A1A1A"/>
<ellipse cx="100.54" cy="101" rx="99.422" ry="100"/>
<g transform="translate(-.043811 1)" clip-path="url(#clip0_4864_4144)" stroke="#727171">
<path d="m97.225 37.672c-7.5861-19.484-16.826-28.051-22.054-34.859l-28.813 0.75778-20.347 24.447c1.6695-1.8123 10.516-0.092 32.545 21.288 22.029 21.38 29.908 40.861 31.093 47.929l15.475-10.344c0-15.191-0.313-29.735-7.899-49.219z"/>
<path d="m166.5 132.89c20.8 2.127 32.637-2.193 41.079-3.744l12.457-25.992-12.488-29.253c0.852 2.312-4.71 9.4022-33.78 19.267-29.07 9.8649-50.001 7.9989-56.833 5.8331l-3.553 17.159c13.521 6.923 32.318 14.603 53.118 16.73z"/>
<path d="m46.728 132.5c-14.634 14.934-23.517 27.044-27.569 34.611l12.551 25.947 30.656 8.48c-2.3389-0.776-4.4126-9.546 6.0037-38.423s24.928-44.076 30.881-48.066l-12.593-9.458c-13.844 6.253-25.296 11.976-39.93 26.909z"/>
</g>
<circle cx="100.47" cy="101.51" r="20.796" fill="#dedede" stroke="#000" tb:tag="secondary-background"/>
<path d="m39 361h122v38h-122z" fill="#dedede" stroke="#000" tb:tag="secondary-background"/>
</g><ellipse cx="100.11" cy="101" rx="99.009" ry="99.164" stroke="#000" stroke-width="2"/><path d="m67.264 0s-67.264 0-67.264 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="m38.422 7.1554c1.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="m38.422 7.1554c1.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="m40.211 8.0498c0.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="m44.559 37.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><defs>
<clipPath id="clip0_4864_4144">
<rect width="200" height="200" rx="100" fill="#fff"/>
</clipPath>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 14 KiB

354
application/src/main/data/json/system/scada_symbols/drilling-rig-hp.svg

@ -0,0 +1,354 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:tb="https://thingsboard.io/svg" width="800" height="1800" fill="none" version="1.1" viewBox="0 0 800 1800"><tb:metadata xmlns=""><![CDATA[{
"title": "HP Drilling rig",
"description": "Drilling rig with various states.",
"searchTags": [
"drilling rig"
],
"widgetSizeX": 4,
"widgetSizeY": 9,
"tags": [
{
"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": "drilling-ring",
"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": "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="m280.06 201h239.89c2.435 0 4.516 1.754 4.928 4.153l273.94 1593.8h-797.63l273.94-1593.8c0.413-2.399 2.493-4.153 4.928-4.153z" stroke="#1a1a1a" stroke-width="2"/><line x1="276.08" x2="575.67" y1="202.29" y2="501.88" stroke="#1a1a1a" stroke-width="1.9986"/><line x1="523.29" x2="224.71" y1="201.71" y2="500.29" stroke="#1a1a1a" stroke-width="1.9986"/><line x1="225.08" x2="647.67" y1="500.29" y2="922.88" stroke="#1a1a1a" stroke-width="1.999"/><line x1="573.88" x2="151.29" y1="502.29" y2="924.88" stroke="#1a1a1a" stroke-width="1.999"/><line x1="152.71" x2="751.29" y1="925.29" y2="1523.9" stroke="#1a1a1a" stroke-width="1.9993"/><line x1="647.29" x2="48.707" y1="924.71" y2="1523.3" stroke="#1a1a1a" stroke-width="1.9993"/><path d="m389.98 1028.8c2.365-3.65 3.896-6.72 4.6109-9.87 0.64099-2.82 0.61099-5.64 0.017-8.92h30.21c0.58999 3.57 0.85699 11.11-3.162 23.22-1.333 4.02-4.2859 7.86-8.1039 11.68-3.19 3.19-6.9109 6.3-10.681 9.45-0.73999 0.62-1.482 1.24-2.223 1.86-4.4839 3.77-8.8969 7.63-12.264 11.69-3.366 4.07-5.7649 8.44-6.0849 13.24-0.61599 9.24 1.978 15.78 5.8949 20.39 3.8929 4.58 9.0239 7.17 13.365 8.69 3.366 1.17 10.24 1.99 16.595-0.23 3.199-1.11 6.2889-3.01 8.7169-6.03 2.429-3.03 4.1489-7.14 4.6969-12.59 0.349-3.48 0.607-6.53 0.82999-9.15 0.119-1.4 0.227-2.69 0.334-3.85 0.31099-3.38 0.60399-5.72 1.064-7.25 0.461-1.53 0.96899-1.88 1.476-1.96 0.337-0.05 0.81799-0.01 1.519 0.2 0.69499 0.21 1.536 0.57 2.566 1.09 11.321 5.64 15.547 14.83 16.45 23.83 0.90799 9.05-1.564 17.88-3.637 22.53-8.6369 19.38-26.348 31.19-48.797 31.19-13.467 0-23.767-2.39-32.055-6.71-8.2839-4.32-14.63-10.62-20.134-18.55-4.4109-6.36-8.8289-16.85-9.9249-28.56-1.095-11.69 1.125-24.52 9.8889-35.66 8.2179-10.45 16.325-15.53 23.13-19.13 1.229-0.65 2.434-1.27 3.598-1.85 2.026-1.03 3.924-1.99 5.5949-2.99 2.665-1.58 4.9279-3.33 6.5099-5.76z" fill="#dedede" stroke="#1a1a1a" stroke-width="2"/><path d="m339 1150h122v38h-122z" fill="#dedede" stroke="#1a1a1a" stroke-width="2"/><path d="m339 981h122v38h-122z" fill="#dedede" stroke="#1a1a1a" stroke-width="2"/><path d="m363 1188h74v487h-74z" fill="#dedede" stroke="#1a1a1a" stroke-width="2"/><path d="m363 201h74v780h-74z" stroke="#1a1a1a" stroke-width="2"/><circle cx="401.33" cy="120" r="119" fill="#dedede" stroke="#1a1a1a" stroke-width="2.0026"/><g clip-path="url(#clip0_4613_175962)" fill="#dedede">
<path d="m397.27 45.19c-9.0358-23.378-20.04-33.657-26.268-41.826l-34.32 0.90925-24.236 29.334c1.9888-2.1746 12.525-0.11046 38.765 25.543 26.239 25.653 35.623 49.028 37.035 57.509l18.432-12.412c0-18.227-0.37246-35.679-9.4092-59.057z" stroke="#727171" stroke-width="1.996"/>
<path d="m480.57 159.3c24.917 2.557 39.097-2.6364 49.21-4.5l14.922-31.246-14.959-35.167c1.0206 2.7794-5.643 11.303-40.467 23.162-34.824 11.859-59.898 9.617-68.082 7.0128l-4.2568 20.627c16.198 8.3224 38.716 17.554 63.633 20.112z" stroke="#727171" stroke-width="2.0051"/>
<path d="m337.34 158.51c-17.566 17.88-28.229 32.38-33.094 41.44l15.066 31.067 36.799 10.153c-2.8073-0.928-5.2964-11.429 7.2073-46.004 12.504-34.575 29.922-52.773 37.069-57.55l-15.116-11.324c-16.619 7.4871-30.366 14.338-47.932 32.219z" stroke="#727171" stroke-width="2.0037"/>
<ellipse cx="401.68" cy="120.34" rx="24.997" ry="24.997" stroke="#1a1a1a" stroke-width="2.0051"/>
</g><circle cx="401.33" cy="120" r="119" stroke="#1a1a1a" stroke-width="2.0026"/><defs>
<clipPath id="clip0_4613_175962">
<rect x="281.33" width="240" height="240" rx="120" fill="#fff"/>
</clipPath>
</defs><g fill="#fff" stroke="#1a1a1a" stroke-width="2" tb:tag="drilling-ring">
<path d="m229 1675h342v91h-342z"/>
<path d="m141 1765h518v34h-518z"/>
</g><path d="m269.06 0s-269.06 0-269.06 301.5v1477.6c0 11.93 7.1636 20.882 16 20.882h768c8.836 0 16-8.9514 16-20.882v-1477.6c0-301.5-264.28-301.5-264.28-301.5h-135.72zm268.28 365.4c-5.1548 0-9.3332 5.6412-9.3332 12.6v1351.8c0 6.9588 4.1788 12.6 9.3332 12.6h58.664c5.1548 0 9.3332-5.6412 9.3332-12.6v-1351.8c0-6.9588-4.1788-12.6-9.3332-12.6z" 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="m38.422 7.1554c1.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="m38.422 7.1554c1.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="m40.211 8.0498c0.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="m44.559 37.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>
</svg>

After

Width:  |  Height:  |  Size: 16 KiB

293
application/src/main/data/json/system/scada_symbols/hook-hp.svg

@ -0,0 +1,293 @@
<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 Hook",
"description": "Hook with various states.",
"searchTags": [
"hook",
"drilling"
],
"widgetSizeX": 1,
"widgetSizeY": 2,
"tags": [
{
"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": "hook",
"stateRenderFunction": "element.attr({fill: ctx.properties.hookColor});",
"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": "hookColor",
"name": "{i18n:scada.symbol.hook-color}",
"type": "color",
"default": "#FFFFFF",
"required": null,
"subLabel": "",
"divider": false,
"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="hook">
<path d="m83.979 279.78c2.3649-3.644 3.8966-6.715 4.6115-9.864 0.64089-2.823 0.61129-5.644 0.017-8.921h30.209c0.58999 3.566 0.85699 11.114-3.162 23.222-1.333 4.015-4.2859 7.854-8.1039 11.674-3.19 3.19-6.9109 6.3-10.681 9.45-0.74019 0.619-1.4823 1.239-2.2226 1.862-4.4846 3.772-8.8978 7.63-12.264 11.697-3.3665 4.066-5.7648 8.433-6.0848 13.232-0.61659 9.244 1.9776 15.781 5.8941 20.39 3.8938 4.582 9.0245 7.176 13.366 8.691 3.3656 1.175 10.24 1.992 16.594-0.225 3.199-1.116 6.2889-3.011 8.7169-6.037 2.429-3.028 4.149-7.131 4.6969-12.59 0.34899-3.477 0.60699-6.524 0.82999-9.148 0.119-1.403 0.22699-2.684 0.33399-3.846 0.311-3.382 0.60399-5.72 1.064-7.249 0.46099-1.528 0.96899-1.88 1.476-1.959 0.33699-0.054 0.81799-0.013 1.519 0.199 0.69499 0.211 1.536 0.57 2.566 1.084 11.321 5.643 15.547 14.835 16.45 23.832 0.90798 9.053-1.564 17.881-3.637 22.532-8.6369 19.376-26.348 31.189-48.797 31.189-13.468 0-23.767-2.387-32.055-6.711-8.2843-4.322-14.63-10.617-20.134-18.55-4.4111-6.357-8.8287-16.852-9.925-28.56-1.0945-11.689 1.1254-24.52 9.889-35.661 8.2183-10.447 16.325-15.531 23.129-19.132 1.2292-0.65 2.4347-1.261 3.5979-1.851 2.0264-1.027 3.9244-1.989 5.5955-2.981 2.6649-1.581 4.9275-3.332 6.5092-5.769z"/>
<path d="m58.08 261.38c-1.9988-1.28-4.4082-3.607-7.1067-6.92-2.688-3.299-5.6227-7.526-8.6813-12.552-6.1167-10.053-12.701-23.261-18.777-38.55-12.154-30.585-22.24-69.418-22.511-107.89-0.43146-61.407 29.982-85.126 51.186-90.56 10.719-2.7467 30.395-3.9859 49.703-3.9086 19.316 0.07727 38.034 1.4712 46.85 3.9039 17.425 4.8087 50.257 32.066 50.257 90.571 0 32.108-9.83 70.081-22.104 101.85-6.133 15.874-12.866 30.17-19.264 41.38-6.423 11.254-12.436 19.266-17.095 22.714-1.119 0.828-3.04 1.62-5.682 2.327-2.615 0.701-5.841 1.294-9.494 1.775-7.304 0.96-16.24 1.459-25.255 1.477-9.0138 0.019-18.079-0.442-25.642-1.393-3.7817-0.476-7.1717-1.072-9.9838-1.787-2.8296-0.72-5.0029-1.542-6.4004-2.437z"/>
</g><mask id="path-5-inside-1_4471_52357" fill="#ffffff">
<path d="m172.8 99c0 39.765-32.236 72-72 72-39.765 0-72-32.235-72-72 0-39.764 32.236-72 72-72 39.764 0 72 32.236 72 72zm-132.78 0c0 33.57 27.214 60.784 60.784 60.784 33.57 0 60.784-27.214 60.784-60.784 0-33.57-27.214-60.784-60.784-60.784-33.57 0-60.784 27.214-60.784 60.784z"/>
</mask><path d="m172.8 99c0 39.765-32.236 72-72 72-39.765 0-72-32.235-72-72 0-39.764 32.236-72 72-72 39.764 0 72 32.236 72 72zm-132.78 0c0 33.57 27.214 60.784 60.784 60.784 33.57 0 60.784-27.214 60.784-60.784 0-33.57-27.214-60.784-60.784-60.784-33.57 0-60.784 27.214-60.784 60.784z" fill="#dedede" mask="url(#path-5-inside-1_4471_52357)" stroke="#1a1a1a" stroke-width="4"/><path d="m67.264 0s-67.264 0-67.264 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="m38.422 7.1554c1.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="m38.422 7.1554c1.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="m40.211 8.0498c0.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="m44.559 37.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>
</svg>

After

Width:  |  Height:  |  Size: 14 KiB

743
application/src/main/data/json/system/scada_symbols/meter.svg

@ -0,0 +1,743 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:tb="https://thingsboard.io/svg" width="100" height="400" fill="none" version="1.1" viewBox="0 0 100 400"><tb:metadata xmlns=""><![CDATA[{
"title": "Meter",
"description": "Meter displays the current value with a moving pointer on the scale.",
"searchTags": [
"scale",
"level",
"progress",
"thermometer"
],
"widgetSizeX": 1,
"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": "progress-indicator",
"stateRenderFunction": "function calculateOffset(value, minValue, maxValue, initial) {\n var clampedValue = Math.max(Math.min(value, Math.max(minValue, maxValue)), Math.min(minValue, maxValue));\n var normalizedValue = minValue < maxValue\n ? (clampedValue - minValue) / (maxValue - minValue)\n : (minValue - clampedValue) / (minValue - maxValue);\n var offset = initial - (normalizedValue * initial);\n return offset;\n}\n\nvar valueSet = element.remember('valueSet');\n\nif (ctx.properties.progressArrow && !ctx.properties.progressBar) {\n element.show();\n var initial = ctx.properties.valueBox ? 329: 366;\n if (!valueSet) {\n element.remember('valueSet', true);\n element.transform({\n translateY: initial\n });\n }\n \n var minValue = ctx.properties.minValue;\n var maxValue = ctx.properties.maxValue;\n var value = ctx.values.value;\n \n var colorProcessor = ctx.properties.progressArrowColor;\n colorProcessor.update(value);\n var fill = colorProcessor.color;\n element.attr({fill: fill});\n \n var offset = calculateOffset(value, minValue, maxValue, initial);\n\n var elementOffset = element.remember('offset');\n if (offset !== elementOffset) {\n element.remember('offset', offset);\n ctx.api.cssAnimate(element, 500).transform({\n translateY: offset\n });\n }\n} else {\n element.hide();\n if (valueSet) {\n element.remember('valueSet', false);\n }\n}",
"actions": null
},
{
"tag": "progressBar",
"stateRenderFunction": "if (ctx.properties.progressBar) {\n element.show();\n} else {\n element.hide();\n}",
"actions": null
},
{
"tag": "progressBorder",
"stateRenderFunction": "if (!ctx.properties.valueBox) {\n element.attr({'height': 367})\n}",
"actions": null
},
{
"tag": "progressCircle",
"stateRenderFunction": "if (!ctx.properties.valueBox) {\n element.attr({cy:383});\n}",
"actions": null
},
{
"tag": "progressFill",
"stateRenderFunction": "if (!ctx.properties.valueBox) {\n element.attr({y:-378});\n}\n\nfunction calculateOffset(value, minValue, maxValue, initial) {\n var clampedValue = Math.max(Math.min(value, Math.max(minValue, maxValue)), Math.min(minValue, maxValue));\n var normalizedValue = minValue < maxValue\n ? (clampedValue - minValue) / (maxValue - minValue)\n : (minValue - clampedValue) / (minValue - maxValue);\n var offset = normalizedValue * initial;\n return offset;\n}\n\nvar valueSet = element.remember('valueSet');\nif (ctx.properties.progressBar) {\n var initial = ctx.properties.valueBox ? 329: 366;\n if (!valueSet) {\n element.remember('valueSet', true);\n element.attr({height: 2});\n }\n \n var minValue = ctx.properties.minValue;\n var maxValue = ctx.properties.maxValue;\n var value = ctx.values.value;\n \n var colorProcessor = ctx.properties.progressBarColor;\n colorProcessor.update(value);\n var fill = colorProcessor.color;\n element.attr({fill: fill, stroke: fill});\n ctx.tags.progressCircle[0].fill(fill);\n \n var height = calculateOffset(value, minValue, maxValue, initial);\n\n var elementHeight = element.remember('height');\n if (height !== elementHeight) {\n element.remember('height', height);\n ctx.api.cssAnimate(element, 500).attr({height: height+2});\n }\n} else {\n if (valueSet) {\n element.remember('valueSet', false);\n }\n}",
"actions": null
},
{
"tag": "scale",
"stateRenderFunction": "var scaleSet = element.remember('scaleSet');\nif (!scaleSet) {\n element.remember('scaleSet', true);\n element.clear();\n \n var majorIntervals = ctx.properties.majorIntervals;\n var minorIntervals = ctx.properties.minorIntervals;\n var minValue = ctx.properties.minValue;\n var maxValue = ctx.properties.maxValue;\n \n var start = 11;\n var end = ctx.properties.valueBox ? 328 : 365;\n var majorIntervalLength = end / majorIntervals;\n var minorIntervalLength = majorIntervalLength / minorIntervals;\n element.add(ctx.svg.line(63, end+11, 63, 11).stroke({ width: 1 }).attr({class: 'majorTick'}));\n for (var i = 0; i < majorIntervals+1; i++) {\n var y = start + i * majorIntervalLength;\n var line = ctx.svg.line(51, y, 63, y).stroke({ width: 1 }).attr({class: 'majorTick'});\n element.add(line);\n var majorText = (maxValue - ((maxValue - (minValue)) / (majorIntervals) * i)).toFixed(0);\n var majorTickText = ctx.svg.text(majorText);\n majorTickText.attr({x: 45, y: y + 2, 'text-anchor': 'end', class: 'majorTickText'});\n majorTickText.first().attr({'dominant-baseline': 'middle'});\n element.add(majorTickText);\n if (i < majorIntervals) {\n drawMinorTicks(y, minorIntervals, minorIntervalLength);\n }\n }\n}\n\nvar majorFont = ctx.properties.majorFont;\nvar majorColor = ctx.properties.majorColor;\nvar minorColor = ctx.properties.minorColor;\nif (ctx.values.critical) {\n majorColor = ctx.properties.majorCriticalColor;\n minorColor = ctx.properties.minorCriticalColor;\n} else if (ctx.values.warning) {\n majorColor = ctx.properties.minorWarningColor;\n minorColor = ctx.properties.minorWarningColor;\n}\n\nvar majorTicks = element.find('line.majorTick');\nmajorTicks.forEach(t => t.attr({stroke: majorColor}));\n\nvar majorTicksText = element.find('text.majorTickText');\nctx.api.font(majorTicksText, majorFont, majorColor);\n\nvar minorTicks = element.find('line.minorTick');\nminorTicks.forEach(t => t.attr({stroke: minorColor}));\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\nfunction drawMinorTicks(start, minorIntervals, minorIntervalLength) {\n for (var i = 1; i < minorIntervals; i++) {\n var minorY = start + i * minorIntervalLength;\n var minorLine = ctx.svg.line(57, minorY, 63, minorY).stroke({ width: 1 }).attr({class: 'minorTick'});\n element.add(minorLine);\n }\n}",
"actions": null
},
{
"tag": "value-box",
"stateRenderFunction": "if (ctx.properties.valueBox) {\n element.show();\n} else {\n element.hide();\n}",
"actions": null
},
{
"tag": "value-box-background",
"stateRenderFunction": "if (ctx.properties.valueBox) {\n var colorProcessor = ctx.properties.valueBoxColor;\n colorProcessor.update(ctx.values.value);\n element.attr({fill: colorProcessor.color});\n}",
"actions": null
},
{
"tag": "value-text",
"stateRenderFunction": "if (ctx.properties.valueBox) {\n var valueTextFont = ctx.properties.valueTextFont;\n var valueTextColor = ctx.properties.valueTextColor;\n var currentVolume = ctx.values.value;\n var valueText = ctx.api.formatValue(currentVolume, 0, ctx.properties.valueUnits, false);\n var colorProcessor = ctx.properties.valueTextColor;\n colorProcessor.update(ctx.values.value);\n ctx.api.font(element, valueTextFont, colorProcessor.color);\n ctx.api.text(element, valueText);\n}",
"actions": null
}
],
"behavior": [
{
"id": "value",
"name": "{i18n:scada.symbol.value}",
"hint": null,
"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": "waterLevel"
},
"dataToValue": {
"type": "NONE",
"dataToValueFunction": "/* Should return boolean value */\nreturn data;"
}
},
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": null
},
{
"id": "warning",
"name": "{i18n:scada.symbol.warning-state}",
"hint": "{i18n:scada.symbol.warning-state-hint}",
"group": null,
"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": "critical",
"name": "{i18n:scada.symbol.critical-state}",
"hint": "{i18n:scada.symbol.critical-state-hint}",
"group": null,
"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": "criticalAnimation",
"name": "{i18n:scada.symbol.critical-state-animation}",
"hint": "{i18n:scada.symbol.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": "minValue",
"name": "{i18n:scada.symbol.min-max-value}",
"type": "number",
"default": 0,
"required": true,
"subLabel": "{i18n:scada.symbol.min-value}",
"divider": true,
"min": -1000,
"step": 1,
"disabled": false,
"visible": true
},
{
"id": "maxValue",
"name": "{i18n:scada.symbol.min-max-value}",
"type": "number",
"default": 100,
"required": true,
"subLabel": "{i18n:scada.symbol.max-value}",
"max": 1000,
"step": 1,
"disabled": false,
"visible": true
},
{
"id": "backgroundColor",
"name": "{i18n:scada.symbol.background-color}",
"type": "color",
"default": "#FFFFFF",
"disabled": false,
"visible": true
},
{
"id": "progressBar",
"name": "{i18n:scada.symbol.progress-bar}",
"type": "switch",
"default": true,
"disabled": false,
"visible": true
},
{
"id": "progressBarColor",
"name": "{i18n:scada.symbol.progress-bar}",
"type": "color_settings",
"default": {
"type": "constant",
"color": "#4D94E1",
"gradient": {
"advancedMode": false,
"gradient": [
"rgba(0, 255, 0, 1)",
"rgba(255, 0, 0, 1)"
],
"gradientAdvanced": [
{
"source": {
"type": "constant"
},
"color": "rgba(0, 255, 0, 1)"
},
{
"source": {
"type": "constant"
},
"color": "rgba(255, 0, 0, 1)"
}
],
"minValue": 0,
"maxValue": 100
},
"rangeList": {
"advancedMode": false,
"range": [],
"rangeAdvanced": []
},
"colorFunction": "var temperature = value;\nif (typeof temperature !== undefined) {\n var percent = (temperature + 60)/120 * 100;\n return tinycolor.mix('blue', 'red', percent).toHexString();\n}\nreturn 'blue';"
},
"disableOnProperty": "progressBar",
"disabled": false,
"visible": true
},
{
"id": "progressArrow",
"name": "{i18n:scada.symbol.progress-arrow}",
"type": "switch",
"default": false,
"disabled": false,
"visible": true
},
{
"id": "progressArrowColor",
"name": "{i18n:scada.symbol.progress-arrow}",
"type": "color_settings",
"default": {
"type": "constant",
"color": "#1C943E",
"gradient": {
"advancedMode": false,
"gradient": [
"rgba(0, 255, 0, 1)",
"rgba(255, 0, 0, 1)"
],
"gradientAdvanced": [
{
"source": {
"type": "constant"
},
"color": "rgba(0, 255, 0, 1)"
},
{
"source": {
"type": "constant"
},
"color": "rgba(255, 0, 0, 1)"
}
],
"minValue": 0,
"maxValue": 100
},
"rangeList": {
"advancedMode": false,
"range": [],
"rangeAdvanced": []
},
"colorFunction": "var temperature = value;\nif (typeof temperature !== undefined) {\n var percent = (temperature + 60)/120 * 100;\n return tinycolor.mix('blue', 'red', percent).toHexString();\n}\nreturn 'blue';"
},
"disableOnProperty": "progressArrow",
"disabled": true,
"visible": true
},
{
"id": "valueBox",
"name": "{i18n:scada.symbol.value-box}",
"type": "switch",
"default": true,
"disabled": false,
"visible": true
},
{
"id": "valueBoxColor",
"name": "{i18n:scada.symbol.value-box}",
"type": "color_settings",
"default": {
"type": "constant",
"color": "#F3F3F3",
"gradient": {
"advancedMode": false,
"gradient": [
"rgba(0, 255, 0, 1)",
"rgba(255, 0, 0, 1)"
],
"gradientAdvanced": [
{
"source": {
"type": "constant"
},
"color": "rgba(0, 255, 0, 1)"
},
{
"source": {
"type": "constant"
},
"color": "rgba(255, 0, 0, 1)"
}
],
"minValue": 0,
"maxValue": 100
},
"rangeList": {
"advancedMode": false,
"range": [],
"rangeAdvanced": []
},
"colorFunction": "var temperature = value;\nif (typeof temperature !== undefined) {\n var percent = (temperature + 60)/120 * 100;\n return tinycolor.mix('blue', 'red', percent).toHexString();\n}\nreturn 'blue';"
},
"disableOnProperty": "valueBox",
"disabled": false,
"visible": true
},
{
"id": "valueUnits",
"name": "{i18n:scada.symbol.value-text}",
"type": "units",
"default": "%",
"subLabel": "{i18n:scada.symbol.units}",
"disableOnProperty": "valueBox",
"disabled": false,
"visible": true
},
{
"id": "valueTextFont",
"name": "{i18n:scada.symbol.value-text}",
"type": "font",
"default": {
"size": 14,
"sizeUnit": "px",
"family": "Roboto",
"weight": "500",
"style": "normal"
},
"disableOnProperty": "valueBox",
"disabled": false,
"visible": true
},
{
"id": "valueTextColor",
"name": "{i18n:scada.symbol.value-text}",
"type": "color_settings",
"default": {
"type": "constant",
"color": "#0000008A",
"gradient": {
"advancedMode": false,
"gradient": [
"rgba(0, 255, 0, 1)",
"rgba(255, 0, 0, 1)"
],
"gradientAdvanced": [
{
"source": {
"type": "constant"
},
"color": "rgba(0, 255, 0, 1)"
},
{
"source": {
"type": "constant"
},
"color": "rgba(255, 0, 0, 1)"
}
],
"minValue": 0,
"maxValue": 100
},
"rangeList": {
"advancedMode": false,
"range": [],
"rangeAdvanced": []
},
"colorFunction": "var temperature = value;\nif (typeof temperature !== undefined) {\n var percent = (temperature + 60)/120 * 100;\n return tinycolor.mix('blue', 'red', percent).toHexString();\n}\nreturn 'blue';"
},
"disableOnProperty": "valueBox",
"disabled": false,
"visible": true
},
{
"id": "majorIntervals",
"name": "{i18n:scada.symbol.major-ticks}",
"type": "number",
"default": 10,
"subLabel": "{i18n:scada.symbol.intervals}",
"divider": true,
"min": 1,
"step": 1,
"disabled": false,
"visible": true
},
{
"id": "majorFont",
"name": "{i18n:scada.symbol.major-ticks}",
"type": "font",
"default": {
"size": 12,
"sizeUnit": "px",
"family": "Roboto",
"weight": "500",
"style": "normal"
},
"disabled": false,
"visible": true
},
{
"id": "majorColor",
"name": "{i18n:scada.symbol.major-ticks-color}",
"type": "color",
"default": "#747474",
"subLabel": "{i18n:scada.symbol.normal}",
"divider": true,
"disabled": false,
"visible": true
},
{
"id": "majorWarningColor",
"name": "{i18n:scada.symbol.major-ticks-color}",
"type": "color",
"default": "#FAA405",
"subLabel": "{i18n:scada.symbol.warning}",
"divider": true,
"disabled": false,
"visible": true
},
{
"id": "majorCriticalColor",
"name": "{i18n:scada.symbol.major-ticks-color}",
"type": "color",
"default": "#D12730",
"subLabel": "{i18n:scada.symbol.critical}",
"disabled": false,
"visible": true
},
{
"id": "minorIntervals",
"name": "{i18n:scada.symbol.minor-ticks}",
"type": "number",
"default": 10,
"subLabel": "{i18n:scada.symbol.intervals}",
"min": 1,
"disabled": false,
"visible": true
},
{
"id": "minorColor",
"name": "{i18n:scada.symbol.minor-ticks-color}",
"type": "color",
"default": "#747474",
"subLabel": "{i18n:scada.symbol.normal}",
"divider": true,
"disabled": false,
"visible": true
},
{
"id": "minorWarningColor",
"name": "{i18n:scada.symbol.minor-ticks-color}",
"type": "color",
"default": "#FAA405",
"subLabel": "{i18n:scada.symbol.warning}",
"divider": true,
"disabled": false,
"visible": true
},
{
"id": "minorCriticalColor",
"name": "{i18n:scada.symbol.minor-ticks-color}",
"type": "color",
"default": "#D12730",
"subLabel": "{i18n:scada.symbol.critical}",
"disabled": false,
"visible": true
}
]
}]]></tb:metadata>
<path d="m16 400c-2.2091 0-4-1.791-4-4v-392c0-2.2091 1.7909-4 4-4h68c2.2091 0 4 1.7909 4 4v392c0 2.209-1.7909 4-4 4h-68z" fill="#E5E5E5" tb:tag="background"/><path d="m16 400c-2.2091 0-4-1.791-4-4v-392c0-2.2091 1.7909-4 4-4h68c2.2091 0 4 1.7909 4 4v392c0 2.209-1.7909 4-4 4h-68z" fill="url(#paint0_linear_2475_365165)"/><path d="m16 398.5c-1.3807 0-2.5-1.119-2.5-2.5v-392c0-1.3807 1.1193-2.5 2.5-2.5h68c1.3807 0 2.5 1.1193 2.5 2.5v392c0 1.381-1.1193 2.5-2.5 2.5h-68z" stroke="#000" stroke-opacity=".12" stroke-width="3"/><g tb:tag="scale">
<path d="m27.539 10.44v8.5605h-1.4121v-6.8848l-2.0918 0.709v-1.166l3.3339-1.2187h0.17zm8.7754 3.58v1.3946c0 0.6679-0.0665 1.2382-0.1993 1.7109-0.1289 0.4688-0.3164 0.8496-0.5625 1.1426-0.2461 0.2929-0.541 0.5078-0.8847 0.6445-0.3399 0.1367-0.7207 0.2051-1.1426 0.2051-0.3359 0-0.6484-0.043-0.9375-0.1289-0.2852-0.086-0.543-0.2207-0.7734-0.4043-0.2305-0.1836-0.4278-0.4199-0.5918-0.709-0.1602-0.293-0.2852-0.6426-0.375-1.0488-0.086-0.4063-0.1289-0.877-0.1289-1.4121v-1.3946c0-0.6718 0.0664-1.2383 0.1992-1.6992 0.1328-0.4648 0.3222-0.8418 0.5683-1.1308 0.2461-0.293 0.5391-0.5059 0.8789-0.6387 0.3438-0.1328 0.7266-0.1992 1.1485-0.1992 0.3398 0 0.6523 0.0429 0.9375 0.1289 0.289 0.082 0.5468 0.2129 0.7734 0.3925 0.2305 0.1797 0.4258 0.4141 0.5859 0.7032 0.1641 0.2851 0.2891 0.6308 0.375 1.0371 0.086 0.4023 0.129 0.8711 0.129 1.4062zm-1.4122 1.5938v-1.8047c0-0.3398-0.0195-0.6387-0.0585-0.8965-0.0391-0.2617-0.0977-0.4824-0.1758-0.6621-0.0742-0.1836-0.168-0.332-0.2813-0.4453-0.1133-0.1172-0.2422-0.2012-0.3867-0.252-0.1445-0.0547-0.3066-0.082-0.4863-0.082-0.2188 0-0.4141 0.043-0.586 0.1289-0.1718 0.082-0.3164 0.2149-0.4336 0.3984-0.1171 0.1836-0.207 0.4258-0.2695 0.7266-0.0586 0.2969-0.0879 0.6582-0.0879 1.084v1.8047c0 0.3437 0.0195 0.6465 0.0586 0.9082s0.0977 0.4863 0.1758 0.6738c0.0781 0.1836 0.1719 0.3359 0.2812 0.457 0.1133 0.1172 0.2422 0.2032 0.3868 0.2579 0.1484 0.0546 0.3105 0.082 0.4863 0.082 0.2226 0 0.4199-0.043 0.5918-0.1289 0.1719-0.086 0.3164-0.2227 0.4336-0.4102 0.1172-0.1914 0.2051-0.4394 0.2637-0.7441 0.0585-0.3047 0.0878-0.6699 0.0878-1.0957zm8.4825-1.5938v1.3946c0 0.6679-0.0664 1.2382-0.1993 1.7109-0.1289 0.4688-0.3164 0.8496-0.5625 1.1426-0.246 0.2929-0.541 0.5078-0.8847 0.6445-0.3399 0.1367-0.7207 0.2051-1.1426 0.2051-0.3359 0-0.6484-0.043-0.9375-0.1289-0.2852-0.086-0.543-0.2207-0.7734-0.4043-0.2305-0.1836-0.4278-0.4199-0.5918-0.709-0.1602-0.293-0.2852-0.6426-0.375-1.0488-0.086-0.4063-0.1289-0.877-0.1289-1.4121v-1.3946c0-0.6718 0.0664-1.2383 0.1992-1.6992 0.1328-0.4648 0.3222-0.8418 0.5683-1.1308 0.2461-0.293 0.5391-0.5059 0.8789-0.6387 0.3438-0.1328 0.7266-0.1992 1.1485-0.1992 0.3398 0 0.6523 0.0429 0.9375 0.1289 0.289 0.082 0.5469 0.2129 0.7734 0.3925 0.2305 0.1797 0.4258 0.4141 0.586 0.7032 0.164 0.2851 0.289 0.6308 0.375 1.0371 0.0859 0.4023 0.1289 0.8711 0.1289 1.4062zm-1.4121 1.5938v-1.8047c0-0.3398-0.0196-0.6387-0.0586-0.8965-0.0391-0.2617-0.0977-0.4824-0.1758-0.6621-0.0742-0.1836-0.168-0.332-0.2813-0.4453-0.1132-0.1172-0.2422-0.2012-0.3867-0.252-0.1445-0.0547-0.3066-0.082-0.4863-0.082-0.2188 0-0.4141 0.043-0.586 0.1289-0.1718 0.082-0.3164 0.2149-0.4335 0.3984-0.1172 0.1836-0.2071 0.4258-0.2696 0.7266-0.0586 0.2969-0.0879 0.6582-0.0879 1.084v1.8047c0 0.3437 0.0196 0.6465 0.0586 0.9082 0.0391 0.2617 0.0977 0.4863 0.1758 0.6738 0.0781 0.1836 0.1719 0.3359 0.2813 0.457 0.1132 0.1172 0.2421 0.2032 0.3867 0.2579 0.1484 0.0546 0.3105 0.082 0.4863 0.082 0.2227 0 0.4199-0.043 0.5918-0.1289 0.1719-0.086 0.3164-0.2227 0.4336-0.4102 0.1172-0.1914 0.2051-0.4394 0.2637-0.7441s0.0879-0.6699 0.0879-1.0957z" fill="#000" fill-opacity=".38"/>
<path d="m31.891 50.186h0.1172c0.5391 0 0.9883-0.0703 1.3477-0.2109 0.3633-0.1445 0.6523-0.3438 0.8672-0.5977 0.2148-0.2539 0.3691-0.5527 0.4628-0.8965 0.0938-0.3437 0.1407-0.7168 0.1407-1.1191v-1.4707c0-0.3477-0.0371-0.6523-0.1114-0.9141-0.0703-0.2656-0.1718-0.4863-0.3046-0.6621-0.129-0.1797-0.2793-0.3144-0.4512-0.4043-0.168-0.0898-0.3496-0.1347-0.5449-0.1347-0.2149 0-0.4082 0.0488-0.5801 0.1465-0.168 0.0937-0.3106 0.2246-0.4278 0.3925-0.1132 0.1641-0.2011 0.3575-0.2636 0.5801-0.0586 0.2188-0.0879 0.4531-0.0879 0.7031 0 0.2344 0.0273 0.461 0.082 0.6797 0.0586 0.2149 0.1445 0.4063 0.2578 0.5742 0.1133 0.168 0.2559 0.3008 0.4278 0.3985 0.1718 0.0976 0.373 0.1465 0.6035 0.1465 0.2187 0 0.4199-0.0411 0.6035-0.1231 0.1836-0.0859 0.3437-0.2012 0.4805-0.3457 0.1367-0.1445 0.2441-0.3066 0.3222-0.4863 0.0782-0.1797 0.1211-0.3633 0.1289-0.5508l0.5391 0.1641c0 0.2968-0.0625 0.5898-0.1875 0.8789-0.1211 0.2851-0.291 0.5468-0.5098 0.7851-0.2148 0.2344-0.4668 0.4219-0.7558 0.5625-0.2852 0.1407-0.5957 0.211-0.9317 0.211-0.4062 0-0.7656-0.0762-1.0781-0.2286-0.3086-0.1562-0.5664-0.3671-0.7734-0.6328-0.2032-0.2656-0.3555-0.5703-0.4571-0.914-0.1015-0.3438-0.1523-0.7051-0.1523-1.084 0-0.4102 0.0625-0.7949 0.1875-1.1543s0.3066-0.6758 0.5449-0.9492c0.2383-0.2774 0.5274-0.4922 0.8672-0.6446 0.3438-0.1562 0.7324-0.2343 1.166-0.2343 0.461 0 0.8653 0.0898 1.2129 0.2695 0.3477 0.1797 0.6406 0.4277 0.8789 0.7441s0.418 0.6836 0.5391 1.1016 0.1816 0.8672 0.1816 1.3477v0.498c0 0.5039-0.0449 0.9902-0.1347 1.459-0.0899 0.4648-0.2364 0.8965-0.4395 1.2949-0.1992 0.3945-0.4629 0.7422-0.791 1.043-0.3242 0.2969-0.7227 0.5293-1.1953 0.6972-0.4688 0.1641-1.0196 0.2461-1.6524 0.2461h-0.1289v-1.166zm11.494-3.8672v1.3946c0 0.6679-0.0664 1.2382-0.1993 1.7109-0.1289 0.4688-0.3164 0.8496-0.5625 1.1426-0.246 0.293-0.541 0.5078-0.8847 0.6445-0.3399 0.1367-0.7207 0.2051-1.1426 0.2051-0.3359 0-0.6484-0.043-0.9375-0.1289-0.2852-0.086-0.543-0.2207-0.7734-0.4043-0.2305-0.1836-0.4278-0.4199-0.5918-0.709-0.1602-0.293-0.2852-0.6426-0.375-1.0488-0.086-0.4063-0.1289-0.877-0.1289-1.4121v-1.3946c0-0.6718 0.0664-1.2382 0.1992-1.6992 0.1328-0.4648 0.3222-0.8418 0.5683-1.1308 0.2461-0.293 0.5391-0.5059 0.8789-0.6387 0.3438-0.1328 0.7266-0.1992 1.1485-0.1992 0.3398 0 0.6523 0.0429 0.9375 0.1289 0.289 0.082 0.5469 0.2129 0.7734 0.3926 0.2305 0.1796 0.4258 0.414 0.586 0.7031 0.164 0.2851 0.289 0.6308 0.375 1.0371 0.0859 0.4023 0.1289 0.8711 0.1289 1.4062zm-1.4121 1.5938v-1.8047c0-0.3398-0.0196-0.6387-0.0586-0.8965-0.0391-0.2617-0.0977-0.4824-0.1758-0.6621-0.0742-0.1836-0.168-0.332-0.2813-0.4453-0.1132-0.1172-0.2422-0.2012-0.3867-0.252-0.1445-0.0546-0.3066-0.082-0.4863-0.082-0.2188 0-0.4141 0.043-0.586 0.1289-0.1718 0.082-0.3164 0.2149-0.4335 0.3985-0.1172 0.1835-0.2071 0.4257-0.2696 0.7265-0.0586 0.2969-0.0879 0.6582-0.0879 1.084v1.8047c0 0.3437 0.0196 0.6465 0.0586 0.9082 0.0391 0.2617 0.0977 0.4863 0.1758 0.6738 0.0781 0.1836 0.1719 0.336 0.2813 0.457 0.1132 0.1172 0.2421 0.2032 0.3867 0.2579 0.1484 0.0546 0.3105 0.082 0.4863 0.082 0.2227 0 0.4199-0.043 0.5918-0.1289 0.1719-0.086 0.3164-0.2227 0.4336-0.4102 0.1172-0.1914 0.2051-0.4394 0.2637-0.7441s0.0879-0.6699 0.0879-1.0957z" fill="#000" fill-opacity=".38"/>
<path d="m36.332 81.274c0 0.5313-0.123 0.9785-0.3691 1.3418s-0.582 0.6387-1.0078 0.8262c-0.4219 0.1836-0.8985 0.2754-1.4297 0.2754-0.5313 0-1.0098-0.0918-1.4356-0.2754-0.4257-0.1875-0.7617-0.4629-1.0078-0.8262s-0.3691-0.8105-0.3691-1.3418c0-0.3515 0.0683-0.6699 0.2051-0.9551 0.1367-0.289 0.33-0.5371 0.58-0.7441 0.254-0.2109 0.5508-0.373 0.8907-0.4863 0.3437-0.1133 0.7187-0.1699 1.125-0.1699 0.539 0 1.0215 0.0996 1.4472 0.2988 0.4258 0.1992 0.7598 0.4746 1.002 0.8262 0.2461 0.3515 0.3691 0.7617 0.3691 1.2304zm-1.4179-0.0703c0-0.2851-0.0586-0.5351-0.1758-0.75-0.1172-0.2148-0.2813-0.3808-0.4922-0.498s-0.4551-0.1758-0.7324-0.1758c-0.2813 0-0.5254 0.0586-0.7325 0.1758-0.207 0.1172-0.3691 0.2832-0.4863 0.498-0.1133 0.2149-0.1699 0.4649-0.1699 0.75 0 0.2891 0.0566 0.5391 0.1699 0.75 0.1133 0.207 0.2754 0.3652 0.4863 0.4746 0.211 0.1094 0.459 0.1641 0.7442 0.1641 0.2851 0 0.5312-0.0547 0.7383-0.1641 0.207-0.1094 0.3672-0.2676 0.4804-0.4746 0.1133-0.2109 0.17-0.4609 0.17-0.75zm1.2246-3.8906c0 0.4258-0.1133 0.8047-0.3399 1.1367-0.2226 0.332-0.5312 0.5938-0.9258 0.7852-0.3945 0.1875-0.8437 0.2812-1.3476 0.2812-0.5078 0-0.9609-0.0937-1.3594-0.2812-0.3945-0.1914-0.7051-0.4532-0.9316-0.7852-0.2227-0.332-0.334-0.7109-0.334-1.1367 0-0.5078 0.1113-0.9356 0.334-1.2832 0.2265-0.3516 0.5371-0.6192 0.9316-0.8027 0.3945-0.1836 0.8457-0.2754 1.3535-0.2754s0.959 0.0918 1.3535 0.2754c0.3946 0.1835 0.7032 0.4511 0.9258 0.8027 0.2266 0.3476 0.3399 0.7754 0.3399 1.2832zm-1.4121 0.0469c0-0.2539-0.0508-0.4766-0.1524-0.668-0.0976-0.1953-0.2363-0.3477-0.416-0.457-0.1797-0.1094-0.3926-0.1641-0.6387-0.1641s-0.459 0.0527-0.6386 0.1582c-0.1797 0.1055-0.3184 0.2539-0.4161 0.4453-0.0976 0.1914-0.1464 0.4199-0.1464 0.6856 0 0.2617 0.0488 0.4902 0.1464 0.6855 0.0977 0.1914 0.2364 0.3418 0.4161 0.4512 0.1836 0.1094 0.3984 0.164 0.6445 0.164s0.459-0.0546 0.6387-0.164 0.3183-0.2598 0.416-0.4512c0.0976-0.1953 0.1465-0.4238 0.1465-0.6855zm8.6582 1.2597v1.3946c0 0.6679-0.0664 1.2382-0.1993 1.7109-0.1289 0.4687-0.3164 0.8496-0.5625 1.1426-0.246 0.2929-0.541 0.5078-0.8847 0.6445-0.3399 0.1367-0.7207 0.2051-1.1426 0.2051-0.3359 0-0.6484-0.043-0.9375-0.1289-0.2852-0.086-0.543-0.2207-0.7734-0.4043-0.2305-0.1836-0.4278-0.4199-0.5918-0.709-0.1602-0.293-0.2852-0.6426-0.375-1.0488-0.086-0.4063-0.1289-0.877-0.1289-1.4121v-1.3946c0-0.6718 0.0664-1.2383 0.1992-1.6992 0.1328-0.4648 0.3222-0.8418 0.5683-1.1308 0.2461-0.293 0.5391-0.5059 0.8789-0.6387 0.3438-0.1328 0.7266-0.1992 1.1485-0.1992 0.3398 0 0.6523 0.0429 0.9375 0.1289 0.289 0.082 0.5469 0.2129 0.7734 0.3925 0.2305 0.1797 0.4258 0.4141 0.586 0.7032 0.164 0.2851 0.289 0.6308 0.375 1.0371 0.0859 0.4023 0.1289 0.8711 0.1289 1.4062zm-1.4121 1.5938v-1.8047c0-0.3399-0.0196-0.6387-0.0586-0.8965-0.0391-0.2617-0.0977-0.4824-0.1758-0.6621-0.0742-0.1836-0.168-0.332-0.2813-0.4453-0.1132-0.1172-0.2422-0.2012-0.3867-0.252-0.1445-0.0547-0.3066-0.082-0.4863-0.082-0.2188 0-0.4141 0.043-0.586 0.1289-0.1718 0.082-0.3164 0.2149-0.4335 0.3984-0.1172 0.1836-0.2071 0.4258-0.2696 0.7266-0.0586 0.2969-0.0879 0.6582-0.0879 1.084v1.8047c0 0.3437 0.0196 0.6465 0.0586 0.9082 0.0391 0.2617 0.0977 0.4863 0.1758 0.6738 0.0781 0.1836 0.1719 0.3359 0.2813 0.457 0.1132 0.1172 0.2421 0.2032 0.3867 0.2579 0.1484 0.0546 0.3105 0.082 0.4863 0.082 0.2227 0 0.4199-0.043 0.5918-0.1289 0.1719-0.086 0.3164-0.2227 0.4336-0.4102 0.1172-0.1914 0.2051-0.4394 0.2637-0.7441s0.0879-0.6699 0.0879-1.0957z" fill="#000" fill-opacity=".38"/>
<path d="m36.42 107.37v0.773l-3.4101 7.758h-1.4883l3.4043-7.406h-4.418v-1.125h5.9121zm6.9649 3.55v1.395c0 0.668-0.0664 1.238-0.1993 1.711-0.1289 0.469-0.3164 0.85-0.5625 1.142-0.246 0.293-0.541 0.508-0.8847 0.645-0.3399 0.137-0.7207 0.205-1.1426 0.205-0.3359 0-0.6484-0.043-0.9375-0.129-0.2852-0.086-0.543-0.221-0.7734-0.404-0.2305-0.184-0.4278-0.42-0.5918-0.709-0.1602-0.293-0.2852-0.643-0.375-1.049-0.086-0.406-0.1289-0.877-0.1289-1.412v-1.395c0-0.671 0.0664-1.238 0.1992-1.699 0.1328-0.465 0.3222-0.842 0.5683-1.131 0.2461-0.293 0.5391-0.506 0.8789-0.638 0.3438-0.133 0.7266-0.2 1.1485-0.2 0.3398 0 0.6523 0.043 0.9375 0.129 0.289 0.082 0.5469 0.213 0.7734 0.393 0.2305 0.18 0.4258 0.414 0.586 0.703 0.164 0.285 0.289 0.631 0.375 1.037 0.0859 0.403 0.1289 0.871 0.1289 1.406zm-1.4121 1.594v-1.805c0-0.339-0.0196-0.638-0.0586-0.896-0.0391-0.262-0.0977-0.482-0.1758-0.662-0.0742-0.184-0.168-0.332-0.2813-0.445-0.1132-0.118-0.2422-0.202-0.3867-0.252-0.1445-0.055-0.3066-0.082-0.4863-0.082-0.2188 0-0.4141 0.043-0.586 0.129-0.1718 0.082-0.3164 0.214-0.4335 0.398-0.1172 0.184-0.2071 0.426-0.2696 0.727-0.0586 0.296-0.0879 0.658-0.0879 1.083v1.805c0 0.344 0.0196 0.647 0.0586 0.908 0.0391 0.262 0.0977 0.487 0.1758 0.674 0.0781 0.184 0.1719 0.336 0.2813 0.457 0.1132 0.117 0.2421 0.203 0.3867 0.258 0.1484 0.055 0.3105 0.082 0.4863 0.082 0.2227 0 0.4199-0.043 0.5918-0.129s0.3164-0.222 0.4336-0.41c0.1172-0.191 0.2051-0.439 0.2637-0.744s0.0879-0.67 0.0879-1.096z" fill="#000" fill-opacity=".38"/>
<path d="m35.02 139.62h0.1758v1.155h-0.0996c-0.5039 0-0.9395 0.078-1.3066 0.234-0.3633 0.156-0.6621 0.371-0.8965 0.644-0.2344 0.274-0.4102 0.594-0.5274 0.961-0.1132 0.364-0.1699 0.75-0.1699 1.161v1.341c0 0.34 0.0371 0.641 0.1113 0.903 0.0743 0.257 0.1778 0.474 0.3106 0.65 0.1367 0.172 0.293 0.303 0.4687 0.393 0.1758 0.089 0.3653 0.134 0.5684 0.134 0.2109 0 0.4023-0.043 0.5742-0.129 0.1719-0.089 0.3184-0.212 0.4395-0.369 0.1211-0.156 0.2129-0.341 0.2754-0.556s0.0937-0.45 0.0937-0.703c0-0.243-0.0312-0.469-0.0937-0.68-0.0586-0.215-0.1465-0.402-0.2637-0.563-0.1172-0.164-0.2637-0.291-0.4395-0.38-0.1718-0.094-0.3711-0.141-0.5976-0.141-0.2813 0-0.5371 0.066-0.7676 0.199-0.2266 0.133-0.4102 0.307-0.5508 0.522-0.1367 0.211-0.2109 0.435-0.2226 0.673l-0.5391-0.175c0.0313-0.364 0.1113-0.69 0.2402-0.979 0.1328-0.289 0.3067-0.535 0.5215-0.738 0.2149-0.203 0.4629-0.358 0.7442-0.463 0.2851-0.109 0.5976-0.164 0.9375-0.164 0.414 0 0.7734 0.078 1.0781 0.234 0.3047 0.157 0.5566 0.369 0.7558 0.639 0.2032 0.266 0.3536 0.57 0.4512 0.914 0.1016 0.34 0.1524 0.695 0.1524 1.066 0 0.411-0.0625 0.793-0.1875 1.149-0.125 0.351-0.3086 0.66-0.5508 0.926-0.2383 0.265-0.5293 0.472-0.8731 0.621-0.3398 0.148-0.7265 0.222-1.1601 0.222-0.4571 0-0.8653-0.088-1.2246-0.263-0.3555-0.176-0.6582-0.418-0.9082-0.727-0.2461-0.308-0.4336-0.664-0.5625-1.066-0.1289-0.403-0.1934-0.828-0.1934-1.278v-0.586c0-0.648 0.082-1.259 0.2461-1.834 0.1641-0.578 0.416-1.087 0.7559-1.529 0.3437-0.441 0.7832-0.787 1.3183-1.037 0.5352-0.254 1.1738-0.381 1.916-0.381zm8.3653 3.604v1.394c0 0.668-0.0664 1.239-0.1993 1.711-0.1289 0.469-0.3164 0.85-0.5625 1.143-0.246 0.293-0.541 0.508-0.8847 0.644-0.3399 0.137-0.7207 0.205-1.1426 0.205-0.3359 0-0.6484-0.043-0.9375-0.129-0.2852-0.085-0.543-0.22-0.7734-0.404-0.2305-0.183-0.4278-0.42-0.5918-0.709-0.1602-0.293-0.2852-0.642-0.375-1.049-0.086-0.406-0.1289-0.877-0.1289-1.412v-1.394c0-0.672 0.0664-1.239 0.1992-1.699 0.1328-0.465 0.3222-0.842 0.5683-1.131 0.2461-0.293 0.5391-0.506 0.8789-0.639 0.3438-0.133 0.7266-0.199 1.1485-0.199 0.3398 0 0.6523 0.043 0.9375 0.129 0.289 0.082 0.5469 0.213 0.7734 0.392 0.2305 0.18 0.4258 0.414 0.586 0.703 0.164 0.286 0.289 0.631 0.375 1.037 0.0859 0.403 0.1289 0.872 0.1289 1.407zm-1.4121 1.593v-1.804c0-0.34-0.0196-0.639-0.0586-0.897-0.0391-0.261-0.0977-0.482-0.1758-0.662-0.0742-0.183-0.168-0.332-0.2813-0.445-0.1132-0.117-0.2422-0.201-0.3867-0.252-0.1445-0.055-0.3066-0.082-0.4863-0.082-0.2188 0-0.4141 0.043-0.586 0.129-0.1718 0.082-0.3164 0.215-0.4335 0.398-0.1172 0.184-0.2071 0.426-0.2696 0.727-0.0586 0.297-0.0879 0.658-0.0879 1.084v1.804c0 0.344 0.0196 0.647 0.0586 0.909 0.0391 0.261 0.0977 0.486 0.1758 0.674 0.0781 0.183 0.1719 0.335 0.2813 0.457 0.1132 0.117 0.2421 0.203 0.3867 0.257 0.1484 0.055 0.3105 0.082 0.4863 0.082 0.2227 0 0.4199-0.043 0.5918-0.129 0.1719-0.085 0.3164-0.222 0.4336-0.41 0.1172-0.191 0.2051-0.439 0.2637-0.744s0.0879-0.67 0.0879-1.096z" fill="#000" fill-opacity=".38"/>
<path d="m32.236 176.53-1.125-0.275 0.4629-4.289h4.5996v1.195h-3.4277l-0.2344 2.092c0.1328-0.078 0.3164-0.154 0.5508-0.229 0.2344-0.078 0.502-0.117 0.8027-0.117 0.4024 0 0.7618 0.067 1.0782 0.199 0.3203 0.129 0.5918 0.319 0.8144 0.569 0.2227 0.246 0.3926 0.547 0.5098 0.902 0.1172 0.352 0.1758 0.748 0.1758 1.19 0 0.394-0.0586 0.763-0.1758 1.107-0.1133 0.344-0.2852 0.646-0.5156 0.908-0.2305 0.262-0.5215 0.467-0.8731 0.615-0.3477 0.145-0.7598 0.217-1.2363 0.217-0.3555 0-0.6973-0.051-1.0254-0.152-0.3242-0.106-0.6152-0.26-0.8731-0.463-0.2578-0.207-0.4648-0.461-0.6211-0.762-0.1562-0.304-0.246-0.654-0.2695-1.049h1.3828c0.0352 0.278 0.1114 0.514 0.2285 0.709 0.1211 0.192 0.2813 0.338 0.4805 0.44 0.1992 0.101 0.4297 0.152 0.6914 0.152 0.2383 0 0.4434-0.041 0.6153-0.123 0.1718-0.086 0.3144-0.207 0.4277-0.363 0.1172-0.16 0.2031-0.348 0.2578-0.563 0.0586-0.214 0.0879-0.453 0.0879-0.714 0-0.25-0.0332-0.479-0.0996-0.686-0.0625-0.207-0.1582-0.387-0.2871-0.539-0.125-0.152-0.2832-0.27-0.4746-0.352-0.1914-0.086-0.4121-0.129-0.6621-0.129-0.336 0-0.5938 0.049-0.7735 0.147-0.1758 0.098-0.3398 0.219-0.4922 0.363zm11.148-1.013v1.394c0 0.668-0.0664 1.238-0.1993 1.711-0.1289 0.469-0.3164 0.85-0.5625 1.143-0.246 0.293-0.541 0.507-0.8847 0.644-0.3399 0.137-0.7207 0.205-1.1426 0.205-0.3359 0-0.6484-0.043-0.9375-0.129-0.2852-0.086-0.543-0.22-0.7734-0.404-0.2305-0.184-0.4278-0.42-0.5918-0.709-0.1602-0.293-0.2852-0.643-0.375-1.049-0.086-0.406-0.1289-0.877-0.1289-1.412v-1.394c0-0.672 0.0664-1.239 0.1992-1.7 0.1328-0.465 0.3222-0.841 0.5683-1.131 0.2461-0.293 0.5391-0.505 0.8789-0.638 0.3438-0.133 0.7266-0.199 1.1485-0.199 0.3398 0 0.6523 0.043 0.9375 0.128 0.289 0.082 0.5469 0.213 0.7734 0.393 0.2305 0.18 0.4258 0.414 0.586 0.703 0.164 0.285 0.289 0.631 0.375 1.037 0.0859 0.403 0.1289 0.871 0.1289 1.407zm-1.4121 1.593v-1.804c0-0.34-0.0196-0.639-0.0586-0.897-0.0391-0.262-0.0977-0.482-0.1758-0.662-0.0742-0.184-0.168-0.332-0.2813-0.445-0.1132-0.117-0.2422-0.201-0.3867-0.252-0.1445-0.055-0.3066-0.082-0.4863-0.082-0.2188 0-0.4141 0.043-0.586 0.129-0.1718 0.082-0.3164 0.214-0.4335 0.398-0.1172 0.184-0.2071 0.426-0.2696 0.727-0.0586 0.296-0.0879 0.658-0.0879 1.084v1.804c0 0.344 0.0196 0.647 0.0586 0.908 0.0391 0.262 0.0977 0.487 0.1758 0.674 0.0781 0.184 0.1719 0.336 0.2813 0.457 0.1132 0.118 0.2421 0.203 0.3867 0.258 0.1484 0.055 0.3105 0.082 0.4863 0.082 0.2227 0 0.4199-0.043 0.5918-0.129s0.3164-0.222 0.4336-0.41c0.1172-0.191 0.2051-0.439 0.2637-0.744s0.0879-0.67 0.0879-1.096z" fill="#000" fill-opacity=".38"/>
<path d="m36.631 209.76v1.125h-6.1524l-0.0469-0.85 3.6797-5.765h1.1309l-1.2246 2.097-2.1153 3.393h4.7286zm-1.0664-5.49v8.531h-1.4122v-8.531h1.4122zm7.8203 3.55v1.395c0 0.668-0.0664 1.238-0.1993 1.711-0.1289 0.469-0.3164 0.849-0.5625 1.142-0.246 0.293-0.541 0.508-0.8847 0.645-0.3399 0.137-0.7207 0.205-1.1426 0.205-0.3359 0-0.6484-0.043-0.9375-0.129-0.2852-0.086-0.543-0.221-0.7734-0.404-0.2305-0.184-0.4278-0.42-0.5918-0.709-0.1602-0.293-0.2852-0.643-0.375-1.049-0.086-0.406-0.1289-0.877-0.1289-1.412v-1.395c0-0.672 0.0664-1.238 0.1992-1.699 0.1328-0.465 0.3222-0.842 0.5683-1.131 0.2461-0.293 0.5391-0.506 0.8789-0.638 0.3438-0.133 0.7266-0.2 1.1485-0.2 0.3398 0 0.6523 0.043 0.9375 0.129 0.289 0.082 0.5469 0.213 0.7734 0.393 0.2305 0.18 0.4258 0.414 0.586 0.703 0.164 0.285 0.289 0.631 0.375 1.037 0.0859 0.402 0.1289 0.871 0.1289 1.406zm-1.4121 1.594v-1.805c0-0.339-0.0196-0.638-0.0586-0.896-0.0391-0.262-0.0977-0.483-0.1758-0.662-0.0742-0.184-0.168-0.332-0.2813-0.446-0.1132-0.117-0.2422-0.201-0.3867-0.251-0.1445-0.055-0.3066-0.082-0.4863-0.082-0.2188 0-0.4141 0.042-0.586 0.128-0.1718 0.082-0.3164 0.215-0.4335 0.399-0.1172 0.183-0.2071 0.426-0.2696 0.726-0.0586 0.297-0.0879 0.659-0.0879 1.084v1.805c0 0.344 0.0196 0.647 0.0586 0.908 0.0391 0.262 0.0977 0.487 0.1758 0.674 0.0781 0.184 0.1719 0.336 0.2813 0.457 0.1132 0.117 0.2421 0.203 0.3867 0.258 0.1484 0.055 0.3105 0.082 0.4863 0.082 0.2227 0 0.4199-0.043 0.5918-0.129s0.3164-0.223 0.4336-0.41c0.1172-0.191 0.2051-0.44 0.2637-0.744 0.0586-0.305 0.0879-0.67 0.0879-1.096z" fill="#000" fill-opacity=".38"/>
<path d="m32.412 240.2h0.8438c0.3281 0 0.5996-0.057 0.8144-0.17 0.2188-0.113 0.3809-0.27 0.4863-0.469 0.1055-0.199 0.1582-0.428 0.1582-0.685 0-0.27-0.0488-0.5-0.1464-0.692-0.0938-0.195-0.2383-0.346-0.4336-0.451-0.1914-0.105-0.4356-0.158-0.7325-0.158-0.25 0-0.4765 0.051-0.6796 0.152-0.1993 0.098-0.3575 0.238-0.4747 0.422-0.1171 0.18-0.1757 0.395-0.1757 0.645h-1.418c0-0.454 0.1191-0.856 0.3574-1.207 0.2383-0.352 0.5625-0.627 0.9727-0.827 0.414-0.203 0.8789-0.304 1.3945-0.304 0.5508 0 1.0313 0.091 1.4414 0.275 0.4141 0.18 0.7363 0.449 0.9668 0.809 0.2305 0.359 0.3457 0.804 0.3457 1.336 0 0.242-0.0566 0.488-0.1699 0.738s-0.2813 0.478-0.5039 0.685c-0.2227 0.204-0.5 0.37-0.832 0.498-0.3321 0.125-0.7168 0.188-1.1543 0.188h-1.0606v-0.785zm0 1.101v-0.773h1.0606c0.5 0 0.9257 0.059 1.2773 0.176 0.3555 0.117 0.6445 0.279 0.8672 0.486 0.2226 0.203 0.3848 0.436 0.4863 0.697 0.1055 0.262 0.1582 0.539 0.1582 0.832 0 0.399-0.0722 0.754-0.2168 1.067-0.1406 0.308-0.3418 0.57-0.6035 0.785s-0.5684 0.377-0.9199 0.486c-0.3477 0.11-0.7266 0.164-1.1367 0.164-0.3672 0-0.7188-0.05-1.0547-0.152-0.336-0.102-0.6367-0.252-0.9024-0.451-0.2656-0.203-0.4765-0.455-0.6328-0.756-0.1523-0.305-0.2285-0.656-0.2285-1.055h1.4121c0 0.254 0.0586 0.479 0.1758 0.674 0.1211 0.191 0.2891 0.342 0.5039 0.451 0.2188 0.11 0.4688 0.164 0.75 0.164 0.2969 0 0.5527-0.052 0.7676-0.158 0.2148-0.105 0.3789-0.262 0.4922-0.469 0.1172-0.207 0.1758-0.457 0.1758-0.75 0-0.332-0.0645-0.601-0.1934-0.808s-0.3125-0.36-0.5508-0.457c-0.2383-0.102-0.5195-0.153-0.8437-0.153h-0.8438zm10.973-1.177v1.394c0 0.668-0.0664 1.238-0.1993 1.711-0.1289 0.469-0.3164 0.85-0.5625 1.143-0.246 0.293-0.541 0.507-0.8847 0.644-0.3399 0.137-0.7207 0.205-1.1426 0.205-0.3359 0-0.6484-0.043-0.9375-0.129-0.2852-0.086-0.543-0.22-0.7734-0.404-0.2305-0.184-0.4278-0.42-0.5918-0.709-0.1602-0.293-0.2852-0.642-0.375-1.049-0.086-0.406-0.1289-0.877-0.1289-1.412v-1.394c0-0.672 0.0664-1.239 0.1992-1.7 0.1328-0.464 0.3222-0.841 0.5683-1.13 0.2461-0.293 0.5391-0.506 0.8789-0.639 0.3438-0.133 0.7266-0.199 1.1485-0.199 0.3398 0 0.6523 0.043 0.9375 0.129 0.289 0.082 0.5469 0.212 0.7734 0.392 0.2305 0.18 0.4258 0.414 0.586 0.703 0.164 0.285 0.289 0.631 0.375 1.037 0.0859 0.403 0.1289 0.871 0.1289 1.407zm-1.4121 1.593v-1.804c0-0.34-0.0196-0.639-0.0586-0.897-0.0391-0.262-0.0977-0.482-0.1758-0.662-0.0742-0.183-0.168-0.332-0.2813-0.445-0.1132-0.117-0.2422-0.201-0.3867-0.252-0.1445-0.055-0.3066-0.082-0.4863-0.082-0.2188 0-0.4141 0.043-0.586 0.129-0.1718 0.082-0.3164 0.215-0.4335 0.398-0.1172 0.184-0.2071 0.426-0.2696 0.727-0.0586 0.297-0.0879 0.658-0.0879 1.084v1.804c0 0.344 0.0196 0.647 0.0586 0.909 0.0391 0.261 0.0977 0.486 0.1758 0.673 0.0781 0.184 0.1719 0.336 0.2813 0.457 0.1132 0.118 0.2421 0.204 0.3867 0.258 0.1484 0.055 0.3105 0.082 0.4863 0.082 0.2227 0 0.4199-0.043 0.5918-0.129s0.3164-0.222 0.4336-0.41c0.1172-0.191 0.2051-0.439 0.2637-0.744s0.0879-0.67 0.0879-1.096z" fill="#000" fill-opacity=".38"/>
<path d="m36.473 276.28v1.125h-5.7188v-0.967l2.7773-3.029c0.3047-0.344 0.545-0.641 0.7208-0.891 0.1757-0.25 0.2988-0.474 0.3691-0.674 0.0742-0.203 0.1113-0.4 0.1113-0.591 0-0.27-0.0508-0.506-0.1523-0.709-0.0977-0.207-0.2422-0.37-0.4336-0.487-0.1914-0.121-0.4238-0.181-0.6973-0.181-0.3164 0-0.582 0.068-0.7969 0.205-0.2148 0.136-0.3769 0.326-0.4863 0.568-0.1094 0.238-0.164 0.512-0.164 0.82h-1.4122c0-0.496 0.1133-0.949 0.3399-1.359 0.2265-0.414 0.5547-0.742 0.9844-0.984 0.4297-0.246 0.9472-0.37 1.5527-0.37 0.5703 0 1.0547 0.096 1.4531 0.288 0.3985 0.191 0.7012 0.462 0.9082 0.814 0.211 0.352 0.3164 0.768 0.3164 1.248 0 0.266-0.0429 0.529-0.1289 0.791-0.0859 0.262-0.209 0.524-0.3691 0.785-0.1563 0.258-0.3418 0.518-0.5567 0.78-0.2148 0.257-0.4511 0.519-0.7089 0.785l-1.8457 2.033h3.9375zm6.9121-3.856v1.395c0 0.668-0.0664 1.238-0.1993 1.711-0.1289 0.469-0.3164 0.85-0.5625 1.142-0.246 0.293-0.541 0.508-0.8847 0.645-0.3399 0.137-0.7207 0.205-1.1426 0.205-0.3359 0-0.6484-0.043-0.9375-0.129-0.2852-0.086-0.543-0.221-0.7734-0.404-0.2305-0.184-0.4278-0.42-0.5918-0.709-0.1602-0.293-0.2852-0.643-0.375-1.049-0.086-0.406-0.1289-0.877-0.1289-1.412v-1.395c0-0.671 0.0664-1.238 0.1992-1.699 0.1328-0.465 0.3222-0.842 0.5683-1.131 0.2461-0.293 0.5391-0.506 0.8789-0.638 0.3438-0.133 0.7266-0.2 1.1485-0.2 0.3398 0 0.6523 0.043 0.9375 0.129 0.289 0.082 0.5469 0.213 0.7734 0.393 0.2305 0.18 0.4258 0.414 0.586 0.703 0.164 0.285 0.289 0.631 0.375 1.037 0.0859 0.403 0.1289 0.871 0.1289 1.406zm-1.4121 1.594v-1.805c0-0.339-0.0196-0.638-0.0586-0.896-0.0391-0.262-0.0977-0.482-0.1758-0.662-0.0742-0.184-0.168-0.332-0.2813-0.445-0.1132-0.118-0.2422-0.202-0.3867-0.252-0.1445-0.055-0.3066-0.082-0.4863-0.082-0.2188 0-0.4141 0.043-0.586 0.129-0.1718 0.082-0.3164 0.214-0.4335 0.398-0.1172 0.184-0.2071 0.426-0.2696 0.727-0.0586 0.296-0.0879 0.658-0.0879 1.083v1.805c0 0.344 0.0196 0.647 0.0586 0.908 0.0391 0.262 0.0977 0.487 0.1758 0.674 0.0781 0.184 0.1719 0.336 0.2813 0.457 0.1132 0.117 0.2421 0.203 0.3867 0.258 0.1484 0.055 0.3105 0.082 0.4863 0.082 0.2227 0 0.4199-0.043 0.5918-0.129s0.3164-0.222 0.4336-0.41c0.1172-0.191 0.2051-0.439 0.2637-0.744s0.0879-0.67 0.0879-1.096z" fill="#000" fill-opacity=".38"/>
<path d="m34.609 301.14v8.56h-1.4121v-6.885l-2.0918 0.709v-1.166l3.334-1.218h0.1699zm8.7754 3.58v1.394c0 0.668-0.0664 1.239-0.1993 1.711-0.1289 0.469-0.3164 0.85-0.5625 1.143-0.246 0.293-0.541 0.508-0.8847 0.644-0.3399 0.137-0.7207 0.205-1.1426 0.205-0.3359 0-0.6484-0.043-0.9375-0.129-0.2852-0.085-0.543-0.22-0.7734-0.404-0.2305-0.183-0.4278-0.42-0.5918-0.709-0.1602-0.293-0.2852-0.642-0.375-1.049-0.086-0.406-0.1289-0.877-0.1289-1.412v-1.394c0-0.672 0.0664-1.239 0.1992-1.699 0.1328-0.465 0.3222-0.842 0.5683-1.131 0.2461-0.293 0.5391-0.506 0.8789-0.639 0.3438-0.133 0.7266-0.199 1.1485-0.199 0.3398 0 0.6523 0.043 0.9375 0.129 0.289 0.082 0.5469 0.213 0.7734 0.392 0.2305 0.18 0.4258 0.414 0.586 0.703 0.164 0.286 0.289 0.631 0.375 1.037 0.0859 0.403 0.1289 0.872 0.1289 1.407zm-1.4121 1.593v-1.804c0-0.34-0.0196-0.639-0.0586-0.897-0.0391-0.261-0.0977-0.482-0.1758-0.662-0.0742-0.183-0.168-0.332-0.2813-0.445-0.1132-0.117-0.2422-0.201-0.3867-0.252-0.1445-0.055-0.3066-0.082-0.4863-0.082-0.2188 0-0.4141 0.043-0.586 0.129-0.1718 0.082-0.3164 0.215-0.4335 0.398-0.1172 0.184-0.2071 0.426-0.2696 0.727-0.0586 0.297-0.0879 0.658-0.0879 1.084v1.804c0 0.344 0.0196 0.647 0.0586 0.909 0.0391 0.261 0.0977 0.486 0.1758 0.674 0.0781 0.183 0.1719 0.335 0.2813 0.457 0.1132 0.117 0.2421 0.203 0.3867 0.257 0.1484 0.055 0.3105 0.082 0.4863 0.082 0.2227 0 0.4199-0.043 0.5918-0.129 0.1719-0.085 0.3164-0.222 0.4336-0.41 0.1172-0.191 0.2051-0.439 0.2637-0.744s0.0879-0.67 0.0879-1.096z" fill="#000" fill-opacity=".38"/>
<path d="m43.385 337.02v1.394c0 0.668-0.0664 1.238-0.1993 1.711-0.1289 0.469-0.3164 0.85-0.5625 1.143-0.246 0.293-0.541 0.507-0.8847 0.644-0.3399 0.137-0.7207 0.205-1.1426 0.205-0.3359 0-0.6484-0.043-0.9375-0.129-0.2852-0.086-0.543-0.22-0.7734-0.404-0.2305-0.184-0.4278-0.42-0.5918-0.709-0.1602-0.293-0.2852-0.643-0.375-1.049-0.086-0.406-0.1289-0.877-0.1289-1.412v-1.394c0-0.672 0.0664-1.239 0.1992-1.7 0.1328-0.465 0.3222-0.841 0.5683-1.131 0.2461-0.293 0.5391-0.505 0.8789-0.638 0.3438-0.133 0.7266-0.199 1.1485-0.199 0.3398 0 0.6523 0.043 0.9375 0.128 0.289 0.082 0.5469 0.213 0.7734 0.393 0.2305 0.18 0.4258 0.414 0.586 0.703 0.164 0.285 0.289 0.631 0.375 1.037 0.0859 0.403 0.1289 0.871 0.1289 1.407zm-1.4121 1.593v-1.804c0-0.34-0.0196-0.639-0.0586-0.897-0.0391-0.262-0.0977-0.482-0.1758-0.662-0.0742-0.184-0.168-0.332-0.2813-0.445-0.1132-0.117-0.2422-0.201-0.3867-0.252-0.1445-0.055-0.3066-0.082-0.4863-0.082-0.2188 0-0.4141 0.043-0.586 0.129-0.1718 0.082-0.3164 0.214-0.4335 0.398-0.1172 0.184-0.2071 0.426-0.2696 0.727-0.0586 0.296-0.0879 0.658-0.0879 1.084v1.804c0 0.344 0.0196 0.647 0.0586 0.908 0.0391 0.262 0.0977 0.487 0.1758 0.674 0.0781 0.184 0.1719 0.336 0.2813 0.457 0.1132 0.118 0.2421 0.203 0.3867 0.258 0.1484 0.055 0.3105 0.082 0.4863 0.082 0.2227 0 0.4199-0.043 0.5918-0.129s0.3164-0.222 0.4336-0.41c0.1172-0.191 0.2051-0.439 0.2637-0.744s0.0879-0.67 0.0879-1.096z" fill="#000" fill-opacity=".38"/>
<path d="m63 10v329h1v-329z" fill="#747474" style="stroke-width:.70711"/>
<line x1="52" x2="64" y1="10.5" y2="10.5" stroke="#747474"/>
<line x1="58" x2="64" y1="13.79" y2="13.79" stroke="#747474"/>
<line x1="58" x2="64" y1="17.08" y2="17.08" stroke="#747474"/>
<line x1="58" x2="64" y1="20.37" y2="20.37" stroke="#747474"/>
<line x1="58" x2="64" y1="23.66" y2="23.66" stroke="#747474"/>
<line x1="58" x2="64" y1="26.95" y2="26.95" stroke="#747474"/>
<line x1="58" x2="64" y1="30.24" y2="30.24" stroke="#747474"/>
<line x1="58" x2="64" y1="33.53" y2="33.53" stroke="#747474"/>
<line x1="58" x2="64" y1="36.82" y2="36.82" stroke="#747474"/>
<line x1="58" x2="64" y1="40.11" y2="40.11" stroke="#747474"/>
<line x1="52" x2="64" y1="43.4" y2="43.4" stroke="#747474"/>
<line x1="58" x2="64" y1="46.69" y2="46.69" stroke="#747474"/>
<line x1="58" x2="64" y1="49.98" y2="49.98" stroke="#747474"/>
<line x1="58" x2="64" y1="53.27" y2="53.27" stroke="#747474"/>
<line x1="58" x2="64" y1="56.56" y2="56.56" stroke="#747474"/>
<line x1="58" x2="64" y1="59.85" y2="59.85" stroke="#747474"/>
<line x1="58" x2="64" y1="63.14" y2="63.14" stroke="#747474"/>
<line x1="58" x2="64" y1="66.43" y2="66.43" stroke="#747474"/>
<line x1="58" x2="64" y1="69.72" y2="69.72" stroke="#747474"/>
<line x1="58" x2="64" y1="73.01" y2="73.01" stroke="#747474"/>
<line x1="52" x2="64" y1="76.3" y2="76.3" stroke="#747474"/>
<line x1="58" x2="64" y1="79.59" y2="79.59" stroke="#747474"/>
<line x1="58" x2="64" y1="82.88" y2="82.88" stroke="#747474"/>
<line x1="58" x2="64" y1="86.17" y2="86.17" stroke="#747474"/>
<line x1="58" x2="64" y1="89.46" y2="89.46" stroke="#747474"/>
<line x1="58" x2="64" y1="92.75" y2="92.75" stroke="#747474"/>
<line x1="58" x2="64" y1="96.04" y2="96.04" stroke="#747474"/>
<line x1="58" x2="64" y1="99.33" y2="99.33" stroke="#747474"/>
<line x1="58" x2="64" y1="102.62" y2="102.62" stroke="#747474"/>
<line x1="58" x2="64" y1="105.91" y2="105.91" stroke="#747474"/>
<line x1="52" x2="64" y1="109.2" y2="109.2" stroke="#747474"/>
<line x1="58" x2="64" y1="112.49" y2="112.49" stroke="#747474"/>
<line x1="58" x2="64" y1="115.78" y2="115.78" stroke="#747474"/>
<line x1="58" x2="64" y1="119.07" y2="119.07" stroke="#747474"/>
<line x1="58" x2="64" y1="122.36" y2="122.36" stroke="#747474"/>
<line x1="58" x2="64" y1="125.65" y2="125.65" stroke="#747474"/>
<line x1="58" x2="64" y1="128.94" y2="128.94" stroke="#747474"/>
<line x1="58" x2="64" y1="132.23" y2="132.23" stroke="#747474"/>
<line x1="58" x2="64" y1="135.52" y2="135.52" stroke="#747474"/>
<line x1="58" x2="64" y1="138.81" y2="138.81" stroke="#747474"/>
<line x1="52" x2="64" y1="142.1" y2="142.1" stroke="#747474"/>
<line x1="58" x2="64" y1="145.39" y2="145.39" stroke="#747474"/>
<line x1="58" x2="64" y1="148.68" y2="148.68" stroke="#747474"/>
<line x1="58" x2="64" y1="151.97" y2="151.97" stroke="#747474"/>
<line x1="58" x2="64" y1="155.26" y2="155.26" stroke="#747474"/>
<line x1="58" x2="64" y1="158.55" y2="158.55" stroke="#747474"/>
<line x1="58" x2="64" y1="161.84" y2="161.84" stroke="#747474"/>
<line x1="58" x2="64" y1="165.13" y2="165.13" stroke="#747474"/>
<line x1="58" x2="64" y1="168.42" y2="168.42" stroke="#747474"/>
<line x1="58" x2="64" y1="171.71" y2="171.71" stroke="#747474"/>
<line x1="52" x2="64" y1="175" y2="175" stroke="#747474"/>
<line x1="58" x2="64" y1="178.29" y2="178.29" stroke="#747474"/>
<line x1="58" x2="64" y1="181.58" y2="181.58" stroke="#747474"/>
<line x1="58" x2="64" y1="184.87" y2="184.87" stroke="#747474"/>
<line x1="58" x2="64" y1="188.16" y2="188.16" stroke="#747474"/>
<line x1="58" x2="64" y1="191.45" y2="191.45" stroke="#747474"/>
<line x1="58" x2="64" y1="194.74" y2="194.74" stroke="#747474"/>
<line x1="58" x2="64" y1="198.03" y2="198.03" stroke="#747474"/>
<line x1="58" x2="64" y1="201.32" y2="201.32" stroke="#747474"/>
<line x1="58" x2="64" y1="204.61" y2="204.61" stroke="#747474"/>
<line x1="52" x2="64" y1="207.9" y2="207.9" stroke="#747474"/>
<line x1="58" x2="64" y1="211.19" y2="211.19" stroke="#747474"/>
<line x1="58" x2="64" y1="214.48" y2="214.48" stroke="#747474"/>
<line x1="58" x2="64" y1="217.77" y2="217.77" stroke="#747474"/>
<line x1="58" x2="64" y1="221.06" y2="221.06" stroke="#747474"/>
<line x1="58" x2="64" y1="224.35" y2="224.35" stroke="#747474"/>
<line x1="58" x2="64" y1="227.64" y2="227.64" stroke="#747474"/>
<line x1="58" x2="64" y1="230.93" y2="230.93" stroke="#747474"/>
<line x1="58" x2="64" y1="234.22" y2="234.22" stroke="#747474"/>
<line x1="58" x2="64" y1="237.51" y2="237.51" stroke="#747474"/>
<line x1="52" x2="64" y1="240.8" y2="240.8" stroke="#747474"/>
<line x1="58" x2="64" y1="244.09" y2="244.09" stroke="#747474"/>
<line x1="58" x2="64" y1="247.38" y2="247.38" stroke="#747474"/>
<line x1="58" x2="64" y1="250.67" y2="250.67" stroke="#747474"/>
<line x1="58" x2="64" y1="253.96" y2="253.96" stroke="#747474"/>
<line x1="58" x2="64" y1="257.25" y2="257.25" stroke="#747474"/>
<line x1="58" x2="64" y1="260.54" y2="260.54" stroke="#747474"/>
<line x1="58" x2="64" y1="263.83" y2="263.83" stroke="#747474"/>
<line x1="58" x2="64" y1="267.12" y2="267.12" stroke="#747474"/>
<line x1="58" x2="64" y1="270.41" y2="270.41" stroke="#747474"/>
<line x1="52" x2="64" y1="273.7" y2="273.7" stroke="#747474"/>
<line x1="58" x2="64" y1="276.99" y2="276.99" stroke="#747474"/>
<line x1="58" x2="64" y1="280.28" y2="280.28" stroke="#747474"/>
<line x1="58" x2="64" y1="283.57" y2="283.57" stroke="#747474"/>
<line x1="58" x2="64" y1="286.86" y2="286.86" stroke="#747474"/>
<line x1="58" x2="64" y1="290.15" y2="290.15" stroke="#747474"/>
<line x1="58" x2="64" y1="293.44" y2="293.44" stroke="#747474"/>
<line x1="58" x2="64" y1="296.73" y2="296.73" stroke="#747474"/>
<line x1="58" x2="64" y1="300.02" y2="300.02" stroke="#747474"/>
<line x1="58" x2="64" y1="303.31" y2="303.31" stroke="#747474"/>
<line x1="52" x2="64" y1="306.6" y2="306.6" stroke="#747474"/>
<line x1="58" x2="64" y1="309.89" y2="309.89" stroke="#747474"/>
<line x1="58" x2="64" y1="313.18" y2="313.18" stroke="#747474"/>
<line x1="58" x2="64" y1="316.47" y2="316.47" stroke="#747474"/>
<line x1="58" x2="64" y1="319.76" y2="319.76" stroke="#747474"/>
<line x1="58" x2="64" y1="323.05" y2="323.05" stroke="#747474"/>
<line x1="58" x2="64" y1="326.34" y2="326.34" stroke="#747474"/>
<line x1="58" x2="64" y1="329.63" y2="329.63" stroke="#747474"/>
<line x1="58" x2="64" y1="332.92" y2="332.92" stroke="#747474"/>
<line x1="58" x2="64" y1="336.21" y2="336.21" stroke="#747474"/>
<line x1="52" x2="64" y1="339.5" y2="339.5" stroke="#747474"/>
</g><g tb:tag="progressBar">
<rect x="68" y="10.5" width="6" height="331" ry="1.12" stroke="#cecece" tb:tag="progressBorder"/>
<rect transform="scale(1,-1)" x="68" y="-342" width="6" height="125" ry="1.12" fill="#4d94e1" stroke="#4d94e1" tb:tag="progressFill"/>
<circle cx="71" cy="347" r="7" fill="#4d94e1" tb:tag="progressCircle"/>
</g><g transform="translate(0,329)" fill="#1c943e" style="display: none;" tb:tag="progress-indicator">
<path d="m63.022 10.562 10.5 6.062v-12.124z" style=""/>
</g><g filter="url(#filter0_ii_2475_365165)" tb:tag="value-box">
<rect x="21.5" y="362" width="56" height="30" rx="4" fill="#f3f3f3" fill-opacity=".75" tb:tag="value-box-background"/>
<rect x="22.5" y="363" width="54" height="28" rx="3" stroke="#fff" stroke-width="2"/>
<text x="50.492188" y="378.0625" fill="#727171" font-family="Roboto" font-size="14px" font-weight="500" text-anchor="middle" tb:tag="value-text" xml:space="preserve"><tspan dominant-baseline="middle">37%</tspan></text>
</g><path d="m37.56 0s-25.56 0-25.56 67v328.36c0 2.6512 0.68053 4.6404 1.52 4.6404h72.96c0.83942 0 1.52-1.9892 1.52-4.6404v-328.36c0-67-25.107-67-25.107-67h-12.893zm25.487 81.2c-0.48969 0-0.88669 1.2536-0.88669 2.8v300.4c0 1.5464 0.39697 2.8 0.88669 2.8h5.5733c0.48969 0 0.88669-1.2536 0.88669-2.8v-300.4c0-1.5464-0.39697-2.8-0.88669-2.8z" fill="#000" fill-opacity="0" style="stroke-width:.17436" tb:tag="clickArea"/><defs>
<filter id="filter0_ii_2475_365165" x="19.5" y="360" width="60" height="34" color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
<feColorMatrix in="SourceAlpha" result="hardAlpha" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/>
<feOffset dx="-2" dy="2"/>
<feGaussianBlur stdDeviation="3"/>
<feComposite in2="hardAlpha" k2="-1" k3="1" operator="arithmetic"/>
<feColorMatrix values="0 0 0 0 0.445833 0 0 0 0 0.445833 0 0 0 0 0.445833 0 0 0 0.5 0"/>
<feBlend in2="shape" result="effect1_innerShadow_2475_365165"/>
<feColorMatrix in="SourceAlpha" result="hardAlpha" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/>
<feOffset dx="2" dy="-2"/>
<feGaussianBlur stdDeviation="2"/>
<feComposite in2="hardAlpha" k2="-1" k3="1" operator="arithmetic"/>
<feColorMatrix values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0.5 0"/>
<feBlend in2="effect1_innerShadow_2475_365165" result="effect2_innerShadow_2475_365165"/>
</filter>
<linearGradient id="paint0_linear_2475_365165" x1="88" x2="12" y1="200" y2="200.04" gradientUnits="userSpaceOnUse">
<stop stop-color="#020202" stop-opacity=".35" offset="0"/>
<stop stop-color="#020202" stop-opacity=".12" offset=".02629"/>
<stop stop-color="#fff" stop-opacity=".12" offset=".11617"/>
<stop stop-color="#fff" stop-opacity=".3" offset=".49829"/>
<stop stop-color="#fff" stop-opacity=".12" offset=".88762"/>
<stop stop-color="#020202" stop-opacity=".12" offset=".96591"/>
<stop stop-color="#020202" stop-opacity=".35" offset="1"/>
</linearGradient>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 58 KiB

267
application/src/main/data/json/system/scada_symbols/platform-hp.svg

@ -0,0 +1,267 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:tb="https://thingsboard.io/svg" width="1200" height="600" fill="none" version="1.1" viewBox="0 0 1200 600"><tb:metadata xmlns=""><![CDATA[{
"title": "HP Platform",
"description": "Platform with various states.",
"searchTags": [
"platform",
"drilling"
],
"widgetSizeX": 6,
"widgetSizeY": 3,
"tags": [
{
"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": "warningColor",
"name": "{i18n:scada.symbol.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.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="m1199 201.7v397.3h-1198v-397.3c0.62677 0.346 1.4439 0.79199 2.4378 1.328 2.5404 1.371 6.2364 3.328 10.864 5.676 9.2543 4.696 22.238 10.957 37.156 17.218 29.8 12.508 67.456 25.078 98.542 25.078s68.743-12.57 98.542-25.078c14.918-6.261 27.902-12.522 37.156-17.218 4.628-2.348 8.324-4.305 10.864-5.676 1.27-0.68499 2.252-1.224 2.916-1.592 0.204-0.113 0.379-0.209 0.522-0.28999 0.143 0.081 0.318 0.17699 0.522 0.28999 0.664 0.368 1.646 0.907 2.916 1.592 2.54 1.371 6.236 3.328 10.864 5.676 9.254 4.696 22.238 10.957 37.156 17.218 29.799 12.508 67.456 25.078 98.542 25.078s68.743-12.57 98.542-25.078c14.918-6.261 27.902-12.522 37.156-17.218 4.628-2.348 8.324-4.305 10.864-5.676 1.27-0.68499 2.252-1.224 2.916-1.592 0.204-0.113 0.379-0.209 0.522-0.28999 0.143 0.081 0.318 0.17699 0.522 0.28999 0.664 0.368 1.646 0.907 2.916 1.592 2.54 1.371 6.236 3.328 10.864 5.676 9.254 4.696 22.238 10.957 37.156 17.218 29.799 12.508 67.456 25.078 98.542 25.078s68.743-12.57 98.542-25.078c14.918-6.261 27.902-12.522 37.156-17.218 4.628-2.348 8.324-4.305 10.864-5.676 1.27-0.68499 2.252-1.224 2.916-1.592 0.204-0.113 0.379-0.209 0.522-0.28999 0.143 0.081 0.318 0.17699 0.522 0.28999 0.664 0.368 1.646 0.907 2.916 1.592 2.54 1.371 6.236 3.328 10.864 5.676 9.254 4.696 22.238 10.957 37.156 17.218 29.799 12.508 67.452 25.078 98.542 25.078s68.74-12.57 98.54-25.078c14.92-6.261 27.9-12.522 37.16-17.218 4.63-2.348 8.32-4.305 10.86-5.676 1-0.536 1.81-0.98199 2.44-1.328z" stroke="#1a1a1a" stroke-width="2"/><path d="m700 300h500" stroke="#1a1a1a" stroke-width="6"/><path d="m600 0v200" stroke="#1a1a1a" stroke-width="6"/><path d="m600 400v200" stroke="#1a1a1a" stroke-width="6"/><path d="m700 300h-85c-8.284 0-15 6.716-15 15v85" stroke="#1a1a1a" stroke-width="6"/><path d="m700 300h-85c-8.284 0-15-6.716-15-15v-85" stroke="#1a1a1a" stroke-width="6"/><path d="m600 200v200" stroke="#1a1a1a" stroke-width="6"/><path d="m600 313v-26s0 13 14 13c-14 0-14 13-14 13z" fill="#1a1a1a" stroke="#1a1a1a" stroke-width="2"/><rect x="1074" y="99" width="48" height="462" stroke="#1a1a1a" stroke-width="2"/><rect x="1037" y="561" width="122" height="38" stroke="#1a1a1a" stroke-width="2"/><rect x="78" y="99" width="48" height="462" stroke="#1a1a1a" stroke-width="2"/><rect x="41" y="561" width="122" height="38" stroke="#1a1a1a" stroke-width="2"/><rect x="1" y="1" width="1198" height="98" stroke="#1a1a1a" stroke-width="2"/><path d="m599.68 99.026-598.68-98.026" stroke="#1a1a1a" stroke-width="2.0003"/><path d="m599.68 99.026-598.68-98.027" stroke="#1a1a1a" stroke-width="1.9995"/><path d="m600 99.026 598.68-98.026" stroke="#1a1a1a" stroke-width="2.0003"/><path d="m599.68 0.99987-598.68 98.027" stroke="#1a1a1a" stroke-width="1.9995"/><path d="m600 1.0007 599.68 98.025" stroke="#1a1a1a" stroke-width="2.0011"/><path d="m403.58 0s-403.58 0-403.58 100.5v492.54c0 3.9768 10.745 6.9606 24 6.9606h1152c13.254 0 24-2.9838 24-6.9606v-492.54c0-100.5-396.42-100.5-396.42-100.5h-203.57zm402.42 121.8c-7.7322 0-14 1.8804-14 4.2v450.6c0 2.3196 6.2682 4.2 14 4.2h87.996c7.7322 0 14-1.8804 14-4.2v-450.6c0-2.3196-6.2682-4.2-14-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 516)" fill="#faa405" style="display: none;" tb:tag="warning">
<path d="m38.422 7.1554c1.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="m38.422 7.1554c1.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="m40.211 8.0498c0.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="m44.559 37.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>
</svg>

After

Width:  |  Height:  |  Size: 13 KiB

343
application/src/main/data/json/system/scada_symbols/preventer-hp.svg

@ -0,0 +1,343 @@
<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 Preventer",
"description": "Preventer with various states.",
"searchTags": [
"preventer",
"drilling"
],
"widgetSizeX": 2,
"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>
<path d="m137 15h1v-14h124v14h32.947l46.053 4.8993v21.201l-46.053 4.8993h-9.947v24h45.907l68.093 12.829v32.342l-68.093 12.829h-45.907v25h8.938l47.062 5.883v20.234l-47.062 5.883h-31.938v14h-124v-14h-31.938l-47.062-5.883v-20.234l47.062-5.883h8.938v-25h-45.907l-68.093-12.829v-32.342l68.093-12.829h45.907v-24h-9.947l-46.053-4.8993v-21.201l46.053-4.8993z" tb:tag="background" fill="#fff" stroke="#1a1a1a" stroke-width="2"/><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" 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="m38.422 7.1554c1.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="m38.422 7.1554c1.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="m40.211 8.0498c0.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="m44.559 37.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>
</svg>

After

Width:  |  Height:  |  Size: 13 KiB

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

@ -0,0 +1,346 @@
<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 Rotor",
"description": "Rotor with various states.",
"searchTags": [
"rotor",
"drilling"
],
"widgetSizeX": 2,
"widgetSizeY": 1,
"tags": [
{
"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": "rotor-background",
"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": "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="m163 1h74v76h-74v-76z" fill="#fff" stroke="#1A1A1A" stroke-width="2"/><g fill="#fff" stroke="#1A1A1A" stroke-width="2" tb:tag="rotor-background">
<path d="m51 77h298v88h-298v-88z"/>
<path d="m1 165h398v34h-398l-5e-5 -34z"/>
</g><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" tb:tag="clickArea"/><g transform="translate(0,116)" 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,116)" fill="#faa405" style="display: none;" tb:tag="warning">
<path d="m38.422 7.1554c1.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="m38.422 7.1554c1.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="m40.211 8.0498c0.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="m44.559 37.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>
</svg>

After

Width:  |  Height:  |  Size: 13 KiB

717
application/src/main/data/json/system/scada_symbols/small-left-meter.svg

@ -0,0 +1,717 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:tb="https://thingsboard.io/svg" width="100" height="200" fill="none" version="1.1" viewBox="0 0 100 200"><tb:metadata xmlns=""><![CDATA[{
"title": "Small left meter",
"description": "Small left meter displays the current value with a moving pointer on the scale.",
"searchTags": [
"scale",
"level",
"progress",
"thermometer"
],
"widgetSizeX": 1,
"widgetSizeY": 2,
"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": "progress-indicator",
"stateRenderFunction": "function calculateOffset(value, minValue, maxValue, initial) {\n var clampedValue = Math.max(Math.min(value, Math.max(minValue, maxValue)), Math.min(minValue, maxValue));\n var normalizedValue = minValue < maxValue\n ? (clampedValue - minValue) / (maxValue - minValue)\n : (minValue - clampedValue) / (minValue - maxValue);\n var offset = initial - (normalizedValue * initial);\n return offset;\n}\n\nvar valueSet = element.remember('valueSet');\n\nif (ctx.properties.progressArrow && !ctx.properties.progressBar) {\n element.show();\n var initial = ctx.properties.valueBox ? 135 : 168;\n if (!valueSet) {\n element.remember('valueSet', true);\n element.transform({\n translateY: initial\n });\n }\n \n var minValue = ctx.properties.minValue;\n var maxValue = ctx.properties.maxValue;\n var value = ctx.values.value;\n \n var colorProcessor = ctx.properties.progressArrowColor;\n colorProcessor.update(value);\n var fill = colorProcessor.color;\n element.attr({fill: fill});\n \n var offset = calculateOffset(value, minValue, maxValue, initial);\n\n var elementOffset = element.remember('offset');\n if (offset !== elementOffset) {\n element.remember('offset', offset);\n ctx.api.cssAnimate(element, 500).transform({\n translateY: offset\n });\n }\n} else {\n element.hide();\n if (valueSet) {\n element.remember('valueSet', false);\n }\n}",
"actions": null
},
{
"tag": "progressBar",
"stateRenderFunction": "if (ctx.properties.progressBar) {\n element.show();\n} else {\n element.hide();\n}",
"actions": null
},
{
"tag": "progressBorder",
"stateRenderFunction": "if (ctx.properties.valueBox) {\n element.attr({'height': 137})\n}",
"actions": null
},
{
"tag": "progressCircle",
"stateRenderFunction": "if (ctx.properties.valueBox) {\n element.attr({cy:152});\n}",
"actions": null
},
{
"tag": "progressFill",
"stateRenderFunction": "if (ctx.properties.valueBox) {\n element.attr({y:-147});\n}\n\nfunction calculateOffset(value, minValue, maxValue, initial) {\n var clampedValue = Math.max(Math.min(value, Math.max(minValue, maxValue)), Math.min(minValue, maxValue));\n var normalizedValue = minValue < maxValue\n ? (clampedValue - minValue) / (maxValue - minValue)\n : (minValue - clampedValue) / (minValue - maxValue);\n var offset = normalizedValue * initial;\n return offset;\n}\n\nvar valueSet = element.remember('valueSet');\nif (ctx.properties.progressBar) {\n var initial = ctx.properties.valueBox ? 135: 168;\n if (!valueSet) {\n element.remember('valueSet', true);\n element.attr({height: 2});\n }\n \n var minValue = ctx.properties.minValue;\n var maxValue = ctx.properties.maxValue;\n var value = ctx.values.value;\n \n var colorProcessor = ctx.properties.progressBarColor;\n colorProcessor.update(value);\n var fill = colorProcessor.color;\n element.attr({fill: fill, stroke: fill});\n ctx.tags.progressCircle[0].fill(fill);\n \n var height = calculateOffset(value, minValue, maxValue, initial);\n\n var elementHeight = element.remember('height');\n if (height !== elementHeight) {\n element.remember('height', height);\n ctx.api.cssAnimate(element, 500).attr({height: height+2});\n }\n} else {\n if (valueSet) {\n element.remember('valueSet', false);\n }\n}",
"actions": null
},
{
"tag": "scale",
"stateRenderFunction": "var scaleSet = element.remember('scaleSet');\nif (!scaleSet) {\n element.remember('scaleSet', true);\n element.clear();\n \n var majorIntervals = ctx.properties.majorIntervals;\n var minorIntervals = ctx.properties.minorIntervals;\n var minValue = ctx.properties.minValue;\n var maxValue = ctx.properties.maxValue;\n \n var start = 11;\n var end = ctx.properties.valueBox ? 134 : 167;\n var majorIntervalLength = end / majorIntervals;\n var minorIntervalLength = majorIntervalLength / minorIntervals;\n element.add(ctx.svg.line(50, end+11, 50, 11).stroke({ width: 1 }).attr({class: 'majorTick'}));\n for (var i = 0; i < majorIntervals+1; i++) {\n var y = start + i * majorIntervalLength;\n var line = ctx.svg.line(38, y, 50, y).stroke({ width: 1 }).attr({class: 'majorTick'});\n element.add(line);\n var majorText = (maxValue - ((maxValue - (minValue)) / (majorIntervals) * i)).toFixed(0);\n var majorTickText = ctx.svg.text(majorText);\n majorTickText.attr({x: 32, y: y + 2, 'text-anchor': 'end', class: 'majorTickText'});\n majorTickText.first().attr({'dominant-baseline': 'middle'});\n element.add(majorTickText);\n if (i < majorIntervals) {\n drawMinorTicks(y, minorIntervals, minorIntervalLength);\n }\n }\n}\n\nvar majorFont = ctx.properties.majorFont;\nvar majorColor = ctx.properties.majorColor;\nvar minorColor = ctx.properties.minorColor;\nif (ctx.values.critical) {\n majorColor = ctx.properties.majorCriticalColor;\n minorColor = ctx.properties.minorCriticalColor;\n} else if (ctx.values.warning) {\n majorColor = ctx.properties.minorWarningColor;\n minorColor = ctx.properties.minorWarningColor;\n}\n\nvar majorTicks = element.find('line.majorTick');\nmajorTicks.forEach(t => t.attr({stroke: majorColor}));\n\nvar majorTicksText = element.find('text.majorTickText');\nctx.api.font(majorTicksText, majorFont, majorColor);\n\nvar minorTicks = element.find('line.minorTick');\nminorTicks.forEach(t => t.attr({stroke: minorColor}));\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\nfunction drawMinorTicks(start, minorIntervals, minorIntervalLength) {\n for (var i = 1; i < minorIntervals; i++) {\n var minorY = start + i * minorIntervalLength;\n var minorLine = ctx.svg.line(44, minorY, 50, minorY).stroke({ width: 1 }).attr({class: 'minorTick'});\n element.add(minorLine);\n }\n}",
"actions": null
},
{
"tag": "value-box",
"stateRenderFunction": "if (ctx.properties.valueBox) {\n element.show();\n} else {\n element.hide();\n}",
"actions": null
},
{
"tag": "value-box-background",
"stateRenderFunction": "if (ctx.properties.valueBox) {\n var colorProcessor = ctx.properties.valueBoxColor;\n colorProcessor.update(ctx.values.value);\n element.attr({fill: colorProcessor.color});\n}",
"actions": null
},
{
"tag": "value-text",
"stateRenderFunction": "if (ctx.properties.valueBox) {\n var valueTextFont = ctx.properties.valueTextFont;\n var valueTextColor = ctx.properties.valueTextColor;\n var currentVolume = ctx.values.value;\n var valueText = ctx.api.formatValue(currentVolume, 0, ctx.properties.valueUnits, false);\n var colorProcessor = ctx.properties.valueTextColor;\n colorProcessor.update(ctx.values.value);\n ctx.api.font(element, valueTextFont, colorProcessor.color);\n ctx.api.text(element, valueText);\n}",
"actions": null
}
],
"behavior": [
{
"id": "value",
"name": "{i18n:scada.symbol.value}",
"hint": null,
"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": "waterLevel"
},
"dataToValue": {
"type": "NONE",
"dataToValueFunction": "/* Should return boolean value */\nreturn data;"
}
},
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": null
},
{
"id": "warning",
"name": "{i18n:scada.symbol.warning-state}",
"hint": "{i18n:scada.symbol.warning-state-hint}",
"group": null,
"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": "critical",
"name": "{i18n:scada.symbol.critical-state}",
"hint": "{i18n:scada.symbol.critical-state-hint}",
"group": null,
"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": "criticalAnimation",
"name": "{i18n:scada.symbol.critical-state-animation}",
"hint": "{i18n:scada.symbol.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": "minValue",
"name": "{i18n:scada.symbol.min-max-value}",
"type": "number",
"default": 0,
"required": true,
"subLabel": "{i18n:scada.symbol.min-value}",
"divider": true,
"min": -1000,
"step": 1,
"disabled": false,
"visible": true
},
{
"id": "maxValue",
"name": "{i18n:scada.symbol.min-max-value}",
"type": "number",
"default": 100,
"required": true,
"subLabel": "{i18n:scada.symbol.max-value}",
"max": 1000,
"step": 1,
"disabled": false,
"visible": true
},
{
"id": "backgroundColor",
"name": "{i18n:scada.symbol.background-color}",
"type": "color",
"default": "#FFFFFF",
"disabled": false,
"visible": true
},
{
"id": "progressBar",
"name": "{i18n:scada.symbol.progress-bar}",
"type": "switch",
"default": true,
"disabled": false,
"visible": true
},
{
"id": "progressBarColor",
"name": "{i18n:scada.symbol.progress-bar}",
"type": "color_settings",
"default": {
"type": "constant",
"color": "#4D94E1",
"gradient": {
"advancedMode": false,
"gradient": [
"rgba(0, 255, 0, 1)",
"rgba(255, 0, 0, 1)"
],
"gradientAdvanced": [
{
"source": {
"type": "constant"
},
"color": "rgba(0, 255, 0, 1)"
},
{
"source": {
"type": "constant"
},
"color": "rgba(255, 0, 0, 1)"
}
],
"minValue": 0,
"maxValue": 100
},
"rangeList": {
"advancedMode": false,
"range": [],
"rangeAdvanced": []
},
"colorFunction": "var temperature = value;\nif (typeof temperature !== undefined) {\n var percent = (temperature + 60)/120 * 100;\n return tinycolor.mix('blue', 'red', percent).toHexString();\n}\nreturn 'blue';"
},
"disableOnProperty": "progressBar",
"disabled": false,
"visible": true
},
{
"id": "progressArrow",
"name": "{i18n:scada.symbol.progress-arrow}",
"type": "switch",
"default": false,
"disabled": false,
"visible": true
},
{
"id": "progressArrowColor",
"name": "{i18n:scada.symbol.progress-arrow}",
"type": "color_settings",
"default": {
"type": "constant",
"color": "#1C943E",
"gradient": {
"advancedMode": false,
"gradient": [
"rgba(0, 255, 0, 1)",
"rgba(255, 0, 0, 1)"
],
"gradientAdvanced": [
{
"source": {
"type": "constant"
},
"color": "rgba(0, 255, 0, 1)"
},
{
"source": {
"type": "constant"
},
"color": "rgba(255, 0, 0, 1)"
}
],
"minValue": 0,
"maxValue": 100
},
"rangeList": {
"advancedMode": false,
"range": [],
"rangeAdvanced": []
},
"colorFunction": "var temperature = value;\nif (typeof temperature !== undefined) {\n var percent = (temperature + 60)/120 * 100;\n return tinycolor.mix('blue', 'red', percent).toHexString();\n}\nreturn 'blue';"
},
"disableOnProperty": "progressArrow",
"disabled": true,
"visible": true
},
{
"id": "valueBox",
"name": "{i18n:scada.symbol.value-box}",
"type": "switch",
"default": false,
"disabled": false,
"visible": true
},
{
"id": "valueBoxColor",
"name": "{i18n:scada.symbol.value-box}",
"type": "color_settings",
"default": {
"type": "constant",
"color": "#F3F3F3",
"gradient": {
"advancedMode": false,
"gradient": [
"rgba(0, 255, 0, 1)",
"rgba(255, 0, 0, 1)"
],
"gradientAdvanced": [
{
"source": {
"type": "constant"
},
"color": "rgba(0, 255, 0, 1)"
},
{
"source": {
"type": "constant"
},
"color": "rgba(255, 0, 0, 1)"
}
],
"minValue": 0,
"maxValue": 100
},
"rangeList": {
"advancedMode": false,
"range": [],
"rangeAdvanced": []
},
"colorFunction": "var temperature = value;\nif (typeof temperature !== undefined) {\n var percent = (temperature + 60)/120 * 100;\n return tinycolor.mix('blue', 'red', percent).toHexString();\n}\nreturn 'blue';"
},
"disableOnProperty": "valueBox",
"disabled": false,
"visible": true
},
{
"id": "valueUnits",
"name": "{i18n:scada.symbol.value-text}",
"type": "units",
"default": "%",
"subLabel": "{i18n:scada.symbol.units}",
"disableOnProperty": "valueBox",
"disabled": false,
"visible": true
},
{
"id": "valueTextFont",
"name": "{i18n:scada.symbol.value-text}",
"type": "font",
"default": {
"size": 14,
"sizeUnit": "px",
"family": "Roboto",
"weight": "500",
"style": "normal"
},
"disableOnProperty": "valueBox",
"disabled": false,
"visible": true
},
{
"id": "valueTextColor",
"name": "{i18n:scada.symbol.value-text}",
"type": "color_settings",
"default": {
"type": "constant",
"color": "#0000008A",
"gradient": {
"advancedMode": false,
"gradient": [
"rgba(0, 255, 0, 1)",
"rgba(255, 0, 0, 1)"
],
"gradientAdvanced": [
{
"source": {
"type": "constant"
},
"color": "rgba(0, 255, 0, 1)"
},
{
"source": {
"type": "constant"
},
"color": "rgba(255, 0, 0, 1)"
}
],
"minValue": 0,
"maxValue": 100
},
"rangeList": {
"advancedMode": false,
"range": [],
"rangeAdvanced": []
},
"colorFunction": "var temperature = value;\nif (typeof temperature !== undefined) {\n var percent = (temperature + 60)/120 * 100;\n return tinycolor.mix('blue', 'red', percent).toHexString();\n}\nreturn 'blue';"
},
"disableOnProperty": "valueBox",
"disabled": false,
"visible": true
},
{
"id": "majorIntervals",
"name": "{i18n:scada.symbol.major-ticks}",
"type": "number",
"default": 5,
"subLabel": "{i18n:scada.symbol.intervals}",
"divider": true,
"min": 1,
"step": 1,
"disabled": false,
"visible": true
},
{
"id": "majorFont",
"name": "{i18n:scada.symbol.major-ticks}",
"type": "font",
"default": {
"size": 12,
"sizeUnit": "px",
"family": "Roboto",
"weight": "500",
"style": "normal"
},
"disabled": false,
"visible": true
},
{
"id": "majorColor",
"name": "{i18n:scada.symbol.major-ticks-color}",
"type": "color",
"default": "#747474",
"subLabel": "{i18n:scada.symbol.normal}",
"divider": true,
"disabled": false,
"visible": true
},
{
"id": "majorWarningColor",
"name": "{i18n:scada.symbol.major-ticks-color}",
"type": "color",
"default": "#FAA405",
"subLabel": "{i18n:scada.symbol.warning}",
"divider": true,
"disabled": false,
"visible": true
},
{
"id": "majorCriticalColor",
"name": "{i18n:scada.symbol.major-ticks-color}",
"type": "color",
"default": "#D12730",
"subLabel": "{i18n:scada.symbol.critical}",
"disabled": false,
"visible": true
},
{
"id": "minorIntervals",
"name": "{i18n:scada.symbol.minor-ticks}",
"type": "number",
"default": 10,
"subLabel": "{i18n:scada.symbol.intervals}",
"min": 1,
"disabled": false,
"visible": true
},
{
"id": "minorColor",
"name": "{i18n:scada.symbol.minor-ticks-color}",
"type": "color",
"default": "#747474",
"subLabel": "{i18n:scada.symbol.normal}",
"divider": true,
"disabled": false,
"visible": true
},
{
"id": "minorWarningColor",
"name": "{i18n:scada.symbol.minor-ticks-color}",
"type": "color",
"default": "#FAA405",
"subLabel": "{i18n:scada.symbol.warning}",
"divider": true,
"disabled": false,
"visible": true
},
{
"id": "minorCriticalColor",
"name": "{i18n:scada.symbol.minor-ticks-color}",
"type": "color",
"default": "#D12730",
"subLabel": "{i18n:scada.symbol.critical}",
"disabled": false,
"visible": true
}
]
}]]></tb:metadata>
<path d="m4 200c-2.2091 0-4-1.791-4-4v-192c0-2.2091 1.7909-4 4-4h68c2.2091 0 4 1.7909 4 4v192c0 2.209-1.7909 4-4 4h-68z" fill="#E5E5E5" tb:tag="background"/><path d="m4 200c-2.2091 0-4-1.791-4-4v-192c0-2.2091 1.7909-4 4-4h68c2.2091 0 4 1.7909 4 4v192c0 2.209-1.7909 4-4 4h-68z" fill="url(#paint0_linear_3742_299967)"/><path d="m4 198.5c-1.3807 0-2.5-1.119-2.5-2.5v-192c0-1.3807 1.1193-2.5 2.5-2.5h68c1.3807 0 2.5 1.1193 2.5 2.5v192c0 1.381-1.1193 2.5-2.5 2.5h-68z" stroke="#000" stroke-opacity=".12" stroke-width="3"/><g tb:tag="scale">
<g fill="#919191">
<path d="m14.539 10.088v8.5605h-1.4121v-6.8848l-2.0918 0.709v-1.166l3.3339-1.2187zm8.7754 3.58v1.3946c0 0.6679-0.0665 1.2382-0.1993 1.7109-0.1289 0.4688-0.3164 0.8496-0.5625 1.1426-0.2461 0.2929-0.541 0.5078-0.8847 0.6445-0.3399 0.1367-0.7207 0.2051-1.1426 0.2051-0.3359 0-0.6484-0.043-0.9375-0.1289-0.2852-0.086-0.543-0.2207-0.7734-0.4043-0.2305-0.1836-0.4278-0.4199-0.5918-0.709-0.1602-0.293-0.2852-0.6426-0.375-1.0488-0.086-0.4063-0.1289-0.877-0.1289-1.4121v-1.3946c0-0.6718 0.0664-1.2383 0.1992-1.6992 0.1328-0.4648 0.3222-0.8418 0.5683-1.1308 0.2461-0.293 0.5391-0.5059 0.8789-0.6387 0.3438-0.1328 0.7266-0.1992 1.1485-0.1992 0.3398 0 0.6523 0.0429 0.9375 0.1289 0.289 0.082 0.5468 0.2129 0.7734 0.3925 0.2305 0.1797 0.4258 0.4141 0.5859 0.7032 0.1641 0.2851 0.2891 0.6308 0.375 1.0371 0.086 0.4023 0.129 0.8711 0.129 1.4062zm-1.4122 1.5938v-1.8047c0-0.3398-0.0195-0.6387-0.0585-0.8965-0.0391-0.2617-0.0977-0.4824-0.1758-0.6621-0.0742-0.1836-0.168-0.332-0.2813-0.4453-0.1133-0.1172-0.2422-0.2012-0.3867-0.252-0.1445-0.0547-0.3066-0.082-0.4863-0.082-0.2188 0-0.4141 0.043-0.586 0.1289-0.1718 0.082-0.3164 0.2149-0.4336 0.3984-0.1171 0.1836-0.207 0.4258-0.2695 0.7266-0.0586 0.2969-0.0879 0.6582-0.0879 1.084v1.8047c0 0.3437 0.0195 0.6465 0.0586 0.9082s0.0977 0.4863 0.1758 0.6738c0.0781 0.1836 0.1719 0.3359 0.2812 0.457 0.1133 0.1172 0.2422 0.2032 0.3868 0.2579 0.1484 0.0546 0.3105 0.082 0.4863 0.082 0.2226 0 0.4199-0.043 0.5918-0.1289 0.1719-0.086 0.3164-0.2227 0.4336-0.4102 0.1172-0.1914 0.2051-0.4394 0.2637-0.7441 0.0585-0.3047 0.0878-0.6699 0.0878-1.0957zm8.4825-1.5938v1.3946c0 0.6679-0.0664 1.2382-0.1993 1.7109-0.1289 0.4688-0.3164 0.8496-0.5625 1.1426-0.246 0.2929-0.541 0.5078-0.8847 0.6445-0.3399 0.1367-0.7207 0.2051-1.1426 0.2051-0.3359 0-0.6484-0.043-0.9375-0.1289-0.2852-0.086-0.543-0.2207-0.7734-0.4043-0.2305-0.1836-0.4278-0.4199-0.5918-0.709-0.1602-0.293-0.2852-0.6426-0.375-1.0488-0.086-0.4063-0.1289-0.877-0.1289-1.4121v-1.3946c0-0.6718 0.0664-1.2383 0.1992-1.6992 0.1328-0.4648 0.3222-0.8418 0.5683-1.1308 0.2461-0.293 0.5391-0.5059 0.8789-0.6387 0.3438-0.1328 0.7266-0.1992 1.1485-0.1992 0.3398 0 0.6523 0.0429 0.9375 0.1289 0.289 0.082 0.5469 0.2129 0.7734 0.3925 0.2305 0.1797 0.4258 0.4141 0.586 0.7032 0.164 0.2851 0.289 0.6308 0.375 1.0371 0.0859 0.4023 0.1289 0.8711 0.1289 1.4062zm-1.4121 1.5938v-1.8047c0-0.3398-0.0196-0.6387-0.0586-0.8965-0.0391-0.2617-0.0977-0.4824-0.1758-0.6621-0.0742-0.1836-0.168-0.332-0.2813-0.4453-0.1132-0.1172-0.2422-0.2012-0.3867-0.252-0.1445-0.0547-0.3066-0.082-0.4863-0.082-0.2188 0-0.4141 0.043-0.586 0.1289-0.1718 0.082-0.3164 0.2149-0.4335 0.3984-0.1172 0.1836-0.2071 0.4258-0.2696 0.7266-0.0586 0.2969-0.0879 0.6582-0.0879 1.084v1.8047c0 0.3437 0.0196 0.6465 0.0586 0.9082 0.0391 0.2617 0.0977 0.4863 0.1758 0.6738 0.0781 0.1836 0.1719 0.3359 0.2813 0.457 0.1132 0.1172 0.2421 0.2032 0.3867 0.2579 0.1484 0.0546 0.3105 0.082 0.4863 0.082 0.2227 0 0.4199-0.043 0.5918-0.1289 0.1719-0.086 0.3164-0.2227 0.4336-0.4102 0.1172-0.1914 0.2051-0.4394 0.2637-0.7441s0.0879-0.6699 0.0879-1.0957z"/>
<path d="m23.332 49.374c0 0.5313-0.123 0.9785-0.3691 1.3418s-0.582 0.6387-1.0078 0.8262c-0.4219 0.1836-0.8985 0.2754-1.4297 0.2754-0.5313 0-1.0098-0.0918-1.4356-0.2754-0.4257-0.1875-0.7617-0.4629-1.0078-0.8262s-0.3691-0.8105-0.3691-1.3418c0-0.3515 0.0683-0.6699 0.2051-0.955 0.1367-0.2891 0.33-0.5372 0.58-0.7442 0.254-0.2109 0.5508-0.373 0.8907-0.4863 0.3437-0.1133 0.7187-0.1699 1.125-0.1699 0.539 0 1.0215 0.0996 1.4472 0.2988 0.4258 0.1992 0.7598 0.4746 1.002 0.8262 0.2461 0.3515 0.3691 0.7617 0.3691 1.2304zm-1.4179-0.0703c0-0.2851-0.0586-0.5351-0.1758-0.75-0.1172-0.2148-0.2813-0.3808-0.4922-0.498s-0.4551-0.1758-0.7324-0.1758c-0.2813 0-0.5254 0.0586-0.7325 0.1758-0.207 0.1172-0.3691 0.2832-0.4863 0.498-0.1133 0.2149-0.1699 0.4649-0.1699 0.75 0 0.2891 0.0566 0.5391 0.1699 0.75 0.1133 0.207 0.2754 0.3653 0.4863 0.4746 0.211 0.1094 0.459 0.1641 0.7442 0.1641 0.2851 0 0.5312-0.0547 0.7383-0.1641 0.207-0.1093 0.3672-0.2676 0.4804-0.4746 0.1133-0.2109 0.17-0.4609 0.17-0.75zm1.2246-3.8906c0 0.4258-0.1133 0.8047-0.3399 1.1367-0.2226 0.332-0.5312 0.5938-0.9258 0.7852-0.3945 0.1875-0.8437 0.2812-1.3476 0.2812-0.5078 0-0.9609-0.0937-1.3594-0.2812-0.3945-0.1914-0.7051-0.4532-0.9316-0.7852-0.2227-0.332-0.334-0.7109-0.334-1.1367 0-0.5078 0.1113-0.9356 0.334-1.2832 0.2265-0.3516 0.5371-0.6192 0.9316-0.8027 0.3945-0.1836 0.8457-0.2754 1.3535-0.2754s0.959 0.0918 1.3535 0.2754c0.3946 0.1835 0.7032 0.4511 0.9258 0.8027 0.2266 0.3476 0.3399 0.7754 0.3399 1.2832zm-1.4121 0.0469c0-0.2539-0.0508-0.4766-0.1524-0.668-0.0976-0.1953-0.2363-0.3477-0.416-0.457-0.1797-0.1094-0.3926-0.1641-0.6387-0.1641s-0.459 0.0527-0.6386 0.1582c-0.1797 0.1055-0.3184 0.2539-0.4161 0.4453-0.0976 0.1914-0.1464 0.4199-0.1464 0.6856 0 0.2617 0.0488 0.4902 0.1464 0.6855 0.0977 0.1914 0.2364 0.3418 0.4161 0.4512 0.1836 0.1094 0.3984 0.164 0.6445 0.164s0.459-0.0546 0.6387-0.164 0.3183-0.2598 0.416-0.4512c0.0976-0.1953 0.1465-0.4238 0.1465-0.6855zm8.6582 1.2597v1.3946c0 0.6679-0.0664 1.2382-0.1993 1.7109-0.1289 0.4688-0.3164 0.8496-0.5625 1.1426-0.246 0.2929-0.541 0.5078-0.8847 0.6445-0.3399 0.1367-0.7207 0.2051-1.1426 0.2051-0.3359 0-0.6484-0.043-0.9375-0.1289-0.2852-0.086-0.543-0.2207-0.7734-0.4043-0.2305-0.1836-0.4278-0.4199-0.5918-0.709-0.1602-0.293-0.2852-0.6426-0.375-1.0488-0.086-0.4063-0.1289-0.877-0.1289-1.4121v-1.3946c0-0.6718 0.0664-1.2382 0.1992-1.6992 0.1328-0.4648 0.3222-0.8418 0.5683-1.1308 0.2461-0.293 0.5391-0.5059 0.8789-0.6387 0.3438-0.1328 0.7266-0.1992 1.1485-0.1992 0.3398 0 0.6523 0.0429 0.9375 0.1289 0.289 0.082 0.5469 0.2129 0.7734 0.3925 0.2305 0.1797 0.4258 0.4141 0.586 0.7032 0.164 0.2851 0.289 0.6308 0.375 1.0371 0.0859 0.4023 0.1289 0.8711 0.1289 1.4062zm-1.4121 1.5938v-1.8047c0-0.3398-0.0196-0.6387-0.0586-0.8965-0.0391-0.2617-0.0977-0.4824-0.1758-0.6621-0.0742-0.1836-0.168-0.332-0.2813-0.4453-0.1132-0.1172-0.2422-0.2012-0.3867-0.252-0.1445-0.0547-0.3066-0.082-0.4863-0.082-0.2188 0-0.4141 0.043-0.586 0.1289-0.1718 0.082-0.3164 0.2149-0.4335 0.3984-0.1172 0.1836-0.2071 0.4258-0.2696 0.7266-0.0586 0.2969-0.0879 0.6582-0.0879 1.084v1.8047c0 0.3437 0.0196 0.6465 0.0586 0.9082 0.0391 0.2617 0.0977 0.4863 0.1758 0.6738 0.0781 0.1836 0.1719 0.336 0.2813 0.457 0.1132 0.1172 0.2421 0.2032 0.3867 0.2579 0.1484 0.0546 0.3105 0.082 0.4863 0.082 0.2227 0 0.4199-0.043 0.5918-0.1289 0.1719-0.086 0.3164-0.2227 0.4336-0.4102 0.1172-0.1914 0.2051-0.4394 0.2637-0.7441s0.0879-0.6699 0.0879-1.0957z"/>
<path d="m22.02 74.016h0.1758v1.1543h-0.0996c-0.5039 0-0.9395 0.0781-1.3066 0.2343-0.3633 0.1563-0.6621 0.3711-0.8965 0.6446-0.2344 0.2734-0.4102 0.5937-0.5274 0.9609-0.1132 0.3633-0.1699 0.75-0.1699 1.1602v1.3418c0 0.3398 0.0371 0.6406 0.1113 0.9023 0.0743 0.2578 0.1778 0.4746 0.3106 0.6504 0.1367 0.1719 0.293 0.3027 0.4687 0.3926 0.1758 0.0898 0.3653 0.1347 0.5684 0.1347 0.2109 0 0.4023-0.0429 0.5742-0.1289 0.1719-0.0898 0.3184-0.2129 0.4395-0.3691 0.1211-0.1563 0.2129-0.3418 0.2754-0.5567 0.0625-0.2148 0.0937-0.4492 0.0937-0.7031 0-0.2422-0.0312-0.4687-0.0937-0.6797-0.0586-0.2148-0.1465-0.4023-0.2637-0.5625-0.1172-0.164-0.2637-0.291-0.4395-0.3808-0.1718-0.0938-0.3711-0.1406-0.5976-0.1406-0.2813 0-0.5371 0.0664-0.7676 0.1992-0.2266 0.1328-0.4102 0.3066-0.5508 0.5215-0.1367 0.2109-0.2109 0.4355-0.2226 0.6738l-0.5391-0.1758c0.0313-0.3633 0.1113-0.6895 0.2402-0.9785 0.1328-0.2891 0.3067-0.5352 0.5215-0.7383 0.2149-0.2031 0.4629-0.3574 0.7442-0.4629 0.2851-0.1094 0.5976-0.164 0.9375-0.164 0.414 0 0.7734 0.0781 1.0781 0.2343 0.3047 0.1563 0.5566 0.3692 0.7558 0.6387 0.2032 0.2656 0.3536 0.5703 0.4512 0.9141 0.1016 0.3398 0.1524 0.6953 0.1524 1.0664 0 0.4101-0.0625 0.7929-0.1875 1.1484-0.125 0.3516-0.3086 0.6602-0.5508 0.9258-0.2383 0.2656-0.5293 0.4726-0.8731 0.6211-0.3398 0.1484-0.7265 0.2226-1.1601 0.2226-0.4571 0-0.8653-0.0879-1.2246-0.2636-0.3555-0.1758-0.6582-0.418-0.9082-0.7266-0.2461-0.3086-0.4336-0.6641-0.5625-1.0664s-0.1934-0.8281-0.1934-1.2773v-0.586c0-0.6484 0.082-1.2598 0.2461-1.834 0.1641-0.5781 0.416-1.0879 0.7559-1.5293 0.3437-0.4414 0.7832-0.7871 1.3183-1.0371 0.5352-0.2539 1.1738-0.3808 1.916-0.3808zm8.3653 3.6035v1.3945c0 0.668-0.0664 1.2383-0.1993 1.7109-0.1289 0.4688-0.3164 0.8497-0.5625 1.1426-0.246 0.293-0.541 0.5078-0.8847 0.6446-0.3399 0.1367-0.7207 0.205-1.1426 0.205-0.3359 0-0.6484-0.0429-0.9375-0.1289-0.2852-0.0859-0.543-0.2207-0.7734-0.4043-0.2305-0.1836-0.4278-0.4199-0.5918-0.709-0.1602-0.2929-0.2852-0.6425-0.375-1.0488-0.086-0.4062-0.1289-0.8769-0.1289-1.4121v-1.3945c0-0.6719 0.0664-1.2383 0.1992-1.6992 0.1328-0.4649 0.3222-0.8418 0.5683-1.1309 0.2461-0.293 0.5391-0.5059 0.8789-0.6387 0.3438-0.1328 0.7266-0.1992 1.1485-0.1992 0.3398 0 0.6523 0.043 0.9375 0.1289 0.289 0.082 0.5469 0.2129 0.7734 0.3926 0.2305 0.1797 0.4258 0.4141 0.586 0.7031 0.164 0.2852 0.289 0.6309 0.375 1.0371 0.0859 0.4024 0.1289 0.8711 0.1289 1.4063zm-1.4121 1.5937v-1.8047c0-0.3398-0.0196-0.6386-0.0586-0.8964-0.0391-0.2618-0.0977-0.4825-0.1758-0.6622-0.0742-0.1835-0.168-0.332-0.2813-0.4453-0.1132-0.1172-0.2422-0.2011-0.3867-0.2519-0.1445-0.0547-0.3066-0.082-0.4863-0.082-0.2188 0-0.4141 0.0429-0.586 0.1289-0.1718 0.082-0.3164 0.2148-0.4335 0.3984-0.1172 0.1836-0.2071 0.4258-0.2696 0.7266-0.0586 0.2968-0.0879 0.6582-0.0879 1.0839v1.8047c0 0.3438 0.0196 0.6465 0.0586 0.9082 0.0391 0.2618 0.0977 0.4864 0.1758 0.6739 0.0781 0.1836 0.1719 0.3359 0.2813 0.457 0.1132 0.1172 0.2421 0.2031 0.3867 0.2578 0.1484 0.0547 0.3105 0.082 0.4863 0.082 0.2227 0 0.4199-0.0429 0.5918-0.1289 0.1719-0.0859 0.3164-0.2226 0.4336-0.4101 0.1172-0.1914 0.2051-0.4395 0.2637-0.7442s0.0879-0.6699 0.0879-1.0957z"/>
<path d="m23.631 111.66v1.125h-6.1524l-0.0469-0.85 3.6797-5.765h1.1309l-1.2246 2.097-2.1153 3.393zm-1.0664-5.49v8.531h-1.4122v-8.531zm7.8203 3.55v1.395c0 0.668-0.0664 1.238-0.1993 1.711-0.1289 0.469-0.3164 0.85-0.5625 1.143-0.246 0.292-0.541 0.507-0.8847 0.644-0.3399 0.137-0.7207 0.205-1.1426 0.205-0.3359 0-0.6484-0.043-0.9375-0.129-0.2852-0.086-0.543-0.22-0.7734-0.404-0.2305-0.184-0.4278-0.42-0.5918-0.709-0.1602-0.293-0.2852-0.643-0.375-1.049-0.086-0.406-0.1289-0.877-0.1289-1.412v-1.395c0-0.671 0.0664-1.238 0.1992-1.699 0.1328-0.465 0.3222-0.842 0.5683-1.131 0.2461-0.293 0.5391-0.505 0.8789-0.638 0.3438-0.133 0.7266-0.199 1.1485-0.199 0.3398 0 0.6523 0.042 0.9375 0.128 0.289 0.082 0.5469 0.213 0.7734 0.393 0.2305 0.18 0.4258 0.414 0.586 0.703 0.164 0.285 0.289 0.631 0.375 1.037 0.0859 0.403 0.1289 0.871 0.1289 1.406zm-1.4121 1.594v-1.804c0-0.34-0.0196-0.639-0.0586-0.897-0.0391-0.262-0.0977-0.482-0.1758-0.662-0.0742-0.184-0.168-0.332-0.2813-0.445-0.1132-0.118-0.2422-0.202-0.3867-0.252-0.1445-0.055-0.3066-0.082-0.4863-0.082-0.2188 0-0.4141 0.043-0.586 0.129-0.1718 0.082-0.3164 0.214-0.4335 0.398-0.1172 0.184-0.2071 0.426-0.2696 0.727-0.0586 0.296-0.0879 0.658-0.0879 1.084v1.804c0 0.344 0.0196 0.647 0.0586 0.908 0.0391 0.262 0.0977 0.487 0.1758 0.674 0.0781 0.184 0.1719 0.336 0.2813 0.457 0.1132 0.117 0.2421 0.203 0.3867 0.258 0.1484 0.055 0.3105 0.082 0.4863 0.082 0.2227 0 0.4199-0.043 0.5918-0.129s0.3164-0.222 0.4336-0.41c0.1172-0.191 0.2051-0.439 0.2637-0.744s0.0879-0.67 0.0879-1.096z"/>
<path d="m23.473 145.48v1.125h-5.7188v-0.967l2.7773-3.029c0.3047-0.344 0.545-0.641 0.7208-0.891 0.1757-0.25 0.2988-0.474 0.3691-0.673 0.0742-0.204 0.1113-0.401 0.1113-0.592 0-0.27-0.0508-0.506-0.1523-0.709-0.0977-0.207-0.2422-0.369-0.4336-0.487-0.1914-0.121-0.4238-0.181-0.6973-0.181-0.3164 0-0.582 0.068-0.7969 0.205-0.2148 0.137-0.3769 0.326-0.4863 0.568-0.1094 0.239-0.164 0.512-0.164 0.821h-1.4122c0-0.497 0.1133-0.95 0.3399-1.36 0.2265-0.414 0.5547-0.742 0.9844-0.984 0.4297-0.246 0.9472-0.369 1.5527-0.369 0.5703 0 1.0547 0.095 1.4531 0.287 0.3985 0.191 0.7012 0.463 0.9082 0.814 0.211 0.352 0.3164 0.768 0.3164 1.248 0 0.266-0.0429 0.53-0.1289 0.791-0.0859 0.262-0.209 0.524-0.3691 0.785-0.1563 0.258-0.3418 0.518-0.5567 0.78-0.2148 0.258-0.4511 0.519-0.7089 0.785l-1.8457 2.033zm6.9121-3.855v1.394c0 0.668-0.0664 1.238-0.1993 1.711-0.1289 0.469-0.3164 0.85-0.5625 1.143-0.246 0.293-0.541 0.507-0.8847 0.644-0.3399 0.137-0.7207 0.205-1.1426 0.205-0.3359 0-0.6484-0.043-0.9375-0.129-0.2852-0.086-0.543-0.22-0.7734-0.404-0.2305-0.184-0.4278-0.42-0.5918-0.709-0.1602-0.293-0.2852-0.642-0.375-1.049-0.086-0.406-0.1289-0.877-0.1289-1.412v-1.394c0-0.672 0.0664-1.239 0.1992-1.7 0.1328-0.464 0.3222-0.841 0.5683-1.13 0.2461-0.293 0.5391-0.506 0.8789-0.639 0.3438-0.133 0.7266-0.199 1.1485-0.199 0.3398 0 0.6523 0.043 0.9375 0.129 0.289 0.082 0.5469 0.212 0.7734 0.392 0.2305 0.18 0.4258 0.414 0.586 0.703 0.164 0.285 0.289 0.631 0.375 1.037 0.0859 0.403 0.1289 0.871 0.1289 1.407zm-1.4121 1.593v-1.804c0-0.34-0.0196-0.639-0.0586-0.897-0.0391-0.262-0.0977-0.482-0.1758-0.662-0.0742-0.183-0.168-0.332-0.2813-0.445-0.1132-0.117-0.2422-0.201-0.3867-0.252-0.1445-0.055-0.3066-0.082-0.4863-0.082-0.2188 0-0.4141 0.043-0.586 0.129-0.1718 0.082-0.3164 0.215-0.4335 0.398-0.1172 0.184-0.2071 0.426-0.2696 0.727-0.0586 0.297-0.0879 0.658-0.0879 1.084v1.804c0 0.344 0.0196 0.647 0.0586 0.909 0.0391 0.261 0.0977 0.486 0.1758 0.673 0.0781 0.184 0.1719 0.336 0.2813 0.457 0.1132 0.118 0.2421 0.204 0.3867 0.258 0.1484 0.055 0.3105 0.082 0.4863 0.082 0.2227 0 0.4199-0.043 0.5918-0.129s0.3164-0.222 0.4336-0.41c0.1172-0.191 0.2051-0.439 0.2637-0.744s0.0879-0.67 0.0879-1.096z"/>
<path d="m30.385 173.02v1.394c0 0.668-0.0664 1.238-0.1993 1.711-0.1289 0.469-0.3164 0.85-0.5625 1.143-0.246 0.293-0.541 0.507-0.8847 0.644-0.3399 0.137-0.7207 0.205-1.1426 0.205-0.3359 0-0.6484-0.043-0.9375-0.129-0.2852-0.086-0.543-0.22-0.7734-0.404-0.2305-0.184-0.4278-0.42-0.5918-0.709-0.1602-0.293-0.2852-0.643-0.375-1.049-0.086-0.406-0.1289-0.877-0.1289-1.412v-1.394c0-0.672 0.0664-1.239 0.1992-1.7 0.1328-0.465 0.3222-0.841 0.5683-1.131 0.2461-0.293 0.5391-0.505 0.8789-0.638 0.3438-0.133 0.7266-0.199 1.1485-0.199 0.3398 0 0.6523 0.043 0.9375 0.128 0.289 0.082 0.5469 0.213 0.7734 0.393 0.2305 0.18 0.4258 0.414 0.586 0.703 0.164 0.285 0.289 0.631 0.375 1.037 0.0859 0.403 0.1289 0.871 0.1289 1.407zm-1.4121 1.593v-1.804c0-0.34-0.0196-0.639-0.0586-0.897-0.0391-0.262-0.0977-0.482-0.1758-0.662-0.0742-0.184-0.168-0.332-0.2813-0.445-0.1132-0.117-0.2422-0.201-0.3867-0.252-0.1445-0.055-0.3066-0.082-0.4863-0.082-0.2188 0-0.4141 0.043-0.586 0.129-0.1718 0.082-0.3164 0.214-0.4335 0.398-0.1172 0.184-0.2071 0.426-0.2696 0.727-0.0586 0.296-0.0879 0.658-0.0879 1.084v1.804c0 0.344 0.0196 0.647 0.0586 0.908 0.0391 0.262 0.0977 0.487 0.1758 0.674 0.0781 0.184 0.1719 0.336 0.2813 0.457 0.1132 0.118 0.2421 0.203 0.3867 0.258 0.1484 0.055 0.3105 0.082 0.4863 0.082 0.2227 0 0.4199-0.043 0.5918-0.129s0.3164-0.222 0.4336-0.41c0.1172-0.191 0.2051-0.439 0.2637-0.744s0.0879-0.67 0.0879-1.096z"/>
</g>
<g transform="matrix(1 0 0 1.0194 9.4118e-7 -3.9105)" stroke="#747474">
<path d="m50.695 14.031v164.03h0.22794v-164.03z" fill="#747474" stroke-width=".77206"/>
<line x1="39" x2="51" y1="14.145" y2="14.145"/>
<line x1="45" x2="51" y1="17.76" y2="17.76"/>
<line x1="45" x2="51" y1="21.02" y2="21.02"/>
<line x1="45" x2="51" y1="24.28" y2="24.28"/>
<line x1="45" x2="51" y1="27.54" y2="27.54"/>
<line x1="45" x2="51" y1="30.8" y2="30.8"/>
<line x1="45" x2="51" y1="34.06" y2="34.06"/>
<line x1="45" x2="51" y1="37.32" y2="37.32"/>
<line x1="45" x2="51" y1="40.58" y2="40.58"/>
<line x1="45" x2="51" y1="43.84" y2="43.84"/>
<line x1="39" x2="51" y1="47.1" y2="47.1"/>
<line x1="45" x2="51" y1="50.36" y2="50.36"/>
<line x1="45" x2="51" y1="53.62" y2="53.62"/>
<line x1="45" x2="51" y1="56.88" y2="56.88"/>
<line x1="45" x2="51" y1="60.14" y2="60.14"/>
<line x1="45" x2="51" y1="63.4" y2="63.4"/>
<line x1="45" x2="51" y1="66.66" y2="66.66"/>
<line x1="45" x2="51" y1="69.92" y2="69.92"/>
<line x1="45" x2="51" y1="73.18" y2="73.18"/>
<line x1="45" x2="51" y1="76.44" y2="76.44"/>
<line x1="39" x2="51" y1="79.7" y2="79.7"/>
<line x1="45" x2="51" y1="82.96" y2="82.96"/>
<line x1="45" x2="51" y1="86.22" y2="86.22"/>
<line x1="45" x2="51" y1="89.48" y2="89.48"/>
<line x1="45" x2="51" y1="92.74" y2="92.74"/>
<line x1="45" x2="51" y1="96" y2="96"/>
<line x1="45" x2="51" y1="99.26" y2="99.26"/>
<line x1="45" x2="51" y1="102.52" y2="102.52"/>
<line x1="45" x2="51" y1="105.78" y2="105.78"/>
<line x1="45" x2="51" y1="109.04" y2="109.04"/>
<line x1="39" x2="51" y1="112.3" y2="112.3"/>
<line x1="45" x2="51" y1="115.56" y2="115.56"/>
<line x1="45" x2="51" y1="118.82" y2="118.82"/>
<line x1="45" x2="51" y1="122.08" y2="122.08"/>
<line x1="45" x2="51" y1="125.34" y2="125.34"/>
<line x1="45" x2="51" y1="128.6" y2="128.6"/>
<line x1="45" x2="51" y1="131.86" y2="131.86"/>
<line x1="45" x2="51" y1="135.12" y2="135.12"/>
<line x1="45" x2="51" y1="138.38" y2="138.38"/>
<line x1="45" x2="51" y1="141.64" y2="141.64"/>
<line x1="39" x2="51" y1="144.9" y2="144.9"/>
<line x1="45" x2="51" y1="148.16" y2="148.16"/>
<line x1="45" x2="51" y1="151.42" y2="151.42"/>
<line x1="45" x2="51" y1="154.68" y2="154.68"/>
<line x1="45" x2="51" y1="157.94" y2="157.94"/>
<line x1="45" x2="51" y1="161.2" y2="161.2"/>
<line x1="45" x2="51" y1="164.46" y2="164.46"/>
<line x1="45" x2="51" y1="167.72" y2="167.72"/>
<line x1="45" x2="51" y1="170.98" y2="170.98"/>
<line x1="45" x2="51" y1="174.24" y2="174.24"/>
<line x1="38.985" x2="50.985" y1="177.96" y2="177.96"/>
</g>
</g><path d="m96 200c2.2091 0 4-1.791 4-4v-192c0-2.2091-1.7909-4-4-4h-4c-2.2091 0-4 1.7909-4 4v192c0 2.209 1.7909 4 4 4h4z" fill="#93979B"/><path d="m96 200c2.2091 0 4-1.791 4-4v-192c0-2.2091-1.7909-4-4-4h-4c-2.2091 0-4 1.7909-4 4v192c0 2.209 1.7909 4 4 4h4z" fill="url(#paint1_linear_3742_299967)"/><path d="m96 198.5c1.3807 0 2.5-1.119 2.5-2.5v-192c0-1.3807-1.1193-2.5-2.5-2.5h-4c-1.3807 0-2.5 1.1193-2.5 2.5v192c0 1.381 1.1193 2.5 2.5 2.5h4z" stroke="#000" stroke-opacity=".12" stroke-width="3"/><path d="m76 140c0 2.209 1.7908 4 3.9999 4h4c2.2092 0 4.0001-1.791 4.0001-4v-92c0-2.2091-1.7909-4-4-4h-4c-2.2091 0-4 1.7909-4 4v92z" fill="#647484"/><path d="m76 140c0 2.209 1.7908 4 3.9999 4h4c2.2092 0 4.0001-1.791 4.0001-4v-92c0-2.2091-1.7909-4-4-4h-4c-2.2091 0-4 1.7909-4 4v92z" fill="url(#paint2_linear_3742_299967)"/><path d="m77.5 140c0 1.38 1.1193 2.5 2.4999 2.5h4c1.3808 0 2.5001-1.119 2.5001-2.5v-92c0-1.3807-1.1193-2.5-2.5-2.5h-4c-1.3807 0-2.5 1.1193-2.5 2.5v92z" stroke="#000" stroke-opacity=".12" stroke-width="3"/><defs>
<linearGradient id="paint0_linear_3742_299967" x1="76" x2=".00010292" y1="100" y2="100.09" gradientUnits="userSpaceOnUse">
<stop stop-color="#020202" stop-opacity=".35" offset="0"/>
<stop stop-color="#020202" stop-opacity=".12" offset=".02629"/>
<stop stop-color="#fff" stop-opacity=".12" offset=".11617"/>
<stop stop-color="#fff" stop-opacity=".3" offset=".49829"/>
<stop stop-color="#fff" stop-opacity=".12" offset=".88762"/>
<stop stop-color="#020202" stop-opacity=".12" offset=".96591"/>
<stop stop-color="#020202" stop-opacity=".35" offset="1"/>
</linearGradient>
<linearGradient id="paint1_linear_3742_299967" x1="89.93" x2="134" y1="-14.344" y2="205.53" gradientUnits="userSpaceOnUse">
<stop stop-color="#020202" stop-opacity=".35" offset="0"/>
<stop stop-color="#020202" stop-opacity=".12" offset=".23574"/>
<stop stop-color="#fff" stop-opacity=".12" offset=".39937"/>
<stop stop-color="#fff" stop-opacity=".3" offset=".49829"/>
<stop stop-color="#fff" stop-opacity=".12" offset=".59721"/>
<stop stop-color="#020202" stop-opacity=".12" offset=".76303"/>
<stop stop-color="#020202" stop-opacity=".35" offset="1"/>
</linearGradient>
<linearGradient id="paint2_linear_3742_299967" x1="83.045" x2="78.639" y1="47.812" y2="139.03" gradientUnits="userSpaceOnUse">
<stop stop-color="#020202" stop-opacity=".2" offset="0"/>
<stop stop-color="#020202" stop-opacity=".18" offset=".090959"/>
<stop stop-color="#020202" stop-opacity=".1" offset=".1"/>
<stop stop-color="#020202" stop-opacity=".08" offset=".20513"/>
<stop stop-color="#020202" stop-opacity=".05" offset=".21555"/>
<stop stop-color="#020202" stop-opacity=".02" offset=".36962"/>
<stop stop-color="#fff" stop-opacity=".01" offset=".37768"/>
<stop stop-color="#fff" stop-opacity=".01" offset=".62413"/>
<stop stop-color="#020202" stop-opacity=".02" offset=".6313"/>
<stop stop-color="#020202" stop-opacity=".05" offset=".77601"/>
<stop stop-color="#020202" stop-opacity=".08" offset=".7898"/>
<stop stop-color="#020202" stop-opacity=".1" offset=".9"/>
<stop stop-color="#020202" stop-opacity=".18" offset=".90846"/>
<stop stop-color="#020202" stop-opacity=".2" offset="1"/>
</linearGradient>
<filter id="filter0_ii_3742_299961" x="20" y="162" width="60" height="32" color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
<feColorMatrix in="SourceAlpha" result="hardAlpha" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/>
<feOffset dx="-2" dy="2"/>
<feGaussianBlur stdDeviation="3"/>
<feComposite in2="hardAlpha" k2="-1" k3="1" operator="arithmetic"/>
<feColorMatrix values="0 0 0 0 0.445833 0 0 0 0 0.445833 0 0 0 0 0.445833 0 0 0 0.5 0"/>
<feBlend in2="shape" result="effect1_innerShadow_3742_299961"/>
<feColorMatrix in="SourceAlpha" result="hardAlpha" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/>
<feOffset dx="2" dy="-2"/>
<feGaussianBlur stdDeviation="2"/>
<feComposite in2="hardAlpha" k2="-1" k3="1" operator="arithmetic"/>
<feColorMatrix values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0.5 0"/>
<feBlend in2="effect1_innerShadow_3742_299961" result="effect2_innerShadow_3742_299961"/>
</filter>
</defs><g tb:tag="progressBar">
<rect x="56" y="10.5" width="6" height="169" ry="1.12" stroke="#cecece" tb:tag="progressBorder"/>
<rect transform="scale(1,-1)" x="56" y="-180" width="6" height="62" ry="1.12" fill="#4d94e1" stroke="#4d94e1" tb:tag="progressFill"/>
<circle cx="59" cy="185" r="7" fill="#4d94e1" tb:tag="progressCircle"/>
</g><g transform="translate(0,166)" fill="#1c943e" style="display: none;" tb:tag="progress-indicator">
<path d="m52 10.562 10.5 6.062v-12.124z" style=""/>
</g><g transform="translate(-12)" filter="url(#filter0_ii_3742_299961)" style="display: none;" tb:tag="value-box">
<rect x="22" y="164" width="56" height="28" rx="4" fill="#fffefe" fill-opacity=".75" tb:tag="value-box-background" style=""/>
<rect x="23" y="165" width="54" height="26" rx="3" stroke="#fff" stroke-width="2" style=""/>
<text x="49.853027" y="179.5625" fill="#727171" font-family="Roboto" font-size="14px" font-weight="500" text-anchor="middle" tb:tag="value-text" xml:space="preserve" style=""><tspan dominant-baseline="middle">37%</tspan></text>
</g><path d="m25.56-0.12402s-25.56 0-25.56 33.5v164.18c0 1.3256 0.68053 2.3202 1.52 2.3202h72.96c0.83942 0 1.52-0.9946 1.52-2.3202v-164.18c0-33.5-25.107-33.5-25.107-33.5h-12.893zm25.487 40.6c-0.48969 0-0.88669 0.6268-0.88669 1.4v150.2c0 0.7732 0.39697 1.4 0.88669 1.4h5.5733c0.48969 0 0.88669-0.6268 0.88669-1.4v-150.2c0-0.7732-0.39697-1.4-0.88669-1.4z" fill-opacity="0" tb:tag="clickArea"/>
</svg>

After

Width:  |  Height:  |  Size: 45 KiB

688
application/src/main/data/json/system/scada_symbols/small-meter.svg

@ -0,0 +1,688 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:tb="https://thingsboard.io/svg" width="100" height="200" fill="none" version="1.1" viewBox="0 0 100 200"><tb:metadata xmlns=""><![CDATA[{
"title": "Small meter",
"description": "Small meter displays the current value with a moving pointer on the scale.",
"searchTags": [
"scale",
"level",
"progress",
"thermometer"
],
"widgetSizeX": 1,
"widgetSizeY": 2,
"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": "progress-indicator",
"stateRenderFunction": "function calculateOffset(value, minValue, maxValue, initial) {\n var clampedValue = Math.max(Math.min(value, Math.max(minValue, maxValue)), Math.min(minValue, maxValue));\n var normalizedValue = minValue < maxValue\n ? (clampedValue - minValue) / (maxValue - minValue)\n : (minValue - clampedValue) / (minValue - maxValue);\n var offset = initial - (normalizedValue * initial);\n return offset;\n}\n\nvar valueSet = element.remember('valueSet');\n\nif (ctx.properties.progressArrow && !ctx.properties.progressBar) {\n element.show();\n var initial = ctx.properties.valueBox ? 132 : 167;\n if (!valueSet) {\n element.remember('valueSet', true);\n element.transform({\n translateY: initial\n });\n }\n \n var minValue = ctx.properties.minValue;\n var maxValue = ctx.properties.maxValue;\n var value = ctx.values.value;\n \n var colorProcessor = ctx.properties.progressArrowColor;\n colorProcessor.update(value);\n var fill = colorProcessor.color;\n element.attr({fill: fill});\n \n var offset = calculateOffset(value, minValue, maxValue, initial);\n\n var elementOffset = element.remember('offset');\n if (offset !== elementOffset) {\n element.remember('offset', offset);\n ctx.api.cssAnimate(element, 500).transform({\n translateY: offset\n });\n }\n} else {\n element.hide();\n if (valueSet) {\n element.remember('valueSet', false);\n }\n}",
"actions": null
},
{
"tag": "progressBar",
"stateRenderFunction": "if (ctx.properties.progressBar) {\n element.show();\n} else {\n element.hide();\n}",
"actions": null
},
{
"tag": "progressBorder",
"stateRenderFunction": "if (!ctx.properties.valueBox) {\n element.attr({'height': 168})\n}",
"actions": null
},
{
"tag": "progressCircle",
"stateRenderFunction": "if (!ctx.properties.valueBox) {\n element.attr({cy:185});\n}",
"actions": null
},
{
"tag": "progressFill",
"stateRenderFunction": "if (!ctx.properties.valueBox) {\n element.attr({y:-180});\n}\n\nfunction calculateOffset(value, minValue, maxValue, initial) {\n var clampedValue = Math.max(Math.min(value, Math.max(minValue, maxValue)), Math.min(minValue, maxValue));\n var normalizedValue = minValue < maxValue\n ? (clampedValue - minValue) / (maxValue - minValue)\n : (minValue - clampedValue) / (minValue - maxValue);\n var offset = normalizedValue * initial;\n return offset;\n}\n\nvar valueSet = element.remember('valueSet');\nif (ctx.properties.progressBar) {\n var initial = ctx.properties.valueBox ? 132: 168;\n if (!valueSet) {\n element.remember('valueSet', true);\n element.attr({height: 2});\n }\n \n var minValue = ctx.properties.minValue;\n var maxValue = ctx.properties.maxValue;\n var value = ctx.values.value;\n \n var colorProcessor = ctx.properties.progressBarColor;\n colorProcessor.update(value);\n var fill = colorProcessor.color;\n element.attr({fill: fill, stroke: fill});\n ctx.tags.progressCircle[0].fill(fill);\n \n var height = calculateOffset(value, minValue, maxValue, initial);\n\n var elementHeight = element.remember('height');\n if (height !== elementHeight) {\n element.remember('height', height);\n ctx.api.cssAnimate(element, 500).attr({height: height+2});\n }\n} else {\n if (valueSet) {\n element.remember('valueSet', false);\n }\n}",
"actions": null
},
{
"tag": "scale",
"stateRenderFunction": "var scaleSet = element.remember('scaleSet');\nif (!scaleSet) {\n element.remember('scaleSet', true);\n element.clear();\n \n var majorIntervals = ctx.properties.majorIntervals;\n var minorIntervals = ctx.properties.minorIntervals;\n var minValue = ctx.properties.minValue;\n var maxValue = ctx.properties.maxValue;\n \n var start = 11;\n var end = ctx.properties.valueBox ? 132 : 167;\n var majorIntervalLength = end / majorIntervals;\n var minorIntervalLength = majorIntervalLength / minorIntervals;\n element.add(ctx.svg.line(63, end+11, 63, 11).stroke({ width: 1 }).attr({class: 'majorTick'}));\n for (var i = 0; i < majorIntervals+1; i++) {\n var y = start + i * majorIntervalLength;\n var line = ctx.svg.line(51, y, 63, y).stroke({ width: 1 }).attr({class: 'majorTick'});\n element.add(line);\n var majorText = (maxValue - ((maxValue - (minValue)) / (majorIntervals) * i)).toFixed(0);\n var majorTickText = ctx.svg.text(majorText);\n majorTickText.attr({x: 45, y: y + 2, 'text-anchor': 'end', class: 'majorTickText'});\n majorTickText.first().attr({'dominant-baseline': 'middle'});\n element.add(majorTickText);\n if (i < majorIntervals) {\n drawMinorTicks(y, minorIntervals, minorIntervalLength);\n }\n }\n}\n\nvar majorFont = ctx.properties.majorFont;\nvar majorColor = ctx.properties.majorColor;\nvar minorColor = ctx.properties.minorColor;\nif (ctx.values.critical) {\n majorColor = ctx.properties.majorCriticalColor;\n minorColor = ctx.properties.minorCriticalColor;\n} else if (ctx.values.warning) {\n majorColor = ctx.properties.minorWarningColor;\n minorColor = ctx.properties.minorWarningColor;\n}\n\nvar majorTicks = element.find('line.majorTick');\nmajorTicks.forEach(t => t.attr({stroke: majorColor}));\n\nvar majorTicksText = element.find('text.majorTickText');\nctx.api.font(majorTicksText, majorFont, majorColor);\n\nvar minorTicks = element.find('line.minorTick');\nminorTicks.forEach(t => t.attr({stroke: minorColor}));\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\nfunction drawMinorTicks(start, minorIntervals, minorIntervalLength) {\n for (var i = 1; i < minorIntervals; i++) {\n var minorY = start + i * minorIntervalLength;\n var minorLine = ctx.svg.line(57, minorY, 63, minorY).stroke({ width: 1 }).attr({class: 'minorTick'});\n element.add(minorLine);\n }\n}",
"actions": null
},
{
"tag": "value-box",
"stateRenderFunction": "if (ctx.properties.valueBox) {\n element.show();\n} else {\n element.hide();\n}",
"actions": null
},
{
"tag": "value-box-background",
"stateRenderFunction": "if (ctx.properties.valueBox) {\n var colorProcessor = ctx.properties.valueBoxColor;\n colorProcessor.update(ctx.values.value);\n element.attr({fill: colorProcessor.color});\n}",
"actions": null
},
{
"tag": "value-text",
"stateRenderFunction": "if (ctx.properties.valueBox) {\n var valueTextFont = ctx.properties.valueTextFont;\n var valueTextColor = ctx.properties.valueTextColor;\n var currentVolume = ctx.values.value;\n var valueText = ctx.api.formatValue(currentVolume, 0, ctx.properties.valueUnits, false);\n var colorProcessor = ctx.properties.valueTextColor;\n colorProcessor.update(ctx.values.value);\n ctx.api.font(element, valueTextFont, colorProcessor.color);\n ctx.api.text(element, valueText);\n}",
"actions": null
}
],
"behavior": [
{
"id": "value",
"name": "{i18n:scada.symbol.value}",
"hint": null,
"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": "waterLevel"
},
"dataToValue": {
"type": "NONE",
"dataToValueFunction": "/* Should return boolean value */\nreturn data;"
}
},
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": null
},
{
"id": "warning",
"name": "{i18n:scada.symbol.warning-state}",
"hint": "{i18n:scada.symbol.warning-state-hint}",
"group": null,
"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": "critical",
"name": "{i18n:scada.symbol.critical-state}",
"hint": "{i18n:scada.symbol.critical-state-hint}",
"group": null,
"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": "criticalAnimation",
"name": "{i18n:scada.symbol.critical-state-animation}",
"hint": "{i18n:scada.symbol.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": "minValue",
"name": "{i18n:scada.symbol.min-max-value}",
"type": "number",
"default": 0,
"required": true,
"subLabel": "{i18n:scada.symbol.min-value}",
"divider": true,
"min": -1000,
"step": 1,
"disabled": false,
"visible": true
},
{
"id": "maxValue",
"name": "{i18n:scada.symbol.min-max-value}",
"type": "number",
"default": 100,
"required": true,
"subLabel": "{i18n:scada.symbol.max-value}",
"max": 1000,
"step": 1,
"disabled": false,
"visible": true
},
{
"id": "backgroundColor",
"name": "{i18n:scada.symbol.background-color}",
"type": "color",
"default": "#FFFFFF",
"disabled": false,
"visible": true
},
{
"id": "progressBar",
"name": "{i18n:scada.symbol.progress-bar}",
"type": "switch",
"default": true,
"disabled": false,
"visible": true
},
{
"id": "progressBarColor",
"name": "{i18n:scada.symbol.progress-bar}",
"type": "color_settings",
"default": {
"type": "constant",
"color": "#4D94E1",
"gradient": {
"advancedMode": false,
"gradient": [
"rgba(0, 255, 0, 1)",
"rgba(255, 0, 0, 1)"
],
"gradientAdvanced": [
{
"source": {
"type": "constant"
},
"color": "rgba(0, 255, 0, 1)"
},
{
"source": {
"type": "constant"
},
"color": "rgba(255, 0, 0, 1)"
}
],
"minValue": 0,
"maxValue": 100
},
"rangeList": {
"advancedMode": false,
"range": [],
"rangeAdvanced": []
},
"colorFunction": "var temperature = value;\nif (typeof temperature !== undefined) {\n var percent = (temperature + 60)/120 * 100;\n return tinycolor.mix('blue', 'red', percent).toHexString();\n}\nreturn 'blue';"
},
"disableOnProperty": "progressBar",
"disabled": false,
"visible": true
},
{
"id": "progressArrow",
"name": "{i18n:scada.symbol.progress-arrow}",
"type": "switch",
"default": false,
"disabled": false,
"visible": true
},
{
"id": "progressArrowColor",
"name": "{i18n:scada.symbol.progress-arrow}",
"type": "color_settings",
"default": {
"type": "constant",
"color": "#1C943E",
"gradient": {
"advancedMode": false,
"gradient": [
"rgba(0, 255, 0, 1)",
"rgba(255, 0, 0, 1)"
],
"gradientAdvanced": [
{
"source": {
"type": "constant"
},
"color": "rgba(0, 255, 0, 1)"
},
{
"source": {
"type": "constant"
},
"color": "rgba(255, 0, 0, 1)"
}
],
"minValue": 0,
"maxValue": 100
},
"rangeList": {
"advancedMode": false,
"range": [],
"rangeAdvanced": []
},
"colorFunction": "var temperature = value;\nif (typeof temperature !== undefined) {\n var percent = (temperature + 60)/120 * 100;\n return tinycolor.mix('blue', 'red', percent).toHexString();\n}\nreturn 'blue';"
},
"disableOnProperty": "progressArrow",
"disabled": true,
"visible": true
},
{
"id": "valueBox",
"name": "{i18n:scada.symbol.value-box}",
"type": "switch",
"default": true,
"disabled": false,
"visible": true
},
{
"id": "valueBoxColor",
"name": "{i18n:scada.symbol.value-box}",
"type": "color_settings",
"default": {
"type": "constant",
"color": "#F3F3F3",
"gradient": {
"advancedMode": false,
"gradient": [
"rgba(0, 255, 0, 1)",
"rgba(255, 0, 0, 1)"
],
"gradientAdvanced": [
{
"source": {
"type": "constant"
},
"color": "rgba(0, 255, 0, 1)"
},
{
"source": {
"type": "constant"
},
"color": "rgba(255, 0, 0, 1)"
}
],
"minValue": 0,
"maxValue": 100
},
"rangeList": {
"advancedMode": false,
"range": [],
"rangeAdvanced": []
},
"colorFunction": "var temperature = value;\nif (typeof temperature !== undefined) {\n var percent = (temperature + 60)/120 * 100;\n return tinycolor.mix('blue', 'red', percent).toHexString();\n}\nreturn 'blue';"
},
"disableOnProperty": "valueBox",
"disabled": true,
"visible": true
},
{
"id": "valueUnits",
"name": "{i18n:scada.symbol.value-text}",
"type": "units",
"default": "%",
"subLabel": "{i18n:scada.symbol.units}",
"disableOnProperty": "valueBox",
"disabled": true,
"visible": true
},
{
"id": "valueTextFont",
"name": "{i18n:scada.symbol.value-text}",
"type": "font",
"default": {
"size": 14,
"sizeUnit": "px",
"family": "Roboto",
"weight": "500",
"style": "normal"
},
"disableOnProperty": "valueBox",
"disabled": true,
"visible": true
},
{
"id": "valueTextColor",
"name": "{i18n:scada.symbol.value-text}",
"type": "color_settings",
"default": {
"type": "constant",
"color": "#0000008A",
"gradient": {
"advancedMode": false,
"gradient": [
"rgba(0, 255, 0, 1)",
"rgba(255, 0, 0, 1)"
],
"gradientAdvanced": [
{
"source": {
"type": "constant"
},
"color": "rgba(0, 255, 0, 1)"
},
{
"source": {
"type": "constant"
},
"color": "rgba(255, 0, 0, 1)"
}
],
"minValue": 0,
"maxValue": 100
},
"rangeList": {
"advancedMode": false,
"range": [],
"rangeAdvanced": []
},
"colorFunction": "var temperature = value;\nif (typeof temperature !== undefined) {\n var percent = (temperature + 60)/120 * 100;\n return tinycolor.mix('blue', 'red', percent).toHexString();\n}\nreturn 'blue';"
},
"disableOnProperty": "valueBox",
"disabled": true,
"visible": true
},
{
"id": "majorIntervals",
"name": "{i18n:scada.symbol.major-ticks}",
"type": "number",
"default": 5,
"subLabel": "{i18n:scada.symbol.intervals}",
"divider": true,
"min": 1,
"step": 1,
"disabled": false,
"visible": true
},
{
"id": "majorFont",
"name": "{i18n:scada.symbol.major-ticks}",
"type": "font",
"default": {
"size": 12,
"sizeUnit": "px",
"family": "Roboto",
"weight": "500",
"style": "normal"
},
"disabled": false,
"visible": true
},
{
"id": "majorColor",
"name": "{i18n:scada.symbol.major-ticks-color}",
"type": "color",
"default": "#747474",
"subLabel": "{i18n:scada.symbol.normal}",
"divider": true,
"disabled": false,
"visible": true
},
{
"id": "majorWarningColor",
"name": "{i18n:scada.symbol.major-ticks-color}",
"type": "color",
"default": "#FAA405",
"subLabel": "{i18n:scada.symbol.warning}",
"divider": true,
"disabled": false,
"visible": true
},
{
"id": "majorCriticalColor",
"name": "{i18n:scada.symbol.major-ticks-color}",
"type": "color",
"default": "#D12730",
"subLabel": "{i18n:scada.symbol.critical}",
"disabled": false,
"visible": true
},
{
"id": "minorIntervals",
"name": "{i18n:scada.symbol.minor-ticks}",
"type": "number",
"default": 10,
"subLabel": "{i18n:scada.symbol.intervals}",
"min": 1,
"disabled": false,
"visible": true
},
{
"id": "minorColor",
"name": "{i18n:scada.symbol.minor-ticks-color}",
"type": "color",
"default": "#747474",
"subLabel": "{i18n:scada.symbol.normal}",
"divider": true,
"disabled": false,
"visible": true
},
{
"id": "minorWarningColor",
"name": "{i18n:scada.symbol.minor-ticks-color}",
"type": "color",
"default": "#FAA405",
"subLabel": "{i18n:scada.symbol.warning}",
"divider": true,
"disabled": false,
"visible": true
},
{
"id": "minorCriticalColor",
"name": "{i18n:scada.symbol.minor-ticks-color}",
"type": "color",
"default": "#D12730",
"subLabel": "{i18n:scada.symbol.critical}",
"disabled": false,
"visible": true
}
]
}]]></tb:metadata>
<path d="m16 200c-2.2091 0-4-1.791-4-4v-192c0-2.2091 1.7909-4 4-4h68c2.2091 0 4 1.7909 4 4v192c0 2.209-1.7909 4-4 4h-68z" fill="#E5E5E5" tb:tag="background"/><path d="m16 200c-2.2091 0-4-1.791-4-4v-192c0-2.2091 1.7909-4 4-4h68c2.2091 0 4 1.7909 4 4v192c0 2.209-1.7909 4-4 4h-68z" fill="url(#paint0_linear_3742_299961)"/><path d="m16 198.5c-1.3807 0-2.5-1.119-2.5-2.5v-192c0-1.3807 1.1193-2.5 2.5-2.5h68c1.3807 0 2.5 1.1193 2.5 2.5v192c0 1.381-1.1193 2.5-2.5 2.5h-68z" stroke="#000" stroke-opacity=".12" stroke-width="3"/><g tb:tag="scale">
<path d="m28.539 10.088v8.5605h-1.4121v-6.8848l-2.0918 0.709v-1.166l3.3339-1.2187zm8.7754 3.58v1.3946c0 0.6679-0.0665 1.2382-0.1993 1.7109-0.1289 0.4688-0.3164 0.8496-0.5625 1.1426-0.2461 0.2929-0.541 0.5078-0.8847 0.6445-0.3399 0.1367-0.7207 0.2051-1.1426 0.2051-0.3359 0-0.6484-0.043-0.9375-0.1289-0.2852-0.086-0.543-0.2207-0.7734-0.4043-0.2305-0.1836-0.4278-0.4199-0.5918-0.709-0.1602-0.293-0.2852-0.6426-0.375-1.0488-0.086-0.4063-0.1289-0.877-0.1289-1.4121v-1.3946c0-0.6718 0.0664-1.2383 0.1992-1.6992 0.1328-0.4648 0.3222-0.8418 0.5683-1.1308 0.2461-0.293 0.5391-0.5059 0.8789-0.6387 0.3438-0.1328 0.7266-0.1992 1.1485-0.1992 0.3398 0 0.6523 0.0429 0.9375 0.1289 0.289 0.082 0.5468 0.2129 0.7734 0.3925 0.2305 0.1797 0.4258 0.4141 0.5859 0.7032 0.1641 0.2851 0.2891 0.6308 0.375 1.0371 0.086 0.4023 0.129 0.8711 0.129 1.4062zm-1.4122 1.5938v-1.8047c0-0.3398-0.0195-0.6387-0.0585-0.8965-0.0391-0.2617-0.0977-0.4824-0.1758-0.6621-0.0742-0.1836-0.168-0.332-0.2813-0.4453-0.1133-0.1172-0.2422-0.2012-0.3867-0.252-0.1445-0.0547-0.3066-0.082-0.4863-0.082-0.2188 0-0.4141 0.043-0.586 0.1289-0.1718 0.082-0.3164 0.2149-0.4336 0.3984-0.1171 0.1836-0.207 0.4258-0.2695 0.7266-0.0586 0.2969-0.0879 0.6582-0.0879 1.084v1.8047c0 0.3437 0.0195 0.6465 0.0586 0.9082s0.0977 0.4863 0.1758 0.6738c0.0781 0.1836 0.1719 0.3359 0.2812 0.457 0.1133 0.1172 0.2422 0.2032 0.3868 0.2579 0.1484 0.0546 0.3105 0.082 0.4863 0.082 0.2226 0 0.4199-0.043 0.5918-0.1289 0.1719-0.086 0.3164-0.2227 0.4336-0.4102 0.1172-0.1914 0.2051-0.4394 0.2637-0.7441 0.0585-0.3047 0.0878-0.6699 0.0878-1.0957zm8.4825-1.5938v1.3946c0 0.6679-0.0664 1.2382-0.1993 1.7109-0.1289 0.4688-0.3164 0.8496-0.5625 1.1426-0.246 0.2929-0.541 0.5078-0.8847 0.6445-0.3399 0.1367-0.7207 0.2051-1.1426 0.2051-0.3359 0-0.6484-0.043-0.9375-0.1289-0.2852-0.086-0.543-0.2207-0.7734-0.4043-0.2305-0.1836-0.4278-0.4199-0.5918-0.709-0.1602-0.293-0.2852-0.6426-0.375-1.0488-0.086-0.4063-0.1289-0.877-0.1289-1.4121v-1.3946c0-0.6718 0.0664-1.2383 0.1992-1.6992 0.1328-0.4648 0.3222-0.8418 0.5683-1.1308 0.2461-0.293 0.5391-0.5059 0.8789-0.6387 0.3438-0.1328 0.7266-0.1992 1.1485-0.1992 0.3398 0 0.6523 0.0429 0.9375 0.1289 0.289 0.082 0.5469 0.2129 0.7734 0.3925 0.2305 0.1797 0.4258 0.4141 0.586 0.7032 0.164 0.2851 0.289 0.6308 0.375 1.0371 0.0859 0.4023 0.1289 0.8711 0.1289 1.4062zm-1.4121 1.5938v-1.8047c0-0.3398-0.0196-0.6387-0.0586-0.8965-0.0391-0.2617-0.0977-0.4824-0.1758-0.6621-0.0742-0.1836-0.168-0.332-0.2813-0.4453-0.1132-0.1172-0.2422-0.2012-0.3867-0.252-0.1445-0.0547-0.3066-0.082-0.4863-0.082-0.2188 0-0.4141 0.043-0.586 0.1289-0.1718 0.082-0.3164 0.2149-0.4335 0.3984-0.1172 0.1836-0.2071 0.4258-0.2696 0.7266-0.0586 0.2969-0.0879 0.6582-0.0879 1.084v1.8047c0 0.3437 0.0196 0.6465 0.0586 0.9082 0.0391 0.2617 0.0977 0.4863 0.1758 0.6738 0.0781 0.1836 0.1719 0.3359 0.2813 0.457 0.1132 0.1172 0.2421 0.2032 0.3867 0.2579 0.1484 0.0546 0.3105 0.082 0.4863 0.082 0.2227 0 0.4199-0.043 0.5918-0.1289 0.1719-0.086 0.3164-0.2227 0.4336-0.4102 0.1172-0.1914 0.2051-0.4394 0.2637-0.7441s0.0879-0.6699 0.0879-1.0957z" fill="#000" fill-opacity=".38"/>
<path d="m37.332 40.682c0 0.5313-0.123 0.9785-0.3691 1.3418s-0.582 0.6387-1.0078 0.8262c-0.4219 0.1836-0.8985 0.2754-1.4297 0.2754-0.5313 0-1.0098-0.0918-1.4356-0.2754-0.4257-0.1875-0.7617-0.4629-1.0078-0.8262s-0.3691-0.8105-0.3691-1.3418c0-0.3515 0.0683-0.6699 0.2051-0.955 0.1367-0.2891 0.33-0.5372 0.58-0.7442 0.254-0.2109 0.5508-0.373 0.8907-0.4863 0.3437-0.1133 0.7187-0.1699 1.125-0.1699 0.539 0 1.0215 0.0996 1.4472 0.2988 0.4258 0.1992 0.7598 0.4746 1.002 0.8262 0.2461 0.3515 0.3691 0.7617 0.3691 1.2304zm-1.4179-0.0703c0-0.2851-0.0586-0.5351-0.1758-0.75-0.1172-0.2148-0.2813-0.3808-0.4922-0.498s-0.4551-0.1758-0.7324-0.1758c-0.2813 0-0.5254 0.0586-0.7325 0.1758-0.207 0.1172-0.3691 0.2832-0.4863 0.498-0.1133 0.2149-0.1699 0.4649-0.1699 0.75 0 0.2891 0.0566 0.5391 0.1699 0.75 0.1133 0.207 0.2754 0.3653 0.4863 0.4746 0.211 0.1094 0.459 0.1641 0.7442 0.1641 0.2851 0 0.5312-0.0547 0.7383-0.1641 0.207-0.1093 0.3672-0.2676 0.4804-0.4746 0.1133-0.2109 0.17-0.4609 0.17-0.75zm1.2246-3.8906c0 0.4258-0.1133 0.8047-0.3399 1.1367-0.2226 0.332-0.5312 0.5938-0.9258 0.7852-0.3945 0.1875-0.8437 0.2812-1.3476 0.2812-0.5078 0-0.9609-0.0937-1.3594-0.2812-0.3945-0.1914-0.7051-0.4532-0.9316-0.7852-0.2227-0.332-0.334-0.7109-0.334-1.1367 0-0.5078 0.1113-0.9356 0.334-1.2832 0.2265-0.3516 0.5371-0.6192 0.9316-0.8027 0.3945-0.1836 0.8457-0.2754 1.3535-0.2754s0.959 0.0918 1.3535 0.2754c0.3946 0.1835 0.7032 0.4511 0.9258 0.8027 0.2266 0.3476 0.3399 0.7754 0.3399 1.2832zm-1.4121 0.0469c0-0.2539-0.0508-0.4766-0.1524-0.668-0.0976-0.1953-0.2363-0.3477-0.416-0.457-0.1797-0.1094-0.3926-0.1641-0.6387-0.1641s-0.459 0.0527-0.6386 0.1582c-0.1797 0.1055-0.3184 0.2539-0.4161 0.4453-0.0976 0.1914-0.1464 0.4199-0.1464 0.6856 0 0.2617 0.0488 0.4902 0.1464 0.6855 0.0977 0.1914 0.2364 0.3418 0.4161 0.4512 0.1836 0.1094 0.3984 0.164 0.6445 0.164s0.459-0.0546 0.6387-0.164 0.3183-0.2598 0.416-0.4512c0.0976-0.1953 0.1465-0.4238 0.1465-0.6855zm8.6582 1.2597v1.3946c0 0.6679-0.0664 1.2382-0.1993 1.7109-0.1289 0.4688-0.3164 0.8496-0.5625 1.1426-0.246 0.2929-0.541 0.5078-0.8847 0.6445-0.3399 0.1367-0.7207 0.2051-1.1426 0.2051-0.3359 0-0.6484-0.043-0.9375-0.1289-0.2852-0.086-0.543-0.2207-0.7734-0.4043-0.2305-0.1836-0.4278-0.4199-0.5918-0.709-0.1602-0.293-0.2852-0.6426-0.375-1.0488-0.086-0.4063-0.1289-0.877-0.1289-1.4121v-1.3946c0-0.6718 0.0664-1.2382 0.1992-1.6992 0.1328-0.4648 0.3222-0.8418 0.5683-1.1308 0.2461-0.293 0.5391-0.5059 0.8789-0.6387 0.3438-0.1328 0.7266-0.1992 1.1485-0.1992 0.3398 0 0.6523 0.0429 0.9375 0.1289 0.289 0.082 0.5469 0.2129 0.7734 0.3925 0.2305 0.1797 0.4258 0.4141 0.586 0.7032 0.164 0.2851 0.289 0.6308 0.375 1.0371 0.0859 0.4023 0.1289 0.8711 0.1289 1.4062zm-1.4121 1.5938v-1.8047c0-0.3398-0.0196-0.6387-0.0586-0.8965-0.0391-0.2617-0.0977-0.4824-0.1758-0.6621-0.0742-0.1836-0.168-0.332-0.2813-0.4453-0.1132-0.1172-0.2422-0.2012-0.3867-0.252-0.1445-0.0547-0.3066-0.082-0.4863-0.082-0.2188 0-0.4141 0.043-0.586 0.1289-0.1718 0.082-0.3164 0.2149-0.4335 0.3984-0.1172 0.1836-0.2071 0.4258-0.2696 0.7266-0.0586 0.2969-0.0879 0.6582-0.0879 1.084v1.8047c0 0.3437 0.0196 0.6465 0.0586 0.9082 0.0391 0.2617 0.0977 0.4863 0.1758 0.6738 0.0781 0.1836 0.1719 0.336 0.2813 0.457 0.1132 0.1172 0.2421 0.2032 0.3867 0.2579 0.1484 0.0546 0.3105 0.082 0.4863 0.082 0.2227 0 0.4199-0.043 0.5918-0.1289 0.1719-0.086 0.3164-0.2227 0.4336-0.4102 0.1172-0.1914 0.2051-0.4394 0.2637-0.7441s0.0879-0.6699 0.0879-1.0957z" fill="#000" fill-opacity=".38"/>
<path d="m36.02 60.784h0.1758v1.1543h-0.0996c-0.5039 0-0.9395 0.078-1.3066 0.2343-0.3633 0.1563-0.6621 0.3711-0.8965 0.6446-0.2344 0.2734-0.4102 0.5937-0.5274 0.9609-0.1132 0.3633-0.1699 0.75-0.1699 1.1602v1.3418c0 0.3398 0.0371 0.6406 0.1113 0.9023 0.0743 0.2578 0.1778 0.4746 0.3106 0.6504 0.1367 0.1719 0.293 0.3027 0.4687 0.3926 0.1758 0.09 0.3653 0.1347 0.5684 0.1347 0.2109 0 0.4023-0.043 0.5742-0.1289 0.1719-0.09 0.3184-0.2129 0.4395-0.3691 0.1211-0.1563 0.2129-0.3418 0.2754-0.5567 0.0625-0.2148 0.0937-0.4492 0.0937-0.7031 0-0.2422-0.0312-0.4687-0.0937-0.6797-0.0586-0.2148-0.1465-0.4023-0.2637-0.5625-0.1172-0.164-0.2637-0.291-0.4395-0.3808-0.1718-0.094-0.3711-0.1406-0.5976-0.1406-0.2813 0-0.5371 0.066-0.7676 0.1992-0.2266 0.1328-0.4102 0.3066-0.5508 0.5215-0.1367 0.2109-0.2109 0.4355-0.2226 0.6738l-0.5391-0.1758c0.0313-0.3633 0.1113-0.6895 0.2402-0.9785 0.1328-0.2891 0.3067-0.5352 0.5215-0.7383 0.2149-0.2031 0.4629-0.3574 0.7442-0.4629 0.2851-0.1094 0.5976-0.164 0.9375-0.164 0.414 0 0.7734 0.078 1.0781 0.2343s0.5566 0.3692 0.7558 0.6387c0.2032 0.2656 0.3536 0.5703 0.4512 0.9141 0.1016 0.3398 0.1524 0.6953 0.1524 1.0664 0 0.4101-0.0625 0.7929-0.1875 1.1484-0.125 0.3516-0.3086 0.6602-0.5508 0.9258-0.2383 0.2656-0.5293 0.4726-0.8731 0.6211-0.3398 0.1484-0.7265 0.2226-1.1601 0.2226-0.4571 0-0.8653-0.088-1.2246-0.2636-0.3555-0.1758-0.6582-0.418-0.9082-0.7266-0.2461-0.3086-0.4336-0.6641-0.5625-1.0664s-0.1934-0.8281-0.1934-1.2773v-0.586c0-0.6484 0.082-1.2598 0.2461-1.834 0.1641-0.5781 0.416-1.0879 0.7559-1.5293 0.3437-0.4414 0.7832-0.7871 1.3183-1.0371 0.5352-0.2539 1.1738-0.3808 1.916-0.3808zm8.3653 3.6035v1.3945c0 0.668-0.0664 1.2383-0.1993 1.7109-0.1289 0.4688-0.3164 0.8497-0.5625 1.1426-0.246 0.293-0.541 0.5078-0.8847 0.6446-0.3399 0.1367-0.7207 0.205-1.1426 0.205-0.3359 0-0.6484-0.043-0.9375-0.1289-0.2852-0.086-0.543-0.2207-0.7734-0.4043-0.2305-0.1836-0.4278-0.4199-0.5918-0.709-0.1602-0.2929-0.2852-0.6425-0.375-1.0488-0.086-0.4062-0.1289-0.8769-0.1289-1.4121v-1.3945c0-0.6719 0.0664-1.2383 0.1992-1.6992 0.1328-0.4649 0.3222-0.8418 0.5683-1.1309 0.2461-0.293 0.5391-0.5059 0.8789-0.6387 0.3438-0.1328 0.7266-0.1992 1.1485-0.1992 0.3398 0 0.6523 0.043 0.9375 0.1289 0.289 0.082 0.5469 0.2129 0.7734 0.3926 0.2305 0.1797 0.4258 0.4141 0.586 0.7031 0.164 0.2852 0.289 0.6309 0.375 1.0371 0.0859 0.4024 0.1289 0.8711 0.1289 1.4063zm-1.4121 1.5937v-1.8047c0-0.3398-0.0196-0.6386-0.0586-0.8964-0.0391-0.2618-0.0977-0.4825-0.1758-0.6622-0.0742-0.1835-0.168-0.332-0.2813-0.4453-0.1132-0.1172-0.2422-0.2011-0.3867-0.2519-0.1445-0.055-0.3066-0.082-0.4863-0.082-0.2188 0-0.4141 0.043-0.586 0.1289-0.1718 0.082-0.3164 0.2148-0.4335 0.3984-0.1172 0.1836-0.2071 0.4258-0.2696 0.7266-0.0586 0.2968-0.0879 0.6582-0.0879 1.0839v1.8047c0 0.3438 0.0196 0.6465 0.0586 0.9082 0.0391 0.2618 0.0977 0.4864 0.1758 0.6739 0.0781 0.1836 0.1719 0.3359 0.2813 0.457 0.1132 0.1172 0.2421 0.2031 0.3867 0.2578 0.1484 0.055 0.3105 0.082 0.4863 0.082 0.2227 0 0.4199-0.043 0.5918-0.1289 0.1719-0.086 0.3164-0.2226 0.4336-0.4101 0.1172-0.1914 0.2051-0.4395 0.2637-0.7442s0.0879-0.6699 0.0879-1.0957z" fill="#000" fill-opacity=".38"/>
<path d="m37.631 90.687v1.125h-6.1524l-0.0469-0.8496 3.6797-5.7656h1.1309l-1.2246 2.0977-2.1153 3.3925zm-1.0664-5.4902v8.5313h-1.4122v-8.5313zm7.8203 3.5508v1.3945c0 0.668-0.0664 1.2383-0.1993 1.711-0.1289 0.4687-0.3164 0.8496-0.5625 1.1425-0.246 0.293-0.541 0.5078-0.8847 0.6446-0.3399 0.1367-0.7207 0.205-1.1426 0.205-0.3359 0-0.6484-0.0429-0.9375-0.1289-0.2852-0.0859-0.543-0.2207-0.7734-0.4043-0.2305-0.1836-0.4278-0.4199-0.5918-0.7089-0.1602-0.293-0.2852-0.6426-0.375-1.0489-0.086-0.4062-0.1289-0.8769-0.1289-1.4121v-1.3945c0-0.6719 0.0664-1.2383 0.1992-1.6992 0.1328-0.4649 0.3222-0.8418 0.5683-1.1309 0.2461-0.293 0.5391-0.5059 0.8789-0.6387 0.3438-0.1328 0.7266-0.1992 1.1485-0.1992 0.3398 0 0.6523 0.043 0.9375 0.1289 0.289 0.0821 0.5469 0.2129 0.7734 0.3926 0.2305 0.1797 0.4258 0.4141 0.586 0.7031 0.164 0.2852 0.289 0.6309 0.375 1.0371 0.0859 0.4024 0.1289 0.8711 0.1289 1.4063zm-1.4121 1.5937v-1.8047c0-0.3398-0.0196-0.6386-0.0586-0.8964-0.0391-0.2618-0.0977-0.4825-0.1758-0.6621-0.0742-0.1836-0.168-0.3321-0.2813-0.4454-0.1132-0.1171-0.2422-0.2011-0.3867-0.2519-0.1445-0.0547-0.3066-0.082-0.4863-0.082-0.2188 0-0.4141 0.0429-0.586 0.1289-0.1718 0.082-0.3164 0.2148-0.4335 0.3984-0.1172 0.1836-0.2071 0.4258-0.2696 0.7266-0.0586 0.2968-0.0879 0.6582-0.0879 1.0839v1.8047c0 0.3438 0.0196 0.6465 0.0586 0.9082 0.0391 0.2618 0.0977 0.4864 0.1758 0.6739 0.0781 0.1836 0.1719 0.3359 0.2813 0.457 0.1132 0.1172 0.2421 0.2031 0.3867 0.2578 0.1484 0.0547 0.3105 0.082 0.4863 0.082 0.2227 0 0.4199-0.0429 0.5918-0.1289 0.1719-0.0859 0.3164-0.2226 0.4336-0.4101 0.1172-0.1914 0.2051-0.4395 0.2637-0.7442s0.0879-0.6699 0.0879-1.0957z" fill="#000" fill-opacity=".38"/>
<path d="m37.473 116.48v1.125h-5.7188v-0.967l2.7773-3.029c0.3047-0.344 0.545-0.641 0.7208-0.891 0.1757-0.25 0.2988-0.474 0.3691-0.673 0.0742-0.204 0.1113-0.401 0.1113-0.592 0-0.27-0.0508-0.506-0.1523-0.709-0.0977-0.207-0.2422-0.369-0.4336-0.487-0.1914-0.121-0.4238-0.181-0.6973-0.181-0.3164 0-0.582 0.068-0.7969 0.205-0.2148 0.137-0.3769 0.326-0.4863 0.568-0.1094 0.239-0.164 0.512-0.164 0.821h-1.4122c0-0.497 0.1133-0.95 0.3399-1.36 0.2265-0.414 0.5547-0.742 0.9844-0.984 0.4297-0.246 0.9472-0.369 1.5527-0.369 0.5703 0 1.0547 0.095 1.4531 0.287 0.3985 0.191 0.7012 0.463 0.9082 0.814 0.211 0.352 0.3164 0.768 0.3164 1.248 0 0.266-0.0429 0.53-0.1289 0.791-0.0859 0.262-0.209 0.524-0.3691 0.785-0.1563 0.258-0.3418 0.518-0.5567 0.78-0.2148 0.258-0.4511 0.519-0.7089 0.785l-1.8457 2.033zm6.9121-3.855v1.394c0 0.668-0.0664 1.238-0.1993 1.711-0.1289 0.469-0.3164 0.85-0.5625 1.143-0.246 0.293-0.541 0.507-0.8847 0.644-0.3399 0.137-0.7207 0.205-1.1426 0.205-0.3359 0-0.6484-0.043-0.9375-0.129-0.2852-0.086-0.543-0.22-0.7734-0.404-0.2305-0.184-0.4278-0.42-0.5918-0.709-0.1602-0.293-0.2852-0.642-0.375-1.049-0.086-0.406-0.1289-0.877-0.1289-1.412v-1.394c0-0.672 0.0664-1.239 0.1992-1.7 0.1328-0.464 0.3222-0.841 0.5683-1.13 0.2461-0.293 0.5391-0.506 0.8789-0.639 0.3438-0.133 0.7266-0.199 1.1485-0.199 0.3398 0 0.6523 0.043 0.9375 0.129 0.289 0.082 0.5469 0.212 0.7734 0.392 0.2305 0.18 0.4258 0.414 0.586 0.703 0.164 0.285 0.289 0.631 0.375 1.037 0.0859 0.403 0.1289 0.871 0.1289 1.407zm-1.4121 1.593v-1.804c0-0.34-0.0196-0.639-0.0586-0.897-0.0391-0.262-0.0977-0.482-0.1758-0.662-0.0742-0.183-0.168-0.332-0.2813-0.445-0.1132-0.117-0.2422-0.201-0.3867-0.252-0.1445-0.055-0.3066-0.082-0.4863-0.082-0.2188 0-0.4141 0.043-0.586 0.129-0.1718 0.082-0.3164 0.215-0.4335 0.398-0.1172 0.184-0.2071 0.426-0.2696 0.727-0.0586 0.297-0.0879 0.658-0.0879 1.084v1.804c0 0.344 0.0196 0.647 0.0586 0.909 0.0391 0.261 0.0977 0.486 0.1758 0.673 0.0781 0.184 0.1719 0.336 0.2813 0.457 0.1132 0.118 0.2421 0.204 0.3867 0.258 0.1484 0.055 0.3105 0.082 0.4863 0.082 0.2227 0 0.4199-0.043 0.5918-0.129s0.3164-0.222 0.4336-0.41c0.1172-0.191 0.2051-0.439 0.2637-0.744s0.0879-0.67 0.0879-1.096z" fill="#000" fill-opacity=".38"/>
<path d="m44.385 139.02v1.394c0 0.668-0.0664 1.238-0.1993 1.711-0.1289 0.469-0.3164 0.85-0.5625 1.143-0.246 0.293-0.541 0.507-0.8847 0.644-0.3399 0.137-0.7207 0.205-1.1426 0.205-0.3359 0-0.6484-0.043-0.9375-0.129-0.2852-0.086-0.543-0.22-0.7734-0.404-0.2305-0.184-0.4278-0.42-0.5918-0.709-0.1602-0.293-0.2852-0.643-0.375-1.049-0.086-0.406-0.1289-0.877-0.1289-1.412v-1.394c0-0.672 0.0664-1.239 0.1992-1.7 0.1328-0.465 0.3222-0.841 0.5683-1.131 0.2461-0.293 0.5391-0.505 0.8789-0.638 0.3438-0.133 0.7266-0.199 1.1485-0.199 0.3398 0 0.6523 0.043 0.9375 0.128 0.289 0.082 0.5469 0.213 0.7734 0.393 0.2305 0.18 0.4258 0.414 0.586 0.703 0.164 0.285 0.289 0.631 0.375 1.037 0.0859 0.403 0.1289 0.871 0.1289 1.407zm-1.4121 1.593v-1.804c0-0.34-0.0196-0.639-0.0586-0.897-0.0391-0.262-0.0977-0.482-0.1758-0.662-0.0742-0.184-0.168-0.332-0.2813-0.445-0.1132-0.117-0.2422-0.201-0.3867-0.252-0.1445-0.055-0.3066-0.082-0.4863-0.082-0.2188 0-0.4141 0.043-0.586 0.129-0.1718 0.082-0.3164 0.214-0.4335 0.398-0.1172 0.184-0.2071 0.426-0.2696 0.727-0.0586 0.296-0.0879 0.658-0.0879 1.084v1.804c0 0.344 0.0196 0.647 0.0586 0.908 0.0391 0.262 0.0977 0.487 0.1758 0.674 0.0781 0.184 0.1719 0.336 0.2813 0.457 0.1132 0.118 0.2421 0.203 0.3867 0.258 0.1484 0.055 0.3105 0.082 0.4863 0.082 0.2227 0 0.4199-0.043 0.5918-0.129s0.3164-0.222 0.4336-0.41c0.1172-0.191 0.2051-0.439 0.2637-0.744s0.0879-0.67 0.0879-1.096z" fill="#000" fill-opacity=".38"/>
<line x1="52" x2="64" y1="10.5" y2="10.5" stroke="#747474"/>
<line x1="58" x2="64" y1="13.136" y2="13.136" stroke="#747474"/>
<line x1="58" x2="64" y1="15.772" y2="15.772" stroke="#747474"/>
<line x1="58" x2="64" y1="18.408" y2="18.408" stroke="#747474"/>
<line x1="58" x2="64" y1="21.044" y2="21.044" stroke="#747474"/>
<line x1="58" x2="64" y1="23.68" y2="23.68" stroke="#747474"/>
<line x1="58" x2="64" y1="26.316" y2="26.316" stroke="#747474"/>
<line x1="58" x2="64" y1="28.952" y2="28.952" stroke="#747474"/>
<line x1="58" x2="64" y1="31.588" y2="31.588" stroke="#747474"/>
<line x1="58" x2="64" y1="34.224" y2="34.224" stroke="#747474"/>
<line x1="58" x2="64" y1="39.496" y2="39.496" stroke="#747474"/>
<line x1="52" x2="64" y1="36.86" y2="36.86" stroke="#747474"/>
<line x1="58" x2="64" y1="42.132" y2="42.132" stroke="#747474"/>
<line x1="58" x2="64" y1="44.768" y2="44.768" stroke="#747474"/>
<line x1="58" x2="64" y1="47.404" y2="47.404" stroke="#747474"/>
<line x1="58" x2="64" y1="50.04" y2="50.04" stroke="#747474"/>
<line x1="58" x2="64" y1="52.676" y2="52.676" stroke="#747474"/>
<line x1="58" x2="64" y1="55.312" y2="55.312" stroke="#747474"/>
<line x1="58" x2="64" y1="57.948" y2="57.948" stroke="#747474"/>
<line x1="58" x2="64" y1="60.584" y2="60.584" stroke="#747474"/>
<line x1="58" x2="64" y1="65.856" y2="65.856" stroke="#747474"/>
<line x1="52" x2="64" y1="63.22" y2="63.22" stroke="#747474"/>
<line x1="58" x2="64" y1="68.492" y2="68.492" stroke="#747474"/>
<line x1="58" x2="64" y1="71.128" y2="71.128" stroke="#747474"/>
<line x1="58" x2="64" y1="73.764" y2="73.764" stroke="#747474"/>
<line x1="58" x2="64" y1="76.4" y2="76.4" stroke="#747474"/>
<line x1="58" x2="64" y1="81.672" y2="81.672" stroke="#747474"/>
<line x1="58" x2="64" y1="79.036" y2="79.036" stroke="#747474"/>
<line x1="58" x2="64" y1="84.308" y2="84.308" stroke="#747474"/>
<line x1="52" x2="64" y1="89.58" y2="89.58" stroke="#747474"/>
<line x1="58" x2="64" y1="86.944" y2="86.944" stroke="#747474"/>
<line x1="58" x2="64" y1="92.216" y2="92.216" stroke="#747474"/>
<line x1="58" x2="64" y1="94.852" y2="94.852" stroke="#747474"/>
<line x1="58" x2="64" y1="97.488" y2="97.488" stroke="#747474"/>
<line x1="58" x2="64" y1="100.12" y2="100.12" stroke="#747474"/>
<line x1="58" x2="64" y1="102.76" y2="102.76" stroke="#747474"/>
<line x1="58" x2="64" y1="105.4" y2="105.4" stroke="#747474"/>
<line x1="58" x2="64" y1="108.03" y2="108.03" stroke="#747474"/>
<line x1="58" x2="64" y1="110.67" y2="110.67" stroke="#747474"/>
<line x1="52" x2="64" y1="115.94" y2="115.94" stroke="#747474"/>
<line x1="58" x2="64" y1="113.3" y2="113.3" stroke="#747474"/>
<line x1="58" x2="64" y1="118.58" y2="118.58" stroke="#747474"/>
<line x1="58" x2="64" y1="121.21" y2="121.21" stroke="#747474"/>
<line x1="58" x2="64" y1="123.85" y2="123.85" stroke="#747474"/>
<line x1="58" x2="64" y1="126.48" y2="126.48" stroke="#747474"/>
<line x1="58" x2="64" y1="129.12" y2="129.12" stroke="#747474"/>
<line x1="58" x2="64" y1="131.76" y2="131.76" stroke="#747474"/>
<line x1="58" x2="64" y1="134.39" y2="134.39" stroke="#747474"/>
<line x1="58" x2="64" y1="137.03" y2="137.03" stroke="#747474"/>
<line x1="52" x2="64" y1="142.5" y2="142.5" stroke="#747474"/>
<line x1="58" x2="64" y1="139.66" y2="139.66" stroke="#747474"/>
<path d="m63 10v133h1v-133z" fill="#747474"/>
</g><g filter="url(#filter0_ii_3742_299961)" tb:tag="value-box">
<rect x="22" y="164" width="56" height="28" rx="4" fill="#FFFEFE" fill-opacity=".75" tb:tag="value-box-background"/>
<rect x="23" y="165" width="54" height="26" rx="3" stroke="#fff" stroke-width="2"/>
<text x="49.853027" y="179.5625" fill="#727171" font-family="Roboto" font-size="14px" font-weight="500" text-anchor="middle" tb:tag="value-text" xml:space="preserve"><tspan dominant-baseline="middle">37%</tspan></text>
</g><g tb:tag="progressBar">
<rect x="69" y="10.5" width="6" height="134" ry="1.12" stroke="#cecece" tb:tag="progressBorder"/>
<rect transform="scale(1,-1)" x="69" y="-144.5" width="6" height="50" ry="1.12" fill="#4d94e1" stroke="#4d94e1" tb:tag="progressFill"/>
<circle cx="72" cy="150" r="7" fill="#4d94e1" tb:tag="progressCircle"/>
</g><g transform="translate(0,132)" fill="#1c943e" style="display: none;" tb:tag="progress-indicator">
<path d="m64 10.562 10.5 6.062v-12.124z" style=""/>
</g><path d="m37.56 0s-25.56 0-25.56 33.5v164.18c0 1.3256 0.68053 2.3202 1.52 2.3202h72.96c0.83942 0 1.52-0.9946 1.52-2.3202v-164.18c0-33.5-25.107-33.5-25.107-33.5h-12.893zm25.487 40.6c-0.48969 0-0.88669 0.6268-0.88669 1.4v150.2c0 0.7732 0.39697 1.4 0.88669 1.4h5.5733c0.48969 0 0.88669-0.6268 0.88669-1.4v-150.2c0-0.7732-0.39697-1.4-0.88669-1.4z" fill="#000" fill-opacity="0" tb:tag="clickArea"/><defs>
<filter id="filter0_ii_3742_299961" x="20" y="162" width="60" height="32" color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
<feColorMatrix in="SourceAlpha" result="hardAlpha" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/>
<feOffset dx="-2" dy="2"/>
<feGaussianBlur stdDeviation="3"/>
<feComposite in2="hardAlpha" k2="-1" k3="1" operator="arithmetic"/>
<feColorMatrix values="0 0 0 0 0.445833 0 0 0 0 0.445833 0 0 0 0 0.445833 0 0 0 0.5 0"/>
<feBlend in2="shape" result="effect1_innerShadow_3742_299961"/>
<feColorMatrix in="SourceAlpha" result="hardAlpha" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/>
<feOffset dx="2" dy="-2"/>
<feGaussianBlur stdDeviation="2"/>
<feComposite in2="hardAlpha" k2="-1" k3="1" operator="arithmetic"/>
<feColorMatrix values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0.5 0"/>
<feBlend in2="effect1_innerShadow_3742_299961" result="effect2_innerShadow_3742_299961"/>
</filter>
<linearGradient id="paint0_linear_3742_299961" x1="88" x2="12" y1="100" y2="100.09" gradientUnits="userSpaceOnUse">
<stop stop-color="#020202" stop-opacity=".35" offset="0"/>
<stop stop-color="#020202" stop-opacity=".12" offset=".02629"/>
<stop stop-color="#fff" stop-opacity=".12" offset=".11617"/>
<stop stop-color="#fff" stop-opacity=".3" offset=".49829"/>
<stop stop-color="#fff" stop-opacity=".12" offset=".88762"/>
<stop stop-color="#020202" stop-opacity=".12" offset=".96591"/>
<stop stop-color="#020202" stop-opacity=".35" offset="1"/>
</linearGradient>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 44 KiB

717
application/src/main/data/json/system/scada_symbols/small-right-center.svg

@ -0,0 +1,717 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:tb="https://thingsboard.io/svg" width="100" height="200" fill="none" version="1.1" viewBox="0 0 100 200"><tb:metadata xmlns=""><![CDATA[{
"title": "Small right meter",
"description": "Small right meter displays the current value with a moving pointer on the scale.",
"searchTags": [
"scale",
"level",
"progress",
"thermometer"
],
"widgetSizeX": 1,
"widgetSizeY": 2,
"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": "progress-indicator",
"stateRenderFunction": "function calculateOffset(value, minValue, maxValue, initial) {\n var clampedValue = Math.max(Math.min(value, Math.max(minValue, maxValue)), Math.min(minValue, maxValue));\n var normalizedValue = minValue < maxValue\n ? (clampedValue - minValue) / (maxValue - minValue)\n : (minValue - clampedValue) / (minValue - maxValue);\n var offset = initial - (normalizedValue * initial);\n return offset;\n}\n\nvar valueSet = element.remember('valueSet');\n\nif (ctx.properties.progressArrow && !ctx.properties.progressBar) {\n element.show();\n var initial = ctx.properties.valueBox ? 135 : 168;\n if (!valueSet) {\n element.remember('valueSet', true);\n element.transform({\n translateY: initial\n });\n }\n \n var minValue = ctx.properties.minValue;\n var maxValue = ctx.properties.maxValue;\n var value = ctx.values.value;\n \n var colorProcessor = ctx.properties.progressArrowColor;\n colorProcessor.update(value);\n var fill = colorProcessor.color;\n element.attr({fill: fill});\n \n var offset = calculateOffset(value, minValue, maxValue, initial);\n\n var elementOffset = element.remember('offset');\n if (offset !== elementOffset) {\n element.remember('offset', offset);\n ctx.api.cssAnimate(element, 500).transform({\n translateY: offset\n });\n }\n} else {\n element.hide();\n if (valueSet) {\n element.remember('valueSet', false);\n }\n}",
"actions": null
},
{
"tag": "progressBar",
"stateRenderFunction": "if (ctx.properties.progressBar) {\n element.show();\n} else {\n element.hide();\n}",
"actions": null
},
{
"tag": "progressBorder",
"stateRenderFunction": "if (ctx.properties.valueBox) {\n element.attr({'height': 137})\n}",
"actions": null
},
{
"tag": "progressCircle",
"stateRenderFunction": "if (ctx.properties.valueBox) {\n element.attr({cy:152});\n}",
"actions": null
},
{
"tag": "progressFill",
"stateRenderFunction": "if (ctx.properties.valueBox) {\n element.attr({y:-147});\n}\n\nfunction calculateOffset(value, minValue, maxValue, initial) {\n var clampedValue = Math.max(Math.min(value, Math.max(minValue, maxValue)), Math.min(minValue, maxValue));\n var normalizedValue = minValue < maxValue\n ? (clampedValue - minValue) / (maxValue - minValue)\n : (minValue - clampedValue) / (minValue - maxValue);\n var offset = normalizedValue * initial;\n return offset;\n}\n\nvar valueSet = element.remember('valueSet');\nif (ctx.properties.progressBar) {\n var initial = ctx.properties.valueBox ? 135: 168;\n if (!valueSet) {\n element.remember('valueSet', true);\n element.attr({height: 2});\n }\n \n var minValue = ctx.properties.minValue;\n var maxValue = ctx.properties.maxValue;\n var value = ctx.values.value;\n \n var colorProcessor = ctx.properties.progressBarColor;\n colorProcessor.update(value);\n var fill = colorProcessor.color;\n element.attr({fill: fill, stroke: fill});\n ctx.tags.progressCircle[0].fill(fill);\n \n var height = calculateOffset(value, minValue, maxValue, initial);\n\n var elementHeight = element.remember('height');\n if (height !== elementHeight) {\n element.remember('height', height);\n ctx.api.cssAnimate(element, 500).attr({height: height+2});\n }\n} else {\n if (valueSet) {\n element.remember('valueSet', false);\n }\n}",
"actions": null
},
{
"tag": "scale",
"stateRenderFunction": "var scaleSet = element.remember('scaleSet');\nif (!scaleSet) {\n element.remember('scaleSet', true);\n element.clear();\n \n var majorIntervals = ctx.properties.majorIntervals;\n var minorIntervals = ctx.properties.minorIntervals;\n var minValue = ctx.properties.minValue;\n var maxValue = ctx.properties.maxValue;\n \n var start = 11;\n var end = ctx.properties.valueBox ? 134 : 167;\n var majorIntervalLength = end / majorIntervals;\n var minorIntervalLength = majorIntervalLength / minorIntervals;\n element.add(ctx.svg.line(73, end+11, 73, 11).stroke({ width: 1 }).attr({class: 'majorTick'}));\n for (var i = 0; i < majorIntervals+1; i++) {\n var y = start + i * majorIntervalLength;\n var line = ctx.svg.line(61, y, 73, y).stroke({ width: 1 }).attr({class: 'majorTick'});\n element.add(line);\n var majorText = (maxValue - ((maxValue - (minValue)) / (majorIntervals) * i)).toFixed(0);\n var majorTickText = ctx.svg.text(majorText);\n majorTickText.attr({x: 55, y: y + 2, 'text-anchor': 'end', class: 'majorTickText'});\n majorTickText.first().attr({'dominant-baseline': 'middle'});\n element.add(majorTickText);\n if (i < majorIntervals) {\n drawMinorTicks(y, minorIntervals, minorIntervalLength);\n }\n }\n}\n\nvar majorFont = ctx.properties.majorFont;\nvar majorColor = ctx.properties.majorColor;\nvar minorColor = ctx.properties.minorColor;\nif (ctx.values.critical) {\n majorColor = ctx.properties.majorCriticalColor;\n minorColor = ctx.properties.minorCriticalColor;\n} else if (ctx.values.warning) {\n majorColor = ctx.properties.minorWarningColor;\n minorColor = ctx.properties.minorWarningColor;\n}\n\nvar majorTicks = element.find('line.majorTick');\nmajorTicks.forEach(t => t.attr({stroke: majorColor}));\n\nvar majorTicksText = element.find('text.majorTickText');\nctx.api.font(majorTicksText, majorFont, majorColor);\n\nvar minorTicks = element.find('line.minorTick');\nminorTicks.forEach(t => t.attr({stroke: minorColor}));\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\nfunction drawMinorTicks(start, minorIntervals, minorIntervalLength) {\n for (var i = 1; i < minorIntervals; i++) {\n var minorY = start + i * minorIntervalLength;\n var minorLine = ctx.svg.line(67, minorY, 73, minorY).stroke({ width: 1 }).attr({class: 'minorTick'});\n element.add(minorLine);\n }\n}",
"actions": null
},
{
"tag": "value-box",
"stateRenderFunction": "if (ctx.properties.valueBox) {\n element.show();\n} else {\n element.hide();\n}",
"actions": null
},
{
"tag": "value-box-background",
"stateRenderFunction": "if (ctx.properties.valueBox) {\n var colorProcessor = ctx.properties.valueBoxColor;\n colorProcessor.update(ctx.values.value);\n element.attr({fill: colorProcessor.color});\n}",
"actions": null
},
{
"tag": "value-text",
"stateRenderFunction": "if (ctx.properties.valueBox) {\n var valueTextFont = ctx.properties.valueTextFont;\n var valueTextColor = ctx.properties.valueTextColor;\n var currentVolume = ctx.values.value;\n var valueText = ctx.api.formatValue(currentVolume, 0, ctx.properties.valueUnits, false);\n var colorProcessor = ctx.properties.valueTextColor;\n colorProcessor.update(ctx.values.value);\n ctx.api.font(element, valueTextFont, colorProcessor.color);\n ctx.api.text(element, valueText);\n}",
"actions": null
}
],
"behavior": [
{
"id": "value",
"name": "{i18n:scada.symbol.value}",
"hint": null,
"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": "waterLevel"
},
"dataToValue": {
"type": "NONE",
"dataToValueFunction": "/* Should return boolean value */\nreturn data;"
}
},
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": null
},
{
"id": "warning",
"name": "{i18n:scada.symbol.warning-state}",
"hint": "{i18n:scada.symbol.warning-state-hint}",
"group": null,
"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": "critical",
"name": "{i18n:scada.symbol.critical-state}",
"hint": "{i18n:scada.symbol.critical-state-hint}",
"group": null,
"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": "criticalAnimation",
"name": "{i18n:scada.symbol.critical-state-animation}",
"hint": "{i18n:scada.symbol.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": "minValue",
"name": "{i18n:scada.symbol.min-max-value}",
"type": "number",
"default": 0,
"required": true,
"subLabel": "{i18n:scada.symbol.min-value}",
"divider": true,
"min": -1000,
"step": 1,
"disabled": false,
"visible": true
},
{
"id": "maxValue",
"name": "{i18n:scada.symbol.min-max-value}",
"type": "number",
"default": 100,
"required": true,
"subLabel": "{i18n:scada.symbol.max-value}",
"max": 1000,
"step": 1,
"disabled": false,
"visible": true
},
{
"id": "backgroundColor",
"name": "{i18n:scada.symbol.background-color}",
"type": "color",
"default": "#FFFFFF",
"disabled": false,
"visible": true
},
{
"id": "progressBar",
"name": "{i18n:scada.symbol.progress-bar}",
"type": "switch",
"default": true,
"disabled": false,
"visible": true
},
{
"id": "progressBarColor",
"name": "{i18n:scada.symbol.progress-bar}",
"type": "color_settings",
"default": {
"type": "constant",
"color": "#4D94E1",
"gradient": {
"advancedMode": false,
"gradient": [
"rgba(0, 255, 0, 1)",
"rgba(255, 0, 0, 1)"
],
"gradientAdvanced": [
{
"source": {
"type": "constant"
},
"color": "rgba(0, 255, 0, 1)"
},
{
"source": {
"type": "constant"
},
"color": "rgba(255, 0, 0, 1)"
}
],
"minValue": 0,
"maxValue": 100
},
"rangeList": {
"advancedMode": false,
"range": [],
"rangeAdvanced": []
},
"colorFunction": "var temperature = value;\nif (typeof temperature !== undefined) {\n var percent = (temperature + 60)/120 * 100;\n return tinycolor.mix('blue', 'red', percent).toHexString();\n}\nreturn 'blue';"
},
"disableOnProperty": "progressBar",
"disabled": false,
"visible": true
},
{
"id": "progressArrow",
"name": "{i18n:scada.symbol.progress-arrow}",
"type": "switch",
"default": false,
"disabled": false,
"visible": true
},
{
"id": "progressArrowColor",
"name": "{i18n:scada.symbol.progress-arrow}",
"type": "color_settings",
"default": {
"type": "constant",
"color": "#1C943E",
"gradient": {
"advancedMode": false,
"gradient": [
"rgba(0, 255, 0, 1)",
"rgba(255, 0, 0, 1)"
],
"gradientAdvanced": [
{
"source": {
"type": "constant"
},
"color": "rgba(0, 255, 0, 1)"
},
{
"source": {
"type": "constant"
},
"color": "rgba(255, 0, 0, 1)"
}
],
"minValue": 0,
"maxValue": 100
},
"rangeList": {
"advancedMode": false,
"range": [],
"rangeAdvanced": []
},
"colorFunction": "var temperature = value;\nif (typeof temperature !== undefined) {\n var percent = (temperature + 60)/120 * 100;\n return tinycolor.mix('blue', 'red', percent).toHexString();\n}\nreturn 'blue';"
},
"disableOnProperty": "progressArrow",
"disabled": false,
"visible": true
},
{
"id": "valueBox",
"name": "{i18n:scada.symbol.value-box}",
"type": "switch",
"default": false,
"disabled": false,
"visible": true
},
{
"id": "valueBoxColor",
"name": "{i18n:scada.symbol.value-box}",
"type": "color_settings",
"default": {
"type": "constant",
"color": "#F3F3F3",
"gradient": {
"advancedMode": false,
"gradient": [
"rgba(0, 255, 0, 1)",
"rgba(255, 0, 0, 1)"
],
"gradientAdvanced": [
{
"source": {
"type": "constant"
},
"color": "rgba(0, 255, 0, 1)"
},
{
"source": {
"type": "constant"
},
"color": "rgba(255, 0, 0, 1)"
}
],
"minValue": 0,
"maxValue": 100
},
"rangeList": {
"advancedMode": false,
"range": [],
"rangeAdvanced": []
},
"colorFunction": "var temperature = value;\nif (typeof temperature !== undefined) {\n var percent = (temperature + 60)/120 * 100;\n return tinycolor.mix('blue', 'red', percent).toHexString();\n}\nreturn 'blue';"
},
"disableOnProperty": "valueBox",
"disabled": true,
"visible": true
},
{
"id": "valueUnits",
"name": "{i18n:scada.symbol.value-text}",
"type": "units",
"default": "%",
"subLabel": "{i18n:scada.symbol.units}",
"disableOnProperty": "valueBox",
"disabled": true,
"visible": true
},
{
"id": "valueTextFont",
"name": "{i18n:scada.symbol.value-text}",
"type": "font",
"default": {
"size": 14,
"sizeUnit": "px",
"family": "Roboto",
"weight": "500",
"style": "normal"
},
"disableOnProperty": "valueBox",
"disabled": true,
"visible": true
},
{
"id": "valueTextColor",
"name": "{i18n:scada.symbol.value-text}",
"type": "color_settings",
"default": {
"type": "constant",
"color": "#0000008A",
"gradient": {
"advancedMode": false,
"gradient": [
"rgba(0, 255, 0, 1)",
"rgba(255, 0, 0, 1)"
],
"gradientAdvanced": [
{
"source": {
"type": "constant"
},
"color": "rgba(0, 255, 0, 1)"
},
{
"source": {
"type": "constant"
},
"color": "rgba(255, 0, 0, 1)"
}
],
"minValue": 0,
"maxValue": 100
},
"rangeList": {
"advancedMode": false,
"range": [],
"rangeAdvanced": []
},
"colorFunction": "var temperature = value;\nif (typeof temperature !== undefined) {\n var percent = (temperature + 60)/120 * 100;\n return tinycolor.mix('blue', 'red', percent).toHexString();\n}\nreturn 'blue';"
},
"disableOnProperty": "valueBox",
"disabled": true,
"visible": true
},
{
"id": "majorIntervals",
"name": "{i18n:scada.symbol.major-ticks}",
"type": "number",
"default": 5,
"subLabel": "{i18n:scada.symbol.intervals}",
"divider": true,
"min": 1,
"step": 1,
"disabled": false,
"visible": true
},
{
"id": "majorFont",
"name": "{i18n:scada.symbol.major-ticks}",
"type": "font",
"default": {
"size": 12,
"sizeUnit": "px",
"family": "Roboto",
"weight": "500",
"style": "normal"
},
"disabled": false,
"visible": true
},
{
"id": "majorColor",
"name": "{i18n:scada.symbol.major-ticks-color}",
"type": "color",
"default": "#747474",
"subLabel": "{i18n:scada.symbol.normal}",
"divider": true,
"disabled": false,
"visible": true
},
{
"id": "majorWarningColor",
"name": "{i18n:scada.symbol.major-ticks-color}",
"type": "color",
"default": "#FAA405",
"subLabel": "{i18n:scada.symbol.warning}",
"divider": true,
"disabled": false,
"visible": true
},
{
"id": "majorCriticalColor",
"name": "{i18n:scada.symbol.major-ticks-color}",
"type": "color",
"default": "#D12730",
"subLabel": "{i18n:scada.symbol.critical}",
"disabled": false,
"visible": true
},
{
"id": "minorIntervals",
"name": "{i18n:scada.symbol.minor-ticks}",
"type": "number",
"default": 10,
"subLabel": "{i18n:scada.symbol.intervals}",
"min": 1,
"disabled": false,
"visible": true
},
{
"id": "minorColor",
"name": "{i18n:scada.symbol.minor-ticks-color}",
"type": "color",
"default": "#747474",
"subLabel": "{i18n:scada.symbol.normal}",
"divider": true,
"disabled": false,
"visible": true
},
{
"id": "minorWarningColor",
"name": "{i18n:scada.symbol.minor-ticks-color}",
"type": "color",
"default": "#FAA405",
"subLabel": "{i18n:scada.symbol.warning}",
"divider": true,
"disabled": false,
"visible": true
},
{
"id": "minorCriticalColor",
"name": "{i18n:scada.symbol.minor-ticks-color}",
"type": "color",
"default": "#D12730",
"subLabel": "{i18n:scada.symbol.critical}",
"disabled": false,
"visible": true
}
]
}]]></tb:metadata>
<path d="m28 200c-2.2091 0-4-1.791-4-4v-192c0-2.2091 1.7909-4 4-4h68c2.2091 0 4 1.7909 4 4v192c0 2.209-1.7909 4-4 4h-68z" fill="#E5E5E5" tb:tag="background"/><path d="m28 200c-2.2091 0-4-1.791-4-4v-192c0-2.2091 1.7909-4 4-4h68c2.2091 0 4 1.7909 4 4v192c0 2.209-1.7909 4-4 4h-68z" fill="url(#paint0_linear_3742_299973)"/><path d="m28 198.5c-1.3807 0-2.5-1.119-2.5-2.5v-192c0-1.3807 1.1193-2.5 2.5-2.5h68c1.3807 0 2.5 1.1193 2.5 2.5v192c0 1.381-1.1193 2.5-2.5 2.5h-68z" stroke="#000" stroke-opacity=".12" stroke-width="3"/><g tb:tag="scale">
<g transform="translate(23.965)" fill="#919191">
<path d="m14.539 10.088v8.5605h-1.4121v-6.8848l-2.0918 0.709v-1.166l3.3339-1.2187zm8.7754 3.58v1.3946c0 0.6679-0.0665 1.2382-0.1993 1.7109-0.1289 0.4688-0.3164 0.8496-0.5625 1.1426-0.2461 0.2929-0.541 0.5078-0.8847 0.6445-0.3399 0.1367-0.7207 0.2051-1.1426 0.2051-0.3359 0-0.6484-0.043-0.9375-0.1289-0.2852-0.086-0.543-0.2207-0.7734-0.4043-0.2305-0.1836-0.4278-0.4199-0.5918-0.709-0.1602-0.293-0.2852-0.6426-0.375-1.0488-0.086-0.4063-0.1289-0.877-0.1289-1.4121v-1.3946c0-0.6718 0.0664-1.2383 0.1992-1.6992 0.1328-0.4648 0.3222-0.8418 0.5683-1.1308 0.2461-0.293 0.5391-0.5059 0.8789-0.6387 0.3438-0.1328 0.7266-0.1992 1.1485-0.1992 0.3398 0 0.6523 0.0429 0.9375 0.1289 0.289 0.082 0.5468 0.2129 0.7734 0.3925 0.2305 0.1797 0.4258 0.4141 0.5859 0.7032 0.1641 0.2851 0.2891 0.6308 0.375 1.0371 0.086 0.4023 0.129 0.8711 0.129 1.4062zm-1.4122 1.5938v-1.8047c0-0.3398-0.0195-0.6387-0.0585-0.8965-0.0391-0.2617-0.0977-0.4824-0.1758-0.6621-0.0742-0.1836-0.168-0.332-0.2813-0.4453-0.1133-0.1172-0.2422-0.2012-0.3867-0.252-0.1445-0.0547-0.3066-0.082-0.4863-0.082-0.2188 0-0.4141 0.043-0.586 0.1289-0.1718 0.082-0.3164 0.2149-0.4336 0.3984-0.1171 0.1836-0.207 0.4258-0.2695 0.7266-0.0586 0.2969-0.0879 0.6582-0.0879 1.084v1.8047c0 0.3437 0.0195 0.6465 0.0586 0.9082s0.0977 0.4863 0.1758 0.6738c0.0781 0.1836 0.1719 0.3359 0.2812 0.457 0.1133 0.1172 0.2422 0.2032 0.3868 0.2579 0.1484 0.0546 0.3105 0.082 0.4863 0.082 0.2226 0 0.4199-0.043 0.5918-0.1289 0.1719-0.086 0.3164-0.2227 0.4336-0.4102 0.1172-0.1914 0.2051-0.4394 0.2637-0.7441 0.0585-0.3047 0.0878-0.6699 0.0878-1.0957zm8.4825-1.5938v1.3946c0 0.6679-0.0664 1.2382-0.1993 1.7109-0.1289 0.4688-0.3164 0.8496-0.5625 1.1426-0.246 0.2929-0.541 0.5078-0.8847 0.6445-0.3399 0.1367-0.7207 0.2051-1.1426 0.2051-0.3359 0-0.6484-0.043-0.9375-0.1289-0.2852-0.086-0.543-0.2207-0.7734-0.4043-0.2305-0.1836-0.4278-0.4199-0.5918-0.709-0.1602-0.293-0.2852-0.6426-0.375-1.0488-0.086-0.4063-0.1289-0.877-0.1289-1.4121v-1.3946c0-0.6718 0.0664-1.2383 0.1992-1.6992 0.1328-0.4648 0.3222-0.8418 0.5683-1.1308 0.2461-0.293 0.5391-0.5059 0.8789-0.6387 0.3438-0.1328 0.7266-0.1992 1.1485-0.1992 0.3398 0 0.6523 0.0429 0.9375 0.1289 0.289 0.082 0.5469 0.2129 0.7734 0.3925 0.2305 0.1797 0.4258 0.4141 0.586 0.7032 0.164 0.2851 0.289 0.6308 0.375 1.0371 0.0859 0.4023 0.1289 0.8711 0.1289 1.4062zm-1.4121 1.5938v-1.8047c0-0.3398-0.0196-0.6387-0.0586-0.8965-0.0391-0.2617-0.0977-0.4824-0.1758-0.6621-0.0742-0.1836-0.168-0.332-0.2813-0.4453-0.1132-0.1172-0.2422-0.2012-0.3867-0.252-0.1445-0.0547-0.3066-0.082-0.4863-0.082-0.2188 0-0.4141 0.043-0.586 0.1289-0.1718 0.082-0.3164 0.2149-0.4335 0.3984-0.1172 0.1836-0.2071 0.4258-0.2696 0.7266-0.0586 0.2969-0.0879 0.6582-0.0879 1.084v1.8047c0 0.3437 0.0196 0.6465 0.0586 0.9082 0.0391 0.2617 0.0977 0.4863 0.1758 0.6738 0.0781 0.1836 0.1719 0.3359 0.2813 0.457 0.1132 0.1172 0.2421 0.2032 0.3867 0.2579 0.1484 0.0546 0.3105 0.082 0.4863 0.082 0.2227 0 0.4199-0.043 0.5918-0.1289 0.1719-0.086 0.3164-0.2227 0.4336-0.4102 0.1172-0.1914 0.2051-0.4394 0.2637-0.7441s0.0879-0.6699 0.0879-1.0957z"/>
<path d="m23.332 49.374c0 0.5313-0.123 0.9785-0.3691 1.3418s-0.582 0.6387-1.0078 0.8262c-0.4219 0.1836-0.8985 0.2754-1.4297 0.2754-0.5313 0-1.0098-0.0918-1.4356-0.2754-0.4257-0.1875-0.7617-0.4629-1.0078-0.8262s-0.3691-0.8105-0.3691-1.3418c0-0.3515 0.0683-0.6699 0.2051-0.955 0.1367-0.2891 0.33-0.5372 0.58-0.7442 0.254-0.2109 0.5508-0.373 0.8907-0.4863 0.3437-0.1133 0.7187-0.1699 1.125-0.1699 0.539 0 1.0215 0.0996 1.4472 0.2988 0.4258 0.1992 0.7598 0.4746 1.002 0.8262 0.2461 0.3515 0.3691 0.7617 0.3691 1.2304zm-1.4179-0.0703c0-0.2851-0.0586-0.5351-0.1758-0.75-0.1172-0.2148-0.2813-0.3808-0.4922-0.498s-0.4551-0.1758-0.7324-0.1758c-0.2813 0-0.5254 0.0586-0.7325 0.1758-0.207 0.1172-0.3691 0.2832-0.4863 0.498-0.1133 0.2149-0.1699 0.4649-0.1699 0.75 0 0.2891 0.0566 0.5391 0.1699 0.75 0.1133 0.207 0.2754 0.3653 0.4863 0.4746 0.211 0.1094 0.459 0.1641 0.7442 0.1641 0.2851 0 0.5312-0.0547 0.7383-0.1641 0.207-0.1093 0.3672-0.2676 0.4804-0.4746 0.1133-0.2109 0.17-0.4609 0.17-0.75zm1.2246-3.8906c0 0.4258-0.1133 0.8047-0.3399 1.1367-0.2226 0.332-0.5312 0.5938-0.9258 0.7852-0.3945 0.1875-0.8437 0.2812-1.3476 0.2812-0.5078 0-0.9609-0.0937-1.3594-0.2812-0.3945-0.1914-0.7051-0.4532-0.9316-0.7852-0.2227-0.332-0.334-0.7109-0.334-1.1367 0-0.5078 0.1113-0.9356 0.334-1.2832 0.2265-0.3516 0.5371-0.6192 0.9316-0.8027 0.3945-0.1836 0.8457-0.2754 1.3535-0.2754s0.959 0.0918 1.3535 0.2754c0.3946 0.1835 0.7032 0.4511 0.9258 0.8027 0.2266 0.3476 0.3399 0.7754 0.3399 1.2832zm-1.4121 0.0469c0-0.2539-0.0508-0.4766-0.1524-0.668-0.0976-0.1953-0.2363-0.3477-0.416-0.457-0.1797-0.1094-0.3926-0.1641-0.6387-0.1641s-0.459 0.0527-0.6386 0.1582c-0.1797 0.1055-0.3184 0.2539-0.4161 0.4453-0.0976 0.1914-0.1464 0.4199-0.1464 0.6856 0 0.2617 0.0488 0.4902 0.1464 0.6855 0.0977 0.1914 0.2364 0.3418 0.4161 0.4512 0.1836 0.1094 0.3984 0.164 0.6445 0.164s0.459-0.0546 0.6387-0.164 0.3183-0.2598 0.416-0.4512c0.0976-0.1953 0.1465-0.4238 0.1465-0.6855zm8.6582 1.2597v1.3946c0 0.6679-0.0664 1.2382-0.1993 1.7109-0.1289 0.4688-0.3164 0.8496-0.5625 1.1426-0.246 0.2929-0.541 0.5078-0.8847 0.6445-0.3399 0.1367-0.7207 0.2051-1.1426 0.2051-0.3359 0-0.6484-0.043-0.9375-0.1289-0.2852-0.086-0.543-0.2207-0.7734-0.4043-0.2305-0.1836-0.4278-0.4199-0.5918-0.709-0.1602-0.293-0.2852-0.6426-0.375-1.0488-0.086-0.4063-0.1289-0.877-0.1289-1.4121v-1.3946c0-0.6718 0.0664-1.2382 0.1992-1.6992 0.1328-0.4648 0.3222-0.8418 0.5683-1.1308 0.2461-0.293 0.5391-0.5059 0.8789-0.6387 0.3438-0.1328 0.7266-0.1992 1.1485-0.1992 0.3398 0 0.6523 0.0429 0.9375 0.1289 0.289 0.082 0.5469 0.2129 0.7734 0.3925 0.2305 0.1797 0.4258 0.4141 0.586 0.7032 0.164 0.2851 0.289 0.6308 0.375 1.0371 0.0859 0.4023 0.1289 0.8711 0.1289 1.4062zm-1.4121 1.5938v-1.8047c0-0.3398-0.0196-0.6387-0.0586-0.8965-0.0391-0.2617-0.0977-0.4824-0.1758-0.6621-0.0742-0.1836-0.168-0.332-0.2813-0.4453-0.1132-0.1172-0.2422-0.2012-0.3867-0.252-0.1445-0.0547-0.3066-0.082-0.4863-0.082-0.2188 0-0.4141 0.043-0.586 0.1289-0.1718 0.082-0.3164 0.2149-0.4335 0.3984-0.1172 0.1836-0.2071 0.4258-0.2696 0.7266-0.0586 0.2969-0.0879 0.6582-0.0879 1.084v1.8047c0 0.3437 0.0196 0.6465 0.0586 0.9082 0.0391 0.2617 0.0977 0.4863 0.1758 0.6738 0.0781 0.1836 0.1719 0.336 0.2813 0.457 0.1132 0.1172 0.2421 0.2032 0.3867 0.2579 0.1484 0.0546 0.3105 0.082 0.4863 0.082 0.2227 0 0.4199-0.043 0.5918-0.1289 0.1719-0.086 0.3164-0.2227 0.4336-0.4102 0.1172-0.1914 0.2051-0.4394 0.2637-0.7441s0.0879-0.6699 0.0879-1.0957z"/>
<path d="m22.02 74.016h0.1758v1.1543h-0.0996c-0.5039 0-0.9395 0.0781-1.3066 0.2343-0.3633 0.1563-0.6621 0.3711-0.8965 0.6446-0.2344 0.2734-0.4102 0.5937-0.5274 0.9609-0.1132 0.3633-0.1699 0.75-0.1699 1.1602v1.3418c0 0.3398 0.0371 0.6406 0.1113 0.9023 0.0743 0.2578 0.1778 0.4746 0.3106 0.6504 0.1367 0.1719 0.293 0.3027 0.4687 0.3926 0.1758 0.0898 0.3653 0.1347 0.5684 0.1347 0.2109 0 0.4023-0.0429 0.5742-0.1289 0.1719-0.0898 0.3184-0.2129 0.4395-0.3691 0.1211-0.1563 0.2129-0.3418 0.2754-0.5567 0.0625-0.2148 0.0937-0.4492 0.0937-0.7031 0-0.2422-0.0312-0.4687-0.0937-0.6797-0.0586-0.2148-0.1465-0.4023-0.2637-0.5625-0.1172-0.164-0.2637-0.291-0.4395-0.3808-0.1718-0.0938-0.3711-0.1406-0.5976-0.1406-0.2813 0-0.5371 0.0664-0.7676 0.1992-0.2266 0.1328-0.4102 0.3066-0.5508 0.5215-0.1367 0.2109-0.2109 0.4355-0.2226 0.6738l-0.5391-0.1758c0.0313-0.3633 0.1113-0.6895 0.2402-0.9785 0.1328-0.2891 0.3067-0.5352 0.5215-0.7383 0.2149-0.2031 0.4629-0.3574 0.7442-0.4629 0.2851-0.1094 0.5976-0.164 0.9375-0.164 0.414 0 0.7734 0.0781 1.0781 0.2343 0.3047 0.1563 0.5566 0.3692 0.7558 0.6387 0.2032 0.2656 0.3536 0.5703 0.4512 0.9141 0.1016 0.3398 0.1524 0.6953 0.1524 1.0664 0 0.4101-0.0625 0.7929-0.1875 1.1484-0.125 0.3516-0.3086 0.6602-0.5508 0.9258-0.2383 0.2656-0.5293 0.4726-0.8731 0.6211-0.3398 0.1484-0.7265 0.2226-1.1601 0.2226-0.4571 0-0.8653-0.0879-1.2246-0.2636-0.3555-0.1758-0.6582-0.418-0.9082-0.7266-0.2461-0.3086-0.4336-0.6641-0.5625-1.0664s-0.1934-0.8281-0.1934-1.2773v-0.586c0-0.6484 0.082-1.2598 0.2461-1.834 0.1641-0.5781 0.416-1.0879 0.7559-1.5293 0.3437-0.4414 0.7832-0.7871 1.3183-1.0371 0.5352-0.2539 1.1738-0.3808 1.916-0.3808zm8.3653 3.6035v1.3945c0 0.668-0.0664 1.2383-0.1993 1.7109-0.1289 0.4688-0.3164 0.8497-0.5625 1.1426-0.246 0.293-0.541 0.5078-0.8847 0.6446-0.3399 0.1367-0.7207 0.205-1.1426 0.205-0.3359 0-0.6484-0.0429-0.9375-0.1289-0.2852-0.0859-0.543-0.2207-0.7734-0.4043-0.2305-0.1836-0.4278-0.4199-0.5918-0.709-0.1602-0.2929-0.2852-0.6425-0.375-1.0488-0.086-0.4062-0.1289-0.8769-0.1289-1.4121v-1.3945c0-0.6719 0.0664-1.2383 0.1992-1.6992 0.1328-0.4649 0.3222-0.8418 0.5683-1.1309 0.2461-0.293 0.5391-0.5059 0.8789-0.6387 0.3438-0.1328 0.7266-0.1992 1.1485-0.1992 0.3398 0 0.6523 0.043 0.9375 0.1289 0.289 0.082 0.5469 0.2129 0.7734 0.3926 0.2305 0.1797 0.4258 0.4141 0.586 0.7031 0.164 0.2852 0.289 0.6309 0.375 1.0371 0.0859 0.4024 0.1289 0.8711 0.1289 1.4063zm-1.4121 1.5937v-1.8047c0-0.3398-0.0196-0.6386-0.0586-0.8964-0.0391-0.2618-0.0977-0.4825-0.1758-0.6622-0.0742-0.1835-0.168-0.332-0.2813-0.4453-0.1132-0.1172-0.2422-0.2011-0.3867-0.2519-0.1445-0.0547-0.3066-0.082-0.4863-0.082-0.2188 0-0.4141 0.0429-0.586 0.1289-0.1718 0.082-0.3164 0.2148-0.4335 0.3984-0.1172 0.1836-0.2071 0.4258-0.2696 0.7266-0.0586 0.2968-0.0879 0.6582-0.0879 1.0839v1.8047c0 0.3438 0.0196 0.6465 0.0586 0.9082 0.0391 0.2618 0.0977 0.4864 0.1758 0.6739 0.0781 0.1836 0.1719 0.3359 0.2813 0.457 0.1132 0.1172 0.2421 0.2031 0.3867 0.2578 0.1484 0.0547 0.3105 0.082 0.4863 0.082 0.2227 0 0.4199-0.0429 0.5918-0.1289 0.1719-0.0859 0.3164-0.2226 0.4336-0.4101 0.1172-0.1914 0.2051-0.4395 0.2637-0.7442s0.0879-0.6699 0.0879-1.0957z"/>
<path d="m23.631 111.66v1.125h-6.1524l-0.0469-0.85 3.6797-5.765h1.1309l-1.2246 2.097-2.1153 3.393zm-1.0664-5.49v8.531h-1.4122v-8.531zm7.8203 3.55v1.395c0 0.668-0.0664 1.238-0.1993 1.711-0.1289 0.469-0.3164 0.85-0.5625 1.143-0.246 0.292-0.541 0.507-0.8847 0.644-0.3399 0.137-0.7207 0.205-1.1426 0.205-0.3359 0-0.6484-0.043-0.9375-0.129-0.2852-0.086-0.543-0.22-0.7734-0.404-0.2305-0.184-0.4278-0.42-0.5918-0.709-0.1602-0.293-0.2852-0.643-0.375-1.049-0.086-0.406-0.1289-0.877-0.1289-1.412v-1.395c0-0.671 0.0664-1.238 0.1992-1.699 0.1328-0.465 0.3222-0.842 0.5683-1.131 0.2461-0.293 0.5391-0.505 0.8789-0.638 0.3438-0.133 0.7266-0.199 1.1485-0.199 0.3398 0 0.6523 0.042 0.9375 0.128 0.289 0.082 0.5469 0.213 0.7734 0.393 0.2305 0.18 0.4258 0.414 0.586 0.703 0.164 0.285 0.289 0.631 0.375 1.037 0.0859 0.403 0.1289 0.871 0.1289 1.406zm-1.4121 1.594v-1.804c0-0.34-0.0196-0.639-0.0586-0.897-0.0391-0.262-0.0977-0.482-0.1758-0.662-0.0742-0.184-0.168-0.332-0.2813-0.445-0.1132-0.118-0.2422-0.202-0.3867-0.252-0.1445-0.055-0.3066-0.082-0.4863-0.082-0.2188 0-0.4141 0.043-0.586 0.129-0.1718 0.082-0.3164 0.214-0.4335 0.398-0.1172 0.184-0.2071 0.426-0.2696 0.727-0.0586 0.296-0.0879 0.658-0.0879 1.084v1.804c0 0.344 0.0196 0.647 0.0586 0.908 0.0391 0.262 0.0977 0.487 0.1758 0.674 0.0781 0.184 0.1719 0.336 0.2813 0.457 0.1132 0.117 0.2421 0.203 0.3867 0.258 0.1484 0.055 0.3105 0.082 0.4863 0.082 0.2227 0 0.4199-0.043 0.5918-0.129s0.3164-0.222 0.4336-0.41c0.1172-0.191 0.2051-0.439 0.2637-0.744s0.0879-0.67 0.0879-1.096z"/>
<path d="m23.473 145.48v1.125h-5.7188v-0.967l2.7773-3.029c0.3047-0.344 0.545-0.641 0.7208-0.891 0.1757-0.25 0.2988-0.474 0.3691-0.673 0.0742-0.204 0.1113-0.401 0.1113-0.592 0-0.27-0.0508-0.506-0.1523-0.709-0.0977-0.207-0.2422-0.369-0.4336-0.487-0.1914-0.121-0.4238-0.181-0.6973-0.181-0.3164 0-0.582 0.068-0.7969 0.205-0.2148 0.137-0.3769 0.326-0.4863 0.568-0.1094 0.239-0.164 0.512-0.164 0.821h-1.4122c0-0.497 0.1133-0.95 0.3399-1.36 0.2265-0.414 0.5547-0.742 0.9844-0.984 0.4297-0.246 0.9472-0.369 1.5527-0.369 0.5703 0 1.0547 0.095 1.4531 0.287 0.3985 0.191 0.7012 0.463 0.9082 0.814 0.211 0.352 0.3164 0.768 0.3164 1.248 0 0.266-0.0429 0.53-0.1289 0.791-0.0859 0.262-0.209 0.524-0.3691 0.785-0.1563 0.258-0.3418 0.518-0.5567 0.78-0.2148 0.258-0.4511 0.519-0.7089 0.785l-1.8457 2.033zm6.9121-3.855v1.394c0 0.668-0.0664 1.238-0.1993 1.711-0.1289 0.469-0.3164 0.85-0.5625 1.143-0.246 0.293-0.541 0.507-0.8847 0.644-0.3399 0.137-0.7207 0.205-1.1426 0.205-0.3359 0-0.6484-0.043-0.9375-0.129-0.2852-0.086-0.543-0.22-0.7734-0.404-0.2305-0.184-0.4278-0.42-0.5918-0.709-0.1602-0.293-0.2852-0.642-0.375-1.049-0.086-0.406-0.1289-0.877-0.1289-1.412v-1.394c0-0.672 0.0664-1.239 0.1992-1.7 0.1328-0.464 0.3222-0.841 0.5683-1.13 0.2461-0.293 0.5391-0.506 0.8789-0.639 0.3438-0.133 0.7266-0.199 1.1485-0.199 0.3398 0 0.6523 0.043 0.9375 0.129 0.289 0.082 0.5469 0.212 0.7734 0.392 0.2305 0.18 0.4258 0.414 0.586 0.703 0.164 0.285 0.289 0.631 0.375 1.037 0.0859 0.403 0.1289 0.871 0.1289 1.407zm-1.4121 1.593v-1.804c0-0.34-0.0196-0.639-0.0586-0.897-0.0391-0.262-0.0977-0.482-0.1758-0.662-0.0742-0.183-0.168-0.332-0.2813-0.445-0.1132-0.117-0.2422-0.201-0.3867-0.252-0.1445-0.055-0.3066-0.082-0.4863-0.082-0.2188 0-0.4141 0.043-0.586 0.129-0.1718 0.082-0.3164 0.215-0.4335 0.398-0.1172 0.184-0.2071 0.426-0.2696 0.727-0.0586 0.297-0.0879 0.658-0.0879 1.084v1.804c0 0.344 0.0196 0.647 0.0586 0.909 0.0391 0.261 0.0977 0.486 0.1758 0.673 0.0781 0.184 0.1719 0.336 0.2813 0.457 0.1132 0.118 0.2421 0.204 0.3867 0.258 0.1484 0.055 0.3105 0.082 0.4863 0.082 0.2227 0 0.4199-0.043 0.5918-0.129s0.3164-0.222 0.4336-0.41c0.1172-0.191 0.2051-0.439 0.2637-0.744s0.0879-0.67 0.0879-1.096z"/>
<path d="m30.385 173.02v1.394c0 0.668-0.0664 1.238-0.1993 1.711-0.1289 0.469-0.3164 0.85-0.5625 1.143-0.246 0.293-0.541 0.507-0.8847 0.644-0.3399 0.137-0.7207 0.205-1.1426 0.205-0.3359 0-0.6484-0.043-0.9375-0.129-0.2852-0.086-0.543-0.22-0.7734-0.404-0.2305-0.184-0.4278-0.42-0.5918-0.709-0.1602-0.293-0.2852-0.643-0.375-1.049-0.086-0.406-0.1289-0.877-0.1289-1.412v-1.394c0-0.672 0.0664-1.239 0.1992-1.7 0.1328-0.465 0.3222-0.841 0.5683-1.131 0.2461-0.293 0.5391-0.505 0.8789-0.638 0.3438-0.133 0.7266-0.199 1.1485-0.199 0.3398 0 0.6523 0.043 0.9375 0.128 0.289 0.082 0.5469 0.213 0.7734 0.393 0.2305 0.18 0.4258 0.414 0.586 0.703 0.164 0.285 0.289 0.631 0.375 1.037 0.0859 0.403 0.1289 0.871 0.1289 1.407zm-1.4121 1.593v-1.804c0-0.34-0.0196-0.639-0.0586-0.897-0.0391-0.262-0.0977-0.482-0.1758-0.662-0.0742-0.184-0.168-0.332-0.2813-0.445-0.1132-0.117-0.2422-0.201-0.3867-0.252-0.1445-0.055-0.3066-0.082-0.4863-0.082-0.2188 0-0.4141 0.043-0.586 0.129-0.1718 0.082-0.3164 0.214-0.4335 0.398-0.1172 0.184-0.2071 0.426-0.2696 0.727-0.0586 0.296-0.0879 0.658-0.0879 1.084v1.804c0 0.344 0.0196 0.647 0.0586 0.908 0.0391 0.262 0.0977 0.487 0.1758 0.674 0.0781 0.184 0.1719 0.336 0.2813 0.457 0.1132 0.118 0.2421 0.203 0.3867 0.258 0.1484 0.055 0.3105 0.082 0.4863 0.082 0.2227 0 0.4199-0.043 0.5918-0.129s0.3164-0.222 0.4336-0.41c0.1172-0.191 0.2051-0.439 0.2637-0.744s0.0879-0.67 0.0879-1.096z"/>
</g>
<g transform="matrix(1 0 0 1.0194 24.515 -3.9105)" stroke="#747474">
<path d="m50.695 14.031v164.03h0.22794v-164.03z" fill="#747474" stroke-width=".77206"/>
<line x1="39" x2="51" y1="14.145" y2="14.145"/>
<line x1="45" x2="51" y1="17.76" y2="17.76"/>
<line x1="45" x2="51" y1="21.02" y2="21.02"/>
<line x1="45" x2="51" y1="24.28" y2="24.28"/>
<line x1="45" x2="51" y1="27.54" y2="27.54"/>
<line x1="45" x2="51" y1="30.8" y2="30.8"/>
<line x1="45" x2="51" y1="34.06" y2="34.06"/>
<line x1="45" x2="51" y1="37.32" y2="37.32"/>
<line x1="45" x2="51" y1="40.58" y2="40.58"/>
<line x1="45" x2="51" y1="43.84" y2="43.84"/>
<line x1="39" x2="51" y1="47.1" y2="47.1"/>
<line x1="45" x2="51" y1="50.36" y2="50.36"/>
<line x1="45" x2="51" y1="53.62" y2="53.62"/>
<line x1="45" x2="51" y1="56.88" y2="56.88"/>
<line x1="45" x2="51" y1="60.14" y2="60.14"/>
<line x1="45" x2="51" y1="63.4" y2="63.4"/>
<line x1="45" x2="51" y1="66.66" y2="66.66"/>
<line x1="45" x2="51" y1="69.92" y2="69.92"/>
<line x1="45" x2="51" y1="73.18" y2="73.18"/>
<line x1="45" x2="51" y1="76.44" y2="76.44"/>
<line x1="39" x2="51" y1="79.7" y2="79.7"/>
<line x1="45" x2="51" y1="82.96" y2="82.96"/>
<line x1="45" x2="51" y1="86.22" y2="86.22"/>
<line x1="45" x2="51" y1="89.48" y2="89.48"/>
<line x1="45" x2="51" y1="92.74" y2="92.74"/>
<line x1="45" x2="51" y1="96" y2="96"/>
<line x1="45" x2="51" y1="99.26" y2="99.26"/>
<line x1="45" x2="51" y1="102.52" y2="102.52"/>
<line x1="45" x2="51" y1="105.78" y2="105.78"/>
<line x1="45" x2="51" y1="109.04" y2="109.04"/>
<line x1="39" x2="51" y1="112.3" y2="112.3"/>
<line x1="45" x2="51" y1="115.56" y2="115.56"/>
<line x1="45" x2="51" y1="118.82" y2="118.82"/>
<line x1="45" x2="51" y1="122.08" y2="122.08"/>
<line x1="45" x2="51" y1="125.34" y2="125.34"/>
<line x1="45" x2="51" y1="128.6" y2="128.6"/>
<line x1="45" x2="51" y1="131.86" y2="131.86"/>
<line x1="45" x2="51" y1="135.12" y2="135.12"/>
<line x1="45" x2="51" y1="138.38" y2="138.38"/>
<line x1="45" x2="51" y1="141.64" y2="141.64"/>
<line x1="39" x2="51" y1="144.9" y2="144.9"/>
<line x1="45" x2="51" y1="148.16" y2="148.16"/>
<line x1="45" x2="51" y1="151.42" y2="151.42"/>
<line x1="45" x2="51" y1="154.68" y2="154.68"/>
<line x1="45" x2="51" y1="157.94" y2="157.94"/>
<line x1="45" x2="51" y1="161.2" y2="161.2"/>
<line x1="45" x2="51" y1="164.46" y2="164.46"/>
<line x1="45" x2="51" y1="167.72" y2="167.72"/>
<line x1="45" x2="51" y1="170.98" y2="170.98"/>
<line x1="45" x2="51" y1="174.24" y2="174.24"/>
<line x1="38.985" x2="50.985" y1="177.96" y2="177.96"/>
</g>
</g><g tb:tag="progressBar">
<rect x="79.5" y="10.5" width="6" height="169" ry="1.12" stroke="#cecece" tb:tag="progressBorder"/>
<rect transform="scale(1,-1)" x="79.5" y="-180" width="6" height="62" ry="1.12" fill="#4d94e1" stroke="#4d94e1" tb:tag="progressFill"/>
<circle cx="82.5" cy="185" r="7" fill="#4d94e1" tb:tag="progressCircle"/>
</g><g transform="translate(0,167)" fill="#1c943e" style="display: none;" tb:tag="progress-indicator">
<path d="m75 10.562 10.5 6.062v-12.124z" style=""/>
</g><g transform="translate(12)" filter="url(#filter0_ii_3742_299961)" style="display: none;" tb:tag="value-box">
<rect x="22" y="164" width="56" height="28" rx="4" fill="#fffefe" fill-opacity=".75" tb:tag="value-box-background" style=""/>
<rect x="23" y="165" width="54" height="26" rx="3" stroke="#fff" stroke-width="2" style=""/>
<text x="49.853027" y="179.5625" fill="#727171" font-family="Roboto" font-size="14px" font-weight="500" text-anchor="middle" tb:tag="value-text" xml:space="preserve" style=""><tspan dominant-baseline="middle">37%</tspan></text>
</g><path d="m49.56 0s-25.56 0-25.56 33.5v164.18c0 1.3256 0.68053 2.3202 1.52 2.3202h72.96c0.83942 0 1.52-0.9946 1.52-2.3202v-164.18c0-33.5-25.107-33.5-25.107-33.5h-12.893zm25.487 40.6c-0.48969 0-0.88669 0.6268-0.88669 1.4v150.2c0 0.7732 0.39697 1.4 0.88669 1.4h5.5733c0.48969 0 0.88669-0.6268 0.88669-1.4v-150.2c0-0.7732-0.39697-1.4-0.88669-1.4z" fill-opacity="0" tb:tag="clickArea"/><path d="m8 200c2.2091 0 4-1.791 4-4v-192c0-2.2091-1.7909-4-4-4h-4c-2.2091 0-4 1.7909-4 4v192c0 2.209 1.7909 4 4 4h4z" fill="#93979B"/><path d="m8 200c2.2091 0 4-1.791 4-4v-192c0-2.2091-1.7909-4-4-4h-4c-2.2091 0-4 1.7909-4 4v192c0 2.209 1.7909 4 4 4h4z" fill="url(#paint1_linear_3742_299973)"/><path d="m8 198.5c1.3807 0 2.5-1.119 2.5-2.5v-192c0-1.3807-1.1193-2.5-2.5-2.5h-4c-1.3807 0-2.5 1.1193-2.5 2.5v192c0 1.381 1.1193 2.5 2.5 2.5h4z" stroke="#000" stroke-opacity=".12" stroke-width="3"/><path d="m12 146c0 2.209 1.7908 4 3.9999 4h4c2.2092 0 4.0001-1.791 4.0001-4v-92c0-2.2091-1.7909-4-4-4h-4c-2.2091 0-4 1.7909-4 4v92z" fill="#647484"/><path d="m12 146c0 2.209 1.7908 4 3.9999 4h4c2.2092 0 4.0001-1.791 4.0001-4v-92c0-2.2091-1.7909-4-4-4h-4c-2.2091 0-4 1.7909-4 4v92z" fill="url(#paint2_linear_3742_299973)"/><path d="m13.5 146c0 1.38 1.1193 2.5 2.4999 2.5h4c1.3808 0 2.5001-1.119 2.5001-2.5v-92c0-1.3807-1.1193-2.5-2.5-2.5h-4c-1.3807 0-2.5 1.1193-2.5 2.5v92z" stroke="#000" stroke-opacity=".12" stroke-width="3"/><defs>
<linearGradient id="paint0_linear_3742_299973" x1="100" x2="24" y1="100" y2="100.09" gradientUnits="userSpaceOnUse">
<stop stop-color="#020202" stop-opacity=".35" offset="0"/>
<stop stop-color="#020202" stop-opacity=".12" offset=".02629"/>
<stop stop-color="#fff" stop-opacity=".12" offset=".11617"/>
<stop stop-color="#fff" stop-opacity=".3" offset=".49829"/>
<stop stop-color="#fff" stop-opacity=".12" offset=".88762"/>
<stop stop-color="#020202" stop-opacity=".12" offset=".96591"/>
<stop stop-color="#020202" stop-opacity=".35" offset="1"/>
</linearGradient>
<linearGradient id="paint1_linear_3742_299973" x1="1.9297" x2="46.003" y1="-14.344" y2="205.53" gradientUnits="userSpaceOnUse">
<stop stop-color="#020202" stop-opacity=".35" offset="0"/>
<stop stop-color="#020202" stop-opacity=".12" offset=".23574"/>
<stop stop-color="#fff" stop-opacity=".12" offset=".39937"/>
<stop stop-color="#fff" stop-opacity=".3" offset=".49829"/>
<stop stop-color="#fff" stop-opacity=".12" offset=".59721"/>
<stop stop-color="#020202" stop-opacity=".12" offset=".76303"/>
<stop stop-color="#020202" stop-opacity=".35" offset="1"/>
</linearGradient>
<linearGradient id="paint2_linear_3742_299973" x1="19.045" x2="14.639" y1="53.812" y2="145.03" gradientUnits="userSpaceOnUse">
<stop stop-color="#020202" stop-opacity=".2" offset="0"/>
<stop stop-color="#020202" stop-opacity=".18" offset=".090959"/>
<stop stop-color="#020202" stop-opacity=".1" offset=".1"/>
<stop stop-color="#020202" stop-opacity=".08" offset=".20513"/>
<stop stop-color="#020202" stop-opacity=".05" offset=".21555"/>
<stop stop-color="#020202" stop-opacity=".02" offset=".36962"/>
<stop stop-color="#fff" stop-opacity=".01" offset=".37768"/>
<stop stop-color="#fff" stop-opacity=".01" offset=".62413"/>
<stop stop-color="#020202" stop-opacity=".02" offset=".6313"/>
<stop stop-color="#020202" stop-opacity=".05" offset=".77601"/>
<stop stop-color="#020202" stop-opacity=".08" offset=".7898"/>
<stop stop-color="#020202" stop-opacity=".1" offset=".9"/>
<stop stop-color="#020202" stop-opacity=".18" offset=".90846"/>
<stop stop-color="#020202" stop-opacity=".2" offset="1"/>
</linearGradient>
<filter id="filter0_ii_3742_299961" x="20" y="162" width="60" height="32" color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
<feColorMatrix in="SourceAlpha" result="hardAlpha" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/>
<feOffset dx="-2" dy="2"/>
<feGaussianBlur stdDeviation="3"/>
<feComposite in2="hardAlpha" k2="-1" k3="1" operator="arithmetic"/>
<feColorMatrix values="0 0 0 0 0.445833 0 0 0 0 0.445833 0 0 0 0 0.445833 0 0 0 0.5 0"/>
<feBlend in2="shape" result="effect1_innerShadow_3742_299961"/>
<feColorMatrix in="SourceAlpha" result="hardAlpha" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/>
<feOffset dx="2" dy="-2"/>
<feGaussianBlur stdDeviation="2"/>
<feComposite in2="hardAlpha" k2="-1" k3="1" operator="arithmetic"/>
<feColorMatrix values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0.5 0"/>
<feBlend in2="effect1_innerShadow_3742_299961" result="effect2_innerShadow_3742_299961"/>
</filter>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 45 KiB

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

@ -26,6 +26,8 @@
"hp_bottom_tee_connector",
"hp_right_tee_connector",
"hp_left_tee_connector",
"hp_top_tee_connector"
"hp_top_tee_connector",
"hp_drawwork",
"hp_crane"
]
}

20
application/src/main/data/json/system/widget_bundles/high_performance_scada_oil_gas.json

@ -0,0 +1,20 @@
{
"widgetsBundle": {
"alias": "high_performance_scada_oil_gas",
"title": "High-performance SCADA oil & gas",
"image": "tb-image:aHBfc2NhZGFfb2lsX2dhc19zeXN0ZW1fYnVuZGxlX2ltYWdlLnBuZw==:IkhpZ2gtcGVyZm9ybWFuY2UgU0NBREEgb2lsICYgZ2FzIiBzeXN0ZW0gYnVuZGxlIGltYWdl:SU1BR0U=;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAACgCAMAAAB+IdObAAAAflBMVEXe3t7b29vf398AAADf39/e3t7e3t7////Gxsapqam5ubnR0NDj4+Otra2hoaHS0tLi4uK4uLjx8fGYmJikpKSdnZ2VlZWWlpbU1NS1tbWnp6eKioqysrLLy8uampra2tqvr6/X19eRkZF+fn7Dw8N1dXW/vr6FhYViYmJwcHCzXr36AAAABnRSTlPvIK8Av79l/pT7AAAI0UlEQVR42uza23LaMBSF4Z5msbyFpOFMAXcg0HT6/i/YGqvdNhBiYXtipf0v7CRX+UaSbWQ+fP745QNS79PHzx8+ps8A8JvxCe+idzCtwpC8Fwj+Q4bWvw0R7oQiJIbTAxAvwOmAIsFgiodYXxxPODecMYmGeD4fAOQoGtCYxEIMgcMQJbEQD5wlCvEYRLEQoig/wCBkMIgiIYKyE+claTBzKxJClO0AegDI8x0GUTREz5NTbvJUR0RwzjjAn1GpQlgcDif4nfiDAZAqBAIc8nBjNyY3ef6MQRR/HzlI7ZI7lCfHaIg5oA5Bu5bZzZaIKh6Cha9BHFq2HN2sb4gjra84rHAreCDKcjUr+n4b8n1WtHKW0LqDSGGwyFFmaOBMLGRv57uM4+moSWNONvuF7RrC8vhsBTBSEJwBEdfXUXRfux+RADIiJM4OSIIQVs8sHUmOiKlBSgd8pGS/2M8zrhutkemY2XyZ7TuGeKlBXHAJ4qN1q9mP+4ofs5WTXq5agipkqePzYLP7kBkiioIQIRrAifouSggCOsN0IaIQxyorJiOrb4uy5StrZFG2WVnTF8QZkAh5NjW4ebbKxqPo1pPdk2paQ7xHaGsAWMTMreXW7ibTUYum3DxtXBcQHRA5H6PmVjbqpKxLCEE9FUliEP49Uc9FNjGIBIdCwHSnFm8cwKQg9PqPXxgEr3ZkB4zp+tgBxNSWif7cDAJx3542nLa4+NrtkugAItefR3TxN4x2tthN1uPQ6G7jP01W2dyxszu7BXELAkIQk7Gh433I0ZaJ6fZZi8RtCEiPagN/aHS4hNSN2rAhwpch1qLasCEEX4JYCuIy4lbfXn+M36ycGHQMEby02K0aG27QbSbjadM7Bzfzhe0YAtYg6oAASGU7iLi8IaoD9OlAJBAUog5AkoHI1cBQHVEQu3nabyacNlsi2W6ebdkhRBe6QtQBIjKxDV4rzB0NtE4goiSFSI131SBf9ChEP+qKwV3IIF+9GWgsIRUHPNFDPUC8oJItDq7iePvX7U0hgmokIALt7b9L9yAEFENo6YwIL34TIk2IQPu796ulOrXC3q/29pethhDvoYV3PBzU3GoIEVRypr73W/TmcysaUjiqe7+hVCBE6OwIkPrfLTqvzxEpHApRSSojEiDBcXv/2qPv2kPoURQcNYhKBH3XHmJQFhw1COSsTAMixUEddQhcKSH6rj3EAlDHBaSUpDEiBCqOS0iQ0KPbeppa6riGBAn6rD3kynENKSWCfmsP4YXjGlJIHoYcs4t+ekQUARF1XENUQjyUrEcXrYmIYiDquIao5Fd797rcJgxEAbjX1UogBBRfErupm16mff8XbO2RWYuDqyCBx+30/EiMmTb6ugtSgYwtJcW2Q0hbUSSJkJ04ECJZO0rJRkE2hJkF4l4EYUMp0Qh5IswMEEPGvQDClAZ5RoglzAwQJpFch3DqRLK/WWsZEslVCFMqRE+4H5ILCSWWDf+OYQu0hDhGCDNh8iEFhRIbvhCCS5HYEiG1IUguRIZn+Cok55crqwm3R/IgRlrq/J3ZXLZW1u2exwnPCmRDROJj4PGB5Io8T3i+LA/CNJQUXFBRyf4syGEM0hFkvoqIpCJyFhxzttaeILNBRGKJ2BEVFsbupktcMwZpHEFyIc7RQGL8Y4GOxZHUW7KIjy3k8yE4NsvGT/bE4kjuraoFBS7kF4GQXR/fNcaRYcqGbJSKH+05EBwbnoUr3EVToxUGF/JLVETmePcCdco0ggv5hSDM67Wxds1MEEcTs79VaxkcWsU+6yg7sbVwIZ8PKQhi5UU2hFmpCeffnIpMg0z9+bYch9SWJEtBmC3z6UtuRar1D30lP9YVQXIgfPXNEcfEK9mdL0ezC868jS+KSJaoiBDYMmX1Fu/9iJvgiNeN9z06yoLEHb4iZPN6a3UugWpacbSstN98pvkgPPqWh4gkBdKVZ4falgKpWbXavzzQghXBhzNRPqWxjo1UbwXCx+1GmmshCD4uC39gSmP5MdccQI46aa5lWotDDUqcm9pYYxClW2muBSoy/kh5Ukm+6VO++Hm8d/jjpf3p9ydD4g6BiGQ6pPPnWqmCHOyyQ3UzQRi3QghKOAHSBPPIEhBLkqIigIhkIoR3/ajbAeTpEvKFZ28tcQhEJNMghWbuIY0uw5m91rqHMAslB1KEDoSgxMV/sOmUuoAoHa61tuoColTH+RDH6BBIIBayiToeVAhRtRaHLlUIUQ8mG2LAARCQRHuLH9UAIlO5nwp1K5CjhLMh4AAISKIV2akAwuW5DnLyrTmAqEMuhMEBEJDEIPsygPgRw7cA0la5FQEHQFDCsStyoxBuL9cqTQhRXT5EHAhBSfy0ZcsBpJHp4wgYh9Q2C+IcOBCCEhO/iyCQmi8ndN2vHEOI+pAFMehACEpc/MqiQJp2DNI2A4jNg6ADISjh+JVFgWjlcxKx8tEDSJcFYXQgBCU2slgEiPzPkHvWrBCDDoSghJMgzWnzGuSQBbEVRSDTJXoA2fbNFKzn6wFklQMxa0qBUGGi04hAlEBgc67WKigNQuYFV60bfcpOha3V9mtgfUrjPZxVkVQIT3xkQ2b2VqvRVHRzSHRGtFuFkUVWG7k2nwLhFEj8SvbTHxyqHd27o2UrktZbrhtxlP0/fqMgmyILYigJEl/JM0iai3bbNuBgyoLwUhByq1JdpNXBZv3UBpvPUo+bV4QpkvWu7BkffsAh8bWntN2B6I4hRHa1b5ibx9WmYK/qx87UrR6ZWW+0JclNWivpSjaz75oPD+L4+sFPxzIJ3q4i+Xepv5yXJKuCIFkQHAtLrP9yTpEKkXBX6YfDLsJIgcBf+bG8mo9YstTMD4HD7JO6mk80iKGFkt9aUyD3VRForSkQlyiZHYJn0EmQxN5aAIIjmQi5n4oMIX9tRUaer66vZkunfCafe4LISKAU8cLcU2tV3Odj+cJ85z7mBpL/H+x41/kPubf8Mx+s++od/RN58+98iPbb13//x2i/ev/67S8YXTU9MiU8PgAAAABJRU5ErkJggg==",
"scada": true,
"description": "Bundle with high-performance SCADA symbols for oil and gas system",
"order": 9405,
"name": "High-performance SCADA oil & gas"
},
"widgetTypeFqns": [
"hp_drilling_rig",
"hp_hook",
"hp_rotor",
"hp_preventer",
"hp_drill",
"hp_drilling_line",
"hp_platform"
]
}

4
application/src/main/data/json/system/widget_bundles/scada_fluid_system.json

@ -42,6 +42,10 @@
"vertical_inline_flow_meter",
"left_analog_water_level_meter",
"right_analog_water_level_meter",
"meter",
"small_meter",
"small_right_meter",
"small_left_meter",
"leak_sensor",
"centrifugal_pump",
"small_right_motor_pump",

10
application/src/main/java/org/thingsboard/server/service/ttl/AlarmsCleanUpService.java

@ -17,6 +17,7 @@ package org.thingsboard.server.service.ttl;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
@ -66,7 +67,7 @@ public class AlarmsCleanUpService {
try {
cleanUp(tenantId);
} catch (Exception e) {
log.warn("Failed to clean up alarms by ttl for tenant {}", tenantId, e);
getLogger().warn("Failed to clean up alarms by ttl for tenant {}", tenantId, e);
}
}
}
@ -105,8 +106,13 @@ public class AlarmsCleanUpService {
alarmService.delAlarmTypes(tenantId, typesToRemove);
if (totalRemoved > 0) {
log.info("Removed {} outdated alarm(s) for tenant {} older than {}", totalRemoved, tenantId, new Date(expirationTime));
getLogger().info("Removed {} outdated alarm(s) for tenant {} older than {}", totalRemoved, tenantId, new Date(expirationTime));
}
}
// wrapper for tests to spy on static logger
Logger getLogger() {
return log;
}
}

31
application/src/test/java/org/thingsboard/server/controller/AbstractWebTest.java

@ -149,10 +149,6 @@ import org.thingsboard.server.service.security.auth.rest.LoginRequest;
import org.thingsboard.server.service.security.model.token.JwtTokenFactory;
import java.io.IOException;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.VarHandle;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.nio.charset.StandardCharsets;
import java.sql.SQLException;
import java.util.ArrayList;
@ -1053,33 +1049,6 @@ public abstract class AbstractWebTest extends AbstractInMemoryStorageTest {
throw new AssertionError("Unexpected status " + mvcResult.getResponse().getStatus());
}
protected static <T> T getFieldValue(Object target, String fieldName) throws Exception {
Field field = target.getClass().getDeclaredField(fieldName);
field.setAccessible(true);
return (T) field.get(target);
}
protected static void setStaticFieldValue(Class<?> targetCls, String fieldName, Object value) throws Exception {
Field field = targetCls.getDeclaredField(fieldName);
field.setAccessible(true);
field.set(null, value);
}
protected static void setStaticFinalFieldValue(Class<?> targetCls, String fieldName, Object value) throws Exception {
Field field = targetCls.getDeclaredField(fieldName);
field.setAccessible(true);
// Get the VarHandle for the 'modifiers' field in the Field class
MethodHandles.Lookup lookup = MethodHandles.privateLookupIn(Field.class, MethodHandles.lookup());
VarHandle modifiersHandle = lookup.findVarHandle(Field.class, "modifiers", int.class);
// Remove the final modifier from the field
int currentModifiers = field.getModifiers();
modifiersHandle.set(field, currentModifiers & ~Modifier.FINAL);
// Set the new value
field.set(null, value);
}
protected int getDeviceActorSubscriptionCount(DeviceId deviceId, FeatureType featureType) {
DeviceActorMessageProcessor processor = getDeviceActorProcessor(deviceId);
Map<UUID, SessionInfo> subscriptions = (Map<UUID, SessionInfo>) ReflectionTestUtils.getField(processor, getMapName(featureType));

2
application/src/test/java/org/thingsboard/server/edge/DeviceProfileEdgeTest.java

@ -359,7 +359,7 @@ public class DeviceProfileEdgeTest extends AbstractEdgeTest {
transportConfiguration.setBootstrapServerUpdateEnable(true);
TelemetryMappingConfiguration observeAttrConfiguration =
JacksonUtil.fromString(AbstractLwM2MIntegrationTest.OBSERVE_ATTRIBUTES_WITH_PARAMS, TelemetryMappingConfiguration.class);
JacksonUtil.fromString(AbstractLwM2MIntegrationTest.TELEMETRY_WITHOUT_OBSERVE, TelemetryMappingConfiguration.class);
transportConfiguration.setObserveAttr(observeAttrConfiguration);
List<LwM2MBootstrapServerCredential> bootstrap = new ArrayList<>();

15
application/src/test/java/org/thingsboard/server/edge/imitator/EdgeImitator.java

@ -66,7 +66,9 @@ import org.thingsboard.server.gen.edge.v1.WidgetsBundleUpdateMsg;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ThreadLocalRandom;
@ -78,6 +80,7 @@ import java.util.stream.Collectors;
@Slf4j
public class EdgeImitator {
private static final int MAX_DOWNLINK_FAILS = 2;
private final String routingKey;
private final String routingSecret;
@ -93,6 +96,7 @@ public class EdgeImitator {
private boolean randomFailuresOnTimeseriesDownlink = false;
@Setter
private double failureProbability = 0.0;
private final Map<Integer, Integer> downlinkFailureCountMap = new HashMap<>();
@Getter
private EdgeConfiguration configuration;
@ -244,8 +248,11 @@ public class EdgeImitator {
if (downlinkMsg.getEntityDataCount() > 0) {
for (EntityDataProto entityData : downlinkMsg.getEntityDataList()) {
if (randomFailuresOnTimeseriesDownlink) {
if (getRandomBoolean()) {
int downlinkMsgId = downlinkMsg.getDownlinkMsgId();
if (getRandomBoolean() && checkFailureThreshold(downlinkMsgId)) {
result.add(Futures.immediateFailedFuture(new RuntimeException("Random failure. This is expected error for edge test")));
downlinkFailureCountMap.put(downlinkMsgId, downlinkFailureCountMap.getOrDefault(downlinkMsgId, 0) + 1);
} else {
result.add(saveDownlinkMsg(entityData));
}
@ -354,6 +361,12 @@ public class EdgeImitator {
return Futures.allAsList(result);
}
private boolean checkFailureThreshold(int downlinkMsgId) {
return failureProbability == 100 ||
downlinkFailureCountMap.get(downlinkMsgId) == null ||
downlinkFailureCountMap.get(downlinkMsgId) < MAX_DOWNLINK_FAILS;
}
private boolean getRandomBoolean() {
double randomValue = ThreadLocalRandom.current().nextDouble() * 100;
return randomValue <= this.failureProbability;

5
application/src/test/java/org/thingsboard/server/service/script/AbstractTbelInvokeTest.java

@ -16,8 +16,10 @@
package org.thingsboard.server.service.script;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.thingsboard.common.util.JacksonUtil;
import org.thingsboard.script.api.ScriptType;
import org.thingsboard.script.api.tbel.DefaultTbelInvokeService;
import org.thingsboard.script.api.tbel.TbelInvokeService;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.controller.AbstractControllerTest;
@ -28,7 +30,8 @@ import java.util.concurrent.ExecutionException;
import static org.thingsboard.server.common.data.msg.TbMsgType.POST_TELEMETRY_REQUEST;
public abstract class AbstractTbelInvokeTest extends AbstractControllerTest {
@SpringBootTest(classes = DefaultTbelInvokeService.class)
public abstract class AbstractTbelInvokeTest {
@Autowired
protected TbelInvokeService invokeService;

26
application/src/test/java/org/thingsboard/server/service/script/TbelInvokeDocsIoTest.java

@ -18,7 +18,6 @@ package org.thingsboard.server.service.script;
import org.junit.jupiter.api.Test;
import org.thingsboard.common.util.JacksonUtil;
import org.thingsboard.script.api.tbel.TbDate;
import org.thingsboard.server.dao.service.DaoSqlTest;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
@ -34,7 +33,6 @@ import java.util.concurrent.atomic.AtomicReference;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.junit.jupiter.api.Assertions.assertEquals;
@DaoSqlTest
class TbelInvokeDocsIoTest extends AbstractTbelInvokeTest {
private String decoderStr;
@ -1469,6 +1467,26 @@ class TbelInvokeDocsIoTest extends AbstractTbelInvokeTest {
assertEquals(expected, actual);
}
// hexToBytes List or Array
@Test
public void hexToBytes_Test() throws ExecutionException, InterruptedException {
msgStr = "{}";
decoderStr = """
var validInputList = "0x01752B0367FA000500010488FFFFFFFFFFFFFFFF33";
var validInputArray = "AABBCCDDEE";
return {
"hexToBytes": hexToBytes(validInputList),
"hexToBytesArray": hexToBytesArray(validInputArray),
}
""";
Object actual = invokeScript(evalScript(decoderStr), msgStr);
LinkedHashMap<String, Object> expected = new LinkedHashMap<>();
expected.put("hexToBytes", bytesToList(new byte[]{1, 117, 43, 3, 103, -6, 0, 5, 0, 1, 4, -120, -1, -1, -1, -1, -1, -1, -1, -1, 51}));
// [-86, -69, -52, -35, -18] == new byte[]{(byte) 0xAA, (byte) 0xBB, (byte) 0xCC, (byte) 0xDD, (byte) 0xEE}
expected.put("hexToBytesArray", bytesToList(new byte[]{(byte) 0xAA, (byte) 0xBB, (byte) 0xCC, (byte) 0xDD, (byte) 0xEE}));
assertEquals( expected, actual);
}
// parseBinaryArray
@Test
public void parseBinaryArray_Test() throws ExecutionException, InterruptedException {
@ -1761,13 +1779,15 @@ class TbelInvokeDocsIoTest extends AbstractTbelInvokeTest {
return {
"base64ToHex": base64ToHex("Kkk="),
"bytesToBase64": bytesToBase64([42, 73]),
"base64ToBytes": base64ToBytes("Kkk=")
"base64ToBytes": base64ToBytes("Kkk="),
"base64ToBytesList": base64ToBytesList("AQIDBAU=")
}
""";
LinkedHashMap<String, Object> expected = new LinkedHashMap<>();
expected.put("base64ToHex", "2A49");
expected.put("bytesToBase64", "Kkk=");
expected.put("base64ToBytes", bytesToList(new byte[]{42, 73}));
expected.put("base64ToBytesList", bytesToList(new byte[]{1, 2, 3, 4, 5}));
Object actual = invokeScript(evalScript(decoderStr), msgStr);
assertEquals(expected, actual);
}

19
application/src/test/java/org/thingsboard/server/service/script/TbelInvokeServiceTest.java

@ -22,9 +22,9 @@ import org.junit.Ignore;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.test.context.TestPropertySource;
import org.springframework.test.util.ReflectionTestUtils;
import org.thingsboard.common.util.JacksonUtil;
import org.thingsboard.script.api.tbel.TbelScript;
import org.thingsboard.server.dao.service.DaoSqlTest;
import java.io.Serializable;
import java.util.ArrayList;
@ -38,7 +38,6 @@ import java.util.concurrent.TimeUnit;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
@DaoSqlTest
@TestPropertySource(properties = {
"tbel.max_script_body_size=100",
"tbel.max_total_args_size=50",
@ -120,9 +119,9 @@ class TbelInvokeServiceTest extends AbstractTbelInvokeTest {
scriptsIds.add(scriptId);
}
Map<UUID, String> scriptIdToHash = getFieldValue(invokeService, "scriptIdToHash");
Map<String, TbelScript> scriptMap = getFieldValue(invokeService, "scriptMap");
Cache<String, Serializable> compiledScriptsCache = getFieldValue(invokeService, "compiledScriptsCache");
Map<UUID, String> scriptIdToHash = (Map<UUID, String>) ReflectionTestUtils.getField(invokeService, "scriptIdToHash");
Map<String, TbelScript> scriptMap = (Map<String, TbelScript>) ReflectionTestUtils.getField(invokeService, "scriptMap");
Cache<String, Serializable> compiledScriptsCache = (Cache<String, Serializable>) ReflectionTestUtils.getField(invokeService, "compiledScriptsCache");
String scriptHash = scriptIdToHash.get(scriptsIds.get(0));
@ -140,9 +139,9 @@ class TbelInvokeServiceTest extends AbstractTbelInvokeTest {
scriptsIds.add(scriptId);
}
Map<UUID, String> scriptIdToHash = getFieldValue(invokeService, "scriptIdToHash");
Map<String, TbelScript> scriptMap = getFieldValue(invokeService, "scriptMap");
Cache<String, Serializable> compiledScriptsCache = getFieldValue(invokeService, "compiledScriptsCache");
Map<UUID, String> scriptIdToHash = (Map<UUID, String>) ReflectionTestUtils.getField(invokeService, "scriptIdToHash");
Map<String, TbelScript> scriptMap = (Map<String, TbelScript>) ReflectionTestUtils.getField(invokeService, "scriptMap");
Cache<String, Serializable> compiledScriptsCache = (Cache<String, Serializable>) ReflectionTestUtils.getField(invokeService, "compiledScriptsCache");
String scriptHash = scriptIdToHash.get(scriptsIds.get(0));
for (int i = 0; i < 9; i++) {
@ -163,8 +162,8 @@ class TbelInvokeServiceTest extends AbstractTbelInvokeTest {
@Ignore("This test is based on assumption that Caffeine cache is LRU based but in fact it is based on " +
"Tiny LFU which is the cause that the tests fail sometime: https://arxiv.org/pdf/1512.00727.pdf")
public void whenCompiledScriptsCacheIsTooBig_thenRemoveRarelyUsedScripts() throws Exception {
Map<UUID, String> scriptIdToHash = getFieldValue(invokeService, "scriptIdToHash");
Cache<String, Serializable> compiledScriptsCache = getFieldValue(invokeService, "compiledScriptsCache");
Map<UUID, String> scriptIdToHash = (Map<UUID, String>) ReflectionTestUtils.getField(invokeService, "scriptIdToHash");
Cache<String, Serializable> compiledScriptsCache = (Cache<String, Serializable>) ReflectionTestUtils.getField(invokeService, "compiledScriptsCache");
List<UUID> scriptsIds = new ArrayList<>();
for (int i = 0; i < 110; i++) { // tbel.compiled_scripts_cache_size = 100

17
application/src/test/java/org/thingsboard/server/service/ttl/AlarmsCleanUpServiceTest.java

@ -15,7 +15,7 @@
*/
package org.thingsboard.server.service.ttl;
import org.junit.BeforeClass;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mockito;
import org.slf4j.Logger;
@ -40,6 +40,7 @@ import java.util.concurrent.TimeUnit;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.startsWith;
import static org.mockito.BDDMockito.willReturn;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
@ -49,19 +50,19 @@ import static org.mockito.Mockito.verify;
})
public class AlarmsCleanUpServiceTest extends AbstractControllerTest {
@Autowired
@SpyBean
private AlarmsCleanUpService alarmsCleanUpService;
@SpyBean
private AlarmService alarmService;
@Autowired
private AlarmDao alarmDao;
private static Logger cleanUpServiceLogger;
private Logger cleanUpServiceLoggerSpy;
@BeforeClass
public static void before() throws Exception {
cleanUpServiceLogger = Mockito.spy(LoggerFactory.getLogger(AlarmsCleanUpService.class));
setStaticFinalFieldValue(AlarmsCleanUpService.class, "log", cleanUpServiceLogger);
@Before
public void beforeEach() throws Exception {
cleanUpServiceLoggerSpy = Mockito.spy(LoggerFactory.getLogger(AlarmsCleanUpService.class));
willReturn(cleanUpServiceLoggerSpy).given(alarmsCleanUpService).getLogger();
}
@Test
@ -110,7 +111,7 @@ public class AlarmsCleanUpServiceTest extends AbstractControllerTest {
verify(alarmService, never()).delAlarm(eq(tenantId), eq(freshAlarm), eq(false));
}
verify(cleanUpServiceLogger).info(startsWith("Removed {} outdated alarm"), eq((long) count), eq(tenantId), any());
verify(cleanUpServiceLoggerSpy).info(startsWith("Removed {} outdated alarm"), eq((long) count), eq(tenantId), any());
}
}

8
application/src/test/java/org/thingsboard/server/transport/coap/AbstractCoapIntegrationTest.java

@ -54,6 +54,14 @@ public abstract class AbstractCoapIntegrationTest extends AbstractTransportInteg
protected final byte[] EMPTY_PAYLOAD = new byte[0];
protected CoapTestClient client;
protected static final String PAYLOAD_VALUES_STR = "{\"key1\":\"value1\", \"key2\":true, \"key3\": 3.0, \"key4\": 4," +
" \"key5\": {\"someNumber\": 42, \"someArray\": [1,2,3], \"someNestedObject\": {\"key\": \"value\"}}}";
protected static final String PAYLOAD_VALUES_STR_01 = "{\"key2\":\"value2\", \"key3\":false, \"key4\": 4.0, \"key5\": 5," +
" \"key6\": {\"someNumber_02\": 52, \"someArray_02\": [1,2,3,4], \"someNestedObject_02\": {\"key_02\": \"value_02\"}}}";
protected void processBeforeTest() throws Exception {
loginTenantAdmin();
}
protected void processAfterTest() throws Exception {
if (client != null) {

2
application/src/test/java/org/thingsboard/server/transport/coap/client/CoapClientIntegrationTest.java

@ -63,8 +63,6 @@ import static org.thingsboard.server.common.data.query.EntityKeyType.SHARED_ATTR
@DaoSqlTest
public class CoapClientIntegrationTest extends AbstractCoapIntegrationTest {
private static final String PAYLOAD_VALUES_STR = "{\"key1\":\"value1\", \"key2\":true, \"key3\": 3.0, \"key4\": 4," +
" \"key5\": {\"someNumber\": 42, \"someArray\": [1,2,3], \"someNestedObject\": {\"key\": \"value\"}}}";
private static final List<String> EXPECTED_KEYS = Arrays.asList("key1", "key2", "key3", "key4", "key5");
private static final String DEVICE_RESPONSE = "{\"value1\":\"A\",\"value2\":\"B\"}";

291
application/src/test/java/org/thingsboard/server/transport/coap/security/AbstractCoapSecurityIntegrationTest.java

@ -0,0 +1,291 @@
/**
* 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.coap.security;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JsonNode;
import lombok.extern.slf4j.Slf4j;
import org.eclipse.californium.core.CoapResponse;
import org.eclipse.californium.core.coap.CoAP;
import org.junit.Assert;
import org.springframework.test.context.TestPropertySource;
import org.thingsboard.common.util.JacksonUtil;
import org.thingsboard.server.common.data.CoapDeviceType;
import org.thingsboard.server.common.data.Device;
import org.thingsboard.server.common.data.DeviceProfile;
import org.thingsboard.server.common.data.SaveDeviceWithCredentialsRequest;
import org.thingsboard.server.common.data.TransportPayloadType;
import org.thingsboard.server.common.data.id.DeviceId;
import org.thingsboard.server.common.data.id.DeviceProfileId;
import org.thingsboard.server.common.data.security.DeviceCredentials;
import org.thingsboard.server.common.data.security.DeviceCredentialsType;
import org.thingsboard.server.common.msg.session.FeatureType;
import org.thingsboard.server.transport.coap.AbstractCoapIntegrationTest;
import org.thingsboard.server.transport.coap.x509.CertPrivateKey;
import org.thingsboard.server.transport.coap.x509.CoapClientX509Test;
import org.thingsboard.server.transport.coap.CoapTestConfigProperties;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.security.GeneralSecurityException;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import static org.awaitility.Awaitility.await;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
@Slf4j
@TestPropertySource(properties = {
"coap.enabled=true",
"coap.dtls.enabled=true",
"coap.dtls.credentials.pem.cert_file=coap/credentials/server/cert.pem",
"device.connectivity.coaps.enabled=true",
"service.integrations.supported=ALL",
"transport.coap.enabled=true",
})
public abstract class AbstractCoapSecurityIntegrationTest extends AbstractCoapIntegrationTest {
private static final String COAPS_BASE_URL = "coaps://localhost:5684/api/v1/";
protected final String CREDENTIALS_PATH = "coap/credentials/";
protected final String CREDENTIALS_PATH_CLIENT = CREDENTIALS_PATH + "client/";
protected final String CREDENTIALS_PATH_CLIENT_CERT_PEM = CREDENTIALS_PATH_CLIENT + "cert.pem";
protected final String CREDENTIALS_PATH_CLIENT_KEY_PEM = CREDENTIALS_PATH_CLIENT + "key.pem";
protected final X509Certificate clientX509CertTrustNo; // client certificate signed by intermediate, rootCA with a good CN ("host name")
protected final PrivateKey clientPrivateKeyFromCertTrustNo;
protected static final String CLIENT_JKS_FOR_TEST = "coapclientTest";
protected static final String CLIENT_STORE_PWD = "client_ks_password";
protected static final String CLIENT_ALIAS_CERT_TRUST_NO = "client_alias_trust_no";
protected AbstractCoapSecurityIntegrationTest() {
try {
// Get certificates from key store
char[] clientKeyStorePwd = CLIENT_STORE_PWD.toCharArray();
KeyStore clientKeyStore = KeyStore.getInstance(KeyStore.getDefaultType());
try (InputStream clientKeyStoreFile =
this.getClass().getClassLoader().
getResourceAsStream(CREDENTIALS_PATH + CLIENT_JKS_FOR_TEST + ".jks")) {
clientKeyStore.load(clientKeyStoreFile, clientKeyStorePwd);
}
// No trust
clientPrivateKeyFromCertTrustNo = (PrivateKey) clientKeyStore.getKey(CLIENT_ALIAS_CERT_TRUST_NO, clientKeyStorePwd);
clientX509CertTrustNo = (X509Certificate) clientKeyStore.getCertificate(CLIENT_ALIAS_CERT_TRUST_NO);
} catch (GeneralSecurityException | IOException e) {
throw new RuntimeException(e);
}
}
protected Device createDeviceWithX509(String deviceName, DeviceProfileId deviceProfileId, X509Certificate clientX509Cert) throws Exception {
Device device = new Device();
device.setName(deviceName);
device.setType(deviceName);
device.setDeviceProfileId(deviceProfileId);
DeviceCredentials deviceCredentials = new DeviceCredentials();
deviceCredentials.setCredentialsType(DeviceCredentialsType.X509_CERTIFICATE);
String pemFormatCert = CertPrivateKey.convertCertToPEM(clientX509Cert);
deviceCredentials.setCredentialsValue(pemFormatCert);
SaveDeviceWithCredentialsRequest saveRequest = new SaveDeviceWithCredentialsRequest(device, deviceCredentials);
Device deviceX509 = readResponse(doPost("/api/device-with-credentials", saveRequest)
.andExpect(status().isOk()), Device.class);
DeviceCredentials savedDeviceCredentials =
doGet("/api/device/" + deviceX509.getId().getId() + "/credentials", DeviceCredentials.class);
Assert.assertNotNull(savedDeviceCredentials);
Assert.assertNotNull(savedDeviceCredentials.getId());
Assert.assertEquals(deviceX509.getId(), savedDeviceCredentials.getDeviceId());
Assert.assertEquals(DeviceCredentialsType.X509_CERTIFICATE, savedDeviceCredentials.getCredentialsType());
accessToken = savedDeviceCredentials.getCredentialsId();
assertNotNull(accessToken);
return deviceX509;
}
protected void clientX509FromJksUpdateAttributesTest() throws Exception {
CertPrivateKey certPrivateKey = new CertPrivateKey(clientX509CertTrustNo, clientPrivateKeyFromCertTrustNo);
CoapTestConfigProperties configProperties = CoapTestConfigProperties.builder()
.coapDeviceType(CoapDeviceType.DEFAULT)
.transportPayloadType(TransportPayloadType.JSON)
.build();
DeviceProfile deviceProfile = createCoapDeviceProfile(configProperties);
assertNotNull(deviceProfile);
CoapClientX509Test clientX509 = clientX509UpdateTest(FeatureType.ATTRIBUTES, certPrivateKey,
"CoapX509TrustNo_" + FeatureType.ATTRIBUTES.name(), deviceProfile.getId(), null);
clientX509.disconnect();
}
protected void clientX509FromPathUpdateFeatureTypeTest(FeatureType featureType) throws Exception {
CertPrivateKey certPrivateKey = new CertPrivateKey(CREDENTIALS_PATH_CLIENT_CERT_PEM, CREDENTIALS_PATH_CLIENT_KEY_PEM);
CoapTestConfigProperties configProperties = CoapTestConfigProperties.builder()
.coapDeviceType(CoapDeviceType.DEFAULT)
.transportPayloadType(TransportPayloadType.JSON)
.build();
DeviceProfile deviceProfile = createCoapDeviceProfile(configProperties);
assertNotNull(deviceProfile);
CoapClientX509Test clientX509 = clientX509UpdateTest(featureType, certPrivateKey,
"CoapX509TrustNo_" + featureType.name(), deviceProfile.getId(), null);
clientX509.disconnect();
}
protected void twoClientWithSamePortX509FromPathConnectTest() throws Exception {
CoapTestConfigProperties configProperties = CoapTestConfigProperties.builder()
.coapDeviceType(CoapDeviceType.DEFAULT)
.transportPayloadType(TransportPayloadType.JSON)
.build();
DeviceProfile deviceProfile = createCoapDeviceProfile(configProperties);
CertPrivateKey certPrivateKey = new CertPrivateKey(CREDENTIALS_PATH_CLIENT_CERT_PEM, CREDENTIALS_PATH_CLIENT_KEY_PEM);
CertPrivateKey certPrivateKey_01 = new CertPrivateKey(CREDENTIALS_PATH_CLIENT + "cert_01.pem",
CREDENTIALS_PATH_CLIENT + "key_01.pem");
Integer fixedPort = getFreePort();
CoapClientX509Test clientX509 = clientX509UpdateTest(FeatureType.ATTRIBUTES, certPrivateKey,
"CoapX509TrustNo_" + FeatureType.TELEMETRY.name(), deviceProfile.getId(), fixedPort);
clientX509.disconnect();
await("Need to make port " + fixedPort + " free")
.atMost(40, TimeUnit.SECONDS)
.until(() -> isPortAvailable(fixedPort));
CoapClientX509Test clientX509_01 = clientX509UpdateTest(FeatureType.ATTRIBUTES, certPrivateKey_01,
"CoapX509TrustNo_" + FeatureType.TELEMETRY.name() + "_01", deviceProfile.getId(),
fixedPort, PAYLOAD_VALUES_STR_01);
clientX509_01.disconnect();
}
private CoapClientX509Test clientX509UpdateTest(FeatureType featureType, CertPrivateKey certPrivateKey,
String deviceName, DeviceProfileId deviceProfileId, Integer fixedPort) throws Exception {
return clientX509UpdateTest(featureType, certPrivateKey, deviceName, deviceProfileId, fixedPort, null);
}
private CoapClientX509Test clientX509UpdateTest(FeatureType featureType, CertPrivateKey certPrivateKey,
String deviceName, DeviceProfileId deviceProfileId, Integer fixedPort, String payload) throws Exception {
String payloadValuesStr = payload == null ? PAYLOAD_VALUES_STR : payload;
Device deviceX509 = createDeviceWithX509(deviceName, deviceProfileId, certPrivateKey.getCert());
CoapClientX509Test clientX509 = new CoapClientX509Test(certPrivateKey, featureType, COAPS_BASE_URL, fixedPort);
CoapResponse coapResponseX509 = clientX509.postMethod(payloadValuesStr);
assertNotNull(coapResponseX509);
assertEquals(CoAP.ResponseCode.CREATED, coapResponseX509.getCode());
if (FeatureType.ATTRIBUTES.equals(featureType)) {
DeviceId deviceId = deviceX509.getId();
JsonNode expectedNode = JacksonUtil.toJsonNode(payloadValuesStr);
List<String> expectedKeys = getKeysFromNode(expectedNode);
List<String> actualKeys = getActualKeysList(deviceId, expectedKeys, "attributes/CLIENT_SCOPE");
assertNotNull(actualKeys);
Set<String> actualKeySet = new HashSet<>(actualKeys);
Set<String> expectedKeySet = new HashSet<>(expectedKeys);
assertEquals(expectedKeySet, actualKeySet);
String getAttributesValuesUrl = getAttributesValuesUrl(deviceId, actualKeySet, "attributes/CLIENT_SCOPE");
List<Map<String, Object>> actualValues = doGetAsyncTyped(getAttributesValuesUrl, new TypeReference<>() {
});
assertValuesList(actualValues, expectedNode);
}
return clientX509;
}
private List<String> getActualKeysList(DeviceId deviceId, List<String> expectedKeys, String apiSuffix) throws Exception {
long start = System.currentTimeMillis();
long end = System.currentTimeMillis() + 5000;
List<String> actualKeys = null;
while (start <= end) {
actualKeys = doGetAsyncTyped("/api/plugins/telemetry/DEVICE/" + deviceId + "/keys/" + apiSuffix, new TypeReference<>() {
});
if (actualKeys.size() == expectedKeys.size()) {
break;
}
Thread.sleep(100);
start += 100;
}
return actualKeys;
}
private String getAttributesValuesUrl(DeviceId deviceId, Set<String> actualKeySet, String apiSuffix) {
return "/api/plugins/telemetry/DEVICE/" + deviceId + "/values/" + apiSuffix + "?keys=" + String.join(",", actualKeySet);
}
private List getKeysFromNode(JsonNode jNode) {
List<String> jKeys = new ArrayList<>();
Iterator<String> fieldNames = jNode.fieldNames();
while (fieldNames.hasNext()) {
jKeys.add(fieldNames.next());
}
return jKeys;
}
protected void assertValuesList(List<Map<String, Object>> actualValues, JsonNode expectedValues) {
assertTrue(actualValues.size() > 0);
assertEquals(expectedValues.size(), actualValues.size());
for (Map<String, Object> map : actualValues) {
String key = (String) map.get("key");
Object actualValue = map.get("value");
assertTrue(expectedValues.has(key));
JsonNode expectedValue = expectedValues.get(key);
assertExpectedActualValue(expectedValue, actualValue);
}
}
protected void assertExpectedActualValue(JsonNode expectedValue, Object actualValue) {
switch (expectedValue.getNodeType()) {
case STRING:
assertEquals(expectedValue.asText(), actualValue);
break;
case NUMBER:
if (expectedValue.isInt()) {
assertEquals(expectedValue.asInt(), actualValue);
} else if (expectedValue.isLong()) {
assertEquals(expectedValue.asLong(), actualValue);
} else if (expectedValue.isFloat() || expectedValue.isDouble()) {
assertEquals(expectedValue.asDouble(), actualValue);
}
break;
case BOOLEAN:
assertEquals(expectedValue.asBoolean(), actualValue);
break;
case ARRAY:
case OBJECT:
expectedValue.toString().equals(JacksonUtil.toString(actualValue));
break;
default:
break;
}
}
private static int getFreePort() throws IOException {
try (ServerSocket socket = new ServerSocket(0)) {
return socket.getLocalPort();
}
}
private static boolean isPortAvailable(int port) {
try (ServerSocket serverSocket = new ServerSocket(port)) {
serverSocket.setReuseAddress(true);
return true;
} catch (IOException e) {
return false;
}
}
}

44
application/src/test/java/org/thingsboard/server/transport/coap/security/sql/CoapClientX509SecurityJksIntegrationTest.java

@ -0,0 +1,44 @@
/**
* 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.coap.security.sql;
import lombok.extern.slf4j.Slf4j;
import org.junit.Before;
import org.junit.Test;
import org.springframework.test.context.TestPropertySource;
import org.thingsboard.server.dao.service.DaoSqlTest;
import org.thingsboard.server.transport.coap.security.AbstractCoapSecurityIntegrationTest;
@Slf4j
@DaoSqlTest
@TestPropertySource(properties = {
"coap.dtls.credentials.type=KEYSTORE",
"coap.dtls.credentials.keystore.store_file=coap/credentials/coapserverTest.jks",
"coap.dtls.credentials.keystore.key_password=server_ks_password",
"coap.dtls.credentials.keystore.key_alias=server",
})
public class CoapClientX509SecurityJksIntegrationTest extends AbstractCoapSecurityIntegrationTest {
@Before
public void beforeTest() throws Exception {
processBeforeTest();
}
@Test
public void testX509NoTrustFromJksConnectCoapSuccessUpdateAttributesSuccess() throws Exception {
clientX509FromJksUpdateAttributesTest();
}
}

44
application/src/test/java/org/thingsboard/server/transport/coap/security/sql/CoapClientX509SecurityPemIntegrationTest.java

@ -0,0 +1,44 @@
/**
* 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.coap.security.sql;
import lombok.extern.slf4j.Slf4j;
import org.junit.Before;
import org.junit.Test;
import org.thingsboard.server.common.msg.session.FeatureType;
import org.thingsboard.server.dao.service.DaoSqlTest;
import org.thingsboard.server.transport.coap.security.AbstractCoapSecurityIntegrationTest;
@Slf4j
@DaoSqlTest
public class CoapClientX509SecurityPemIntegrationTest extends AbstractCoapSecurityIntegrationTest {
@Before
public void beforeTest() throws Exception {
processBeforeTest();
}
@Test
public void testX509NoTrustFromPathConnectCoapSuccessUpdateAttributesSuccess() throws Exception {
clientX509FromPathUpdateFeatureTypeTest(FeatureType.ATTRIBUTES);
}
@Test
public void testX509NoTrustFromPathConnectCoapSuccessUpdateTelemetrySuccess() throws Exception {
clientX509FromPathUpdateFeatureTypeTest(FeatureType.TELEMETRY);
} @Test
public void testTwoDevicesWithSamePortX509NoTrustFromPathConnectCoapSuccess() throws Exception {
twoClientWithSamePortX509FromPathConnectTest();
}
}

3
application/src/test/java/org/thingsboard/server/transport/coap/telemetry/attributes/CoapAttributesIntegrationTest.java

@ -44,9 +44,6 @@ import static org.junit.Assert.assertTrue;
@DaoSqlTest
public class CoapAttributesIntegrationTest extends AbstractCoapIntegrationTest {
private static final String PAYLOAD_VALUES_STR = "{\"key1\":\"value1\", \"key2\":true, \"key3\": 3.0, \"key4\": 4," +
" \"key5\": {\"someNumber\": 42, \"someArray\": [1,2,3], \"someNestedObject\": {\"key\": \"value\"}}}";
@Before
public void beforeTest() throws Exception {
CoapTestConfigProperties configProperties = CoapTestConfigProperties.builder()

3
application/src/test/java/org/thingsboard/server/transport/coap/telemetry/timeseries/AbstractCoapTimeseriesIntegrationTest.java

@ -40,9 +40,6 @@ import static org.junit.Assert.assertNotNull;
@Slf4j
public abstract class AbstractCoapTimeseriesIntegrationTest extends AbstractCoapIntegrationTest {
private static final String PAYLOAD_VALUES_STR = "{\"key1\":\"value1\", \"key2\":true, \"key3\": 3.0, \"key4\": 4," +
" \"key5\": {\"someNumber\": 42, \"someArray\": [1,2,3], \"someNestedObject\": {\"key\": \"value\"}}}";
@Before
public void beforeTest() throws Exception {
CoapTestConfigProperties configProperties = CoapTestConfigProperties.builder()

82
application/src/test/java/org/thingsboard/server/transport/coap/x509/CertPrivateKey.java

@ -0,0 +1,82 @@
/**
* 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.coap.x509;
import org.apache.commons.io.FileUtils;
import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPrivateKey;
import org.thingsboard.common.util.SslUtil;
import java.io.File;
import java.io.IOException;
import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.cert.X509Certificate;
import java.security.interfaces.ECPrivateKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.Base64;
import java.util.List;
public class CertPrivateKey {
private final X509Certificate cert;
private PrivateKey privateKey;
public CertPrivateKey(String certFilePathPem, String keyFilePathPem) throws Exception {
List<X509Certificate> certs = SslUtil.readCertFile(fileRead(certFilePathPem));
this.cert = certs.get(0);
this.privateKey = SslUtil.readPrivateKey(fileRead(keyFilePathPem), null);
if (this.privateKey instanceof BCECPrivateKey) {
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(this.privateKey.getEncoded());
KeyFactory keyFactory = KeyFactory.getInstance("EC");
this.privateKey = keyFactory.generatePrivate(keySpec);
}
if (!(this.privateKey instanceof ECPrivateKey)) {
throw new RuntimeException("Private key generation must be of type java.security.interfaces.ECPrivateKey, which is used in the standard Java API!");
}
}
public CertPrivateKey(X509Certificate cert, PrivateKey privateKey) {
this.cert = cert;
this.privateKey = privateKey;
}
public X509Certificate getCert() {
return this.cert;
}
public PrivateKey getPrivateKey() {
return this.privateKey;
}
private String fileRead(String fileName) throws IOException {
ClassLoader classLoader = getClass().getClassLoader();
File file = new File(classLoader.getResource(fileName).getFile());
return FileUtils.readFileToString(file, "UTF-8");
}
public static String convertCertToPEM(X509Certificate certificate) throws Exception {
StringBuilder pemBuilder = new StringBuilder();
pemBuilder.append("-----BEGIN CERTIFICATE-----\n");
// Copy cert to Base64
String base64EncodedCert = Base64.getEncoder().encodeToString(certificate.getEncoded());
int index = 0;
while (index < base64EncodedCert.length()) {
pemBuilder.append(base64EncodedCert, index, Math.min(index + 64, base64EncodedCert.length()));
pemBuilder.append("\n");
index += 64;
}
pemBuilder.append("-----END CERTIFICATE-----\n");
return pemBuilder.toString();
}
}

239
application/src/test/java/org/thingsboard/server/transport/coap/x509/CoapClientX509Test.java

@ -0,0 +1,239 @@
/**
* 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.coap.x509;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.eclipse.californium.core.CoapClient;
import org.eclipse.californium.core.CoapHandler;
import org.eclipse.californium.core.CoapObserveRelation;
import org.eclipse.californium.core.CoapResponse;
import org.eclipse.californium.core.coap.CoAP;
import org.eclipse.californium.core.coap.MediaTypeRegistry;
import org.eclipse.californium.core.coap.Request;
import org.eclipse.californium.core.config.CoapConfig;
import org.eclipse.californium.core.network.CoapEndpoint;
import org.eclipse.californium.elements.config.Configuration;
import org.eclipse.californium.elements.config.ValueException;
import org.eclipse.californium.elements.exception.ConnectorException;
import org.eclipse.californium.scandium.DTLSConnector;
import org.eclipse.californium.scandium.config.DtlsConfig.SignatureAndHashAlgorithmsDefinition;
import org.eclipse.californium.scandium.config.DtlsConnectorConfig;
import org.eclipse.californium.scandium.dtls.CertificateType;
import org.eclipse.californium.scandium.dtls.SignatureAndHashAlgorithm;
import org.eclipse.californium.scandium.dtls.SignatureAndHashAlgorithm.HashAlgorithm;
import org.eclipse.californium.scandium.dtls.SignatureAndHashAlgorithm.SignatureAlgorithm;
import org.eclipse.californium.scandium.dtls.cipher.CipherSuite;
import org.eclipse.californium.scandium.dtls.x509.CertificateProvider;
import org.eclipse.californium.scandium.dtls.x509.SingleCertificateProvider;
import org.thingsboard.server.common.msg.session.FeatureType;
import org.thingsboard.server.transport.coap.CoapTestCallback;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.security.cert.X509Certificate;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.TimeUnit;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static org.eclipse.californium.core.config.CoapConfig.DEFAULT_BLOCKWISE_STATUS_LIFETIME_IN_SECONDS;
import static org.eclipse.californium.scandium.config.DtlsConfig.DTLS_AUTO_HANDSHAKE_TIMEOUT;
import static org.eclipse.californium.scandium.config.DtlsConfig.DTLS_CIPHER_SUITES;
import static org.eclipse.californium.scandium.config.DtlsConfig.DTLS_MAX_FRAGMENTED_HANDSHAKE_MESSAGE_LENGTH;
import static org.eclipse.californium.scandium.config.DtlsConfig.DTLS_MAX_PENDING_HANDSHAKE_RESULT_JOBS;
import static org.eclipse.californium.scandium.config.DtlsConfig.DTLS_MAX_RETRANSMISSIONS;
import static org.eclipse.californium.scandium.config.DtlsConfig.DTLS_MAX_RETRANSMISSION_TIMEOUT;
import static org.eclipse.californium.scandium.config.DtlsConfig.DTLS_RECEIVE_BUFFER_SIZE;
import static org.eclipse.californium.scandium.config.DtlsConfig.DTLS_RECOMMENDED_CIPHER_SUITES_ONLY;
import static org.eclipse.californium.scandium.config.DtlsConfig.DTLS_RETRANSMISSION_TIMEOUT;
import static org.eclipse.californium.scandium.config.DtlsConfig.DTLS_ROLE;
import static org.eclipse.californium.scandium.config.DtlsConfig.DTLS_SIGNATURE_AND_HASH_ALGORITHMS;
import static org.eclipse.californium.scandium.config.DtlsConfig.DTLS_USE_HELLO_VERIFY_REQUEST;
import static org.eclipse.californium.scandium.config.DtlsConfig.DTLS_USE_MULTI_HANDSHAKE_MESSAGE_RECORDS;
import static org.eclipse.californium.scandium.config.DtlsConfig.DTLS_VERIFY_SERVER_CERTIFICATES_SUBJECT;
import static org.eclipse.californium.scandium.config.DtlsConfig.DtlsRole.CLIENT_ONLY;
import static org.eclipse.californium.scandium.config.DtlsConfig.MODULE;
import static org.eclipse.californium.scandium.dtls.SignatureAndHashAlgorithm.SHA256_WITH_ECDSA;
import static org.eclipse.californium.scandium.dtls.SignatureAndHashAlgorithm.SHA256_WITH_RSA;
import static org.eclipse.californium.scandium.dtls.SignatureAndHashAlgorithm.SHA384_WITH_ECDSA;
@Slf4j
public class CoapClientX509Test {
private static final long CLIENT_REQUEST_TIMEOUT = 60000L;
private final CoapClient clientX509;
private final DTLSConnector dtlsConnector;
private final Configuration config;
private final CertPrivateKey certPrivateKey;
private final String coapsBaseUrl;
@Getter
private CoAP.Type type = CoAP.Type.CON;
public CoapClientX509Test(CertPrivateKey certPrivateKey, FeatureType featureType, String coapsBaseUrl, Integer fixedPort) {
this.certPrivateKey = certPrivateKey;
this.coapsBaseUrl = coapsBaseUrl;
this.config = createConfiguration();
this.dtlsConnector = createDTLSConnector(fixedPort);
this.clientX509 = createClient(getFeatureTokenUrl(featureType));
}
public void disconnect() {
if (clientX509 != null) {
clientX509.shutdown();
}
}
public CoapResponse postMethod(String requestBody) throws ConnectorException, IOException {
return this.postMethod(requestBody.getBytes());
}
public CoapResponse postMethod(byte[] requestBodyBytes) throws ConnectorException, IOException {
return clientX509.setTimeout(CLIENT_REQUEST_TIMEOUT).post(requestBodyBytes, MediaTypeRegistry.APPLICATION_JSON);
}
public void postMethod(CoapHandler handler, String payload, int format) {
clientX509.setTimeout(CLIENT_REQUEST_TIMEOUT).post(handler, payload, format);
}
public void postMethod(CoapHandler handler, byte[] payload) {
clientX509.setTimeout(CLIENT_REQUEST_TIMEOUT).post(handler, payload, MediaTypeRegistry.APPLICATION_JSON);
}
public void postMethod(CoapHandler handler, byte[] payload, int format) {
clientX509.setTimeout(CLIENT_REQUEST_TIMEOUT).post(handler, payload, format);
}
public CoapResponse getMethod() throws ConnectorException, IOException {
return clientX509.setTimeout(CLIENT_REQUEST_TIMEOUT).get();
}
public CoapObserveRelation getObserveRelation(CoapTestCallback callback) {
return getObserveRelation(callback, true);
}
public CoapObserveRelation getObserveRelation(CoapTestCallback callback, boolean confirmable) {
Request request = Request.newGet().setObserve();
request.setType(confirmable ? CoAP.Type.CON : CoAP.Type.NON);
return clientX509.observe(request, callback);
}
public void setURI(String featureTokenUrl) {
if (clientX509 == null) {
throw new RuntimeException("Failed to connect! CoapClient is not initialized!");
}
clientX509.setURI(featureTokenUrl);
}
public void setURI(String accessToken, FeatureType featureType) {
if (featureType == null) {
featureType = FeatureType.ATTRIBUTES;
}
setURI(getFeatureTokenUrl(accessToken, featureType));
}
public void useCONs() {
if (clientX509 == null) {
throw new RuntimeException("Failed to connect! CoapClient is not initialized!");
}
type = CoAP.Type.CON;
clientX509.useCONs();
}
public void useNONs() {
if (clientX509 == null) {
throw new RuntimeException("Failed to connect! CoapClient is not initialized!");
}
type = CoAP.Type.NON;
clientX509.useNONs();
}
private Configuration createConfiguration() {
Configuration clientCoapConfig = new Configuration();
clientCoapConfig.set(CoapConfig.BLOCKWISE_STRICT_BLOCK2_OPTION, true);
clientCoapConfig.set(CoapConfig.BLOCKWISE_ENTITY_TOO_LARGE_AUTO_FAILOVER, true);
clientCoapConfig.set(CoapConfig.BLOCKWISE_STATUS_LIFETIME, DEFAULT_BLOCKWISE_STATUS_LIFETIME_IN_SECONDS, TimeUnit.SECONDS);
clientCoapConfig.set(CoapConfig.MAX_RESOURCE_BODY_SIZE, 256 * 1024 * 1024);
clientCoapConfig.set(CoapConfig.RESPONSE_MATCHING, CoapConfig.MatcherMode.RELAXED);
clientCoapConfig.set(CoapConfig.PREFERRED_BLOCK_SIZE, 1024);
clientCoapConfig.set(CoapConfig.MAX_MESSAGE_SIZE, 1024);
clientCoapConfig.set(DTLS_ROLE, CLIENT_ONLY);
clientCoapConfig.set(DTLS_MAX_RETRANSMISSIONS, 2);
clientCoapConfig.set(DTLS_RETRANSMISSION_TIMEOUT, 5000, MILLISECONDS);
clientCoapConfig.set(DTLS_MAX_RETRANSMISSION_TIMEOUT, 60000, TimeUnit.MILLISECONDS);
clientCoapConfig.set(DTLS_USE_HELLO_VERIFY_REQUEST, false);
clientCoapConfig.set(DTLS_VERIFY_SERVER_CERTIFICATES_SUBJECT, false);
clientCoapConfig.set(DTLS_MAX_FRAGMENTED_HANDSHAKE_MESSAGE_LENGTH, 22490);
clientCoapConfig.set(DTLS_AUTO_HANDSHAKE_TIMEOUT, 100000, TimeUnit.MILLISECONDS);
clientCoapConfig.set(DTLS_MAX_PENDING_HANDSHAKE_RESULT_JOBS, 64);
clientCoapConfig.set(DTLS_USE_MULTI_HANDSHAKE_MESSAGE_RECORDS, false);
clientCoapConfig.set(DTLS_RECEIVE_BUFFER_SIZE, 8192);
clientCoapConfig.setTransient(DTLS_RECOMMENDED_CIPHER_SUITES_ONLY);
SignatureAndHashAlgorithmsDefinition algorithmsDefinition = new SignatureAndHashAlgorithmsDefinition(MODULE + "SIGNATURE_AND_HASH_ALGORITHMS", "List of DTLS signature- and hash-algorithms.\nValues e.g SHA256withECDSA or ED25519.");
SignatureAndHashAlgorithm SHA384_WITH_RSA = new SignatureAndHashAlgorithm(HashAlgorithm.SHA384,
SignatureAlgorithm.RSA);
List<SignatureAndHashAlgorithm> algorithms = null;
try {
algorithms = algorithmsDefinition.checkValue(Arrays.asList(SHA256_WITH_ECDSA, SHA256_WITH_RSA, SHA384_WITH_ECDSA, SHA384_WITH_RSA));
} catch (ValueException e) {
throw new RuntimeException(e);
}
clientCoapConfig.setTransient(DTLS_SIGNATURE_AND_HASH_ALGORITHMS);
clientCoapConfig.set(DTLS_SIGNATURE_AND_HASH_ALGORITHMS, algorithms);
clientCoapConfig.setTransient(DTLS_CIPHER_SUITES);
clientCoapConfig.set(DTLS_CIPHER_SUITES, Arrays.asList(CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256));
clientCoapConfig.setTransient(DTLS_VERIFY_SERVER_CERTIFICATES_SUBJECT);
clientCoapConfig.set(DTLS_VERIFY_SERVER_CERTIFICATES_SUBJECT, false);
return clientCoapConfig;
}
private DTLSConnector createDTLSConnector(Integer fixedPort) {
try {
// Create DTLS config client
DtlsConnectorConfig.Builder configBuilder = new DtlsConnectorConfig.Builder(this.config);
configBuilder.setAdvancedCertificateVerifier(new TbAdvancedCertificateVerifier());
X509Certificate[] certificateChainClient = new X509Certificate[]{this.certPrivateKey.getCert()};
CertificateProvider certificateProvider = new SingleCertificateProvider(this.certPrivateKey.getPrivateKey(), certificateChainClient, Collections.singletonList(CertificateType.X_509));
configBuilder.setCertificateIdentityProvider(certificateProvider);
if (fixedPort != null) {
InetSocketAddress localAddress = new InetSocketAddress("0.0.0.0", fixedPort);
configBuilder.setAddress(localAddress);
configBuilder.setReuseAddress(true);
}
return new DTLSConnector(configBuilder.build());
} catch (Exception e) {
throw new RuntimeException("", e);
}
}
private CoapClient createClient(String featureTokenUrl) {
CoapClient client = new CoapClient(featureTokenUrl);
CoapEndpoint.Builder builder = new CoapEndpoint.Builder();
builder.setConnector(dtlsConnector);
client.setEndpoint(builder.build());
return client;
}
public String getFeatureTokenUrl(FeatureType featureType) {
return this.coapsBaseUrl + featureType.name().toLowerCase();
}
public String getFeatureTokenUrl(String token, FeatureType featureType) {
return this.coapsBaseUrl + token + "/" + featureType.name().toLowerCase();
}
}

129
application/src/test/java/org/thingsboard/server/transport/coap/x509/TbAdvancedCertificateVerifier.java

@ -0,0 +1,129 @@
/**
* 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.coap.x509;
import lombok.extern.slf4j.Slf4j;
import org.eclipse.californium.scandium.dtls.AlertMessage;
import org.eclipse.californium.scandium.dtls.AlertMessage.AlertDescription;
import org.eclipse.californium.scandium.dtls.AlertMessage.AlertLevel;
import org.eclipse.californium.scandium.dtls.CertificateMessage;
import org.eclipse.californium.scandium.dtls.CertificateType;
import org.eclipse.californium.scandium.dtls.CertificateVerificationResult;
import org.eclipse.californium.scandium.dtls.ConnectionId;
import org.eclipse.californium.scandium.dtls.HandshakeException;
import org.eclipse.californium.scandium.dtls.HandshakeResultHandler;
import org.eclipse.californium.scandium.dtls.x509.NewAdvancedCertificateVerifier;
import org.eclipse.californium.scandium.util.ServerNames;
import javax.security.auth.x500.X500Principal;
import java.net.InetSocketAddress;
import java.security.PublicKey;
import java.security.cert.CertPath;
import java.util.Arrays;
import java.util.List;
@Slf4j
public class TbAdvancedCertificateVerifier implements NewAdvancedCertificateVerifier {
private HandshakeResultHandler resultHandler;
/**
* Get the list of supported certificate types in order of preference.
*
* @return the list of supported certificate types.
* @since 3.0 (renamed from getSupportedCertificateType)
*/
@Override
public List<CertificateType> getSupportedCertificateTypes() {
return Arrays.asList(CertificateType.X_509, CertificateType.RAW_PUBLIC_KEY);
}
/**
* Validates the certificate provided by the the peer as part of the
* certificate message.
* <p>
* If a x509 certificate chain is provided in the certificate message,
* validate the chain and key usage. If a RawPublicKey certificate is
* provided, check, if this public key is trusted.
*
* @param cid connection ID
* @param serverName indicated server names. May be {@code null}, if not
* available or SNI is not enabled.
* @param remotePeer socket address of remote peer
* @param clientUsage indicator to check certificate usage. {@code true},
* check key usage for client, {@code false} for server.
* @param verifySubject {@code true} to verify the certificate's subjects,
* {@code false}, if not.
* @param truncateCertificatePath {@code true} truncate certificate path at
* a trusted certificate before validation.
* @param message certificate message to be validated
* @return certificate verification result, or {@code null}, if result is
* provided asynchronous.
* @since 3.0 (removed DTLSSession session, added remotePeer and
* verifySubject)
*/
@Override
public CertificateVerificationResult verifyCertificate(ConnectionId cid, ServerNames serverName, InetSocketAddress remotePeer,
boolean clientUsage, boolean verifySubject, boolean truncateCertificatePath,
CertificateMessage message) {
CertPath certChain = message.getCertificateChain();
CertificateVerificationResult result;
if (certChain == null) {
PublicKey publicKey = message.getPublicKey();
result = new CertificateVerificationResult(cid, publicKey, null);
} else {
if (message.getCertificateChain().getCertificates().isEmpty()) {
result = new CertificateVerificationResult(cid, new HandshakeException("Empty certificate chain",
new AlertMessage(AlertLevel.FATAL, AlertDescription.BAD_CERTIFICATE)), null);
} else {
result = new CertificateVerificationResult(cid, certChain, null);
}
}
return result;
}
/**
* Return an list of certificate authorities which are trusted
* for authenticating peers.
*
* @return a non-null (possibly empty) list of accepted CA issuers.
*/
@Override
public List<X500Principal> getAcceptedIssuers() {
log.trace("getAcceptedIssuers: return null");
return null;
}
/**
* Set the handler for asynchronous handshake results.
* <p>
* Called during initialization of the {link DTLSConnector}. Synchronous
* implementations may just ignore this using an empty implementation.
*
* @param resultHandler handler for asynchronous master secret results. This
* handler MUST NOT be called from the thread calling
* {@link #verifyCertificate(ConnectionId, ServerNames, InetSocketAddress, boolean, boolean, boolean, CertificateMessage)},
* instead just return the result there.
*/
@Override
public void setResultHandler(HandshakeResultHandler resultHandler) {
if (this.resultHandler != null && resultHandler != null && this.resultHandler != resultHandler) {
throw new IllegalStateException("handshake result handler already set!");
}
this.resultHandler = resultHandler;
}
}

38
application/src/test/java/org/thingsboard/server/transport/lwm2m/AbstractLwM2MIntegrationTest.java

@ -147,8 +147,7 @@ public abstract class AbstractLwM2MIntegrationTest extends AbstractTransportInte
" \"telemetry\": [],\n" +
" \"attributeLwm2m\": {}\n" +
" }";
public static String OBSERVE_ATTRIBUTES_WITH_PARAMS =
public static String TELEMETRY_WITHOUT_OBSERVE =
" {\n" +
" \"keyName\": {\n" +
" \"/3_1.2/0/9\": \"batteryLevel\"\n" +
@ -161,6 +160,39 @@ public abstract class AbstractLwM2MIntegrationTest extends AbstractTransportInte
" ],\n" +
" \"attributeLwm2m\": {}\n" +
" }";
public static String TELEMETRY_WITH_ONE_OBSERVE =
" {\n" +
" \"keyName\": {\n" +
" \"/3_1.2/0/9\": \"batteryLevel\"\n" +
" },\n" +
" \"observe\": [\n" +
" \"/3_1.2/0/9\"\n" +
" ],\n" +
" \"attribute\": [\n" +
" ],\n" +
" \"telemetry\": [\n" +
" \"/3_1.2/0/9\"\n" +
" ],\n" +
" \"attributeLwm2m\": {}\n" +
" }";
public static String TELEMETRY_WITH_MANY_OBSERVE =
" {\n" +
" \"keyName\": {\n" +
" \"/3_1.2/0/9\": \"batteryLevel\",\n" +
" \"/3_1.2/0/20\": \"batteryStatus\"\n" +
" },\n" +
" \"observe\": [\n" +
" \"/3_1.2/0/9\",\n" +
" \"/3_1.2/0/20\"\n" +
" ],\n" +
" \"attribute\": [],\n" +
" \"telemetry\": [\n" +
" \"/3_1.2/0/9\",\n" +
" \"/3_1.2/0/20\"\n" +
" ],\n" +
" \"attributeLwm2m\": {}\n" +
" }";
public static final String CLIENT_LWM2M_SETTINGS =
" {\n" +
@ -217,7 +249,7 @@ public abstract class AbstractLwM2MIntegrationTest extends AbstractTransportInte
LwM2MDeviceCredentials deviceCredentials,
String endpoint,
boolean queueMode) throws Exception {
Lwm2mDeviceProfileTransportConfiguration transportConfiguration = getTransportConfiguration(OBSERVE_ATTRIBUTES_WITH_PARAMS, getBootstrapServerCredentialsNoSec(NONE));
Lwm2mDeviceProfileTransportConfiguration transportConfiguration = getTransportConfiguration(TELEMETRY_WITHOUT_OBSERVE, getBootstrapServerCredentialsNoSec(NONE));
DeviceProfile deviceProfile = createLwm2mDeviceProfile("profileFor" + endpoint, transportConfiguration);
Device device = createLwm2mDevice(deviceCredentials, endpoint, deviceProfile.getId());

6
application/src/test/java/org/thingsboard/server/transport/lwm2m/client/LwM2MTestClient.java

@ -458,6 +458,12 @@ public class LwM2MTestClient {
}
}
public void stop(boolean deregister) {
if (leshanClient != null) {
leshanClient.stop(deregister);
}
}
private void awaitClientAfterStartConnectLw() {
LwM2mClient lwM2MClient = this.clientContext.getClientByEndpoint(endpoint);
Mockito.doAnswer(invocationOnMock -> null).when(defaultLwM2mUplinkMsgHandlerTest).initAttributes(lwM2MClient, true);

1
application/src/test/java/org/thingsboard/server/transport/lwm2m/client/SimpleLwM2MDevice.java

@ -93,6 +93,7 @@ public class SimpleLwM2MDevice extends BaseInstanceEnabler implements Destroyabl
try {
executorService.scheduleWithFixedDelay(() -> {
fireResourceChange(9);
fireResourceChange(20);
}
, 1, 1, TimeUnit.SECONDS); // 2 sec
// , 1800000, 1800000, TimeUnit.MILLISECONDS); // 30 MIN

2
application/src/test/java/org/thingsboard/server/transport/lwm2m/ota/sql/Ota5LwM2MIntegrationTest.java

@ -51,7 +51,7 @@ public class Ota5LwM2MIntegrationTest extends AbstractOtaLwM2MIntegrationTest {
@Test
public void testFirmwareUpdateWithClientWithoutFirmwareOtaInfoFromProfile_IsNotSupported() throws Exception {
Lwm2mDeviceProfileTransportConfiguration transportConfiguration = getTransportConfiguration(OBSERVE_ATTRIBUTES_WITH_PARAMS, getBootstrapServerCredentialsNoSec(NONE));
Lwm2mDeviceProfileTransportConfiguration transportConfiguration = getTransportConfiguration(TELEMETRY_WITHOUT_OBSERVE, getBootstrapServerCredentialsNoSec(NONE));
DeviceProfile deviceProfile = createLwm2mDeviceProfile("profileFor" + this.CLIENT_ENDPOINT_WITHOUT_FW_INFO, transportConfiguration);
LwM2MDeviceCredentials deviceCredentials = getDeviceCredentialsNoSec(createNoSecClientCredentials(this.CLIENT_ENDPOINT_WITHOUT_FW_INFO));
final Device device = createLwm2mDevice(deviceCredentials, this.CLIENT_ENDPOINT_WITHOUT_FW_INFO, deviceProfile.getId());

3
application/src/test/java/org/thingsboard/server/transport/lwm2m/security/AbstractSecurityLwM2MIntegrationTest.java

@ -196,7 +196,7 @@ public abstract class AbstractSecurityLwM2MIntegrationTest extends AbstractLwM2M
false);
}
protected void basicTestConnection(Security security, Security securityBs,
protected Device basicTestConnection(Security security, Security securityBs,
LwM2MDeviceCredentials deviceCredentials,
String endpoint,
Lwm2mDeviceProfileTransportConfiguration transportConfiguration,
@ -227,6 +227,7 @@ public abstract class AbstractSecurityLwM2MIntegrationTest extends AbstractLwM2M
return lwM2MTestClient.getClientStates().contains(finishState) || lwM2MTestClient.getClientStates().contains(ON_UPDATE_SUCCESS);
});
Assert.assertTrue(lwM2MTestClient.getClientStates().containsAll(expectedStatuses));
return device;
}

81
application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/PskLwm2mIntegrationTest.java

@ -16,10 +16,13 @@
package org.thingsboard.server.transport.lwm2m.security.sql;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.eclipse.leshan.client.object.Security;
import org.eclipse.leshan.core.util.Hex;
import org.junit.Assert;
import org.junit.Test;
import org.springframework.test.web.servlet.MvcResult;
import org.thingsboard.server.common.data.Device;
import org.thingsboard.server.common.data.DeviceProfile;
import org.thingsboard.server.common.data.device.credentials.lwm2m.LwM2MDeviceCredentials;
import org.thingsboard.server.common.data.device.credentials.lwm2m.PSKClientCredential;
@ -27,7 +30,6 @@ import org.thingsboard.server.common.data.device.profile.Lwm2mDeviceProfileTrans
import org.thingsboard.server.transport.lwm2m.security.AbstractSecurityLwM2MIntegrationTest;
import java.nio.charset.StandardCharsets;
import static org.eclipse.leshan.client.object.Security.psk;
import static org.eclipse.leshan.client.object.Security.pskBootstrap;
import static org.junit.Assert.assertEquals;
@ -37,6 +39,7 @@ import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MClient
import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MProfileBootstrapConfigType.BOTH;
import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MProfileBootstrapConfigType.NONE;
@Slf4j
public class PskLwm2mIntegrationTest extends AbstractSecurityLwM2MIntegrationTest {
//Lwm2m only
@ -66,6 +69,82 @@ public class PskLwm2mIntegrationTest extends AbstractSecurityLwM2MIntegrationTes
ON_REGISTRATION_SUCCESS,
true);
}
@Test
public void testWithPskConnectLwm2mOneObserveSuccessUpdateProfileManyObserveUpdateRegistrationSuccess() throws Exception {
String clientEndpoint = CLIENT_ENDPOINT_PSK;
String identity = CLIENT_PSK_IDENTITY;
String keyPsk = CLIENT_PSK_KEY;
PSKClientCredential clientCredentials = new PSKClientCredential();
clientCredentials.setEndpoint(clientEndpoint);
clientCredentials.setIdentity(identity);
clientCredentials.setKey(keyPsk);
Security security = psk(SECURE_URI,
shortServerId,
identity.getBytes(StandardCharsets.UTF_8),
Hex.decodeHex(keyPsk.toCharArray()));
Lwm2mDeviceProfileTransportConfiguration transportConfiguration = getTransportConfiguration(TELEMETRY_WITH_ONE_OBSERVE, getBootstrapServerCredentialsSecure(PSK, NONE));
LwM2MDeviceCredentials deviceCredentials = getDeviceCredentialsSecure(clientCredentials, null, null, PSK, false);
String awaitAlias = "await on client state (Psk_Lwm2m)";
Device lwm2mDevice = this.basicTestConnection(security,
null,
deviceCredentials,
clientEndpoint,
transportConfiguration,
awaitAlias,
expectedStatusesRegistrationLwm2mSuccess,
false,
ON_REGISTRATION_SUCCESS,
true);
awaitObserveReadAll(1, lwm2mDevice.getId().getId().toString());
DeviceProfile foundDeviceProfile = doGet("/api/deviceProfile/" + lwm2mDevice.getDeviceProfileId().getId().toString(), DeviceProfile.class);
transportConfiguration = getTransportConfiguration(TELEMETRY_WITH_MANY_OBSERVE, getBootstrapServerCredentialsSecure(PSK, NONE));
foundDeviceProfile.getProfileData().setTransportConfiguration(transportConfiguration);
DeviceProfile lwm2mDeviceProfileManyParams = doPost("/api/deviceProfile", foundDeviceProfile, DeviceProfile.class);
Assert.assertNotNull(lwm2mDeviceProfileManyParams);
awaitObserveReadAll(2, lwm2mDevice.getId().getId().toString());
awaitUpdateReg(3);
}
@Test
public void testWithPskConnectLwm2mSuccessObserveSuccessUnRegClientUpdateProfileObserveConnectLwm2mSuccessOWithNewObserve() throws Exception {
String clientEndpoint = CLIENT_ENDPOINT_PSK;
String identity = CLIENT_PSK_IDENTITY;
String keyPsk = CLIENT_PSK_KEY;
PSKClientCredential clientCredentials = new PSKClientCredential();
clientCredentials.setEndpoint(clientEndpoint);
clientCredentials.setIdentity(identity);
clientCredentials.setKey(keyPsk);
Security security = psk(SECURE_URI,
shortServerId,
identity.getBytes(StandardCharsets.UTF_8),
Hex.decodeHex(keyPsk.toCharArray()));
Lwm2mDeviceProfileTransportConfiguration transportConfiguration = getTransportConfiguration(TELEMETRY_WITH_ONE_OBSERVE, getBootstrapServerCredentialsSecure(PSK, NONE));
LwM2MDeviceCredentials deviceCredentials = getDeviceCredentialsSecure(clientCredentials, null, null, PSK, false);
String awaitAlias = "await on client state (Psk_Lwm2m)";
Device lwm2mDevice = this.basicTestConnection(security,
null,
deviceCredentials,
clientEndpoint,
transportConfiguration,
awaitAlias,
expectedStatusesRegistrationLwm2mSuccess,
false,
ON_REGISTRATION_SUCCESS,
true);
awaitObserveReadAll(1, lwm2mDevice.getId().getId().toString());
lwM2MTestClient.stop(true);
DeviceProfile foundDeviceProfile = doGet("/api/deviceProfile/" + lwm2mDevice.getDeviceProfileId().getId().toString(), DeviceProfile.class);
transportConfiguration = getTransportConfiguration(TELEMETRY_WITH_MANY_OBSERVE, getBootstrapServerCredentialsSecure(PSK, NONE));
foundDeviceProfile.getProfileData().setTransportConfiguration(transportConfiguration);
DeviceProfile lwm2mDeviceProfileManyParams = doPost("/api/deviceProfile", foundDeviceProfile, DeviceProfile.class);
Assert.assertNotNull(lwm2mDeviceProfileManyParams);
lwM2MTestClient.start(true);
awaitObserveReadAll(2, lwm2mDevice.getId().getId().toString());
awaitUpdateReg(3);
}
@Test
public void testWithPskConnectLwm2mBadPskKeyByLength_BAD_REQUEST() throws Exception {

13
application/src/test/resources/coap/credentials/client/cert.pem

@ -0,0 +1,13 @@
-----BEGIN CERTIFICATE-----
MIIB/TCCAaOgAwIBAgIIVNrVgKT9OE8wCgYIKoZIzj0EAwIwWjEOMAwGA1UEAxMF
Y2YtY2ExFDASBgNVBAsTC0NhbGlmb3JuaXVtMRQwEgYDVQQKEwtFY2xpcHNlIElv
VDEPMA0GA1UEBxMGT3R0YXdhMQswCQYDVQQGEwJDQTAeFw0yMzEwMjYwODA4MjJa
Fw0yNTEwMjUwODA4MjJaMF4xEjAQBgNVBAMTCWNmLWNsaWVudDEUMBIGA1UECxML
Q2FsaWZvcm5pdW0xFDASBgNVBAoTC0VjbGlwc2UgSW9UMQ8wDQYDVQQHEwZPdHRh
d2ExCzAJBgNVBAYTAkNBMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEQxYO5/M5
ie6+3QPOaAy5MD6CkFILZwIb2rOBCX/EWPaocX1H+eynUnaEEbmqxeN6rnI/pH19
j4PtsegfHLrzzaNPME0wHQYDVR0OBBYEFKwEDLTJ+5cQoZfbjWN1vJ2ssgK+MAsG
A1UdDwQEAwIHgDAfBgNVHSMEGDAWgBSxVzoI1TL87++hsUb9vQwqODzgUTAKBggq
hkjOPQQDAgNIADBFAiA2KCOw3n2AK9Vm8u2u1bQREIEs3tKAU7eFjpNFn929NwIh
AInhBGoEwS2Xlu5bdZSfWnujoRrEQiIiQpStmLxVcIsH
-----END CERTIFICATE-----

14
application/src/test/resources/coap/credentials/client/cert_01.pem

@ -0,0 +1,14 @@
-----BEGIN CERTIFICATE-----
MIICIzCCAcmgAwIBAgIUZZCGYm65c9vU0Xfvd/pAnLVDouUwCgYIKoZIzj0EAwIw
ZzELMAkGA1UEBhMCVUExDTALBgNVBAgMBEtpeXYxDTALBgNVBAcMBEtpeXYxFDAS
BgNVBAoMC1RoaW5nc2JvYXJkMRIwEAYDVQQLDAlkZXZlbG9wZXIxEDAOBgNVBAMM
B2NlcnRfMDEwHhcNMjQxMjE4MTU1NjE1WhcNMjUxMjE4MTU1NjE1WjBnMQswCQYD
VQQGEwJVQTENMAsGA1UECAwES2l5djENMAsGA1UEBwwES2l5djEUMBIGA1UECgwL
VGhpbmdzYm9hcmQxEjAQBgNVBAsMCWRldmVsb3BlcjEQMA4GA1UEAwwHY2VydF8w
MTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABNU1tE6o/QpqJJqpy+m+UoPuQe5g
eTgS4M3x0iQS6pzNEJBhzbnOp/BysGMB4wKiAWTRuKdH/gcRXDBTjLd/d7ijUzBR
MB0GA1UdDgQWBBSiao1iNWYzlsrSbxYqbda116HG1jAfBgNVHSMEGDAWgBSiao1i
NWYzlsrSbxYqbda116HG1jAPBgNVHRMBAf8EBTADAQH/MAoGCCqGSM49BAMCA0gA
MEUCIB2aCM/nvDqic9NkoSX/71GwksLiAKiFNkt2BZQykrcHAiEAr2h5IMdkyurN
Jy/idx2y44CP0tMq/3QV0QLCQFJIi6s=
-----END CERTIFICATE-----

4
application/src/test/resources/coap/credentials/client/key.pem

@ -0,0 +1,4 @@
-----BEGIN PRIVATE KEY-----
MEECAQAwEwYHKoZIzj0CAQYIKoZIzj0DAQcEJzAlAgEBBCDn0+4CuLeX7xwBs0ts
UUEDB3+HRwRKdIPeJlIbKuvvEQ==
-----END PRIVATE KEY-----

8
application/src/test/resources/coap/credentials/client/key_01.pem

@ -0,0 +1,8 @@
-----BEGIN EC PARAMETERS-----
BggqhkjOPQMBBw==
-----END EC PARAMETERS-----
-----BEGIN EC PRIVATE KEY-----
MHcCAQEEIJldU1MBuJUJnNHa9Ob5NGlXc/Os6put9eh1TlIbuScnoAoGCCqGSM49
AwEHoUQDQgAE1TW0Tqj9CmokmqnL6b5Sg+5B7mB5OBLgzfHSJBLqnM0QkGHNuc6n
8HKwYwHjAqIBZNG4p0f+BxFcMFOMt393uA==
-----END EC PRIVATE KEY-----

BIN
application/src/test/resources/coap/credentials/coapclientTest.jks

Binary file not shown.

BIN
application/src/test/resources/coap/credentials/coapserverTest.jks

Binary file not shown.

35
application/src/test/resources/coap/credentials/server/cert.pem

@ -0,0 +1,35 @@
-----BEGIN CERTIFICATE-----
MIIBaDCCAQ2gAwIBAgIUCY+goBAOhowBs7BHs/qXdAX8XFgwCgYIKoZIzj0EAwIw
ETEPMA0GA1UEAwwGUm9vdENBMB4XDTI0MTIxOTEzNTY1OFoXDTM0MTIxNzEzNTY1
OFowETEPMA0GA1UEAwwGU2VydmVyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE
/qief3Kjnz0FpkQVaKRqJq3kHmCqqs+y1EGYLEZZAqLFvxmv7xoL6muG4Mj8tzqk
Ll94JJuz97hG1FiEZsq7O6NDMEEwCwYDVR0PBAQDAgWgMBMGA1UdJQQMMAoGCCsG
AQUFBwMBMB0GA1UdDgQWBBTK/UPsN0I2ErVPILWKMRV6TSeAmTAKBggqhkjOPQQD
AgNJADBGAiEA8EhlOwvTbwGlxo55UIOJp9LBbCp0BEIWojlu8PzOVSsCIQDlV24S
3BUJVCuMRujO5lTfJLxaSKkOEIgRANwIGi88WA==
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIBGzCBwgIUP/PGQOKa5EyvsIXNgvv9PNietyEwCgYIKoZIzj0EAwMwEDEOMAwG
A1UEAwwFVFJVU1QwHhcNMjQxMjE5MTM1NjU4WhcNMzQxMjE3MTM1NjU4WjARMQ8w
DQYDVQQDDAZSb290Q0EwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAT+qJ5/cqOf
PQWmRBVopGomreQeYKqqz7LUQZgsRlkCosW/Ga/vGgvqa4bgyPy3OqQuX3gkm7P3
uEbUWIRmyrs7MAoGCCqGSM49BAMDA0gAMEUCIQD2DY3UDXbzaIBKrsCtohKlEunH
ip9LkSeYfSKCnfm23gIgA8AEJdunpRmPkilxgy6wZSLLROqDpGDnhnyv8dsR8cc=
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIBLTCB1AIUcsuauXAqvIS2RQcNPYysETJUAvwwCgYIKoZIzj0EAwMwIzEhMB8G
A1UEAwwYQUFBIENlcnRpZmljYXRlIFNlcnZpY2VzMB4XDTI0MTIxOTEzNTY1OFoX
DTM0MTIxNzEzNTY1OFowEDEOMAwGA1UEAwwFVFJVU1QwWTATBgcqhkjOPQIBBggq
hkjOPQMBBwNCAAT+qJ5/cqOfPQWmRBVopGomreQeYKqqz7LUQZgsRlkCosW/Ga/v
Ggvqa4bgyPy3OqQuX3gkm7P3uEbUWIRmyrs7MAoGCCqGSM49BAMDA0gAMEUCIQCM
DV8sfoArfWiXAUF2LNS3kkHD7sgb91jr2+poEHgBBgIgXf9VeJp3K5jHX6lJwtE8
nd+jW7T9nhTc/5njHg7xons=
-----END CERTIFICATE-----
-----BEGIN EC PARAMETERS-----
BggqhkjOPQMBBw==
-----END EC PARAMETERS-----
-----BEGIN EC PRIVATE KEY-----
MHcCAQEEIB+Z69so6HqCCWo5VOFxGsLXOlTWIYijOtzt+SeNGrgPoAoGCCqGSM49
AwEHoUQDQgAE/qief3Kjnz0FpkQVaKRqJq3kHmCqqs+y1EGYLEZZAqLFvxmv7xoL
6muG4Mj8tzqkLl94JJuz97hG1FiEZsq7Ow==
-----END EC PRIVATE KEY-----

3
common/coap-server/src/main/java/org/thingsboard/server/coapserver/CoapServerService.java

@ -17,7 +17,6 @@ package org.thingsboard.server.coapserver;
import org.eclipse.californium.core.CoapServer;
import java.net.InetSocketAddress;
import java.net.UnknownHostException;
import java.util.concurrent.ConcurrentMap;
@ -25,5 +24,5 @@ public interface CoapServerService {
CoapServer getCoapServer() throws UnknownHostException;
ConcurrentMap<InetSocketAddress, TbCoapDtlsSessionInfo> getDtlsSessionsMap();
ConcurrentMap<TbCoapDtlsSessionKey, TbCoapDtlsSessionInfo> getDtlsSessionsMap();
}

2
common/coap-server/src/main/java/org/thingsboard/server/coapserver/DefaultCoapServerService.java

@ -78,7 +78,7 @@ public class DefaultCoapServerService implements CoapServerService {
}
@Override
public ConcurrentMap<InetSocketAddress, TbCoapDtlsSessionInfo> getDtlsSessionsMap() {
public ConcurrentMap<TbCoapDtlsSessionKey, TbCoapDtlsSessionInfo> getDtlsSessionsMap() {
return tbDtlsCertificateVerifier != null ? tbDtlsCertificateVerifier.getTbCoapDtlsSessionsMap() : null;
}

5
common/coap-server/src/main/java/org/thingsboard/server/coapserver/TbCoapDtlsCertificateVerifier.java

@ -109,7 +109,8 @@ public class TbCoapDtlsCertificateVerifier implements NewAdvancedCertificateVeri
if (msg != null && strCert.equals(msg.getCredentials())) {
DeviceProfile deviceProfile = msg.getDeviceProfile();
if (msg.hasDeviceInfo() && deviceProfile != null) {
tbCoapDtlsSessionInMemoryStorage.put(remotePeer, new TbCoapDtlsSessionInfo(msg, deviceProfile));
TbCoapDtlsSessionKey tbCoapDtlsSessionKey = new TbCoapDtlsSessionKey(remotePeer, msg.getCredentials());
tbCoapDtlsSessionInMemoryStorage.put(tbCoapDtlsSessionKey, new TbCoapDtlsSessionInfo(msg, deviceProfile));
}
break;
}
@ -138,7 +139,7 @@ public class TbCoapDtlsCertificateVerifier implements NewAdvancedCertificateVeri
public void setResultHandler(HandshakeResultHandler resultHandler) {
}
public ConcurrentMap<InetSocketAddress, TbCoapDtlsSessionInfo> getTbCoapDtlsSessionsMap() {
public ConcurrentMap<TbCoapDtlsSessionKey, TbCoapDtlsSessionInfo> getTbCoapDtlsSessionsMap() {
return tbCoapDtlsSessionInMemoryStorage.getDtlsSessionsMap();
}

9
common/coap-server/src/main/java/org/thingsboard/server/coapserver/TbCoapDtlsSessionInMemoryStorage.java

@ -18,7 +18,6 @@ package org.thingsboard.server.coapserver;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import java.net.InetSocketAddress;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
@ -26,7 +25,7 @@ import java.util.concurrent.ConcurrentMap;
@Data
public class TbCoapDtlsSessionInMemoryStorage {
private final ConcurrentMap<InetSocketAddress, TbCoapDtlsSessionInfo> dtlsSessionsMap = new ConcurrentHashMap<>();
private final ConcurrentMap<TbCoapDtlsSessionKey, TbCoapDtlsSessionInfo> dtlsSessionsMap = new ConcurrentHashMap<>();
private long dtlsSessionInactivityTimeout;
private long dtlsSessionReportTimeout;
@ -36,9 +35,9 @@ public class TbCoapDtlsSessionInMemoryStorage {
this.dtlsSessionReportTimeout = dtlsSessionReportTimeout;
}
public void put(InetSocketAddress remotePeer, TbCoapDtlsSessionInfo dtlsSessionInfo) {
log.trace("DTLS session added to in-memory store: [{}] timestamp: [{}]", remotePeer, dtlsSessionInfo.getLastActivityTime());
dtlsSessionsMap.putIfAbsent(remotePeer, dtlsSessionInfo);
public void put(TbCoapDtlsSessionKey tbCoapDtlsSessionKey, TbCoapDtlsSessionInfo dtlsSessionInfo) {
log.trace("DTLS session added to in-memory store: [{}] timestamp: [{}]", tbCoapDtlsSessionKey, dtlsSessionInfo.getLastActivityTime());
dtlsSessionsMap.putIfAbsent(tbCoapDtlsSessionKey, dtlsSessionInfo);
}
public void evictTimeoutSessions() {

32
common/coap-server/src/main/java/org/thingsboard/server/coapserver/TbCoapDtlsSessionKey.java

@ -0,0 +1,32 @@
/**
* 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.coapserver;
import java.net.InetSocketAddress;
import java.util.Objects;
public record TbCoapDtlsSessionKey(InetSocketAddress peerAddress, String credentials) {
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
TbCoapDtlsSessionKey that = (TbCoapDtlsSessionKey) o;
return Objects.equals(peerAddress, that.peerAddress) &&
Objects.equals(credentials, that.credentials);
}
}

4
common/data/src/main/java/org/thingsboard/server/common/data/mobile/app/StoreInfo.java

@ -15,12 +15,16 @@
*/
package org.thingsboard.server.common.data.mobile.app;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.thingsboard.server.common.data.validation.NoXss;
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class StoreInfo {
@NoXss

2
common/edge-api/src/main/java/org/thingsboard/edge/rpc/EdgeGrpcClient.java

@ -136,7 +136,7 @@ public class EdgeGrpcClient implements EdgeRpcClient {
.setConnectRequestMsg(ConnectRequestMsg.newBuilder()
.setEdgeRoutingKey(edgeKey)
.setEdgeSecret(edgeSecret)
.setEdgeVersion(EdgeVersion.V_3_9_0)
.setEdgeVersion(EdgeVersion.V_4_0_0)
.setMaxInboundMessageSize(maxInboundMessageSize)
.build())
.build());

1
common/edge-api/src/main/proto/edge.proto

@ -41,6 +41,7 @@ enum EdgeVersion {
V_3_7_0 = 7;
V_3_8_0 = 8;
V_3_9_0 = 9;
V_4_0_0 = 10;
}
/**

96
common/script/script-api/src/main/java/org/thingsboard/script/api/tbel/TbUtils.java

@ -257,6 +257,8 @@ public class TbUtils {
float.class, int.class)));
parserConfig.addImport("hexToBytes", new MethodStub(TbUtils.class.getMethod("hexToBytes",
ExecutionContext.class, String.class)));
parserConfig.addImport("hexToBytesArray", new MethodStub(TbUtils.class.getMethod("hexToBytesArray",
String.class)));
parserConfig.addImport("intToHex", new MethodStub(TbUtils.class.getMethod("intToHex",
Integer.class)));
parserConfig.addImport("intToHex", new MethodStub(TbUtils.class.getMethod("intToHex",
@ -297,6 +299,8 @@ public class TbUtils {
String.class)));
parserConfig.addImport("base64ToBytes", new MethodStub(TbUtils.class.getMethod("base64ToBytes",
String.class)));
parserConfig.addImport("base64ToBytesList", new MethodStub(TbUtils.class.getMethod("base64ToBytesList",
ExecutionContext.class, String.class)));
parserConfig.addImport("bytesToBase64", new MethodStub(TbUtils.class.getMethod("bytesToBase64",
byte[].class)));
parserConfig.addImport("bytesToHex", new MethodStub(TbUtils.class.getMethod("bytesToHex",
@ -335,7 +339,7 @@ public class TbUtils {
byte.class)));
parserConfig.addImport("parseByteToBinaryArray", new MethodStub(TbUtils.class.getMethod("parseByteToBinaryArray",
byte.class, int.class)));
parserConfig.addImport("parseByteToBinaryArray", new MethodStub(TbUtils.class.getMethod("parseByteToBinaryArray",
parserConfig.addImport("parseByteToBinaryArray", new MethodStub(TbUtils.class.getMethod("parseByteToBinaryArray",
byte.class, int.class, boolean.class)));
parserConfig.addImport("parseBytesToBinaryArray", new MethodStub(TbUtils.class.getMethod("parseBytesToBinaryArray",
List.class)));
@ -664,23 +668,16 @@ public class TbUtils {
}
public static ExecutionArrayList<Byte> hexToBytes(ExecutionContext ctx, String value) {
String hex = prepareNumberString(value, true);
if (hex == null) {
throw new IllegalArgumentException("Hex string must be not empty!");
}
int len = hex.length();
if (len % 2 > 0) {
throw new IllegalArgumentException("Hex string must be even-length.");
}
int radix = isHexadecimal(value);
if (radix != HEX_RADIX) {
throw new NumberFormatException("Value: \"" + value + "\" is not numeric or hexDecimal format!");
}
byte [] data = hexToBytes(hex);
String hex = validateAndPrepareHex(value);
byte[] data = hexToBytes(hex);
return bytesToExecutionArrayList(ctx, data);
}
public static byte[] hexToBytesArray(String value) {
String hex = validateAndPrepareHex(value);
return hexToBytes(hex);
}
public static List<Integer> printUnsignedBytes(ExecutionContext ctx, List<Byte> byteArray) {
ExecutionArrayList<Integer> data = new ExecutionArrayList<>(ctx);
for (Byte b : byteArray) {
@ -839,6 +836,11 @@ public class TbUtils {
return Base64.getDecoder().decode(input);
}
public static ExecutionArrayList<Byte> base64ToBytesList(ExecutionContext ctx, String input) {
byte[] bytes = Base64.getDecoder().decode(input);
return bytesToExecutionArrayList(ctx, bytes);
}
public static int parseBytesToInt(List<Byte> data) {
return parseBytesToInt(data, 0);
}
@ -879,6 +881,48 @@ public class TbUtils {
return bb.getInt();
}
public static long parseBytesToUnsignedInt(byte[] data) {
return parseBytesToUnsignedInt(data, 0);
}
public static long parseBytesToUnsignedInt(byte[] data, int offset) {
return parseBytesToUnsignedInt(data, offset, validateLength(data.length, offset, BYTES_LEN_INT_MAX));
}
public static long parseBytesToUnsignedInt(byte[] data, int offset, int length) {
return parseBytesToUnsignedInt(data, offset, length, true);
}
public static long parseBytesToUnsignedInt(byte[] data, int offset, int length, boolean bigEndian) {
validationNumberByLength(data, offset, length, BYTES_LEN_INT_MAX);
ByteBuffer bb = ByteBuffer.allocate(8);
if (!bigEndian) {
bb.order(ByteOrder.LITTLE_ENDIAN);
}
bb.position(bigEndian ? 8 - length : 0);
bb.put(data, offset, length);
bb.position(0);
return bb.getLong();
}
public static long parseBytesToUnsignedInt(List<Byte> data) {
return parseBytesToUnsignedInt(data, 0);
}
public static long parseBytesToUnsignedInt(List<Byte> data, int offset) {
return parseBytesToUnsignedInt(data, offset, validateLength(data.size(), offset, BYTES_LEN_INT_MAX));
}
public static long parseBytesToUnsignedInt(List<Byte> data, int offset, int length) {
return parseBytesToUnsignedInt(data, offset, length, true);
}
public static long parseBytesToUnsignedInt(List<Byte> data, int offset, int length, boolean bigEndian) {
return parseBytesToUnsignedInt(Bytes.toArray(data), offset, length, bigEndian);
}
public static long parseBytesToLong(List<Byte> data) {
return parseBytesToLong(data, 0);
}
@ -1304,7 +1348,7 @@ public class TbUtils {
public static byte[] parseByteToBinaryArray(byte byteValue, int binLength, boolean bigEndian) {
byte[] bins = new byte[binLength];
for (int i = 0; i < binLength; i++) {
if(bigEndian) {
if (bigEndian) {
bins[binLength - 1 - i] = (byte) ((byteValue >> i) & 1);
} else {
bins[i] = (byte) ((byteValue >> i) & 1);
@ -1435,16 +1479,32 @@ public class TbUtils {
}
private static byte[] hexToBytes(String hex) {
byte [] data = new byte[hex.length()/2];
byte[] data = new byte[hex.length() / 2];
for (int i = 0; i < hex.length(); i += 2) {
// Extract two characters from the hex string
String byteString = hex.substring(i, i + 2);
// Parse the hex string to a byte
byte byteValue = (byte) Integer.parseInt(byteString, HEX_RADIX);
// Add the byte to the ArrayList
data[i/2] = byteValue;
data[i / 2] = byteValue;
}
return data;
}
private static String validateAndPrepareHex(String value) {
String hex = prepareNumberString(value, true);
if (hex == null) {
throw new IllegalArgumentException("Hex string must be not empty!");
}
int len = hex.length();
if (len % 2 > 0) {
throw new IllegalArgumentException("Hex string must be even-length.");
}
int radix = isHexadecimal(value);
if (radix != HEX_RADIX) {
throw new NumberFormatException("Value: \"" + value + "\" is not numeric or hexDecimal format!");
}
return hex;
}
}

36
common/script/script-api/src/test/java/org/thingsboard/script/api/tbel/TbUtilsTest.java

@ -19,7 +19,6 @@ import com.google.common.collect.Lists;
import com.google.common.primitives.Bytes;
import com.google.common.primitives.Ints;
import lombok.extern.slf4j.Slf4j;
import org.checkerframework.checker.units.qual.A;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
@ -36,6 +35,7 @@ import java.math.BigInteger;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Base64;
import java.util.Calendar;
import java.util.Collections;
import java.util.List;
@ -787,8 +787,12 @@ public class TbUtilsTest {
public void hexToBytes_Test() {
String input = "0x01752B0367FA000500010488FFFFFFFFFFFFFFFF33";
byte[] expected = {1, 117, 43, 3, 103, -6, 0, 5, 0, 1, 4, -120, -1, -1, -1, -1, -1, -1, -1, -1, 51};
List<Byte> actual = TbUtils.hexToBytes(ctx, input);
Assertions.assertEquals(toList(expected), actual);
List<Byte> actualList = TbUtils.hexToBytes(ctx, input);
Assertions.assertEquals(toList(expected), actualList);
String validInput = "AABBCCDDEE";
expected = new byte[]{(byte) 0xAA, (byte) 0xBB, (byte) 0xCC, (byte) 0xDD, (byte) 0xEE};
byte[] actualBytes = TbUtils.hexToBytesArray(validInput);
Assertions.assertArrayEquals(expected, actualBytes);
try {
input = "0x01752B0367FA000500010488FFFFFFFFFFFFFFFF3";
TbUtils.hexToBytes(ctx, input);
@ -807,6 +811,12 @@ public class TbUtilsTest {
} catch (IllegalArgumentException e) {
Assertions.assertTrue(e.getMessage().contains("Hex string must be not empty"));
}
try {
input = null;
TbUtils.hexToBytes(ctx, input);
} catch (IllegalArgumentException e) {
Assertions.assertTrue(e.getMessage().contains("Hex string must be not empty"));
}
}
@Test
@ -1086,6 +1096,26 @@ public class TbUtilsTest {
String actual = TbUtils.hexToBase64(hex);
Assertions.assertEquals(expected, actual);
}
@Test
void base64ToBytesList_Test() {
String validInput = Base64.getEncoder().encodeToString(new byte[]{1, 2, 3, 4, 5});
ExecutionArrayList<Byte> actual = TbUtils.base64ToBytesList(ctx, validInput);
ExecutionArrayList<Byte> expected = new ExecutionArrayList<>(ctx);
expected.addAll(List.of((byte) 1, (byte)2, (byte)3, (byte)4, (byte)5));
Assertions.assertEquals(expected, actual);
String emptyInput = Base64.getEncoder().encodeToString(new byte[]{});
actual = TbUtils.base64ToBytesList(ctx, emptyInput);
Assertions.assertTrue(actual.isEmpty());
String invalidInput = "NotAValidBase64String";
Assertions.assertThrows(IllegalArgumentException.class, () -> {
TbUtils.base64ToBytesList(ctx, invalidInput);
});
Assertions.assertThrows(NullPointerException.class, () -> {
TbUtils.base64ToBytesList(ctx, null);
});
}
@Test
public void bytesToHex_Test() {
byte[] bb = {(byte) 0xBB, (byte) 0xAA};

44
common/transport/coap/src/main/java/org/thingsboard/server/transport/coap/CoapTransportResource.java

@ -24,7 +24,10 @@ import org.eclipse.californium.core.observe.ObserveRelation;
import org.eclipse.californium.core.server.resources.CoapExchange;
import org.eclipse.californium.core.server.resources.Resource;
import org.eclipse.californium.core.server.resources.ResourceObserver;
import org.eclipse.californium.elements.EndpointContext;
import org.eclipse.californium.elements.auth.X509CertPath;
import org.thingsboard.server.coapserver.CoapServerService;
import org.thingsboard.server.coapserver.TbCoapDtlsSessionKey;
import org.thingsboard.server.coapserver.TbCoapDtlsSessionInfo;
import org.thingsboard.server.common.adaptor.AdaptorException;
import org.thingsboard.server.common.adaptor.JsonConverter;
@ -47,12 +50,14 @@ import org.thingsboard.server.transport.coap.client.CoapClientContext;
import org.thingsboard.server.transport.coap.client.TbCoapClientState;
import java.net.InetSocketAddress;
import java.util.Base64;
import java.util.List;
import java.util.Optional;
import java.util.Random;
import java.util.UUID;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.TimeUnit;
import java.security.cert.X509Certificate;
import static org.eclipse.californium.elements.DtlsEndpointContext.KEY_SESSION_ID;
@ -65,7 +70,7 @@ public class CoapTransportResource extends AbstractCoapTransportResource {
private static final int FEATURE_TYPE_POSITION_CERTIFICATE_REQUEST = 3;
private static final int REQUEST_ID_POSITION_CERTIFICATE_REQUEST = 4;
private final ConcurrentMap<InetSocketAddress, TbCoapDtlsSessionInfo> dtlsSessionsMap;
private final ConcurrentMap<TbCoapDtlsSessionKey, TbCoapDtlsSessionInfo> dtlsSessionsMap;
private final long timeout;
private final long piggybackTimeout;
private final CoapClientContext clients;
@ -177,11 +182,7 @@ public class CoapTransportResource extends AbstractCoapTransportResource {
var dtlsSessionId = request.getSourceContext().get(KEY_SESSION_ID);
if (dtlsSessionsMap != null && dtlsSessionId != null && !dtlsSessionId.isEmpty()) {
TbCoapDtlsSessionInfo tbCoapDtlsSessionInfo = dtlsSessionsMap
.computeIfPresent(request.getSourceContext().getPeerAddress(), (dtlsSessionIdStr, dtlsSessionInfo) -> {
dtlsSessionInfo.setLastActivityTime(System.currentTimeMillis());
return dtlsSessionInfo;
});
TbCoapDtlsSessionInfo tbCoapDtlsSessionInfo = this.getCoapDtlsSessionInfo(request.getSourceContext());
if (tbCoapDtlsSessionInfo != null) {
processRequest(exchange, type, request, tbCoapDtlsSessionInfo.getMsg(), tbCoapDtlsSessionInfo.getDeviceProfile());
} else {
@ -251,7 +252,7 @@ public class CoapTransportResource extends AbstractCoapTransportResource {
TransportProtos.SessionInfoProto sessionInfo = clients.getNewSyncSession(clientState);
UUID sessionId = toSessionId(sessionInfo);
transportService.process(sessionInfo, clientState.getAdaptor().convertToPostAttributes(sessionId, request,
clientState.getConfiguration().getAttributesMsgDescriptor()),
clientState.getConfiguration().getAttributesMsgDescriptor()),
new CoapResponseCodeCallback(exchange, CoAP.ResponseCode.CREATED, CoAP.ResponseCode.INTERNAL_SERVER_ERROR));
}
@ -259,7 +260,7 @@ public class CoapTransportResource extends AbstractCoapTransportResource {
TransportProtos.SessionInfoProto sessionInfo = clients.getNewSyncSession(clientState);
UUID sessionId = toSessionId(sessionInfo);
transportService.process(sessionInfo, clientState.getAdaptor().convertToPostTelemetry(sessionId, request,
clientState.getConfiguration().getTelemetryMsgDescriptor()),
clientState.getConfiguration().getTelemetryMsgDescriptor()),
new CoapResponseCodeCallback(exchange, CoAP.ResponseCode.CREATED, CoAP.ResponseCode.INTERNAL_SERVER_ERROR));
}
@ -458,5 +459,32 @@ public class CoapTransportResource extends AbstractCoapTransportResource {
}
}
private TbCoapDtlsSessionInfo getCoapDtlsSessionInfo(EndpointContext endpointContext) {
InetSocketAddress peerAddress = endpointContext.getPeerAddress();
String certPemStr = getCertPem(endpointContext);
TbCoapDtlsSessionKey tbCoapDtlsSessionKey = StringUtils.isNotBlank(certPemStr) ? new TbCoapDtlsSessionKey(peerAddress, certPemStr) : null;
TbCoapDtlsSessionInfo tbCoapDtlsSessionInfo;
if (tbCoapDtlsSessionKey != null) {
tbCoapDtlsSessionInfo = dtlsSessionsMap
.computeIfPresent(tbCoapDtlsSessionKey, (dtlsSessionIdStr, dtlsSessionInfo) -> {
dtlsSessionInfo.setLastActivityTime(System.currentTimeMillis());
return dtlsSessionInfo;
});
} else {
tbCoapDtlsSessionInfo = null;
}
return tbCoapDtlsSessionInfo;
}
private String getCertPem(EndpointContext endpointContext) {
try {
X509CertPath certPath = (X509CertPath) endpointContext.getPeerIdentity();
X509Certificate x509Certificate = (X509Certificate) certPath.getPath().getCertificates().get(0);
return Base64.getEncoder().encodeToString(x509Certificate.getEncoded());
} catch (Exception e) {
log.error("Failed to get cert PEM: [{}]", endpointContext.getPeerAddress(), e);
return null;
}
}
}

14
common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/store/util/LwM2MClientSerDes.java

@ -17,7 +17,6 @@ package org.thingsboard.server.transport.lwm2m.server.store.util;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
@ -57,7 +56,7 @@ public class LwM2MClientSerDes {
@SneakyThrows
public static byte[] serialize(LwM2mClient client) {
JsonObject o = new JsonObject();
JsonObject o = new JsonObject();
o.addProperty("nodeId", client.getNodeId());
o.addProperty("endpoint", client.getEndpoint());
@ -111,14 +110,7 @@ public class LwM2MClientSerDes {
o.addProperty("defaultObjectIDVer", client.getDefaultObjectIDVer().toString());
if (client.getRegistration() != null) {
String registrationAddress = client.getRegistration().getAddress().toString();
JsonNode registrationNode = registrationSerDes.jSerialize(client.getRegistration());
if (!registrationAddress.equals(registrationNode.get("transportdata").get("address").asText())){
ObjectNode actualRegAddress = (ObjectNode)registrationNode.get("transportdata");
actualRegAddress.put("address", registrationAddress);
ObjectNode actualIdentity = (ObjectNode) actualRegAddress.get("identity");
actualIdentity.put("address", registrationAddress);
}
o.addProperty("registration", registrationNode.toString());
}
o.addProperty("asleep", client.isAsleep());
@ -188,7 +180,7 @@ public class LwM2MClientSerDes {
case STRING:
return value.getAsString();
case TIME:
return Instant.ofEpochMilli(value.getAsLong());
return new Date(value.getAsLong());
case OBJLNK:
return ObjectLink.decodeFromString(value.getAsString());
case UNSIGNED_INTEGER:
@ -249,7 +241,7 @@ public class LwM2MClientSerDes {
o.addProperty(VALUE, ((ObjectLink) value).encodeToString());
break;
case UNSIGNED_INTEGER:
o.addProperty(VALUE, Integer.toUnsignedString((int)value));
o.addProperty(VALUE, Integer.toUnsignedString((int) value));
break;
default:
throw new LwM2mNodeException(String.format("Type %s is not supported", type.name()));

2
common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/uplink/DefaultLwM2mUplinkMsgHandler.java

@ -279,6 +279,7 @@ public class DefaultLwM2mUplinkMsgHandler extends LwM2MExecutorAwareService impl
clientContext.unregister(client, registration);
SessionInfoProto sessionInfo = client.getSession();
if (sessionInfo != null) {
securityStore.remove(client.getEndpoint(), client.getRegistration().getId());
sessionManager.deregister(sessionInfo);
sessionStore.remove(registration.getEndpoint());
log.info("Client close session: [{}] unReg [{}] name [{}] profile ", registration.getId(), registration.getEndpoint(), sessionInfo.getDeviceType());
@ -401,7 +402,6 @@ public class DefaultLwM2mUplinkMsgHandler extends LwM2MExecutorAwareService impl
.stream().filter(e -> e.getProfileId() != null)
.filter(e -> e.getProfileId().equals(deviceProfile.getUuidId())).collect(Collectors.toList());
clients.forEach(client -> {
this.securityStore.remove(client.getEndpoint(), client.getRegistration().getId());
client.onDeviceProfileUpdate(deviceProfile);
});
if (clients.size() > 0) {

29
common/transport/lwm2m/src/test/java/org/thingsboard/server/transport/lwm2m/server/store/util/LwM2MClientSerDesTest.java

@ -18,13 +18,17 @@ package org.thingsboard.server.transport.lwm2m.server.store.util;
import org.eclipse.leshan.core.LwM2m.LwM2mVersion;
import org.eclipse.leshan.core.endpoint.EndpointUriUtil;
import org.eclipse.leshan.core.link.Link;
import org.eclipse.leshan.core.link.attributes.AttributeSet;
import org.eclipse.leshan.core.link.attributes.ResourceTypeAttribute;
import org.eclipse.leshan.core.node.LwM2mMultipleResource;
import org.eclipse.leshan.core.node.LwM2mPath;
import org.eclipse.leshan.core.node.LwM2mResource;
import org.eclipse.leshan.core.node.LwM2mSingleResource;
import org.eclipse.leshan.core.peer.IpPeer;
import org.eclipse.leshan.core.request.WriteRequest;
import org.eclipse.leshan.server.registration.DefaultRegistrationDataExtractor;
import org.eclipse.leshan.server.registration.Registration;
import org.eclipse.leshan.server.registration.RegistrationDataExtractor;
import org.junit.jupiter.api.Test;
import org.thingsboard.server.common.data.TbResource;
import org.thingsboard.server.common.data.device.data.PowerMode;
@ -83,12 +87,22 @@ public class LwM2MClientSerDesTest {
client.init(credentialsResponse, UUID.randomUUID());
AttributeSet attrs = new AttributeSet( //
new ResourceTypeAttribute("oma.lwm2m"));
Link[] objs = new Link[]{new Link("/15", attrs), new Link("/17")};
RegistrationDataExtractor.RegistrationData dataFromObjectLinks = new DefaultRegistrationDataExtractor().extractDataFromObjectLinks(objs,
LwM2mVersion.V1_0);
Registration registration = new Registration
.Builder("test", "endpoint", new IpPeer(new InetSocketAddress(Inet4Address.getLoopbackAddress(), 1000)),
EndpointUriUtil.createUri("coap://localhost:5685"))
.supportedContentFormats()
.supportedObjects(Map.of(15, LwM2mVersion.V1_0, 17, LwM2mVersion.V1_0))
.objectLinks(new Link[] { new Link("/15"), new Link("/17") })
EndpointUriUtil.createUri("coap://localhost:5685"))
.objectLinks(objs)
.rootPath(dataFromObjectLinks.getAlternatePath())
.supportedContentFormats(dataFromObjectLinks.getSupportedContentFormats())
.supportedObjects(dataFromObjectLinks.getSupportedObjects())
.availableInstances(dataFromObjectLinks.getAvailableInstances())
.build();
client.setRegistration(registration);
@ -135,12 +149,7 @@ public class LwM2MClientSerDesTest {
assertEquals(client.getPsmActivityTimer(), desClient.getPsmActivityTimer());
assertEquals(client.getPagingTransmissionWindow(), desClient.getPagingTransmissionWindow());
assertEquals(client.getEdrxCycle(), desClient.getEdrxCycle());
if (((IpPeer)desClient.getRegistration().getClientTransportData()).getSocketAddress().isUnresolved()) {
String actualReg = desClient.getRegistration().toString().replaceAll("/<unresolved>", "");
assertEquals(client.getRegistration().toString(), actualReg);
} else {
assertEquals(client.getRegistration(), desClient.getRegistration());
}
assertEquals(client.getRegistration(), desClient.getRegistration());
assertEquals(client.isAsleep(), desClient.isAsleep());
assertEquals(client.getLastUplinkTime(), desClient.getLastUplinkTime());
assertEquals(client.getSleepTask(), desClient.getSleepTask());

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

@ -94,6 +94,10 @@ import java.util.function.Function;
import java.util.stream.Collectors;
import static org.eclipse.jgit.api.ListBranchCommand.ListMode;
import static org.eclipse.jgit.transport.RemoteRefUpdate.Status.REJECTED_NODELETE;
import static org.eclipse.jgit.transport.RemoteRefUpdate.Status.REJECTED_NONFASTFORWARD;
import static org.eclipse.jgit.transport.RemoteRefUpdate.Status.REJECTED_OTHER_REASON;
import static org.eclipse.jgit.transport.RemoteRefUpdate.Status.REJECTED_REMOTE_CHANGED;
@Slf4j
public class GitRepository {
@ -358,8 +362,10 @@ public class GitRepository {
result.forEach(pushResult -> {
for (RemoteRefUpdate update : pushResult.getRemoteUpdates()) {
RemoteRefUpdate.Status status = update.getStatus();
if (status != RemoteRefUpdate.Status.OK && status != RemoteRefUpdate.Status.UP_TO_DATE) {
throw new RuntimeException("Failed to push changes: " + Optional.ofNullable(update.getMessage()).orElseGet(status::name));
if (status == REJECTED_NONFASTFORWARD || status == REJECTED_NODELETE ||
status == REJECTED_REMOTE_CHANGED || status == REJECTED_OTHER_REASON) {
throw new RuntimeException("Remote repository answered with error: " +
Optional.ofNullable(update.getMessage()).orElseGet(status::name));
}
}
});

2
dao/src/main/java/org/thingsboard/server/dao/mobile/QrCodeSettingServiceImpl.java

@ -115,7 +115,7 @@ public class QrCodeSettingServiceImpl extends AbstractCachedEntityService<Tenant
qrCodeSettings.setQrCodeConfig(qrCodeConfig);
qrCodeSettings.setMobileAppBundleId(qrCodeSettings.getMobileAppBundleId());
}
if (qrCodeSettings.isUseDefaultApp()) {
if (qrCodeSettings.isUseDefaultApp() || qrCodeSettings.getMobileAppBundleId() == null) {
qrCodeSettings.setGooglePlayLink(googlePlayLink);
qrCodeSettings.setAppStoreLink(appStoreLink);
} else {

4
dao/src/main/java/org/thingsboard/server/dao/model/ModelConstants.java

@ -19,6 +19,8 @@ import com.datastax.oss.driver.api.core.uuid.Uuids;
import org.apache.commons.lang3.ArrayUtils;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.kv.Aggregation;
import org.thingsboard.server.common.data.mobile.app.MobileAppVersionInfo;
import org.thingsboard.server.common.data.mobile.app.StoreInfo;
import java.util.UUID;
@ -454,6 +456,8 @@ public class ModelConstants {
public static final String MOBILE_APP_STATUS_PROPERTY = "status";
public static final String MOBILE_APP_VERSION_INFO_PROPERTY = "version_info";
public static final String MOBILE_APP_STORE_INFO_PROPERTY = "store_info";
public static final MobileAppVersionInfo MOBILE_APP_VERSION_INFO_EMPTY_OBJECT = new MobileAppVersionInfo();
public static final StoreInfo MOBILE_APP_STORE_INFO_EMPTY_OBJECT = new StoreInfo();
/**
* Mobile application bundle constants.

6
dao/src/main/java/org/thingsboard/server/dao/model/sql/MobileAppEntity.java

@ -37,6 +37,8 @@ import org.thingsboard.server.dao.util.mapping.JsonConverter;
import java.util.UUID;
import static org.thingsboard.server.dao.model.ModelConstants.MOBILE_APP_STORE_INFO_EMPTY_OBJECT;
import static org.thingsboard.server.dao.model.ModelConstants.MOBILE_APP_VERSION_INFO_EMPTY_OBJECT;
import static org.thingsboard.server.dao.model.ModelConstants.TENANT_ID_COLUMN;
@Data
@ -99,8 +101,8 @@ public class MobileAppEntity extends BaseSqlEntity<MobileApp> {
mobile.setAppSecret(appSecret);
mobile.setPlatformType(platformType);
mobile.setStatus(status);
mobile.setVersionInfo(fromJson(versionInfo, MobileAppVersionInfo.class));
mobile.setStoreInfo(fromJson(storeInfo, StoreInfo.class));
mobile.setVersionInfo(versionInfo != null ? fromJson(versionInfo, MobileAppVersionInfo.class) : MOBILE_APP_VERSION_INFO_EMPTY_OBJECT);
mobile.setStoreInfo(storeInfo != null ? fromJson(storeInfo, StoreInfo.class) : MOBILE_APP_STORE_INFO_EMPTY_OBJECT);
return mobile;
}
}

16
dao/src/main/java/org/thingsboard/server/dao/service/validator/MobileAppDataValidator.java

@ -30,21 +30,17 @@ public class MobileAppDataValidator extends DataValidator<MobileApp> {
@Override
protected void validateDataImpl(TenantId tenantId, MobileApp mobileApp) {
if (mobileApp.getPlatformType() == PlatformType.ANDROID) {
if (mobileApp.getStoreInfo() != null &&
if (mobileApp.getStatus() == MobileAppStatus.PUBLISHED) {
if (mobileApp.getStoreInfo() == null) {
throw new DataValidationException("Store info is required for published apps");
}
if (mobileApp.getPlatformType() == PlatformType.ANDROID &&
(mobileApp.getStoreInfo().getSha256CertFingerprints() == null || mobileApp.getStoreInfo().getStoreLink() == null)) {
throw new DataValidationException("Sha256CertFingerprints and store link are required");
}
} else if (mobileApp.getPlatformType() == PlatformType.IOS) {
if (mobileApp.getStoreInfo() != null &&
} else if (mobileApp.getPlatformType() == PlatformType.IOS &&
(mobileApp.getStoreInfo().getAppId() == null || mobileApp.getStoreInfo().getStoreLink() == null)) {
throw new DataValidationException("AppId and store link are required");
}
} else {
throw new DataValidationException("Wrong application platform type");
}
if (mobileApp.getStatus() == MobileAppStatus.PUBLISHED && mobileApp.getStoreInfo() == null) {
throw new DataValidationException("Store info is required for published apps");
}
}
}

3
packaging/java/scripts/control/template.service

@ -8,7 +8,8 @@ ExecStart=${pkg.installFolder}/bin/${pkg.name}.jar
SuccessExitStatus=143
# Service shall be restarted in 30 seconds when the service process exits, is killed, or a timeout is reached.
Restart=always # default 'no'
# Restart parameter default value 'no'
Restart=always
RestartSec=30
[Install]

1
rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbAssignToCustomerNode.java

@ -40,7 +40,6 @@ import org.thingsboard.server.common.msg.TbMsg;
nodeDescription = "Assign message originator entity to customer",
nodeDetails = "Finds target customer by title and assign message originator entity to this customer. " +
"Rule node will create a new customer if it doesn't exist, and 'Create new customer if it doesn't exist' enabled.",
uiResources = {"static/rulenode/rulenode-core-config.js"},
configDirective = "tbActionNodeAssignToCustomerConfig",
icon = "add_circle",
version = 1

1
rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbClearAlarmNode.java

@ -43,7 +43,6 @@ import org.thingsboard.server.common.msg.TbMsg;
"If alarm was not cleared, original message is returned. Otherwise new Message returned with type 'ALARM', Alarm object in 'msg' property and 'metadata' will contains 'isClearedAlarm' property. " +
"Message payload can be accessed via <code>msg</code> property. For example <code>'temperature = ' + msg.temperature ;</code>. " +
"Message metadata can be accessed via <code>metadata</code> property. For example <code>'name = ' + metadata.customerName;</code>.",
uiResources = {"static/rulenode/rulenode-core-config.js"},
configDirective = "tbActionNodeClearAlarmConfig",
icon = "notifications_off"
)

1
rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbCopyAttributesToEntityViewNode.java

@ -63,7 +63,6 @@ import static org.thingsboard.server.common.data.msg.TbNodeConnectionType.SUCCES
nodeDetails = "Copy attributes from asset/device to related entity view according to entity view configuration. \n " +
"Copy will be done only for attributes that are between start and end dates and according to attribute keys configuration. \n" +
"Changes message originator to related entity view and produces new messages according to count of updated entity views",
uiResources = {"static/rulenode/rulenode-core-config.js"},
configDirective = "tbNodeEmptyConfig",
icon = "content_copy"
)

1
rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbCreateAlarmNode.java

@ -51,7 +51,6 @@ import java.util.List;
"If alarm was not created, original message is returned. Otherwise new Message returned with type 'ALARM', Alarm object in 'msg' property and 'metadata' will contains one of those properties 'isNewAlarm/isExistingAlarm'. " +
"Message payload can be accessed via <code>msg</code> property. For example <code>'temperature = ' + msg.temperature ;</code>. " +
"Message metadata can be accessed via <code>metadata</code> property. For example <code>'name = ' + metadata.customerName;</code>.",
uiResources = {"static/rulenode/rulenode-core-config.js"},
configDirective = "tbActionNodeCreateAlarmConfig",
icon = "notifications_active"
)

1
rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbCreateRelationNode.java

@ -61,7 +61,6 @@ import static org.thingsboard.common.util.DonAsynchron.withCallback;
"Useful in GPS tracking use cases where relation acts as a temporary indicator of a tracker presence in specific geofence.</li>" +
"<li><strong>Change originator to target entity</strong> - useful when you need to process submitted message as a message from target entity.</li></ul>" +
"Output connections: <code>Success</code> - if the relation already exists or successfully created, otherwise <code>Failure</code>.",
uiResources = {"static/rulenode/rulenode-core-config.js"},
configDirective = "tbActionNodeCreateRelationConfig",
icon = "add_circle",
version = 1

1
rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbDeleteRelationNode.java

@ -53,7 +53,6 @@ import static org.thingsboard.common.util.DonAsynchron.withCallback;
"<li><strong>User</strong> - use a user with the specified email as the target entity to delete relation with.</li>" +
"<li><strong>Edge</strong> - use an edge with the specified name as the target entity to delete relation with.</li></ul>" +
"Output connections: <code>Success</code> - If the relation(s) successfully deleted, otherwise <code>Failure</code>.",
uiResources = {"static/rulenode/rulenode-core-config.js"},
configDirective = "tbActionNodeDeleteRelationConfig",
icon = "remove_circle",
version = 1

1
rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbDeviceStateNode.java

@ -58,7 +58,6 @@ import java.util.Set;
"This node is particularly useful when device isn't using transports to receive data, such as when fetching data from external API or computing new data within the rule chain.",
configClazz = TbDeviceStateNodeConfiguration.class,
relationTypes = {TbNodeConnectionType.SUCCESS, TbNodeConnectionType.FAILURE, "Rate limited"},
uiResources = {"static/rulenode/rulenode-core-config.js"},
configDirective = "tbActionNodeDeviceStateConfig"
)
public class TbDeviceStateNode implements TbNode {

1
rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbLogNode.java

@ -43,7 +43,6 @@ import java.util.Objects;
nodeDetails = "Transform incoming Message with configured JS function to String and log final value into Thingsboard log file. " +
"Message payload can be accessed via <code>msg</code> property. For example <code>'temperature = ' + msg.temperature ;</code>. " +
"Message metadata can be accessed via <code>metadata</code> property. For example <code>'name = ' + metadata.customerName;</code>.",
uiResources = {"static/rulenode/rulenode-core-config.js"},
configDirective = "tbActionNodeLogConfig",
icon = "menu"
)

1
rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbMsgCountNode.java

@ -42,7 +42,6 @@ import java.util.concurrent.atomic.AtomicLong;
nodeDescription = "Count incoming messages",
nodeDetails = "Count incoming messages for specified interval and produces POST_TELEMETRY_REQUEST msg with messages count",
icon = "functions",
uiResources = {"static/rulenode/rulenode-core-config.js"},
configDirective = "tbActionNodeMsgCountConfig"
)
public class TbMsgCountNode implements TbNode {

1
rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbSaveToCustomCassandraTableNode.java

@ -69,7 +69,6 @@ import static org.thingsboard.common.util.DonAsynchron.withCallback;
"<b>Note:</b>If the mapping key is <b>$entity_id</b>, that is identified by the Message Originator, then to the appropriate column name(mapping value) will be write the message originator id.<br><br>" +
"If specified message field does not exist or is not a JSON Primitive, the outbound message will be routed via <b>failure</b> chain," +
" otherwise, the message will be routed via <b>success</b> chain.",
uiResources = {"static/rulenode/rulenode-core-config.js"},
configDirective = "tbActionNodeCustomTableConfig",
icon = "file_upload",
ruleChainTypes = RuleChainType.CORE)

1
rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbUnassignFromCustomerNode.java

@ -42,7 +42,6 @@ import org.thingsboard.server.common.msg.TbMsg;
"If the incoming message originator is a dashboard, will try to search for the customer by title specified in the configuration. " +
"If customer doesn't exist, the exception will be thrown. Otherwise will unassign the dashboard from retrieved customer.<br><br>" +
"Other entities can be assigned only to one customer, so specified customer title in the configuration will be ignored if the originator isn't a dashboard.",
uiResources = {"static/rulenode/rulenode-core-config.js"},
configDirective = "tbActionNodeUnAssignToCustomerConfig",
icon = "remove_circle",
version = 1

1
rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/aws/lambda/TbAwsLambdaNode.java

@ -53,7 +53,6 @@ import static org.thingsboard.server.dao.service.ConstraintValidator.validateFie
"It sends messages using a RequestResponse invocation type. " +
"The node uses a pre-configured client and specified function to run.<br><br>" +
"Output connections: <code>Success</code>, <code>Failure</code>.",
uiResources = {"static/rulenode/rulenode-core-config.js"},
configDirective = "tbExternalNodeLambdaConfig",
iconUrl = "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCIgd2lkdGg9IjQ4IiBoZWlnaHQ9IjQ4Ij48cGF0aCBkPSJNMTMuMjMgMTAuNTZWMTBjLTEuOTQgMC0zLjk5LjM5LTMuOTkgMi42NyAwIDEuMTYuNjEgMS45NSAxLjYzIDEuOTUuNzYgMCAxLjQzLS40NyAxLjg2LTEuMjIuNTItLjkzLjUtMS44LjUtMi44NG0yLjcgNi41M2MtLjE4LjE2LS40My4xNy0uNjMuMDYtLjg5LS43NC0xLjA1LTEuMDgtMS41NC0xLjc5LTEuNDcgMS41LTIuNTEgMS45NS00LjQyIDEuOTUtMi4yNSAwLTQuMDEtMS4zOS00LjAxLTQuMTcgMC0yLjE4IDEuMTctMy42NCAyLjg2LTQuMzggMS40Ni0uNjQgMy40OS0uNzYgNS4wNC0uOTNWNy41YzAtLjY2LjA1LTEuNDEtLjMzLTEuOTYtLjMyLS40OS0uOTUtLjctMS41LS43LTEuMDIgMC0xLjkzLjUzLTIuMTUgMS42MS0uMDUuMjQtLjI1LjQ4LS40Ny40OWwtMi42LS4yOGMtLjIyLS4wNS0uNDYtLjIyLS40LS41Ni42LTMuMTUgMy40NS00LjEgNi00LjEgMS4zIDAgMyAuMzUgNC4wMyAxLjMzQzE3LjExIDQuNTUgMTcgNi4xOCAxNyA3Ljk1djQuMTdjMCAxLjI1LjUgMS44MSAxIDIuNDguMTcuMjUuMjEuNTQgMCAuNzFsLTIuMDYgMS43OGgtLjAxIj48L3BhdGg+PHBhdGggZD0iTTIwLjE2IDE5LjU0QzE4IDIxLjE0IDE0LjgyIDIyIDEyLjEgMjJjLTMuODEgMC03LjI1LTEuNDEtOS44NS0zLjc2LS4yLS4xOC0uMDItLjQzLjI1LS4yOSAyLjc4IDEuNjMgNi4yNSAyLjYxIDkuODMgMi42MSAyLjQxIDAgNS4wNy0uNSA3LjUxLTEuNTMuMzctLjE2LjY2LjI0LjMyLjUxIj48L3BhdGg+PHBhdGggZD0iTTIxLjA3IDE4LjVjLS4yOC0uMzYtMS44NS0uMTctMi41Ny0uMDgtLjE5LjAyLS4yMi0uMTYtLjAzLS4zIDEuMjQtLjg4IDMuMjktLjYyIDMuNTMtLjMzLjI0LjMtLjA3IDIuMzUtMS4yNCAzLjMyLS4xOC4xNi0uMzUuMDctLjI2LS4xMS4yNi0uNjcuODUtMi4xNC41Ny0yLjV6Ij48L3BhdGg+PC9zdmc+"
)

1
rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/aws/sns/TbSnsNode.java

@ -46,7 +46,6 @@ import static org.thingsboard.common.util.DonAsynchron.withCallback;
nodeDetails = "Will publish message payload to the AWS SNS topic. Outbound message will contain response fields " +
"(<code>messageId</code>, <code>requestId</code>) in the Message Metadata from the AWS SNS. " +
"For example <b>requestId</b> field can be accessed with <code>metadata.requestId</code>.",
uiResources = {"static/rulenode/rulenode-core-config.js"},
configDirective = "tbExternalNodeSnsConfig",
iconUrl = "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCIgd2lkdGg9IjQ4IiBoZWlnaHQ9IjQ4Ij48cGF0aCBkPSJNMTMuMjMgMTAuNTZWMTBjLTEuOTQgMC0zLjk5LjM5LTMuOTkgMi42NyAwIDEuMTYuNjEgMS45NSAxLjYzIDEuOTUuNzYgMCAxLjQzLS40NyAxLjg2LTEuMjIuNTItLjkzLjUtMS44LjUtMi44NG0yLjcgNi41M2MtLjE4LjE2LS40My4xNy0uNjMuMDYtLjg5LS43NC0xLjA1LTEuMDgtMS41NC0xLjc5LTEuNDcgMS41LTIuNTEgMS45NS00LjQyIDEuOTUtMi4yNSAwLTQuMDEtMS4zOS00LjAxLTQuMTcgMC0yLjE4IDEuMTctMy42NCAyLjg2LTQuMzggMS40Ni0uNjQgMy40OS0uNzYgNS4wNC0uOTNWNy41YzAtLjY2LjA1LTEuNDEtLjMzLTEuOTYtLjMyLS40OS0uOTUtLjctMS41LS43LTEuMDIgMC0xLjkzLjUzLTIuMTUgMS42MS0uMDUuMjQtLjI1LjQ4LS40Ny40OWwtMi42LS4yOGMtLjIyLS4wNS0uNDYtLjIyLS40LS41Ni42LTMuMTUgMy40NS00LjEgNi00LjEgMS4zIDAgMyAuMzUgNC4wMyAxLjMzQzE3LjExIDQuNTUgMTcgNi4xOCAxNyA3Ljk1djQuMTdjMCAxLjI1LjUgMS44MSAxIDIuNDguMTcuMjUuMjEuNTQgMCAuNzFsLTIuMDYgMS43OGgtLjAxIj48L3BhdGg+PHBhdGggZD0iTTIwLjE2IDE5LjU0QzE4IDIxLjE0IDE0LjgyIDIyIDEyLjEgMjJjLTMuODEgMC03LjI1LTEuNDEtOS44NS0zLjc2LS4yLS4xOC0uMDItLjQzLjI1LS4yOSAyLjc4IDEuNjMgNi4yNSAyLjYxIDkuODMgMi42MSAyLjQxIDAgNS4wNy0uNSA3LjUxLTEuNTMuMzctLjE2LjY2LjI0LjMyLjUxIj48L3BhdGg+PHBhdGggZD0iTTIxLjA3IDE4LjVjLS4yOC0uMzYtMS44NS0uMTctMi41Ny0uMDgtLjE5LjAyLS4yMi0uMTYtLjAzLS4zIDEuMjQtLjg4IDMuMjktLjYyIDMuNTMtLjMzLjI0LjMtLjA3IDIuMzUtMS4yNCAzLjMyLS4xOC4xNi0uMzUuMDctLjI2LS4xMS4yNi0uNjcuODUtMi4xNC41Ny0yLjV6Ij48L3BhdGg+PC9zdmc+"
)

1
rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/aws/sqs/TbSqsNode.java

@ -52,7 +52,6 @@ import static org.thingsboard.common.util.DonAsynchron.withCallback;
"response fields (<code>messageId</code>, <code>requestId</code>, <code>messageBodyMd5</code>, <code>messageAttributesMd5</code>" +
", <code>sequenceNumber</code>) in the Message Metadata from the AWS SQS." +
" For example <b>requestId</b> field can be accessed with <code>metadata.requestId</code>.",
uiResources = {"static/rulenode/rulenode-core-config.js"},
configDirective = "tbExternalNodeSqsConfig",
iconUrl = "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCIgd2lkdGg9IjQ4IiBoZWlnaHQ9IjQ4Ij48cGF0aCBkPSJNMTMuMjMgMTAuNTZWMTBjLTEuOTQgMC0zLjk5LjM5LTMuOTkgMi42NyAwIDEuMTYuNjEgMS45NSAxLjYzIDEuOTUuNzYgMCAxLjQzLS40NyAxLjg2LTEuMjIuNTItLjkzLjUtMS44LjUtMi44NG0yLjcgNi41M2MtLjE4LjE2LS40My4xNy0uNjMuMDYtLjg5LS43NC0xLjA1LTEuMDgtMS41NC0xLjc5LTEuNDcgMS41LTIuNTEgMS45NS00LjQyIDEuOTUtMi4yNSAwLTQuMDEtMS4zOS00LjAxLTQuMTcgMC0yLjE4IDEuMTctMy42NCAyLjg2LTQuMzggMS40Ni0uNjQgMy40OS0uNzYgNS4wNC0uOTNWNy41YzAtLjY2LjA1LTEuNDEtLjMzLTEuOTYtLjMyLS40OS0uOTUtLjctMS41LS43LTEuMDIgMC0xLjkzLjUzLTIuMTUgMS42MS0uMDUuMjQtLjI1LjQ4LS40Ny40OWwtMi42LS4yOGMtLjIyLS4wNS0uNDYtLjIyLS40LS41Ni42LTMuMTUgMy40NS00LjEgNi00LjEgMS4zIDAgMyAuMzUgNC4wMyAxLjMzQzE3LjExIDQuNTUgMTcgNi4xOCAxNyA3Ljk1djQuMTdjMCAxLjI1LjUgMS44MSAxIDIuNDguMTcuMjUuMjEuNTQgMCAuNzFsLTIuMDYgMS43OGgtLjAxIj48L3BhdGg+PHBhdGggZD0iTTIwLjE2IDE5LjU0QzE4IDIxLjE0IDE0LjgyIDIyIDEyLjEgMjJjLTMuODEgMC03LjI1LTEuNDEtOS44NS0zLjc2LS4yLS4xOC0uMDItLjQzLjI1LS4yOSAyLjc4IDEuNjMgNi4yNSAyLjYxIDkuODMgMi42MSAyLjQxIDAgNS4wNy0uNSA3LjUxLTEuNTMuMzctLjE2LjY2LjI0LjMyLjUxIj48L3BhdGg+PHBhdGggZD0iTTIxLjA3IDE4LjVjLS4yOC0uMzYtMS44NS0uMTctMi41Ny0uMDgtLjE5LjAyLS4yMi0uMTYtLjAzLS4zIDEuMjQtLjg4IDMuMjktLjYyIDMuNTMtLjMzLjI0LjMtLjA3IDIuMzUtMS4yNCAzLjMyLS4xOC4xNi0uMzUuMDctLjI2LS4xMS4yNi0uNjcuODUtMi4xNC41Ny0yLjV6Ij48L3BhdGg+PC9zdmc+"
)

1
rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/debug/TbMsgGeneratorNode.java

@ -62,7 +62,6 @@ import static org.thingsboard.server.common.data.DataConstants.QUEUE_NAME;
nodeDescription = "Periodically generates messages",
nodeDetails = "Generates messages with configurable period. Javascript function used for message generation.",
inEnabled = false,
uiResources = {"static/rulenode/rulenode-core-config.js"},
configDirective = "tbActionNodeGeneratorConfig",
icon = "repeat"
)

3
rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/deduplication/TbMsgDeduplicationNode.java

@ -59,8 +59,7 @@ import static org.thingsboard.server.common.data.DataConstants.QUEUE_NAME;
"<li><strong>ALL</strong> - return all messages as a single JSON array message. " +
"Where each element represents object with <strong><i>msg</i></strong> and <strong><i>metadata</i></strong> inner properties.</li></ul>",
icon = "content_copy",
uiResources = {"static/rulenode/rulenode-core-config.js"},
configDirective = "tbActionNodeMsgDeduplicationConfig"
configDirective = "tbTransformationNodeDeduplicationConfig"
)
@Slf4j
public class TbMsgDeduplicationNode implements TbNode {

1
rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/delay/TbMsgDelayNode.java

@ -45,7 +45,6 @@ import java.util.concurrent.TimeUnit;
"Deprecated because the acknowledged message still stays in memory (to be delayed) and this " +
"does not guarantee that message will be processed even if the \"retry failures and timeouts\" processing strategy will be chosen.",
icon = "pause",
uiResources = {"static/rulenode/rulenode-core-config.js"},
configDirective = "tbActionNodeMsgDelayConfig"
)
public class TbMsgDelayNode implements TbNode {

1
rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/edge/TbMsgPushToCloudNode.java

@ -46,7 +46,6 @@ import java.util.UUID;
"<br><code>ALARM</code><br><br>" +
"Message will be routed via <b>Failure</b> route if node was not able to save cloud event to database or unsupported originator type/message type arrived. " +
"In case successful storage cloud event to database message will be routed via <b>Success</b> route.",
uiResources = {"static/rulenode/rulenode-core-config.js"},
configDirective = "tbActionNodePushToCloudConfig",
icon = "cloud_upload",
ruleChainTypes = RuleChainType.EDGE

1
rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/edge/TbMsgPushToEdgeNode.java

@ -61,7 +61,6 @@ import static org.thingsboard.server.dao.edge.BaseRelatedEdgesService.RELATED_ED
"<br><code>ALARM</code><br><br>" +
"Message will be routed via <b>Failure</b> route if node was not able to save edge event to database or unsupported message type arrived. " +
"In case successful storage edge event to database message will be routed via <b>Success</b> route.",
uiResources = {"static/rulenode/rulenode-core-config.js"},
configDirective = "tbActionNodePushToEdgeConfig",
icon = "cloud_download",
ruleChainTypes = RuleChainType.CORE

1
rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbAssetTypeSwitchNode.java

@ -36,7 +36,6 @@ import org.thingsboard.server.common.data.plugin.ComponentType;
nodeDescription = "Route incoming messages based on the name of the asset profile",
nodeDetails = "Route incoming messages based on the name of the asset profile. The asset profile name is case-sensitive.<br><br>" +
"Output connections: <i>Asset profile name</i> or <code>Failure</code>",
uiResources = {"static/rulenode/rulenode-core-config.js"},
configDirective = "tbNodeEmptyConfig")
public class TbAssetTypeSwitchNode extends TbAbstractTypeSwitchNode {

1
rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbCheckAlarmStatusNode.java

@ -43,7 +43,6 @@ import java.util.Objects;
nodeDescription = "Checks alarm status.",
nodeDetails = "Checks the alarm status to match one of the specified statuses.<br><br>" +
"Output connections: <code>True</code>, <code>False</code>, <code>Failure</code>.",
uiResources = {"static/rulenode/rulenode-core-config.js"},
configDirective = "tbFilterNodeCheckAlarmStatusConfig")
public class TbCheckAlarmStatusNode implements TbNode {

1
rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbCheckMessageNode.java

@ -40,7 +40,6 @@ import java.util.Map;
nodeDetails = "By default, the rule node checks that all specified fields are present. " +
"Uncheck the 'Check that all selected fields are present' if the presence of at least one field is sufficient.<br><br>" +
"Output connections: <code>True</code>, <code>False</code>, <code>Failure</code>",
uiResources = {"static/rulenode/rulenode-core-config.js"},
configDirective = "tbFilterNodeCheckMessageConfig")
public class TbCheckMessageNode implements TbNode {

1
rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbCheckRelationNode.java

@ -56,7 +56,6 @@ import static org.thingsboard.common.util.DonAsynchron.withCallback;
"Otherwise, the rule node checks the presence of a relation to any entity. " +
"In both cases, relation lookup is based on configured direction and type.<br><br>" +
"Output connections: <code>True</code>, <code>False</code>, <code>Failure</code>",
uiResources = {"static/rulenode/rulenode-core-config.js"},
configDirective = "tbFilterNodeCheckRelationConfig")
public class TbCheckRelationNode implements TbNode {

1
rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbDeviceTypeSwitchNode.java

@ -36,7 +36,6 @@ import org.thingsboard.server.common.data.plugin.ComponentType;
nodeDescription = "Route incoming messages based on the name of the device profile",
nodeDetails = "Route incoming messages based on the name of the device profile. The device profile name is case-sensitive<br><br>" +
"Output connections: <i>Device profile name</i> or <code>Failure</code>",
uiResources = {"static/rulenode/rulenode-core-config.js"},
configDirective = "tbNodeEmptyConfig")
public class TbDeviceTypeSwitchNode extends TbAbstractTypeSwitchNode {

1
rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbJsFilterNode.java

@ -44,7 +44,6 @@ import static org.thingsboard.common.util.DonAsynchron.withCallback;
"Message metadata can be accessed via <code>metadata</code> property. For example <code>metadata.customerName === 'John';</code><br/>" +
"Message type can be accessed via <code>msgType</code> property.<br><br>" +
"Output connections: <code>True</code>, <code>False</code>, <code>Failure</code>",
uiResources = {"static/rulenode/rulenode-core-config.js"},
configDirective = "tbFilterNodeScriptConfig"
)
public class TbJsFilterNode implements TbNode {

1
rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbJsSwitchNode.java

@ -46,7 +46,6 @@ import java.util.Set;
"Message metadata can be accessed via <code>metadata</code> property. For example <code>metadata.customerName === 'John';</code><br/>" +
"Message type can be accessed via <code>msgType</code> property.<br><br>" +
"Output connections: <i>Custom connection(s) defined by switch node</i> or <code>Failure</code>",
uiResources = {"static/rulenode/rulenode-core-config.js"},
configDirective = "tbFilterNodeSwitchConfig")
public class TbJsSwitchNode implements TbNode {

1
rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbMsgTypeFilterNode.java

@ -38,7 +38,6 @@ import org.thingsboard.server.common.msg.TbMsg;
nodeDescription = "Filter incoming messages by Message Type",
nodeDetails = "If incoming message type is expected - send Message via <b>True</b> chain, otherwise <b>False</b> chain is used.<br><br>" +
"Output connections: <code>True</code>, <code>False</code>, <code>Failure</code>",
uiResources = {"static/rulenode/rulenode-core-config.js"},
configDirective = "tbFilterNodeMessageTypeConfig")
public class TbMsgTypeFilterNode implements TbNode {

1
rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbMsgTypeSwitchNode.java

@ -36,7 +36,6 @@ import org.thingsboard.server.common.msg.TbMsg;
nodeDetails = "Sends messages with message types <b>\"Post attributes\", \"Post telemetry\", \"RPC Request\"</b>" +
" etc. via corresponding chain, otherwise <b>Other</b> chain is used.<br><br>" +
"Output connections: <i>Message type connection</i>, <code>Other</code> - if message type is custom or <code>Failure</code>",
uiResources = {"static/rulenode/rulenode-core-config.js"},
configDirective = "tbNodeEmptyConfig")
public class TbMsgTypeSwitchNode implements TbNode {

1
rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbOriginatorTypeFilterNode.java

@ -36,7 +36,6 @@ import org.thingsboard.server.common.msg.TbMsg;
nodeDescription = "Filter incoming messages by the type of message originator entity",
nodeDetails = "Checks that the entity type of the incoming message originator matches one of the values specified in the filter.<br><br>" +
"Output connections: <code>True</code>, <code>False</code>, <code>Failure</code>",
uiResources = {"static/rulenode/rulenode-core-config.js"},
configDirective = "tbFilterNodeOriginatorTypeConfig")
public class TbOriginatorTypeFilterNode implements TbNode {

1
rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbOriginatorTypeSwitchNode.java

@ -31,7 +31,6 @@ import org.thingsboard.server.common.data.plugin.ComponentType;
nodeDescription = "Route incoming messages by Message Originator Type",
nodeDetails = "Routes messages to chain according to the entity type ('Device', 'Asset', etc.).<br><br>" +
"Output connections: <i>Message originator type</i> or <code>Failure</code>",
uiResources = {"static/rulenode/rulenode-core-config.js"},
configDirective = "tbNodeEmptyConfig")
public class TbOriginatorTypeSwitchNode extends TbAbstractTypeSwitchNode {

1
rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/flow/TbAckNode.java

@ -33,7 +33,6 @@ import org.thingsboard.server.common.msg.TbMsg;
configClazz = EmptyNodeConfiguration.class,
nodeDescription = "Acknowledges the incoming message",
nodeDetails = "After acknowledgement, the message is pushed to related rule nodes. Useful if you don't care what happens to this message next.",
uiResources = {"static/rulenode/rulenode-core-config.js"},
configDirective = "tbNodeEmptyConfig"
)
public class TbAckNode implements TbNode {

1
rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/flow/TbCheckpointNode.java

@ -40,7 +40,6 @@ import static org.thingsboard.server.common.data.DataConstants.QUEUE_NAME;
hasQueueName = true,
nodeDescription = "transfers the message to another queue",
nodeDetails = "After successful transfer incoming message is automatically acknowledged. Queue name is configurable.",
uiResources = {"static/rulenode/rulenode-core-config.js"},
configDirective = "tbNodeEmptyConfig"
)
public class TbCheckpointNode implements TbNode {

1
rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/flow/TbRuleChainInputNode.java

@ -46,7 +46,6 @@ import java.util.UUID;
"then target rule chain might be resolved dynamically based on incoming message originator. " +
"In this case rule chain specified in the configuration will be used as fallback rule chain.<br><br>" +
"Output connections: <i>Any connection(s) produced by output node(s) in the target rule chain.</i>",
uiResources = {"static/rulenode/rulenode-core-config.js"},
configDirective = "tbFlowNodeRuleChainInputConfig",
relationTypes = {},
ruleChainNode = true,

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

Loading…
Cancel
Save