Browse Source

Merge remote-tracking branch 'ce/rc' into fix-rule-chain-metadata-for-old-edge-ce

pull/12843/head
yevhenii 2 years ago
parent
commit
6eab8a46dc
  1. 2
      application/src/main/data/json/system/scada_symbols/apartments-hp.svg
  2. 2
      application/src/main/data/json/system/scada_symbols/bottom-light-bulb-hp.svg
  3. 2
      application/src/main/data/json/system/scada_symbols/conical-tank.svg
  4. 2
      application/src/main/data/json/system/scada_symbols/consumers-hp.svg
  5. 2
      application/src/main/data/json/system/scada_symbols/dynamic-horizontal-scale-hp.svg
  6. 2
      application/src/main/data/json/system/scada_symbols/dynamic-vertical-scale-hp.svg
  7. 2
      application/src/main/data/json/system/scada_symbols/electrical-distribution-board-hp.svg
  8. 2
      application/src/main/data/json/system/scada_symbols/filter-hp.svg
  9. 2
      application/src/main/data/json/system/scada_symbols/four-rate-energy-meter-hp.svg
  10. 2
      application/src/main/data/json/system/scada_symbols/gas-preventer-hp.svg
  11. 2
      application/src/main/data/json/system/scada_symbols/heat-exchanger-hp.svg
  12. 2
      application/src/main/data/json/system/scada_symbols/heat-pump-hp.svg
  13. 2
      application/src/main/data/json/system/scada_symbols/horizontal-tank-hp.svg
  14. 2
      application/src/main/data/json/system/scada_symbols/house-hp.svg
  15. 2
      application/src/main/data/json/system/scada_symbols/industrial-fuel-generator-hp.svg
  16. 2
      application/src/main/data/json/system/scada_symbols/large-horizontal-separator-hp.svg
  17. 2
      application/src/main/data/json/system/scada_symbols/large-inverter-hp.svg
  18. 2
      application/src/main/data/json/system/scada_symbols/large-stand-cylindrical-tank.svg
  19. 2
      application/src/main/data/json/system/scada_symbols/large-stand-vertical-tank.svg
  20. 2
      application/src/main/data/json/system/scada_symbols/large-vertical-separator-hp.svg
  21. 2
      application/src/main/data/json/system/scada_symbols/leak-sensor.svg
  22. 2
      application/src/main/data/json/system/scada_symbols/low-voltage-tower-hp.svg
  23. 2
      application/src/main/data/json/system/scada_symbols/meter.svg
  24. 2
      application/src/main/data/json/system/scada_symbols/oil-pump-hp.svg
  25. 2
      application/src/main/data/json/system/scada_symbols/pool-hp.svg
  26. 2
      application/src/main/data/json/system/scada_symbols/pool.svg
  27. 2
      application/src/main/data/json/system/scada_symbols/power-socket-hp.svg
  28. 2
      application/src/main/data/json/system/scada_symbols/short-vertical-tank-hp.svg
  29. 2
      application/src/main/data/json/system/scada_symbols/simple-horizontal-scale-hp.svg
  30. 2
      application/src/main/data/json/system/scada_symbols/simple-vertical-scale-hp.svg
  31. 2
      application/src/main/data/json/system/scada_symbols/small-cylindrical-tank.svg
  32. 2
      application/src/main/data/json/system/scada_symbols/small-horizontal-separator-connector-hp.svg
  33. 2
      application/src/main/data/json/system/scada_symbols/small-left-meter.svg
  34. 2
      application/src/main/data/json/system/scada_symbols/small-vertical-separator-connector-hp.svg
  35. 2
      application/src/main/data/json/system/scada_symbols/small-vertical-separator-hp.svg
  36. 2
      application/src/main/data/json/system/scada_symbols/spherical-tank.svg
  37. 2
      application/src/main/data/json/system/scada_symbols/stand-cylindrical-tank.svg
  38. 2
      application/src/main/data/json/system/scada_symbols/stand-vertical-short-tank.svg
  39. 2
      application/src/main/data/json/system/scada_symbols/top-light-bulb-hp.svg
  40. 2
      application/src/main/data/json/system/scada_symbols/turbine-hp.svg
  41. 2
      application/src/main/data/json/system/scada_symbols/vertical-energy-system-controller-hp.svg
  42. 2
      application/src/main/data/json/system/scada_symbols/vertical-tank-hp.svg
  43. 2
      application/src/main/data/json/system/scada_symbols/voltage-stabilizer-hp.svg
  44. 4
      application/src/main/data/json/system/scada_symbols/wind-turbine-cluster-hp.svg
  45. 2
      application/src/main/data/json/system/scada_symbols/wind-turbine-hp.svg
  46. 4
      application/src/main/data/json/system/widget_types/bar_chart.json
  47. 4
      application/src/main/data/json/system/widget_types/bar_chart_with_labels.json
  48. 4
      application/src/main/data/json/system/widget_types/bars.json
  49. 4
      application/src/main/data/json/system/widget_types/doughnut.json
  50. 4
      application/src/main/data/json/system/widget_types/horizontal_doughnut.json
  51. 4
      application/src/main/data/json/system/widget_types/image_map.json
  52. 4
      application/src/main/data/json/system/widget_types/line_chart.json
  53. 4
      application/src/main/data/json/system/widget_types/map.json
  54. 4
      application/src/main/data/json/system/widget_types/pie.json
  55. 4
      application/src/main/data/json/system/widget_types/point_chart.json
  56. 4
      application/src/main/data/json/system/widget_types/polar_area.json
  57. 4
      application/src/main/data/json/system/widget_types/radar.json
  58. 2
      application/src/main/data/json/system/widget_types/radial_gauge.json
  59. 4
      application/src/main/data/json/system/widget_types/range_chart.json
  60. 4
      application/src/main/data/json/system/widget_types/route_map.json
  61. 4
      application/src/main/data/json/system/widget_types/state_chart.json
  62. 4
      application/src/main/data/json/system/widget_types/time_series_chart.json
  63. 4
      application/src/main/data/json/system/widget_types/trip_map.json
  64. 10
      application/src/main/data/upgrade/basic/schema_update.sql
  65. 7
      application/src/main/java/org/thingsboard/server/actors/calculatedField/CalculatedFieldEntityActor.java
  66. 10
      application/src/main/java/org/thingsboard/server/actors/calculatedField/CalculatedFieldEntityMessageProcessor.java
  67. 7
      application/src/main/java/org/thingsboard/server/actors/calculatedField/CalculatedFieldManagerActor.java
  68. 24
      application/src/main/java/org/thingsboard/server/actors/calculatedField/CalculatedFieldManagerMessageProcessor.java
  69. 10
      application/src/main/java/org/thingsboard/server/actors/tenant/TenantActor.java
  70. 2
      application/src/main/java/org/thingsboard/server/config/ThingsboardSecurityConfiguration.java
  71. 9
      application/src/main/java/org/thingsboard/server/service/cf/ctx/state/CalculatedFieldCtx.java
  72. 5
      application/src/main/java/org/thingsboard/server/service/cf/ctx/state/KafkaCalculatedFieldStateService.java
  73. 5
      application/src/main/java/org/thingsboard/server/service/edqs/DefaultEdqsApiService.java
  74. 14
      application/src/main/java/org/thingsboard/server/service/edqs/DefaultEdqsService.java
  75. 14
      application/src/main/java/org/thingsboard/server/service/edqs/KafkaEdqsSyncService.java
  76. 5
      application/src/main/java/org/thingsboard/server/service/install/DefaultSystemDataLoaderService.java
  77. 20
      application/src/main/java/org/thingsboard/server/service/queue/DefaultTbCalculatedFieldConsumerService.java
  78. 17
      application/src/main/java/org/thingsboard/server/service/queue/DefaultTbRuleEngineConsumerService.java
  79. 93
      application/src/main/java/org/thingsboard/server/service/queue/processing/AbstractPartitionBasedConsumerService.java
  80. 7
      application/src/main/java/org/thingsboard/server/service/subscription/DefaultTbEntityDataSubscriptionService.java
  81. 16
      application/src/main/resources/thingsboard.yml
  82. 3
      application/src/test/java/org/thingsboard/server/controller/EntityQueryControllerTest.java
  83. 2
      application/src/test/java/org/thingsboard/server/service/entitiy/EdqsEntityServiceTest.java
  84. 19
      application/src/test/java/org/thingsboard/server/service/entitiy/EntityServiceTest.java
  85. 2
      common/data/src/main/java/org/thingsboard/server/common/data/edqs/DataPoint.java
  86. 6
      common/edqs/src/main/java/org/thingsboard/server/edqs/data/CustomerData.java
  87. 6
      common/edqs/src/main/java/org/thingsboard/server/edqs/data/dp/AbstractDataPoint.java
  88. 5
      common/edqs/src/main/java/org/thingsboard/server/edqs/data/dp/BoolDataPoint.java
  89. 5
      common/edqs/src/main/java/org/thingsboard/server/edqs/data/dp/DoubleDataPoint.java
  90. 6
      common/edqs/src/main/java/org/thingsboard/server/edqs/data/dp/LongDataPoint.java
  91. 35
      common/edqs/src/main/java/org/thingsboard/server/edqs/processor/EdqsProcessor.java
  92. 40
      common/edqs/src/main/java/org/thingsboard/server/edqs/processor/EdqsProducer.java
  93. 3
      common/edqs/src/main/java/org/thingsboard/server/edqs/query/SortableEntityData.java
  94. 3
      common/edqs/src/main/java/org/thingsboard/server/edqs/query/processor/AbstractQueryProcessor.java
  95. 3
      common/edqs/src/main/java/org/thingsboard/server/edqs/query/processor/AbstractRelationQueryProcessor.java
  96. 30
      common/edqs/src/main/java/org/thingsboard/server/edqs/repo/TenantRepo.java
  97. 7
      common/edqs/src/main/java/org/thingsboard/server/edqs/state/EdqsPartitionService.java
  98. 60
      common/edqs/src/main/java/org/thingsboard/server/edqs/state/KafkaEdqsStateService.java
  99. 5
      common/edqs/src/main/java/org/thingsboard/server/edqs/state/LocalEdqsStateService.java
  100. 21
      common/edqs/src/main/java/org/thingsboard/server/edqs/util/RepositoryUtils.java

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

@ -330,7 +330,7 @@
}
]
}]]></tb:metadata>
<path d="m25 106c0-2.761 2.2386-5 5-5h210c2.761 0 5 2.239 5 5v266c0 2.761-2.239 5-5 5h-210c-2.7614 0-5-2.239-5-5v-266z" fill="#fff" stroke="#1A1A1A" stroke-width="2" tb:tag="background"/><rect x="143" y="146" width="86" height="36" rx="1" fill="#999" stroke="#1A1A1A" stroke-width="2"/><rect x="143" y="254" width="86" height="36" rx="1" fill="#999" stroke="#1A1A1A" stroke-width="2"/><rect x="143" y="200" width="86" height="36" rx="1" fill="#999" stroke="#1A1A1A" stroke-width="2"/><rect x="143" y="308" width="86" height="36" rx="1" fill="#999" stroke="#1A1A1A" stroke-width="2"/><path d="m155 6c0-2.7614 2.239-5 5-5h210c2.761 0 5 2.2386 5 5v366c0 2.761-2.239 5-5 5h-210c-2.761 0-5-2.239-5-5v-366z" fill="#fff" stroke="#1A1A1A" stroke-width="2" tb:tag="background"/><rect x="269" y="57" width="86" height="36" rx="1" fill="#999" stroke="#1A1A1A" stroke-width="2"/><rect x="269" y="165" width="86" height="36" rx="1" fill="#999" stroke="#1A1A1A" stroke-width="2"/><rect x="269" y="111" width="86" height="36" rx="1" fill="#999" stroke="#1A1A1A" stroke-width="2"/><rect x="269" y="219" width="86" height="36" rx="1" fill="#999" stroke="#1A1A1A" stroke-width="2"/><rect x="175" y="57" width="86" height="36" rx="1" fill="#999" stroke="#1A1A1A" stroke-width="2"/><rect x="175" y="165" width="86" height="36" rx="1" fill="#999" stroke="#1A1A1A" stroke-width="2"/><rect x="175" y="111" width="86" height="36" rx="1" fill="#999" stroke="#1A1A1A" stroke-width="2"/><rect x="175" y="219" width="86" height="36" rx="1" fill="#999" stroke="#1A1A1A" stroke-width="2"/><rect x="216" y="286" width="98" height="91" rx="1" fill="#999" stroke="#1A1A1A" stroke-width="2"/><rect x="49" y="146" width="86" height="36" rx="1" fill="#999" stroke="#1A1A1A" stroke-width="2"/><rect x="49" y="254" width="86" height="36" rx="1" fill="#999" stroke="#1A1A1A" stroke-width="2"/><rect x="49" y="200" width="86" height="36" rx="1" fill="#999" stroke="#1A1A1A" stroke-width="2"/><rect x="49" y="308" width="86" height="36" rx="1" fill="#999" stroke="#1A1A1A" stroke-width="2"/><rect x="1" y="377" width="398" height="22" rx="5" fill="#fff" stroke="#1A1A1A" stroke-width="2" tb:tag="background"/><path d="m134.53 0s-134.53 0-134.53 67v328.36c0 2.6512 3.5818 4.6403 8 4.6403h384c4.418 0 8-1.9892 8-4.6403v-328.36c0-67-132.14-67-132.14-67h-67.86zm134.14 81.2c-2.5774 0-4.6666 1.2536-4.6666 2.8v300.4c0 1.5464 2.0894 2.8 4.6666 2.8h29.332c2.5774 0 4.6666-1.2536 4.6666-2.8v-300.4c0-1.5464-2.0894-2.8-4.6666-2.8z" fill-opacity="0" style="stroke-width:1.4784" tb:tag="clickArea"/><g transform="translate(0,316)" fill="#d12730" style="display: none;" tb:tag="critical">
<path d="m25 106c0-2.761 2.2386-5 5-5h210c2.761 0 5 2.239 5 5v266c0 2.761-2.239 5-5 5h-210c-2.7614 0-5-2.239-5-5v-266z" fill="#fff" stroke="#1A1A1A" stroke-width="2" tb:tag="background"/><rect x="143" y="146" width="86" height="36" rx="1" fill="#999" stroke="#1A1A1A" stroke-width="2"/><rect x="143" y="254" width="86" height="36" rx="1" fill="#999" stroke="#1A1A1A" stroke-width="2"/><rect x="143" y="200" width="86" height="36" rx="1" fill="#999" stroke="#1A1A1A" stroke-width="2"/><rect x="143" y="308" width="86" height="36" rx="1" fill="#999" stroke="#1A1A1A" stroke-width="2"/><path d="m155 6c0-2.7614 2.239-5 5-5h210c2.761 0 5 2.2386 5 5v366c0 2.761-2.239 5-5 5h-210c-2.761 0-5-2.239-5-5v-366z" fill="#fff" stroke="#1A1A1A" stroke-width="2" tb:tag="background"/><rect x="269" y="57" width="86" height="36" rx="1" fill="#999" stroke="#1A1A1A" stroke-width="2"/><rect x="269" y="165" width="86" height="36" rx="1" fill="#999" stroke="#1A1A1A" stroke-width="2"/><rect x="269" y="111" width="86" height="36" rx="1" fill="#999" stroke="#1A1A1A" stroke-width="2"/><rect x="269" y="219" width="86" height="36" rx="1" fill="#999" stroke="#1A1A1A" stroke-width="2"/><rect x="175" y="57" width="86" height="36" rx="1" fill="#999" stroke="#1A1A1A" stroke-width="2"/><rect x="175" y="165" width="86" height="36" rx="1" fill="#999" stroke="#1A1A1A" stroke-width="2"/><rect x="175" y="111" width="86" height="36" rx="1" fill="#999" stroke="#1A1A1A" stroke-width="2"/><rect x="175" y="219" width="86" height="36" rx="1" fill="#999" stroke="#1A1A1A" stroke-width="2"/><rect x="216" y="286" width="98" height="91" rx="1" fill="#999" stroke="#1A1A1A" stroke-width="2"/><rect x="49" y="146" width="86" height="36" rx="1" fill="#999" stroke="#1A1A1A" stroke-width="2"/><rect x="49" y="254" width="86" height="36" rx="1" fill="#999" stroke="#1A1A1A" stroke-width="2"/><rect x="49" y="200" width="86" height="36" rx="1" fill="#999" stroke="#1A1A1A" stroke-width="2"/><rect x="49" y="308" width="86" height="36" rx="1" fill="#999" stroke="#1A1A1A" stroke-width="2"/><rect x="1" y="377" width="398" height="22" rx="5" fill="#fff" stroke="#1A1A1A" stroke-width="2" tb:tag="background"/><path d="m134.53 0s-134.53 0-134.53 67v328.36c0 2.6512 3.5818 4.6403 8 4.6403h384c4.418 0 8-1.9892 8-4.6403v-328.36c0-67-132.14-67-132.14-67h-67.86zm134.14 81.2c-2.5774 0-4.6666 1.2536-4.6666 2.8v300.4c0 1.5464 2.0894 2.8 4.6666 2.8h29.332c2.5774 0 4.6666-1.2536 4.6666-2.8v-300.4c0-1.5464-2.0894-2.8-4.6666-2.8z" fill-opacity="0" fill="#000" tb:tag="clickArea"/><g transform="translate(0,316)" fill="#d12730" style="display: none;" tb:tag="critical">
<rect width="84" height="84" rx="4" fill="#fff" style=""/>
<rect width="84" height="84" rx="4" style=""/>
<rect x="2" y="2" width="80" height="80" rx="2" stroke="#000" stroke-opacity=".87" stroke-width="4" style=""/>

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 15 KiB

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

@ -332,7 +332,7 @@
<path d="m77.22 69 1.6-8h42.36l1.6 8h-45.56z"/>
<path d="m77.117 69h45.742c0.108 0.2569 0.244 0.5047 0.385 0.7358 0.342 0.5586 0.824 1.1869 1.403 1.8699 1.16 1.3677 2.802 3.0619 4.738 5.0193 0.519 0.5244 1.059 1.0689 1.62 1.6328 3.641 3.6659 8.098 8.154 12.557 13.274 10.326 11.856 20.438 26.862 20.438 42.468 0 21.266-7.121 37.489-18.622 48.399-11.511 10.92-27.5 16.601-45.378 16.601-17.878 0-33.867-5.681-45.378-16.601-11.502-10.91-18.622-27.133-18.622-48.399 0-15.606 10.106-30.612 20.426-42.468 4.456-5.1195 8.9107-9.6073 12.55-13.273 0.5601-0.5643 1.1009-1.1091 1.6194-1.6337 1.9344-1.9574 3.576-3.6516 4.735-5.0193 0.5788-0.683 1.0604-1.3114 1.4022-1.87 0.1413-0.231 0.2771-0.4787 0.3847-0.7355z"/>
<path d="m80.13 5.9751c1.5245-3.049 4.6409-4.9751 8.0498-4.9751h23.64c3.409 0 6.525 1.926 8.05 4.9751l6.18 12.361c0.625 1.2497 0.95 2.6277 0.95 4.0249v38.639h-54v-38.639c0-1.3972 0.3253-2.7752 0.9502-4.0249l6.1803-12.361z"/>
</g><path d="m73 53h54" stroke="#1A1A1A" stroke-width="2"/><path d="m73 21h54" stroke="#1A1A1A" stroke-width="2"/><path d="m67.265 0s-67.265 0-67.265 33.5v164.18c0 1.3256 1.7909 2.3202 4 2.3202h192c2.209 0 4-0.9946 4-2.3202v-164.18c0-33.5-66.07-33.5-66.07-33.5h-33.93zm67.07 40.6c-1.2887 0-2.3333 0.6268-2.3333 1.4v150.2c0 0.7732 1.0447 1.4 2.3333 1.4h14.666c1.2887 0 2.3333-0.6268 2.3333-1.4v-150.2c0-0.7732-1.0447-1.4-2.3333-1.4z" fill-opacity="0" tb:tag="clickArea"/><g fill="#d12730" style="display: none;" tb:tag="critical">
</g><path d="m73 53h54" stroke="#1A1A1A" stroke-width="2"/><path d="m73 21h54" stroke="#1A1A1A" stroke-width="2"/><path d="m67.265 0s-67.265 0-67.265 33.5v164.18c0 1.3256 1.7909 2.3202 4 2.3202h192c2.209 0 4-0.9946 4-2.3202v-164.18c0-33.5-66.07-33.5-66.07-33.5h-33.93zm67.07 40.6c-1.2887 0-2.3333 0.6268-2.3333 1.4v150.2c0 0.7732 1.0447 1.4 2.3333 1.4h14.666c1.2887 0 2.3333-0.6268 2.3333-1.4v-150.2c0-0.7732-1.0447-1.4-2.3333-1.4z" fill-opacity="0" fill="#000" 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=""/>

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 14 KiB

2
application/src/main/data/json/system/scada_symbols/conical-tank.svg

@ -371,7 +371,7 @@
<rect x="841" y="957" width="100" height="29" rx="7" fill="#fff" style=""/>
<rect x="841" y="957" width="100" height="29" rx="7" fill="url(#paint638_linear_2901_184325)" style=""/>
<rect x="842.5" y="958.5" width="97" height="26" rx="5.5" stroke="#000" stroke-opacity=".12" stroke-width="3" style=""/>
</g><path d="m336.32 0s-336.32 0-336.32 167.5v820.9c0 6.628 8.9543 11.601 20 11.601h960c11.045 0 20-4.973 20-11.601v-820.9c0-167.5-330.35-167.5-330.35-167.5h-169.65zm335.35 203c-6.4433 0-11.667 3.134-11.667 7v751c0 3.866 5.2233 7 11.667 7h73.333c6.4433 0 11.667-3.134 11.667-7v-751c0-3.866-5.2233-7-11.667-7z" fill="#000" fill-opacity="0" style="stroke-width:1.6667" tb:tag="clickArea"/><defs>
</g><path d="m336.32 0s-336.32 0-336.32 167.5v820.9c0 6.628 8.9543 11.601 20 11.601h960c11.045 0 20-4.973 20-11.601v-820.9c0-167.5-330.35-167.5-330.35-167.5h-169.65zm335.35 203c-6.4433 0-11.667 3.134-11.667 7v751c0 3.866 5.2233 7 11.667 7h73.333c6.4433 0 11.667-3.134 11.667-7v-751c0-3.866-5.2233-7-11.667-7z" fill="#000" fill-opacity="0" tb:tag="clickArea"/><defs>
<linearGradient id="paint0_linear_2901_184325" x1="1e3" x2="2.2785" y1="818.55" y2="867.09" gradientUnits="userSpaceOnUse">
<stop stop-color="#020202" stop-opacity=".35" offset="0"/>
<stop stop-color="#020202" stop-opacity=".12" offset=".23574"/>

Before

Width:  |  Height:  |  Size: 85 KiB

After

Width:  |  Height:  |  Size: 85 KiB

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

@ -332,7 +332,7 @@
<g fill="#fff" stroke="#1A1A1A" stroke-width="2" tb:tag="background">
<path d="m21 240.65c0-1.409 0.5943-2.752 1.6366-3.699l104-94.546c1.907-1.734 4.819-1.734 6.726 0l104 94.546c1.043 0.947 1.637 2.29 1.637 3.699v131.35c0 2.761-2.239 5-5 5h-208c-2.7614 0-5-2.239-5-5v-131.35z"/>
<path d="m130.68 141.26-0.678-0.626-0.678 0.626-112.38 103.74h-14.385l127.44-117.64 127.44 117.64h-14.384l-112.38-103.74z"/>
</g><rect x="56" y="307" width="44" height="70" rx="1" fill="#999" stroke="#1A1A1A" stroke-width="2"/><path d="m80 240c0-0.552 0.4477-1 1-1h18c0.5523 0 1 0.448 1 1v44c0 0.552-0.4477 1-1 1h-18c-0.5523 0-1-0.448-1-1v-44z" fill="#999" stroke="#1A1A1A" stroke-width="2"/><path d="m170 240c0-0.552 0.448-1 1-1h18c0.552 0 1 0.448 1 1v44c0 0.552-0.448 1-1 1h-18c-0.552 0-1-0.448-1-1v-44z" fill="#999" stroke="#1A1A1A" stroke-width="2"/><path d="m170 308c0-0.552 0.448-1 1-1h18c0.552 0 1 0.448 1 1v44c0 0.552-0.448 1-1 1h-18c-0.552 0-1-0.448-1-1v-44z" fill="#999" stroke="#1A1A1A" stroke-width="2"/><path d="m56 240c0-0.552 0.4477-1 1-1h18c0.5523 0 1 0.448 1 1v44c0 0.552-0.4477 1-1 1h-18c-0.5523 0-1-0.448-1-1v-44z" fill="#999" stroke="#1A1A1A" stroke-width="2"/><path d="m146 240c0-0.552 0.448-1 1-1h18c0.552 0 1 0.448 1 1v44c0 0.552-0.448 1-1 1h-18c-0.552 0-1-0.448-1-1v-44z" fill="#999" stroke="#1A1A1A" stroke-width="2"/><rect transform="rotate(-90 194 285)" x="194" y="285" width="46" height="20" rx="1" fill="#999" stroke="#1A1A1A" stroke-width="2"/><path d="m146 308c0-0.552 0.448-1 1-1h18c0.552 0 1 0.448 1 1v44c0 0.552-0.448 1-1 1h-18c-0.552 0-1-0.448-1-1v-44z" fill="#999" stroke="#1A1A1A" stroke-width="2"/><rect transform="rotate(-90 194 353)" x="194" y="353" width="46" height="20" rx="1" fill="#999" stroke="#1A1A1A" stroke-width="2"/><path d="m129.26 178.32c0.397-0.442 1.089-0.442 1.486 0l0.744-0.669-0.744 0.669 13.51 15.01c0.579 0.644 0.122 1.669-0.744 1.669h-27.018c-0.866 0-1.323-1.025-0.744-1.669l13.51-15.01z" fill="#999" stroke="#1A1A1A" stroke-width="2"/><path d="m425 176v1.804l1.53-0.956 60.94-38.088c0.666-0.416 1.53 0.063 1.53 0.848v37.392h85c2.761 0 5 2.239 5 5v190c0 2.761-2.239 5-5 5h-217c-2.761 0-5-2.239-5-5v-194.8c0-0.369 0.204-0.709 0.529-0.882l71-37.867c0.667-0.355 1.471 0.127 1.471 0.882v36.667z" fill="#fff" stroke="#1A1A1A" stroke-width="2" tb:tag="background"/><path d="m519.88 19.938c0.033-0.527 0.47-0.9376 0.998-0.9376h30.242c0.528 0 0.965 0.4106 0.998 0.9376l9.75 156c0.036 0.575-0.421 1.062-0.998 1.062h-49.742c-0.577 0-1.034-0.487-0.998-1.062l9.75-156z" fill="#999" stroke="#1A1A1A" stroke-width="2"/><rect x="429" y="236" width="38" height="38" rx="1" fill="#999" stroke="#1A1A1A" stroke-width="2"/><rect x="385" y="236" width="38" height="38" rx="1" fill="#999" stroke="#1A1A1A" stroke-width="2"/><rect x="429" y="280" width="38" height="38" rx="1" fill="#999" stroke="#1A1A1A" stroke-width="2"/><rect x="385" y="280" width="38" height="38" rx="1" fill="#999" stroke="#1A1A1A" stroke-width="2"/><rect x="473" y="236" width="38" height="38" rx="1" fill="#999" stroke="#1A1A1A" stroke-width="2"/><rect x="473" y="280" width="38" height="38" rx="1" fill="#999" stroke="#1A1A1A" stroke-width="2"/><rect x="517" y="236" width="38" height="38" rx="1" fill="#999" stroke="#1A1A1A" stroke-width="2"/><rect x="517" y="280" width="38" height="38" rx="1" fill="#999" stroke="#1A1A1A" stroke-width="2"/><path d="m190 6c0-2.7614 2.239-5 5-5h210c2.761 0 5 2.2386 5 5v366c0 2.761-2.239 5-5 5h-210c-2.761 0-5-2.239-5-5v-366z" fill="#fff" stroke="#1A1A1A" stroke-width="2" tb:tag="background"/><rect x="304" y="57" width="86" height="36" rx="1" fill="#999" stroke="#1A1A1A" stroke-width="2"/><rect x="304" y="165" width="86" height="36" rx="1" fill="#999" stroke="#1A1A1A" stroke-width="2"/><rect x="304" y="111" width="86" height="36" rx="1" fill="#999" stroke="#1A1A1A" stroke-width="2"/><rect x="304" y="219" width="86" height="36" rx="1" fill="#999" stroke="#1A1A1A" stroke-width="2"/><rect x="210" y="57" width="86" height="36" rx="1" fill="#999" stroke="#1A1A1A" stroke-width="2"/><rect x="210" y="165" width="86" height="36" rx="1" fill="#999" stroke="#1A1A1A" stroke-width="2"/><rect x="210" y="111" width="86" height="36" rx="1" fill="#999" stroke="#1A1A1A" stroke-width="2"/><rect x="210" y="219" width="86" height="36" rx="1" fill="#999" stroke="#1A1A1A" stroke-width="2"/><rect x="251" y="286" width="98" height="91" rx="1" fill="#999" stroke="#1A1A1A" stroke-width="2"/><rect x="1" y="377" width="598" height="22" rx="5" fill="#fff" stroke="#1A1A1A" stroke-width="2" tb:tag="background"/><path d="m201.8 0s-201.8 0-201.8 67v328.36c0 2.6512 5.3727 4.6403 12 4.6403h576c6.627 0 12-1.9892 12-4.6403v-328.36c0-67-198.21-67-198.21-67h-101.79zm201.21 81.2c-3.8661 0-6.9999 1.2536-6.9999 2.8v300.4c0 1.5464 3.1341 2.8 6.9999 2.8h43.998c3.8661 0 6.9999-1.2536 6.9999-2.8v-300.4c0-1.5464-3.1341-2.8-6.9999-2.8z" fill-opacity="0" style="stroke-width:1.8107" tb:tag="clickArea"/><g transform="translate(0,316)" fill="#d12730" style="display: none;" tb:tag="critical">
</g><rect x="56" y="307" width="44" height="70" rx="1" fill="#999" stroke="#1A1A1A" stroke-width="2"/><path d="m80 240c0-0.552 0.4477-1 1-1h18c0.5523 0 1 0.448 1 1v44c0 0.552-0.4477 1-1 1h-18c-0.5523 0-1-0.448-1-1v-44z" fill="#999" stroke="#1A1A1A" stroke-width="2"/><path d="m170 240c0-0.552 0.448-1 1-1h18c0.552 0 1 0.448 1 1v44c0 0.552-0.448 1-1 1h-18c-0.552 0-1-0.448-1-1v-44z" fill="#999" stroke="#1A1A1A" stroke-width="2"/><path d="m170 308c0-0.552 0.448-1 1-1h18c0.552 0 1 0.448 1 1v44c0 0.552-0.448 1-1 1h-18c-0.552 0-1-0.448-1-1v-44z" fill="#999" stroke="#1A1A1A" stroke-width="2"/><path d="m56 240c0-0.552 0.4477-1 1-1h18c0.5523 0 1 0.448 1 1v44c0 0.552-0.4477 1-1 1h-18c-0.5523 0-1-0.448-1-1v-44z" fill="#999" stroke="#1A1A1A" stroke-width="2"/><path d="m146 240c0-0.552 0.448-1 1-1h18c0.552 0 1 0.448 1 1v44c0 0.552-0.448 1-1 1h-18c-0.552 0-1-0.448-1-1v-44z" fill="#999" stroke="#1A1A1A" stroke-width="2"/><rect transform="rotate(-90 194 285)" x="194" y="285" width="46" height="20" rx="1" fill="#999" stroke="#1A1A1A" stroke-width="2"/><path d="m146 308c0-0.552 0.448-1 1-1h18c0.552 0 1 0.448 1 1v44c0 0.552-0.448 1-1 1h-18c-0.552 0-1-0.448-1-1v-44z" fill="#999" stroke="#1A1A1A" stroke-width="2"/><rect transform="rotate(-90 194 353)" x="194" y="353" width="46" height="20" rx="1" fill="#999" stroke="#1A1A1A" stroke-width="2"/><path d="m129.26 178.32c0.397-0.442 1.089-0.442 1.486 0l0.744-0.669-0.744 0.669 13.51 15.01c0.579 0.644 0.122 1.669-0.744 1.669h-27.018c-0.866 0-1.323-1.025-0.744-1.669l13.51-15.01z" fill="#999" stroke="#1A1A1A" stroke-width="2"/><path d="m425 176v1.804l1.53-0.956 60.94-38.088c0.666-0.416 1.53 0.063 1.53 0.848v37.392h85c2.761 0 5 2.239 5 5v190c0 2.761-2.239 5-5 5h-217c-2.761 0-5-2.239-5-5v-194.8c0-0.369 0.204-0.709 0.529-0.882l71-37.867c0.667-0.355 1.471 0.127 1.471 0.882v36.667z" fill="#fff" stroke="#1A1A1A" stroke-width="2" tb:tag="background"/><path d="m519.88 19.938c0.033-0.527 0.47-0.9376 0.998-0.9376h30.242c0.528 0 0.965 0.4106 0.998 0.9376l9.75 156c0.036 0.575-0.421 1.062-0.998 1.062h-49.742c-0.577 0-1.034-0.487-0.998-1.062l9.75-156z" fill="#999" stroke="#1A1A1A" stroke-width="2"/><rect x="429" y="236" width="38" height="38" rx="1" fill="#999" stroke="#1A1A1A" stroke-width="2"/><rect x="385" y="236" width="38" height="38" rx="1" fill="#999" stroke="#1A1A1A" stroke-width="2"/><rect x="429" y="280" width="38" height="38" rx="1" fill="#999" stroke="#1A1A1A" stroke-width="2"/><rect x="385" y="280" width="38" height="38" rx="1" fill="#999" stroke="#1A1A1A" stroke-width="2"/><rect x="473" y="236" width="38" height="38" rx="1" fill="#999" stroke="#1A1A1A" stroke-width="2"/><rect x="473" y="280" width="38" height="38" rx="1" fill="#999" stroke="#1A1A1A" stroke-width="2"/><rect x="517" y="236" width="38" height="38" rx="1" fill="#999" stroke="#1A1A1A" stroke-width="2"/><rect x="517" y="280" width="38" height="38" rx="1" fill="#999" stroke="#1A1A1A" stroke-width="2"/><path d="m190 6c0-2.7614 2.239-5 5-5h210c2.761 0 5 2.2386 5 5v366c0 2.761-2.239 5-5 5h-210c-2.761 0-5-2.239-5-5v-366z" fill="#fff" stroke="#1A1A1A" stroke-width="2" tb:tag="background"/><rect x="304" y="57" width="86" height="36" rx="1" fill="#999" stroke="#1A1A1A" stroke-width="2"/><rect x="304" y="165" width="86" height="36" rx="1" fill="#999" stroke="#1A1A1A" stroke-width="2"/><rect x="304" y="111" width="86" height="36" rx="1" fill="#999" stroke="#1A1A1A" stroke-width="2"/><rect x="304" y="219" width="86" height="36" rx="1" fill="#999" stroke="#1A1A1A" stroke-width="2"/><rect x="210" y="57" width="86" height="36" rx="1" fill="#999" stroke="#1A1A1A" stroke-width="2"/><rect x="210" y="165" width="86" height="36" rx="1" fill="#999" stroke="#1A1A1A" stroke-width="2"/><rect x="210" y="111" width="86" height="36" rx="1" fill="#999" stroke="#1A1A1A" stroke-width="2"/><rect x="210" y="219" width="86" height="36" rx="1" fill="#999" stroke="#1A1A1A" stroke-width="2"/><rect x="251" y="286" width="98" height="91" rx="1" fill="#999" stroke="#1A1A1A" stroke-width="2"/><rect x="1" y="377" width="598" height="22" rx="5" fill="#fff" stroke="#1A1A1A" stroke-width="2" tb:tag="background"/><path d="m201.8 0s-201.8 0-201.8 67v328.36c0 2.6512 5.3727 4.6403 12 4.6403h576c6.627 0 12-1.9892 12-4.6403v-328.36c0-67-198.21-67-198.21-67h-101.79zm201.21 81.2c-3.8661 0-6.9999 1.2536-6.9999 2.8v300.4c0 1.5464 3.1341 2.8 6.9999 2.8h43.998c3.8661 0 6.9999-1.2536 6.9999-2.8v-300.4c0-1.5464-3.1341-2.8-6.9999-2.8z" fill-opacity="0" fill="#000" tb:tag="clickArea"/><g transform="translate(0,316)" fill="#d12730" style="display: none;" tb:tag="critical">
<rect width="84" height="84" rx="4" fill="#fff" style=""/>
<rect width="84" height="84" rx="4" style=""/>
<rect x="2" y="2" width="80" height="80" rx="2" stroke="#000" stroke-opacity=".87" stroke-width="4" style=""/>

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 17 KiB

2
application/src/main/data/json/system/scada_symbols/dynamic-horizontal-scale-hp.svg

@ -791,5 +791,5 @@
<rect transform="scale(-1,1)" x="-732.5" y="183.5" width="81" height="41" fill="#666" tb:tag="highCriticalScale"/>
</g><g transform="translate(400)" style="display: none;" tb:tag="target">
<rect transform="rotate(45)" x="201.8" y="64.66" width="22" height="22" fill="#dedede" stroke="#000" stroke-width="2" tb:tag="targetBackground" style=""/>
</g><path d="m269.06 0s-269.06 0-269.06 67v328.36c0 2.6512 7.1634 4.6404 16 4.6404h768c8.836 0 16-1.9892 16-4.6404v-328.36c0-67-264.28-67-264.28-67h-135.72zm268.28 81.2c-5.1546 0-9.3334 1.2536-9.3334 2.8v300.4c0 1.5464 4.1786 2.8 9.3334 2.8h58.666c5.1546 0 9.3334-1.2536 9.3334-2.8v-300.4c0-1.5464-4.1786-2.8-9.3334-2.8z" fill="#000" fill-opacity="0" style="stroke-width:.7303" tb:tag="clickArea"/>
</g><path d="m269.06 0s-269.06 0-269.06 67v328.36c0 2.6512 7.1634 4.6404 16 4.6404h768c8.836 0 16-1.9892 16-4.6404v-328.36c0-67-264.28-67-264.28-67h-135.72zm268.28 81.2c-5.1546 0-9.3334 1.2536-9.3334 2.8v300.4c0 1.5464 4.1786 2.8 9.3334 2.8h58.666c5.1546 0 9.3334-1.2536 9.3334-2.8v-300.4c0-1.5464-4.1786-2.8-9.3334-2.8z" fill="#000" fill-opacity="0" tb:tag="clickArea"/>
</svg>

Before

Width:  |  Height:  |  Size: 30 KiB

After

Width:  |  Height:  |  Size: 30 KiB

2
application/src/main/data/json/system/scada_symbols/dynamic-vertical-scale-hp.svg

