@ -3,6 +3,7 @@
"description": "Cross connector",
"widgetSizeX": 1,
"widgetSizeY": 1,
"stateRenderFunction": "const {\n flowAnimationWidth: lineWidth,\n flowAnimationColor: lineColor,\n flowStyleDash: dashWidth,\n flowStyleGap: dashGap,\n flowDashCap: dashCap\n} = ctx.properties;\n\nconst leftLine = \"M0 100H100\";\nconst topLine = \"M100 97L100 0\";\nconst rightLine = \"M100 100H200\";\nconst bottomLine = \"M 100,200 V 103\";\n\nprepareFlowAnimation('left', leftLine);\nprepareFlowAnimation('top', topLine);\nprepareFlowAnimation('right', rightLine);\nprepareFlowAnimation('bottom', bottomLine);\n\nfunction prepareFlowAnimation(prefix, line) {\n const flowAnimation = ctx.values[prefix + 'Flow'];\n const flowDirection = ctx.values[prefix + 'FlowDirection'];\n const flowAnimationSpeed = ctx.values[prefix + 'FlowAnimationSpeed'];\n\n const animation = ctx.tags[prefix + 'Line'][0];\n const offset = Date.now() % 1000;\n const duration = 1 / flowAnimationSpeed;\n \n const prevFlowAnimation = animation.remember('flowAnimation');\n const prevFlowDirection = animation.remember('flowDirection');\n const prevFlowDuration = animation.remember('flowDuration');\n \n if (flowAnimation & & flowAnimation !== prevFlowAnimation) {\n animation.remember('flowAnimation', flowAnimation);\n animation.remember('flowDuration', duration);\n animation.remember('flowDirection', flowDirection);\n animateFlow(animation, offset, flowDirection, duration, line);\n } else if (flowAnimation & & flowDirection !== prevFlowDirection) {\n animation.remember('flowDirection', flowDirection);\n animateFlow(animation, offset, flowDirection, duration, line);\n } else if (flowAnimation & & duration !== prevFlowDuration) {\n animation.remember('flowDuration', duration);\n animation.findOne('animate').attr('dur', `${duration}s`) ;\n } else if (!flowAnimation & & prevFlowAnimation) {\n animation.remember('flowAnimation', null);\n animation.clear();\n }\n}\n\nfunction animateFlow(group, offset, flowDirection, duration, line) {\n group.clear();\n const dashArray = `${dashWidth}${dashGap ? ` ${dashGap}` : ''}`;\n const value = flowDirection ? `${dashWidth + (dashGap || dashWidth)}` : `-${dashWidth + (dashGap || dashWidth)}`;\n\n group.add(`<path style= \"stroke-dasharray: $ { d a s h A r r a y } ; s t r o k e - l i n e c a p : $ { d a s h C a p } ; s t r o k e - d a s h o f f s e t : 0 ; \ " d= \"${line}\" stroke-miterlimit= \"10\" fill= \"none\" stroke= \"${lineColor}\" stroke-width= \"${lineWidth}\" > <animate attributeName= \"stroke-dashoffset\" values= \"${value};0\" dur= \"${duration}s\" begin= \"-${offset}ms\" calcMode= \"linear\" repeatCount= \"indefinite\" /> </path> `);\n}",
"tags": [
{
"tag": "line",
@ -15,23 +16,480 @@
"actions": null
}
],
"behavior": [],
"behavior": [
{
"id": "leftFlow",
"name": "{i18n:scada.symbol.flow-animation}",
"hint": "{i18n:scada.symbol.flow-animation-hint}",
"group": "{i18n:scada.symbol.left-connector}",
"type": "value",
"valueType": "BOOLEAN",
"trueLabel": "{i18n:scada.symbol.present}",
"falseLabel": "{i18n:scada.symbol.absent}",
"stateLabel": "{i18n:scada.symbol.flow-present}",
"defaultGetValueSettings": {
"action": "DO_NOTHING",
"defaultValue": false,
"executeRpc": {
"method": "getState",
"requestTimeout": 5000,
"requestPersistent": false,
"persistentPollingInterval": 1000
},
"getAttribute": {
"key": "state",
"scope": null
},
"getTimeSeries": {
"key": "state"
},
"getAlarmStatus": {
"severityList": null,
"typeList": null
},
"dataToValue": {
"type": "NONE",
"compareToValue": true,
"dataToValueFunction": "/* Should return boolean value */\nreturn data;"
}
},
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": null
},
{
"id": "leftFlowDirection",
"name": "{i18n:scada.symbol.animation-direction}",
"hint": "{i18n:scada.symbol.animation-direction-hint}",
"group": "{i18n:scada.symbol.left-connector}",
"type": "value",
"valueType": "BOOLEAN",
"trueLabel": "{i18n:scada.symbol.forward}",
"falseLabel": "{i18n:scada.symbol.reverse}",
"stateLabel": "{i18n:scada.symbol.forward}",
"defaultGetValueSettings": {
"action": "DO_NOTHING",
"defaultValue": true,
"executeRpc": {
"method": "getState",
"requestTimeout": 5000,
"requestPersistent": false,
"persistentPollingInterval": 1000
},
"getAttribute": {
"scope": null,
"key": "state"
},
"getTimeSeries": {
"key": "state"
},
"getAlarmStatus": {
"severityList": null,
"typeList": null
},
"dataToValue": {
"type": "NONE",
"dataToValueFunction": "/* Should return boolean value */\nreturn data;",
"compareToValue": true
}
},
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": null
},
{
"id": "leftFlowAnimationSpeed",
"name": "{i18n:scada.symbol.flow-animation-speed}",
"hint": "{i18n:scada.symbol.flow-animation-speed-hint}",
"group": "{i18n:scada.symbol.left-connector}",
"type": "value",
"valueType": "DOUBLE",
"trueLabel": null,
"falseLabel": null,
"stateLabel": null,
"defaultGetValueSettings": {
"action": "DO_NOTHING",
"defaultValue": 1,
"executeRpc": {
"method": "getState",
"requestTimeout": 5000,
"requestPersistent": false,
"persistentPollingInterval": 1000
},
"getAttribute": {
"scope": null,
"key": "state"
},
"getTimeSeries": {
"key": "state"
},
"getAlarmStatus": {
"severityList": null,
"typeList": null
},
"dataToValue": {
"type": "NONE",
"dataToValueFunction": "/* Should return boolean value */\nreturn data;"
}
},
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": null
},
{
"id": "topFlow",
"name": "{i18n:scada.symbol.flow-animation}",
"hint": "{i18n:scada.symbol.flow-animation-hint}",
"group": "{i18n:scada.symbol.top-connector}",
"type": "value",
"valueType": "BOOLEAN",
"trueLabel": "{i18n:scada.symbol.present}",
"falseLabel": "{i18n:scada.symbol.absent}",
"stateLabel": "{i18n:scada.symbol.fluid-present}",
"defaultGetValueSettings": {
"action": "DO_NOTHING",
"defaultValue": false,
"executeRpc": {
"method": "getState",
"requestTimeout": 5000,
"requestPersistent": false,
"persistentPollingInterval": 1000
},
"getAttribute": {
"key": "state",
"scope": null
},
"getTimeSeries": {
"key": "state"
},
"getAlarmStatus": {
"severityList": null,
"typeList": null
},
"dataToValue": {
"type": "NONE",
"compareToValue": true,
"dataToValueFunction": "/* Should return boolean value */\nreturn data;"
}
},
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": null
},
{
"id": "topFlowDirection",
"name": "{i18n:scada.symbol.animation-direction}",
"hint": "{i18n:scada.symbol.animation-direction-hint}",
"group": "{i18n:scada.symbol.top-connector}",
"type": "value",
"valueType": "BOOLEAN",
"trueLabel": "{i18n:scada.symbol.forward}",
"falseLabel": "{i18n:scada.symbol.reverse}",
"stateLabel": "{i18n:scada.symbol.forward}",
"defaultGetValueSettings": {
"action": "DO_NOTHING",
"defaultValue": true,
"executeRpc": {
"method": "getState",
"requestTimeout": 5000,
"requestPersistent": false,
"persistentPollingInterval": 1000
},
"getAttribute": {
"scope": null,
"key": "state"
},
"getTimeSeries": {
"key": "state"
},
"getAlarmStatus": {
"severityList": null,
"typeList": null
},
"dataToValue": {
"type": "NONE",
"dataToValueFunction": "/* Should return boolean value */\nreturn data;",
"compareToValue": true
}
},
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": null
},
{
"id": "topFlowAnimationSpeed",
"name": "{i18n:scada.symbol.flow-animation-speed}",
"hint": "{i18n:scada.symbol.flow-animation-speed-hint}",
"group": "{i18n:scada.symbol.top-connector}",
"type": "value",
"valueType": "DOUBLE",
"trueLabel": null,
"falseLabel": null,
"stateLabel": null,
"defaultGetValueSettings": {
"action": "DO_NOTHING",
"defaultValue": 1,
"executeRpc": {
"method": "getState",
"requestTimeout": 5000,
"requestPersistent": false,
"persistentPollingInterval": 1000
},
"getAttribute": {
"scope": null,
"key": "state"
},
"getTimeSeries": {
"key": "state"
},
"getAlarmStatus": {
"severityList": null,
"typeList": null
},
"dataToValue": {
"type": "NONE",
"dataToValueFunction": "/* Should return boolean value */\nreturn data;"
}
},
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": null
},
{
"id": "rightFlow",
"name": "{i18n:scada.symbol.flow-animation}",
"hint": "{i18n:scada.symbol.flow-animation-hint}",
"group": "{i18n:scada.symbol.right-connector}",
"type": "value",
"valueType": "BOOLEAN",
"trueLabel": "{i18n:scada.symbol.present}",
"falseLabel": "{i18n:scada.symbol.absent}",
"stateLabel": "{i18n:scada.symbol.flow-present}",
"defaultGetValueSettings": {
"action": "DO_NOTHING",
"defaultValue": false,
"executeRpc": {
"method": "getState",
"requestTimeout": 5000,
"requestPersistent": false,
"persistentPollingInterval": 1000
},
"getAttribute": {
"key": "state",
"scope": null
},
"getTimeSeries": {
"key": "state"
},
"getAlarmStatus": {
"severityList": null,
"typeList": null
},
"dataToValue": {
"type": "NONE",
"compareToValue": true,
"dataToValueFunction": "/* Should return boolean value */\nreturn data;"
}
},
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": null
},
{
"id": "rightFlowDirection",
"name": "{i18n:scada.symbol.flow-direction}",
"hint": "{i18n:scada.symbol.flow-direction-hint}",
"group": "{i18n:scada.symbol.right-connector}",
"type": "value",
"valueType": "BOOLEAN",
"trueLabel": "{i18n:scada.symbol.forward}",
"falseLabel": "{i18n:scada.symbol.reverse}",
"stateLabel": "{i18n:scada.symbol.forward}",
"defaultGetValueSettings": {
"action": "DO_NOTHING",
"defaultValue": true,
"executeRpc": {
"method": "getState",
"requestTimeout": 5000,
"requestPersistent": false,
"persistentPollingInterval": 1000
},
"getAttribute": {
"scope": null,
"key": "state"
},
"getTimeSeries": {
"key": "state"
},
"getAlarmStatus": {
"severityList": null,
"typeList": null
},
"dataToValue": {
"type": "NONE",
"dataToValueFunction": "/* Should return boolean value */\nreturn data;",
"compareToValue": true
}
},
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": null
},
{
"id": "rightFlowAnimationSpeed",
"name": "{i18n:scada.symbol.flow-animation-speed}",
"hint": "{i18n:scada.symbol.flow-animation-speed-hint}",
"group": "{i18n:scada.symbol.right-connector}",
"type": "value",
"valueType": "DOUBLE",
"trueLabel": null,
"falseLabel": null,
"stateLabel": null,
"defaultGetValueSettings": {
"action": "DO_NOTHING",
"defaultValue": 1,
"executeRpc": {
"method": "getState",
"requestTimeout": 5000,
"requestPersistent": false,
"persistentPollingInterval": 1000
},
"getAttribute": {
"scope": null,
"key": "state"
},
"getTimeSeries": {
"key": "state"
},
"getAlarmStatus": {
"severityList": null,
"typeList": null
},
"dataToValue": {
"type": "NONE",
"dataToValueFunction": "/* Should return boolean value */\nreturn data;"
}
},
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": null
},
{
"id": "bottomFlow",
"name": "{i18n:scada.symbol.flow-animation}",
"hint": "{i18n:scada.symbol.flow-animation-hint}",
"group": "{i18n:scada.symbol.bottom-connector}",
"type": "value",
"valueType": "BOOLEAN",
"trueLabel": "{i18n:scada.symbol.present}",
"falseLabel": "{i18n:scada.symbol.absent}",
"stateLabel": "{i18n:scada.symbol.flow-present}",
"defaultGetValueSettings": {
"action": "DO_NOTHING",
"defaultValue": false,
"executeRpc": {
"method": "getState",
"requestTimeout": 5000,
"requestPersistent": false,
"persistentPollingInterval": 1000
},
"getAttribute": {
"key": "state",
"scope": null
},
"getTimeSeries": {
"key": "state"
},
"getAlarmStatus": {
"severityList": null,
"typeList": null
},
"dataToValue": {
"type": "NONE",
"compareToValue": true,
"dataToValueFunction": "/* Should return boolean value */\nreturn data;"
}
},
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": null
},
{
"id": "bottomFlowDirection",
"name": "{i18n:scada.symbol.animation-direction}",
"hint": "{i18n:scada.symbol.animation-direction-hint}",
"group": "{i18n:scada.symbol.bottom-connector}",
"type": "value",
"valueType": "BOOLEAN",
"trueLabel": "{i18n:scada.symbol.forward}",
"falseLabel": "{i18n:scada.symbol.reverse}",
"stateLabel": "{i18n:scada.symbol.forward}",
"defaultGetValueSettings": {
"action": "DO_NOTHING",
"defaultValue": true,
"executeRpc": {
"method": "getState",
"requestTimeout": 5000,
"requestPersistent": false,
"persistentPollingInterval": 1000
},
"getAttribute": {
"scope": null,
"key": "state"
},
"getTimeSeries": {
"key": "state"
},
"getAlarmStatus": {
"severityList": null,
"typeList": null
},
"dataToValue": {
"type": "NONE",
"dataToValueFunction": "/* Should return boolean value */\nreturn data;",
"compareToValue": true
}
},
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": null
},
{
"id": "bottomFlowAnimationSpeed",
"name": "{i18n:scada.symbol.flow-animation-speed}",
"hint": "{i18n:scada.symbol.flow-animation-speed-hint}",
"group": "{i18n:scada.symbol.bottom-connector}",
"type": "value",
"valueType": "DOUBLE",
"trueLabel": null,
"falseLabel": null,
"stateLabel": null,
"defaultGetValueSettings": {
"action": "DO_NOTHING",
"defaultValue": 1,
"executeRpc": {
"method": "getState",
"requestTimeout": 5000,
"requestPersistent": false,
"persistentPollingInterval": 1000
},
"getAttribute": {
"scope": null,
"key": "state"
},
"getTimeSeries": {
"key": "state"
},
"getAlarmStatus": {
"severityList": null,
"typeList": null
},
"dataToValue": {
"type": "NONE",
"dataToValueFunction": "/* Should return boolean value */\nreturn data;"
}
},
"defaultSetValueSettings": null,
"defaultWidgetActionSettings": null
}
],
"properties": [
{
"id": "mainLine",
"name": "{i18n:scada.symbol.main-line}",
"type": "switch",
"default": true,
"required": null,
"subLabel": null,
"divider": null,
"fieldSuffix": null,
"disableOnProperty": null,
"rowClass": "",
"fieldClass": "",
"min": null,
"max": null,
"step": null
"disabled": false,
"visible": true
},
{
"id": "mainLineSize",
@ -42,12 +500,11 @@
"subLabel": "Main",
"divider": true,
"fieldSuffix": "px",
"disableOnProperty": null,
"rowClass": "",
"fieldClass": "",
"min": 0,
"max": 99,
"step": 1
"step": 1,
"disabled": false,
"visible": true
},
{
"id": "secondaryLineSize",
@ -56,32 +513,95 @@
"default": 2,
"required": true,
"subLabel": "Secondary",
"divider": null,
"fieldSuffix": "px",
"disableOnProperty": null,
"rowClass": "",
"fieldClass": "",
"min": 0,
"max": 99,
"step": 1
"step": 1,
"disabled": false,
"visible": true
},
{
"id": "lineColor",
"name": "{i18n:scada.symbol.line-color}",
"type": "color",
"default": "#1A1A1A",
"required": null,
"subLabel": null,
"divider": null,
"fieldSuffix": null,
"disableOnProperty": null,
"rowClass": "",
"fieldClass": "",
"min": null,
"max": null,
"step": null
"disabled": false,
"visible": true
},
{
"id": "flowAnimationWidth",
"name": "{i18n:scada.symbol.flow}",
"group": "{i18n:scada.symbol.animation}",
"type": "number",
"default": 4,
"subLabel": "Width",
"fieldSuffix": "px",
"min": 1,
"step": 1,
"disabled": false,
"visible": true
},
{
"id": "flowAnimationColor",
"name": "{i18n:scada.symbol.flow}",
"group": "{i18n:scada.symbol.animation}",
"type": "color",
"default": "#C8DFF7",
"disabled": false,
"visible": true
},
{
"id": "flowStyleDash",
"name": "{i18n:scada.symbol.flow-style}",
"group": "{i18n:scada.symbol.animation}",
"type": "number",
"default": 10,
"required": true,
"subLabel": "{i18n:scada.symbol.dash}",
"divider": true,
"fieldSuffix": "px",
"min": 0,
"step": 1,
"disabled": false,
"visible": true
},
{
"id": "flowStyleGap",
"name": "{i18n:scada.symbol.flow-style}",
"group": "{i18n:scada.symbol.animation}",
"type": "number",
"default": 10,
"subLabel": "{i18n:scada.symbol.gap}",
"fieldSuffix": "px",
"min": 1,
"step": 1,
"disabled": false,
"visible": true
},
{
"id": "flowDashCap",
"name": "{i18n:scada.symbol.flow-dash-cap}",
"group": "{i18n:scada.symbol.animation}",
"type": "select",
"default": "butt",
"items": [
{
"value": "butt",
"label": "{i18n:scada.symbol.dash-cap-butt}"
},
{
"value": "round",
"label": "{i18n:scada.symbol.dash-cap-round}"
},
{
"value": "square",
"label": "{i18n:scada.symbol.dash-cap-square}"
}
],
"disabled": false,
"visible": true
}
]
}]]></tb:metadata>
<path d= "M87 100H113C113 100 100 100 100 86C100 100 87 100 87 100Z" id= "path12" fill= "#1A1A1A" tb:tag= "line-color" /> <path d= "M87 100H113C113 100 100 100 100 114C100 100 87 100 87 100Z" id= "path10" fill= "#1A1A1A" tb:tag= "line-color" /> <path d= "M0 100H85C93.2843 100 100 93.2843 100 85V0" stroke-width= "6" id= "path8" stroke= "#1A1A1A" tb:tag= "line" /> <path d= "M200 100H115C106.716 100 100 93.2843 100 85V0" stroke-width= "6" id= "path6" stroke= "#1A1A1A" tb:tag= "line" /> <path d= "M0 100H85C93.2843 100 100 106.716 100 115V200" stroke-width= "6" id= "path4" stroke= "#1A1A1A" tb:tag= "line" /> <path d= "M200 100H115C106.716 100 100 106.716 100 115V200" stroke-width= "6" id= "path2" stroke= "#1A1A1A" tb:tag= "line" />
<path d= "M87 100H113C113 100 100 100 100 86C100 100 87 100 87 100Z" id= "path12" fill= "#1A1A1A" tb:tag= "line-color" /> <path d= "M87 100H113C113 100 100 100 100 114C100 100 87 100 87 100Z" id= "path10" fill= "#1A1A1A" tb:tag= "line-color" /> <path d= "M0 100H85C93.2843 100 100 93.2843 100 85V0" stroke-width= "6" id= "path8" stroke= "#1A1A1A" tb:tag= "line" /> <path d= "M200 100H115C106.716 100 100 93.2843 100 85V0" stroke-width= "6" id= "path6" stroke= "#1A1A1A" tb:tag= "line" /> <path d= "M0 100H85C93.2843 100 100 106.716 100 115V200" stroke-width= "6" id= "path4" stroke= "#1A1A1A" tb:tag= "line" /> <path d= "M200 100H115C106.716 100 100 106.716 100 115V200" stroke-width= "6" id= "path2" stroke= "#1A1A1A" tb:tag= "line" /> <g tb:tag= "animationGroup" > <g tb:tag= "leftLine" /> <g tb:tag= "topLine" /> <g tb:tag= "rightLine" /> <g tb:tag= "bottomLine" /> </g>
</svg>