Инструменты пользователя

Инструменты сайта


mikrotik:rb951ui-2nd:routeros:system:scripts:ups-monitiring

Скрипт для мониторинга и управления ИБП на MikroTik

Попал ко мне с оказией старенький, но рабочий UPS. Долго думал, как его поудачней применить?! В итоге спрятал его в кладовке, а на него повесил роутер, подъездную камеру, видеофон и кучу прочей мелочи. Удобно, оказывается, когда у всех нет света, а у тебя звонок работает. 8-)

Описание работы

Скрипт периодические запускается планировщиком и следит за состоянием подключенного по USB ИБП и при изменении состояний отправляет уведомления на почту.

:!: Для работы скрипта, нужен пакет «UPS», устанавливаемый отдельно.

Комментарии к коду

Серийный номер должен соответствовать подключенному ИБП, т.к. по нему определяется конкретный экземпляр.

:local upsSerial XXXXXXXXXXXX;
:local adminMail "email@address.zone";

Настройка периодичности отправки сообщений об отсутствии связи, об ошибках диагностики и сообщений периодической диагностики.

Cчитается, исходя из периодичности запуска – если скрипт запускается каждые 30 секунд, то для задержки в 1 час нужно установить 60*60*2-1=7199. Я запускаю скрипт каждые 5 минут, т.е. 300 секунд.

:local commErrPer "5";
:local diagErrPer "2";
:local diagWeekPer "865";

Текстовые строки писем.

:local commErrMsg "Ошибка связи с UPS ($upsSerial)!";
:local commOkMsg "Соединение с UPS ($upsSerial) восстановлено!";
:local diagErrMsg "Диагностические сведения вернули ошибку!";
:local diagWeekMsg "Периодическое информационное письмо!";
:local powerFailMsg "Сбой питания!";
:local powerOkMsg "Питание восстановлено!";
:local batteryFull "Батарея достаточно заряжена.";

Пороги отправки сообщений о сбое питания в %.

:local powerLvl1 50;
:local powerLvl2 25;

Порог в %, после которого батарея считается заряженной полностью.

:local battFullLvl 95;

Инициализация переменных.

:local upsNumber;
:local upsName;

Инициализация глобального счетчика.

:global upsCounters;
:if ( [ :typeof $upsCounters ] = "nothing" ) do={ :set upsCounters [ :toarray "" ]; }

Функция сбора диагностики. Понятия не имею, как это работает, но это работает! Подсмотрено тут.

:local upsDiagData do={
  :local diagData [ :toarray "" ];

  /system ups {
    monitor $upsNumber once do={
      :set ( $diagData -> "runtimeLeft" ) $"runtime-left";
      :set ( $diagData -> "batteryCharge" ) $"battery-charge";
      :set ( $diagData -> "batteryVoltage" ) $"battery-voltage";
      :set ( $diagData -> "lineVoltage" ) $"line-voltage";
      :set ( $diagData -> "upsLoad" ) $"load";
      :set ( $diagData -> "replaceBattery" ) $"replace-battery";
      :set ( $diagData -> "upsOverload" ) $"overload";
#      :set ( $diagData -> "lowBattery" ) $"low-battery";
      :set ( $diagData -> "hidSelfTest" ) $"hid-self-test";
    }
  }

  :return $diagData;
}

Функция счетчика.

:local sendCounter do={

  :global upsCounters;
  :local sendLabel;

  :if ( [ :typeof ( $upsCounters -> "$counterLabel" ) ]  = "nothing" || $resetCounter = true ) do={
    :set ( $upsCounters -> "$counterLabel" ) $counterLimit;
  }

  :if ( ( $upsCounters -> "$counterLabel" ) = $counterLimit ) do={
    :set sendLabel true;

    :if ( $resetCounter != true ) do={
      :set ( $upsCounters -> "$counterLabel" ) 0;
    }
    } else={
      :set sendLabel false;
      :set ( $upsCounters -> "$counterLabel" ) ( ( $upsCounters -> "$counterLabel" ) + 1 );
    }

  :return $sendLabel;
}

Функция отправки писем.

:local sendMail do={
  :local errorTxt "Function \"sendMail\" could not send message!";
  :local subjTxt "Оповещение системы мониторинга UPS";

  :local monthToNum;
  :local dateToPick;
  :local dateToLog;
  :local timeToLog;

  :set monthToNum {jan="01";feb="02";mar="03";apr="04";may="05";jun="06";jul="07";aug="08";sep="09";oct="10";nov="11";dec="12";};
  :set dateToPick [/system clock get date];
  :set dateToLog ( [:pick $dateToPick 4 6] . "." . ( $monthToNum -> [:pick $dateToPick 0 3] ) . "." . [:pick $dateToPick 7 11] );
  :set timeToLog [/system clock get time];

  :set subjTxt "$subjTxt @ $dateToLog $timeToLog";

  :do { /tool e-mail send to=$mailTo subject=$subjTxt body=$msg; } on-error={ :log error ("$errorTxt"); }
}

Получение серийного номера и модели UPS.

