UPS مزرعة مراقبة جماعية مع بروتوكول Megatec في Zabbix

كانت هناك حاجة لرصد حديقة حيوان UPS ، Ippon ، Powercom و Krauler. كأداة رصد تستخدم Zabbix.

بطبيعة الحال ، يجب حل المشكلة 1) بثمن بخس 2) أرخص ، لذلك تم رفض الخيار مع وحدات SNMP على الفور. تقرر استخدام اتصال المنفذ التسلسلي ، نظرًا لوجود تجربة تطوير لـ Ippon و APC. بالمناسبة ، يحتوي APC في السوق الثانوية على وحدات SNMP بسعر معقول ، ولكن بالنسبة لأجهزة UPS غير المكلفة ، لم أتمكن من العثور إلا على وحدات جديدة بسعر 11-20 ألف روبل.

في سياق العمل ، تم تحديد المهام الإضافية التالية:

  1. ابحث عن الكابلات وافحصها لتوصيل كل UPS ، لعدم وجود أي منها في المجموعة
  2. لتنفيذ وحدة معينة من شأنها أن تحتوي على واجهة RS-232 من ناحية وفهم بروتوكول تبادل البيانات مع كل UPS ، ومن ناحية أخرى ، لديها واجهة شبكة ويمكن أن ترسل البيانات في شكل zabbix_trapper.
  3. اختبار نموذج جمع البيانات ونقلها ، وأجزاء من الرمز ، وكذلك تنسيق البيانات.


أثناء تنفيذ الفقرتين الثانية والثالثة ، أردت أن أجمع في مكان واحد جميع البيانات التي ستسمح في المستقبل بتنفيذ جهاز منفصل لـ m / c.

لذا:

  • 1. الكابلات

لم يكن هناك أي كابلات لأي UPS. من حيث المبدأ ، لا تمثل المهمة الأولى مشكلة للأشخاص الذين يمكنهم حساب جهات الاتصال على موصل DB9. كما اتضح ، ليس الجميع فقط يعرفون كيف ، بما في ذلك أنا. يتم عكس جهات الاتصال على موصلات F و M ، ولكن يتم توقيعها بشكل عام ، من المستحيل ارتكاب خطأ ، إذا كنت حذراً.



offtopic صغير. يتكون العمود الفقري للخادم من مضيفين Vmware ESXi ، وهما موجودان في رف مع اثنين من UPS. تحتوي بعض الخوادم على إثنين من مصادر الطاقة. وجزء ، للأسف ، هو واحد فقط ، ولهذا السبب يعانون بشكل دوري. تتم استضافة Zabbix حاليًا على أحد الأجهزة المضيفة كآلة افتراضية. من حيث المبدأ ، فإن نشر خادم افتراضي صغير على Ubuntu (أستخدم هذا النظام الأساسي للخدمات) لتنفيذ أي مهمة لا يمثل مشكلة.

وبالتالي ، كان المخطط على النحو التالي: منفذ COM على ESXi -> منفذ Com على الجهاز الظاهري -> برنامج C الذي يعيد البيانات من UPS -> Script أو البرنامج الذي يرسل فخ zabbix. يجب الجمع بين النقطتين الأخيرتين في المستقبل. على الرغم من أنه يعمل بهذه الطريقة.

تم حل المشكلة بالتسلسل ، عن طريق توصيل الكبل لجهاز UPS واحد ، عن طريق توصيل موصل إضافي للخادم (هناك اثنان ، بالإضافة إلى محول rj-45 في DB9) ، والتحقق من الاتصال ، والتحقق من البرنامج ، وإعداد العناصر في Zabbix.

  • 2. استجواب منفذ COM بواسطة البرنامج

أول شيء كان مطلوبًا هو اختيار خادم لاستضافة التعليمات البرمجية القابلة للتنفيذ. لم أقم بتثبيت أدمغتي ونشرت كل هذا على خادم Zabbix.
ثانيًا ، فكرت في كيفية معالجة البيانات. بسبب التصميم في باش
array=( $(/home/appliance/uniups) )

التي تقسم السلسلة إلى صفيف من البيانات ، قررت فقط إرجاع مقطع السطر MMM.M NNN.N PPP.P QQQ RR.R S.SS TT.T
كود البرنامج
#include <stdio.h>   /*   / */
#include <string>
#include <iostream>
#include <cstring>

using namespace std;
#include <unistd.h>  /*    UNIX */
#include <fcntl.h>   /*    */
#include <errno.h>   /*    */
#include <termios.h> /*   POSIX- */
#include <sys/types.h>
#include <sys/stat.h>

