«Сфера»: як моніторити мільярди кіловат-годин



Є така електростанція — «Три ущелини». На неї витратили 10 років і $26 млрд. Під воду пішли два міста, переселили 1,3 млн осіб. Вона генерує 100 млрд кВт⋅год в рік, але це покриває… 1,7% потреб Китаю.

У світі є 192 атомні електростанції з 444 реакторами загальною електричною потужністю близько 386 276 МВт. (Потужність «Трьох ущелин» 22 500 МВт).

Коли я грав в C&C, RedAlert і Total Annihilation, було милим справою прорватися і знищити/захопити кілька ворожих електростанцій, тим самим загальмувати розвиток противника. Не дивно, що зараз енергетична інфраструктура є ласою мішенню для хакерів: «Злом електромережі: від окремої підстанції до блекауту», «Подробиці про безпрецедентний зломі електричної мережі України».

Хто і як пише софт для систем такого масштабу?

Розробники компанії EDISON розповіли, як вони писали систему моніторингу електромережі і візуалізації подій. У загальній складності на проект витрачено 14984 людино-години, з квітня 2010 по серпень 2011 року.


Введення

Енергетичний сектор забезпечує життєдіяльність всіх галузей народного господарства. Економічне зростання неминуче тягне за собою збільшення попиту на енергетичні ресурси і вимагає вирішення накопичених проблем старіння обладнання.

Для довгострокового стабільного забезпечення економіки та населення регіону енергоресурсами необхідна обґрунтована електроенергетична політика, заснована на проникливому контролі та моніторингу процесів в електромережах.

Збільшити відгук системи моніторингу електромережі на події, що відбуваються у вузлах мережі, і покликана програма «Сфера» — заміна застарілого ПО візуалізації подій. «Сфера» призначена для відображення схем електромереж на екрані з великою роздільною здатністю і розміром в центрі моніторингу електромереж. Важливим параметром який вимагався від програми була робота в режимі реального часу з локальним оновленням зображення в точці події. Для цього застосовувалася бібліотека WPF. Були розроблені інструменти для відображення і редагування елементів схеми також у реальному часі. Для управління подіями використовувався скриптова движок Pascal. Графічна частина розроблена на WPF/C#, логіка подій — через Delphi/ScriptPascal. Мова Delphi не вдалося уникнути з-за вимог зворотної сумісності з цілим рядом старих додатків.

Основні компоненти

Модульна архітектура
Підсистема Delphi.
  • БД графічного подання.
  • Модуль сценаріїв (скриптів).
Підсистема C#/WPF.
  • Візуалізація схеми графічного подання.
  • " Редагування схеми графічного подання.
Графічне ядро
Модуль графіки системи призначений для візуалізації схем, заснованих на даних CIM-моделі. Відображення розрахункових величин і даних телеметрії — як реального часу, так і на заданий час. Графіка використовує для візуалізації високопродуктивну бібліотеку Windows Presentation Foundation (WPF), яка може виконувати рендеринг як програмно, так і використовуючи апаратне прискорення сучасних відеокарт.

Схеми графіки автоматично оновлюють дані при зміні даних у CIM-моделі. Графічне представлення може настроюватися з використанням скриптової мови, що дозволяє гнучко реалізувати бізнес-логіку. Скриптові сценарії проводять розрахунки і можуть повністю визначати поведінку об'єктів графічного подання.

Зовнішній вид візуального представлення подібний графу, вершинами якого є вузли та об'єкти-обладнання, а ребрами — гілки та об'єкти-зв'язку. Крім вузлів і гілок на візуальному представленні розташовані блоки виведення даних, які відображають деякі значення сховища, і графічні примітиви для оформлення схеми.

Вузли можуть бути представлені у вигляді:
  • круга;
  • горизонтальній шини;
  • вертикальної шини.
На сайті розташовані точки приєднання, які використовуються для приєднання додаткового устаткування і вузлів. Вони розташовані по периметру вузла з певним кроком, який можна настроювати. Підключення додаткового обладнання контролюється сценаріями, які з настроюваної логіці включають або вимикають відображення знаків додаткового обладнання:
  • генератор;
  • синхронний компенсатор;
  • навантаження;
  • реактор;
  • батарея статичних конденсаторів;
  • активний шунт.