/system ups {
  :set upsNumber [ find serial=$upsSerial ];
  :set upsName [ get $upsNumber model ];

Проверка коммуникации с UPS.

  :if ( [ :typeof $upsName ] = "nil" ) do={
    :log error ("UPS communication error!");

    :if ( [ $sendCounter counterLabel=commFail counterLimit=$commErrPer ] = true ) do={
      $sendMail mailTo=$adminMail msg=$commErrMsg;
    }

  :if ( ( $upsCounters -> "commErrFlg" ) != true ) do={ :set ( $upsCounters -> "commErrFlg" ) true; }

  :error "UPS communication error. Exit!";
  } else={
    :if ( ( $upsCounters -> "commErrFlg" ) = true ) do={
      $sendCounter counterLabel=commFail counterLimit=$commErrPer resetCounter=true;
      $sendMail mailTo=$adminMail msg=$commOkMsg;
      :set ( $upsCounters -> "commErrFlg" ) false;
      :log warning ("communication with UPS restored!");
    }
  }

Сбор данных диагностики.

  :local currDiagData [ $upsDiagData upsNumber=$upsNumber; ];

Подготовка данных диагностики.

  :local runtimeLeft ( [ :pick ( $currDiagData -> "runtimeLeft" ) 0 2 ] . "h" . [ :pick ( $currDiagData -> "runtimeLeft" ) 3 5 ] . "m" );
  :local batteryCharge ( $currDiagData -> "batteryCharge" );
  :local batteryVoltage ( [ :pick ( $currDiagData -> "batteryVoltage" ) 0 2 ] . "." . [ :pick ( $currDiagData -> "batteryVoltage" ) 2 4 ] . "V" );
  :local lineVoltage ( [ :pick ( $currDiagData -> "lineVoltage" ) 0 3 ] . "V" );
  :local upsLoad ( $currDiagData -> "upsLoad" );
  :local replaceBattery ( $currDiagData -> "replaceBattery" );
  :local upsOverload ( $currDiagData -> "upsOverload" );
  :local hidSelfTest ( $currDiagData -> "hidSelfTest" );

Проверка наличия питания.

  :if ( [ get $upsNumber on-line ] = true ) do={

Проверка уровня заряда АКБ.

    :if ( ( $upsCounters -> "batteryUsed" ) != true && ( $currDiagData -> "batteryCharge" ) < $battFullLvl ) do={
      :set ( $upsCounters -> "batteryUsed" ) true;
    }

Отправка письма о достаточном заряде АКБ.

    :if ( ( $upsCounters -> "batteryUsed" ) = true && ( $currDiagData -> "batteryCharge" ) >= $battFullLvl ) do={
      :set batteryFull "$batteryFull\r\n\r\nRuntime Left: $runtimeLeft\r\nBattery Charge: $batteryCharge%\r\nBattery Voltage: $batteryVoltage\r\nLoad: $upsLoad%\r\n\r\n$upsName (SN: $upsSerial)";
      $sendMail mailTo=$adminMail msg=$batteryFull;
      :set ( $upsCounters -> "batteryUsed" ) false;
    }

Отправка письма о восстановлении энергоснабжения.

    :if ( ( $upsCounters -> "powerFailFlg" ) = true ) do={
      :set powerOkMsg "$powerOkMsg\r\n\r\nRuntime Left: $runtimeLeft\r\nBattery Charge: $batteryCharge%\r\nBattery Voltage: $batteryVoltage\r\nLoad: $upsLoad%\r\n\r\n$upsName (SN: $upsSerial)";
      $sendMail mailTo=$adminMail msg=$powerOkMsg;
      :set ( $upsCounters -> "powerFailFlg" ) false;
      :set ( $upsCounters -> "powerFailSnd" ) false;
      :log warning ("power restored!");
      :error "UPS Power Ok. Exit!";
    }

Проверка нагрузки и состояния АКБ, отправка сообщения.

    :if ( ( $currDiagData -> "replaceBattery" ) = true || ( $currDiagData -> "upsOverload" ) = true ) do={
      :if ( [ $sendCounter counterLabel=diagFail counterLimit=$diagErrPer ] = true ) do={
        :set diagErrMsg "$diagErrMsg\r\n\r\nReplace Battery: $replaceBattery\r\nOverload: $upsOverload (Load: $upsLoad%)\r\n\r\n$upsName (SN: $upsSerial)";
        $sendMail mailTo=$adminMail msg=$diagErrMsg;
      }
      :error "Diagnostic error. Exit!";
    }

Отправка периодической диагностики.

  :if ( [ $sendCounter counterLabel=diagWeek counterLimit=$diagWeekPer ] = true ) do={
    :set diagWeekMsg "$diagWeekMsg\r\n\r\nRuntime Left: $runtimeLeft\r\nBattery Charge: $batteryCharge%\r\nBattery Voltage: $batteryVoltage\r\nLine Voltage: $lineVoltage\r\nLoad: $upsLoad%\r\n\r\nReplace Battery: $replaceBattery\r\nOverload: $upsOverload\r\nHID Self Test: $hidSelfTest\r\n\r\n$upsName (SN: $upsSerial)";
    $sendMail mailTo=$adminMail msg=$diagWeekMsg;
  }

Действия при работе от батарей.

  } else={

Установка метки работы от батарей.

    :set ( $upsCounters -> "batteryUsed" ) true;

Подготовка сообщения о сбое питания.

    :set powerFailMsg "$powerFailMsg\r\n\r\nRuntime Left: $runtimeLeft\r\nBattery Charge: $batteryCharge%\r\nBattery Voltage: $batteryVoltage\r\nLoad: $upsLoad%\r\n\r\n$upsName (SN: $upsSerial)";

Отправка первого сообщения.

    :if ( ( ( $upsCounters -> "powerFailFlg" ) = false && ( $upsCounters -> "powerFailSnd" ) = false ) || [ :typeof ( $upsCounters -> "powerFailFlg" ) ]  = "nothing"  ) do={
      $sendMail mailTo=$adminMail msg=$powerFailMsg;
      :set ( $upsCounters -> "powerFailFlg" ) true;
      :set ( $upsCounters -> "powerFailSnd" ) true;
      :log error ("power lost!");
      :error "First message sent. Exit!";
    }

Отправка второго сообщения при пересечении первого порога.

    :if ( ( $upsCounters -> "powerFailFlg" ) = true && ( $upsCounters -> "powerFailSnd" ) = true && $batteryCharge <= $powerLvl1 ) do={
      $sendMail mailTo=$adminMail msg=$powerFailMsg;
      :set ( $upsCounters -> "powerFailSnd" ) false;
      :error "Second message sent. Exit!";
    }

Отправка третьего сообщения при пересечении второго порога.

    :if ( ( $upsCounters -> "powerFailFlg" ) = true && ( $upsCounters -> "powerFailSnd" ) = false && $batteryCharge <= $powerLvl2 ) do={
      $sendMail mailTo=$adminMail msg=$powerFailMsg;
      :set ( $upsCounters -> "powerFailSnd" ) last;
      :error "Third message sent. Exit!";
    }
  }
}

Код для импорта

ups-monitiring.rsc
/system script
add comment="\CC\EE\ED\E8\F2\EE\F0\E8\ED\E3 UPS" dont-require-permissions=no \
    name=ups-monitiring owner=vasya policy=read,write,policy,test source="# Wr\
    itten by Nikolay Soloshin (nikolay@soloshin.su) for RouterOS v6.47.8 on hA\
    P (mipsbe) @ 2020.12\r\
    \n# Tested with APC Back-UPS RS 1000 FW:7.g9a.I USB FW:g9a (BR1000I)\r\
    \n\r\
    \n# \D1\E5\F0\E8\E9\ED\FB\E9 \ED\EE\EC\E5\F0 UPS \E8 \E0\E4\F0\E5\F1 \E4\
    \EB\FF \F3\E2\E5\E4\EE\EC\EB\E5\ED\E8\E9\r\
    \n:local upsSerial XXXXXXXXXXXX;\r\
    \n:local adminMail \"email@address.zone\";\r\
    \n\r\
    \n# \CF\E5\F0\E8\EE\E4\E8\F7\ED\EE\F1\F2\FC \EE\F2\EF\F0\E0\E2\EA\E8 \F1\
    \EE\EE\E1\F9\E5\ED\E8\E9 \EE\E1 \EE\F2\F1\F3\F2\F1\F2\E2\E8\E8 \F1\E2\FF\
    \E7\E8 \F1 UPS\r\
    \n:local commErrPer \"5\";\r\
    \n# \CF\E5\F0\E8\EE\E4\E8\F7\ED\EE\F1\F2\FC \EE\F2\EF\F0\E0\E2\EA\E8 \F1\
    \EE\EE\E1\F9\E5\ED\E8\E9 \EE\E1 \EE\F8\E8\E1\EA\E0\F5 \E4\E8\E0\E3\ED\EE\
    \F1\F2\E8\EA\E8\r\
    \n:local diagErrPer \"2\";\r\
    \n# \CF\E5\F0\E8\EE\E4\E8\F7\ED\EE\F1\F2\FC \EE\F2\EF\F0\E0\E2\EA\E8 \F1\
    \EE\EE\E1\F9\E5\ED\E8\E9 \EF\E5\F0\E8\EE\E4\E8\F7\E5\F1\EA\EE\E9 \E4\E8\E0\
    \E3\ED\EE\F1\F2\E8\EA\E8\r\
    \n:local diagWeekPer \"865\";\r\
    \n# C\F7\E8\F2\E0\E5\F2\F1\FF, \E8\F1\F5\EE\E4\FF \E8\E7 \EF\E5\F0\E8\EE\
    \E4\E8\F7\ED\EE\F1\F2\E8 \E7\E0\EF\F3\F1\EA\E0 - \E5\F1\EB\E8 \F1\EA\F0\E8\
    \EF\F2 \E7\E0\EF\F3\F1\EA\E0\E5\F2\F1\FF \EA\E0\E6\E4\FB\E5 30 \F1\E5\EA\
    \F3\ED\E4, \F2\EE \E4\EB\FF \E7\E0\E4\E5\F0\E6\EA\E8 \E2 1 \F7\E0\F1 \ED\
    \F3\E6\ED\EE \F3\F1\F2\E0\ED\EE\E2\E8\F2\FC 60*60*2-1=7199\r\
    \n\r\
    \n# \D2\E5\EA\F1\F2\EE\E2\FB\E5 \F1\F2\F0\EE\EA\E8 \EF\E8\F1\E5\EC\r\
    \n:local commErrMsg \"\CE\F8\E8\E1\EA\E0 \F1\E2\FF\E7\E8 \F1 UPS (\$upsSer\
    ial)!\";\r\
    \n:local commOkMsg \"\D1\EE\E5\E4\E8\ED\E5\ED\E8\E5 \F1 UPS (\$upsSerial) \
    \E2\EE\F1\F1\F2\E0\ED\EE\E2\EB\E5\ED\EE!\";\r\
    \n:local diagErrMsg \"\C4\E8\E0\E3\ED\EE\F1\F2\E8\F7\E5\F1\EA\E8\E5 \F1\E2\
    \E5\E4\E5\ED\E8\FF \E2\E5\F0\ED\F3\EB\E8 \EE\F8\E8\E1\EA\F3!\";\r\
    \n:local diagWeekMsg \"\CF\E5\F0\E8\EE\E4\E8\F7\E5\F1\EA\EE\E5 \E8\ED\F4\
    \EE\F0\EC\E0\F6\E8\EE\ED\ED\EE\E5 \EF\E8\F1\FC\EC\EE!\";\r\
    \n:local powerFailMsg \"\D1\E1\EE\E9 \EF\E8\F2\E0\ED\E8\FF!\";\r\
    \n:local powerOkMsg \"\CF\E8\F2\E0\ED\E8\E5 \E2\EE\F1\F1\F2\E0\ED\EE\E2\EB\
    \E5\ED\EE!\";\r\
    \n:local batteryFull \"\C1\E0\F2\E0\F0\E5\FF \E4\EE\F1\F2\E0\F2\EE\F7\ED\
    \EE \E7\E0\F0\FF\E6\E5\ED\E0.\";\r\
    \n\r\
    \n# \CF\EE\F0\EE\E3\E8 \EE\F2\EF\F0\E0\E2\EA\E8 \F1\EE\EE\E1\F9\E5\ED\E8\
    \E9 \EE \F1\E1\EE\E5 \EF\E8\F2\E0\ED\E8\FF \E2 %\r\
    \n:local powerLvl1 50;\r\
    \n:local powerLvl2 25;\r\
    \n\r\
    \n# \CF\EE\F0\EE\E3 \E2 %, \EF\EE\F1\EB\E5 \EA\EE\F2\EE\F0\EE\E3\EE \E1\E0\
    \F2\E0\F0\E5\FF \F1\F7\E8\F2\E0\E5\F2\F1\FF \E7\E0\F0\FF\E6\E5\ED\ED\EE\E9\
    \_\EF\EE\EB\ED\EE\F1\F2\FC\FE\r\
    \n:local battFullLvl 95;\r\
    \n\r\
    \n# \C8\ED\E8\F6\E8\E0\EB\E8\E7\E0\F6\E8\FF \EF\E5\F0\E5\EC\E5\ED\ED\FB\F5\
    \_- \F3\F1\EB\EE\E2\ED\FB\E9 \ED\EE\EC\E5\F0 UPS \E2 \F1\E8\F1\F2\E5\EC\E5\
    , \ED\E0\E7\E2\E0\ED\E8\E5 \EC\EE\E4\E5\EB\E8 \E8 \F1\F2\E0\F2\F3\F1\r\
    \n:local upsNumber;\r\
    \n:local upsName;\r\
    \n\r\
    \n# \C8\ED\E8\F6\E8\E0\EB\E8\E7\E0\F6\E8\FF \E3\EB\EE\E1\E0\EB\FC\ED\EE\E3\
    \EE \F1\F7\E5\F2\F7\E8\EA\E0\r\
    \n:global upsCounters;\r\
    \n:if ( [ :typeof \$upsCounters ] = \"nothing\" ) do={ :set upsCounters [ \
    :toarray \"\" ]; }\r\
    \n\r\
    \n# \D4\F3\ED\EA\F6\E8\FF \F1\E1\EE\F0\E0 \E4\E8\E0\E3\ED\EE\F1\F2\E8\EA\
    \E8\r\
    \n:local upsDiagData do={\r\
    \n  :local diagData [ :toarray \"\" ];\r\
    \n\r\
    \n  /system ups {\r\
    \n    # \CF\EE\ED\FF\F2\E8\FF \ED\E5 \E8\EC\E5\FE, \EA\E0\EA \FD\F2\EE \F0\
    \E0\E1\EE\F2\E0\E5\F2, \ED\EE \FD\F2\EE \F0\E0\E1\EE\F2\E0\E5\F2!\r\
    \n    # \CF\EE\E4\F1\EC\EE\F2\F0\E5\ED\EE \F2\F3\F2 https://wiki.mikrotik.\
    com/wiki/UPS_scripts\r\
    \n    monitor \$upsNumber once do={\r\
    \n      :set ( \$diagData -> \"runtimeLeft\" ) \$\"runtime-left\";\r\
    \n      :set ( \$diagData -> \"batteryCharge\" ) \$\"battery-charge\";\r\
    \n      :set ( \$diagData -> \"batteryVoltage\" ) \$\"battery-voltage\";\r\
    \n      :set ( \$diagData -> \"lineVoltage\" ) \$\"line-voltage\";\r\
    \n      :set ( \$diagData -> \"upsLoad\" ) \$\"load\";\r\
    \n      :set ( \$diagData -> \"replaceBattery\" ) \$\"replace-battery\";\r\
    \n      :set ( \$diagData -> \"upsOverload\" ) \$\"overload\";\r\
    \n#      :set ( \$diagData -> \"lowBattery\" ) \$\"low-battery\";\r\
    \n      :set ( \$diagData -> \"hidSelfTest\" ) \$\"hid-self-test\";\r\
    \n    }\r\
    \n  }\r\
    \n\r\
    \n  :return \$diagData;\r\
    \n}\r\
    \n\r\
    \n# \D4\F3\ED\EA\F6\E8\FF \F1\F7\E5\F2\F7\E8\EA\E0\r\
    \n:local sendCounter do={\r\
    \n\r\
    \n  :global upsCounters;\r\
    \n  :local sendLabel;\r\
    \n\r\
    \n  :if ( [ :typeof ( \$upsCounters -> \"\$counterLabel\" ) ]  = \"nothing\
    \" || \$resetCounter = true ) do={\r\
    \n    :set ( \$upsCounters -> \"\$counterLabel\" ) \$counterLimit;\r\
    \n  }\r\
    \n\r\
    \n  :if ( ( \$upsCounters -> \"\$counterLabel\" ) = \$counterLimit ) do={\
    \r\
    \n    :set sendLabel true;\r\
    \n\r\
    \n    :if ( \$resetCounter != true ) do={\r\
    \n      :set ( \$upsCounters -> \"\$counterLabel\" ) 0;\r\
    \n    }\r\
    \n    } else={\r\
    \n      :set sendLabel false;\r\
    \n      :set ( \$upsCounters -> \"\$counterLabel\" ) ( ( \$upsCounters -> \
    \"\$counterLabel\" ) + 1 );\r\
    \n    }\r\
    \n\r\
    \n  :return \$sendLabel;\r\
    \n}\r\
    \n\r\
    \n# \D4\F3\ED\EA\F6\E8\FF \EE\F2\EF\F0\E0\E2\EA\E8 \EF\E8\F1\E5\EC\r\
    \n:local sendMail do={\r\
    \n  :local errorTxt \"Function \\\"sendMail\\\" could not send message!\";\
    \r\
    \n  :local subjTxt \"\CE\EF\EE\E2\E5\F9\E5\ED\E8\E5 \F1\E8\F1\F2\E5\EC\FB \
    \EC\EE\ED\E8\F2\EE\F0\E8\ED\E3\E0 UPS\";\r\
    \n\r\
    \n  :local monthToNum;\r\
    \n  :local dateToPick;\r\
    \n  :local dateToLog;\r\
    \n  :local timeToLog;\r\
    \n\r\
    \n  :set monthToNum {jan=\"01\";feb=\"02\";mar=\"03\";apr=\"04\";may=\"05\
    \";jun=\"06\";jul=\"07\";aug=\"08\";sep=\"09\";oct=\"10\";nov=\"11\";dec=\
    \"12\";};\r\
    \n  :set dateToPick [/system clock get date];\r\
    \n  :set dateToLog ( [:pick \$dateToPick 4 6] . \".\" . ( \$monthToNum -> \
    [:pick \$dateToPick 0 3] ) . \".\" . [:pick \$dateToPick 7 11] );\r\
    \n  :set timeToLog [/system clock get time];\r\
    \n\r\
    \n  :set subjTxt \"\$subjTxt @ \$dateToLog \$timeToLog\";\r\
    \n\r\
    \n  :do { /tool e-mail send to=\$mailTo subject=\$subjTxt body=\$msg; } on\
    -error={ :log error (\"\$errorTxt\"); }\r\
    \n}\r\
    \n\r\
    \n/system ups {\r\
    \n  # \CF\EE\EB\F3\F7\E5\ED\E8\E5 \F1\E5\F0\E8\E9\ED\EE\E3\EE \ED\EE\EC\E5\
    \F0\E0 \E8 \EC\EE\E4\E5\EB\E8 UPS\r\
    \n  :set upsNumber [ find serial=\$upsSerial ];\r\
    \n  :set upsName [ get \$upsNumber model ];\r\
    \n\r\
    \n  # \CF\F0\EE\E2\E5\F0\EA\E0 \EA\EE\EC\EC\F3\ED\E8\EA\E0\F6\E8\E8 \F1 UP\
    S\r\
    \n  :if ( [ :typeof \$upsName ] = \"nil\" ) do={\r\
    \n    :log error (\"UPS communication error!\");\r\
    \n\r\
    \n    :if ( [ \$sendCounter counterLabel=commFail counterLimit=\$commErrPe\
    r ] = true ) do={\r\
    \n      \$sendMail mailTo=\$adminMail msg=\$commErrMsg;\r\
    \n    }\r\
    \n\r\
    \n  :if ( ( \$upsCounters -> \"commErrFlg\" ) != true ) do={ :set ( \$upsC\
    ounters -> \"commErrFlg\" ) true; }\r\
    \n\r\
    \n  :error \"UPS communication error. Exit!\";\r\
    \n  } else={\r\
    \n    :if ( ( \$upsCounters -> \"commErrFlg\" ) = true ) do={\r\
    \n      \$sendCounter counterLabel=commFail counterLimit=\$commErrPer rese\
    tCounter=true;\r\
    \n      \$sendMail mailTo=\$adminMail msg=\$commOkMsg;\r\
    \n      :set ( \$upsCounters -> \"commErrFlg\" ) false;\r\
    \n      :log warning (\"communication with UPS restored!\");\r\
    \n    }\r\
    \n  }\r\
    \n\r\
    \n  # \D1\E1\EE\F0 \E4\E0\ED\ED\FB\F5 \E4\E8\E0\E3\ED\EE\F1\F2\E8\EA\E8\r\
    \n  :local currDiagData [ \$upsDiagData upsNumber=\$upsNumber; ];\r\
    \n\r\
    \n  # \CF\EE\E4\E3\EE\F2\EE\E2\EA\E0 \E4\E0\ED\ED\FB\F5 \E4\E8\E0\E3\ED\EE\
    \F1\F2\E8\EA\E8\r\
    \n  :local runtimeLeft ( [ :pick ( \$currDiagData -> \"runtimeLeft\" ) 0 2\
    \_] . \"h\" . [ :pick ( \$currDiagData -> \"runtimeLeft\" ) 3 5 ] . \"m\" \
    );\r\
    \n  :local batteryCharge ( \$currDiagData -> \"batteryCharge\" );\r\
    \n  :local batteryVoltage ( [ :pick ( \$currDiagData -> \"batteryVoltage\"\
    \_) 0 2 ] . \".\" . [ :pick ( \$currDiagData -> \"batteryVoltage\" ) 2 4 ]\
    \_. \"V\" );\r\
    \n  :local lineVoltage ( [ :pick ( \$currDiagData -> \"lineVoltage\" ) 0 3\
    \_] . \"V\" );\r\
    \n  :local upsLoad ( \$currDiagData -> \"upsLoad\" );\r\
    \n  :local replaceBattery ( \$currDiagData -> \"replaceBattery\" );\r\
    \n  :local upsOverload ( \$currDiagData -> \"upsOverload\" );\r\
    \n  :local hidSelfTest ( \$currDiagData -> \"hidSelfTest\" );\r\
    \n\r\
    \n  # \CF\F0\EE\E2\E5\F0\EA\E0 \ED\E0\EB\E8\F7\E8\FF \F1\E5\F2\E8\r\
    \n  :if ( [ get \$upsNumber on-line ] = true ) do={\r\
    \n\r\
    \n    # \CF\F0\EE\E2\E5\F0\EA\E0 \F3\F0\EE\E2\ED\FF \E7\E0\F0\FF\E4\E0 \C0\
    \CA\C1\r\
    \n    :if ( ( \$upsCounters -> \"batteryUsed\" ) != true && ( \$currDiagDa\
    ta -> \"batteryCharge\" ) < \$battFullLvl ) do={\r\
    \n      :set ( \$upsCounters -> \"batteryUsed\" ) true;\r\
    \n    }\r\
    \n\r\
    \n    # \CE\F2\EF\F0\E0\E2\EA\E0 \EF\E8\F1\FC\EC\E0 \EE \E4\EE\F1\F2\E0\F2\
    \EE\F7\ED\EE\E9 \E7\E0\F0\FF\E4\EA\E5 \C0\CA\C1\r\
    \n    :if ( ( \$upsCounters -> \"batteryUsed\" ) = true && ( \$currDiagDat\
    a -> \"batteryCharge\" ) >= \$battFullLvl ) do={\r\
    \n      :set batteryFull \"\$batteryFull\\r\\n\\r\\nRuntime Left: \$runtim\
    eLeft\\r\\nBattery Charge: \$batteryCharge%\\r\\nBattery Voltage: \$batter\
    yVoltage\\r\\nLoad: \$upsLoad%\\r\\n\\r\\n\$upsName (SN: \$upsSerial)\";\r\
    \n      \$sendMail mailTo=\$adminMail msg=\$batteryFull;\r\
    \n      :set ( \$upsCounters -> \"batteryUsed\" ) false;\r\
    \n    }\r\
    \n\r\
    \n    # \CE\F2\EF\F0\E0\E2\EA\E0 \EF\E8\F1\FC\EC\E0 \EE \E2\EE\F1\F1\F2\E0\
    \ED\EE\E2\EB\E5\ED\E8\E8 \FD\ED\E5\F0\E3\EE\F1\ED\E0\E1\E6\E5\ED\E8\FF\r\
    \n    :if ( ( \$upsCounters -> \"powerFailFlg\" ) = true ) do={\r\
    \n      :set powerOkMsg \"\$powerOkMsg\\r\\n\\r\\nRuntime Left: \$runtimeL\
    eft\\r\\nBattery Charge: \$batteryCharge%\\r\\nBattery Voltage: \$batteryV\
    oltage\\r\\nLoad: \$upsLoad%\\r\\n\\r\\n\$upsName (SN: \$upsSerial)\";\r\
    \n      \$sendMail mailTo=\$adminMail msg=\$powerOkMsg;\r\
    \n      :set ( \$upsCounters -> \"powerFailFlg\" ) false;\r\
    \n      :set ( \$upsCounters -> \"powerFailSnd\" ) false;\r\
    \n      :log warning (\"power restored!\");\r\
    \n      :error \"UPS Power Ok. Exit!\";\r\
    \n    }\r\
    \n\r\
    \n    # \CF\F0\EE\E2\E5\EA\E0 \ED\E0\E3\F0\F3\E7\EA\E8 \E8 \F1\EE\F1\F2\EE\
    \FF\ED\E8\FF \C0\CA\C1, \EE\F2\EF\F0\E0\E2\EA\E0 \F1\EE\EE\E1\F9\E5\ED\E8\
    \FF\r\
    \n    :if ( ( \$currDiagData -> \"replaceBattery\" ) = true || ( \$currDia\
    gData -> \"upsOverload\" ) = true ) do={\r\
    \n      :if ( [ \$sendCounter counterLabel=diagFail counterLimit=\$diagErr\
    Per ] = true ) do={\r\
    \n        :set diagErrMsg \"\$diagErrMsg\\r\\n\\r\\nReplace Battery: \$rep\
    laceBattery\\r\\nOverload: \$upsOverload (Load: \$upsLoad%)\\r\\n\\r\\n\$u\
    psName (SN: \$upsSerial)\";\r\
    \n        \$sendMail mailTo=\$adminMail msg=\$diagErrMsg;\r\
    \n      }\r\
    \n      :error \"Diagnostic error. Exit!\";\r\
    \n    }\r\
    \n\r\
    \n    # \CE\F2\EF\F0\E0\E2\EA\E0 \EF\E5\F0\E8\EE\E4\E8\F7\E5\F1\EA\EE\E9 \
    \E4\E8\E0\E3\ED\EE\F1\F2\E8\EA\E8\r\
    \n    :if ( [ \$sendCounter counterLabel=diagWeek counterLimit=\$diagWeekP\
    er ] = true ) do={\r\
    \n      :set diagWeekMsg \"\$diagWeekMsg\\r\\n\\r\\nRuntime Left: \$runtim\
    eLeft\\r\\nBattery Charge: \$batteryCharge%\\r\\nBattery Voltage: \$batter\
    yVoltage\\r\\nLine Voltage: \$lineVoltage\\r\\nLoad: \$upsLoad%\\r\\n\\r\\\
    nReplace Battery: \$replaceBattery\\r\\nOverload: \$upsOverload\\r\\nHID S\
    elf Test: \$hidSelfTest\\r\\n\\r\\n\$upsName (SN: \$upsSerial)\";\r\
    \n      \$sendMail mailTo=\$adminMail msg=\$diagWeekMsg;\r\
    \n    }\r\
    \n\r\
    \n  # \C4\E5\E9\F1\F2\E2\E8\FF \EF\F0\E8 \F0\E0\E1\EE\F2\E5 \EE\F2 \E1\E0\
    \F2\E0\F0\E5\E9\r\
    \n  } else={\r\
    \n    # \D3\F1\F2\E0\ED\EE\E2\EA\E0 \EC\E5\F2\EA\E8 \F0\E0\E1\EE\F2\FB \EE\
    \F2 \E1\E0\F2\E0\F0\E5\E9\r\
    \n    :set ( \$upsCounters -> \"batteryUsed\" ) true;\r\
    \n\r\
    \n    # \CF\EE\E4\E3\EE\F2\EE\E2\EA\E0 \F1\EE\EE\E1\F9\E5\ED\E8\FF \EE \F1\
    \E1\EE\E5 \EF\E8\F2\E0\ED\E8\FF\r\
    \n    :set powerFailMsg \"\$powerFailMsg\\r\\n\\r\\nRuntime Left: \$runtim\
    eLeft\\r\\nBattery Charge: \$batteryCharge%\\r\\nBattery Voltage: \$batter\
    yVoltage\\r\\nLoad: \$upsLoad%\\r\\n\\r\\n\$upsName (SN: \$upsSerial)\";\r\
    \n\r\
    \n    # \CE\F2\EF\F0\E0\E2\EA\E0 \EF\E5\F0\E2\EE\E3\EE \F1\EE\EE\E1\F9\E5\
    \ED\E8\FF\r\
    \n    :if ( ( ( \$upsCounters -> \"powerFailFlg\" ) = false && ( \$upsCoun\
    ters -> \"powerFailSnd\" ) = false ) || [ :typeof ( \$upsCounters -> \"pow\
    erFailFlg\" ) ]  = \"nothing\"  ) do={\r\
    \n      \$sendMail mailTo=\$adminMail msg=\$powerFailMsg;\r\
    \n      :set ( \$upsCounters -> \"powerFailFlg\" ) true;\r\
    \n      :set ( \$upsCounters -> \"powerFailSnd\" ) true;\r\
    \n      :log error (\"power lost!\");\r\
    \n      :error \"First message sent. Exit!\";\r\
    \n    }\r\
    \n\r\
    \n    # \CE\F2\EF\F0\E0\E2\EA\E0 \E2\F2\EE\F0\EE\E3\EE \F1\EE\EE\E1\F9\E5\
    \ED\E8\FF \EF\F0\E8 \EF\E5\F0\E5\F1\E5\F7\E5\ED\E8\E8 \EF\E5\F0\E2\EE\E3\
    \EE \EF\EE\F0\EE\E3\E0\r\
    \n    :if ( ( \$upsCounters -> \"powerFailFlg\" ) = true && ( \$upsCounter\
    s -> \"powerFailSnd\" ) = true && \$batteryCharge <= \$powerLvl1 ) do={\r\
    \n      \$sendMail mailTo=\$adminMail msg=\$powerFailMsg;\r\
    \n      :set ( \$upsCounters -> \"powerFailSnd\" ) false;\r\
    \n      :error \"Second message sent. Exit!\";\r\
    \n    }\r\
    \n\r\
    \n    # \CE\F2\EF\F0\E0\E2\EA\E0 \F2\F0\E5\F2\FC\E5\E3\EE \F1\EE\EE\E1\F9\
    \E5\ED\E8\FF \EF\F0\E8 \EF\E5\F0\E5\F1\E5\F7\E5\ED\E8\E8 \E2\F2\EE\F0\EE\
    \E3\EE \EF\EE\F0\EE\E3\E0\r\
    \n    :if ( ( \$upsCounters -> \"powerFailFlg\" ) = true && ( \$upsCounter\
    s -> \"powerFailSnd\" ) = false && \$batteryCharge <= \$powerLvl2 ) do={\r\
    \n      \$sendMail mailTo=\$adminMail msg=\$powerFailMsg;\r\
    \n      :set ( \$upsCounters -> \"powerFailSnd\" ) last;\r\
    \n      :error \"Third message sent. Exit!\";\r\
    \n    }\r\
    \n  }\r\
    \n}\r\
    \n\r\
    \n# With love from Vladivostok."

Запуск скрипта

Скрипт должен выполняться планировщиком по расписанию. Я использую интервал в 5 минут.

ups-scheduling.rsc
/system scheduler
add interval=5m name="UPS monitiring" on-event=ups-monitiring policy=\
    read,write,policy,test start-date=dec/06/2020 start-time=08:05:00

Пример сообщений

Политики запуска

Это минимально необходимый набор для работы скрипта.

  • read,
  • write,
  • policy,
  • test.

Дисклеймер

  • Использование материалов данной базы знаний разрешено на условиях лицензии, указанной внизу каждой страницы! При использовании материалов активная гиперссылка на соответствующую страницу данной базы знаний обязательна!
  • Автор не несет и не может нести какую либо ответственность за последствия использования материалов, размещенных в данной базе знаний. Все материалы предоставляются по принципу «как есть». Используйте их исключительно на свой страх и риск.
  • Все высказывания, мысли или идеи автора, размещенные в материалах данной базе знаний, являются исключительно его личным субъективным мнением и могут не совпадать с мнением читателей!
  • При размещении ссылок в данной базе знаний на интернет-страницы третьих лиц автор не несет ответственности за их техническую функциональность (особенно отсутствие вирусов) и содержание! При обнаружении таких ссылок, можно и желательно сообщить о них в комментариях к соответствующей статье.

Обсуждение

Vadym, 2022/04/11 00:12
Hi, after import all comments are like this:





# Ñåðèéíûé íîìåð UPS è àäðåñ äëÿ óâåäîìëåíèé

:local upsSerial XXXXXXXXXXXX;



could you please upload script with comments replaced by readable symbols?
Николай Солошин, 2022/04/18 10:48
Hey! Comments are written in Russian. If there is no Russian support, just ignore it.
Ваш комментарий:
M T᠎ K T T S U R X X T U Q​ U N P
 
Последнее изменение: 2022/02/12 11:40 (внешнее изменение)