int fd; /*     */
char buf[512];/*      */
int main (int argc, char* argv[])
 {
    int iIn,iOut;
    string UPSAnswer;
    if (argc>=2)
{
        fd = open(argv[1], O_RDWR | O_NOCTTY | O_NDELAY); /*'open_port()' -    */
        if (fd == -1)   {
           printf("error port\n");
           perror("open_port: Unable to open port - ");   }
     else
        {
         struct termios options; /*   */
         tcgetattr(fd, &options); /*  */

         cfsetispeed(&options, B2400); /*  */
         cfsetospeed(&options, B2400); /*  */

         options.c_cflag &= ~PARENB; /*  */
         options.c_cflag &= ~CSTOPB; /* 2- ,  1 */
         options.c_cflag &= ~CSIZE; /*  */
         options.c_cflag |= CS8; /* 8*/
         tcsetattr(fd, TCSANOW, &options); /*  */
        }

        char Params[64];

        if(argc>=3)
        {
            if (!strcmp(argv[2],"status"))
            {
                iOut = write(fd, "Q1\r", 3);
                usleep(800000);
                if (iOut < 0)  fputs("write() of 4 bytes failed!\n", stderr);
                iIn=read(fd,buf,250); /*    */

                 strncpy(Params,&buf[38],11);
                 Params[46]=0;
            }
            else if (!strcmp(argv[2],"help"))
            {
                printf (" .   !\r\n");
            }
            else if (!strcmp(argv[2],"name"))
            {
                iOut = write(fd, "I\r", 3);
                usleep(800000);
                if (iOut < 0)  fputs("write() of 4 bytes failed!\n", stderr);
                iIn=read(fd,buf,250); /*    */
                strncpy(Params,&buf[0],60);

            }
            else if (!strcmp(argv[2],"stat2"))
            {
                iOut = write(fd, "F\r", 3);
                usleep(800000);
                if (iOut < 0)  fputs("write() of 4 bytes failed!\n", stderr);
                iIn=read(fd,buf,250); /*    */
                strncpy(Params,&buf[1],60);
         Params[20]=0;
            }
            else
            {
                printf ("? \r\n");
            }
        }
        else
        {
           /*    Q1 */
                usleep(1800);
                iIn=read(fd,buf,250);
                usleep(1800);
           iOut = write(fd, "Q1\r", 3);
           usleep(800000);
           if (iOut < 0)  fputs("write() of 4 bytes failed!\n", stderr);
           iIn=read(fd,buf,250); /*    */

           strncpy(Params,&buf[1],36);
           Params[36]=' ';
        }
    close(fd);
    printf("%s\r\n",Params);
}
else
printf("Usage %s /dev/ttySx", argv[0]);

}


لقد وجدت عملًا مع المنفذ في Google ، يمكنك القراءة من Bash ، ولكن من Bash لم يكن من الممكن تحقيق عملية مستقرة. من حيث المبدأ ، فإن رمز C في لينكس هو ب. تم اختبار أول Ippon ، ثم أثناء دراسة Powercom UPS ، تم إطلاق شاشة منفذ ، والتي أظهرت أن PowerCom تعمل أيضًا عبر بروتوكول Megatec ، ويقوم البرنامج الأصلي باستطلاع UPS عند بدء التشغيل باستخدام أمري "I" و "F" ، ثم دوريًا "Q1". قمت بتعليق اسم المنفذ في شكل "/ dev / ttyS0" أو "/ dev / ttyS1" في الوسيطة الأولى ، تسمح لك الوسيطة الثانية بطلب معلمات إضافية ، يظهر الرمز.

في الدليل / المنزل / الجهاز / وضع البرنامج ، أطلق عليه uniups.cpp. جمعت
g++ -o uniups uniups.cpp 
.

من حيث المبدأ ، النتيجة هي شيء من هذا القبيل (نعم ، أعمل تحت الجذر ، لا تعلق حتى)

root@zabbix:~# ./uniups /dev/ttyS0
204.4 204.4 204.4 035 49.9 54.8 54.5
root@zabbix:~# ./uniups /dev/ttyS0 name
I
root@zabbix:~# ./uniups /dev/ttyS1 name
#POWERCOM        SXL-2000A  LCD  V4.3
root@zabbix:~# ./uniups /dev/ttyS1
216.3 216.3 216.3 000 50.0 54.2 30.0
root@zabbix:~# ./uniups /dev/ttyS1 stat2
220.0 009 048.0 50.0
root@zabbix:~#

ما هو مهم ، في النهاية اتضح أن جميع UPS تستخدم نفس البروتوكول ، الذي سمح باستخدام برنامج واحد. يتم استخدام الاتصال على 2400 ، 8N1 ، كل شيء آخر مغلق. كان هناك ذبابة في المرهم ، وعادة ما يعود اسم UPS فقط إلى Powercom ، ولا يفهم Ippon الأمر "I" ، ويعيد Krauler "# R1.1.1".

بالإضافة إلى ذلك ، ترجع Krauler الجهد إلى العنصر ، وبقية UPS إلى البطاريات ، في الوثائق التي توصف بأنها
SS.S أو S.SS للوحدات على الخط ، يتم توفير جهد / خلية البطارية على شكل S.SS. بالنسبة للوحدات الاحتياطية ، يتم توفير جهد البطارية الفعلي في شكل SS.S

في ضوء ذلك ، كان علي أن أضع التصحيح على البرنامج النصي. حول ذلك أدناه.

  • 3. إرسال البيانات إلى Zabbix

مع إرسال هذا تبين حديقة الحيوان لجميع المناسبات. على الخادم ، استخدمت Zabbix الأداة المساعدة zabbix_sender لتسريع العملية.
zabbix_sender -z _ -p 10051 -s ___ -k  -o 

من حيث المبدأ ، بالنسبة لاستطلاع اثنين من UPS ، هذا يكفي ، ولكن في هذه اللحظة ، سيكون لدي ثالث ، وفي المستقبل سيكون لدي الرابع ، لذلك اخترت أول واحد ، وبمصادفة غريبة ، خادم Linux الوحيد على مضيف Vmware الثاني وطرحه إلى له منافذ COM.

لم أستخدم عامل zabbix أو نسخ zabbix_sender ، لقد وجدت أن وصف الأخير على

All salt يتكون من ترميز البيانات في Base64. للتحقق ، استخدمت الأمر

echo "<req>\n<host>S3JhdWxlck1lbW9SVDIwMDA=</host>\n<key>RnJlcQ==</key>\n<data>NDkuNA==</data>\n</req>\n" | nc -q 0 192.168.53.23 10051
حيث 192.168.53.23 هو عنوان خادم Zabbix. إنها تعمل.
دعوت النص البرمجي أعلاه zabbix_sender.pl ووضعته على الخادم ، يبدو النص البرمجي كما يلي:
#!/usr/bin/perl

use IO::Socket;
use IO::Select;
use MIME::Base64;

my ($zabbixserver,$hostname,$item,$data) = @_;

$zabbixserver= @ARGV[0];
$hostname= @ARGV[1];
$item= @ARGV[2];
$data= @ARGV[3];

 my $timeout=10;
 my $request=sprintf("<req>\n<host>%s</host>\n<key>%s</key>\n<data>%s</data>\n</req>\n",
 encode_base64($hostname),encode_base64($item),encode_base64($data));

 my $sock = new IO::Socket::INET ( PeerAddr => $zabbixserver, PeerPort => '10051', Proto => 'tcp', Timeout => $timeout);
 die "Could not create socket: $!\n" unless $sock;
 $sock->send($request);
 my @handles=IO::Select->new($sock)->can_read($timeout);
 if (scalar(@handles) > 0)
 {
  $sock->recv($result,1024);
  print "answer from zabbix server $zabbixserver: $result\n";
 }
 else
 {
  print "no answer from zabbix server\n";
 }
 $sock->close();

كان Perl بالفعل على الخادم.

بعد ذلك ، كنا بحاجة إلى برنامج نصي يربط جميع المكونات معًا ويمكن وضعه في Cron.

هنا مثال لمنفذ واحد ، لمنفذ آخر يمكنك ببساطة نسخ نفس الرمز واستبدال اسم مختلف. لم أقم بالدورة ، بالكاد أتخيل سيارة بها أكثر من منفذي COM.

#!/bin/bash
array=( $(//uniups /dev/ttyS0) )
Names=( InVolt FaultVolt OutVolt Current Freq UBatt UTemp NA )
correct[5]="24.0"
j=0;
echo "Checking UPS on serial A - ${#array[@]}"
if  [ ${#array[@]} -gt "7" ]
then
param=""
for i in "${array[@]}"
do
   if [[ ${correct[$j]} ]]
      then
         param=$( echo "scale = 0; $i * ${correct[$j]}" | bc)
       else.
      param=$i
    fi
   //zabbix_sender.pl 192.168.53.23 KraulerMemoRT2000 ${Names[$j]} $param
   j=$j+1;
done
else
echo "No data on A"
fi


تعليقات صغيرة:
  • المصفوفة - المصفوفة التي يُرجعها برنامج الاستقصاء UPS ، الأسماء - يجب بدء مصفوفة بأسماء العنصر ، على عناصر خادم Zabbix بنفس الأسماء. KraulerMemoRT2000 - يجب أن يتطابق اسم غير المنقطع مع اسم المضيف على الخادم.
  • , , Zabbix , , , NA, , , .
  • ${#array[@]}, . , . : , , . , , . , , .
  • الصحيح [5] = "24.0" هو تصحيح الجهد للبطاريات (العنصر الخامس في المصفوفة) إذا قامت UPS بإرجاع الجهد على العنصر (جهد / خلية البطارية). لدي 6 عناصر في البطارية ، 4 قطع في السلسلة ، إجمالي 24. من حيث المبدأ ، يتم وصف هذا في البروتوكول. لقد وجدت أنه من غير الضروري إنشاء عنصر منفصل ، نظرًا لأن جميع وحدات UPS التي قمت بمراقبتها بواسطة القالب ولديها 48 فولت. عند مراقبة UPS من الفولتية المختلفة ، بالطبع ، سيكون من الضروري تغيير الهيكل قليلاً ، قد يكون من الأفضل وضع معلمات البطارية على الخادم.


يضاف النص أعلاه إلى كرون لكل دقيقة تنفيذ. لا يعتبر إعداد Zabbix في هذه المقالة.

من حيث المبدأ ، هذا كل شيء. سأكون سعيدًا إذا كانت المعلومات التي تم جمعها مفيدة لشخص ما.

Source: https://habr.com/ru/post/ar397637/


All Articles