Как работает оживление мнемосхем в SoloScada

Нарисуем простую схему в редакторе, потом рассмотрим, что получилось и как это работает.

Мощность и ток будут привязаны к переменным P_10_111 и I_10_111 соответственно. Включенное состояние выключателя привязано к красному прямоугольнику (он спрятан под зеленый прямоугольник), отключенное к зеленому.



Сохраним схему, перезапустим сервис, откроем в браузере 127.0.0.1, получим следующее:

Нажмем Сtrl+u в браузере, увидим исходный код страницы (непривязанные линии опущены):

<!DOCTYPE html>
<html ng-app="countryApp">
<head>
 <meta name="Content-Type" content="text/html; charset=utf-8">
 <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
 <title>SoloSCADA Пример мнемосхемы</title>
 <link rel="stylesheet" href="./css/jquery-ui.css">
  <script src="./js/jquery.js"></script>
  <script src="./js/jquery-ui.js"></script>
 <script src="/js/angular.min.js"></script>
 <script src="/js/scada.js"></script>
<script>
  var countryApp = angular.module('countryApp', []);
  countryApp.controller('CountryCtrl', function ($scope, $http, $interval){
    $http.get('all.json').success(function(data) {
      $scope.val = data.val;
    });
$interval(function(){
    $http.get('all.json').success(function(data) {
      $scope.val = data.val;
	    $( "#label_err" ).text( "" );
    }).error(function(data, status) {
	    console.error('Error occurred:', data, status);
	    $( "#label_err" ).text( 'Нет связи с сервером!' );
	});
},1000);
  });
  countryApp.filter('format_off', function(){
  return function(text){
    if(text.indexOf("0")===0){
      return "1";
    }
    else{
      return "0";
    }
  } 
});
countryApp.filter('format_on', function(){
  return function(text){
    if(text.indexOf("1")===0){
      return "1";
    }
    else{
     return "0";
    }
  }
});
   </script>
</head>
<body ng-controller="CountryCtrl">
<div id="dialog-confirm" title="Выберите действие">
 <label id="label2">444VG</label>
</div>
<p>
  <button type="button" class="ui-button ui-widget ui-corner-all" onClick="javascript:window.
location='index.html'"
>
Главная</button> <button type="button" class="ui-button ui-widget ui-corner-all" onClick="javascript:window.
location='ps10.html'"
>
10 кВ</button> <button type="button" class="ui-button ui-widget ui-corner-all" onClick="javascript:window.
location='name_3.html'"
>
Пример мнемосхемы</button> <label id="label_err"></label> </p> <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1"
viewBox="0 0 930 504" xml:space="preserve">
<desc>Created with Fabric.js 1.7.3</desc> <defs> </defs> <g transform="translate(260.61 175.8) matrix(1 0 0 1 0 0) "> <text font-family="helvetica" font-size="20" font-weight="normal" style="stroke:
none; stroke-width: 1; stroke-dasharray: none; stroke-linecap: butt; stroke-linejoin: miter;
 stroke-miterlimit: 10; fill: rgb(1,1,1); fill-rule: nonzero; opacity: 1;"
>
<tspan x="-50.88" y="6.3" fill="rgb(1,1,1)">Мощность:</tspan> </text> </g> <g transform="translate(293.54 208.8) matrix(1 0 0 1 0 0) "> <text font-family="helvetica" font-size="20" font-weight="normal" style="stroke:
 none; stroke-width: 1; stroke-dasharray: none; stroke-linecap: butt; stroke-linejoin: miter;
stroke-miterlimit: 10; fill: rgb(1,1,1); fill-rule: nonzero; opacity: 1;"
>
<tspan x="-18.04" y="6.3" fill="rgb(1,1,1)">Ток:</tspan> </text> </g> <rect id="V_10_111_on" x="-25" y="-25" rx="0" ry="0" width="50" height="50" style=" cursor:pointer;
 stroke: none; stroke-width: 1; stroke-dasharray: none; stroke-linecap: butt; stroke-linejoin: miter;
 stroke-miterlimit: 10; fill: rgb(255,0,0); fill-rule: nonzero; opacity:
{{val.V_10_111 | format_on}};"
transform="translate(94.34 185.86) scale(0.94 0.94) matrix(1 0 0 1 0 0) " onclick="tmcontrol('V_10_111',
'В-10-111')"
title="Управление В-10-111"/>
<g id="P_10_111" transform="translate(397.54 177.8) matrix(1 0 0 1 0 0) "> <text font-family="helvetica" font-size="20" font-weight="normal" style="stroke: none;
stroke-width: 1; stroke-dasharray: none; stroke-linecap: butt; stroke-linejoin: miter; stroke-miterlimit:
 10; fill: rgb(1,1,1); fill-rule: nonzero; opacity: 1;"
>
<tspan x="-73.04" y="6.3" fill="rgb(1,1,1)">
{{val.P_10_111}}</tspan> </text> </g> <g id="I_10_111" transform="translate(393.65 208.8) matrix(1 0 0 1 0 0) "> <text font-family="helvetica" font-size="20" font-weight="normal" style="stroke: none;
 stroke-width: 1; stroke-dasharray: none; stroke-linecap: butt; stroke-linejoin: miter; stroke-miterlimit:
10; fill: rgb(1,1,1); fill-rule: nonzero; opacity: 1;"
>
<tspan x="-69.15" y="6.3" fill="rgb(1,1,1)">
{{val.I_10_111}}</tspan> </text> </g> <rect id="V_10_111_off" x="-25" y="-25" rx="0" ry="0" width="50" height="50" style=" cursor:pointer;
 stroke: none; stroke-width: 1; stroke-dasharray: none; stroke-linecap: butt; stroke-linejoin: miter;