Гілки з'єднують між собою вузли. Гілка зображується ламаною лінією, кінці якої приєднані до точок підключення вузла початку і кінця. Суцільною лінією відображається включена гілку, пунктирною — відключена. На гілки може розташовуватися знак, відображення якого контролюється сценаріями:
  • трансформатор;
  • пристрій поздовжньої компенсації;
  • кабельна лінія;
  • струмообмежувальних реакторів;
  • комутаційний апарат.
Відображення знака і стану лінії залежить від параметрів суті, з якою пов'язана гілку.

Подання містить безліч шарів, і будь-який об'єкт подання може бути віднесений до одного або кількох шарів. Якщо хоча б один з шарів, до яких віднесено об'єкт, включений, то об'єкт бачимо. Якщо об'єкт не належить ні до одного шару, то він завжди видно.

Вузли в поданні можна об'єднувати в групи для заміни при певному масштабі на зображення групи. Наприклад, вузли, що входять до складу підстанції, можна об'єднати в групу «підстанція», а підстанції об'єднати в групу «станція». Налаштувавши різні масштаби заміни відображення сайтів на групу, можна домогтися, що при наближенні (збільшення масштабу зображення станції деталізується до зображень підстанцій, при подальшому наближенні будуть показані індивідуальні вузли підстанцій.

Об'єкти-обладнання та об'єкти-зв'язки об'єднують вузли і гілки. Як і у випадку з групами, переміщення об'єктів призводить до переміщення входять до складу гілок і вузлів.

Для відображення карт місцевості або іншої графічної інформації графічне представлення дозволяє відображати растрові та векторні зображення. Зображення завжди відображаються під об'єктами.

На графічному рівні WPF робота йшла з такими елементами як Visual, DrawingVisual, Drawing, XAML, для роботи з великими обсягами графічних примітивів використовувалося квадродерево, що оптимізувало VisualCollection і Canvas-об'єкти.

Додаткової оптимізацією графіки, в якій використовувалося квадродерево був режим, який сам по собі не властивий системі WPF, але був доданий нами через функції WinApi. Цей режим використовував функції WinApi, які виконували переміщення видимого на екрані фрагмента зображення попіксельно в залежності від напрямку скролінгу, при цьому WPF залишалося оновити лише невеликий фрагмент, який залишався після зсуву зображення. Тут включалося квадродерево і передавало движок WPF, що працює з VisualCollection і getVisualChild, тільки набір об'єктів, що входять в область оновлення. Коли програма запускається в центрі моніторингу на великому моніторі, складеному з безлічі звичайних моніторів (близько 20-30 штук), то при відображенні подій використання квадродерева істотно знімало навантаження з WPF і забезпечувало високу продуктивність графіки.

Труднощі, з якими зіткнулися при розробці, і оптимізація

Оптимізація хіт-тесту
При роботі з хіт тестом в системі WPF були виявлені проблеми продуктивності для деяких типів примітивів. Вирішено було замінити відображений тип на еквівалентний, але не має цих проблем при операції хіт-тесту.

Так як ми управляємо хіт-тестом в обхід перебору об'єктів системою WPF, то в обробники потрапляння ми власними силами передаємо інформацію про реальний візуальному елемент, для якого виконується хіт-тест, а не про те елементі який повертає WPF. В головній функції обробки хіт-тесту він був нами оптимізовано під використання квадродерева. Система хіт-тесту в WPF реалізована не досить ефективно і не досить гнучко для наших завдань. Таким чином, щоб реалізувати оптимізацію під квадродерево, довелося імітувати хіт-тест «мікро-подання для кожного об'єкта окремо за допомогою винесення вектора переміщення і матриці трансформації об'єктів Drawing в об'єкти DrawingVisual.

Всередині самої функції хіт-тесту наступний алгоритм.

  1. Робимо регіон у вигляді дуже короткої лінії і перевіряємо її на перетин.
  2. Створюємо заглушку «мікро-представлення» — аналог Canvas.
  3. Спеціальний візуальний елемент поміщається на «мікро-подання» та інкапсулює векторну графіку з кожного візуального елемента по черзі.
  4. Передаємо інформацію про трансформації в візуальний елемент призначення з вихідного і скасовуємо відповідну трансформацію векторної графіки.
    var t = VisualTreeHelper.GetTransform(v);
    var o = VisualTreeHelper.GetOffset(v);
    destVisual.Transform = t;
    destVisual.Offset = o;
    if (drw.IsFrozen)
    drw = (DrawingGroup)drw.Clone();
    drw.Transform = Transform.Identity;
  5. Особливим чином формуємо елемент для хіт-тесту перетікання потужності, який при своєму рендерінгу готує набір візуальних елементів, коректно для хіт-тесту замінюють низькорівневі операції трансформації.
  6. Відновлюємо трансформацію векторної графіки. Операція скасування відновлення трансформації пов'язана з некоректною роботою системи хіт-тесту з трансформацією всередині Drawing об'єктів, у той час як рендеринг у битмапку, конвертування в EMF і т. д. вимагає складання векторної графіки на низькому рівні (Drawing) з урахуванням трансформації візуальних елементів переданих всередину цієї графіки.
Оптимізація візуалізації векторних об'єктів
За замовчуванням WPF використовує векторну модель промальовування всіх об'єктів, що знижувало продуктивність. Для виправлення була реалізована система кешей битмапов поверх векторних об'єктів Visual. Кеші перемальовувалися при зміні масштабу або оновлення контенту кэшированых Visual.

Система кешування побудована таким чином, що на кожен візуальний елемент типу Visual доводилося створювати окремий битмап об'єкт через взаємодію з ОС Windows і отримання хэндла на битмап, а так як кількість доступних хэндлов для процесу обмежена, то необхідно було враховувати ці ліміти. Відповідно в разі, якщо в кадрі було видно велику кількість об'єктів, то при перевищенні цього ліміту доводилося залишати частину об'єктів без кешей, але такі випадки бувають не часто, і частина закэшированых зображень яка працювала все одно досить добре, підвищувала продуктивність. Для розрахунку лімітів використовується наступний підхід.
RegistryKey hklm = Registry.LocalMachine;
hklm = hklm.OpenSubKey("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Windows");
GDIResourcesMax = (int)hklm.GetValue("GDIProcessHandleQuota");
double GDIUsageLimit = 0.7;
double GDISafeResourcesLimit = GDIUsageLimit * GDIResourcesMax;
public static int GetGuiResourcesGDICount()
{
return GetGuiResources(Process.GetCurrentProcess().Handle, 0);
}


  • GDIUsageLimit — коефіцієнт, який показує скільки хэндлов ми можемо безпечно зарезервувати для нормальної роботи;
  • GDISafeResourcesLimit — відповідно, кількість об'єктів з урахуванням коефіцієнта;
  • GetGuiResourcesGDICount — функція, що дозволяє визначити скільки виділено хендлов поточним процесом.


На основі даних параметрів при старті програми відбувалася резервація хендлов битмапок в масив, з якого вони надалі витягувалися системою кешування по мірі необхідності.

Кожен битмап-об'єкт резервується таким кодом:
var bm = new BitmapCacheBrush();
bitmapCacheFree.Add(bm);


База даних

Файл графічного подання являє собою бекап бази даних Firebird і зберігає інформацію про спосіб візуалізації графа. Візуальне подання створюється користувачем і знаходиться у файлі з розширенням “*.GVIEW". Файл може містити декілька схем-уявлень.

Основною таблицею є BASE_ENTITY, в ній зберігаються всі основні властивості об'єктів подання. Для кожного конкретного типу є таблиця, в якій зберігаються інші поля. Наприклад, для вузлів це BUS_ENTITY, для гілок — BRANCH_ENTITY. Ці деталізують таблиці мають зв'язок один до одного з таблицею BASE_ENTITY. Цілісність даних в основному контролюється посилальною цілісністю між таблицями. Наприклад, видалення подання з таблиці Gview автоматично видаляє всі належні їй об'єкти з таблиці BASE_ENTITY, а потім каскадно видаляються деталізації з таблиць конкретних типів.

Шаблони блоків мають структуру, схожу з уявленнями, зберігаються також в таблиці GView з встановленим прапором HIDDEN. У файлі не зберігаються внутрішні об'єкти блоків, вони повністю конструюються при створенні на основі шаблонів. Тому налаштування внутрішніх об'єктів блоку, зроблені сценаріями, губляться при збереженні і завантаженні.

Сценарії

Сценарії (скрипти) керують знаками обладнання та іншими елементами схеми в залежності від подій, що надходять від реального обладнання в центр моніторингу. В залежності від подій скрипти керують видимістю, ефектом мерехтіння, кольоровою підсвіткою, виведенням даних в елементи додаткової інформації, які якорями прив'язані до знаків обладнання, видимістю груп, окремих елементів і т. д.

Сценарії необхідні для тонкого налаштування візуалізації CIM-об'єктів і для обчислення даних, відображуваних полями і блоками виводу. Модуль скриптів дозволяє в режимі реального часу робити довільні обчислення над об'єктами графічного представлення та пов'язаними з ними сутностями, на підставі отриманих даних управляти зовнішнім виглядом і виводити розрахункові дані і дані телеметрії.

Завдяки скриптам можна по-різному візуалізувати різні атрибути об'єкта графічного подання, такі як текст, шрифт, колір, розмір і кут нахилу, довільно керувати видимістю уявлень.

Перед приміщенням об'єкта на графічне представлення або при зміні властивостей сутності, пов'язаної з об'єктом, модуль скриптів викликає скрипт і передає в нього контекст об'єкта і його оточення. Суть сценарію полягає в установці видимості, настроювання властивостей об'єкта, переданого в обробку або розрахунку даних, що виводяться для об'єкта. Наприклад, на підставі достовірності даних можна змінити колір об'єкта чи визначити, які додаткові поля повинні бути показані, а потім приховати або показати прив'язані до об'єкту поля або блоки даних.

Виконання скриптів
Виконання сценаріїв відбувається в контексті головного потоку програми.

В цілях поліпшення продуктивності застосовується «ледаче» виконання, тобто виконання сценарію, завжди відкладається до моменту, коли його дані дійсно потрібні. Наприклад, виконання скриптів, які використовуються для отримання тексту та інших параметрів полів висновку, відкладається до моменту візуалізації. Це означає, що якщо подання прив'язане до невидимого шару, або значення масштабу невидимості не дозволяє його побачити, то й скрипт, який обчислює полі, не буде виконуватися до тих пір, поки уявлення не стане видимим.

При зміні даних суті відбувається автоматичне оновлення всіх уявлень, прив'язаних до нього, для цього повторно виконуються скрипти, які залежать від даних суті. Тобто якщо в скрипті відбувається звернення до контекстної змінної Entity, то вважається, що скрипт залежить від сутності, і він буде перерахований.

На дії користувача по кліку або подвійному кліку відповідні сценарії з поточного профілю скриптів запускаються негайно.
В процесі виконання скрипта можуть відбуватися помилкові ситуації, що призводять до викиду винятків. Необроблені виняткові ситуації відображаються модулем нотифікації у вигляді спливаючих повідомлень, а також зберігаються в локальний каталог користувача.

Загальні модулі
Загальні модулі призначені для визначення коду програмних модулів, багаторазово використовуваних скриптами графічного подання.

У секції «Модулі» діалогового вікна «Загальні модулі скриптів» можна додати, змінити або видалити модулі скриптів, натиснувши відповідні кнопки. При визначенні загального модуля необхідно вказати його ім'я, за яким він буде доступний зі скрипта. У правій частині діалогового вікна, в секції «Модуль», з допомогою редактора скриптів задається початковий код модуля. Створені модулі можна багаторазово використовувати при визначенні коду різних скриптів.

Для використання коду загальних модулів в скриптах слід скористатися наступною формою запису скрипта, і в заголовку скрипта з допомогою визначення uses перерахувати через кому плагіни.

{$MANUAL}
// Підключення загальних модулів
uses 'common', 'math';
// Визначення функції скрипта
function __f__: Variant;
begin
// Виклик функції A() модуля 'common'
Result := A();
end;

Begin
end.

Профілі скриптів
Профілі скриптів дозволяють створювати кілька наборів скриптів, що викликаються при виникненні наступних подій графічного подання:
  • зміна даних суті;
  • одинарний або подвійний клік миші по зображенню;
  • зміна масштабу графічного подання.
При зміні даних сутностей проводиться оновлення тексту полів виводу і блоків, прив'язаних до цих сутностей. Для цього виконуються скрипти, які містяться в полях виведення даних, які обчислюють виведений текст і задають форматування.

При одинарному або подвійному кліку миші по зображенню може бути корисним вивести будь-якої спливаючий діалог, що містить деталізацію виділеного графічного об'єкту.

При зміні масштабу графічного подання може бути корисним трохи збільшити або зменшити масштаб об'єктів графічного подання, або приховати зайві об'єкти, щоб не захаращувати ними екран.

Суть профілів сценаріїв подання полягає в наданні можливості по-різному обробити перераховані вище події, залежно від обраного профілю. Так можна створити профілі, які будуть налаштовувати кольору об'єктів по-різному або по-різному будуть розраховувати виводяться дані. У стрічковому меню графічного подання користувач може вибрати активний профіль скриптів, від якого буде залежати поточне поведінку графічного подання. При зміні профілю всі сутності графічного подання обробляються скриптом «Зміна суті»; якщо сценарій складний, і об'єктів багато, то це може зайняти деякий час.

Вибрати активний профіль скриптів можна за допомогою випадаючого списку.

Профіль скриптів в стрічковому меню.
Щоб додати новий профіль скриптів, потрібно натиснути кнопку «Додати», розташовану під списком профілів діалогового вікна «Налаштування профілів сценаріїв», і вказати ім'я та опис профілю. Після чого, за допомогою редактора скриптів можна ввести код профілю у вкладках:
  • зміна даних суті;
  • клацання миші;
  • подвійне клацання миші;
  • зміна масштабу.


Додаткові функції програми



" Редагування гілок і примітивів
Функція редагування гілок включає можливість створення вузлів зламу на гілки і видалення вузлів. Також підтримується ортогональний режим, в якому гілки відповідно вирівняні по осях координат під прямими кутами. Підтримується функціонал інтегрування знаків обладнання на гілку і переміщення їх уздовж гілки.
При редагуванні примітивів можна намалювати довільні елементи, такі як ламані поли-лінії, кола, сектори, текстові блоки і т. д.



Робота зі знаками обладнання
У роботу зі знаками обладнання у разі розміщення на гілки входить функція відображення знака на гілки відносно осі гілки. Можливість зміни знака обладнання і зміни скрипта керуючого знаком. Як для звичайних знаків, так і для знаків на гілки доступні функції прив'язки якорем додаткових елементів управління, які можуть управлятися скриптом і відображати додаткову інформацію.

Групи об'єктів
Об'єкти можна групувати і управляти видимістю груп з скриптів. Зовнішній вид груп визначається специфікацією CIM-моделей. Групи можуть бути вкладеними один в одного і автоматично розширюватися в залежності від видимих/невидимих вкладених підгруп.



Блок виведення даних

Вкладка «Блок виведення даних» дозволяє налаштувати конкретний екземпляр блоку виводу даних, його положення, ім'я блоку для використання в скриптах, координати щодо об'єкта, до якого прив'язаний блок виводу.

Форма редагування блоку


Приклад виводу блоків на схемі


Використання шарів
Механізм шарів дозволяє виконувати оптимізацію кількості видимих об'єктів у залежності від масштабу, або від логіки скриптів, або налаштовуватися в ручну.

Копіювання в буфер
Буфер обміну є мильтиформатным і підтримує копіювання як у векторному форматі даних, так і в растровому.

Друк
Доступні функції як кольорового друку, так і чорно-белойЧ. Роздрукувати можна будь-яку довільну область схеми.

Експорт у різні формати
Доступний експорт в різних форматах як растрових, так і векторних (WMF, EMF, SVG).

Пошук
Функція дозволяє за фрагментом тексту знайти місце розташування об'єктів на схемі, з автоматичним позиціонуванням області перегляду.

Навігатор
Вікно навігатора дозволяє бачити начерк всієї схеми цілком у спрощеному вигляді з відображенням поточної області перегляду.



Обладнання, на якому працював софт

Відеокарта була спеціалізована, яка видавала дозвіл 8192x2048, у неї не було ніяких прискорень, вона підтримувала всі тільки програмно, щоб тягнути велике дозвіл на екрані у центрі моніторингу.

Об'єктів у кадрі близько 100 тисяч.

FPS в районі 1.

Опис установки в центрі управління.

Великий екран у центрі керування складається з 24 секцій, 8 завширшки і 3 у висоту. Кожна секція — це окремий маленький екран дозволом 1024х1024 пікселів. 24 проектора встановлені з зворотного боку, кожен світить на свій квадрат.

Відео-фрагмент масштабування електросхеми на екрані




Більше проектів:
SDK для підтримки впровадження електронних книг у форматі FB2
Як за 5233 людино-години створити софт для микротомографа
Управління доступом до електронних документів. Від DefView до Vivaldi
Розробка простого плагіна для JIRA для роботи з базою даних
На допомогу DevOps: складальник прошивок для мережевих пристроїв на Debian за 1008 годин
Автооновлення служби Windows через AWS для бідних

Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.