@ -791,5 +791,5 @@
<text x="223.60547" y="739.125" fill="#002878" font-family="Roboto" font-size="60px" font-weight="400" tb:tag="value" xml:space="preserve"><tspan dominant-baseline="middle">26</tspan></text>
</g><g transform="translate(0,-400)" style="display: none;" tb:tag="target">
<rect transform="rotate(-45)" x="-379.76" y="636.31" width="22" height="22" fill="#dedede" stroke="#000" stroke-width="2" tb:tag="targetBackground" style=""/>
</g><path d="m134.53 0s-134.53 0-134.53 134v656.72c0 5.3024 3.5817 9.2808 8 9.2808h384c4.418 0 8-3.9784 8-9.2808v-656.72c0-134-132.14-134-132.14-134h-67.86zm134.14 162.4c-2.5773 0-4.6667 2.5072-4.6667 5.6v600.8c0 3.0928 2.0893 5.6 4.6667 5.6h29.333c2.5773 0 4.6667-2.5072 4.6667-5.6v-600.8c0-3.0928-2.0893-5.6-4.6667-5.6z" fill="#000" fill-opacity="0" style="stroke-width:.7303" tb:tag="clickArea"/>
</g><path d="m134.53 0s-134.53 0-134.53 134v656.72c0 5.3024 3.5817 9.2808 8 9.2808h384c4.418 0 8-3.9784 8-9.2808v-656.72c0-134-132.14-134-132.14-134h-67.86zm134.14 162.4c-2.5773 0-4.6667 2.5072-4.6667 5.6v600.8c0 3.0928 2.0893 5.6 4.6667 5.6h29.333c2.5773 0 4.6667-2.5072 4.6667-5.6v-600.8c0-3.0928-2.0893-5.6-4.6667-5.6z" fill="#000" fill-opacity="0" tb:tag="clickArea"/>
</svg>

Before

Width:  |  Height:  |  Size: 30 KiB

After

Width:  |  Height:  |  Size: 30 KiB

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

@ -318,7 +318,7 @@
}]]></tb:metadata>
<rect x="1" y="1" width="398" height="598" rx="3" fill="#fff" stroke="#1a1a1a" stroke-width="2" tb:tag="background"/><path d="m150.82 344.75c-1.541 0-2.503-1.669-1.731-3.002l49.176-84.942c0.771-1.33 2.692-1.33 3.462 0l49.177 84.942c0.772 1.333-0.19 3.002-1.731 3.002h-98.353z" stroke="#D12730" stroke-width="8" tb:tag="triangle"/><g transform="translate(200,310)" tb:tag="icon">
<path d="m4.3731-15.914-16.841 15.085c-1.041 0.943-0.455 2.682 0.943 2.812l13.151 1.268-7.884 10.989c-0.358 0.504-0.309 1.203 0.13 1.642 0.487 0.488 1.251 0.504 1.755 0.033l16.841-15.086c1.041-0.943 0.455-2.682-0.943-2.812l-13.151-1.268 7.885-10.989c0.357-0.504 0.308-1.203-0.131-1.642-0.487-0.488-1.251-0.504-1.755-0.032z" fill="#1a1a1a"/>
</g><path d="m134.53 0s-134.53 0-134.53 100.5v492.54c0 3.9768 3.5818 6.9606 8 6.9606h384c4.418 0 8-2.9838 8-6.9606v-492.54c0-100.5-132.14-100.5-132.14-100.5h-67.86zm134.14 121.8c-2.5774 0-4.6666 1.8804-4.6666 4.2v450.6c0 2.3196 2.0894 4.2 4.6666 4.2h29.332c2.5774 0 4.6666-1.8804 4.6666-4.2v-450.6c0-2.3196-2.0894-4.2-4.6666-4.2z" fill-opacity="0" tb:tag="clickArea"/><g fill="#d12730" style="display: none;" tb:tag="critical">
</g><path d="m134.53 0s-134.53 0-134.53 100.5v492.54c0 3.9768 3.5818 6.9606 8 6.9606h384c4.418 0 8-2.9838 8-6.9606v-492.54c0-100.5-132.14-100.5-132.14-100.5h-67.86zm134.14 121.8c-2.5774 0-4.6666 1.8804-4.6666 4.2v450.6c0 2.3196 2.0894 4.2 4.6666 4.2h29.332c2.5774 0 4.6666-1.8804 4.6666-4.2v-450.6c0-2.3196-2.0894-4.2-4.6666-4.2z" fill-opacity="0" fill="#000" 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=""/>

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 13 KiB

2
application/src/main/data/json/system/scada_symbols/filter-hp.svg

@ -273,7 +273,7 @@
}
]
}]]></tb:metadata>
<path d="m19.382 177.15c-0.0794-1.362-0.71139-2.633-1.7498-3.518l-9.0296-7.697c-4.0474-3.45-6.4624-8.4-6.6282-13.706-0.65056-20.807-1.9624-74.2 0.297-110.67 0.77777-12.553 2.4266-30.326 3.1467-37.866 0.1463-1.5318 1.4324-2.6953 2.9818-2.6953h183.2c1.549 0 2.835 1.1635 2.982 2.6953 0.71999 7.5402 2.369 25.314 3.146 37.866 2.26 36.465 0.94799 89.858 0.297 110.67-0.165 5.306-2.58 10.256-6.6279 13.706l-9.0289 7.697c-1.039 0.885-1.671 2.156-1.75 3.518l-8.5699 147.01c-0.589 10.108-5.361 19.513-13.17 25.958-34.184 28.21-83.573 28.21-117.76 0-7.8087-6.445-12.581-15.85-13.17-25.958z" fill="#fff" stroke="#000" stroke-width="2" tb:tag="background"/><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" style="stroke-width:1.4142" tb:tag="clickArea"/><g transform="translate(0,316)" fill="#d12730" style="display: none;" tb:tag="critical">
<path d="m19.382 177.15c-0.0794-1.362-0.71139-2.633-1.7498-3.518l-9.0296-7.697c-4.0474-3.45-6.4624-8.4-6.6282-13.706-0.65056-20.807-1.9624-74.2 0.297-110.67 0.77777-12.553 2.4266-30.326 3.1467-37.866 0.1463-1.5318 1.4324-2.6953 2.9818-2.6953h183.2c1.549 0 2.835 1.1635 2.982 2.6953 0.71999 7.5402 2.369 25.314 3.146 37.866 2.26 36.465 0.94799 89.858 0.297 110.67-0.165 5.306-2.58 10.256-6.6279 13.706l-9.0289 7.697c-1.039 0.885-1.671 2.156-1.75 3.518l-8.5699 147.01c-0.589 10.108-5.361 19.513-13.17 25.958-34.184 28.21-83.573 28.21-117.76 0-7.8087-6.445-12.581-15.85-13.17-25.958z" fill="#fff" stroke="#000" stroke-width="2" tb:tag="background"/><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 transform="translate(0,316)" fill="#d12730" style="display: none;" tb:tag="critical">
<rect width="84" height="84" rx="4" fill="#fff" style=""/>
<rect width="84" height="84" rx="4" style=""/>
<rect x="2" y="2" width="80" height="80" rx="2" stroke="#000" stroke-opacity=".87" stroke-width="4" style=""/>

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 12 KiB

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

@ -862,7 +862,7 @@
}
]
}]]></tb:metadata>
<rect x="1" y="1" width="598" height="398" fill="#fff" stroke="#1A1A1A" stroke-width="2" tb:tag="background"/><rect x="49" y="81" width="238" height="82" rx="3" fill="#dedede" stroke="#1a1a1a" stroke-width="2" tb:tag="value-box-off-peak"/><rect x="313" y="81" width="238" height="82" rx="3" fill="#dedede" stroke="#1a1a1a" stroke-width="2" tb:tag="value-box-night"/><rect x="49" y="237" width="238" height="82" rx="3" fill="#dedede" stroke="#1a1a1a" stroke-width="2" tb:tag="value-box-peak"/><rect x="313" y="237" width="238" height="82" rx="3" fill="#dedede" stroke="#1a1a1a" stroke-width="2" tb:tag="value-box-export"/><text x="171.2998" y="58.286133" fill="#000000" font-family="Roboto" font-size="34px" font-weight="400" text-anchor="middle" tb:tag="off-peak-label" xml:space="default"><tspan dominant-baseline="start">T1</tspan></text><text x="433.2998" y="58.734375" fill="#000000" font-family="Roboto" font-size="34px" font-weight="400" text-anchor="middle" tb:tag="night-label"><tspan dominant-baseline="start">T2</tspan></text><text x="169.2998" y="214.23438" fill="#000000" font-family="Roboto" font-size="34px" font-weight="400" text-anchor="middle" tb:tag="peak-label" xml:space="default"><tspan dominant-baseline="start">T3</tspan></text><text x="432.31152" y="213.78613" fill="#000000" font-family="Roboto" font-size="34px" font-weight="400" text-anchor="middle" tb:tag="export-label" xml:space="default"><tspan dominant-baseline="start">Export</tspan></text><text x="169.45312" y="139.625" fill="#002878" font-family="Roboto" font-size="48px" font-weight="400" text-anchor="middle" tb:tag="off-peak-rate" xml:space="default"><tspan dominant-baseline="start">000223</tspan></text><text x="433.45312" y="139.625" fill="#002878" font-family="Roboto" font-size="48px" font-weight="400" text-anchor="middle" tb:tag="night-rate" xml:space="default"><tspan dominant-baseline="start">000223</tspan></text><text x="169.45312" y="295.625" fill="#002878" font-family="Roboto" font-size="48px" font-weight="400" text-anchor="middle" tb:tag="peak-rate" xml:space="default"><tspan dominant-baseline="start">000223</tspan></text><text x="433.45312" y="295.625" fill="#002878" font-family="Roboto" font-size="48px" font-weight="400" text-anchor="middle" tb:tag="export-rate" xml:space="default"><tspan dominant-baseline="start">000223</tspan></text><text x="299.89453" y="371.67578" fill="#000000" font-family="Roboto" font-size="36px" font-weight="400" text-anchor="middle" tb:tag="units" xml:space="preserve"><tspan dominant-baseline="start">kWh</tspan></text><path d="m201.8-2e-4s-201.8 0-201.8 67v328.36c0 2.6512 5.3727 4.6404 12 4.6404h576c6.627 0 12-1.9892 12-4.6404v-328.36c0-67-198.21-67-198.21-67h-101.79zm201.21 81.2c-3.8661 0-6.9999 1.2536-6.9999 2.8v300.4c0 1.5464 3.1341 2.8 6.9999 2.8h43.998c3.8661 0 6.9999-1.2536 6.9999-2.8v-300.4c0-1.5464-3.1341-2.8-6.9999-2.8z" fill-opacity="0" tb:tag="clickArea"/><g fill="#d12730" style="display: none;" tb:tag="critical">
<rect x="1" y="1" width="598" height="398" fill="#fff" stroke="#1A1A1A" stroke-width="2" tb:tag="background"/><rect x="49" y="81" width="238" height="82" rx="3" fill="#dedede" stroke="#1a1a1a" stroke-width="2" tb:tag="value-box-off-peak"/><rect x="313" y="81" width="238" height="82" rx="3" fill="#dedede" stroke="#1a1a1a" stroke-width="2" tb:tag="value-box-night"/><rect x="49" y="237" width="238" height="82" rx="3" fill="#dedede" stroke="#1a1a1a" stroke-width="2" tb:tag="value-box-peak"/><rect x="313" y="237" width="238" height="82" rx="3" fill="#dedede" stroke="#1a1a1a" stroke-width="2" tb:tag="value-box-export"/><text x="171.2998" y="58.286133" fill="#000000" font-family="Roboto" font-size="34px" font-weight="400" text-anchor="middle" tb:tag="off-peak-label" xml:space="default"><tspan dominant-baseline="start">T1</tspan></text><text x="433.2998" y="58.734375" fill="#000000" font-family="Roboto" font-size="34px" font-weight="400" text-anchor="middle" tb:tag="night-label"><tspan dominant-baseline="start">T2</tspan></text><text x="169.2998" y="214.23438" fill="#000000" font-family="Roboto" font-size="34px" font-weight="400" text-anchor="middle" tb:tag="peak-label" xml:space="default"><tspan dominant-baseline="start">T3</tspan></text><text x="432.31152" y="213.78613" fill="#000000" font-family="Roboto" font-size="34px" font-weight="400" text-anchor="middle" tb:tag="export-label" xml:space="default"><tspan dominant-baseline="start">Export</tspan></text><text x="169.45312" y="139.625" fill="#002878" font-family="Roboto" font-size="48px" font-weight="400" text-anchor="middle" tb:tag="off-peak-rate" xml:space="default"><tspan dominant-baseline="start">000223</tspan></text><text x="433.45312" y="139.625" fill="#002878" font-family="Roboto" font-size="48px" font-weight="400" text-anchor="middle" tb:tag="night-rate" xml:space="default"><tspan dominant-baseline="start">000223</tspan></text><text x="169.45312" y="295.625" fill="#002878" font-family="Roboto" font-size="48px" font-weight="400" text-anchor="middle" tb:tag="peak-rate" xml:space="default"><tspan dominant-baseline="start">000223</tspan></text><text x="433.45312" y="295.625" fill="#002878" font-family="Roboto" font-size="48px" font-weight="400" text-anchor="middle" tb:tag="export-rate" xml:space="default"><tspan dominant-baseline="start">000223</tspan></text><text x="299.89453" y="371.67578" fill="#000000" font-family="Roboto" font-size="36px" font-weight="400" text-anchor="middle" tb:tag="units" xml:space="preserve"><tspan dominant-baseline="start">kWh</tspan></text><path d="m201.8-2e-4s-201.8 0-201.8 67v328.36c0 2.6512 5.3727 4.6404 12 4.6404h576c6.627 0 12-1.9892 12-4.6404v-328.36c0-67-198.21-67-198.21-67h-101.79zm201.21 81.2c-3.8661 0-6.9999 1.2536-6.9999 2.8v300.4c0 1.5464 3.1341 2.8 6.9999 2.8h43.998c3.8661 0 6.9999-1.2536 6.9999-2.8v-300.4c0-1.5464-3.1341-2.8-6.9999-2.8z" fill-opacity="0" fill="#000" 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=""/>

Before

Width:  |  Height:  |  Size: 30 KiB

After

Width:  |  Height:  |  Size: 30 KiB

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

@ -347,7 +347,7 @@
<circle cx="116" cy="52" r="7"/>
<circle cx="148" cy="52" r="7"/>
<circle cx="180" cy="52" r="7"/>
</g><path d="m67.263 0s-67.263 0-67.263 33.5v164.18c0 1.3256 1.7909 2.3202 4 2.3202h192c2.209 0 4-0.9946 4-2.3202v-164.18c0-33.5-66.07-33.5-66.07-33.5h-33.93zm67.07 40.6c-1.2887 0-2.3333 0.6268-2.3333 1.4v150.2c0 0.7732 1.0447 1.4 2.3333 1.4h14.666c1.2887 0 2.3333-0.6268 2.3333-1.4v-150.2c0-0.7732-1.0447-1.4-2.3333-1.4z" fill-opacity="0" tb:tag="clickArea"/><g transform="translate(0,116)" fill="#d12730" style="display: none;" tb:tag="critical">
</g><path d="m67.263 0s-67.263 0-67.263 33.5v164.18c0 1.3256 1.7909 2.3202 4 2.3202h192c2.209 0 4-0.9946 4-2.3202v-164.18c0-33.5-66.07-33.5-66.07-33.5h-33.93zm67.07 40.6c-1.2887 0-2.3333 0.6268-2.3333 1.4v150.2c0 0.7732 1.0447 1.4 2.3333 1.4h14.666c1.2887 0 2.3333-0.6268 2.3333-1.4v-150.2c0-0.7732-1.0447-1.4-2.3333-1.4z" fill-opacity="0" fill="#000" 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=""/>

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 13 KiB

2
application/src/main/data/json/system/scada_symbols/heat-exchanger-hp.svg

@ -349,7 +349,7 @@
<path d="m200 0v138"/>
<path d="m400 0v138"/>
<path d="m338 318v56"/>
</g><path d="m201.79 0s-201.79 0-201.79 100.5v492.54c0 3.9768 5.3727 6.9606 12 6.9606h576c6.627 0 12-2.9838 12-6.9606v-492.54c0-100.5-198.21-100.5-198.21-100.5h-101.79zm201.21 121.8c-3.8661 0-6.9999 1.8804-6.9999 4.2v450.6c0 2.3196 3.1341 4.2 6.9999 4.2h43.998c3.8661 0 6.9999-1.8804 6.9999-4.2v-450.6c0-2.3196-3.1341-4.2-6.9999-4.2z" fill-opacity="0" tb:tag="clickArea"/><g fill="#d12730" style="display: none;" tb:tag="critical">
</g><path d="m201.79 0s-201.79 0-201.79 100.5v492.54c0 3.9768 5.3727 6.9606 12 6.9606h576c6.627 0 12-2.9838 12-6.9606v-492.54c0-100.5-198.21-100.5-198.21-100.5h-101.79zm201.21 121.8c-3.8661 0-6.9999 1.8804-6.9999 4.2v450.6c0 2.3196 3.1341 4.2 6.9999 4.2h43.998c3.8661 0 6.9999-1.8804 6.9999-4.2v-450.6c0-2.3196-3.1341-4.2-6.9999-4.2z" fill-opacity="0" fill="#000" 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=""/>

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 13 KiB

2
application/src/main/data/json/system/scada_symbols/heat-pump-hp.svg

@ -587,7 +587,7 @@
<path d="m722 284c0 99.411-80.589 180-180 180s-180-80.589-180-180 80.589-180 180-180 180 80.589 180 180zm-331.96 0c0 83.926 68.035 151.96 151.96 151.96s151.96-68.035 151.96-151.96-68.035-151.96-151.96-151.96-151.96 68.035-151.96 151.96z"/>
</mask>
<path d="m722 284c0 99.411-80.589 180-180 180s-180-80.589-180-180 80.589-180 180-180 180 80.589 180 180zm-331.96 0c0 83.926 68.035 151.96 151.96 151.96s151.96-68.035 151.96-151.96-68.035-151.96-151.96-151.96-151.96 68.035-151.96 151.96z" fill="#DEDEDE" mask="url(#path-29-inside-1_3215_7169)" stroke="#000" stroke-opacity=".87" stroke-width="4" tb:tag="circle-background"/>
</g><path d="m269.06 0s-269.06 0-269.06 100.5v492.54c0 3.9768 7.1636 6.9606 16 6.9606h768c8.836 0 16-2.9838 16-6.9606v-492.54c0-100.5-264.28-100.5-264.28-100.5h-135.72zm268.28 121.8c-5.1548 0-9.3332 1.8804-9.3332 4.2v450.6c0 2.3196 4.1788 4.2 9.3332 4.2h58.664c5.1548 0 9.3332-1.8804 9.3332-4.2v-450.6c0-2.3196-4.1788-4.2-9.3332-4.2z" fill="#000" fill-opacity="0" style="stroke-width:2.4495" tb:tag="clickArea"/><g tb:tag="levelUpButton">
</g><path d="m269.06 0s-269.06 0-269.06 100.5v492.54c0 3.9768 7.1636 6.9606 16 6.9606h768c8.836 0 16-2.9838 16-6.9606v-492.54c0-100.5-264.28-100.5-264.28-100.5h-135.72zm268.28 121.8c-5.1548 0-9.3332 1.8804-9.3332 4.2v450.6c0 2.3196 4.1788 4.2 9.3332 4.2h58.664c5.1548 0 9.3332-1.8804 9.3332-4.2v-450.6c0-2.3196-4.1788-4.2-9.3332-4.2z" fill="#000" fill-opacity="0" tb:tag="clickArea"/><g tb:tag="levelUpButton">
<path d="m164 290.19c0 5.42-4.394 9.814-9.815 9.814h-68.371c-5.4203 0-9.8143-4.394-9.8143-9.814v-68.373c0-5.421 4.394-9.815 9.8143-9.815h68.371c5.421 0 9.815 4.394 9.815 9.815z"/>
<path d="m163 290.19c0 4.868-3.947 8.814-8.815 8.814h-68.371c-4.868 0-8.8143-3.946-8.8143-8.814v-68.373c0-4.868 3.9463-8.815 8.8143-8.815h68.371c4.868 0 8.815 3.947 8.815 8.815z" stroke="#000" stroke-opacity=".87" stroke-width="2"/>
<path d="m135.92 263.33c0.89 0 1.336-1.077 0.707-1.706l-15.921-15.921c-0.39-0.39-1.023-0.39-1.413 0l-15.921 15.921c-0.629 0.629-0.183 1.706 0.707 1.706z" fill="#000" fill-opacity=".87"/>

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 26 KiB

2
application/src/main/data/json/system/scada_symbols/horizontal-tank-hp.svg

@ -502,7 +502,7 @@
<path d="m185.2 478.95v2.25h-11.437v-1.933l5.554-6.059c0.61-0.687 1.09-1.281 1.442-1.781 0.351-0.5 0.598-0.949 0.738-1.348 0.149-0.406 0.223-0.801 0.223-1.183 0-0.54-0.102-1.012-0.305-1.418-0.195-0.415-0.484-0.739-0.867-0.973-0.383-0.242-0.848-0.363-1.395-0.363-0.632 0-1.164 0.136-1.593 0.41-0.43 0.273-0.754 0.652-0.973 1.137-0.219 0.476-0.328 1.023-0.328 1.64h-2.824c0-0.992 0.226-1.898 0.679-2.719 0.453-0.828 1.11-1.484 1.969-1.968 0.86-0.493 1.895-0.739 3.106-0.739 1.14 0 2.109 0.192 2.906 0.575 0.797 0.382 1.402 0.925 1.816 1.628 0.422 0.704 0.633 1.536 0.633 2.497 0 0.531-0.086 1.058-0.258 1.582-0.172 0.523-0.418 1.046-0.738 1.57-0.313 0.516-0.684 1.035-1.113 1.558-0.43 0.516-0.903 1.04-1.418 1.571l-3.692 4.066zm13.575-7.711v2.789c0 1.336-0.133 2.477-0.399 3.422-0.258 0.938-0.633 1.699-1.125 2.285s-1.082 1.016-1.769 1.289c-0.68 0.274-1.442 0.411-2.286 0.411-0.671 0-1.296-0.086-1.875-0.258-0.57-0.172-1.086-0.442-1.546-0.809-0.461-0.367-0.856-0.84-1.184-1.418-0.32-0.586-0.57-1.285-0.75-2.097-0.172-0.813-0.258-1.754-0.258-2.825v-2.789c0-1.343 0.133-2.476 0.399-3.398 0.265-0.93 0.644-1.684 1.136-2.262 0.492-0.586 1.078-1.012 1.758-1.277 0.688-0.266 1.453-0.399 2.297-0.399 0.68 0 1.305 0.086 1.875 0.258 0.578 0.164 1.094 0.426 1.547 0.785 0.461 0.36 0.851 0.828 1.172 1.407 0.328 0.57 0.578 1.261 0.75 2.074 0.172 0.804 0.258 1.742 0.258 2.812zm-2.825 3.188v-3.61c0-0.679-0.039-1.277-0.117-1.793-0.078-0.523-0.195-0.964-0.351-1.324-0.149-0.367-0.336-0.664-0.563-0.89-0.226-0.235-0.484-0.403-0.773-0.504-0.289-0.11-0.614-0.164-0.973-0.164-0.438 0-0.828 0.086-1.172 0.257-0.344 0.164-0.633 0.43-0.867 0.797s-0.414 0.852-0.539 1.453c-0.117 0.594-0.176 1.317-0.176 2.168v3.61c0 0.687 0.039 1.293 0.117 1.816 0.078 0.524 0.196 0.973 0.352 1.348 0.156 0.367 0.344 0.672 0.562 0.914 0.227 0.234 0.485 0.406 0.774 0.516 0.297 0.109 0.621 0.164 0.972 0.164 0.446 0 0.84-0.086 1.184-0.258s0.633-0.446 0.867-0.821c0.235-0.382 0.41-0.878 0.528-1.488 0.117-0.609 0.175-1.34 0.175-2.191z" fill="#000" fill-opacity=".38"/>
<path d="m181.47 521.48v17.121h-2.824v-13.77l-4.184 1.418v-2.332l6.668-2.437zm17.301 7.16v2.789c0 1.336-0.133 2.476-0.399 3.422-0.258 0.937-0.633 1.699-1.125 2.285s-1.082 1.015-1.769 1.289c-0.68 0.273-1.442 0.41-2.286 0.41-0.671 0-1.296-0.086-1.875-0.258-0.57-0.172-1.086-0.441-1.546-0.808-0.461-0.368-0.856-0.84-1.184-1.418-0.32-0.586-0.57-1.286-0.75-2.098-0.172-0.813-0.258-1.754-0.258-2.824v-2.789c0-1.344 0.133-2.477 0.399-3.399 0.265-0.929 0.644-1.683 1.136-2.261 0.492-0.586 1.078-1.012 1.758-1.278 0.688-0.265 1.453-0.398 2.297-0.398 0.68 0 1.305 0.086 1.875 0.258 0.578 0.164 1.094 0.425 1.547 0.785 0.461 0.359 0.851 0.828 1.172 1.406 0.328 0.57 0.578 1.262 0.75 2.074 0.172 0.805 0.258 1.742 0.258 2.813zm-2.825 3.187v-3.609c0-0.68-0.039-1.278-0.117-1.793-0.078-0.524-0.195-0.965-0.351-1.324-0.149-0.368-0.336-0.664-0.563-0.891-0.226-0.234-0.484-0.402-0.773-0.504-0.289-0.109-0.614-0.164-0.973-0.164-0.438 0-0.828 0.086-1.172 0.258-0.344 0.164-0.633 0.43-0.867 0.797s-0.414 0.851-0.539 1.453c-0.117 0.594-0.176 1.316-0.176 2.168v3.609c0 0.688 0.039 1.293 0.117 1.817 0.078 0.523 0.196 0.972 0.352 1.347 0.156 0.367 0.344 0.672 0.562 0.914 0.227 0.235 0.485 0.407 0.774 0.516 0.297 0.109 0.621 0.164 0.972 0.164 0.446 0 0.84-0.086 1.184-0.258s0.633-0.445 0.867-0.82c0.235-0.383 0.41-0.879 0.528-1.488 0.117-0.61 0.175-1.34 0.175-2.192z" fill="#000" fill-opacity=".38"/>
<path d="m198.77 586.04v2.789c0 1.336-0.133 2.477-0.399 3.422-0.258 0.938-0.633 1.699-1.125 2.285s-1.082 1.016-1.769 1.289c-0.68 0.274-1.442 0.41-2.286 0.41-0.671 0-1.296-0.086-1.875-0.257-0.57-0.172-1.086-0.442-1.546-0.809-0.461-0.367-0.856-0.84-1.184-1.418-0.32-0.586-0.57-1.285-0.75-2.098-0.172-0.812-0.258-1.754-0.258-2.824v-2.789c0-1.344 0.133-2.477 0.399-3.398 0.265-0.93 0.644-1.684 1.136-2.262 0.492-0.586 1.078-1.012 1.758-1.277 0.688-0.266 1.453-0.399 2.297-0.399 0.68 0 1.305 0.086 1.875 0.258 0.578 0.164 1.094 0.426 1.547 0.785 0.461 0.359 0.851 0.828 1.172 1.406 0.328 0.571 0.578 1.262 0.75 2.075 0.172 0.804 0.258 1.742 0.258 2.812zm-2.825 3.188v-3.61c0-0.679-0.039-1.277-0.117-1.793-0.078-0.523-0.195-0.965-0.351-1.324-0.149-0.367-0.336-0.664-0.563-0.891-0.226-0.234-0.484-0.402-0.773-0.504-0.289-0.109-0.614-0.164-0.973-0.164-0.438 0-0.828 0.086-1.172 0.258-0.344 0.164-0.633 0.43-0.867 0.797s-0.414 0.852-0.539 1.453c-0.117 0.594-0.176 1.317-0.176 2.168v3.61c0 0.687 0.039 1.293 0.117 1.816s0.196 0.973 0.352 1.348c0.156 0.367 0.344 0.671 0.562 0.914 0.227 0.234 0.485 0.406 0.774 0.515 0.297 0.11 0.621 0.164 0.972 0.164 0.446 0 0.84-0.086 1.184-0.257 0.344-0.172 0.633-0.446 0.867-0.821 0.235-0.383 0.41-0.879 0.528-1.488 0.117-0.609 0.175-1.34 0.175-2.191z" fill="#000" fill-opacity=".38"/>
</g><path d="m336.32 0s-336.32 0-336.32 100.5v492.54c0 3.9768 8.9546 6.9606 20 6.9606h960c11.045 0 20-2.9838 20-6.9606v-492.54c0-100.5-330.35-100.5-330.35-100.5h-169.65zm335.35 121.8c-6.4433 0-11.667 1.8804-11.667 4.2v450.6c0 2.3196 5.2233 4.2 11.667 4.2h73.329c6.4433 0 11.667-1.8804 11.667-4.2v-450.6c0-2.3196-5.2233-4.2-11.667-4.2z" fill="#000" fill-opacity="0" style="stroke-width:.55902" tb:tag="clickArea"/><g fill="#d12730" style="display: none;" tb:tag="critical">
</g><path d="m336.32 0s-336.32 0-336.32 100.5v492.54c0 3.9768 8.9546 6.9606 20 6.9606h960c11.045 0 20-2.9838 20-6.9606v-492.54c0-100.5-330.35-100.5-330.35-100.5h-169.65zm335.35 121.8c-6.4433 0-11.667 1.8804-11.667 4.2v450.6c0 2.3196 5.2233 4.2 11.667 4.2h73.329c6.4433 0 11.667-1.8804 11.667-4.2v-450.6c0-2.3196-5.2233-4.2-11.667-4.2z" 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=""/>

Before

Width:  |  Height:  |  Size: 49 KiB

After

Width:  |  Height:  |  Size: 49 KiB

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

@ -335,7 +335,7 @@
<path d="m287 60c0-2.7614 2.239-5 5-5h54.5c2.761 0 5 2.2386 5 5v86.08c0 4.322-5.113 6.609-8.334 3.727l-54.5-48.763c-1.06-0.949-1.666-2.3042-1.666-3.7267v-37.317z"/>
<rect x="1" y="377" width="398" height="22" rx="5"/>
<path d="m29.655 185h-24.568c-0.9085 0-1.3463-1.114-0.68102-1.732l193.55-180c1.151-1.0709 2.935-1.0709 4.086 0l193.55 180c0.665 0.618 0.227 1.732-0.681 1.732h-24.568c-1.256 0-2.467-0.473-3.39-1.325l-164.92-152.16c-1.149-1.0601-2.919-1.0601-4.068 0l-164.92 152.16c-0.9235 0.852-2.1339 1.325-3.3904 1.325z"/>
</g><rect x="89" y="187" width="30" height="63" rx="1" fill="#999" stroke="#1A1A1A" stroke-width="2"/><rect x="221" y="187" width="30" height="63" rx="1" fill="#999" stroke="#1A1A1A" stroke-width="2"/><rect x="221" y="286" width="30" height="63" rx="1" fill="#999" stroke="#1A1A1A" stroke-width="2"/><rect x="89" y="286" width="64" height="91" rx="1" fill="#999" stroke="#1A1A1A" stroke-width="2"/><rect x="123" y="187" width="30" height="63" rx="1" fill="#999" stroke="#1A1A1A" stroke-width="2"/><rect x="255" y="187" width="30" height="63" rx="1" fill="#999" stroke="#1A1A1A" stroke-width="2"/><rect x="255" y="286" width="30" height="63" rx="1" fill="#999" stroke="#1A1A1A" stroke-width="2"/><rect x="289" y="187" width="30" height="63" rx="1" fill="#999" stroke="#1A1A1A" stroke-width="2"/><rect x="289" y="286" width="30" height="63" rx="1" fill="#999" stroke="#1A1A1A" stroke-width="2"/><path d="m200.7 104.07 27.061 26.216c0.645 0.625 0.203 1.718-0.696 1.718h-54.122c-0.899 0-1.341-1.093-0.696-1.718l27.061-26.216c0.388-0.375 1.004-0.375 1.392 0z" fill="#999" stroke="#1A1A1A" stroke-width="2"/><path d="m134.53 0s-134.53 0-134.53 67v328.36c0 2.6512 3.5818 4.6403 8 4.6403h384c4.418 0 8-1.9892 8-4.6403v-328.36c0-67-132.14-67-132.14-67h-67.86zm134.14 81.2c-2.5774 0-4.6666 1.2536-4.6666 2.8v300.4c0 1.5464 2.0894 2.8 4.6666 2.8h29.332c2.5774 0 4.6666-1.2536 4.6666-2.8v-300.4c0-1.5464-2.0894-2.8-4.6666-2.8z" fill-opacity="0" tb:tag="clickArea"/><g transform="translate(0,316)" fill="#d12730" style="display: none;" tb:tag="critical">
</g><rect x="89" y="187" width="30" height="63" rx="1" fill="#999" stroke="#1A1A1A" stroke-width="2"/><rect x="221" y="187" width="30" height="63" rx="1" fill="#999" stroke="#1A1A1A" stroke-width="2"/><rect x="221" y="286" width="30" height="63" rx="1" fill="#999" stroke="#1A1A1A" stroke-width="2"/><rect x="89" y="286" width="64" height="91" rx="1" fill="#999" stroke="#1A1A1A" stroke-width="2"/><rect x="123" y="187" width="30" height="63" rx="1" fill="#999" stroke="#1A1A1A" stroke-width="2"/><rect x="255" y="187" width="30" height="63" rx="1" fill="#999" stroke="#1A1A1A" stroke-width="2"/><rect x="255" y="286" width="30" height="63" rx="1" fill="#999" stroke="#1A1A1A" stroke-width="2"/><rect x="289" y="187" width="30" height="63" rx="1" fill="#999" stroke="#1A1A1A" stroke-width="2"/><rect x="289" y="286" width="30" height="63" rx="1" fill="#999" stroke="#1A1A1A" stroke-width="2"/><path d="m200.7 104.07 27.061 26.216c0.645 0.625 0.203 1.718-0.696 1.718h-54.122c-0.899 0-1.341-1.093-0.696-1.718l27.061-26.216c0.388-0.375 1.004-0.375 1.392 0z" fill="#999" stroke="#1A1A1A" stroke-width="2"/><path d="m134.53 0s-134.53 0-134.53 67v328.36c0 2.6512 3.5818 4.6403 8 4.6403h384c4.418 0 8-1.9892 8-4.6403v-328.36c0-67-132.14-67-132.14-67h-67.86zm134.14 81.2c-2.5774 0-4.6666 1.2536-4.6666 2.8v300.4c0 1.5464 2.0894 2.8 4.6666 2.8h29.332c2.5774 0 4.6666-1.2536 4.6666-2.8v-300.4c0-1.5464-2.0894-2.8-4.6666-2.8z" fill-opacity="0" fill="#000" tb:tag="clickArea"/><g transform="translate(0,316)" fill="#d12730" style="display: none;" tb:tag="critical">
<rect width="84" height="84" rx="4" fill="#fff" style=""/>
<rect width="84" height="84" rx="4" style=""/>
<rect x="2" y="2" width="80" height="80" rx="2" stroke="#000" stroke-opacity=".87" stroke-width="4" style=""/>

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 14 KiB

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

@ -344,7 +344,7 @@
}
]
}]]></tb:metadata>
<rect x="1" y="1" width="998" height="598" fill="#fff" stroke="#1A1A1A" stroke-width="2" tb:tag="background"/><rect x="1" y="1" width="998" height="28" stroke="#1A1A1A" stroke-width="2"/><line x1="858" x2="952" y1="361" y2="361" stroke="#1A1A1A" stroke-linecap="round" stroke-width="6"/><line x1="858" x2="952" y1="393" y2="393" stroke="#1A1A1A" stroke-linecap="round" stroke-width="6"/><line x1="858" x2="952" y1="425" y2="425" stroke="#1A1A1A" stroke-linecap="round" stroke-width="6"/><line x1="858" x2="952" y1="457" y2="457" stroke="#1A1A1A" stroke-linecap="round" stroke-width="6"/><line x1="858" x2="952" y1="67" y2="67" stroke="#1A1A1A" stroke-linecap="round" stroke-width="6"/><line x1="858" x2="952" y1="99" y2="99" stroke="#1A1A1A" stroke-linecap="round" stroke-width="6"/><line x1="858" x2="952" y1="131" y2="131" stroke="#1A1A1A" stroke-linecap="round" stroke-width="6"/><line x1="858" x2="952" y1="163" y2="163" stroke="#1A1A1A" stroke-linecap="round" stroke-width="6"/><rect x="79" y="96" width="278" height="338" rx="3" stroke="#1A1A1A" stroke-width="2"/><rect x="479" y="96" width="278" height="338" rx="3" stroke="#1A1A1A" stroke-width="2"/><circle cx="418" cy="278" r="19" stroke="#1A1A1A" stroke-width="2"/><circle cx="418" cy="278" r="7" fill="#1A1A1A"/><rect x="1" y="501" width="998" height="98" fill="#999" stroke="#1A1A1A" stroke-width="2" tb:tag="sub-background"/><path d="m336.32 0s-336.32 0-336.32 100.5v492.54c0 3.9768 8.9545 6.9604 20 6.9604h960c11.045 0 20-2.9838 20-6.9604v-492.54c0-100.5-330.35-100.5-330.35-100.5h-169.65zm335.35 121.8c-6.4435 0-11.666 1.8804-11.666 4.2v450.6c0 2.3196 5.2235 4.2 11.666 4.2h73.33c6.4435 0 11.666-1.8804 11.666-4.2v-450.6c0-2.3196-5.2235-4.2-11.666-4.2z" fill-opacity="0" style="stroke-width:2.8629" tb:tag="clickArea"/><g fill="#d12730" style="display: none;" tb:tag="critical">
<rect x="1" y="1" width="998" height="598" fill="#fff" stroke="#1A1A1A" stroke-width="2" tb:tag="background"/><rect x="1" y="1" width="998" height="28" stroke="#1A1A1A" stroke-width="2"/><line x1="858" x2="952" y1="361" y2="361" stroke="#1A1A1A" stroke-linecap="round" stroke-width="6"/><line x1="858" x2="952" y1="393" y2="393" stroke="#1A1A1A" stroke-linecap="round" stroke-width="6"/><line x1="858" x2="952" y1="425" y2="425" stroke="#1A1A1A" stroke-linecap="round" stroke-width="6"/><line x1="858" x2="952" y1="457" y2="457" stroke="#1A1A1A" stroke-linecap="round" stroke-width="6"/><line x1="858" x2="952" y1="67" y2="67" stroke="#1A1A1A" stroke-linecap="round" stroke-width="6"/><line x1="858" x2="952" y1="99" y2="99" stroke="#1A1A1A" stroke-linecap="round" stroke-width="6"/><line x1="858" x2="952" y1="131" y2="131" stroke="#1A1A1A" stroke-linecap="round" stroke-width="6"/><line x1="858" x2="952" y1="163" y2="163" stroke="#1A1A1A" stroke-linecap="round" stroke-width="6"/><rect x="79" y="96" width="278" height="338" rx="3" stroke="#1A1A1A" stroke-width="2"/><rect x="479" y="96" width="278" height="338" rx="3" stroke="#1A1A1A" stroke-width="2"/><circle cx="418" cy="278" r="19" stroke="#1A1A1A" stroke-width="2"/><circle cx="418" cy="278" r="7" fill="#1A1A1A"/><rect x="1" y="501" width="998" height="98" fill="#999" stroke="#1A1A1A" stroke-width="2" tb:tag="sub-background"/><path d="m336.32 0s-336.32 0-336.32 100.5v492.54c0 3.9768 8.9545 6.9604 20 6.9604h960c11.045 0 20-2.9838 20-6.9604v-492.54c0-100.5-330.35-100.5-330.35-100.5h-169.65zm335.35 121.8c-6.4435 0-11.666 1.8804-11.666 4.2v450.6c0 2.3196 5.2235 4.2 11.666 4.2h73.33c6.4435 0 11.666-1.8804 11.666-4.2v-450.6c0-2.3196-5.2235-4.2-11.666-4.2z" fill-opacity="0" fill="#000" 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=""/>

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 14 KiB

2
application/src/main/data/json/system/scada_symbols/large-horizontal-separator-hp.svg

@ -336,7 +336,7 @@
}
]
}]]></tb:metadata>
<rect x="1" y="1" width="998" height="598" rx="159" fill="#fff" stroke="#1A1A1A" stroke-width="2" tb:tag="background"/><path d="m336.32 0s-336.32 0-336.32 100.5v492.54c0 3.9768 8.9545 6.9605 20 6.9605h960c11.045 0 20-2.9838 20-6.9605v-492.54c0-100.5-330.35-100.5-330.35-100.5h-169.65zm335.35 121.8c-6.4435 0-11.666 1.8804-11.666 4.2v450.6c0 2.3196 5.2235 4.2 11.666 4.2h73.33c6.4435 0 11.666-1.8804 11.666-4.2v-450.6c0-2.3196-5.2235-4.2-11.666-4.2z" fill-opacity="0" tb:tag="clickArea"/><g transform="translate(0,516)" fill="#d12730" style="display: none;" tb:tag="critical">
<rect x="1" y="1" width="998" height="598" rx="159" fill="#fff" stroke="#1A1A1A" stroke-width="2" tb:tag="background"/><path d="m336.32 0s-336.32 0-336.32 100.5v492.54c0 3.9768 8.9545 6.9605 20 6.9605h960c11.045 0 20-2.9838 20-6.9605v-492.54c0-100.5-330.35-100.5-330.35-100.5h-169.65zm335.35 121.8c-6.4435 0-11.666 1.8804-11.666 4.2v450.6c0 2.3196 5.2235 4.2 11.666 4.2h73.33c6.4435 0 11.666-1.8804 11.666-4.2v-450.6c0-2.3196-5.2235-4.2-11.666-4.2z" fill-opacity="0" fill="#000" 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=""/>

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 13 KiB

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

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 68 KiB

After

Width:  |  Height:  |  Size: 68 KiB

2
application/src/main/data/json/system/scada_symbols/large-stand-cylindrical-tank.svg

@ -565,7 +565,7 @@
<path d="m380 487c0-6.627 5.373-12 12-12h216c6.627 0 12 5.373 12 12v56c0 6.627-5.373 12-12 12h-216c-6.627 0-12-5.373-12-12v-56z" fill="#f3f3f3" tb:tag="value-box-background"/>
<path d="m381.5 487c0-5.799 4.701-10.5 10.5-10.5h216c5.799 0 10.5 4.701 10.5 10.5v56c0 5.799-4.701 10.5-10.5 10.5h-216c-5.799 0-10.5-4.701-10.5-10.5v-56z" stroke="#727171" stroke-width="3"/>
<text x="503.10281" y="518.07812" fill="#727171" font-family="Roboto" font-size="32px" font-weight="500" tb:tag="value-text" xml:space="preserve" text-anchor="middle"><tspan dominant-baseline="middle">1660 gal</tspan></text>
</g><path d="m336.32-5e-4s-336.32 0-336.32 201v985.08c0 7.9536 8.9543 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.4433 0-11.667 3.7608-11.667 8.4v901.2c0 4.6392 5.2233 8.4 11.667 8.4h73.333c6.4433 0 11.667-3.7608 11.667-8.4v-901.2c0-4.6392-5.2233-8.4-11.667-8.4z" fill="#000" fill-opacity="0" style="stroke-width:1.0954" tb:tag="clickArea"/><rect x="122" y="1163" width="80" height="24" rx="7" fill="#fff"/><rect x="122" y="1163" width="80" height="24" rx="7" fill="url(#paint245_linear_1702_237993)" style="fill:url(#paint245_linear_1702_237993)"/><rect x="123.5" y="1164.5" width="77" height="21" rx="5.5" stroke="#000" stroke-opacity=".12" stroke-width="3"/><rect x="798" y="1163" width="80" height="24" rx="7" fill="#fff"/><rect x="798" y="1163" width="80" height="24" rx="7" fill="url(#paint246_linear_1702_237993)" style="fill:url(#paint246_linear_1702_237993)"/><rect x="799.5" y="1164.5" width="77" height="21" rx="5.5" stroke="#000" stroke-opacity=".12" stroke-width="3"/><rect transform="rotate(10 168.69 996.46)" x="168.69" y="996.46" width="676" height="8" fill="#727171"/><rect transform="rotate(-10 158.11 1114.7)" x="158.11" y="1114.7" width="687.16" height="8" fill="#727171"/><path d="m146 1163v-169l32 1v168z" fill="#fff"/><path d="m146 1163v-169l32 1v168z" fill="url(#paint247_linear_1702_237993)" style="fill:url(#paint247_linear_1702_237993)"/><path d="m147.5 1161.5v-165.95l29 0.906v165.05z" stroke="#000" stroke-opacity=".12" stroke-width="3"/><path d="m822 1163v-167l32-1v168z" fill="#fff"/><path d="m822 1163v-167l32-1v168z" fill="url(#paint248_linear_1702_237993)" style="fill:url(#paint248_linear_1702_237993)"/><path d="m823.5 1161.5v-164.05l29-0.906v164.95z" stroke="#000" stroke-opacity=".12" stroke-width="3"/><rect transform="rotate(10 135.43 1006.5)" x="135.43" y="1006.5" width="751.02" height="12" fill="#838282"/><rect transform="rotate(-10 130.48 1136)" x="130.48" y="1136" width="748.07" height="12" fill="#838282"/><circle cx="870" cy="885" r="32" fill="url(#paint249_radial_1702_237993)" style="fill:url(#paint249_radial_1702_237993)"/><circle cx="870" cy="885" r="30.5" stroke="#000" stroke-opacity=".12" stroke-width="3"/><circle cx="130" cy="885" r="32" fill="url(#paint250_radial_1702_237993)" style="fill:url(#paint250_radial_1702_237993)"/><circle cx="130" cy="885" r="30.5" stroke="#000" stroke-opacity=".12" stroke-width="3"/><path d="m114 1171v-284c0-8.837 7.163-16 16-16s16 7.163 16 16v284z" fill="#fff"/><path d="m114 1171v-284c0-8.837 7.163-16 16-16s16 7.163 16 16v284z" fill="url(#paint251_linear_1702_237993)" style="fill:url(#paint251_linear_1702_237993)"/><path d="m115.5 1169.5v-282.5c0-8.008 6.492-14.5 14.5-14.5s14.5 6.492 14.5 14.5v282.5z" stroke="#000" stroke-opacity=".12" stroke-width="3"/><path d="m854 1171v-284c0-8.837 7.163-16 16-16s16 7.163 16 16v284z" fill="#fff"/><path d="m854 1171v-284c0-8.837 7.163-16 16-16s16 7.163 16 16v284z" fill="url(#paint252_linear_1702_237993)" style="fill:url(#paint252_linear_1702_237993)"/><path d="m855.5 1169.5v-282.5c0-8.008 6.492-14.5 14.5-14.5s14.5 6.492 14.5 14.5v282.5z" stroke="#000" stroke-opacity=".12" stroke-width="3"/><rect x="80" y="1171" width="100" height="29" rx="7" fill="#fff"/><rect x="80" y="1171" width="100" height="29" rx="7" fill="url(#paint253_linear_1702_237993)" style="fill:url(#paint253_linear_1702_237993)"/><rect x="81.5" y="1172.5" width="97" height="26" rx="5.5" stroke="#000" stroke-opacity=".12" stroke-width="3"/><rect x="820" y="1171" width="100" height="29" rx="7" fill="#fff"/><rect x="820" y="1171" width="100" height="29" rx="7" fill="url(#paint254_linear_1702_237993)" style="fill:url(#paint254_linear_1702_237993)"/><rect x="821.5" y="1172.5" width="97" height="26" rx="5.5" stroke="#000" stroke-opacity=".12" stroke-width="3"/><defs>
</g><path d="m336.32-5e-4s-336.32 0-336.32 201v985.08c0 7.9536 8.9543 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.4433 0-11.667 3.7608-11.667 8.4v901.2c0 4.6392 5.2233 8.4 11.667 8.4h73.333c6.4433 0 11.667-3.7608 11.667-8.4v-901.2c0-4.6392-5.2233-8.4-11.667-8.4z" fill="#000" fill-opacity="0" tb:tag="clickArea"/><rect x="122" y="1163" width="80" height="24" rx="7" fill="#fff"/><rect x="122" y="1163" width="80" height="24" rx="7" fill="url(#paint245_linear_1702_237993)" style="fill:url(#paint245_linear_1702_237993)"/><rect x="123.5" y="1164.5" width="77" height="21" rx="5.5" stroke="#000" stroke-opacity=".12" stroke-width="3"/><rect x="798" y="1163" width="80" height="24" rx="7" fill="#fff"/><rect x="798" y="1163" width="80" height="24" rx="7" fill="url(#paint246_linear_1702_237993)" style="fill:url(#paint246_linear_1702_237993)"/><rect x="799.5" y="1164.5" width="77" height="21" rx="5.5" stroke="#000" stroke-opacity=".12" stroke-width="3"/><rect transform="rotate(10 168.69 996.46)" x="168.69" y="996.46" width="676" height="8" fill="#727171"/><rect transform="rotate(-10 158.11 1114.7)" x="158.11" y="1114.7" width="687.16" height="8" fill="#727171"/><path d="m146 1163v-169l32 1v168z" fill="#fff"/><path d="m146 1163v-169l32 1v168z" fill="url(#paint247_linear_1702_237993)" style="fill:url(#paint247_linear_1702_237993)"/><path d="m147.5 1161.5v-165.95l29 0.906v165.05z" stroke="#000" stroke-opacity=".12" stroke-width="3"/><path d="m822 1163v-167l32-1v168z" fill="#fff"/><path d="m822 1163v-167l32-1v168z" fill="url(#paint248_linear_1702_237993)" style="fill:url(#paint248_linear_1702_237993)"/><path d="m823.5 1161.5v-164.05l29-0.906v164.95z" stroke="#000" stroke-opacity=".12" stroke-width="3"/><rect transform="rotate(10 135.43 1006.5)" x="135.43" y="1006.5" width="751.02" height="12" fill="#838282"/><rect transform="rotate(-10 130.48 1136)" x="130.48" y="1136" width="748.07" height="12" fill="#838282"/><circle cx="870" cy="885" r="32" fill="url(#paint249_radial_1702_237993)" style="fill:url(#paint249_radial_1702_237993)"/><circle cx="870" cy="885" r="30.5" stroke="#000" stroke-opacity=".12" stroke-width="3"/><circle cx="130" cy="885" r="32" fill="url(#paint250_radial_1702_237993)" style="fill:url(#paint250_radial_1702_237993)"/><circle cx="130" cy="885" r="30.5" stroke="#000" stroke-opacity=".12" stroke-width="3"/><path d="m114 1171v-284c0-8.837 7.163-16 16-16s16 7.163 16 16v284z" fill="#fff"/><path d="m114 1171v-284c0-8.837 7.163-16 16-16s16 7.163 16 16v284z" fill="url(#paint251_linear_1702_237993)" style="fill:url(#paint251_linear_1702_237993)"/><path d="m115.5 1169.5v-282.5c0-8.008 6.492-14.5 14.5-14.5s14.5 6.492 14.5 14.5v282.5z" stroke="#000" stroke-opacity=".12" stroke-width="3"/><path d="m854 1171v-284c0-8.837 7.163-16 16-16s16 7.163 16 16v284z" fill="#fff"/><path d="m854 1171v-284c0-8.837 7.163-16 16-16s16 7.163 16 16v284z" fill="url(#paint252_linear_1702_237993)" style="fill:url(#paint252_linear_1702_237993)"/><path d="m855.5 1169.5v-282.5c0-8.008 6.492-14.5 14.5-14.5s14.5 6.492 14.5 14.5v282.5z" stroke="#000" stroke-opacity=".12" stroke-width="3"/><rect x="80" y="1171" width="100" height="29" rx="7" fill="#fff"/><rect x="80" y="1171" width="100" height="29" rx="7" fill="url(#paint253_linear_1702_237993)" style="fill:url(#paint253_linear_1702_237993)"/><rect x="81.5" y="1172.5" width="97" height="26" rx="5.5" stroke="#000" stroke-opacity=".12" stroke-width="3"/><rect x="820" y="1171" width="100" height="29" rx="7" fill="#fff"/><rect x="820" y="1171" width="100" height="29" rx="7" fill="url(#paint254_linear_1702_237993)" style="fill:url(#paint254_linear_1702_237993)"/><rect x="821.5" y="1172.5" width="97" height="26" rx="5.5" stroke="#000" stroke-opacity=".12" stroke-width="3"/><defs>
<filter id="filter0_ii_2005_230043" x="376" y="471" width="248" height="88" color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>

Before

Width:  |  Height:  |  Size: 118 KiB

After

Width:  |  Height:  |  Size: 118 KiB

2
application/src/main/data/json/system/scada_symbols/large-stand-vertical-tank.svg

@ -569,7 +569,7 @@
<text x="505" y="90" fill="#727171" font-family="Roboto" font-size="32px" font-weight="500" tb:tag="value-text" xml:space="preserve" text-anchor="middle"><tspan dominant-baseline="middle">1660 gal</tspan></text>
</g><mask id="path-316-inside-2_1711_311697" fill="white">
<path d="m7 181c-3.866 0-7-3.134-7-7s3.134-7 7-7h986c3.866 0 7 3.134 7 7s-3.134 7-7 7h-986z"/>
</mask><path d="m7 181c-3.866 0-7-3.134-7-7s3.134-7 7-7h986c3.866 0 7 3.134 7 7s-3.134 7-7 7h-986z" fill="#D9D9D9"/><path d="m7 170h986v-6h-986v6zm986 8h-986v6h986v-6zm4-4c0 2.209-1.791 4-4 4v6c5.523 0 10-4.477 10-10h-6zm-4-4c2.209 0 4 1.791 4 4h6c0-5.523-4.477-10-10-10v6zm-990 4c0-2.209 1.7909-4 4-4v-6c-5.5228 0-10 4.477-10 10h6zm-6 0c0 5.523 4.4771 10 10 10v-6c-2.2091 0-4-1.791-4-4h-6z" fill="#727171" mask="url(#path-316-inside-2_1711_311697)"/><path d="m335.68-5e-4s-336.32 0-336.32 201v985.08c0 7.9536 8.9543 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.4433 0-11.667 3.7608-11.667 8.4v901.2c0 4.6392 5.2233 8.4 11.667 8.4h73.333c6.4433 0 11.667-3.7608 11.667-8.4v-901.2c0-4.6392-5.2233-8.4-11.667-8.4z" fill="#000" fill-opacity="0" style="stroke-width:1.0954" tb:tag="clickArea"/><rect x="122" y="1163" width="80" height="24" rx="7" fill="#fff"/><rect x="122" y="1163" width="80" height="24" rx="7" fill="url(#paint245_linear_1711_311696)" style="fill:url(#paint245_linear_1711_311696)"/><rect x="123.5" y="1164.5" width="77" height="21" rx="5.5" stroke="#000" stroke-opacity=".12" stroke-width="3"/><rect x="798" y="1163" width="80" height="24" rx="7" fill="#fff"/><rect x="798" y="1163" width="80" height="24" rx="7" fill="url(#paint246_linear_1711_311696)" style="fill:url(#paint246_linear_1711_311696)"/><rect x="799.5" y="1164.5" width="77" height="21" rx="5.5" stroke="#000" stroke-opacity=".12" stroke-width="3"/><rect transform="rotate(10 168.69 996.46)" x="168.69" y="996.46" width="676" height="8" fill="#727171"/><rect transform="rotate(-10 158.11 1114.7)" x="158.11" y="1114.7" width="687.16" height="8" fill="#727171"/><path d="m146 1163v-169l32 1v168z" fill="#fff"/><path d="m146 1163v-169l32 1v168z" fill="url(#paint247_linear_1711_311696)" style="fill:url(#paint247_linear_1711_311696)"/><path d="m147.5 1161.5v-165.95l29 0.906v165.05z" stroke="#000" stroke-opacity=".12" stroke-width="3"/><path d="m822 1163v-167l32-1v168z" fill="#fff"/><path d="m822 1163v-167l32-1v168z" fill="url(#paint248_linear_1711_311696)" style="fill:url(#paint248_linear_1711_311696)"/><path d="m823.5 1161.5v-164.05l29-0.906v164.95z" stroke="#000" stroke-opacity=".12" stroke-width="3"/><rect transform="rotate(10 135.43 1006.5)" x="135.43" y="1006.5" width="751.02" height="12" fill="#838282"/><rect transform="rotate(-10 130.48 1136)" x="130.48" y="1136" width="748.07" height="12" fill="#838282"/><circle cx="870" cy="885" r="32" fill="url(#paint249_radial_1711_311696)" style="fill:url(#paint249_radial_1711_311696)"/><circle cx="870" cy="885" r="30.5" stroke="#000" stroke-opacity=".12" stroke-width="3"/><circle cx="130" cy="885" r="32" fill="url(#paint250_radial_1711_311696)" style="fill:url(#paint250_radial_1711_311696)"/><circle cx="130" cy="885" r="30.5" stroke="#000" stroke-opacity=".12" stroke-width="3"/><path d="m114 1171v-284c0-8.837 7.163-16 16-16s16 7.163 16 16v284z" fill="#fff"/><path d="m114 1171v-284c0-8.837 7.163-16 16-16s16 7.163 16 16v284z" fill="url(#paint251_linear_1711_311696)" style="fill:url(#paint251_linear_1711_311696)"/><path d="m115.5 1169.5v-282.5c0-8.008 6.492-14.5 14.5-14.5s14.5 6.492 14.5 14.5v282.5z" stroke="#000" stroke-opacity=".12" stroke-width="3"/><path d="m854 1171v-284c0-8.837 7.163-16 16-16s16 7.163 16 16v284z" fill="#fff"/><path d="m854 1171v-284c0-8.837 7.163-16 16-16s16 7.163 16 16v284z" fill="url(#paint252_linear_1711_311696)" style="fill:url(#paint252_linear_1711_311696)"/><path d="m855.5 1169.5v-282.5c0-8.008 6.492-14.5 14.5-14.5s14.5 6.492 14.5 14.5v282.5z" stroke="#000" stroke-opacity=".12" stroke-width="3"/><rect x="80" y="1171" width="100" height="29" rx="7" fill="#fff"/><rect x="80" y="1171" width="100" height="29" rx="7" fill="url(#paint253_linear_1711_311696)" style="fill:url(#paint253_linear_1711_311696)"/><rect x="81.5" y="1172.5" width="97" height="26" rx="5.5" stroke="#000" stroke-opacity=".12" stroke-width="3"/><rect x="820" y="1171" width="100" height="29" rx="7" fill="#fff"/><rect x="820" y="1171" width="100" height="29" rx="7" fill="url(#paint254_linear_1711_311696)" style="fill:url(#paint254_linear_1711_311696)"/><rect x="821.5" y="1172.5" width="97" height="26" rx="5.5" stroke="#000" stroke-opacity=".12" stroke-width="3"/><defs>
</mask><path d="m7 181c-3.866 0-7-3.134-7-7s3.134-7 7-7h986c3.866 0 7 3.134 7 7s-3.134 7-7 7h-986z" fill="#D9D9D9"/><path d="m7 170h986v-6h-986v6zm986 8h-986v6h986v-6zm4-4c0 2.209-1.791 4-4 4v6c5.523 0 10-4.477 10-10h-6zm-4-4c2.209 0 4 1.791 4 4h6c0-5.523-4.477-10-10-10v6zm-990 4c0-2.209 1.7909-4 4-4v-6c-5.5228 0-10 4.477-10 10h6zm-6 0c0 5.523 4.4771 10 10 10v-6c-2.2091 0-4-1.791-4-4h-6z" fill="#727171" mask="url(#path-316-inside-2_1711_311697)"/><path d="m335.68-5e-4s-336.32 0-336.32 201v985.08c0 7.9536 8.9543 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.4433 0-11.667 3.7608-11.667 8.4v901.2c0 4.6392 5.2233 8.4 11.667 8.4h73.333c6.4433 0 11.667-3.7608 11.667-8.4v-901.2c0-4.6392-5.2233-8.4-11.667-8.4z" fill="#000" fill-opacity="0" tb:tag="clickArea"/><rect x="122" y="1163" width="80" height="24" rx="7" fill="#fff"/><rect x="122" y="1163" width="80" height="24" rx="7" fill="url(#paint245_linear_1711_311696)" style="fill:url(#paint245_linear_1711_311696)"/><rect x="123.5" y="1164.5" width="77" height="21" rx="5.5" stroke="#000" stroke-opacity=".12" stroke-width="3"/><rect x="798" y="1163" width="80" height="24" rx="7" fill="#fff"/><rect x="798" y="1163" width="80" height="24" rx="7" fill="url(#paint246_linear_1711_311696)" style="fill:url(#paint246_linear_1711_311696)"/><rect x="799.5" y="1164.5" width="77" height="21" rx="5.5" stroke="#000" stroke-opacity=".12" stroke-width="3"/><rect transform="rotate(10 168.69 996.46)" x="168.69" y="996.46" width="676" height="8" fill="#727171"/><rect transform="rotate(-10 158.11 1114.7)" x="158.11" y="1114.7" width="687.16" height="8" fill="#727171"/><path d="m146 1163v-169l32 1v168z" fill="#fff"/><path d="m146 1163v-169l32 1v168z" fill="url(#paint247_linear_1711_311696)" style="fill:url(#paint247_linear_1711_311696)"/><path d="m147.5 1161.5v-165.95l29 0.906v165.05z" stroke="#000" stroke-opacity=".12" stroke-width="3"/><path d="m822 1163v-167l32-1v168z" fill="#fff"/><path d="m822 1163v-167l32-1v168z" fill="url(#paint248_linear_1711_311696)" style="fill:url(#paint248_linear_1711_311696)"/><path d="m823.5 1161.5v-164.05l29-0.906v164.95z" stroke="#000" stroke-opacity=".12" stroke-width="3"/><rect transform="rotate(10 135.43 1006.5)" x="135.43" y="1006.5" width="751.02" height="12" fill="#838282"/><rect transform="rotate(-10 130.48 1136)" x="130.48" y="1136" width="748.07" height="12" fill="#838282"/><circle cx="870" cy="885" r="32" fill="url(#paint249_radial_1711_311696)" style="fill:url(#paint249_radial_1711_311696)"/><circle cx="870" cy="885" r="30.5" stroke="#000" stroke-opacity=".12" stroke-width="3"/><circle cx="130" cy="885" r="32" fill="url(#paint250_radial_1711_311696)" style="fill:url(#paint250_radial_1711_311696)"/><circle cx="130" cy="885" r="30.5" stroke="#000" stroke-opacity=".12" stroke-width="3"/><path d="m114 1171v-284c0-8.837 7.163-16 16-16s16 7.163 16 16v284z" fill="#fff"/><path d="m114 1171v-284c0-8.837 7.163-16 16-16s16 7.163 16 16v284z" fill="url(#paint251_linear_1711_311696)" style="fill:url(#paint251_linear_1711_311696)"/><path d="m115.5 1169.5v-282.5c0-8.008 6.492-14.5 14.5-14.5s14.5 6.492 14.5 14.5v282.5z" stroke="#000" stroke-opacity=".12" stroke-width="3"/><path d="m854 1171v-284c0-8.837 7.163-16 16-16s16 7.163 16 16v284z" fill="#fff"/><path d="m854 1171v-284c0-8.837 7.163-16 16-16s16 7.163 16 16v284z" fill="url(#paint252_linear_1711_311696)" style="fill:url(#paint252_linear_1711_311696)"/><path d="m855.5 1169.5v-282.5c0-8.008 6.492-14.5 14.5-14.5s14.5 6.492 14.5 14.5v282.5z" stroke="#000" stroke-opacity=".12" stroke-width="3"/><rect x="80" y="1171" width="100" height="29" rx="7" fill="#fff"/><rect x="80" y="1171" width="100" height="29" rx="7" fill="url(#paint253_linear_1711_311696)" style="fill:url(#paint253_linear_1711_311696)"/><rect x="81.5" y="1172.5" width="97" height="26" rx="5.5" stroke="#000" stroke-opacity=".12" stroke-width="3"/><rect x="820" y="1171" width="100" height="29" rx="7" fill="#fff"/><rect x="820" y="1171" width="100" height="29" rx="7" fill="url(#paint254_linear_1711_311696)" style="fill:url(#paint254_linear_1711_311696)"/><rect x="821.5" y="1172.5" width="97" height="26" rx="5.5" stroke="#000" stroke-opacity=".12" stroke-width="3"/><defs>
<filter id="filter0_ii_1711_311697" x="376" y="44" width="248" height="88" color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>

Before

Width:  |  Height:  |  Size: 119 KiB

After

Width:  |  Height:  |  Size: 119 KiB

2
application/src/main/data/json/system/scada_symbols/large-vertical-separator-hp.svg

@ -336,7 +336,7 @@
}
]
}]]></tb:metadata>
<rect x="1" y="1" width="598" height="998" rx="159" fill="#fff" stroke="#1A1A1A" stroke-width="2" tb:tag="background"/><path d="m201.79 0s-201.79 0-201.79 167.5v820.9c0 6.628 5.3727 11.601 12 11.601h576c6.627 0 12-4.973 12-11.601v-820.9c0-167.5-198.21-167.5-198.21-167.5h-101.79zm201.21 203c-3.8661 0-6.9996 3.134-6.9996 7v751c0 3.866 3.1341 7 6.9996 7h43.998c3.8661 0 6.9996-3.134 6.9996-7v-751c0-3.866-3.1341-7-6.9996-7z" fill-opacity="0" tb:tag="clickArea"/><g transform="translate(0,916)" fill="#d12730" style="display: none;" tb:tag="critical">
<rect x="1" y="1" width="598" height="998" rx="159" fill="#fff" stroke="#1A1A1A" stroke-width="2" tb:tag="background"/><path d="m201.79 0s-201.79 0-201.79 167.5v820.9c0 6.628 5.3727 11.601 12 11.601h576c6.627 0 12-4.973 12-11.601v-820.9c0-167.5-198.21-167.5-198.21-167.5h-101.79zm201.21 203c-3.8661 0-6.9996 3.134-6.9996 7v751c0 3.866 3.1341 7 6.9996 7h43.998c3.8661 0 6.9996-3.134 6.9996-7v-751c0-3.866-3.1341-7-6.9996-7z" fill-opacity="0" fill="#000" tb:tag="clickArea"/><g transform="translate(0,916)" 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=""/>

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 13 KiB

2
application/src/main/data/json/system/scada_symbols/leak-sensor.svg

@ -135,7 +135,7 @@
}
]
}]]></tb:metadata>
<rect x=".5" y=".5" width="99" height="99" rx="23.5" fill="#fff" tb:tag="background"/><rect x=".5" y=".5" width="99" height="99" rx="23.5" fill="url(#paint0_linear_2089_217648)"/><rect x=".5" y=".5" width="99" height="99" rx="23.5" fill="url(#paint1_linear_2089_217648)"/><rect x=".5" y=".5" width="99" height="99" rx="23.5" stroke="#fff"/><path d="m56.668 52.309c0 2.04-0.7902 3.9966-2.1967 5.4391-0.7985 0.819-1.7586 1.4347-2.8035 1.8135m10-6.7401c0-10.962-11.667-19.487-11.667-19.487s-11.667 8.5256-11.667 19.487c0 3.2301 1.2292 6.3283 3.4171 8.6125 2.1879 2.284 5.1556 3.5659 8.2497 3.5659 3.0942 0 6.0615-1.2826 8.2493-3.5666 2.188-2.2842 3.4172-5.3817 3.4172-8.6118z" stroke="#1C943E" stroke-linecap="round" stroke-linejoin="round" stroke-width="3" tb:tag="icon"/><path d="m33.631 0s-33.631 0-33.631 16.75v82.09c0 0.6628 0.89543 1.1601 2 1.1601h96c1.1045 0 2-0.4973 2-1.1601v-82.09c0-16.75-33.035-16.75-33.035-16.75h-16.965zm33.535 20.3c-0.64434 0-1.1666 0.3134-1.1666 0.7v75.1c0 0.3866 0.52234 0.7 1.1666 0.7h7.3336c0.64434 0 1.1666-0.3134 1.1666-0.7v-75.1c0-0.3866-0.52233-0.7-1.1666-0.7z" fill="#000" fill-opacity="0" style="stroke-width:.059761" tb:tag="clickArea"/><defs>
<rect x=".5" y=".5" width="99" height="99" rx="23.5" fill="#fff" tb:tag="background"/><rect x=".5" y=".5" width="99" height="99" rx="23.5" fill="url(#paint0_linear_2089_217648)"/><rect x=".5" y=".5" width="99" height="99" rx="23.5" fill="url(#paint1_linear_2089_217648)"/><rect x=".5" y=".5" width="99" height="99" rx="23.5" stroke="#fff"/><path d="m56.668 52.309c0 2.04-0.7902 3.9966-2.1967 5.4391-0.7985 0.819-1.7586 1.4347-2.8035 1.8135m10-6.7401c0-10.962-11.667-19.487-11.667-19.487s-11.667 8.5256-11.667 19.487c0 3.2301 1.2292 6.3283 3.4171 8.6125 2.1879 2.284 5.1556 3.5659 8.2497 3.5659 3.0942 0 6.0615-1.2826 8.2493-3.5666 2.188-2.2842 3.4172-5.3817 3.4172-8.6118z" stroke="#1C943E" stroke-linecap="round" stroke-linejoin="round" stroke-width="3" tb:tag="icon"/><path d="m33.631 0s-33.631 0-33.631 16.75v82.09c0 0.6628 0.89543 1.1601 2 1.1601h96c1.1045 0 2-0.4973 2-1.1601v-82.09c0-16.75-33.035-16.75-33.035-16.75h-16.965zm33.535 20.3c-0.64434 0-1.1666 0.3134-1.1666 0.7v75.1c0 0.3866 0.52234 0.7 1.1666 0.7h7.3336c0.64434 0 1.1666-0.3134 1.1666-0.7v-75.1c0-0.3866-0.52233-0.7-1.1666-0.7z" fill="#000" fill-opacity="0" tb:tag="clickArea"/><defs>
<linearGradient id="paint0_linear_2089_217648" x1="100" x2="1.5002" y1="50.119" y2="49.881" gradientUnits="userSpaceOnUse">
<stop stop-color="#020202" stop-opacity=".2" offset="0"/>
<stop stop-color="#020202" stop-opacity=".12" offset=".05"/>

Before

Width:  |  Height:  |  Size: 6.0 KiB

After

Width:  |  Height:  |  Size: 6.0 KiB

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

@ -264,7 +264,7 @@
<rect transform="matrix(-4.3711e-8 1 1 4.3711e-8 -4.3711e-8 350)" x="1" y="1" width="46" height="184" rx="1" stroke-width="2"/>
<rect transform="matrix(-4.3711e-8 1 1 4.3711e-8 214 350)" x="1" y="1" width="46" height="184" rx="1" stroke-width="2"/>
<rect x="185" y="1" width="30" height="798" rx="5" stroke-width="2"/>
</g><path d="m134.53 0s-134.53 0-134.53 134v656.72c0 5.3024 3.5818 9.2806 8 9.2806h384c4.418 0 8-3.9784 8-9.2806v-656.72c0-134-132.14-134-132.14-134h-67.86zm134.14 162.4c-2.5774 0-4.6666 2.5072-4.6666 5.6v600.8c0 3.0928 2.0894 5.6 4.6666 5.6h29.332c2.5774 0 4.6666-2.5072 4.6666-5.6v-600.8c0-3.0928-2.0894-5.6-4.6666-5.6z" fill-opacity="0" style="stroke-width:2.0908" tb:tag="clickArea"/><g fill="#d12730" style="display: none;" tb:tag="critical">
</g><path d="m134.53 0s-134.53 0-134.53 134v656.72c0 5.3024 3.5818 9.2806 8 9.2806h384c4.418 0 8-3.9784 8-9.2806v-656.72c0-134-132.14-134-132.14-134h-67.86zm134.14 162.4c-2.5774 0-4.6666 2.5072-4.6666 5.6v600.8c0 3.0928 2.0894 5.6 4.6666 5.6h29.332c2.5774 0 4.6666-2.5072 4.6666-5.6v-600.8c0-3.0928-2.0894-5.6-4.6666-5.6z" fill-opacity="0" fill="#000" 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=""/>

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 11 KiB

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

@ -713,7 +713,7 @@
<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>
</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" 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"/>

Before

Width:  |  Height:  |  Size: 58 KiB

After

Width:  |  Height:  |  Size: 58 KiB

2
application/src/main/data/json/system/scada_symbols/oil-pump-hp.svg

@ -343,7 +343,7 @@
<path d="m24.767 832.67c0.5636-1.6 2.0759-2.671 3.7729-2.671h152.67c1.791 0 3.364 1.191 3.85 2.915l18.592 66c0.199 0.71 0.199 1.46 0 2.17l-18.592 66c-0.486 1.724-2.059 2.915-3.85 2.915h-152.67c-1.697 0-3.2093-1.071-3.7729-2.671l-23.239-66c-0.30274-0.86-0.30274-1.798 0-2.658l23.239-66z"/>
<rect x="65" y="970" width="76" height="191"/>
<path d="m134.96 889.96c6.62-6.619 17.351-6.619 23.97 0l124.1 124.11c6.619 6.61 6.619 17.35 0 23.97-6.62 6.61-17.351 6.61-23.97 0l-124.1-124.11c-6.619-6.619-6.619-17.35 0-23.97z"/>
</g><path d="m278.34 1033.8c-4.296 4.29-11.261 4.29-15.557 0-4.295-4.3-4.295-11.26 0-15.56 4.296-4.29 11.261-4.29 15.557 0 4.296 4.3 4.296 11.26 0 15.56z" stroke="#1A1A1A" stroke-width="2"/><path d="m155.75 910.75c-4.296 4.296-11.261 4.296-15.556 0-4.296-4.296-4.296-11.261 0-15.556 4.295-4.296 11.26-4.296 15.556 0 4.296 4.295 4.296 11.26 0 15.556z" 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.666 3.7608-11.666 8.4v901.2c0 4.6392 5.2235 8.4 11.666 8.4h73.33c6.4435 0 11.666-3.7608 11.666-8.4v-901.2c0-4.6392-5.2235-8.4-11.666-8.4z" fill="#000" fill-opacity="0" style="stroke-width:2.2361" tb:tag="clickArea"/><g transform="translate(0,1116)" fill="#d12730" style="display: none;" tb:tag="critical">
</g><path d="m278.34 1033.8c-4.296 4.29-11.261 4.29-15.557 0-4.295-4.3-4.295-11.26 0-15.56 4.296-4.29 11.261-4.29 15.557 0 4.296 4.3 4.296 11.26 0 15.56z" stroke="#1A1A1A" stroke-width="2"/><path d="m155.75 910.75c-4.296 4.296-11.261 4.296-15.556 0-4.296-4.296-4.296-11.261 0-15.556 4.295-4.296 11.26-4.296 15.556 0 4.296 4.295 4.296 11.26 0 15.556z" 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.666 3.7608-11.666 8.4v901.2c0 4.6392 5.2235 8.4 11.666 8.4h73.33c6.4435 0 11.666-3.7608 11.666-8.4v-901.2c0-4.6392-5.2235-8.4-11.666-8.4z" fill="#000" fill-opacity="0" tb:tag="clickArea"/><g transform="translate(0,1116)" 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=""/>

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 16 KiB

2
application/src/main/data/json/system/scada_symbols/pool-hp.svg

@ -501,7 +501,7 @@
<path d="m275.2 639.35v2.25h-11.437v-1.934l5.554-6.059c0.61-0.687 1.09-1.281 1.442-1.781 0.351-0.5 0.598-0.949 0.738-1.347 0.149-0.407 0.223-0.801 0.223-1.184 0-0.539-0.102-1.012-0.305-1.418-0.195-0.414-0.484-0.738-0.867-0.973-0.383-0.242-0.848-0.363-1.395-0.363-0.632 0-1.164 0.137-1.593 0.41-0.43 0.274-0.754 0.653-0.973 1.137-0.219 0.476-0.328 1.023-0.328 1.641h-2.824c0-0.993 0.226-1.899 0.679-2.719 0.453-0.828 1.11-1.485 1.969-1.969 0.86-0.492 1.895-0.738 3.106-0.738 1.14 0 2.109 0.191 2.906 0.574s1.402 0.926 1.816 1.629c0.422 0.703 0.633 1.535 0.633 2.496 0 0.531-0.086 1.059-0.258 1.582s-0.418 1.047-0.738 1.57c-0.313 0.516-0.684 1.035-1.113 1.559-0.43 0.516-0.903 1.039-1.418 1.57l-3.692 4.067zm13.575-7.711v2.789c0 1.336-0.133 2.476-0.399 3.422-0.258 0.937-0.633 1.699-1.125 2.285s-1.082 1.015-1.769 1.289c-0.68 0.273-1.442 0.41-2.286 0.41-0.671 0-1.296-0.086-1.875-0.258-0.57-0.172-1.086-0.441-1.546-0.808-0.461-0.368-0.856-0.84-1.184-1.418-0.32-0.586-0.57-1.286-0.75-2.098-0.172-0.813-0.258-1.754-0.258-2.824v-2.789c0-1.344 0.133-2.477 0.399-3.399 0.265-0.929 0.644-1.683 1.136-2.261 0.492-0.586 1.078-1.012 1.758-1.278 0.688-0.265 1.453-0.398 2.297-0.398 0.68 0 1.305 0.086 1.875 0.258 0.578 0.164 1.094 0.425 1.547 0.785 0.461 0.359 0.851 0.828 1.172 1.406 0.328 0.57 0.578 1.262 0.75 2.074 0.172 0.805 0.258 1.742 0.258 2.813zm-2.825 3.187v-3.609c0-0.68-0.039-1.278-0.117-1.793-0.078-0.524-0.195-0.965-0.351-1.324-0.149-0.368-0.336-0.664-0.563-0.891-0.226-0.234-0.484-0.402-0.773-0.504-0.289-0.109-0.614-0.164-0.973-0.164-0.438 0-0.828 0.086-1.172 0.258-0.344 0.164-0.633 0.43-0.867 0.797s-0.414 0.851-0.539 1.453c-0.117 0.594-0.176 1.316-0.176 2.168v3.609c0 0.688 0.039 1.293 0.117 1.817 0.078 0.523 0.196 0.972 0.352 1.347 0.156 0.367 0.344 0.672 0.562 0.914 0.227 0.235 0.485 0.407 0.774 0.516 0.297 0.109 0.621 0.164 0.972 0.164 0.446 0 0.84-0.086 1.184-0.258s0.633-0.445 0.867-0.82c0.235-0.383 0.41-0.879 0.528-1.488 0.117-0.61 0.175-1.34 0.175-2.192z" fill="#000" fill-opacity=".38"/>
<path d="m271.47 702.18v17.121h-2.824v-13.77l-4.184 1.418v-2.332l6.668-2.437zm17.301 7.16v2.789c0 1.336-0.133 2.476-0.399 3.422-0.258 0.937-0.633 1.699-1.125 2.285s-1.082 1.016-1.769 1.289c-0.68 0.273-1.442 0.41-2.286 0.41-0.671 0-1.296-0.086-1.875-0.258-0.57-0.172-1.086-0.441-1.546-0.808-0.461-0.367-0.856-0.84-1.184-1.418-0.32-0.586-0.57-1.285-0.75-2.098-0.172-0.812-0.258-1.754-0.258-2.824v-2.789c0-1.344 0.133-2.477 0.399-3.399 0.265-0.929 0.644-1.683 1.136-2.261 0.492-0.586 1.078-1.012 1.758-1.278 0.688-0.265 1.453-0.398 2.297-0.398 0.68 0 1.305 0.086 1.875 0.258 0.578 0.164 1.094 0.426 1.547 0.785 0.461 0.359 0.851 0.828 1.172 1.406 0.328 0.57 0.578 1.262 0.75 2.074 0.172 0.805 0.258 1.743 0.258 2.813zm-2.825 3.187v-3.609c0-0.68-0.039-1.277-0.117-1.793-0.078-0.523-0.195-0.965-0.351-1.324-0.149-0.367-0.336-0.664-0.563-0.891-0.226-0.234-0.484-0.402-0.773-0.504-0.289-0.109-0.614-0.164-0.973-0.164-0.438 0-0.828 0.086-1.172 0.258-0.344 0.164-0.633 0.43-0.867 0.797s-0.414 0.851-0.539 1.453c-0.117 0.594-0.176 1.316-0.176 2.168v3.609c0 0.688 0.039 1.293 0.117 1.817 0.078 0.523 0.196 0.972 0.352 1.347 0.156 0.368 0.344 0.672 0.562 0.914 0.227 0.235 0.485 0.407 0.774 0.516 0.297 0.109 0.621 0.164 0.972 0.164 0.446 0 0.84-0.086 1.184-0.258s0.633-0.445 0.867-0.82c0.235-0.383 0.41-0.879 0.528-1.488 0.117-0.61 0.175-1.34 0.175-2.192z" fill="#000" fill-opacity=".38"/>
<path d="m288.77 787.04v2.789c0 1.336-0.133 2.477-0.399 3.422-0.258 0.938-0.633 1.699-1.125 2.285s-1.082 1.016-1.769 1.289c-0.68 0.274-1.442 0.41-2.286 0.41-0.671 0-1.296-0.086-1.875-0.257-0.57-0.172-1.086-0.442-1.546-0.809-0.461-0.367-0.856-0.84-1.184-1.418-0.32-0.586-0.57-1.285-0.75-2.098-0.172-0.812-0.258-1.754-0.258-2.824v-2.789c0-1.344 0.133-2.477 0.399-3.398 0.265-0.93 0.644-1.684 1.136-2.262 0.492-0.586 1.078-1.012 1.758-1.277 0.688-0.266 1.453-0.399 2.297-0.399 0.68 0 1.305 0.086 1.875 0.258 0.578 0.164 1.094 0.426 1.547 0.785 0.461 0.359 0.851 0.828 1.172 1.406 0.328 0.571 0.578 1.262 0.75 2.075 0.172 0.804 0.258 1.742 0.258 2.812zm-2.825 3.188v-3.61c0-0.679-0.039-1.277-0.117-1.793-0.078-0.523-0.195-0.965-0.351-1.324-0.149-0.367-0.336-0.664-0.563-0.891-0.226-0.234-0.484-0.402-0.773-0.504-0.289-0.109-0.614-0.164-0.973-0.164-0.438 0-0.828 0.086-1.172 0.258-0.344 0.164-0.633 0.43-0.867 0.797s-0.414 0.852-0.539 1.453c-0.117 0.594-0.176 1.317-0.176 2.168v3.61c0 0.687 0.039 1.293 0.117 1.816s0.196 0.973 0.352 1.348c0.156 0.367 0.344 0.671 0.562 0.914 0.227 0.234 0.485 0.406 0.774 0.515 0.297 0.11 0.621 0.164 0.972 0.164 0.446 0 0.84-0.086 1.184-0.257 0.344-0.172 0.633-0.446 0.867-0.821 0.235-0.383 0.41-0.879 0.528-1.488 0.117-0.609 0.175-1.34 0.175-2.191z" fill="#000" fill-opacity=".38"/>
</g><path d="m807.17 0s-807.17 0-807.17 134v656.72c0 5.3024 21.491 9.2808 48 9.2808h2304c26.508 0 48-3.9784 48-9.2808v-656.72c0-134-792.84-134-792.84-134h-407.15zm804.84 162.4c-15.464 0-28 2.5072-28 5.6v600.8c0 3.0928 12.536 5.6 28 5.6h175.99c15.464 0 28-2.5072 28-5.6v-600.8c0-3.0928-12.536-5.6-28-5.6z" fill="#000" fill-opacity="0" style="stroke-width:6.9281" tb:tag="clickArea"/><g fill="#d12730" style="display: none;" tb:tag="critical">
</g><path d="m807.17 0s-807.17 0-807.17 134v656.72c0 5.3024 21.491 9.2808 48 9.2808h2304c26.508 0 48-3.9784 48-9.2808v-656.72c0-134-792.84-134-792.84-134h-407.15zm804.84 162.4c-15.464 0-28 2.5072-28 5.6v600.8c0 3.0928 12.536 5.6 28 5.6h175.99c15.464 0 28-2.5072 28-5.6v-600.8c0-3.0928-12.536-5.6-28-5.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=""/>

Before

Width:  |  Height:  |  Size: 48 KiB

After

Width:  |  Height:  |  Size: 48 KiB

2
application/src/main/data/json/system/scada_symbols/pool.svg

@ -292,7 +292,7 @@
<path d="m1076 372.19c0-8.9433 6.8853-16.194 15.378-16.194h276.79c8.4922 0 15.377 7.251 15.377 16.194v75.573c0 8.9433-6.8852 16.194-15.377 16.194h-276.79c-8.4922 0-15.378-7.251-15.378-16.194z" fill="#f3f3f3" tb:tag="value-box-background"/>
<path d="m1078 372.16c0-7.8336 6.0222-14.184 13.451-14.184h276.7c7.4286 0 13.451 6.3503 13.451 14.184v75.647c0 7.8336-6.0221 14.184-13.451 14.184h-276.7c-7.4285 0-13.451-6.3503-13.451-14.184z" stroke="#727171" stroke-width="3.9464"/>
<text x="1235.9021" y="410.52652" fill="#727171" font-family="Roboto" font-size="32px" font-weight="500" tb:tag="value-text" xml:space="preserve" text-anchor="middle"><tspan dominant-baseline="middle">1660 gal</tspan></text>
</g><path d="m2388 0c6.63 0 12 5.3726 12 12v15c0 6.6274-5.37 12-12 12h-2376c-6.6274 0-12-5.3726-12-12v-15c0-6.6274 5.3726-12 12-12h2376z" fill="#647484"/><path d="m2388 0c6.63 0 12 5.3726 12 12v15c0 6.6274-5.37 12-12 12h-2376c-6.6274 0-12-5.3726-12-12v-15c0-6.6274 5.3726-12 12-12h2376z" fill="url(#paint1846_linear_2028_445065)"/><path d="m2388 2c5.52 0 10 4.4772 10 10v15c0 5.5229-4.48 10-10 10h-2376c-5.523 0-10-4.4772-10-10v-15c0-5.5228 4.477-10 10-10h2376z" stroke="#000" stroke-opacity=".12" stroke-width="4"/><path d="m807.17 0s-807.17 0-807.17 134v656.72c0 5.3024 21.49 9.2807 48 9.2807h2304c26.508 0 48-3.9784 48-9.2807v-656.72c0-134-792.84-134-792.84-134h-407.16zm804.84 162.4c-15.464 0-28.001 2.5072-28.001 5.6v600.8c0 3.0928 12.536 5.6 28.001 5.6h176c15.464 0 28.001-2.5072 28.001-5.6v-600.8c0-3.0928-12.536-5.6-28.001-5.6z" fill="#000" fill-opacity="0" style="stroke-width:1.2649" tb:tag="clickArea"/><defs>
</g><path d="m2388 0c6.63 0 12 5.3726 12 12v15c0 6.6274-5.37 12-12 12h-2376c-6.6274 0-12-5.3726-12-12v-15c0-6.6274 5.3726-12 12-12h2376z" fill="#647484"/><path d="m2388 0c6.63 0 12 5.3726 12 12v15c0 6.6274-5.37 12-12 12h-2376c-6.6274 0-12-5.3726-12-12v-15c0-6.6274 5.3726-12 12-12h2376z" fill="url(#paint1846_linear_2028_445065)"/><path d="m2388 2c5.52 0 10 4.4772 10 10v15c0 5.5229-4.48 10-10 10h-2376c-5.523 0-10-4.4772-10-10v-15c0-5.5228 4.477-10 10-10h2376z" stroke="#000" stroke-opacity=".12" stroke-width="4"/><path d="m807.17 0s-807.17 0-807.17 134v656.72c0 5.3024 21.49 9.2807 48 9.2807h2304c26.508 0 48-3.9784 48-9.2807v-656.72c0-134-792.84-134-792.84-134h-407.16zm804.84 162.4c-15.464 0-28.001 2.5072-28.001 5.6v600.8c0 3.0928 12.536 5.6 28.001 5.6h176c15.464 0 28.001-2.5072 28.001-5.6v-600.8c0-3.0928-12.536-5.6-28.001-5.6z" fill="#000" fill-opacity="0" tb:tag="clickArea"/><defs>
<filter id="filter0_ii_2028_445065" x="1076" y="356" width="308" height="108" color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>

Before

Width:  |  Height:  |  Size: 73 KiB

After

Width:  |  Height:  |  Size: 73 KiB

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

@ -357,7 +357,7 @@
<rect transform="rotate(90,85,124)" x="85" y="124" width="6" height="24" rx="1" fill="#1a1a1a" style=""/>
<rect transform="rotate(-90,115,130)" x="115" y="130" width="6" height="24" rx="1" fill="#1a1a1a" style=""/>
<rect x="95" y="70" width="10" height="24" rx="1" fill="#1a1a1a" style=""/>
</g><path d="m67.267 0s-67.267 0-67.267 33.5v164.18c0 1.3256 1.7909 2.3202 4 2.3202h192c2.209 0 4-0.9946 4-2.3202v-164.18c0-33.5-66.07-33.5-66.07-33.5h-33.93zm67.07 40.6c-1.2887 0-2.3333 0.6268-2.3333 1.4v150.2c0 0.7732 1.0447 1.4 2.3333 1.4h14.666c1.2887 0 2.3333-0.6268 2.3333-1.4v-150.2c0-0.7732-1.0447-1.4-2.3333-1.4z" fill-opacity="0" tb:tag="clickArea"/><g fill="#d12730" style="display: none;" tb:tag="critical">
</g><path d="m67.267 0s-67.267 0-67.267 33.5v164.18c0 1.3256 1.7909 2.3202 4 2.3202h192c2.209 0 4-0.9946 4-2.3202v-164.18c0-33.5-66.07-33.5-66.07-33.5h-33.93zm67.07 40.6c-1.2887 0-2.3333 0.6268-2.3333 1.4v150.2c0 0.7732 1.0447 1.4 2.3333 1.4h14.666c1.2887 0 2.3333-0.6268 2.3333-1.4v-150.2c0-0.7732-1.0447-1.4-2.3333-1.4z" fill-opacity="0" fill="#000" 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=""/>

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 14 KiB

2
application/src/main/data/json/system/scada_symbols/short-vertical-tank-hp.svg

@ -502,7 +502,7 @@
<path d="m145.2 478.55v2.25h-11.437v-1.934l5.554-6.058c0.61-0.688 1.09-1.282 1.442-1.782 0.351-0.5 0.598-0.949 0.738-1.347 0.149-0.407 0.223-0.801 0.223-1.184 0-0.539-0.102-1.012-0.305-1.418-0.195-0.414-0.484-0.738-0.867-0.973-0.383-0.242-0.848-0.363-1.395-0.363-0.632 0-1.164 0.137-1.593 0.41-0.43 0.274-0.754 0.653-0.973 1.137-0.219 0.477-0.328 1.023-0.328 1.641h-2.824c0-0.992 0.226-1.899 0.679-2.719 0.453-0.828 1.11-1.484 1.969-1.969 0.86-0.492 1.895-0.738 3.106-0.738 1.14 0 2.109 0.191 2.906 0.574s1.402 0.926 1.816 1.629c0.422 0.703 0.633 1.535 0.633 2.496 0 0.531-0.086 1.059-0.258 1.582-0.172 0.524-0.418 1.047-0.738 1.57-0.313 0.516-0.684 1.036-1.113 1.559-0.43 0.516-0.903 1.039-1.418 1.57l-3.692 4.067zm13.575-7.711v2.789c0 1.336-0.133 2.476-0.399 3.422-0.258 0.937-0.633 1.699-1.125 2.285s-1.082 1.016-1.769 1.289c-0.68 0.273-1.442 0.41-2.286 0.41-0.671 0-1.296-0.086-1.875-0.258-0.57-0.172-1.086-0.441-1.546-0.808-0.461-0.367-0.856-0.84-1.184-1.418-0.32-0.586-0.57-1.285-0.75-2.098-0.172-0.812-0.258-1.754-0.258-2.824v-2.789c0-1.344 0.133-2.477 0.399-3.399 0.265-0.929 0.644-1.683 1.136-2.261 0.492-0.586 1.078-1.012 1.758-1.278 0.688-0.265 1.453-0.398 2.297-0.398 0.68 0 1.305 0.086 1.875 0.258 0.578 0.164 1.094 0.426 1.547 0.785 0.461 0.359 0.851 0.828 1.172 1.406 0.328 0.57 0.578 1.262 0.75 2.074 0.172 0.805 0.258 1.743 0.258 2.813zm-2.825 3.187v-3.609c0-0.68-0.039-1.277-0.117-1.793-0.078-0.523-0.195-0.965-0.351-1.324-0.149-0.367-0.336-0.664-0.563-0.891-0.226-0.234-0.484-0.402-0.773-0.504-0.289-0.109-0.614-0.164-0.973-0.164-0.438 0-0.828 0.086-1.172 0.258-0.344 0.164-0.633 0.43-0.867 0.797s-0.414 0.851-0.539 1.453c-0.117 0.594-0.176 1.316-0.176 2.168v3.609c0 0.688 0.039 1.293 0.117 1.817 0.078 0.523 0.196 0.972 0.352 1.347 0.156 0.368 0.344 0.672 0.562 0.914 0.227 0.235 0.485 0.407 0.774 0.516 0.297 0.109 0.621 0.164 0.972 0.164 0.446 0 0.84-0.086 1.184-0.258s0.633-0.445 0.867-0.82c0.235-0.383 0.41-0.879 0.528-1.488 0.117-0.61 0.175-1.34 0.175-2.192z" fill="#000" fill-opacity=".38"/>
<path d="m141.47 521.28v17.121h-2.824v-13.769l-4.184 1.418v-2.332l6.668-2.438zm17.301 7.16v2.79c0 1.335-0.133 2.476-0.399 3.421-0.258 0.938-0.633 1.7-1.125 2.286-0.492 0.585-1.082 1.015-1.769 1.289-0.68 0.273-1.442 0.41-2.286 0.41-0.671 0-1.296-0.086-1.875-0.258-0.57-0.172-1.086-0.441-1.546-0.809-0.461-0.367-0.856-0.839-1.184-1.418-0.32-0.586-0.57-1.285-0.75-2.097-0.172-0.813-0.258-1.754-0.258-2.824v-2.79c0-1.343 0.133-2.476 0.399-3.398 0.265-0.93 0.644-1.684 1.136-2.262 0.492-0.586 1.078-1.011 1.758-1.277 0.688-0.266 1.453-0.398 2.297-0.398 0.68 0 1.305 0.085 1.875 0.257 0.578 0.164 1.094 0.426 1.547 0.785 0.461 0.36 0.851 0.829 1.172 1.407 0.328 0.57 0.578 1.261 0.75 2.074 0.172 0.805 0.258 1.742 0.258 2.812zm-2.825 3.188v-3.609c0-0.68-0.039-1.278-0.117-1.793-0.078-0.524-0.195-0.965-0.351-1.325-0.149-0.367-0.336-0.664-0.563-0.89-0.226-0.235-0.484-0.403-0.773-0.504-0.289-0.11-0.614-0.164-0.973-0.164-0.438 0-0.828 0.086-1.172 0.258-0.344 0.164-0.633 0.429-0.867 0.796-0.234 0.368-0.414 0.852-0.539 1.454-0.117 0.593-0.176 1.316-0.176 2.168v3.609c0 0.687 0.039 1.293 0.117 1.816 0.078 0.524 0.196 0.973 0.352 1.348 0.156 0.367 0.344 0.672 0.562 0.914 0.227 0.234 0.485 0.406 0.774 0.516 0.297 0.109 0.621 0.164 0.972 0.164 0.446 0 0.84-0.086 1.184-0.258s0.633-0.445 0.867-0.82c0.235-0.383 0.41-0.879 0.528-1.489 0.117-0.609 0.175-1.339 0.175-2.191z" fill="#000" fill-opacity=".38"/>
<path d="m158.77 586.04v2.789c0 1.336-0.133 2.477-0.399 3.422-0.258 0.938-0.633 1.699-1.125 2.285s-1.082 1.016-1.769 1.289c-0.68 0.274-1.442 0.41-2.286 0.41-0.671 0-1.296-0.086-1.875-0.257-0.57-0.172-1.086-0.442-1.546-0.809-0.461-0.367-0.856-0.84-1.184-1.418-0.32-0.586-0.57-1.285-0.75-2.098-0.172-0.812-0.258-1.754-0.258-2.824v-2.789c0-1.344 0.133-2.477 0.399-3.398 0.265-0.93 0.644-1.684 1.136-2.262 0.492-0.586 1.078-1.012 1.758-1.277 0.688-0.266 1.453-0.399 2.297-0.399 0.68 0 1.305 0.086 1.875 0.258 0.578 0.164 1.094 0.426 1.547 0.785 0.461 0.359 0.851 0.828 1.172 1.406 0.328 0.571 0.578 1.262 0.75 2.075 0.172 0.804 0.258 1.742 0.258 2.812zm-2.825 3.188v-3.61c0-0.679-0.039-1.277-0.117-1.793-0.078-0.523-0.195-0.965-0.351-1.324-0.149-0.367-0.336-0.664-0.563-0.891-0.226-0.234-0.484-0.402-0.773-0.504-0.289-0.109-0.614-0.164-0.973-0.164-0.438 0-0.828 0.086-1.172 0.258-0.344 0.164-0.633 0.43-0.867 0.797s-0.414 0.852-0.539 1.453c-0.117 0.594-0.176 1.317-0.176 2.168v3.61c0 0.687 0.039 1.293 0.117 1.816s0.196 0.973 0.352 1.348c0.156 0.367 0.344 0.671 0.562 0.914 0.227 0.234 0.485 0.406 0.774 0.515 0.297 0.11 0.621 0.164 0.972 0.164 0.446 0 0.84-0.086 1.184-0.257 0.344-0.172 0.633-0.446 0.867-0.821 0.235-0.383 0.41-0.879 0.528-1.488 0.117-0.609 0.175-1.34 0.175-2.191z" fill="#000" fill-opacity=".38"/>
</g><path d="m201.79 0s-201.79 0-201.79 100.5v492.54c0 3.9768 5.3727 6.9606 12 6.9606h576c6.627 0 12-2.9838 12-6.9606v-492.54c0-100.5-198.21-100.5-198.21-100.5h-101.79zm201.21 121.8c-3.866 0-7 1.8804-7 4.2v450.6c0 2.3196 3.134 4.2 7 4.2h43.998c3.866 0 7-1.8804 7-4.2v-450.6c0-2.3196-3.134-4.2-7-4.2z" fill="#000" fill-opacity="0" style="stroke-width:.43301" tb:tag="clickArea"/><g fill="#d12730" style="display: none;" tb:tag="critical">
</g><path d="m201.79 0s-201.79 0-201.79 100.5v492.54c0 3.9768 5.3727 6.9606 12 6.9606h576c6.627 0 12-2.9838 12-6.9606v-492.54c0-100.5-198.21-100.5-198.21-100.5h-101.79zm201.21 121.8c-3.866 0-7 1.8804-7 4.2v450.6c0 2.3196 3.134 4.2 7 4.2h43.998c3.866 0 7-1.8804 7-4.2v-450.6c0-2.3196-3.134-4.2-7-4.2z" 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=""/>

Before

Width:  |  Height:  |  Size: 50 KiB

After

Width:  |  Height:  |  Size: 50 KiB

2
application/src/main/data/json/system/scada_symbols/simple-horizontal-scale-hp.svg

@ -719,5 +719,5 @@
<rect transform="scale(-1,1)" x="-732.5" y="183.5" width="81" height="41" fill="#666" tb:tag="highCriticalScale"/>
</g><g transform="translate(400)" style="display: none;" tb:tag="target">
<rect transform="rotate(45)" x="201.8" y="64.66" width="22" height="22" fill="#dedede" stroke="#000" stroke-width="2" tb:tag="targetBackground" style=""/>
</g><path d="m269.06 0s-269.06 0-269.06 67v328.36c0 2.6512 7.1634 4.6404 16 4.6404h768c8.836 0 16-1.9892 16-4.6404v-328.36c0-67-264.28-67-264.28-67h-135.72zm268.28 81.2c-5.1546 0-9.3334 1.2536-9.3334 2.8v300.4c0 1.5464 4.1786 2.8 9.3334 2.8h58.666c5.1546 0 9.3334-1.2536 9.3334-2.8v-300.4c0-1.5464-4.1786-2.8-9.3334-2.8z" fill="#000" fill-opacity="0" style="stroke-width:.7303" tb:tag="clickArea"/>
</g><path d="m269.06 0s-269.06 0-269.06 67v328.36c0 2.6512 7.1634 4.6404 16 4.6404h768c8.836 0 16-1.9892 16-4.6404v-328.36c0-67-264.28-67-264.28-67h-135.72zm268.28 81.2c-5.1546 0-9.3334 1.2536-9.3334 2.8v300.4c0 1.5464 4.1786 2.8 9.3334 2.8h58.666c5.1546 0 9.3334-1.2536 9.3334-2.8v-300.4c0-1.5464-4.1786-2.8-9.3334-2.8z" fill="#000" fill-opacity="0" tb:tag="clickArea"/>
</svg>

Before

Width:  |  Height:  |  Size: 27 KiB

After

Width:  |  Height:  |  Size: 27 KiB

2
application/src/main/data/json/system/scada_symbols/simple-vertical-scale-hp.svg

@ -719,5 +719,5 @@
<text x="223.60547" y="739.125" fill="#002878" font-family="Roboto" font-size="60px" font-weight="400" tb:tag="value" xml:space="preserve"><tspan dominant-baseline="middle">26</tspan></text>
</g><g transform="translate(0,-400)" style="display: none;" tb:tag="target">
<rect transform="rotate(-45)" x="-379.76" y="636.31" width="22" height="22" fill="#dedede" stroke="#000" stroke-width="2" tb:tag="targetBackground" style=""/>
</g><path d="m134.53 0s-134.53 0-134.53 134v656.72c0 5.3024 3.5817 9.2808 8 9.2808h384c4.418 0 8-3.9784 8-9.2808v-656.72c0-134-132.14-134-132.14-134h-67.86zm134.14 162.4c-2.5773 0-4.6667 2.5072-4.6667 5.6v600.8c0 3.0928 2.0893 5.6 4.6667 5.6h29.333c2.5773 0 4.6667-2.5072 4.6667-5.6v-600.8c0-3.0928-2.0893-5.6-4.6667-5.6z" fill="#000" fill-opacity="0" style="stroke-width:.7303" tb:tag="clickArea"/>
</g><path d="m134.53 0s-134.53 0-134.53 134v656.72c0 5.3024 3.5817 9.2808 8 9.2808h384c4.418 0 8-3.9784 8-9.2808v-656.72c0-134-132.14-134-132.14-134h-67.86zm134.14 162.4c-2.5773 0-4.6667 2.5072-4.6667 5.6v600.8c0 3.0928 2.0893 5.6 4.6667 5.6h29.333c2.5773 0 4.6667-2.5072 4.6667-5.6v-600.8c0-3.0928-2.0893-5.6-4.6667-5.6z" fill="#000" fill-opacity="0" tb:tag="clickArea"/>
</svg>

Before

Width:  |  Height:  |  Size: 27 KiB

After

Width:  |  Height:  |  Size: 27 KiB

2
application/src/main/data/json/system/scada_symbols/small-cylindrical-tank.svg

@ -537,7 +537,7 @@
<path d="m381 272c0-6.627 5.373-12 12-12h216c6.627 0 12 5.373 12 12v56c0 6.627-5.373 12-12 12h-216c-6.627 0-12-5.373-12-12z" fill="#f3f3f3" tb:tag="value-box-background"/>
<path d="m382.5 272c0-5.799 4.701-10.5 10.5-10.5h216c5.799 0 10.5 4.701 10.5 10.5v56c0 5.799-4.701 10.5-10.5 10.5h-216c-5.799 0-10.5-4.701-10.5-10.5z" stroke="#727171" stroke-width="3"/>
<text x="500.74219" y="300.07812" fill="#727171" font-family="Roboto" font-size="32px" font-weight="500" text-anchor="middle" tb:tag="value-text" xml:space="preserve"><tspan dominant-baseline="middle">1660 gal</tspan></text>
</g><path d="m201.79 0s-201.79 0-201.79 100.5v492.54c0 3.9768 5.3726 6.9606 12 6.9606h576c6.627 0 12-2.9838 12-6.9606v-492.54c0-100.5-198.21-100.5-198.21-100.5h-101.79zm201.21 121.8c-3.866 0-7 1.8804-7 4.2v450.6c0 2.3196 3.134 4.2 7 4.2h44c3.866 0 7-1.8804 7-4.2v-450.6c0-2.3196-3.134-4.2-7-4.2z" fill="#000" fill-opacity="0" style="stroke-width:.7746" tb:tag="clickArea"/><defs>
</g><path d="m201.79 0s-201.79 0-201.79 100.5v492.54c0 3.9768 5.3726 6.9606 12 6.9606h576c6.627 0 12-2.9838 12-6.9606v-492.54c0-100.5-198.21-100.5-198.21-100.5h-101.79zm201.21 121.8c-3.866 0-7 1.8804-7 4.2v450.6c0 2.3196 3.134 4.2 7 4.2h44c3.866 0 7-1.8804 7-4.2v-450.6c0-2.3196-3.134-4.2-7-4.2z" fill="#000" fill-opacity="0" tb:tag="clickArea"/><defs>
<pattern id="pattern17033" patternTransform="translate(-79.813 574.69)" xlink:href="#liquid"/>
<linearGradient id="paint0_linear_2901_184349" x1="600" x2=".019179" y1="110.96" y2="104.56" gradientUnits="userSpaceOnUse">
<stop stop-color="#020202" stop-opacity=".35" offset="0"/>

Before

Width:  |  Height:  |  Size: 99 KiB

After

Width:  |  Height:  |  Size: 99 KiB

2
application/src/main/data/json/system/scada_symbols/small-horizontal-separator-connector-hp.svg

@ -328,7 +328,7 @@
}
]
}]]></tb:metadata>
<rect x="1" y="81" width="898" height="318" rx="119" fill="#fff" stroke="#1A1A1A" stroke-width="2" tb:tag="background"/><path d="m1e3 300h-8c-16.569 0-30-13.431-30-30v-237c0-16.568-13.431-30-30-30h-240c-16.569 0-30 13.432-30 30v47" stroke="#1A1A1A" stroke-width="6"/><path d="m336.71 0.31299s-336.32 0-336.32 67v328.36c0 2.6512 8.9545 4.6403 20 4.6403h960c11.045 0 20-1.9892 20-4.6403v-328.36c0-67-330.35-67-330.35-67h-169.65zm335.35 81.2c-6.4435 0-11.666 1.2536-11.666 2.8v300.4c0 1.5464 5.2235 2.8 11.666 2.8h73.33c6.4435 0 11.666-1.2536 11.666-2.8v-300.4c0-1.5464-5.2235-2.8-11.666-2.8z" fill-opacity="0" tb:tag="clickArea"/><g transform="translate(0,316)" fill="#d12730" style="display: none;" tb:tag="critical">
<rect x="1" y="81" width="898" height="318" rx="119" fill="#fff" stroke="#1A1A1A" stroke-width="2" tb:tag="background"/><path d="m1e3 300h-8c-16.569 0-30-13.431-30-30v-237c0-16.568-13.431-30-30-30h-240c-16.569 0-30 13.432-30 30v47" stroke="#1A1A1A" stroke-width="6"/><path d="m336.71 0.31299s-336.32 0-336.32 67v328.36c0 2.6512 8.9545 4.6403 20 4.6403h960c11.045 0 20-1.9892 20-4.6403v-328.36c0-67-330.35-67-330.35-67h-169.65zm335.35 81.2c-6.4435 0-11.666 1.2536-11.666 2.8v300.4c0 1.5464 5.2235 2.8 11.666 2.8h73.33c6.4435 0 11.666-1.2536 11.666-2.8v-300.4c0-1.5464-5.2235-2.8-11.666-2.8z" fill-opacity="0" fill="#000" tb:tag="clickArea"/><g transform="translate(0,316)" fill="#d12730" style="display: none;" tb:tag="critical">
<rect width="84" height="84" rx="4" fill="#fff" style=""/>
<rect width="84" height="84" rx="4" style=""/>
<rect x="2" y="2" width="80" height="80" rx="2" stroke="#000" stroke-opacity=".87" stroke-width="4" style=""/>

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 13 KiB

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

@ -713,5 +713,5 @@
<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"/>
</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" fill="#000" tb:tag="clickArea"/>
</svg>

Before

Width:  |  Height:  |  Size: 45 KiB

After

Width:  |  Height:  |  Size: 45 KiB

2
application/src/main/data/json/system/scada_symbols/small-vertical-separator-connector-hp.svg

@ -328,7 +328,7 @@
}
]
}]]></tb:metadata>
<path d="m1 260c0-37.263 0.00859-55.699 4.0548-70.799 11.004-41.066 43.08-73.143 84.146-84.146 15.1-4.046 33.536-4.055 70.8-4.055s55.699 9e-3 70.799 4.055c41.066 11.003 73.143 43.08 84.146 84.146 4.046 15.1 4.055 33.536 4.055 70.799v580c0 37.263-9e-3 55.699-4.055 70.799-11.003 41.066-43.08 73.143-84.146 84.146-15.1 4.046-33.536 4.055-70.799 4.055s-55.699-9e-3 -70.8-4.055c-41.066-11.003-73.142-43.08-84.146-84.146-4.0462-15.1-4.0548-33.536-4.0548-70.799v-580z" fill="#fff" stroke="#1A1A1A" stroke-width="2" tb:tag="background"/><path d="m400 700h-8c-16.569 0-30-13.431-30-30v-637c0-16.569-13.431-30-30-30h-147c-16.569 0-30 13.432-30 30v67" stroke="#1A1A1A" stroke-width="6"/><path d="m134.4 0s-134.53 0-134.53 167.5v820.9c0 6.628 3.5818 11.601 8 11.601h384c4.418 0 8-4.973 8-11.601v-820.9c0-167.5-132.14-167.5-132.14-167.5h-67.86zm134.14 203c-2.5774 0-4.6664 3.134-4.6664 7v751c0 3.866 2.0894 7 4.6664 7h29.332c2.5774 0 4.6664-3.134 4.6664-7v-751c0-3.866-2.0894-7-4.6664-7z" fill-opacity="0" tb:tag="clickArea"/><g transform="translate(0,916)" fill="#d12730" style="display: none;" tb:tag="critical">
<path d="m1 260c0-37.263 0.00859-55.699 4.0548-70.799 11.004-41.066 43.08-73.143 84.146-84.146 15.1-4.046 33.536-4.055 70.8-4.055s55.699 9e-3 70.799 4.055c41.066 11.003 73.143 43.08 84.146 84.146 4.046 15.1 4.055 33.536 4.055 70.799v580c0 37.263-9e-3 55.699-4.055 70.799-11.003 41.066-43.08 73.143-84.146 84.146-15.1 4.046-33.536 4.055-70.799 4.055s-55.699-9e-3 -70.8-4.055c-41.066-11.003-73.142-43.08-84.146-84.146-4.0462-15.1-4.0548-33.536-4.0548-70.799v-580z" fill="#fff" stroke="#1A1A1A" stroke-width="2" tb:tag="background"/><path d="m400 700h-8c-16.569 0-30-13.431-30-30v-637c0-16.569-13.431-30-30-30h-147c-16.569 0-30 13.432-30 30v67" stroke="#1A1A1A" stroke-width="6"/><path d="m134.4 0s-134.53 0-134.53 167.5v820.9c0 6.628 3.5818 11.601 8 11.601h384c4.418 0 8-4.973 8-11.601v-820.9c0-167.5-132.14-167.5-132.14-167.5h-67.86zm134.14 203c-2.5774 0-4.6664 3.134-4.6664 7v751c0 3.866 2.0894 7 4.6664 7h29.332c2.5774 0 4.6664-3.134 4.6664-7v-751c0-3.866-2.0894-7-4.6664-7z" fill-opacity="0" fill="#000" tb:tag="clickArea"/><g transform="translate(0,916)" 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=""/>

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 13 KiB

2
application/src/main/data/json/system/scada_symbols/small-vertical-separator-hp.svg

@ -328,7 +328,7 @@
}
]
}]]></tb:metadata>
<path d="m1 200c0-37.22 0.00484-55.684 3.0551-71.019 12.546-63.074 61.852-112.38 124.93-124.93 15.335-3.0503 33.799-3.0551 71.019-3.0551 37.22 1e-5 55.684 0.00485 71.019 3.0552 63.074 12.546 112.38 61.852 124.93 124.93 3.05 15.335 3.055 33.799 3.055 71.019v600c0 37.22-5e-3 55.684-3.055 71.019-12.546 63.074-61.852 112.38-124.93 124.93-15.335 3.05-33.799 3.055-71.019 3.055s-55.684-5e-3 -71.019-3.055c-63.074-12.546-112.38-61.852-124.93-124.93-3.0503-15.335-3.0551-33.799-3.0551-71.019v-600z" fill="#fff" stroke="#1A1A1A" stroke-width="2" tb:tag="background"/><path d="m134.53 0s-134.53 0-134.53 167.5v820.9c0 6.628 3.5818 11.601 8 11.601h384c4.418 0 8-4.973 8-11.601v-820.9c0-167.5-132.14-167.5-132.14-167.5h-67.86zm134.14 203c-2.5774 0-4.6664 3.134-4.6664 7v751c0 3.866 2.0894 7 4.6664 7h29.332c2.5774 0 4.6664-3.134 4.6664-7v-751c0-3.866-2.0894-7-4.6664-7z" fill-opacity="0" tb:tag="clickArea"/><g transform="translate(0,916)" fill="#d12730" style="display: none;" tb:tag="critical">
<path d="m1 200c0-37.22 0.00484-55.684 3.0551-71.019 12.546-63.074 61.852-112.38 124.93-124.93 15.335-3.0503 33.799-3.0551 71.019-3.0551 37.22 1e-5 55.684 0.00485 71.019 3.0552 63.074 12.546 112.38 61.852 124.93 124.93 3.05 15.335 3.055 33.799 3.055 71.019v600c0 37.22-5e-3 55.684-3.055 71.019-12.546 63.074-61.852 112.38-124.93 124.93-15.335 3.05-33.799 3.055-71.019 3.055s-55.684-5e-3 -71.019-3.055c-63.074-12.546-112.38-61.852-124.93-124.93-3.0503-15.335-3.0551-33.799-3.0551-71.019v-600z" fill="#fff" stroke="#1A1A1A" stroke-width="2" tb:tag="background"/><path d="m134.53 0s-134.53 0-134.53 167.5v820.9c0 6.628 3.5818 11.601 8 11.601h384c4.418 0 8-4.973 8-11.601v-820.9c0-167.5-132.14-167.5-132.14-167.5h-67.86zm134.14 203c-2.5774 0-4.6664 3.134-4.6664 7v751c0 3.866 2.0894 7 4.6664 7h29.332c2.5774 0 4.6664-3.134 4.6664-7v-751c0-3.866-2.0894-7-4.6664-7z" fill-opacity="0" fill="#000" tb:tag="clickArea"/><g transform="translate(0,916)" 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=""/>

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 13 KiB

2
application/src/main/data/json/system/scada_symbols/spherical-tank.svg

@ -572,7 +572,7 @@
<path d="m381 272c0-6.627 5.373-12 12-12h216c6.627 0 12 5.373 12 12v56c0 6.627-5.373 12-12 12h-216c-6.627 0-12-5.373-12-12z" fill="#f3f3f3" tb:tag="value-box-background"/>
<path d="m382.5 272c0-5.799 4.701-10.5 10.5-10.5h216c5.799 0 10.5 4.701 10.5 10.5v56c0 5.799-4.701 10.5-10.5 10.5h-216c-5.799 0-10.5-4.701-10.5-10.5z" stroke="#727171" stroke-width="3"/>
<text x="499.84497" y="300.37811" fill="#727171" font-family="Roboto" font-size="32px" font-weight="500" tb:tag="value-text" xml:space="preserve" text-anchor="middle"><tspan dominant-baseline="middle">1660 gal</tspan></text>
</g><path d="m336.32 0s-336.32 0-336.32 167.5v820.9c0 6.628 8.9543 11.601 20 11.601h960c11.045 0 20-4.973 20-11.601v-820.9c0-167.5-330.35-167.5-330.35-167.5h-169.65zm335.35 203c-6.4433 0-11.667 3.134-11.667 7v751c0 3.866 5.2233 7 11.667 7h73.333c6.4433 0 11.667-3.134 11.667-7v-751c0-3.866-5.2233-7-11.667-7z" fill="#000" fill-opacity="0" style="stroke-width:.91287" tb:tag="clickArea"/><defs>
</g><path d="m336.32 0s-336.32 0-336.32 167.5v820.9c0 6.628 8.9543 11.601 20 11.601h960c11.045 0 20-4.973 20-11.601v-820.9c0-167.5-330.35-167.5-330.35-167.5h-169.65zm335.35 203c-6.4433 0-11.667 3.134-11.667 7v751c0 3.866 5.2233 7 11.667 7h73.333c6.4433 0 11.667-3.134 11.667-7v-751c0-3.866-5.2233-7-11.667-7z" fill="#000" fill-opacity="0" tb:tag="clickArea"/><defs>
<radialGradient id="paint0_radial_1711_251491" cx="0" cy="0" r="1" gradientTransform="translate(500 501.16) rotate(180.27) scale(500.01 501.17)" gradientUnits="userSpaceOnUse">
<stop stop-color="#fff" stop-opacity=".15" offset=".00034187"/>
<stop stop-color="#fff" stop-opacity=".12" offset=".29501"/>

Before

Width:  |  Height:  |  Size: 117 KiB

After

Width:  |  Height:  |  Size: 117 KiB

2
application/src/main/data/json/system/scada_symbols/stand-cylindrical-tank.svg

@ -567,7 +567,7 @@
<path d="m180 62c0-6.6274 5.373-12 12-12h216c6.627 0 12 5.3726 12 12v56c0 6.627-5.373 12-12 12h-216c-6.627 0-12-5.373-12-12z" fill="#f3f3f3" tb:tag="value-box-background"/>
<path d="m192 51.5h216c5.799 0 10.5 4.701 10.5 10.5v56c0 5.799-4.701 10.5-10.5 10.5h-216c-5.799 0-10.5-4.701-10.5-10.5v-56c0-5.799 4.701-10.5 10.5-10.5z" stroke="#727171" stroke-width="3"/>
<text x="301.5625" y="93.546875" fill="#727171" font-family="Roboto" font-size="32px" font-weight="500" tb:tag="value-text" xml:space="preserve" text-anchor="middle"><tspan dominant-baseline="middle">1660 gal</tspan></text>
</g><ellipse cx="300" cy="16" rx="292" ry="16" fill="#5D5C5C"/><rect x="58" y="1163" width="80" height="24" rx="7" fill="#fff"/><rect x="58" y="1163" width="80" height="24" rx="7" fill="url(#paint147_linear_1690_149725)" style="fill:url(#paint147_linear_1690_149725)"/><rect x="59.5" y="1164.5" width="77" height="21" rx="5.5" stroke="#000" stroke-opacity=".12" stroke-width="3"/><rect x="462" y="1163" width="80" height="24" rx="7" fill="#fff"/><rect x="462" y="1163" width="80" height="24" rx="7" fill="url(#paint148_linear_1690_149725)" style="fill:url(#paint148_linear_1690_149725)"/><rect x="463.5" y="1164.5" width="77" height="21" rx="5.5" stroke="#000" stroke-opacity=".12" stroke-width="3"/><rect transform="rotate(15 96 1004.5)" x="96" y="1004.5" width="423.92" height="8" fill="#727171"/><rect transform="rotate(-15 94 1114.2)" x="94" y="1114.2" width="423.92" height="8" fill="#727171"/><path d="m82 1163v-169l32 2v167z" fill="#fff"/><path d="m82 1163v-169l32 2v167z" fill="url(#paint149_linear_1690_149725)" style="fill:url(#paint149_linear_1690_149725)"/><path d="m83.5 1161.5v-165.9l29 1.812v164.09z" stroke="#000" stroke-opacity=".12" stroke-width="3"/><path d="m486 1163v-167l32-2v169z" fill="#fff"/><path d="m486 1163v-167l32-2v169z" fill="url(#paint150_linear_1690_149725)" style="fill:url(#paint150_linear_1690_149725)"/><path d="m487.5 1161.5v-164.09l29-1.812v165.9z" stroke="#000" stroke-opacity=".12" stroke-width="3"/><rect transform="rotate(15 68.875 1013)" x="68.875" y="1013" width="483.9" height="12" fill="#838282"/><rect transform="rotate(-15 63.922 1138.8)" x="63.922" y="1138.8" width="487.78" height="12" fill="#838282"/><circle cx="534" cy="885" r="32" fill="url(#paint151_radial_1690_149725)" style="fill:url(#paint151_radial_1690_149725)"/><circle cx="534" cy="885" r="30.5" stroke="#000" stroke-opacity=".12" stroke-width="3"/><circle cx="66" cy="885" r="32" fill="url(#paint152_radial_1690_149725)" style="fill:url(#paint152_radial_1690_149725)"/><circle cx="66" cy="885" r="30.5" stroke="#000" stroke-opacity=".12" stroke-width="3"/><path d="m50 1171v-284c0-8.837 7.1634-16 16-16s16 7.163 16 16v284z" fill="#fff"/><path d="m50 1171v-284c0-8.837 7.1634-16 16-16s16 7.163 16 16v284z" fill="url(#paint153_linear_1690_149725)" style="fill:url(#paint153_linear_1690_149725)"/><path d="m51.5 1169.5v-282.5c0-8.008 6.4919-14.5 14.5-14.5s14.5 6.492 14.5 14.5v282.5z" stroke="#000" stroke-opacity=".12" stroke-width="3"/><path d="m518 1171v-284c0-8.837 7.163-16 16-16s16 7.163 16 16v284z" fill="#fff"/><path d="m518 1171v-284c0-8.837 7.163-16 16-16s16 7.163 16 16v284z" fill="url(#paint154_linear_1690_149725)" style="fill:url(#paint154_linear_1690_149725)"/><path d="m519.5 1169.5v-282.5c0-8.008 6.492-14.5 14.5-14.5s14.5 6.492 14.5 14.5v282.5z" stroke="#000" stroke-opacity=".12" stroke-width="3"/><rect x="16" y="1171" width="100" height="29" rx="7" fill="#fff"/><rect x="16" y="1171" width="100" height="29" rx="7" fill="url(#paint155_linear_1690_149725)" style="fill:url(#paint155_linear_1690_149725)"/><rect x="17.5" y="1172.5" width="97" height="26" rx="5.5" stroke="#000" stroke-opacity=".12" stroke-width="3"/><rect x="484" y="1171" width="100" height="29" rx="7" fill="#fff"/><rect x="484" y="1171" width="100" height="29" rx="7" fill="url(#paint156_linear_1690_149725)" style="fill:url(#paint156_linear_1690_149725)"/><rect x="485.5" y="1172.5" width="97" height="26" rx="5.5" stroke="#000" stroke-opacity=".12" stroke-width="3"/><path d="m201.79 0s-201.79 0-201.79 201v985.08c0 7.9536 5.3726 13.921 12 13.921h576c6.627 0 12-5.9676 12-13.921v-985.08c0-201-198.21-201-198.21-201h-101.79zm201.21 243.6c-3.866 0-7 3.7608-7 8.4v901.2c0 4.6392 3.134 8.4 7 8.4h44c3.866 0 7-3.7608 7-8.4v-901.2c0-4.6392-3.134-8.4-7-8.4z" fill="#000" fill-opacity="0" style="stroke-width:1.0954" tb:tag="clickArea"/><defs>
</g><ellipse cx="300" cy="16" rx="292" ry="16" fill="#5D5C5C"/><rect x="58" y="1163" width="80" height="24" rx="7" fill="#fff"/><rect x="58" y="1163" width="80" height="24" rx="7" fill="url(#paint147_linear_1690_149725)" style="fill:url(#paint147_linear_1690_149725)"/><rect x="59.5" y="1164.5" width="77" height="21" rx="5.5" stroke="#000" stroke-opacity=".12" stroke-width="3"/><rect x="462" y="1163" width="80" height="24" rx="7" fill="#fff"/><rect x="462" y="1163" width="80" height="24" rx="7" fill="url(#paint148_linear_1690_149725)" style="fill:url(#paint148_linear_1690_149725)"/><rect x="463.5" y="1164.5" width="77" height="21" rx="5.5" stroke="#000" stroke-opacity=".12" stroke-width="3"/><rect transform="rotate(15 96 1004.5)" x="96" y="1004.5" width="423.92" height="8" fill="#727171"/><rect transform="rotate(-15 94 1114.2)" x="94" y="1114.2" width="423.92" height="8" fill="#727171"/><path d="m82 1163v-169l32 2v167z" fill="#fff"/><path d="m82 1163v-169l32 2v167z" fill="url(#paint149_linear_1690_149725)" style="fill:url(#paint149_linear_1690_149725)"/><path d="m83.5 1161.5v-165.9l29 1.812v164.09z" stroke="#000" stroke-opacity=".12" stroke-width="3"/><path d="m486 1163v-167l32-2v169z" fill="#fff"/><path d="m486 1163v-167l32-2v169z" fill="url(#paint150_linear_1690_149725)" style="fill:url(#paint150_linear_1690_149725)"/><path d="m487.5 1161.5v-164.09l29-1.812v165.9z" stroke="#000" stroke-opacity=".12" stroke-width="3"/><rect transform="rotate(15 68.875 1013)" x="68.875" y="1013" width="483.9" height="12" fill="#838282"/><rect transform="rotate(-15 63.922 1138.8)" x="63.922" y="1138.8" width="487.78" height="12" fill="#838282"/><circle cx="534" cy="885" r="32" fill="url(#paint151_radial_1690_149725)" style="fill:url(#paint151_radial_1690_149725)"/><circle cx="534" cy="885" r="30.5" stroke="#000" stroke-opacity=".12" stroke-width="3"/><circle cx="66" cy="885" r="32" fill="url(#paint152_radial_1690_149725)" style="fill:url(#paint152_radial_1690_149725)"/><circle cx="66" cy="885" r="30.5" stroke="#000" stroke-opacity=".12" stroke-width="3"/><path d="m50 1171v-284c0-8.837 7.1634-16 16-16s16 7.163 16 16v284z" fill="#fff"/><path d="m50 1171v-284c0-8.837 7.1634-16 16-16s16 7.163 16 16v284z" fill="url(#paint153_linear_1690_149725)" style="fill:url(#paint153_linear_1690_149725)"/><path d="m51.5 1169.5v-282.5c0-8.008 6.4919-14.5 14.5-14.5s14.5 6.492 14.5 14.5v282.5z" stroke="#000" stroke-opacity=".12" stroke-width="3"/><path d="m518 1171v-284c0-8.837 7.163-16 16-16s16 7.163 16 16v284z" fill="#fff"/><path d="m518 1171v-284c0-8.837 7.163-16 16-16s16 7.163 16 16v284z" fill="url(#paint154_linear_1690_149725)" style="fill:url(#paint154_linear_1690_149725)"/><path d="m519.5 1169.5v-282.5c0-8.008 6.492-14.5 14.5-14.5s14.5 6.492 14.5 14.5v282.5z" stroke="#000" stroke-opacity=".12" stroke-width="3"/><rect x="16" y="1171" width="100" height="29" rx="7" fill="#fff"/><rect x="16" y="1171" width="100" height="29" rx="7" fill="url(#paint155_linear_1690_149725)" style="fill:url(#paint155_linear_1690_149725)"/><rect x="17.5" y="1172.5" width="97" height="26" rx="5.5" stroke="#000" stroke-opacity=".12" stroke-width="3"/><rect x="484" y="1171" width="100" height="29" rx="7" fill="#fff"/><rect x="484" y="1171" width="100" height="29" rx="7" fill="url(#paint156_linear_1690_149725)" style="fill:url(#paint156_linear_1690_149725)"/><rect x="485.5" y="1172.5" width="97" height="26" rx="5.5" stroke="#000" stroke-opacity=".12" stroke-width="3"/><path d="m201.79 0s-201.79 0-201.79 201v985.08c0 7.9536 5.3726 13.921 12 13.921h576c6.627 0 12-5.9676 12-13.921v-985.08c0-201-198.21-201-198.21-201h-101.79zm201.21 243.6c-3.866 0-7 3.7608-7 8.4v901.2c0 4.6392 3.134 8.4 7 8.4h44c3.866 0 7-3.7608 7-8.4v-901.2c0-4.6392-3.134-8.4-7-8.4z" fill="#000" fill-opacity="0" tb:tag="clickArea"/><defs>
<linearGradient id="paint0_linear_1690_149726" x1="600" x2=".018833" y1="510.96" y2="504.56" gradientUnits="userSpaceOnUse">
<stop stop-color="#020202" stop-opacity=".35" offset="0"/>
<stop stop-color="#020202" stop-opacity=".12" offset=".23574"/>

Before

Width:  |  Height:  |  Size: 118 KiB

After

Width:  |  Height:  |  Size: 118 KiB

2
application/src/main/data/json/system/scada_symbols/stand-vertical-short-tank.svg

@ -1364,5 +1364,5 @@
<stop stop-color="#727171" stop-opacity=".2" offset="0"/>
<stop stop-color="#727171" offset="1"/>
</linearGradient>
</defs><path d="m269.05 0s-269.05 0-269.05 134v656.72c0 5.3024 7.1635 9.2808 16 9.2808h768c8.836 0 16-3.9784 16-9.2808v-656.72c0-134-264.28-134-264.28-134h-135.72zm268.28 162.4c-5.1547 0-9.3333 2.5072-9.3333 5.6v600.8c0 3.0928 4.1787 5.6 9.3333 5.6h58.667c5.1547 0 9.3333-2.5072 9.3333-5.6v-600.8c0-3.0928-4.1787-5.6-9.3333-5.6z" fill="#000" fill-opacity="0" style="stroke-width:1.1547" tb:tag="clickArea"/><rect x="78" y="764" width="80" height="24" rx="7" fill="#fff"/><rect x="78" y="764" width="80" height="24" rx="7" fill="url(#paint196_linear_1693_189771)" style="fill:url(#paint196_linear_1693_189771)"/><rect x="79.5" y="765.5" width="77" height="21" rx="5.5" stroke="#000" stroke-opacity=".12" stroke-width="3"/><rect x="642" y="764" width="80" height="24" rx="7" fill="#fff"/><rect x="642" y="764" width="80" height="24" rx="7" fill="url(#paint197_linear_1693_189771)" style="fill:url(#paint197_linear_1693_189771)"/><rect x="643.5" y="765.5" width="77" height="21" rx="5.5" stroke="#000" stroke-opacity=".12" stroke-width="3"/><rect transform="rotate(12 127.78 602.15)" x="127.78" y="602.15" width="558.25" height="8" fill="#727171"/><rect transform="rotate(-12 124.13 718.96)" x="124.13" y="718.97" width="564.03" height="8" fill="#727171"/><path d="m102 764v-164h32v164z" fill="#fff"/><path d="m102 764v-164h32v164z" fill="url(#paint198_linear_1693_189771)" style="fill:url(#paint198_linear_1693_189771)"/><path d="m103.5 762.5v-161h29v161z" stroke="#000" stroke-opacity=".12" stroke-width="3"/><path d="m666 764v-164h32v164z" fill="#fff"/><path d="m666 764v-164h32v164z" fill="url(#paint199_linear_1693_189771)" style="fill:url(#paint199_linear_1693_189771)"/><path d="m667.5 762.5v-161h29v161z" stroke="#000" stroke-opacity=".12" stroke-width="3"/><rect transform="rotate(12 90.57 610.09)" x="90.57" y="610.09" width="637.99" height="12" fill="#838282"/><rect transform="rotate(-12 92.219 742.22)" x="92.219" y="742.22" width="635.17" height="12" fill="#838282"/><circle cx="713" cy="486" r="32" fill="url(#paint200_radial_1693_189771)" style="fill:url(#paint200_radial_1693_189771)"/><circle cx="713" cy="486" r="30.5" stroke="#000" stroke-opacity=".12" stroke-width="3"/><circle cx="86" cy="486" r="32" fill="url(#paint201_radial_1693_189771)" style="fill:url(#paint201_radial_1693_189771)"/><circle cx="86" cy="486" r="30.5" stroke="#000" stroke-opacity=".12" stroke-width="3"/><path d="m70 772v-284c0-8.837 7.1634-16 16-16s16 7.163 16 16v284z" fill="#fff"/><path d="m70 772v-284c0-8.837 7.1634-16 16-16s16 7.163 16 16v284z" fill="url(#paint202_linear_1693_189771)" style="fill:url(#paint202_linear_1693_189771)"/><path d="m71.5 770.5v-282.5c0-8.008 6.4919-14.5 14.5-14.5s14.5 6.492 14.5 14.5v282.5z" stroke="#000" stroke-opacity=".12" stroke-width="3"/><path d="m698 772v-284c0-8.837 7.163-16 16-16s16 7.163 16 16v284z" fill="#fff"/><path d="m698 772v-284c0-8.837 7.163-16 16-16s16 7.163 16 16v284z" fill="url(#paint203_linear_1693_189771)" style="fill:url(#paint203_linear_1693_189771)"/><path d="m699.5 770.5v-282.5c0-8.008 6.492-14.5 14.5-14.5s14.5 6.492 14.5 14.5v282.5z" stroke="#000" stroke-opacity=".12" stroke-width="3"/><rect x="36" y="772" width="100" height="29" rx="7" fill="#fff"/><rect x="36" y="772" width="100" height="29" rx="7" fill="url(#paint204_linear_1693_189771)" style="fill:url(#paint204_linear_1693_189771)"/><rect x="37.5" y="773.5" width="97" height="26" rx="5.5" stroke="#000" stroke-opacity=".12" stroke-width="3"/><rect x="664" y="772" width="100" height="29" rx="7" fill="#fff"/><rect x="664" y="772" width="100" height="29" rx="7" fill="url(#paint205_linear_1693_189771)" style="fill:url(#paint205_linear_1693_189771)"/><rect x="665.5" y="773.5" width="97" height="26" rx="5.5" stroke="#000" stroke-opacity=".12" stroke-width="3"/>
</defs><path d="m269.05 0s-269.05 0-269.05 134v656.72c0 5.3024 7.1635 9.2808 16 9.2808h768c8.836 0 16-3.9784 16-9.2808v-656.72c0-134-264.28-134-264.28-134h-135.72zm268.28 162.4c-5.1547 0-9.3333 2.5072-9.3333 5.6v600.8c0 3.0928 4.1787 5.6 9.3333 5.6h58.667c5.1547 0 9.3333-2.5072 9.3333-5.6v-600.8c0-3.0928-4.1787-5.6-9.3333-5.6z" fill="#000" fill-opacity="0" tb:tag="clickArea"/><rect x="78" y="764" width="80" height="24" rx="7" fill="#fff"/><rect x="78" y="764" width="80" height="24" rx="7" fill="url(#paint196_linear_1693_189771)" style="fill:url(#paint196_linear_1693_189771)"/><rect x="79.5" y="765.5" width="77" height="21" rx="5.5" stroke="#000" stroke-opacity=".12" stroke-width="3"/><rect x="642" y="764" width="80" height="24" rx="7" fill="#fff"/><rect x="642" y="764" width="80" height="24" rx="7" fill="url(#paint197_linear_1693_189771)" style="fill:url(#paint197_linear_1693_189771)"/><rect x="643.5" y="765.5" width="77" height="21" rx="5.5" stroke="#000" stroke-opacity=".12" stroke-width="3"/><rect transform="rotate(12 127.78 602.15)" x="127.78" y="602.15" width="558.25" height="8" fill="#727171"/><rect transform="rotate(-12 124.13 718.96)" x="124.13" y="718.97" width="564.03" height="8" fill="#727171"/><path d="m102 764v-164h32v164z" fill="#fff"/><path d="m102 764v-164h32v164z" fill="url(#paint198_linear_1693_189771)" style="fill:url(#paint198_linear_1693_189771)"/><path d="m103.5 762.5v-161h29v161z" stroke="#000" stroke-opacity=".12" stroke-width="3"/><path d="m666 764v-164h32v164z" fill="#fff"/><path d="m666 764v-164h32v164z" fill="url(#paint199_linear_1693_189771)" style="fill:url(#paint199_linear_1693_189771)"/><path d="m667.5 762.5v-161h29v161z" stroke="#000" stroke-opacity=".12" stroke-width="3"/><rect transform="rotate(12 90.57 610.09)" x="90.57" y="610.09" width="637.99" height="12" fill="#838282"/><rect transform="rotate(-12 92.219 742.22)" x="92.219" y="742.22" width="635.17" height="12" fill="#838282"/><circle cx="713" cy="486" r="32" fill="url(#paint200_radial_1693_189771)" style="fill:url(#paint200_radial_1693_189771)"/><circle cx="713" cy="486" r="30.5" stroke="#000" stroke-opacity=".12" stroke-width="3"/><circle cx="86" cy="486" r="32" fill="url(#paint201_radial_1693_189771)" style="fill:url(#paint201_radial_1693_189771)"/><circle cx="86" cy="486" r="30.5" stroke="#000" stroke-opacity=".12" stroke-width="3"/><path d="m70 772v-284c0-8.837 7.1634-16 16-16s16 7.163 16 16v284z" fill="#fff"/><path d="m70 772v-284c0-8.837 7.1634-16 16-16s16 7.163 16 16v284z" fill="url(#paint202_linear_1693_189771)" style="fill:url(#paint202_linear_1693_189771)"/><path d="m71.5 770.5v-282.5c0-8.008 6.4919-14.5 14.5-14.5s14.5 6.492 14.5 14.5v282.5z" stroke="#000" stroke-opacity=".12" stroke-width="3"/><path d="m698 772v-284c0-8.837 7.163-16 16-16s16 7.163 16 16v284z" fill="#fff"/><path d="m698 772v-284c0-8.837 7.163-16 16-16s16 7.163 16 16v284z" fill="url(#paint203_linear_1693_189771)" style="fill:url(#paint203_linear_1693_189771)"/><path d="m699.5 770.5v-282.5c0-8.008 6.492-14.5 14.5-14.5s14.5 6.492 14.5 14.5v282.5z" stroke="#000" stroke-opacity=".12" stroke-width="3"/><rect x="36" y="772" width="100" height="29" rx="7" fill="#fff"/><rect x="36" y="772" width="100" height="29" rx="7" fill="url(#paint204_linear_1693_189771)" style="fill:url(#paint204_linear_1693_189771)"/><rect x="37.5" y="773.5" width="97" height="26" rx="5.5" stroke="#000" stroke-opacity=".12" stroke-width="3"/><rect x="664" y="772" width="100" height="29" rx="7" fill="#fff"/><rect x="664" y="772" width="100" height="29" rx="7" fill="url(#paint205_linear_1693_189771)" style="fill:url(#paint205_linear_1693_189771)"/><rect x="665.5" y="773.5" width="97" height="26" rx="5.5" stroke="#000" stroke-opacity=".12" stroke-width="3"/>
</svg>

Before

Width:  |  Height:  |  Size: 107 KiB

After

Width:  |  Height:  |  Size: 107 KiB

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

@ -332,7 +332,7 @@
<path d="m77.22 131 1.6 8h42.36l1.6-8h-45.56z"/>
<path d="m77.117 131h45.742c0.108-0.257 0.244-0.505 0.385-0.736 0.342-0.558 0.824-1.187 1.403-1.87 1.16-1.367 2.802-3.062 4.738-5.019 0.519-0.524 1.059-1.069 1.62-1.633 3.641-3.666 8.098-8.154 12.557-13.274 10.326-11.856 20.438-26.862 20.438-42.468 0-21.266-7.121-37.489-18.622-48.4-11.511-10.919-27.5-16.6-45.378-16.6-17.878 0-33.867 5.6814-45.378 16.6-11.502 10.91-18.622 27.134-18.622 48.4 0 15.606 10.106 30.612 20.426 42.468 4.456 5.12 8.9107 9.608 12.55 13.274 0.5601 0.564 1.1009 1.109 1.6194 1.633 1.9344 1.958 3.576 3.652 4.735 5.02 0.5788 0.683 1.0604 1.311 1.4022 1.869 0.1413 0.231 0.2771 0.479 0.3847 0.736z"/>
<path d="m80.13 194.02c1.5245 3.049 4.6409 4.975 8.0498 4.975h23.64c3.409 0 6.525-1.926 8.05-4.975l6.18-12.361c0.625-1.249 0.95-2.627 0.95-4.025v-38.639h-54v38.639c0 1.398 0.3253 2.776 0.9502 4.025l6.1803 12.361z"/>
</g><path d="m73 147h54" stroke="#1A1A1A" stroke-width="2"/><path d="m73 179h54" stroke="#1A1A1A" stroke-width="2"/><path d="m67.265 0s-67.265 0-67.265 33.5v164.18c0 1.3256 1.7909 2.3202 4 2.3202h192c2.209 0 4-0.9946 4-2.3202v-164.18c0-33.5-66.07-33.5-66.07-33.5h-33.93zm67.07 40.6c-1.2887 0-2.3333 0.6268-2.3333 1.4v150.2c0 0.7732 1.0447 1.4 2.3333 1.4h14.666c1.2887 0 2.3333-0.6268 2.3333-1.4v-150.2c0-0.7732-1.0447-1.4-2.3333-1.4z" fill-opacity="0" tb:tag="clickArea"/><g fill="#d12730" style="display: none;" tb:tag="critical">
</g><path d="m73 147h54" stroke="#1A1A1A" stroke-width="2"/><path d="m73 179h54" stroke="#1A1A1A" stroke-width="2"/><path d="m67.265 0s-67.265 0-67.265 33.5v164.18c0 1.3256 1.7909 2.3202 4 2.3202h192c2.209 0 4-0.9946 4-2.3202v-164.18c0-33.5-66.07-33.5-66.07-33.5h-33.93zm67.07 40.6c-1.2887 0-2.3333 0.6268-2.3333 1.4v150.2c0 0.7732 1.0447 1.4 2.3333 1.4h14.666c1.2887 0 2.3333-0.6268 2.3333-1.4v-150.2c0-0.7732-1.0447-1.4-2.3333-1.4z" fill-opacity="0" fill="#000" 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=""/>

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 14 KiB

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

@ -363,7 +363,7 @@
<path d="m785.99 289c-0.236 12.22-4.835 20.271-12.839 25.225-7.92 4.903-19.041 6.687-32.151 6.772v8.998c15.452-0.143 28.851-3.617 38.42-10.434 9.501-6.77 15.301-16.886 15.57-30.561h-9z"/>
<path d="m785.99 111c-0.236-12.22-4.835-20.271-12.839-25.225-7.92-4.9031-19.041-6.6864-32.151-6.7715v-8.9986c15.452 0.1433 28.851 3.6171 38.42 10.435 9.501 6.7698 15.301 16.886 15.57 30.561h-9z"/>
<path d="m196.96 36c-0.419-5.0286-4-8.7363-9.2-11.449-5.538-2.8898-13.138-4.7845-21.485-6.0398-16.304-2.4517-35.811-2.5097-49.274-2.5111v-8.9993c15.934 0.02162 38.037 0.58638 56.285 4.6009 9.322 2.0509 17.547 4.9835 23.419 9.1367 5.552 3.9269 8.95 8.8992 9.271 15.262h-9.016z"/>
</g><path d="m269.05 0s-269.05 0-269.05 67v328.36c0 2.6512 7.1636 4.6404 16 4.6404h768c8.836 0 16-1.9892 16-4.6404v-328.36c0-67-264.28-67-264.28-67h-135.72zm268.28 81.2c-5.1548 0-9.3332 1.2536-9.3332 2.8v300.4c0 1.5464 4.1788 2.8 9.3332 2.8h58.664c5.1548 0 9.3332-1.2536 9.3332-2.8v-300.4c0-1.5464-4.1788-2.8-9.3332-2.8z" fill-opacity="0" tb:tag="clickArea"/><g transform="translate(0,316)" fill="#d12730" style="display: none;" tb:tag="critical">
</g><path d="m269.05 0s-269.05 0-269.05 67v328.36c0 2.6512 7.1636 4.6404 16 4.6404h768c8.836 0 16-1.9892 16-4.6404v-328.36c0-67-264.28-67-264.28-67h-135.72zm268.28 81.2c-5.1548 0-9.3332 1.2536-9.3332 2.8v300.4c0 1.5464 4.1788 2.8 9.3332 2.8h58.664c5.1548 0 9.3332-1.2536 9.3332-2.8v-300.4c0-1.5464-4.1788-2.8-9.3332-2.8z" fill-opacity="0" fill="#000" tb:tag="clickArea"/><g transform="translate(0,316)" fill="#d12730" style="display: none;" tb:tag="critical">
<rect width="84" height="84" rx="4" fill="#fff" style=""/>
<rect width="84" height="84" rx="4" style=""/>
<rect x="2" y="2" width="80" height="80" rx="2" stroke="#000" stroke-opacity=".87" stroke-width="4" style=""/>

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 15 KiB

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

@ -364,7 +364,7 @@
}
]
}]]></tb:metadata>
<rect x="17" y="1" width="366" height="598" rx="5" fill="#fff" stroke="#1A1A1A" stroke-width="2" tb:tag="background"/><rect transform="matrix(1 0 0 -1 382 173)" x="1" y="-1" width="16" height="148" rx="1" fill="#999" stroke="#1A1A1A" stroke-width="2"/><rect transform="matrix(1 0 0 -1 0 173)" x="1" y="-1" width="16" height="148" rx="1" fill="#999" stroke="#1A1A1A" stroke-width="2"/><rect transform="matrix(1 0 0 -1 382 373)" x="1" y="-1" width="16" height="148" rx="1" fill="#999" stroke="#1A1A1A" stroke-width="2"/><rect transform="matrix(1 0 0 -1 382 573)" x="1" y="-1" width="16" height="148" rx="1" fill="#999" stroke="#1A1A1A" stroke-width="2"/><rect transform="matrix(1 0 0 -1 0 573)" x="1" y="-1" width="16" height="148" rx="1" fill="#999" stroke="#1A1A1A" stroke-width="2"/><circle cx="66" cy="86" r="10" fill="#198038" tb:tag="indicator"/><text x="83.31543" y="89.589844" fill="#000000" font-family="Roboto" font-size="30px" font-weight="400" tb:tag="label" xml:space="preserve"><tspan dominant-baseline="middle">Connected</tspan></text><path d="m134.53 0s-134.53 0-134.53 100.5v492.54c0 3.9768 3.5818 6.9604 8 6.9604h384c4.418 0 8-2.9838 8-6.9604v-492.54c0-100.5-132.14-100.5-132.14-100.5h-67.86zm134.14 121.8c-2.5774 0-4.6666 1.8804-4.6666 4.2v450.6c0 2.3196 2.0894 4.2 4.6666 4.2h29.332c2.5774 0 4.6666-1.8804 4.6666-4.2v-450.6c0-2.3196-2.0894-4.2-4.6666-4.2z" fill-opacity="0" tb:tag="clickArea"/><g transform="translate(0,516)" fill="#d12730" style="display: none;" tb:tag="critical">
<rect x="17" y="1" width="366" height="598" rx="5" fill="#fff" stroke="#1A1A1A" stroke-width="2" tb:tag="background"/><rect transform="matrix(1 0 0 -1 382 173)" x="1" y="-1" width="16" height="148" rx="1" fill="#999" stroke="#1A1A1A" stroke-width="2"/><rect transform="matrix(1 0 0 -1 0 173)" x="1" y="-1" width="16" height="148" rx="1" fill="#999" stroke="#1A1A1A" stroke-width="2"/><rect transform="matrix(1 0 0 -1 382 373)" x="1" y="-1" width="16" height="148" rx="1" fill="#999" stroke="#1A1A1A" stroke-width="2"/><rect transform="matrix(1 0 0 -1 382 573)" x="1" y="-1" width="16" height="148" rx="1" fill="#999" stroke="#1A1A1A" stroke-width="2"/><rect transform="matrix(1 0 0 -1 0 573)" x="1" y="-1" width="16" height="148" rx="1" fill="#999" stroke="#1A1A1A" stroke-width="2"/><circle cx="66" cy="86" r="10" fill="#198038" tb:tag="indicator"/><text x="83.31543" y="89.589844" fill="#000000" font-family="Roboto" font-size="30px" font-weight="400" tb:tag="label" xml:space="preserve"><tspan dominant-baseline="middle">Connected</tspan></text><path d="m134.53 0s-134.53 0-134.53 100.5v492.54c0 3.9768 3.5818 6.9604 8 6.9604h384c4.418 0 8-2.9838 8-6.9604v-492.54c0-100.5-132.14-100.5-132.14-100.5h-67.86zm134.14 121.8c-2.5774 0-4.6666 1.8804-4.6666 4.2v450.6c0 2.3196 2.0894 4.2 4.6666 4.2h29.332c2.5774 0 4.6666-1.8804 4.6666-4.2v-450.6c0-2.3196-2.0894-4.2-4.6666-4.2z" fill-opacity="0" fill="#000" 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=""/>

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 15 KiB

2
application/src/main/data/json/system/scada_symbols/vertical-tank-hp.svg

@ -502,7 +502,7 @@
<path d="m139.2 798.95v2.25h-11.437v-1.933l5.554-6.059c0.61-0.687 1.09-1.281 1.442-1.781 0.351-0.5 0.598-0.949 0.738-1.348 0.149-0.406 0.223-0.801 0.223-1.183 0-0.54-0.102-1.012-0.305-1.418-0.195-0.415-0.484-0.739-0.867-0.973-0.383-0.242-0.848-0.363-1.395-0.363-0.632 0-1.164 0.136-1.593 0.41-0.43 0.273-0.754 0.652-0.973 1.137-0.219 0.476-0.328 1.023-0.328 1.64h-2.824c0-0.992 0.226-1.898 0.679-2.719 0.453-0.828 1.11-1.484 1.969-1.968 0.86-0.493 1.895-0.739 3.106-0.739 1.14 0 2.109 0.192 2.906 0.575 0.797 0.382 1.402 0.925 1.816 1.628 0.422 0.704 0.633 1.536 0.633 2.497 0 0.531-0.086 1.058-0.258 1.582-0.172 0.523-0.418 1.046-0.738 1.57-0.313 0.516-0.684 1.035-1.113 1.558-0.43 0.516-0.903 1.04-1.418 1.571l-3.692 4.066zm13.575-7.711v2.789c0 1.336-0.133 2.477-0.399 3.422-0.258 0.938-0.633 1.699-1.125 2.285s-1.082 1.016-1.769 1.289c-0.68 0.274-1.442 0.411-2.286 0.411-0.671 0-1.296-0.086-1.875-0.258-0.57-0.172-1.086-0.442-1.546-0.809-0.461-0.367-0.856-0.84-1.184-1.418-0.32-0.586-0.57-1.285-0.75-2.097-0.172-0.813-0.258-1.754-0.258-2.825v-2.789c0-1.343 0.133-2.476 0.399-3.398 0.265-0.93 0.644-1.684 1.136-2.262 0.492-0.586 1.078-1.012 1.758-1.277 0.688-0.266 1.453-0.399 2.297-0.399 0.68 0 1.305 0.086 1.875 0.258 0.578 0.164 1.094 0.426 1.547 0.785 0.461 0.36 0.851 0.828 1.172 1.407 0.328 0.57 0.578 1.261 0.75 2.074 0.172 0.804 0.258 1.742 0.258 2.812zm-2.825 3.188v-3.61c0-0.679-0.039-1.277-0.117-1.793-0.078-0.523-0.195-0.964-0.351-1.324-0.149-0.367-0.336-0.664-0.563-0.89-0.226-0.235-0.484-0.403-0.773-0.504-0.289-0.11-0.614-0.164-0.973-0.164-0.438 0-0.828 0.086-1.172 0.257-0.344 0.164-0.633 0.43-0.867 0.797s-0.414 0.852-0.539 1.453c-0.117 0.594-0.176 1.317-0.176 2.168v3.61c0 0.687 0.039 1.293 0.117 1.816 0.078 0.524 0.196 0.973 0.352 1.348 0.156 0.367 0.344 0.672 0.562 0.914 0.227 0.234 0.485 0.406 0.774 0.516 0.297 0.109 0.621 0.164 0.972 0.164 0.446 0 0.84-0.086 1.184-0.258s0.633-0.446 0.867-0.821c0.235-0.382 0.41-0.878 0.528-1.488 0.117-0.609 0.175-1.34 0.175-2.191z" fill="#000" fill-opacity=".38"/>
<path d="m135.47 881.48v17.121h-2.824v-13.77l-4.184 1.418v-2.332l6.668-2.437zm17.301 7.16v2.789c0 1.336-0.133 2.476-0.399 3.422-0.258 0.937-0.633 1.699-1.125 2.285s-1.082 1.015-1.769 1.289c-0.68 0.273-1.442 0.41-2.286 0.41-0.671 0-1.296-0.086-1.875-0.258-0.57-0.172-1.086-0.441-1.546-0.808-0.461-0.368-0.856-0.84-1.184-1.418-0.32-0.586-0.57-1.286-0.75-2.098-0.172-0.813-0.258-1.754-0.258-2.824v-2.789c0-1.344 0.133-2.477 0.399-3.399 0.265-0.929 0.644-1.683 1.136-2.261 0.492-0.586 1.078-1.012 1.758-1.278 0.688-0.265 1.453-0.398 2.297-0.398 0.68 0 1.305 0.086 1.875 0.258 0.578 0.164 1.094 0.425 1.547 0.785 0.461 0.359 0.851 0.828 1.172 1.406 0.328 0.57 0.578 1.262 0.75 2.074 0.172 0.805 0.258 1.742 0.258 2.813zm-2.825 3.187v-3.609c0-0.68-0.039-1.278-0.117-1.793-0.078-0.524-0.195-0.965-0.351-1.324-0.149-0.368-0.336-0.664-0.563-0.891-0.226-0.234-0.484-0.402-0.773-0.504-0.289-0.109-0.614-0.164-0.973-0.164-0.438 0-0.828 0.086-1.172 0.258-0.344 0.164-0.633 0.43-0.867 0.797s-0.414 0.851-0.539 1.453c-0.117 0.594-0.176 1.316-0.176 2.168v3.609c0 0.688 0.039 1.293 0.117 1.817 0.078 0.523 0.196 0.972 0.352 1.347 0.156 0.367 0.344 0.672 0.562 0.914 0.227 0.235 0.485 0.407 0.774 0.516 0.297 0.109 0.621 0.164 0.972 0.164 0.446 0 0.84-0.086 1.184-0.258s0.633-0.445 0.867-0.82c0.235-0.383 0.41-0.879 0.528-1.488 0.117-0.61 0.175-1.34 0.175-2.192z" fill="#000" fill-opacity=".38"/>
<path d="m152.77 986.04v2.789c0 1.336-0.133 2.477-0.399 3.422-0.258 0.938-0.633 1.699-1.125 2.285s-1.082 1.016-1.769 1.289c-0.68 0.274-1.442 0.41-2.286 0.41-0.671 0-1.296-0.086-1.875-0.257-0.57-0.172-1.086-0.442-1.546-0.809-0.461-0.367-0.856-0.84-1.184-1.418-0.32-0.586-0.57-1.285-0.75-2.098-0.172-0.812-0.258-1.754-0.258-2.824v-2.789c0-1.344 0.133-2.477 0.399-3.398 0.265-0.93 0.644-1.684 1.136-2.262 0.492-0.586 1.078-1.012 1.758-1.277 0.688-0.266 1.453-0.399 2.297-0.399 0.68 0 1.305 0.086 1.875 0.258 0.578 0.164 1.094 0.426 1.547 0.785 0.461 0.359 0.851 0.828 1.172 1.406 0.328 0.571 0.578 1.262 0.75 2.075 0.172 0.804 0.258 1.742 0.258 2.812zm-2.825 3.188v-3.61c0-0.679-0.039-1.277-0.117-1.793-0.078-0.523-0.195-0.965-0.351-1.324-0.149-0.367-0.336-0.664-0.563-0.891-0.226-0.234-0.484-0.402-0.773-0.504-0.289-0.109-0.614-0.164-0.973-0.164-0.438 0-0.828 0.086-1.172 0.258-0.344 0.164-0.633 0.43-0.867 0.797s-0.414 0.852-0.539 1.453c-0.117 0.594-0.176 1.317-0.176 2.168v3.61c0 0.687 0.039 1.293 0.117 1.816s0.196 0.973 0.352 1.348c0.156 0.367 0.344 0.671 0.562 0.914 0.227 0.234 0.485 0.406 0.774 0.515 0.297 0.11 0.621 0.164 0.972 0.164 0.446 0 0.84-0.086 1.184-0.257 0.344-0.172 0.633-0.446 0.867-0.821 0.235-0.383 0.41-0.879 0.528-1.488 0.117-0.609 0.175-1.34 0.175-2.191z" fill="#000" fill-opacity=".38"/>
</g><path d="m201.79 0s-201.79 0-201.79 167.5v820.9c0 6.628 5.3727 11.601 12 11.601h576c6.627 0 12-4.973 12-11.601v-820.9c0-167.5-198.21-167.5-198.21-167.5h-101.79zm201.21 203c-3.866 0-7 3.134-7 7v751c0 3.866 3.134 7 7 7h43.998c3.866 0 7-3.134 7-7v-751c0-3.866-3.134-7-7-7z" fill="#000" fill-opacity="0" style="stroke-width:.55902" tb:tag="clickArea"/><g fill="#d12730" style="display: none;" tb:tag="critical">
</g><path d="m201.79 0s-201.79 0-201.79 167.5v820.9c0 6.628 5.3727 11.601 12 11.601h576c6.627 0 12-4.973 12-11.601v-820.9c0-167.5-198.21-167.5-198.21-167.5h-101.79zm201.21 203c-3.866 0-7 3.134-7 7v751c0 3.866 3.134 7 7 7h43.998c3.866 0 7-3.134 7-7v-751c0-3.866-3.134-7-7-7z" 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=""/>

Before

Width:  |  Height:  |  Size: 50 KiB

After

Width:  |  Height:  |  Size: 50 KiB

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

@ -570,7 +570,7 @@
}
]
}]]></tb:metadata>
<rect width="400" height="200" fill="#fff" tb:tag="background"/><rect x="1" y="1" width="398" height="198" stroke="#000" stroke-opacity=".87" stroke-width="2"/><rect x="213" y="81" width="126" height="78" rx="1" fill="#dedede" stroke="#000" stroke-opacity=".87" stroke-width="2" tb:tag="out-value-box"/><text x="275.76855" y="136.65625" fill="#002878" font-family="Roboto" font-size="44px" font-weight="400" text-anchor="middle" tb:tag="out-value" xml:space="default"><tspan dominant-baseline="start">220</tspan></text><rect x="61" y="81" width="126" height="78" rx="1" fill="#dedede" stroke="#000" stroke-opacity=".87" stroke-width="2" tb:tag="in-value-box"/><text x="123.76855" y="136.65625" fill="#002878" font-family="Roboto" font-size="44px" font-weight="400" text-anchor="middle" tb:tag="in-value" xml:space="default"><tspan dominant-baseline="start">230</tspan></text><text x="123.29346" y="57.832031" fill="#000000" font-family="Roboto" font-size="34px" font-weight="400" text-anchor="middle" tb:tag="in-label" xml:space="default"><tspan dominant-baseline="start">in</tspan></text><text x="275.96484" y="55.873047" fill="#000000" font-family="Roboto" font-size="34px" font-weight="400" text-anchor="middle" tb:tag="out-label" xml:space="default"><tspan dominant-baseline="start">out</tspan></text><path d="m134.53 0s-134.53 0-134.53 33.5v164.18c0 1.3256 3.5818 2.3202 8 2.3202h384c4.418 0 8-0.9946 8-2.3202v-164.18c0-33.5-132.14-33.5-132.14-33.5h-67.858zm134.14 40.6c-2.5774 0-4.6666 0.6268-4.6666 1.4v150.2c0 0.7732 2.0894 1.4 4.6666 1.4h29.332c2.5774 0 4.6666-0.6268 4.6666-1.4v-150.2c0-0.7732-2.0894-1.4-4.6666-1.4z" fill="#000" fill-opacity="0" style="stroke-width:.70711" tb:tag="clickArea"/><g fill="#d12730" style="display: none;" tb:tag="critical">
<rect width="400" height="200" fill="#fff" tb:tag="background"/><rect x="1" y="1" width="398" height="198" stroke="#000" stroke-opacity=".87" stroke-width="2"/><rect x="213" y="81" width="126" height="78" rx="1" fill="#dedede" stroke="#000" stroke-opacity=".87" stroke-width="2" tb:tag="out-value-box"/><text x="275.76855" y="136.65625" fill="#002878" font-family="Roboto" font-size="44px" font-weight="400" text-anchor="middle" tb:tag="out-value" xml:space="default"><tspan dominant-baseline="start">220</tspan></text><rect x="61" y="81" width="126" height="78" rx="1" fill="#dedede" stroke="#000" stroke-opacity=".87" stroke-width="2" tb:tag="in-value-box"/><text x="123.76855" y="136.65625" fill="#002878" font-family="Roboto" font-size="44px" font-weight="400" text-anchor="middle" tb:tag="in-value" xml:space="default"><tspan dominant-baseline="start">230</tspan></text><text x="123.29346" y="57.832031" fill="#000000" font-family="Roboto" font-size="34px" font-weight="400" text-anchor="middle" tb:tag="in-label" xml:space="default"><tspan dominant-baseline="start">in</tspan></text><text x="275.96484" y="55.873047" fill="#000000" font-family="Roboto" font-size="34px" font-weight="400" text-anchor="middle" tb:tag="out-label" xml:space="default"><tspan dominant-baseline="start">out</tspan></text><path d="m134.53 0s-134.53 0-134.53 33.5v164.18c0 1.3256 3.5818 2.3202 8 2.3202h384c4.418 0 8-0.9946 8-2.3202v-164.18c0-33.5-132.14-33.5-132.14-33.5h-67.858zm134.14 40.6c-2.5774 0-4.6666 0.6268-4.6666 1.4v150.2c0 0.7732 2.0894 1.4 4.6666 1.4h29.332c2.5774 0 4.6666-0.6268 4.6666-1.4v-150.2c0-0.7732-2.0894-1.4-4.6666-1.4z" fill="#000" fill-opacity="0" 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=""/>

Before

Width:  |  Height:  |  Size: 21 KiB

After

Width:  |  Height:  |  Size: 21 KiB

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

@ -349,14 +349,14 @@
<path d="m410.21 378.76c0.18845-0.0291 0.36793-0.0562 0.53942-0.0832-0.10768 0.13636-0.22135 0.27974-0.341 0.42913-1.2354 1.548-3.043 3.7849-5.3283 6.5371-4.5726 5.5054-11.055 13.07-18.696 21.308-15.303 16.496-35.181 35.608-53.635 46.322-18.456 10.715-44.854 18.469-66.713 23.547-10.915 2.5356-20.671 4.3985-27.699 5.6267-3.5127 0.61461-6.3434 1.0708-8.2946 1.3726-0.18745 0.0291-0.36793 0.0561-0.53941 0.0832 0.10868-0.13635 0.22234-0.27973 0.34199-0.42912 1.2354-1.548 3.0431-3.7849 5.3284-6.5371 4.5716-5.5054 11.055-13.07 18.696-21.307 15.303-16.497 35.18-35.608 53.635-46.323 18.456-10.715 44.854-18.469 66.712-23.547 10.915-2.5356 20.671-4.3985 27.699-5.6267 3.5137-0.6146 6.3444-1.0708 8.2946-1.3726z"/>
<path d="m183.22 378.76c0.18844-0.0291 0.36792-0.0561 0.53942-0.0832-0.10768 0.13634-0.22135 0.27971-0.34101 0.4291-1.2354 1.548-3.0431 3.7849-5.3285 6.537-4.5727 5.5054-11.055 13.07-18.696 21.308-15.303 16.496-35.181 35.608-53.637 46.322-18.456 10.715-44.855 18.469-66.714 23.547-10.915 2.5356-20.672 4.3985-27.699 5.6267-3.5134 0.6146-6.3438 1.0708-8.2948 1.3726-0.18807 0.0291-0.36798 0.0561-0.53953 0.0832 0.10838-0.13634 0.22218-0.27971 0.34129-0.42911 1.2356-1.548 3.0432-3.7849 5.329-6.537 4.5719-5.5054 11.055-13.07 18.696-21.306 15.303-16.497 35.181-35.608 53.637-46.323 18.456-10.715 44.855-18.469 66.713-23.547 10.915-2.5356 20.672-4.3985 27.699-5.6267 3.5138-0.6146 6.3445-1.0708 8.2948-1.3726z"/>
<circle cx="414" cy="378" r="27"/>
<circle cx="187" cy="378"/>
<circle cx="187" cy="378" r="27"/>
<path d="m299.84 3.9752c0.178-0.45587 0.34-0.87084 0.486-1.2433 0.147 0.37248 0.309 0.78745 0.486 1.2433 0.9 2.3145 2.187 5.6829 3.732 9.8942 3.089 8.4232 7.207 20.216 11.326 33.692 8.245 26.98 16.456 60.603 16.456 87.437s-8.211 60.457-16.456 87.437c-4.119 13.476-8.237 25.269-11.326 33.692-1.545 4.2111-2.832 7.5794-3.732 9.8939-0.177 0.4559-0.339 0.87081-0.486 1.2437-0.146-0.37292-0.308-0.78783-0.486-1.2437-0.9-2.3145-2.187-5.6828-3.731-9.8939-3.089-8.4232-7.208-20.216-11.326-33.692-8.246-26.98-16.457-60.603-16.457-87.437s8.211-60.457 16.457-87.437c4.118-13.476 8.237-25.269 11.326-33.692 1.544-4.2114 2.831-7.5797 3.731-9.8942z"/>
<path d="m261.38 799 25.902-528h26.096l25.902 528z"/>
<path d="m303.5 272.39c-0.30616-0.38092-0.58532-0.72884-0.83445-1.0418 0.39622 0.059 0.83645 0.12598 1.3207 0.20096 2.4564 0.37792 6.0193 0.94779 10.442 1.7156 8.8458 1.5376 21.127 3.8671 34.866 7.0394 27.508 6.3506 60.756 16.052 84.014 29.469 23.257 13.418 48.289 37.339 67.548 57.967 9.6182 10.304 17.779 19.767 23.534 26.653 2.8766 3.4422 5.1528 6.2406 6.7077 8.1772 0.30717 0.38191 0.58533 0.72984 0.83445 1.0428-0.39521-0.06-0.83645-0.12696-1.3197-0.20095-2.4563-0.37791-6.0203-0.94779-10.443-1.7166-8.8448-1.5367-21.127-3.8671-34.866-7.0384-27.508-6.3516-60.756-16.053-84.013-29.47-23.258-13.417-48.29-37.338-67.548-57.967-9.6192-10.304-17.78-19.766-23.535-26.652-2.8766-3.4432-5.1528-6.2406-6.7077-8.1782z"/>
<path d="m296.78 271.55c0.48325-0.075 0.92446-0.14197 1.3207-0.20096-0.25013 0.31293-0.52826 0.66085-0.83442 1.0418-1.5558 1.9366-3.8309 4.7349-6.7084 8.1781-5.7549 6.8864-13.914 16.348-23.533 26.652-19.258 20.629-44.289 44.55-67.545 57.967-23.257 13.417-56.503 23.119-84.01 29.469-13.739 3.1723-26.019 5.5027-34.864 7.0394-4.4223 0.76882-7.9852 1.3387-10.441 1.7166-0.48374 0.074-0.92456 0.14097-1.3206 0.20096 0.24953-0.31294 0.52796-0.66086 0.83442-1.0428 1.5555-1.9366 3.8309-4.7349 6.7081-8.1781 5.7547-6.8854 13.914-16.348 23.533-26.652 19.257-20.629 44.288-44.549 67.545-57.967 23.256-13.417 56.502-23.119 84.009-29.469 13.739-3.1723 26.02-5.5018 34.864-7.0394 4.4232-0.76782 7.986-1.3377 10.442-1.7156z"/>
<circle cx="300.33" cy="270" r="33"/>
<rect x="136.33" y="777" width="328" height="22" rx="1"/>
</g><path d="m201.8-4e-4s-201.8 0-201.8 134v656.72c0 5.3024 5.3727 9.2808 12 9.2808h576c6.627 0 12-3.9784 12-9.2808v-656.72c0-134-198.21-134-198.21-134h-101.79zm201.21 162.4c-3.8661 0-6.9999 2.5072-6.9999 5.6v600.8c0 3.0928 3.1341 5.6 6.9999 5.6h43.998c3.8661 0 6.9999-2.5072 6.9999-5.6v-600.8c0-3.0928-3.1341-5.6-6.9999-5.6z" fill-opacity="0" tb:tag="clickArea"/><g transform="translate(0,716)" fill="#d12730" style="display: none;" tb:tag="critical">
</g><path d="m201.8-4e-4s-201.8 0-201.8 134v656.72c0 5.3024 5.3727 9.2808 12 9.2808h576c6.627 0 12-3.9784 12-9.2808v-656.72c0-134-198.21-134-198.21-134h-101.79zm201.21 162.4c-3.8661 0-6.9999 2.5072-6.9999 5.6v600.8c0 3.0928 3.1341 5.6 6.9999 5.6h43.998c3.8661 0 6.9999-2.5072 6.9999-5.6v-600.8c0-3.0928-3.1341-5.6-6.9999-5.6z" fill-opacity="0" fill="#000" tb:tag="clickArea"/><g transform="translate(0,716)" fill="#d12730" style="display: none;" tb:tag="critical">
<rect width="84" height="84" rx="4" fill="#fff" style=""/>
<rect width="84" height="84" rx="4" style=""/>
<rect x="2" y="2" width="80" height="80" rx="2" stroke="#000" stroke-opacity=".87" stroke-width="4" style=""/>

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 19 KiB

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

@ -346,7 +346,7 @@
<path d="m261.06 799 25.887-456h26.11l25.887 456z" stroke-width="2"/>
<circle cx="300" cy="342" r="33" stroke-width="2"/>
<rect x="247" y="777" width="106" height="22" rx="1" stroke-width="2"/>
</g><path d="m201.8 0s-201.8 0-201.8 134v656.72c0 5.3024 5.3727 9.2808 12 9.2808h576c6.627 0 12-3.9784 12-9.2808v-656.72c0-134-198.21-134-198.21-134h-101.79zm201.21 162.4c-3.8661 0-6.9999 2.5072-6.9999 5.6v600.8c0 3.0928 3.1341 5.6 6.9999 5.6h43.998c3.8661 0 6.9999-2.5072 6.9999-5.6v-600.8c0-3.0928-3.1341-5.6-6.9999-5.6z" fill-opacity="0" tb:tag="clickArea"/><g transform="translate(0,716)" fill="#d12730" style="display: none;" tb:tag="critical">
</g><path d="m201.8 0s-201.8 0-201.8 134v656.72c0 5.3024 5.3727 9.2808 12 9.2808h576c6.627 0 12-3.9784 12-9.2808v-656.72c0-134-198.21-134-198.21-134h-101.79zm201.21 162.4c-3.8661 0-6.9999 2.5072-6.9999 5.6v600.8c0 3.0928 3.1341 5.6 6.9999 5.6h43.998c3.8661 0 6.9999-2.5072 6.9999-5.6v-600.8c0-3.0928-3.1341-5.6-6.9999-5.6z" fill-opacity="0" fill="#000" tb:tag="clickArea"/><g transform="translate(0,716)" fill="#d12730" style="display: none;" tb:tag="critical">
<rect width="84" height="84" rx="4" fill="#fff" style=""/>
<rect width="84" height="84" rx="4" style=""/>
<rect x="2" y="2" width="80" height="80" rx="2" stroke="#000" stroke-opacity=".87" stroke-width="4" style=""/>

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 15 KiB

4
application/src/main/data/json/system/widget_types/bar_chart.json

@ -9,9 +9,9 @@
"sizeX": 8,
"sizeY": 5,
"resources": [],
"templateHtml": "<tb-time-series-chart-widget \n [ctx]=\"ctx\"\n [widgetTitlePanel]=\"widgetTitlePanel\">\n</tb-time-series-chart-widget>",
"templateHtml": "<tb-time-series-chart-widget \n [ctx]=\"ctx\">\n</tb-time-series-chart-widget>",
"templateCss": "",
"controllerScript": "self.onInit = function() {\n self.ctx.$scope.timeSeriesChartWidget.onInit();\n};\n\nself.onDataUpdated = function() {\n self.ctx.$scope.timeSeriesChartWidget.onDataUpdated();\n}\n\nself.onLatestDataUpdated = function() {\n self.ctx.$scope.timeSeriesChartWidget.onLatestDataUpdated();\n}\n\nself.typeParameters = function() {\n return {\n chartType: 'bar',\n previewWidth: '80%',\n embedTitlePanel: true,\n hasAdditionalLatestDataKeys: true,\n dataKeySettingsFunction: TbTimeSeriesChart.dataKeySettings('bar'),\n defaultDataKeysFunction: function() {\n return [{ name: 'temperature', label: 'Temperature', type: 'timeseries', units: '°C', decimals: 0 }];\n }\n };\n}\n",
"controllerScript": "self.onInit = function() {\n self.ctx.$scope.timeSeriesChartWidget.onInit();\n};\n\nself.onDataUpdated = function() {\n self.ctx.$scope.timeSeriesChartWidget.onDataUpdated();\n}\n\nself.onLatestDataUpdated = function() {\n self.ctx.$scope.timeSeriesChartWidget.onLatestDataUpdated();\n}\n\nself.typeParameters = function() {\n return {\n chartType: 'bar',\n previewWidth: '80%',\n embedTitlePanel: true,\n embedActionsPanel: true,\n hasAdditionalLatestDataKeys: true,\n dataKeySettingsFunction: TbTimeSeriesChart.dataKeySettings('bar'),\n defaultDataKeysFunction: function() {\n return [{ name: 'temperature', label: 'Temperature', type: 'timeseries', units: '°C', decimals: 0 }];\n }\n };\n}\n",
"settingsSchema": "{}",
"dataKeySettingsSchema": "{}",
"latestDataKeySettingsSchema": "{}",

4
application/src/main/data/json/system/widget_types/bar_chart_with_labels.json

@ -9,9 +9,9 @@
"sizeX": 8,
"sizeY": 5,
"resources": [],
"templateHtml": "<tb-bar-chart-with-labels-widget \n [ctx]=\"ctx\"\n [widgetTitlePanel]=\"widgetTitlePanel\">\n</tb-bar-chart-with-labels-widget>",
"templateHtml": "<tb-bar-chart-with-labels-widget \n [ctx]=\"ctx\">\n</tb-bar-chart-with-labels-widget>",
"templateCss": ".legend {\n font-size: 13px;\n line-height: 10px;\n}\n\n.legend table { \n border-spacing: 0px;\n border-collapse: separate;\n}\n\n.mouse-events .flot-overlay {\n cursor: crosshair; \n}\n\n",
"controllerScript": "self.onInit = function() {\n self.ctx.$scope.barChartWidget.onInit();\n};\n\nself.onDataUpdated = function() {\n self.ctx.$scope.barChartWidget.onDataUpdated();\n}\n\nself.typeParameters = function() {\n return {\n previewWidth: '80%',\n embedTitlePanel: true,\n hasAdditionalLatestDataKeys: false,\n defaultDataKeysFunction: function() {\n return [{ name: 'humidity', label: 'Humidity', type: 'timeseries' }];\n }\n };\n}\n",
"controllerScript": "self.onInit = function() {\n self.ctx.$scope.barChartWidget.onInit();\n};\n\nself.onDataUpdated = function() {\n self.ctx.$scope.barChartWidget.onDataUpdated();\n}\n\nself.typeParameters = function() {\n return {\n previewWidth: '80%',\n embedTitlePanel: true,\n embedActionsPanel: true,\n hasAdditionalLatestDataKeys: false,\n defaultDataKeysFunction: function() {\n return [{ name: 'humidity', label: 'Humidity', type: 'timeseries' }];\n }\n };\n}\n",
"settingsSchema": "{}",
"dataKeySettingsSchema": "{}",
"latestDataKeySettingsSchema": "{}",

4
application/src/main/data/json/system/widget_types/bars.json

@ -9,9 +9,9 @@
"sizeX": 5,
"sizeY": 4,
"resources": [],
"templateHtml": "<tb-bar-chart-widget \n [ctx]=\"ctx\"\n [widgetTitlePanel]=\"widgetTitlePanel\">\n</tb-bar-chart-widget>",
"templateHtml": "<tb-bar-chart-widget \n [ctx]=\"ctx\">\n</tb-bar-chart-widget>",
"templateCss": "",
"controllerScript": "self.onInit = function() {\n self.ctx.$scope.barChartWidget.onInit();\n};\n\nself.onDataUpdated = function() {\n self.ctx.$scope.barChartWidget.onDataUpdated();\n};\n\nself.typeParameters = function() {\n return {\n previewWidth: '500px',\n previewHeight: '380px',\n embedTitlePanel: true,\n defaultDataKeysFunction: function() {\n return [{ name: 'windPower', label: 'Wind', type: 'timeseries', color: '#08872B' },\n { name: 'solarPower', label: 'Solar', type: 'timeseries', color: '#FF4D5A' },\n { name: 'hydroelectricPower', label: 'Hydroelectric', type: 'timeseries', color: '#FFDE30' }];\n }\n };\n};\n\nself.onDestroy = function() {\n};\n\n",
"controllerScript": "self.onInit = function() {\n self.ctx.$scope.barChartWidget.onInit();\n};\n\nself.onDataUpdated = function() {\n self.ctx.$scope.barChartWidget.onDataUpdated();\n};\n\nself.typeParameters = function() {\n return {\n previewWidth: '500px',\n previewHeight: '380px',\n embedTitlePanel: true,\n embedActionsPanel: true,\n defaultDataKeysFunction: function() {\n return [{ name: 'windPower', label: 'Wind', type: 'timeseries', color: '#08872B' },\n { name: 'solarPower', label: 'Solar', type: 'timeseries', color: '#FF4D5A' },\n { name: 'hydroelectricPower', label: 'Hydroelectric', type: 'timeseries', color: '#FFDE30' }];\n }\n };\n};\n\nself.onDestroy = function() {\n};\n\n",
"settingsSchema": "",
"dataKeySettingsSchema": "",
"settingsDirective": "tb-bar-chart-widget-settings",

4
application/src/main/data/json/system/widget_types/doughnut.json

@ -9,9 +9,9 @@
"sizeX": 4,
"sizeY": 3,
"resources": [],
"templateHtml": "<tb-doughnut-widget \n [ctx]=\"ctx\"\n [widgetTitlePanel]=\"widgetTitlePanel\">\n</tb-doughnut-widget>",
"templateHtml": "<tb-doughnut-widget \n [ctx]=\"ctx\">\n</tb-doughnut-widget>",
"templateCss": "",
"controllerScript": "self.onInit = function() {\n self.ctx.$scope.doughnutWidget.onInit();\n};\n\nself.onDataUpdated = function() {\n self.ctx.$scope.doughnutWidget.onDataUpdated();\n};\n\nself.typeParameters = function() {\n return {\n previewWidth: '380px',\n previewHeight: '300px',\n embedTitlePanel: true,\n defaultDataKeysFunction: function() {\n return [{ name: 'windPower', label: 'Wind power', type: 'timeseries', color: '#08872B' },\n { name: 'solarPower', label: 'Solar power', type: 'timeseries', color: '#FF4D5A' }];\n }\n };\n};\n\nself.onDestroy = function() {\n};\n",
"controllerScript": "self.onInit = function() {\n self.ctx.$scope.doughnutWidget.onInit();\n};\n\nself.onDataUpdated = function() {\n self.ctx.$scope.doughnutWidget.onDataUpdated();\n};\n\nself.typeParameters = function() {\n return {\n previewWidth: '380px',\n previewHeight: '300px',\n embedTitlePanel: true,\n embedActionsPanel: true,\n defaultDataKeysFunction: function() {\n return [{ name: 'windPower', label: 'Wind power', type: 'timeseries', color: '#08872B' },\n { name: 'solarPower', label: 'Solar power', type: 'timeseries', color: '#FF4D5A' }];\n }\n };\n};\n\nself.onDestroy = function() {\n};\n",
"settingsSchema": "",
"dataKeySettingsSchema": "",
"settingsDirective": "tb-doughnut-widget-settings",

4
application/src/main/data/json/system/widget_types/horizontal_doughnut.json

@ -9,9 +9,9 @@
"sizeX": 4,
"sizeY": 2.5,
"resources": [],
"templateHtml": "<tb-doughnut-widget \n [ctx]=\"ctx\"\n [widgetTitlePanel]=\"widgetTitlePanel\">\n</tb-doughnut-widget>",
"templateHtml": "<tb-doughnut-widget \n [ctx]=\"ctx\">\n</tb-doughnut-widget>",
"templateCss": "",
"controllerScript": "self.onInit = function() {\n self.ctx.$scope.doughnutWidget.onInit();\n};\n\nself.onDataUpdated = function() {\n self.ctx.$scope.doughnutWidget.onDataUpdated();\n};\n\nself.typeParameters = function() {\n return {\n previewWidth: '380px',\n previewHeight: '220px',\n embedTitlePanel: true,\n horizontal: true,\n defaultDataKeysFunction: function() {\n return [{ name: 'windPower', label: 'Wind power', type: 'timeseries', color: '#08872B' },\n { name: 'solarPower', label: 'Solar power', type: 'timeseries', color: '#FF4D5A' }];\n }\n };\n};\n\nself.onDestroy = function() {\n};\n",
"controllerScript": "self.onInit = function() {\n self.ctx.$scope.doughnutWidget.onInit();\n};\n\nself.onDataUpdated = function() {\n self.ctx.$scope.doughnutWidget.onDataUpdated();\n};\n\nself.typeParameters = function() {\n return {\n previewWidth: '380px',\n previewHeight: '220px',\n embedTitlePanel: true,\n embedActionsPanel: true,\n horizontal: true,\n defaultDataKeysFunction: function() {\n return [{ name: 'windPower', label: 'Wind power', type: 'timeseries', color: '#08872B' },\n { name: 'solarPower', label: 'Solar power', type: 'timeseries', color: '#FF4D5A' }];\n }\n };\n};\n\nself.onDestroy = function() {\n};\n",
"settingsSchema": "",
"dataKeySettingsSchema": "",
"settingsDirective": "tb-doughnut-widget-settings",

4
application/src/main/data/json/system/widget_types/image_map.json

@ -9,9 +9,9 @@
"sizeX": 8.5,
"sizeY": 6,
"resources": [],
"templateHtml": "<tb-map-widget \n [ctx]=\"ctx\"\n [widgetTitlePanel]=\"widgetTitlePanel\">\n</tb-map-widget>",
"templateHtml": "<tb-map-widget \n [ctx]=\"ctx\">\n</tb-map-widget>",
"templateCss": "",
"controllerScript": "self.onInit = function() {\n self.ctx.$scope.mapWidget.onInit();\n};\n\nself.typeParameters = function() {\n return {\n hideDataTab: true,\n hideDataSettings: true,\n previewWidth: '80%',\n embedTitlePanel: true,\n datasourcesOptional: true,\n additionalWidgetActionTypes: ['placeMapItem']\n };\n}\n",
"controllerScript": "self.onInit = function() {\n self.ctx.$scope.mapWidget.onInit();\n};\n\nself.typeParameters = function() {\n return {\n hideDataTab: true,\n hideDataSettings: true,\n previewWidth: '80%',\n embedTitlePanel: true,\n embedActionsPanel: true,\n datasourcesOptional: true,\n additionalWidgetActionTypes: ['placeMapItem']\n };\n}\n",
"settingsForm": [],
"dataKeySettingsForm": [],
"settingsDirective": "tb-map-widget-settings",

4
application/src/main/data/json/system/widget_types/line_chart.json

@ -9,9 +9,9 @@
"sizeX": 8,
"sizeY": 5,
"resources": [],
"templateHtml": "<tb-time-series-chart-widget \n [ctx]=\"ctx\"\n [widgetTitlePanel]=\"widgetTitlePanel\">\n</tb-time-series-chart-widget>",
"templateHtml": "<tb-time-series-chart-widget \n [ctx]=\"ctx\">\n</tb-time-series-chart-widget>",
"templateCss": "",
"controllerScript": "self.onInit = function() {\n self.ctx.$scope.timeSeriesChartWidget.onInit();\n};\n\nself.onDataUpdated = function() {\n self.ctx.$scope.timeSeriesChartWidget.onDataUpdated();\n}\n\nself.onLatestDataUpdated = function() {\n self.ctx.$scope.timeSeriesChartWidget.onLatestDataUpdated();\n}\n\nself.typeParameters = function() {\n return {\n chartType: 'line',\n previewWidth: '80%',\n embedTitlePanel: true,\n hasAdditionalLatestDataKeys: true,\n dataKeySettingsFunction: TbTimeSeriesChart.dataKeySettings('line'),\n defaultDataKeysFunction: function() {\n return [{ name: 'temperature', label: 'Temperature', type: 'timeseries', units: '°C', decimals: 0 }];\n }\n };\n}\n",
"controllerScript": "self.onInit = function() {\n self.ctx.$scope.timeSeriesChartWidget.onInit();\n};\n\nself.onDataUpdated = function() {\n self.ctx.$scope.timeSeriesChartWidget.onDataUpdated();\n}\n\nself.onLatestDataUpdated = function() {\n self.ctx.$scope.timeSeriesChartWidget.onLatestDataUpdated();\n}\n\nself.typeParameters = function() {\n return {\n chartType: 'line',\n previewWidth: '80%',\n embedTitlePanel: true,\n embedActionsPanel: true,\n hasAdditionalLatestDataKeys: true,\n dataKeySettingsFunction: TbTimeSeriesChart.dataKeySettings('line'),\n defaultDataKeysFunction: function() {\n return [{ name: 'temperature', label: 'Temperature', type: 'timeseries', units: '°C', decimals: 0 }];\n }\n };\n}\n",
"settingsSchema": "{}",
"dataKeySettingsSchema": "{}",
"latestDataKeySettingsSchema": "{}",

4
application/src/main/data/json/system/widget_types/map.json

@ -9,9 +9,9 @@
"sizeX": 8.5,
"sizeY": 6,
"resources": [],
"templateHtml": "<tb-map-widget \n [ctx]=\"ctx\"\n [widgetTitlePanel]=\"widgetTitlePanel\">\n</tb-map-widget>",
"templateHtml": "<tb-map-widget \n [ctx]=\"ctx\">\n</tb-map-widget>",
"templateCss": "",
"controllerScript": "self.onInit = function() {\n self.ctx.$scope.mapWidget.onInit();\n};\n\nself.typeParameters = function() {\n return {\n hideDataTab: true,\n hideDataSettings: true,\n previewWidth: '80%',\n embedTitlePanel: true,\n datasourcesOptional: true,\n additionalWidgetActionTypes: ['placeMapItem']\n };\n}\n",
"controllerScript": "self.onInit = function() {\n self.ctx.$scope.mapWidget.onInit();\n};\n\nself.typeParameters = function() {\n return {\n hideDataTab: true,\n hideDataSettings: true,\n previewWidth: '80%',\n embedTitlePanel: true,\n embedActionsPanel: true,\n datasourcesOptional: true,\n additionalWidgetActionTypes: ['placeMapItem']\n };\n}\n",
"settingsForm": [],
"dataKeySettingsForm": [],
"settingsDirective": "tb-map-widget-settings",

4
application/src/main/data/json/system/widget_types/pie.json

@ -9,9 +9,9 @@
"sizeX": 5,
"sizeY": 4,
"resources": [],
"templateHtml": "<tb-pie-chart-widget \n [ctx]=\"ctx\"\n [widgetTitlePanel]=\"widgetTitlePanel\">\n</tb-pie-chart-widget>",
"templateHtml": "<tb-pie-chart-widget \n [ctx]=\"ctx\">\n</tb-pie-chart-widget>",
"templateCss": "",
"controllerScript": "self.onInit = function() {\n self.ctx.$scope.pieChartWidget.onInit();\n};\n\nself.onDataUpdated = function() {\n self.ctx.$scope.pieChartWidget.onDataUpdated();\n};\n\nself.typeParameters = function() {\n return {\n previewWidth: '500px',\n previewHeight: '380px',\n embedTitlePanel: true,\n defaultDataKeysFunction: function() {\n return [{ name: 'windPower', label: 'Wind', type: 'timeseries', color: '#08872B' },\n { name: 'solarPower', label: 'Solar', type: 'timeseries', color: '#FF4D5A' },\n { name: 'hydroelectricPower', label: 'Hydroelectric', type: 'timeseries', color: '#FFDE30' }];\n }\n };\n};\n\nself.onDestroy = function() {\n};\n\nself.actionSources = function() {\n return {\n 'sliceClick': {\n name: 'widget-action.pie-slice-click',\n multiple: false\n }\n };\n}\n",
"controllerScript": "self.onInit = function() {\n self.ctx.$scope.pieChartWidget.onInit();\n};\n\nself.onDataUpdated = function() {\n self.ctx.$scope.pieChartWidget.onDataUpdated();\n};\n\nself.typeParameters = function() {\n return {\n previewWidth: '500px',\n previewHeight: '380px',\n embedTitlePanel: true,\n embedActionsPanel: true,\n defaultDataKeysFunction: function() {\n return [{ name: 'windPower', label: 'Wind', type: 'timeseries', color: '#08872B' },\n { name: 'solarPower', label: 'Solar', type: 'timeseries', color: '#FF4D5A' },\n { name: 'hydroelectricPower', label: 'Hydroelectric', type: 'timeseries', color: '#FFDE30' }];\n }\n };\n};\n\nself.onDestroy = function() {\n};\n\nself.actionSources = function() {\n return {\n 'sliceClick': {\n name: 'widget-action.pie-slice-click',\n multiple: false\n }\n };\n}\n",
"settingsSchema": "",
"dataKeySettingsSchema": "",
"settingsDirective": "tb-pie-chart-widget-settings",

4
application/src/main/data/json/system/widget_types/point_chart.json

@ -9,9 +9,9 @@
"sizeX": 8,
"sizeY": 5,
"resources": [],
"templateHtml": "<tb-time-series-chart-widget \n [ctx]=\"ctx\"\n [widgetTitlePanel]=\"widgetTitlePanel\">\n</tb-time-series-chart-widget>",
"templateHtml": "<tb-time-series-chart-widget \n [ctx]=\"ctx\">\n</tb-time-series-chart-widget>",
"templateCss": "",
"controllerScript": "self.onInit = function() {\n self.ctx.$scope.timeSeriesChartWidget.onInit();\n};\n\nself.onDataUpdated = function() {\n self.ctx.$scope.timeSeriesChartWidget.onDataUpdated();\n}\n\nself.onLatestDataUpdated = function() {\n self.ctx.$scope.timeSeriesChartWidget.onLatestDataUpdated();\n}\n\nself.typeParameters = function() {\n return {\n chartType: 'point',\n previewWidth: '80%',\n embedTitlePanel: true,\n hasAdditionalLatestDataKeys: true,\n dataKeySettingsFunction: TbTimeSeriesChart.dataKeySettings('point'),\n defaultDataKeysFunction: function() {\n return [{ name: 'temperature', label: 'Temperature', type: 'timeseries', units: '°C', decimals: 0 }];\n }\n };\n}\n",
"controllerScript": "self.onInit = function() {\n self.ctx.$scope.timeSeriesChartWidget.onInit();\n};\n\nself.onDataUpdated = function() {\n self.ctx.$scope.timeSeriesChartWidget.onDataUpdated();\n}\n\nself.onLatestDataUpdated = function() {\n self.ctx.$scope.timeSeriesChartWidget.onLatestDataUpdated();\n}\n\nself.typeParameters = function() {\n return {\n chartType: 'point',\n previewWidth: '80%',\n embedTitlePanel: true,\n embedActionsPanel: true,\n hasAdditionalLatestDataKeys: true,\n dataKeySettingsFunction: TbTimeSeriesChart.dataKeySettings('point'),\n defaultDataKeysFunction: function() {\n return [{ name: 'temperature', label: 'Temperature', type: 'timeseries', units: '°C', decimals: 0 }];\n }\n };\n}\n",
"settingsSchema": "{}",
"dataKeySettingsSchema": "{}",
"latestDataKeySettingsSchema": "{}",

4
application/src/main/data/json/system/widget_types/polar_area.json

@ -9,9 +9,9 @@
"sizeX": 5,
"sizeY": 4,
"resources": [],
"templateHtml": "<tb-polar-area-chart-widget \n [ctx]=\"ctx\"\n [widgetTitlePanel]=\"widgetTitlePanel\">\n</tb-polar-area-chart-widget>",
"templateHtml": "<tb-polar-area-chart-widget \n [ctx]=\"ctx\">\n</tb-polar-area-chart-widget>",
"templateCss": "",
"controllerScript": "self.onInit = function() {\n self.ctx.$scope.polarAreaChartWidget.onInit();\n};\n\nself.onDataUpdated = function() {\n self.ctx.$scope.polarAreaChartWidget.onDataUpdated();\n};\n\nself.typeParameters = function() {\n return {\n previewWidth: '500px',\n previewHeight: '380px',\n embedTitlePanel: true,\n defaultDataKeysFunction: function() {\n return [{ name: 'windPower', label: 'Wind', type: 'timeseries', color: '#08872B' },\n { name: 'solarPower', label: 'Solar', type: 'timeseries', color: '#FF4D5A' },\n { name: 'hydroelectricPower', label: 'Hydroelectric', type: 'timeseries', color: '#FFDE30' }];\n }\n };\n};\n\nself.onDestroy = function() {\n};\n\n",
"controllerScript": "self.onInit = function() {\n self.ctx.$scope.polarAreaChartWidget.onInit();\n};\n\nself.onDataUpdated = function() {\n self.ctx.$scope.polarAreaChartWidget.onDataUpdated();\n};\n\nself.typeParameters = function() {\n return {\n previewWidth: '500px',\n previewHeight: '380px',\n embedTitlePanel: true,\n embedActionsPanel: true,\n defaultDataKeysFunction: function() {\n return [{ name: 'windPower', label: 'Wind', type: 'timeseries', color: '#08872B' },\n { name: 'solarPower', label: 'Solar', type: 'timeseries', color: '#FF4D5A' },\n { name: 'hydroelectricPower', label: 'Hydroelectric', type: 'timeseries', color: '#FFDE30' }];\n }\n };\n};\n\nself.onDestroy = function() {\n};\n\n",
"settingsSchema": "",
"dataKeySettingsSchema": "",
"settingsDirective": "tb-polar-area-chart-widget-settings",

4
application/src/main/data/json/system/widget_types/radar.json

@ -9,9 +9,9 @@
"sizeX": 5,
"sizeY": 4,
"resources": [],
"templateHtml": "<tb-radar-chart-widget \n [ctx]=\"ctx\"\n [widgetTitlePanel]=\"widgetTitlePanel\">\n</tb-radar-chart-widget>",
"templateHtml": "<tb-radar-chart-widget \n [ctx]=\"ctx\">\n</tb-radar-chart-widget>",
"templateCss": "",
"controllerScript": "self.onInit = function() {\n self.ctx.$scope.radarChartWidget.onInit();\n};\n\nself.onDataUpdated = function() {\n self.ctx.$scope.radarChartWidget.onDataUpdated();\n};\n\nself.typeParameters = function() {\n return {\n previewWidth: '500px',\n previewHeight: '380px',\n embedTitlePanel: true,\n defaultDataKeysFunction: function() {\n return [{ name: 'windPower', label: 'Wind', type: 'timeseries', color: '#08872B' },\n { name: 'solarPower', label: 'Solar', type: 'timeseries', color: '#FF4D5A' },\n { name: 'hydroelectricPower', label: 'Hydroelectric', type: 'timeseries', color: '#FFDE30' }];\n }\n };\n};\n\nself.onDestroy = function() {\n};\n\n",
"controllerScript": "self.onInit = function() {\n self.ctx.$scope.radarChartWidget.onInit();\n};\n\nself.onDataUpdated = function() {\n self.ctx.$scope.radarChartWidget.onDataUpdated();\n};\n\nself.typeParameters = function() {\n return {\n previewWidth: '500px',\n previewHeight: '380px',\n embedTitlePanel: true,\n embedActionsPanel: true,\n defaultDataKeysFunction: function() {\n return [{ name: 'windPower', label: 'Wind', type: 'timeseries', color: '#08872B' },\n { name: 'solarPower', label: 'Solar', type: 'timeseries', color: '#FF4D5A' },\n { name: 'hydroelectricPower', label: 'Hydroelectric', type: 'timeseries', color: '#FFDE30' }];\n }\n };\n};\n\nself.onDestroy = function() {\n};\n\n",
"settingsSchema": "",
"dataKeySettingsSchema": "",
"settingsDirective": "tb-radar-chart-widget-settings",

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

@ -17,7 +17,7 @@
"settingsDirective": "tb-analogue-radial-gauge-widget-settings",
"hasBasicMode": true,
"basicModeDirective": "tb-radial-gauge-basic-config",
"defaultConfig": "{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Temp\",\"color\":\"#2196f3\",\"settings\":{},\"_hash\":0.7282710489093589,\"funcBody\":\"var value = prevValue + Math.random() * 50 - 25;\\nif (value < -100) {\\n\\tvalue = -100;\\n} else if (value > 100) {\\n\\tvalue = 100;\\n}\\nreturn value;\"}]}],\"timewindow\":{\"realtime\":{\"timewindowMs\":60000}},\"showTitle\":false,\"backgroundColor\":\"rgb(255, 255, 255)\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"8px\",\"settings\":{\"maxValue\":100,\"startAngle\":45,\"ticksAngle\":270,\"showBorder\":true,\"defaultColor\":\"#e65100\",\"needleCircleSize\":10,\"highlights\":[],\"showUnitTitle\":true,\"colorPlate\":\"#fff\",\"colorMajorTicks\":\"#444\",\"colorMinorTicks\":\"#666\",\"minorTicks\":10,\"valueInt\":3,\"valueDec\":0,\"highlightsWidth\":15,\"valueBox\":true,\"animation\":true,\"animationDuration\":500,\"animationRule\":\"cycle\",\"colorNeedleShadowUp\":\"rgba(2, 255, 255, 0)\",\"numbersFont\":{\"family\":\"Roboto\",\"size\":18,\"style\":\"normal\",\"weight\":\"500\",\"color\":\"#616161\"},\"titleFont\":{\"family\":\"Roboto\",\"size\":24,\"style\":\"normal\",\"weight\":\"500\",\"color\":\"#888\"},\"unitsFont\":{\"family\":\"Roboto\",\"size\":22,\"style\":\"normal\",\"weight\":\"500\",\"color\":\"#616161\"},\"valueFont\":{\"family\":\"Segment7Standard\",\"size\":36,\"style\":\"normal\",\"weight\":\"normal\",\"shadowColor\":\"rgba(0, 0, 0, 0.49)\",\"color\":\"#444\"},\"minValue\":-100,\"colorNeedleShadowDown\":\"rgba(188,143,143,0.45)\",\"colorValueBoxRect\":\"#888\",\"colorValueBoxRectEnd\":\"#666\",\"colorValueBoxBackground\":\"#babab2\",\"colorValueBoxShadow\":\"rgba(0,0,0,1)\"},\"title\":\"Radial gauge\",\"dropShadow\":true,\"enableFullscreen\":true,\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400},\"widgetStyle\":{},\"widgetCss\":\"\",\"pageSize\":1024,\"decimals\":0,\"noDataDisplayMessage\":\"\",\"configMode\":\"basic\"}"
"defaultConfig": "{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Temp\",\"color\":\"#2196f3\",\"settings\":{},\"_hash\":0.7282710489093589,\"funcBody\":\"var value = prevValue + Math.random() * 50 - 25;\\nif (value < -100) {\\n\\tvalue = -100;\\n} else if (value > 100) {\\n\\tvalue = 100;\\n}\\nreturn value;\"}]}],\"timewindow\":{\"realtime\":{\"timewindowMs\":60000}},\"showTitle\":false,\"backgroundColor\":\"rgb(255, 255, 255)\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"8px\",\"settings\":{\"maxValue\":100,\"startAngle\":45,\"ticksAngle\":270,\"showBorder\":true,\"defaultColor\":\"#e65100\",\"needleCircleSize\":10,\"highlights\":[],\"showUnitTitle\":true,\"colorPlate\":\"#fff\",\"colorMajorTicks\":\"#444\",\"colorMinorTicks\":\"#666\",\"minorTicks\":10,\"valueInt\":3,\"highlightsWidth\":15,\"valueBox\":true,\"animation\":true,\"animationDuration\":500,\"animationRule\":\"cycle\",\"colorNeedleShadowUp\":\"rgba(2, 255, 255, 0)\",\"numbersFont\":{\"family\":\"Roboto\",\"size\":18,\"style\":\"normal\",\"weight\":\"500\",\"color\":\"#616161\"},\"titleFont\":{\"family\":\"Roboto\",\"size\":24,\"style\":\"normal\",\"weight\":\"500\",\"color\":\"#888\"},\"unitsFont\":{\"family\":\"Roboto\",\"size\":22,\"style\":\"normal\",\"weight\":\"500\",\"color\":\"#616161\"},\"valueFont\":{\"family\":\"Segment7Standard\",\"size\":36,\"style\":\"normal\",\"weight\":\"normal\",\"shadowColor\":\"rgba(0, 0, 0, 0.49)\",\"color\":\"#444\"},\"minValue\":-100,\"colorNeedleShadowDown\":\"rgba(188,143,143,0.45)\",\"colorValueBoxRect\":\"#888\",\"colorValueBoxRectEnd\":\"#666\",\"colorValueBoxBackground\":\"#babab2\",\"colorValueBoxShadow\":\"rgba(0,0,0,1)\"},\"title\":\"Radial gauge\",\"dropShadow\":true,\"enableFullscreen\":true,\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400},\"widgetStyle\":{},\"widgetCss\":\"\",\"pageSize\":1024,\"decimals\":0,\"noDataDisplayMessage\":\"\",\"configMode\":\"basic\"}"
},
"resources": [
{

4
application/src/main/data/json/system/widget_types/range_chart.json

@ -9,9 +9,9 @@
"sizeX": 8,
"sizeY": 5,
"resources": [],
"templateHtml": "<tb-range-chart-widget \n [ctx]=\"ctx\"\n [widgetTitlePanel]=\"widgetTitlePanel\">\n</tb-range-chart-widget>",
"templateHtml": "<tb-range-chart-widget \n [ctx]=\"ctx\">\n</tb-range-chart-widget>",
"templateCss": ".legend {\n font-size: 13px;\n line-height: 10px;\n}\n\n.legend table { \n border-spacing: 0px;\n border-collapse: separate;\n}\n\n.mouse-events .flot-overlay {\n cursor: crosshair; \n}\n\n",
"controllerScript": "self.onInit = function() {\n self.ctx.$scope.rangeChartWidget.onInit();\n};\n\nself.onDataUpdated = function() {\n self.ctx.$scope.rangeChartWidget.onDataUpdated();\n}\n\nself.typeParameters = function() {\n return {\n maxDatasources: 1,\n maxDataKeys: 1,\n singleEntity: true,\n previewWidth: '80%',\n embedTitlePanel: true,\n hasAdditionalLatestDataKeys: false,\n defaultDataKeysFunction: function() {\n return [{ name: 'temperature', label: 'Temperature', type: 'timeseries' }];\n }\n };\n}\n",
"controllerScript": "self.onInit = function() {\n self.ctx.$scope.rangeChartWidget.onInit();\n};\n\nself.onDataUpdated = function() {\n self.ctx.$scope.rangeChartWidget.onDataUpdated();\n}\n\nself.typeParameters = function() {\n return {\n maxDatasources: 1,\n maxDataKeys: 1,\n singleEntity: true,\n previewWidth: '80%',\n embedTitlePanel: true,\n embedActionsPanel: true,\n hasAdditionalLatestDataKeys: false,\n defaultDataKeysFunction: function() {\n return [{ name: 'temperature', label: 'Temperature', type: 'timeseries' }];\n }\n };\n}\n",
"settingsSchema": "{}",
"dataKeySettingsSchema": "{}",
"latestDataKeySettingsSchema": "{}",

4
application/src/main/data/json/system/widget_types/route_map.json

@ -9,9 +9,9 @@
"sizeX": 8.5,
"sizeY": 6,
"resources": [],
"templateHtml": "<tb-map-widget \n [ctx]=\"ctx\"\n [widgetTitlePanel]=\"widgetTitlePanel\">\n</tb-map-widget>",
"templateHtml": "<tb-map-widget \n [ctx]=\"ctx\">\n</tb-map-widget>",
"templateCss": "",
"controllerScript": "self.onInit = function() {\n self.ctx.$scope.mapWidget.onInit();\n};\n\nself.typeParameters = function() {\n return {\n trip: true,\n hideDataTab: true,\n hideDataSettings: true,\n previewWidth: '80%',\n embedTitlePanel: true,\n datasourcesOptional: true,\n additionalWidgetActionTypes: ['placeMapItem']\n };\n}",
"controllerScript": "self.onInit = function() {\n self.ctx.$scope.mapWidget.onInit();\n};\n\nself.typeParameters = function() {\n return {\n trip: true,\n hideDataTab: true,\n hideDataSettings: true,\n previewWidth: '80%',\n embedTitlePanel: true,\n embedActionsPanel: true,\n datasourcesOptional: true,\n additionalWidgetActionTypes: ['placeMapItem']\n };\n}",
"settingsForm": [],
"dataKeySettingsForm": [],
"latestDataKeySettingsForm": [],

4
application/src/main/data/json/system/widget_types/state_chart.json

@ -9,9 +9,9 @@
"sizeX": 8,
"sizeY": 5,
"resources": [],
"templateHtml": "<tb-time-series-chart-widget \n [ctx]=\"ctx\"\n [widgetTitlePanel]=\"widgetTitlePanel\">\n</tb-time-series-chart-widget>",
"templateHtml": "<tb-time-series-chart-widget \n [ctx]=\"ctx\">\n</tb-time-series-chart-widget>",
"templateCss": "",
"controllerScript": "self.onInit = function() {\n self.ctx.$scope.timeSeriesChartWidget.onInit();\n};\n\nself.onDataUpdated = function() {\n self.ctx.$scope.timeSeriesChartWidget.onDataUpdated();\n}\n\nself.onLatestDataUpdated = function() {\n self.ctx.$scope.timeSeriesChartWidget.onLatestDataUpdated();\n}\n\nself.typeParameters = function() {\n return {\n stateData: true,\n chartType: 'state',\n previewWidth: '80%',\n embedTitlePanel: true,\n hasAdditionalLatestDataKeys: true,\n dataKeySettingsFunction: TbTimeSeriesChart.dataKeySettings('state'),\n defaultDataKeysFunction: function() {\n return [{ name: 'state', label: 'State', type: 'timeseries', units: '', decimals: 0 }];\n }\n };\n}\n",
"controllerScript": "self.onInit = function() {\n self.ctx.$scope.timeSeriesChartWidget.onInit();\n};\n\nself.onDataUpdated = function() {\n self.ctx.$scope.timeSeriesChartWidget.onDataUpdated();\n}\n\nself.onLatestDataUpdated = function() {\n self.ctx.$scope.timeSeriesChartWidget.onLatestDataUpdated();\n}\n\nself.typeParameters = function() {\n return {\n stateData: true,\n chartType: 'state',\n previewWidth: '80%',\n embedTitlePanel: true,\n embedActionsPanel: true,\n hasAdditionalLatestDataKeys: true,\n dataKeySettingsFunction: TbTimeSeriesChart.dataKeySettings('state'),\n defaultDataKeysFunction: function() {\n return [{ name: 'state', label: 'State', type: 'timeseries', units: '', decimals: 0 }];\n }\n };\n}\n",
"settingsSchema": "{}",
"dataKeySettingsSchema": "{}",
"latestDataKeySettingsSchema": "{}",

4
application/src/main/data/json/system/widget_types/time_series_chart.json

@ -9,9 +9,9 @@
"sizeX": 8,
"sizeY": 5,
"resources": [],
"templateHtml": "<tb-time-series-chart-widget \n [ctx]=\"ctx\"\n [widgetTitlePanel]=\"widgetTitlePanel\">\n</tb-time-series-chart-widget>",
"templateHtml": "<tb-time-series-chart-widget \n [ctx]=\"ctx\">\n</tb-time-series-chart-widget>",
"templateCss": "",
"controllerScript": "self.onInit = function() {\n self.ctx.$scope.timeSeriesChartWidget.onInit();\n};\n\nself.onDataUpdated = function() {\n self.ctx.$scope.timeSeriesChartWidget.onDataUpdated();\n}\n\nself.onLatestDataUpdated = function() {\n self.ctx.$scope.timeSeriesChartWidget.onLatestDataUpdated();\n}\n\nself.typeParameters = function() {\n return {\n previewWidth: '80%',\n embedTitlePanel: true,\n hasAdditionalLatestDataKeys: true,\n dataKeySettingsFunction: TbTimeSeriesChart.dataKeySettings(),\n defaultDataKeysFunction: function() {\n return [{ name: 'temperature', label: 'Temperature', type: 'timeseries', units: '°C', decimals: 0 }];\n }\n };\n}\n",
"controllerScript": "self.onInit = function() {\n self.ctx.$scope.timeSeriesChartWidget.onInit();\n};\n\nself.onDataUpdated = function() {\n self.ctx.$scope.timeSeriesChartWidget.onDataUpdated();\n}\n\nself.onLatestDataUpdated = function() {\n self.ctx.$scope.timeSeriesChartWidget.onLatestDataUpdated();\n}\n\nself.typeParameters = function() {\n return {\n previewWidth: '80%',\n embedTitlePanel: true,\n embedActionsPanel: true,\n hasAdditionalLatestDataKeys: true,\n dataKeySettingsFunction: TbTimeSeriesChart.dataKeySettings(),\n defaultDataKeysFunction: function() {\n return [{ name: 'temperature', label: 'Temperature', type: 'timeseries', units: '°C', decimals: 0 }];\n }\n };\n}\n",
"settingsSchema": "{}",
"dataKeySettingsSchema": "{}",
"latestDataKeySettingsSchema": "{}",

4
application/src/main/data/json/system/widget_types/trip_map.json

@ -9,9 +9,9 @@
"sizeX": 8.5,
"sizeY": 6,
"resources": [],
"templateHtml": "<tb-map-widget \n [ctx]=\"ctx\"\n [widgetTitlePanel]=\"widgetTitlePanel\">\n</tb-map-widget>",
"templateHtml": "<tb-map-widget \n [ctx]=\"ctx\">\n</tb-map-widget>",
"templateCss": "",
"controllerScript": "self.onInit = function() {\n self.ctx.$scope.mapWidget.onInit();\n};\n\nself.typeParameters = function() {\n return {\n trip: true,\n hideDataTab: true,\n hideDataSettings: true,\n previewWidth: '80%',\n embedTitlePanel: true,\n datasourcesOptional: true,\n additionalWidgetActionTypes: ['placeMapItem']\n };\n}",
"controllerScript": "self.onInit = function() {\n self.ctx.$scope.mapWidget.onInit();\n};\n\nself.typeParameters = function() {\n return {\n trip: true,\n hideDataTab: true,\n hideDataSettings: true,\n previewWidth: '80%',\n embedTitlePanel: true,\n embedActionsPanel: true,\n datasourcesOptional: true,\n additionalWidgetActionTypes: ['placeMapItem']\n };\n}",
"settingsForm": [],
"dataKeySettingsForm": [],
"latestDataKeySettingsForm": [],

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

@ -83,3 +83,13 @@ SET profile_data = profile_data
WHERE profile_data->'configuration'->>'maxCalculatedFieldsPerEntity' IS NULL;
-- UPDATE TENANT PROFILE CALCULATED FIELD LIMITS END
-- UPDATE TENANT PROFILE DEBUG DURATION START
UPDATE tenant_profile
SET profile_data = jsonb_set(profile_data, '{configuration,maxDebugModeDurationMinutes}', '15', true)
WHERE
profile_data->'configuration' ? 'maxDebugModeDurationMinutes' = false
OR (profile_data->'configuration'->>'maxDebugModeDurationMinutes')::int = 0;
-- UPDATE TENANT PROFILE DEBUG DURATION END

7
application/src/main/java/org/thingsboard/server/actors/calculatedField/CalculatedFieldEntityActor.java

@ -21,6 +21,7 @@ import org.thingsboard.server.actors.TbActorCtx;
import org.thingsboard.server.actors.TbActorException;
import org.thingsboard.server.common.data.id.EntityId;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.msg.TbActorStopReason;
import org.thingsboard.server.common.msg.ToCalculatedFieldSystemMsg;
import org.thingsboard.server.common.msg.cf.CalculatedFieldPartitionChangeMsg;
@ -47,6 +48,12 @@ public class CalculatedFieldEntityActor extends AbstractCalculatedFieldActor {
}
}
@Override
public void destroy(TbActorStopReason stopReason, Throwable cause) throws TbActorException {
log.debug("[{}] Stopping CF entity actor.", processor.tenantId);
processor.stop();
}
@Override
protected boolean doProcessCfMsg(ToCalculatedFieldSystemMsg msg) throws CalculatedFieldException {
switch (msg.getMsgType()) {

10
application/src/main/java/org/thingsboard/server/actors/calculatedField/CalculatedFieldEntityMessageProcessor.java

@ -92,6 +92,12 @@ public class CalculatedFieldEntityMessageProcessor extends AbstractContextAwareM
this.ctx = ctx;
}
public void stop() {
log.info("[{}][{}] Stopping entity actor.", tenantId, entityId);
states.clear();
ctx.stop(ctx.getSelf());
}
public void process(CalculatedFieldPartitionChangeMsg msg) {
if (!systemContext.getPartitionService().resolve(ServiceType.TB_RULE_ENGINE, DataConstants.CF_QUEUE_NAME, tenantId, entityId).isMyPartition()) {
log.info("[{}] Stopping entity actor due to change partition event.", entityId);
@ -296,6 +302,8 @@ public class CalculatedFieldEntityMessageProcessor extends AbstractContextAwareM
systemContext.persistCalculatedFieldDebugEvent(tenantId, ctx.getCfId(), entityId, state.getArguments(), tbMsgId, tbMsgType, JacksonUtil.writeValueAsString(calculationResult.getResult()), null);
}
}
} else {
callback.onSuccess();
}
} catch (Exception e) {
throw CalculatedFieldException.builder().ctx(ctx).eventEntity(entityId).msgId(tbMsgId).msgType(tbMsgType).arguments(state.getArguments()).cause(e).build();
@ -414,7 +422,7 @@ public class CalculatedFieldEntityMessageProcessor extends AbstractContextAwareM
private Map<String, ArgumentEntry> mapToArgumentsWithFetchedValue(CalculatedFieldCtx ctx, List<String> removedTelemetryKeys) {
Map<String, Argument> deletedArguments = ctx.getArguments().entrySet().stream()
.filter(entry -> removedTelemetryKeys.contains(entry.getKey()))
.filter(entry -> removedTelemetryKeys.contains(entry.getValue().getRefEntityKey().getKey()))
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
Map<String, ArgumentEntry> fetchedArgs = cfService.fetchArgsFromDb(tenantId, entityId, deletedArguments);

7
application/src/main/java/org/thingsboard/server/actors/calculatedField/CalculatedFieldManagerActor.java

@ -20,6 +20,7 @@ import org.thingsboard.server.actors.ActorSystemContext;
import org.thingsboard.server.actors.TbActorCtx;
import org.thingsboard.server.actors.TbActorException;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.msg.TbActorStopReason;
import org.thingsboard.server.common.msg.ToCalculatedFieldSystemMsg;
import org.thingsboard.server.common.msg.cf.CalculatedFieldEntityLifecycleMsg;
import org.thingsboard.server.common.msg.cf.CalculatedFieldInitMsg;
@ -52,6 +53,12 @@ public class CalculatedFieldManagerActor extends AbstractCalculatedFieldActor {
}
}
@Override
public void destroy(TbActorStopReason stopReason, Throwable cause) throws TbActorException {
log.debug("[{}] Stopping CF manager actor.", processor.tenantId);
processor.stop();
}
@Override
protected boolean doProcessCfMsg(ToCalculatedFieldSystemMsg msg) throws CalculatedFieldException {
switch (msg.getMsgType()) {

24
application/src/main/java/org/thingsboard/server/actors/calculatedField/CalculatedFieldManagerMessageProcessor.java

@ -56,7 +56,6 @@ import java.util.concurrent.CopyOnWriteArrayList;
import static org.thingsboard.server.utils.CalculatedFieldUtils.fromProto;
/**
* @author Andrew Shvayka
*/
@ -92,8 +91,17 @@ public class CalculatedFieldManagerMessageProcessor extends AbstractContextAware
this.ctx = ctx;
}
public void stop() {
log.info("[{}] Stopping CF manager actor.", tenantId);
calculatedFields.values().forEach(CalculatedFieldCtx::stop);
calculatedFields.clear();
entityIdCalculatedFields.clear();
entityIdCalculatedFieldLinks.clear();
ctx.stop(ctx.getSelf());
}
public void onFieldInitMsg(CalculatedFieldInitMsg msg) throws CalculatedFieldException {
log.info("[{}] Processing CF init message.", msg.getCf().getId());
log.debug("[{}] Processing CF init message.", msg.getCf().getId());
var cf = msg.getCf();
var cfCtx = new CalculatedFieldCtx(cf, systemContext.getTbelInvokeService(), systemContext.getApiLimitService());
try {
@ -109,7 +117,7 @@ public class CalculatedFieldManagerMessageProcessor extends AbstractContextAware
}
public void onLinkInitMsg(CalculatedFieldLinkInitMsg msg) {
log.info("[{}] Processing CF link init message for entity [{}].", msg.getLink().getCalculatedFieldId(), msg.getLink().getEntityId());
log.debug("[{}] Processing CF link init message for entity [{}].", msg.getLink().getCalculatedFieldId(), msg.getLink().getEntityId());
var link = msg.getLink();
// We use copy on write lists to safely pass the reference to another actor for the iteration.
// Alternative approach would be to use any list but avoid modifications to the list (change the complete map value instead)
@ -122,7 +130,9 @@ public class CalculatedFieldManagerMessageProcessor extends AbstractContextAware
var calculatedField = calculatedFields.get(cfId);
if (calculatedField != null) {
msg.getState().setRequiredArguments(calculatedField.getArgNames());
if (msg.getState() != null) {
msg.getState().setRequiredArguments(calculatedField.getArgNames());
}
log.debug("Pushing CF state restore msg to specific actor [{}]", msg.getId().entityId());
getOrCreateActor(msg.getId().entityId()).tell(msg);
} else {
@ -131,7 +141,7 @@ public class CalculatedFieldManagerMessageProcessor extends AbstractContextAware
}
public void onEntityLifecycleMsg(CalculatedFieldEntityLifecycleMsg msg) throws CalculatedFieldException {
log.info("Processing entity lifecycle event: [{}] for entity: [{}]", msg.getData().getEvent(), msg.getData().getEntityId());
log.debug("Processing entity lifecycle event: [{}] for entity: [{}]", msg.getData().getEvent(), msg.getData().getEntityId());
var entityType = msg.getData().getEntityId().getEntityType();
var event = msg.getData().getEvent();
switch (entityType) {
@ -357,6 +367,10 @@ public class CalculatedFieldManagerMessageProcessor extends AbstractContextAware
log.debug("Received linked telemetry msg from entity [{}]", sourceEntityId);
var proto = msg.getProto();
var linksList = proto.getLinksList();
if (linksList.isEmpty()) {
log.debug("[{}] No CF links to process new telemetry.", msg.getTenantId());
msg.getCallback().onSuccess();
}
for (var linkProto : linksList) {
var link = fromProto(linkProto);
var targetEntityId = link.entityId();

10
application/src/main/java/org/thingsboard/server/actors/tenant/TenantActor.java

@ -28,6 +28,7 @@ import org.thingsboard.server.actors.TbEntityActorId;
import org.thingsboard.server.actors.TbEntityTypeActorIdPredicate;
import org.thingsboard.server.actors.TbStringActorId;
import org.thingsboard.server.actors.calculatedField.CalculatedFieldManagerActorCreator;
import org.thingsboard.server.actors.calculatedField.CalculatedFieldStateRestoreMsg;
import org.thingsboard.server.actors.device.DeviceActorCreator;
import org.thingsboard.server.actors.ruleChain.RuleChainManagerActor;
import org.thingsboard.server.actors.service.ContextBasedCreator;
@ -126,6 +127,9 @@ public class TenantActor extends RuleChainManagerActor {
@Override
public void destroy(TbActorStopReason stopReason, Throwable cause) {
log.info("[{}] Stopping tenant actor.", tenantId);
if (cfActor != null) {
ctx.stop(cfActor.getActorId());
}
}
@Override
@ -190,7 +194,11 @@ public class TenantActor extends RuleChainManagerActor {
private void onToCalculatedFieldSystemActorMsg(ToCalculatedFieldSystemMsg msg, boolean priority) {
if (cfActor == null) {
log.warn("[{}] CF Actor is not initialized.", tenantId);
if (msg instanceof CalculatedFieldStateRestoreMsg) {
log.warn("[{}] CF Actor is not initialized. ToCalculatedFieldSystemMsg: [{}]", tenantId, msg);
} else {
log.debug("[{}] CF Actor is not initialized. ToCalculatedFieldSystemMsg: [{}]", tenantId, msg);
}
return;
}
if (priority) {

2
application/src/main/java/org/thingsboard/server/config/ThingsboardSecurityConfiguration.java

@ -82,7 +82,7 @@ public class ThingsboardSecurityConfiguration {
public static final String TOKEN_BASED_AUTH_ENTRY_POINT = "/api/**";
public static final String WS_ENTRY_POINT = "/api/ws/**";
public static final String MAIL_OAUTH2_PROCESSING_ENTRY_POINT = "/api/admin/mail/oauth2/code";
public static final String DEVICE_CONNECTIVITY_CERTIFICATE_DOWNLOAD_ENTRY_POINT = "/api/device-connectivity/mqtts/certificate/download";
public static final String DEVICE_CONNECTIVITY_CERTIFICATE_DOWNLOAD_ENTRY_POINT = "/api/device-connectivity/*/certificate/download";
@Value("${server.http.max_payload_size:/api/image*/**=52428800;/api/resource/**=52428800;/api/**=16777216}")
private String maxPayloadSizeConfig;

9
application/src/main/java/org/thingsboard/server/service/cf/ctx/state/CalculatedFieldCtx.java

@ -122,6 +122,15 @@ public class CalculatedFieldCtx {
}
}
public void stop() {
if (calculatedFieldScriptEngine != null) {
calculatedFieldScriptEngine.destroy();
}
if (customExpression != null) {
customExpression.remove();
}
}
private CalculatedFieldScriptEngine initEngine(TenantId tenantId, String expression, TbelInvokeService tbelInvokeService) {
if (tbelInvokeService == null) {
throw new IllegalArgumentException("TBEL script engine is disabled!");

5
application/src/main/java/org/thingsboard/server/service/cf/ctx/state/KafkaCalculatedFieldStateService.java

@ -97,7 +97,10 @@ public class KafkaCalculatedFieldStateService extends AbstractCalculatedFieldSta
.scheduler(eventConsumer.getScheduler())
.taskExecutor(eventConsumer.getTaskExecutor())
.build();
super.stateService = new KafkaQueueStateService<>(eventConsumer, stateConsumer);
super.stateService = KafkaQueueStateService.<TbProtoQueueMsg<ToCalculatedFieldMsg>, TbProtoQueueMsg<CalculatedFieldStateProto>>builder()
.eventConsumer(eventConsumer)
.stateConsumer(stateConsumer)
.build();
this.stateProducer = (TbKafkaProducerTemplate<TbProtoQueueMsg<CalculatedFieldStateProto>>) queueFactory.createCalculatedFieldStateProducer();
}

5
application/src/main/java/org/thingsboard/server/service/edqs/DefaultEdqsApiService.java

@ -76,8 +76,9 @@ public class DefaultEdqsApiService implements EdqsApiService {
requestMsg.setCustomerIdLSB(customerId.getId().getLeastSignificantBits());
}
Integer partition = edqsPartitionService.resolvePartition(tenantId);
ListenableFuture<TbProtoQueueMsg<FromEdqsMsg>> resultFuture = requestTemplate.send(new TbProtoQueueMsg<>(UUID.randomUUID(), requestMsg.build()), partition);
UUID key = UUID.randomUUID();
Integer partition = edqsPartitionService.resolvePartition(tenantId, key);
ListenableFuture<TbProtoQueueMsg<FromEdqsMsg>> resultFuture = requestTemplate.send(new TbProtoQueueMsg<>(key, requestMsg.build()), partition);
return Futures.transform(resultFuture, msg -> {
TransportProtos.EdqsResponseMsg responseMsg = msg.getValue().getResponseMsg();
return JacksonUtil.fromString(responseMsg.getValue(), EdqsResponse.class);

14
application/src/main/java/org/thingsboard/server/service/edqs/DefaultEdqsService.java

@ -59,7 +59,6 @@ import org.thingsboard.server.gen.transport.TransportProtos.ToEdqsMsg;
import org.thingsboard.server.queue.discovery.HashPartitionService;
import org.thingsboard.server.queue.discovery.TbServiceInfoProvider;
import org.thingsboard.server.queue.discovery.TopicService;
import org.thingsboard.server.queue.edqs.EdqsQueue;
import org.thingsboard.server.queue.environment.DistributedLock;
import org.thingsboard.server.queue.environment.DistributedLockService;
import org.thingsboard.server.queue.provider.EdqsClientQueueFactory;
@ -96,10 +95,8 @@ public class DefaultEdqsService implements EdqsService {
private void init() {
executor = ThingsBoardExecutors.newWorkStealingPool(12, getClass());
eventsProducer = EdqsProducer.builder()
.queue(EdqsQueue.EVENTS)
.producer(queueFactory.createEdqsEventsProducer())
.partitionService(edqsPartitionService)
.topicService(topicService)
.producer(queueFactory.createEdqsMsgProducer(EdqsQueue.EVENTS))
.build();
syncLock = distributedLockService.getLock("edqs_sync");
}
@ -150,9 +147,12 @@ public class DefaultEdqsService implements EdqsService {
syncLock.lock();
try {
EdqsSyncState syncState = getSyncState();
if (syncState != null && syncState.getStatus() == EdqsSyncStatus.FINISHED) {
log.info("EDQS sync is already finished");
return;
if (syncState != null) {
EdqsSyncStatus status = syncState.getStatus();
if (status == EdqsSyncStatus.FINISHED || status == EdqsSyncStatus.FAILED) {
log.info("EDQS sync is already " + status + ", ignoring the msg");
return;
}
}
saveSyncState(EdqsSyncStatus.STARTED);

14
application/src/main/java/org/thingsboard/server/service/edqs/KafkaEdqsSyncService.java

@ -17,11 +17,14 @@ package org.thingsboard.server.service.edqs;
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
import org.springframework.stereotype.Service;
import org.thingsboard.server.queue.edqs.EdqsQueue;
import org.thingsboard.server.common.msg.queue.TopicPartitionInfo;
import org.thingsboard.server.queue.edqs.EdqsConfig;
import org.thingsboard.server.queue.kafka.TbKafkaAdmin;
import org.thingsboard.server.queue.kafka.TbKafkaSettings;
import java.util.Collections;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
@Service
@ConditionalOnExpression("'${queue.edqs.sync.enabled:true}' == 'true' && '${queue.type:null}' == 'kafka'")
@ -29,9 +32,14 @@ public class KafkaEdqsSyncService extends EdqsSyncService {
private final boolean syncNeeded;
public KafkaEdqsSyncService(TbKafkaSettings kafkaSettings) {
public KafkaEdqsSyncService(TbKafkaSettings kafkaSettings, EdqsConfig edqsConfig) {
TbKafkaAdmin kafkaAdmin = new TbKafkaAdmin(kafkaSettings, Collections.emptyMap());
this.syncNeeded = kafkaAdmin.isTopicEmpty(EdqsQueue.EVENTS.getTopic());
this.syncNeeded = kafkaAdmin.areAllTopicsEmpty(IntStream.range(0, edqsConfig.getPartitions())
.mapToObj(partition -> TopicPartitionInfo.builder()
.topic(edqsConfig.getEventsTopic())
.partition(partition)
.build().getFullTopicName())
.collect(Collectors.toSet()));
}
@Override

5
application/src/main/java/org/thingsboard/server/service/install/DefaultSystemDataLoaderService.java

@ -122,6 +122,7 @@ import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import static org.thingsboard.common.util.DebugModeUtil.DEBUG_MODE_DEFAULT_DURATION_MINUTES;
import static org.thingsboard.server.common.data.DataConstants.DEFAULT_DEVICE_TYPE;
import static org.thingsboard.server.service.security.auth.jwt.settings.DefaultJwtSettingsService.isSigningKeyDefault;
import static org.thingsboard.server.service.security.auth.jwt.settings.DefaultJwtSettingsService.validateKeyLength;
@ -199,7 +200,9 @@ public class DefaultSystemDataLoaderService implements SystemDataLoaderService {
tenantProfileService.findOrCreateDefaultTenantProfile(TenantId.SYS_TENANT_ID);
TenantProfileData isolatedRuleEngineTenantProfileData = new TenantProfileData();
isolatedRuleEngineTenantProfileData.setConfiguration(new DefaultTenantProfileConfiguration());
DefaultTenantProfileConfiguration configuration = new DefaultTenantProfileConfiguration();
configuration.setMaxDebugModeDurationMinutes(DEBUG_MODE_DEFAULT_DURATION_MINUTES);
isolatedRuleEngineTenantProfileData.setConfiguration(configuration);
TenantProfileQueueConfiguration mainQueueConfiguration = new TenantProfileQueueConfiguration();
mainQueueConfiguration.setName(DataConstants.MAIN_QUEUE_NAME);

20
application/src/main/java/org/thingsboard/server/service/queue/DefaultTbCalculatedFieldConsumerService.java

@ -15,7 +15,6 @@
*/
package org.thingsboard.server.service.queue;
import jakarta.annotation.PostConstruct;
import jakarta.annotation.PreDestroy;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
@ -55,7 +54,7 @@ import org.thingsboard.server.service.cf.CalculatedFieldCache;
import org.thingsboard.server.service.cf.CalculatedFieldStateService;
import org.thingsboard.server.service.profile.TbAssetProfileCache;
import org.thingsboard.server.service.profile.TbDeviceProfileCache;
import org.thingsboard.server.service.queue.processing.AbstractConsumerService;
import org.thingsboard.server.service.queue.processing.AbstractPartitionBasedConsumerService;
import org.thingsboard.server.service.queue.processing.IdMsgPair;
import org.thingsboard.server.service.security.auth.jwt.settings.JwtSettingsService;
@ -72,7 +71,7 @@ import java.util.stream.Collectors;
@Service
@TbRuleEngineComponent
@Slf4j
public class DefaultTbCalculatedFieldConsumerService extends AbstractConsumerService<ToCalculatedFieldNotificationMsg> implements TbCalculatedFieldConsumerService {
public class DefaultTbCalculatedFieldConsumerService extends AbstractPartitionBasedConsumerService<ToCalculatedFieldNotificationMsg> implements TbCalculatedFieldConsumerService {
@Value("${queue.calculated_fields.poll_interval:25}")
private long pollInterval;
@ -99,10 +98,8 @@ public class DefaultTbCalculatedFieldConsumerService extends AbstractConsumerSer
this.stateService = stateService;
}
@PostConstruct
public void init() {
super.init("tb-cf");
@Override
protected void onStartUp() {
var queueKey = new QueueKey(ServiceType.TB_RULE_ENGINE, DataConstants.CF_QUEUE_NAME);
PartitionedQueueConsumerManager<TbProtoQueueMsg<ToCalculatedFieldMsg>> eventConsumer = PartitionedQueueConsumerManager.<TbProtoQueueMsg<ToCalculatedFieldMsg>>create()
.queueKey(queueKey)
@ -129,7 +126,7 @@ public class DefaultTbCalculatedFieldConsumerService extends AbstractConsumerSer
}
@Override
protected void onTbApplicationEvent(PartitionChangeEvent event) {
protected void onPartitionChangeEvent(PartitionChangeEvent event) {
try {
event.getNewPartitions().forEach((queueKey, partitions) -> {
if (queueKey.getQueueName().equals(DataConstants.CF_QUEUE_NAME)) {
@ -193,6 +190,11 @@ public class DefaultTbCalculatedFieldConsumerService extends AbstractConsumerSer
return ServiceType.TB_RULE_ENGINE;
}
@Override
protected String getPrefix() {
return "tb-cf";
}
@Override
protected long getNotificationPollDuration() {
return pollInterval;
@ -210,7 +212,7 @@ public class DefaultTbCalculatedFieldConsumerService extends AbstractConsumerSer
@Override
protected TbQueueConsumer<TbProtoQueueMsg<ToCalculatedFieldNotificationMsg>> createNotificationsConsumer() {
return queueFactory.createToCalculatedFieldNotificationsMsgConsumer();
return queueFactory.createToCalculatedFieldNotificationMsgConsumer();
}
@Override

17
application/src/main/java/org/thingsboard/server/service/queue/DefaultTbRuleEngineConsumerService.java

@ -15,7 +15,6 @@
*/
package org.thingsboard.server.service.queue;
import jakarta.annotation.PostConstruct;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.event.EventListener;
@ -50,7 +49,7 @@ import org.thingsboard.server.service.apiusage.TbApiUsageStateService;
import org.thingsboard.server.service.cf.CalculatedFieldCache;
import org.thingsboard.server.service.profile.TbAssetProfileCache;
import org.thingsboard.server.service.profile.TbDeviceProfileCache;
import org.thingsboard.server.service.queue.processing.AbstractConsumerService;
import org.thingsboard.server.service.queue.processing.AbstractPartitionBasedConsumerService;
import org.thingsboard.server.service.queue.ruleengine.TbRuleEngineConsumerContext;
import org.thingsboard.server.service.queue.ruleengine.TbRuleEngineQueueConsumerManager;
import org.thingsboard.server.service.rpc.TbRuleEngineDeviceRpcService;
@ -67,7 +66,7 @@ import java.util.stream.Collectors;
@Service
@TbRuleEngineComponent
@Slf4j
public class DefaultTbRuleEngineConsumerService extends AbstractConsumerService<ToRuleEngineNotificationMsg> implements TbRuleEngineConsumerService {
public class DefaultTbRuleEngineConsumerService extends AbstractPartitionBasedConsumerService<ToRuleEngineNotificationMsg> implements TbRuleEngineConsumerService {
private final TbRuleEngineConsumerContext ctx;
private final QueueService queueService;
@ -93,9 +92,8 @@ public class DefaultTbRuleEngineConsumerService extends AbstractConsumerService<
this.queueService = queueService;
}
@PostConstruct
public void init() {
super.init("tb-rule-engine");
@Override
protected void onStartUp() {
List<Queue> queues = queueService.findAllQueues();
for (Queue configuration : queues) {
if (partitionService.isManagedByCurrentService(configuration.getTenantId())) {
@ -106,7 +104,7 @@ public class DefaultTbRuleEngineConsumerService extends AbstractConsumerService<
}
@Override
protected void onTbApplicationEvent(PartitionChangeEvent event) {
protected void onPartitionChangeEvent(PartitionChangeEvent event) {
event.getNewPartitions().forEach((queueKey, partitions) -> {
if (DataConstants.CF_QUEUE_NAME.equals(queueKey.getQueueName()) || DataConstants.CF_STATES_QUEUE_NAME.equals(queueKey.getQueueName())) {
return;
@ -150,6 +148,11 @@ public class DefaultTbRuleEngineConsumerService extends AbstractConsumerService<
return ServiceType.TB_RULE_ENGINE;
}
@Override
protected String getPrefix() {
return "tb-rule-engine";
}
@Override
protected long getNotificationPollDuration() {
return ctx.getPollDuration();

93
application/src/main/java/org/thingsboard/server/service/queue/processing/AbstractPartitionBasedConsumerService.java

@ -0,0 +1,93 @@
/**
* Copyright © 2016-2025 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thingsboard.server.service.queue.processing;
import jakarta.annotation.PostConstruct;
import org.springframework.context.ApplicationEventPublisher;
import org.thingsboard.server.actors.ActorSystemContext;
import org.thingsboard.server.dao.tenant.TbTenantProfileCache;
import org.thingsboard.server.queue.discovery.PartitionService;
import org.thingsboard.server.queue.discovery.event.PartitionChangeEvent;
import org.thingsboard.server.queue.util.AfterStartUp;
import org.thingsboard.server.service.apiusage.TbApiUsageStateService;
import org.thingsboard.server.service.cf.CalculatedFieldCache;
import org.thingsboard.server.service.profile.TbAssetProfileCache;
import org.thingsboard.server.service.profile.TbDeviceProfileCache;
import org.thingsboard.server.service.security.auth.jwt.settings.JwtSettingsService;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public abstract class AbstractPartitionBasedConsumerService<N extends com.google.protobuf.GeneratedMessageV3> extends AbstractConsumerService<N> {
private final Lock startupLock = new ReentrantLock();
private volatile boolean started = false;
private PartitionChangeEvent lastPartitionChangeEvent;
public AbstractPartitionBasedConsumerService(ActorSystemContext actorContext,
TbTenantProfileCache tenantProfileCache,
TbDeviceProfileCache deviceProfileCache,
TbAssetProfileCache assetProfileCache,
CalculatedFieldCache calculatedFieldCache,
TbApiUsageStateService apiUsageStateService,
PartitionService partitionService,
ApplicationEventPublisher eventPublisher,
JwtSettingsService jwtSettingsService) {
super(actorContext, tenantProfileCache, deviceProfileCache, assetProfileCache, calculatedFieldCache, apiUsageStateService, partitionService, eventPublisher, jwtSettingsService);
}
@PostConstruct
public void init() {
super.init(getPrefix());
}
@AfterStartUp(order = AfterStartUp.REGULAR_SERVICE)
@Override
public void afterStartUp() {
super.afterStartUp();
onStartUp();
startupLock.lock();
try {
onPartitionChangeEvent(lastPartitionChangeEvent);
started = true;
} finally {
startupLock.unlock();
}
}
@Override
protected void onTbApplicationEvent(PartitionChangeEvent event) {
if (!started) {
startupLock.lock();
try {
if (!started) {
lastPartitionChangeEvent = event;
return;
}
} finally {
startupLock.unlock();
}
}
onPartitionChangeEvent(event);
}
protected abstract void onStartUp();
protected abstract void onPartitionChangeEvent(PartitionChangeEvent event);
protected abstract String getPrefix();
}

7
application/src/main/java/org/thingsboard/server/service/subscription/DefaultTbEntityDataSubscriptionService.java

@ -725,7 +725,12 @@ public class DefaultTbEntityDataSubscriptionService implements TbEntityDataSubsc
update = new EntityDataUpdate(ctx.getCmdId(), ctx.getData(), null, ctx.getMaxEntitiesPerDataSubscription());
ctx.setInitialDataSent(true);
} else {
update = new EntityDataUpdate(ctx.getCmdId(), null, ctx.getData().getData(), ctx.getMaxEntitiesPerDataSubscription());
// if ctx has timeseries subscription, timeseries values are cleared after each update and is empty in ctx data,
// so to avoid sending timeseries update with empty map we set it to null
List<EntityData> preparedData = ctx.getData().getData().stream()
.map(entityData -> new EntityData(entityData.getEntityId(), entityData.getLatest(), null))
.toList();
update = new EntityDataUpdate(ctx.getCmdId(), null, preparedData, ctx.getMaxEntitiesPerDataSubscription());
}
ctx.sendWsMsg(update);
} finally {

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

@ -1645,12 +1645,12 @@ queue:
calculated-field: "${TB_QUEUE_KAFKA_CF_TOPIC_PROPERTIES:retention.ms:604800000;segment.bytes:52428800;retention.bytes:1048576000;partitions:1;min.insync.replicas:1}"
# Kafka properties for Calculated Field State topics
calculated-field-state: "${TB_QUEUE_KAFKA_CF_STATE_TOPIC_PROPERTIES:retention.ms:-1;segment.bytes:52428800;retention.bytes:104857600000;partitions:1;min.insync.replicas:1;cleanup.policy:compact}"
# Kafka properties for EDQS events topics. Partitions number must be the same as queue.edqs.partitions
edqs-events: "${TB_QUEUE_KAFKA_EDQS_EVENTS_TOPIC_PROPERTIES:retention.ms:604800000;segment.bytes:52428800;retention.bytes:-1;partitions:12;min.insync.replicas:1}"
# Kafka properties for EDQS requests topic (default: 3 minutes retention). Partitions number must be the same as queue.edqs.partitions
edqs-requests: "${TB_QUEUE_KAFKA_EDQS_REQUESTS_TOPIC_PROPERTIES:retention.ms:180000;segment.bytes:52428800;retention.bytes:1048576000;partitions:12;min.insync.replicas:1}"
# Kafka properties for EDQS state topic (infinite retention, compaction). Partitions number must be the same as queue.edqs.partitions
edqs-state: "${TB_QUEUE_KAFKA_EDQS_STATE_TOPIC_PROPERTIES:retention.ms:-1;segment.bytes:52428800;retention.bytes:-1;partitions:12;min.insync.replicas:1;cleanup.policy:compact}"
# Kafka properties for EDQS events topics
edqs-events: "${TB_QUEUE_KAFKA_EDQS_EVENTS_TOPIC_PROPERTIES:retention.ms:86400000;segment.bytes:52428800;retention.bytes:-1;partitions:1;min.insync.replicas:1}"
# Kafka properties for EDQS requests topic (default: 3 minutes retention)
edqs-requests: "${TB_QUEUE_KAFKA_EDQS_REQUESTS_TOPIC_PROPERTIES:retention.ms:180000;segment.bytes:52428800;retention.bytes:1048576000;partitions:1;min.insync.replicas:1}"
# Kafka properties for EDQS state topic (infinite retention, compaction)
edqs-state: "${TB_QUEUE_KAFKA_EDQS_STATE_TOPIC_PROPERTIES:retention.ms:-1;segment.bytes:52428800;retention.bytes:-1;partitions:1;min.insync.replicas:1;cleanup.policy:compact}"
consumer-stats:
# Prints lag between consumer group offset and last messages offset in Kafka topics
enabled: "${TB_QUEUE_KAFKA_CONSUMER_STATS_ENABLED:true}"
@ -1748,6 +1748,10 @@ queue:
partitions: "${TB_EDQS_PARTITIONS:12}"
# EDQS partitioning strategy: tenant (partition is resolved by tenant id) or none (no specific strategy, resolving by message key)
partitioning_strategy: "${TB_EDQS_PARTITIONING_STRATEGY:tenant}"
# EDQS events topic
events_topic: "${TB_EDQS_EVENTS_TOPIC:edqs.events}"
# EDQS state topic
state_topic: "${TB_EDQS_STATE_TOPIC:edqs.state}"
# EDQS requests topic
requests_topic: "${TB_EDQS_REQUESTS_TOPIC:edqs.requests}"
# EDQS responses topic

3
application/src/test/java/org/thingsboard/server/controller/EntityQueryControllerTest.java

@ -17,8 +17,6 @@ package org.thingsboard.server.controller;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JsonNode;
import org.awaitility.Awaitility;
import com.fasterxml.jackson.databind.node.ObjectNode;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
@ -73,7 +71,6 @@ import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.function.BiPredicate;
import java.util.stream.Collectors;
import static org.assertj.core.api.Assertions.assertThat;

2
application/src/test/java/org/thingsboard/server/service/entitiy/EdqsEntityServiceTest.java

@ -110,7 +110,7 @@ public class EdqsEntityServiceTest extends EntityServiceTest {
@Override
protected List<EntityData> findByQueryAndCheckTelemetry(EntityDataQuery query, EntityKeyType entityKeyType, String key, List<String> expectedTelemetries) {
return await().atMost(TIMEOUT, TimeUnit.SECONDS).until(() -> findEntitiesTelemetry(query, entityKeyType, key, expectedTelemetries),
return await().atMost(TIMEOUT, TimeUnit.SECONDS).until(() -> loadAllData(query, expectedTelemetries.size()),
loadedEntities -> loadedEntities.stream().map(entityData -> entityData.getLatest().get(entityKeyType).get(key).getValue()).toList().containsAll(expectedTelemetries));
}

19
application/src/test/java/org/thingsboard/server/service/entitiy/EntityServiceTest.java

@ -1698,6 +1698,19 @@ public class EntityServiceTest extends AbstractControllerTest {
query = new EntityDataQuery(filter, pageLink, entityFields, latestValues, keyFilters);
findByQueryAndCheckTelemetry(query, EntityKeyType.TIME_SERIES, "temperature", deviceHighTemperatures);
// change sort order to sort by temperature
temperatures.sort(Comparator.naturalOrder());
List<String> expectedSortedList = temperatures.stream().map(aDouble -> Double.toString(aDouble)).collect(Collectors.toList());
EntityDataSortOrder sortByTempOrder = new EntityDataSortOrder(
new EntityKey(EntityKeyType.TIME_SERIES, "temperature"), EntityDataSortOrder.Direction.ASC);
EntityDataPageLink sortByTempPageLink = new EntityDataPageLink(10, 0, null, sortByTempOrder);
EntityDataQuery querySortByTemp = new EntityDataQuery(filter, sortByTempPageLink, entityFields, latestValues, null);
List<EntityData> loadedEntities = loadAllData(querySortByTemp, deviceTemperatures.size());
List<String> entitiesTelemetry = loadedEntities.stream().map(entityData -> entityData.getLatest().get(EntityKeyType.TIME_SERIES).get("temperature").getValue()).toList();
assertThat(entitiesTelemetry).containsExactlyElementsOf(expectedSortedList);
deviceService.deleteDevicesByTenantId(tenantId);
}
@ -2377,14 +2390,14 @@ public class EntityServiceTest extends AbstractControllerTest {
}
protected List<EntityData> findByQueryAndCheckTelemetry(EntityDataQuery query, EntityKeyType entityKeyType, String key, List<String> expectedTelemetry) {
List<EntityData> loadedEntities = findEntitiesTelemetry(query, entityKeyType, key, expectedTelemetry);
List<EntityData> loadedEntities = loadAllData(query, expectedTelemetry.size());
List<String> entitiesTelemetry = loadedEntities.stream().map(entityData -> entityData.getLatest().get(entityKeyType).get(key).getValue()).toList();
assertThat(entitiesTelemetry).containsExactlyInAnyOrderElementsOf(expectedTelemetry);
return loadedEntities;
}
protected List<EntityData> findEntitiesTelemetry(EntityDataQuery query, EntityKeyType entityKeyType, String key, List<String> expectedTelemetries) {
PageData<EntityData> data = findByQueryAndCheck(query, expectedTelemetries.size());
protected List<EntityData> loadAllData(EntityDataQuery query, int expectedSize) {
PageData<EntityData> data = findByQueryAndCheck(query, expectedSize);
List<EntityData> loadedEntities = new ArrayList<>(data.getData());
while (data.hasNext()) {
query = query.next();

2
common/data/src/main/java/org/thingsboard/server/common/data/edqs/DataPoint.java

@ -17,7 +17,7 @@ package org.thingsboard.server.common.data.edqs;
import org.thingsboard.server.common.data.kv.DataType;
public interface DataPoint {
public interface DataPoint extends Comparable<DataPoint> {
String NOT_SUPPORTED = "Not supported!";

6
common/edqs/src/main/java/org/thingsboard/server/edqs/data/CustomerData.java

@ -50,10 +50,10 @@ public class CustomerData extends BaseEntityData<CustomerFields> {
entitiesById.computeIfAbsent(ed.getEntityType(), et -> new ConcurrentHashMap<>()).put(ed.getId(), ed);
}
public boolean remove(EntityData<?> ed) {
var map = entitiesById.get(ed.getEntityType());
public boolean remove(EntityType entityType, UUID entityId) {
var map = entitiesById.get(entityType);
if (map != null) {
return map.remove(ed.getId()) != null;
return map.remove(entityId) != null;
} else {
return false;
}

6
common/edqs/src/main/java/org/thingsboard/server/edqs/data/dp/AbstractDataPoint.java

@ -17,6 +17,7 @@ package org.thingsboard.server.edqs.data.dp;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.thingsboard.server.common.data.edqs.DataPoint;
@RequiredArgsConstructor
@ -54,4 +55,9 @@ public abstract class AbstractDataPoint implements DataPoint {
return valueToString();
}
@Override
public int compareTo(DataPoint dataPoint) {
return StringUtils.compareIgnoreCase(valueToString(), dataPoint.valueToString());
}
}

5
common/edqs/src/main/java/org/thingsboard/server/edqs/data/dp/BoolDataPoint.java

@ -16,6 +16,7 @@
package org.thingsboard.server.edqs.data.dp;
import lombok.Getter;
import org.thingsboard.server.common.data.edqs.DataPoint;
import org.thingsboard.server.common.data.kv.DataType;
public class BoolDataPoint extends AbstractDataPoint {
@ -43,4 +44,8 @@ public class BoolDataPoint extends AbstractDataPoint {
return Boolean.toString(value);
}
@Override
public int compareTo(DataPoint dataPoint) {
return Boolean.compare(value, dataPoint.getBool());
}
}

5
common/edqs/src/main/java/org/thingsboard/server/edqs/data/dp/DoubleDataPoint.java

@ -16,6 +16,7 @@
package org.thingsboard.server.edqs.data.dp;
import lombok.Getter;
import org.thingsboard.server.common.data.edqs.DataPoint;
import org.thingsboard.server.common.data.kv.DataType;
public class DoubleDataPoint extends AbstractDataPoint {
@ -43,4 +44,8 @@ public class DoubleDataPoint extends AbstractDataPoint {
return Double.toString(value);
}
@Override
public int compareTo(DataPoint dataPoint) {
return Double.compare(value, dataPoint.getDouble());
}
}

6
common/edqs/src/main/java/org/thingsboard/server/edqs/data/dp/LongDataPoint.java

@ -16,6 +16,7 @@
package org.thingsboard.server.edqs.data.dp;
import lombok.Getter;
import org.thingsboard.server.common.data.edqs.DataPoint;
import org.thingsboard.server.common.data.kv.DataType;
public class LongDataPoint extends AbstractDataPoint {
@ -47,4 +48,9 @@ public class LongDataPoint extends AbstractDataPoint {
public String valueToString() {
return Long.toString(value);
}
@Override
public int compareTo(DataPoint dataPoint) {
return Long.compare(value, dataPoint.getLong());
}
}

35
common/edqs/src/main/java/org/thingsboard/server/edqs/processor/EdqsProcessor.java

@ -62,7 +62,6 @@ import org.thingsboard.server.queue.discovery.event.PartitionChangeEvent;
import org.thingsboard.server.queue.edqs.EdqsComponent;
import org.thingsboard.server.queue.edqs.EdqsConfig;
import org.thingsboard.server.queue.edqs.EdqsConfig.EdqsPartitioningStrategy;
import org.thingsboard.server.queue.edqs.EdqsQueue;
import org.thingsboard.server.queue.edqs.EdqsQueueFactory;
import org.thingsboard.server.queue.util.AfterStartUp;
@ -123,8 +122,8 @@ public class EdqsProcessor implements TbQueueHandler<TbProtoQueueMsg<ToEdqsMsg>,
};
eventConsumer = PartitionedQueueConsumerManager.<TbProtoQueueMsg<ToEdqsMsg>>create()
.queueKey(new QueueKey(ServiceType.EDQS, EdqsQueue.EVENTS.getTopic()))
.topic(EdqsQueue.EVENTS.getTopic())
.queueKey(new QueueKey(ServiceType.EDQS, config.getEventsTopic()))
.topic(config.getEventsTopic())
.pollInterval(config.getPollInterval())
.msgPackProcessor((msgs, consumer, config) -> {
for (TbProtoQueueMsg<ToEdqsMsg> queueMsg : msgs) {
@ -133,14 +132,14 @@ public class EdqsProcessor implements TbQueueHandler<TbProtoQueueMsg<ToEdqsMsg>,
}
try {
ToEdqsMsg msg = queueMsg.getValue();
process(msg, EdqsQueue.EVENTS);
process(msg, true);
} catch (Exception t) {
log.error("Failed to process message: {}", queueMsg, t);
}
}
consumer.commit();
})
.consumerCreator((config, partitionId) -> queueFactory.createEdqsMsgConsumer(EdqsQueue.EVENTS))
.consumerCreator((config, partitionId) -> queueFactory.createEdqsEventsConsumer())
.queueAdmin(queueFactory.getEdqsQueueAdmin())
.consumerExecutor(consumersExecutor)
.taskExecutor(taskExecutor)
@ -164,25 +163,27 @@ public class EdqsProcessor implements TbQueueHandler<TbProtoQueueMsg<ToEdqsMsg>,
}
try {
Set<TopicPartitionInfo> newPartitions = event.getNewPartitions().get(new QueueKey(ServiceType.EDQS));
Set<TopicPartitionInfo> partitions = newPartitions.stream()
.map(tpi -> tpi.withUseInternalPartition(true))
.collect(Collectors.toSet());
stateService.process(withTopic(partitions, EdqsQueue.STATE.getTopic()));
stateService.process(withTopic(newPartitions, config.getStateTopic()));
// eventsConsumer's partitions are updated by stateService
responseTemplate.subscribe(withTopic(partitions, config.getRequestsTopic())); // FIXME: we subscribe to partitions before we are ready. implement consumer-per-partition version for request template
responseTemplate.subscribe(withTopic(newPartitions, config.getRequestsTopic())); // TODO: we subscribe to partitions before we are ready. implement consumer-per-partition version for request template
Set<TopicPartitionInfo> oldPartitions = event.getOldPartitions().get(new QueueKey(ServiceType.EDQS));
if (CollectionsUtil.isNotEmpty(oldPartitions)) {
Set<Integer> removedPartitions = Sets.difference(oldPartitions, newPartitions).stream()
.map(tpi -> tpi.getPartition().orElse(-1)).collect(Collectors.toSet());
if (config.getPartitioningStrategy() != EdqsPartitioningStrategy.TENANT && !removedPartitions.isEmpty()) {
if (removedPartitions.isEmpty()) {
return;
}
if (config.getPartitioningStrategy() == EdqsPartitioningStrategy.TENANT) {
repository.clearIf(tenantId -> {
Integer partition = partitionService.resolvePartition(tenantId, null);
return removedPartitions.contains(partition);
});
} else {
log.warn("Partitions {} were removed but shouldn't be (due to NONE partitioning strategy)", removedPartitions);
}
repository.clearIf(tenantId -> {
Integer partition = partitionService.resolvePartition(tenantId);
return partition != null && removedPartitions.contains(partition);
});
}
} catch (Throwable t) {
log.error("Failed to handle partition change event {}", event, t);
@ -233,7 +234,7 @@ public class EdqsProcessor implements TbQueueHandler<TbProtoQueueMsg<ToEdqsMsg>,
return response;
}
public void process(ToEdqsMsg edqsMsg, EdqsQueue queue) {
public void process(ToEdqsMsg edqsMsg, boolean backup) {
log.trace("Processing message: {}", edqsMsg);
if (edqsMsg.hasEventMsg()) {
EdqsEventMsg eventMsg = edqsMsg.getEventMsg();
@ -250,7 +251,7 @@ public class EdqsProcessor implements TbQueueHandler<TbProtoQueueMsg<ToEdqsMsg>,
} else if (!ObjectType.unversionedTypes.contains(objectType)) {
log.warn("[{}] {} {} doesn't have version", tenantId, objectType, key);
}
if (queue != EdqsQueue.STATE) {
if (backup) {
stateService.save(tenantId, objectType, key, eventType, edqsMsg);
}

40
common/edqs/src/main/java/org/thingsboard/server/edqs/processor/EdqsProducer.java

@ -16,6 +16,7 @@
package org.thingsboard.server.edqs.processor;
import lombok.Builder;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.kafka.common.errors.RecordTooLargeException;
import org.thingsboard.server.common.data.ObjectType;
@ -27,60 +28,41 @@ import org.thingsboard.server.queue.TbQueueCallback;
import org.thingsboard.server.queue.TbQueueMsgMetadata;
import org.thingsboard.server.queue.TbQueueProducer;
import org.thingsboard.server.queue.common.TbProtoQueueMsg;
import org.thingsboard.server.queue.discovery.TopicService;
import org.thingsboard.server.queue.edqs.EdqsQueue;
import org.thingsboard.server.queue.kafka.TbKafkaProducerTemplate;
@Slf4j
@Builder
@RequiredArgsConstructor
public class EdqsProducer {
private final EdqsQueue queue;
private final EdqsPartitionService partitionService;
private final TopicService topicService;
private final TbQueueProducer<TbProtoQueueMsg<ToEdqsMsg>> producer;
@Builder
public EdqsProducer(EdqsQueue queue,
EdqsPartitionService partitionService,
TopicService topicService,
TbQueueProducer<TbProtoQueueMsg<ToEdqsMsg>> producer) {
this.queue = queue;
this.partitionService = partitionService;
this.topicService = topicService;
this.producer = producer;
}
private final EdqsPartitionService partitionService;
public void send(TenantId tenantId, ObjectType type, String key, ToEdqsMsg msg) {
String topic = topicService.buildTopicName(queue.getTopic());
TopicPartitionInfo tpi = TopicPartitionInfo.builder()
.topic(producer.getDefaultTopic())
.partition(partitionService.resolvePartition(tenantId, key))
.build();
TbQueueCallback callback = new TbQueueCallback() {
@Override
public void onSuccess(TbQueueMsgMetadata metadata) {
log.trace("[{}][{}][{}] Published msg to {}: {}", tenantId, type, key, topic, msg);
log.trace("[{}][{}][{}] Published msg to {}: {}", tenantId, type, key, tpi, msg);
}
@Override
public void onFailure(Throwable t) {
if (t instanceof RecordTooLargeException) {
if (!log.isDebugEnabled()) {
log.warn("[{}][{}][{}] Failed to publish msg to {}", tenantId, type, key, topic, t); // not logging the whole message
log.warn("[{}][{}][{}] Failed to publish msg to {}", tenantId, type, key, tpi, t); // not logging the whole message
return;
}
}
log.warn("[{}][{}][{}] Failed to publish msg to {}: {}", tenantId, type, key, topic, msg, t);
log.warn("[{}][{}][{}] Failed to publish msg to {}: {}", tenantId, type, key, tpi, msg, t);
}
};
if (producer instanceof TbKafkaProducerTemplate<TbProtoQueueMsg<ToEdqsMsg>> kafkaProducer) {
TopicPartitionInfo tpi = TopicPartitionInfo.builder()
.topic(topic)
.partition(partitionService.resolvePartition(tenantId))
.useInternalPartition(true)
.build();
kafkaProducer.send(tpi, key, new TbProtoQueueMsg<>(null, msg), callback); // specifying custom key for compaction
} else {
TopicPartitionInfo tpi = TopicPartitionInfo.builder()
.topic(topic)
.build();
producer.send(tpi, new TbProtoQueueMsg<>(null, msg), callback);
}
}

3
common/edqs/src/main/java/org/thingsboard/server/edqs/query/SortableEntityData.java

@ -16,6 +16,7 @@
package org.thingsboard.server.edqs.query;
import lombok.Data;
import org.thingsboard.server.common.data.edqs.DataPoint;
import org.thingsboard.server.common.data.id.EntityId;
import org.thingsboard.server.common.data.id.EntityIdFactory;
import org.thingsboard.server.edqs.data.EntityData;
@ -26,7 +27,7 @@ import java.util.UUID;
public class SortableEntityData {
private final EntityData entityData;
private String sortValue;
private DataPoint sortValue;
public UUID getId(){
return entityData.getId();

3
common/edqs/src/main/java/org/thingsboard/server/edqs/query/processor/AbstractQueryProcessor.java

@ -16,6 +16,7 @@
package org.thingsboard.server.edqs.query.processor;
import org.thingsboard.server.common.data.EntityType;
import org.thingsboard.server.common.data.edqs.DataPoint;
import org.thingsboard.server.common.data.permission.QueryContext;
import org.thingsboard.server.common.data.query.EntityFilter;
import org.thingsboard.server.edqs.data.EntityData;
@ -50,7 +51,7 @@ public abstract class AbstractQueryProcessor<T extends EntityFilter> implements
protected SortableEntityData toSortData(EntityData<?> ed) {
SortableEntityData sortData = new SortableEntityData(ed);
sortData.setSortValue(getSortValue(ed, sortKey));
sortData.setSortValue(getSortValue(ed, sortKey, ctx));
return sortData;
}

3
common/edqs/src/main/java/org/thingsboard/server/edqs/query/processor/AbstractRelationQueryProcessor.java

@ -34,6 +34,7 @@ import java.util.List;
import java.util.Queue;
import java.util.Set;
import java.util.UUID;
import java.util.stream.Collectors;
public abstract class AbstractRelationQueryProcessor<T extends EntityFilter> extends AbstractQueryProcessor<T> {
@ -89,7 +90,7 @@ public abstract class AbstractRelationQueryProcessor<T extends EntityFilter> ext
private List<SortableEntityData> processTenantQuery(Set<EntityData<?>> entities) {
return entities.stream()
.map(this::toSortData)
.toList();
.collect(Collectors.toList());
}
private List<SortableEntityData> processCustomerQuery(Set<EntityData<?>> entities) {

30
common/edqs/src/main/java/org/thingsboard/server/edqs/repo/TenantRepo.java

@ -150,8 +150,9 @@ public class TenantRepo {
}
} else if (RelationTypeGroup.DASHBOARD.equals(entity.getTypeGroup())) {
if (EntityRelation.CONTAINS_TYPE.equals(entity.getType()) && entity.getFrom().getEntityType() == EntityType.CUSTOMER) {
((CustomerData) getEntityMap(EntityType.CUSTOMER).computeIfAbsent(entity.getFrom().getId(), CustomerData::new))
.addOrUpdate(getEntityMap(EntityType.DASHBOARD).get(entity.getTo().getId()));
CustomerData customerData = (CustomerData) getOrCreate(entity.getFrom());
EntityData<?> dashboardData = getOrCreate(entity.getTo());
customerData.addOrUpdate(dashboardData);
}
}
} finally {
@ -170,8 +171,10 @@ public class TenantRepo {
}
} else if (RelationTypeGroup.DASHBOARD.equals(entityRelation.getTypeGroup())) {
if (EntityRelation.CONTAINS_TYPE.equals(entityRelation.getType()) && entityRelation.getFrom().getEntityType() == EntityType.CUSTOMER) {
((CustomerData) getEntityMap(EntityType.CUSTOMER).computeIfAbsent(entityRelation.getFrom().getId(), CustomerData::new))
.remove(getEntityMap(EntityType.DASHBOARD).get(entityRelation.getTo().getId()));
CustomerData customerData = (CustomerData) get(entityRelation.getFrom());
if (customerData != null) {
customerData.remove(EntityType.DASHBOARD, entityRelation.getTo().getId());
}
}
}
}
@ -197,13 +200,13 @@ public class TenantRepo {
entityData.setCustomerId(newCustomerId);
if (entityIdMismatch(oldCustomerId, newCustomerId)) {
if (oldCustomerId != null) {
CustomerData old = (CustomerData) getEntityMap(EntityType.CUSTOMER).get(oldCustomerId);
CustomerData old = (CustomerData) get(EntityType.CUSTOMER, oldCustomerId);
if (old != null) {
old.remove(entityData);
old.remove(entityType, entityId);
}
}
if (newCustomerId != null) {
CustomerData newData = (CustomerData) getEntityMap(EntityType.CUSTOMER).computeIfAbsent(newCustomerId, CustomerData::new);
CustomerData newData = (CustomerData) getOrCreate(EntityType.CUSTOMER, newCustomerId);
newData.addOrUpdate(entityData);
}
}
@ -223,11 +226,12 @@ public class TenantRepo {
getEntitySet(entityType).remove(removed);
}
edqsStatsService.ifPresent(statService -> statService.reportEvent(tenantId, ObjectType.fromEntityType(entityType), EdqsEventType.DELETED));
UUID customerId = removed.getCustomerId();
if (customerId != null) {
CustomerData customerData = (CustomerData) getEntityMap(EntityType.CUSTOMER).get(customerId);
CustomerData customerData = (CustomerData) get(EntityType.CUSTOMER, customerId);
if (customerData != null) {
customerData.remove(removed);
customerData.remove(entityType, entityId);
}
}
}
@ -303,7 +307,11 @@ public class TenantRepo {
}
private EntityData<?> get(EntityId entityId) {
return getEntityMap(entityId.getEntityType()).get(entityId.getId());
return get(entityId.getEntityType(), entityId.getId());
}
private EntityData<?> get(EntityType entityType, UUID entityId) {
return getEntityMap(entityType).get(entityId);
}
private EntityData<?> constructEntityData(EntityType entityType, UUID id) {
@ -425,7 +433,7 @@ public class TenantRepo {
EntityType entityType = entityId.getEntityType();
return switch (entityType) {
case CUSTOMER, TENANT -> {
EntityFields fields = getEntityMap(entityType).get(entityId.getId()).getFields();
EntityFields fields = get(entityId).getFields();
yield fields != null ? fields.getName() : "";
}
default -> throw new RuntimeException("Unsupported entity type: " + entityType);

7
common/edqs/src/main/java/org/thingsboard/server/edqs/state/EdqsPartitionService.java

@ -29,11 +29,14 @@ public class EdqsPartitionService {
private final HashPartitionService hashPartitionService;
private final EdqsConfig edqsConfig;
public Integer resolvePartition(TenantId tenantId) {
public Integer resolvePartition(TenantId tenantId, Object key) {
if (edqsConfig.getPartitioningStrategy() == EdqsPartitioningStrategy.TENANT) {
return hashPartitionService.resolvePartitionIndex(tenantId.getId(), edqsConfig.getPartitions());
} else {
return null;
if (key == null) {
throw new IllegalArgumentException("Partitioning key is missing but partitioning strategy is not TENANT");
}
return hashPartitionService.resolvePartitionIndex(key.toString(), edqsConfig.getPartitions());
}
}

60
common/edqs/src/main/java/org/thingsboard/server/edqs/state/KafkaEdqsStateService.java

@ -36,15 +36,19 @@ import org.thingsboard.server.queue.common.consumer.QueueConsumerManager;
import org.thingsboard.server.queue.common.state.KafkaQueueStateService;
import org.thingsboard.server.queue.common.state.QueueStateService;
import org.thingsboard.server.queue.discovery.QueueKey;
import org.thingsboard.server.queue.discovery.TopicService;
import org.thingsboard.server.queue.edqs.EdqsConfig;
import org.thingsboard.server.queue.edqs.EdqsQueue;
import org.thingsboard.server.queue.edqs.EdqsQueueFactory;
import org.thingsboard.server.queue.edqs.KafkaEdqsComponent;
import org.thingsboard.server.queue.edqs.KafkaEdqsQueueFactory;
import org.thingsboard.server.queue.kafka.TbKafkaAdmin;
import org.thingsboard.server.queue.kafka.TbKafkaConsumerTemplate;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
@Service
@RequiredArgsConstructor
@ -54,8 +58,7 @@ public class KafkaEdqsStateService implements EdqsStateService {
private final EdqsConfig config;
private final EdqsPartitionService partitionService;
private final EdqsQueueFactory queueFactory;
private final TopicService topicService;
private final KafkaEdqsQueueFactory queueFactory;
@Autowired @Lazy
private EdqsProcessor edqsProcessor;
@ -71,15 +74,16 @@ public class KafkaEdqsStateService implements EdqsStateService {
@Override
public void init(PartitionedQueueConsumerManager<TbProtoQueueMsg<ToEdqsMsg>> eventConsumer) {
TbKafkaAdmin queueAdmin = queueFactory.getEdqsQueueAdmin();
stateConsumer = PartitionedQueueConsumerManager.<TbProtoQueueMsg<ToEdqsMsg>>create()
.queueKey(new QueueKey(ServiceType.EDQS, EdqsQueue.STATE.getTopic()))
.topic(EdqsQueue.STATE.getTopic())
.queueKey(new QueueKey(ServiceType.EDQS, config.getStateTopic()))
.topic(config.getStateTopic())
.pollInterval(config.getPollInterval())
.msgPackProcessor((msgs, consumer, config) -> {
for (TbProtoQueueMsg<ToEdqsMsg> queueMsg : msgs) {
try {
ToEdqsMsg msg = queueMsg.getValue();
edqsProcessor.process(msg, EdqsQueue.STATE);
edqsProcessor.process(msg, false);
if (stateReadCount.incrementAndGet() % 100000 == 0) {
log.info("[state] Processed {} msgs", stateReadCount.get());
}
@ -89,15 +93,15 @@ public class KafkaEdqsStateService implements EdqsStateService {
}
consumer.commit();
})
.consumerCreator((config, partitionId) -> queueFactory.createEdqsMsgConsumer(EdqsQueue.STATE))
.queueAdmin(queueFactory.getEdqsQueueAdmin())
.consumerCreator((config, partitionId) -> queueFactory.createEdqsStateConsumer())
.queueAdmin(queueAdmin)
.consumerExecutor(eventConsumer.getConsumerExecutor())
.taskExecutor(eventConsumer.getTaskExecutor())
.scheduler(eventConsumer.getScheduler())
.uncaughtErrorHandler(edqsProcessor.getErrorHandler())
.build();
queueStateService = new KafkaQueueStateService<>(eventConsumer, stateConsumer);
TbKafkaConsumerTemplate<TbProtoQueueMsg<ToEdqsMsg>> eventsToBackupKafkaConsumer = queueFactory.createEdqsEventsToBackupConsumer();
eventsToBackupConsumer = QueueConsumerManager.<TbProtoQueueMsg<ToEdqsMsg>>builder()
.name("edqs-events-to-backup-consumer")
.pollInterval(config.getPollInterval())
@ -135,23 +139,47 @@ public class KafkaEdqsStateService implements EdqsStateService {
}
consumer.commit();
})
.consumerCreator(() -> queueFactory.createEdqsMsgConsumer(EdqsQueue.EVENTS, "events-to-backup-consumer-group")) // shared by all instances consumer group
.consumerCreator(() -> eventsToBackupKafkaConsumer)
.consumerExecutor(eventConsumer.getConsumerExecutor())
.threadPrefix("edqs-events-to-backup")
.build();
stateProducer = EdqsProducer.builder()
.queue(EdqsQueue.STATE)
.producer(queueFactory.createEdqsStateProducer())
.partitionService(partitionService)
.topicService(topicService)
.producer(queueFactory.createEdqsMsgProducer(EdqsQueue.STATE))
.build();
queueStateService = KafkaQueueStateService.<TbProtoQueueMsg<ToEdqsMsg>, TbProtoQueueMsg<ToEdqsMsg>>builder()
.eventConsumer(eventConsumer)
.stateConsumer(stateConsumer)
.eventsStartOffsetsProvider(() -> {
// taking start offsets for events topics from the events-to-backup consumer group,
// since eventConsumer doesn't use consumer group management and thus offset tracking
// (because we need to be able to consume the same topic-partition by multiple instances)
Map<String, Long> offsets = new HashMap<>();
try {
queueAdmin.getConsumerGroupOffsets(eventsToBackupKafkaConsumer.getGroupId())
.forEach((topicPartition, offsetAndMetadata) -> {
offsets.put(topicPartition.topic(), offsetAndMetadata.offset());
});
} catch (Exception e) {
log.error("Failed to get consumer group offsets for {}", eventsToBackupKafkaConsumer.getGroupId(), e);
}
return offsets;
})
.build();
}
@Override
public void process(Set<TopicPartitionInfo> partitions) {
if (queueStateService.getPartitions().isEmpty()) {
eventsToBackupConsumer.subscribe();
Set<TopicPartitionInfo> allPartitions = IntStream.range(0, config.getPartitions())
.mapToObj(partition -> TopicPartitionInfo.builder()
.topic(config.getEventsTopic())
.partition(partition)
.build())
.collect(Collectors.toSet());
eventsToBackupConsumer.subscribe(allPartitions);
eventsToBackupConsumer.launch();
}
queueStateService.update(new QueueKey(ServiceType.EDQS), partitions);

5
common/edqs/src/main/java/org/thingsboard/server/edqs/state/LocalEdqsStateService.java

@ -29,7 +29,6 @@ import org.thingsboard.server.edqs.util.EdqsRocksDb;
import org.thingsboard.server.gen.transport.TransportProtos.ToEdqsMsg;
import org.thingsboard.server.queue.common.TbProtoQueueMsg;
import org.thingsboard.server.queue.common.consumer.PartitionedQueueConsumerManager;
import org.thingsboard.server.queue.edqs.EdqsQueue;
import org.thingsboard.server.queue.edqs.InMemoryEdqsComponent;
import java.util.Set;
@ -61,14 +60,14 @@ public class LocalEdqsStateService implements EdqsStateService {
try {
ToEdqsMsg edqsMsg = ToEdqsMsg.parseFrom(value);
log.trace("[{}] Restored msg from RocksDB: {}", key, edqsMsg);
processor.process(edqsMsg, EdqsQueue.STATE);
processor.process(edqsMsg, false);
} catch (Exception e) {
log.error("[{}] Failed to restore value", key, e);
}
});
log.info("Restore completed");
}
eventConsumer.update(withTopic(partitions, EdqsQueue.EVENTS.getTopic()));
eventConsumer.update(withTopic(partitions, eventConsumer.getTopic()));
this.partitions = partitions;
}

21
common/edqs/src/main/java/org/thingsboard/server/edqs/util/RepositoryUtils.java

@ -67,10 +67,10 @@ import static org.thingsboard.server.common.data.query.ComplexFilterPredicate.Co
@Slf4j
public class RepositoryUtils {
public static final Comparator<SortableEntityData> SORT_ASC = Comparator.comparing((SortableEntityData sed) -> Optional.ofNullable(sed.getSortValue()).orElse(""), String.CASE_INSENSITIVE_ORDER)
public static final Comparator<SortableEntityData> SORT_ASC = Comparator.comparing(SortableEntityData::getSortValue, Comparator.nullsFirst(Comparator.naturalOrder()))
.thenComparing(sp -> sp.getId().toString());
public static final Comparator<SortableEntityData> SORT_DESC = Comparator.comparing((SortableEntityData sed) -> Optional.ofNullable(sed.getSortValue()).orElse(""), String.CASE_INSENSITIVE_ORDER)
public static final Comparator<SortableEntityData> SORT_DESC = Comparator.comparing(SortableEntityData::getSortValue, Comparator.nullsFirst(Comparator.naturalOrder()))
.thenComparing(sp -> sp.getId().toString()).reversed();
public static EntityType resolveEntityType(EntityFilter entityFilter) {
@ -348,24 +348,11 @@ public class RepositoryUtils {
}
}
public static String getSortValue(EntityData entity, DataKey sortKey) {
public static DataPoint getSortValue(EntityData entity, DataKey sortKey, QueryContext queryContext) {
if (sortKey == null) {
return null;
}
switch (sortKey.type()) {
case ENTITY_FIELD -> {
return entity.getField(sortKey.key());
}
case ATTRIBUTE, CLIENT_ATTRIBUTE, SHARED_ATTRIBUTE, SERVER_ATTRIBUTE -> {
var dp = entity.getAttr(sortKey.keyId(), sortKey.type());
return dp != null ? dp.valueToString() : "";
}
case TIME_SERIES -> {
var dp = entity.getTs(sortKey.keyId());
return dp != null ? dp.valueToString() : "";
}
default -> throw new IllegalStateException("toSortKey is not implemented for type: " + sortKey.type());
}
return entity.getDataPoint(sortKey, queryContext);
}
public static boolean checkFilters(EdqsQuery query, EntityData entity) {

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

Loading…
Cancel
Save