stroke-miterlimit: 10; fill: rgb(0,191,95); fill-rule: nonzero; opacity:
{{val.V_10_111 | format_off}};"
transform="translate(94.28 185.78) scale(0.94 0.94) matrix(1 0 0 1 0 0) " onclick="tmcontrol('V_10_111',
'В-10-111')"
title="Управление В-10-111"/>
</svg> </body> </html>
 

Разберем по порядку:

подключаем jquery:

<script src="./js/jquery.js"></script> 

подключаем jquery-ui для диалога включить/отключить:

<script src="./js/jquery-ui.js"></script>

подключаем angularjs:

<script src="/js/angular.min.js"></script>

подключаем вспомогательный скрипт.

<script src="/js/scada.js"></script> 

Далее создаём контроллер. Значения переменных берем из файла all.json, его мы запрашиваем с сервера при загрузке страницы и с периодичностью раз в секунду с помощью

$interval(function(){  },1000);

Если файл all.json запрошен успешно, выполняется:

$http.get('all.json').success(function(data) {
      $scope.val = data.val;
	    $( "#label_err" ).text( "" );
    }).

Обновляем данные. Если не успешно, вверху выводим сообщение Нет связи с сервером! на label_err.

.error(function(data, status) {
	    console.error('Error occurred:', data, status);
	    $( "#label_err" ).text( 'Нет связи с сервером!' );
	});

Json-файл должен быть такого формата:

{
    "val":{
        "V_10_111": "0",
        "I_10_111": "55.88",
        "P_10_111": "9.11"
        }
}

SVG-файл встраиваем непосредственно в тело страницы:

<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" 
viewBox="0 0 930 504" xml:space="preserve"> </svg>

В текстовое поле выводим значение переменной I_10_111 так:

	<g id="I_10_111" transform="translate(393.65 208.8) matrix(1 0 0 1 0 0) ">
		<text font-family="helvetica" font-size="20" font-weight="normal" style="stroke: none;
 stroke-width: 1; stroke-dasharray: none; stroke-linecap: butt; stroke-linejoin: miter; stroke-miterlimit: 10;
 fill: rgb(1,1,1); fill-rule: nonzero; opacity: 1;"
>
<tspan x="-69.15" y="6.3" fill="rgb(1,1,1)">{{val.I_10_111}}</tspan> </text> </g>

Главное здесь это запись {{val.I_10_111}}. Angularjs сам ищет такие записи и заменяет их на значение I_10_111. Включенное состояние отображаем красным прямоугольником:

Включенное состояние

<rect id="V_10_111_on" x="-25" y="-25" rx="0" ry="0" width="50" height="50" style=" cursor:pointer; 
stroke: none; stroke-width: 1; stroke-dasharray: none; stroke-linecap: butt; stroke-linejoin: miter;
 stroke-miterlimit: 10; fill: rgb(255,0,0); fill-rule: nonzero; opacity:{{val.V_10_111 | format_on}};"

transform="translate(94.34 185.86) scale(0.94 0.94) matrix(1 0 0 1 0 0) " onclick="tmcontrol('V_10_111',
'В-10-111')"
title="Управление В-10-111"/>

Свойство opacity зависит от переменной V_10_111 с примененным фильтром format_on. Когда значение равно 1, прямоугольник виден (opacity: 1). Когда значение равно 0, прямоугольник невиден (opacity: 0). Когда состояние неопределённо (это передаётся знаками вопросов в Json-файле «V_10_111»: "??") применение фильтра format_on даёт 0, т.е. прямоугольник невиден. Отключенное состояние отображаем зеленым прямоугольником:

Отключенное состояние

<rect id="V_10_111_off" x="-25" y="-25" rx="0" ry="0" width="50" height="50" style=" cursor:pointer;
 stroke: none; stroke-width: 1; stroke-dasharray: none; stroke-linecap: butt; stroke-linejoin: miter;
stroke-miterlimit: 10; fill: rgb(0,191,95); fill-rule: nonzero; opacity:{{val.V_10_111 | format_off}};"

 transform="translate(94.28 185.78) scale(0.94 0.94) matrix(1 0 0 1 0 0) " onclick="tmcontrol('V_10_111',
'В-10-111')"
title="Управление В-10-111"/>

Свойство opacity зависит от переменной V_10_111 с примененным фильтром format_off. Когда значение переменной равно 0, прямоугольник виден (opacity: 1). Когда значение равно 1, прямоугольник невиден (opacity: 0). При клике мышкой на прямоугольнике запускается скрипт tmcontrol('V_10_111','В-10-111'). Он описан в файле scada.js.

function tmcontrol(perem,rusname) {
elem = perem;
$( "#label2" ).text( rusname );
dialog.dialog( "open" );
};
$( "#label2" ).text( rusname ); — текстовая метка на диалоге отображает название элемента, над которым выполняется команда.
dialog.dialog( "open" ); — показываем диалоговое окно.

Функция диалогового окна:

$( function() {
   dialog =  $( "#dialog-confirm" ).dialog({
      autoOpen: false,
      resizable: false,
      height: "auto",
      width: 400,
      modal: true,
      buttons: {
        "Включить": function() {
          $.post("control.php", elem+'&1');
          $( this ).dialog( "close" );
        },
        "Отключить": function() {
          $.post("control.php", elem+'&0');
          $( this ).dialog( "close" );
        },
        "Отмена": function() {
          $( this ).dialog( "close" );
        }
      }
    });
    $( "#create-user" ).button().on( "click", function() {
      dialog.dialog( "open" );
    });
  } );

Для окна используется библиотека jquery-ui. Команду включить передаём на сервер методом post:

$.post("control.php", elem+'&1');

Команда отключить:

$.post("control.php", elem+'&0');

Диалоговое окно подключаем в html-файле: