Форум русскоязычного сообщества Ubuntu


Считаете, что Ubuntu недостаточно дружелюбна к новичкам?
Помогите создать новое Руководство для новичков!

Автор Тема: Монитор переменных  (Прочитано 2733 раз)

0 Пользователей и 1 Гость просматривают эту тему.

Оффлайн alexander.pronin

  • Автор темы
  • Старожил
  • *
  • Сообщений: 2539
    • Просмотр профиля
Монитор переменных
« : 20 Июля 2009, 09:13:53 »
   Пролог.
По мотивам conky сделал маленький проект.
Это решение удовлетворяет следующим критериям:
- межплатформенность, интернетодоступность, расширяемость и интегрируемость
- использование только свободных инструментов и простота для пользователя
- изменения осуществляются конфигурацией одного файла.
   Установка на сервере.
1. Установите Apache и PHP5 из репозитариев.
2. Распакуйте и скопируйте папку Monitor в /var/www
   Использование на клиенте.
1. Если клиент локальный (на том же компьютере, что и Apache). В браузере  введите адрес http://localhost/Monitor/PHP/monitor.php
2. Для клиента в локальной сети. Если компьютер, на котором стоит Apache, в сети называется ubuntu-desktop1 введите
http://ubuntu-desktop1/Monitor/PHP/monitor.php
3. Для клиента в Интернете. Если домен называется firma.ru введите
http://firma.ru.ubuntu-desktop1/Monitor/PHP/monitor.php
   Конфигурация параметров.
Файл configure используется для конфигурации и его можно редактировать под свою конфигурацию в любом текстовом редакторе.
Структура файла configure:
- количество строк
- количество столбцов (всегда 2)
- заголовок первого столбца
- заголовок второго столбца
- текст 1 строки
- команда 1 строки
...
- текст k строки
- команда k строки.

   Как сформировать файл configure.
Файл configure можно просто редактировать, но есть и другой способ для больших файлов, чтобы исключать ошибки.
1. В OpenOffice отредактировать (заполнить) таблицу.
2. Сохранить таблицу в формате odt (для дальнейшего использования) и в формате csv с разделителями между полями — ; и двойными кавычками в качестве разделителей текста для дальнейшей обработки.
3. Bash скриптом из файла csv сформировать файл configure.
4. Скопировать configure в /var/www/Monitor/php/
   Примеры.
Пример 1. Надо измерять температуру CPU.
В таблицу добавим строку:
- в колонке 1: Температура CPU
- в колонке 2: cat /proc/acpi/thermal_zone/THM/temperature | cut -b26-27
Пример 2. Надо указать критическую температуру СРU.
В таблицу добавим строку:
- в колонке 1: Критическая температура CPU
- в колонке 2: cat /proc/acpi/thermal_zone/THM/trip_points | cut -b26-28

   Эпилог.
Проект выполнен по технологии Ajax с использованием библиотеки xajax (лицензия GNU). ГНУть, ломать, изменять исходные тексты разрешено.
Пользователям рекомендую делиться своими configure, скриншотами и пожеланиями. В качестве команд можно использовать любые POSIX программы и скрипты: bash, perl, php (не проверял), пользовательские C программы и т.д. Если интересно — выложу скриншоты, свои пояснения и планы развития проекта (точнее куда это все должно эволюционировать). Желаю успехов.

Александр Пронин.


Пользователь решил продолжить мысль 20 Июля 2009, 13:10:57:
PS. Сейчас проверил в ссылках по использованию на клиенте PHP надо написать НЕ ЗАГЛАВНЫМИ БУКВАМИ - php,
http://localhost/Monitor/php/monitor.php
и т.д.
Не помню, когда заменил.
« Последнее редактирование: 20 Июля 2009, 13:10:58 от alexander.pronin »

Оффлайн alexander.pronin

  • Автор темы
  • Старожил
  • *
  • Сообщений: 2539
    • Просмотр профиля
Re: Монитор переменных
« Ответ #1 : 22 Июля 2009, 09:44:07 »
Некоторые пояснения к монитору.
В программе установлен вывод каждые 5 секунд (5000 - это в милисекундах). Вы можете сделать столько сколько Вам нужно.
Особо часто делать не стоит, чтобы не загружать процессор на сервере.
Программой очень удобно дистанционно мониторить серверы апичи, АСУТП шные сервера .

Расширение монитора.
Частота процессора.
al@ubuntu-desktop1:~$ cat /proc/cpuinfo | grep 'cpu MHz' | cut -c12-
3066.969
al@ubuntu-desktop1:~$
Использование вывода top.
Для разового использования в текстовом режиме используйте
top -b -n 1
Это позволяет применять фильтры.
Примеры.
al@ubuntu-desktop1:~$ top -b -n 1 | grep Swap
Swap:  3309348k total,    10768k used,  3298580k free,   170288k cached
al@ubuntu-desktop1:~$ top -b -n 1 | grep Mem
Mem:   1016424k total,  1006056k used,    10368k free,     3152k buffers
al@ubuntu-desktop1:~$
Про мониторинт батарей я не пишу, Вы легко можете это найти в интернете.

Оффлайн truegeek

  • FPGA Designer
  • Почётный модератор
  • Старожил
  • *
  • Сообщений: 4214
  • аЦкий схемотехник
    • Просмотр профиля
Re: Монитор переменных
« Ответ #2 : 22 Июля 2009, 13:16:24 »
ай, молодец какой!!!
было б времени побольше, обязательно попробовал, что за фрукт ))))
+1 за старания

Оффлайн alexander.pronin

  • Автор темы
  • Старожил
  • *
  • Сообщений: 2539
    • Просмотр профиля
Re: Монитор переменных
« Ответ #3 : 22 Июля 2009, 13:37:58 »
Попробовать быстро можно, если апач php5 уже установлены.
Осмысливая, что имеем, продолжу мысли.
Если у Вас установлен lm-sensors,
и работает, команда sensors

al@ubuntu-desktop1:~$ sensors
w83627ehf-isa-0290
Adapter: ISA adapter
VCore:       +1.35 V  (min =  +0.00 V, max =  +1.74 V)   
in1:        +12.30 V  (min =  +6.49 V, max = +10.08 V)   ALARM
AVCC:        +3.33 V  (min =  +2.02 V, max =  +3.06 V)   ALARM
3VCC:        +3.31 V  (min =  +4.08 V, max =  +2.80 V)   ALARM
in4:         +2.04 V  (min =  +2.01 V, max =  +1.27 V)   ALARM
in5:         +1.60 V  (min =  +2.04 V, max =  +2.04 V)   ALARM
in6:         +5.12 V  (min =  +4.89 V, max =  +6.53 V)   
VSB:         +3.30 V  (min =  +1.94 V, max =  +3.04 V)   ALARM
VBAT:        +3.28 V  (min =  +2.03 V, max =  +3.06 V)   ALARM
in9:         +1.63 V  (min =  +1.78 V, max =  +1.02 V)   ALARM
Case Fan:      0 RPM  (min =    0 RPM, div = 128)
CPU Fan:    3409 RPM  (min = 1776 RPM, div = 4)
Aux Fan:       0 RPM  (min = 10546 RPM, div = 128)  ALARM
fan4:          0 RPM  (min = 10546 RPM, div = 128)  ALARM
fan5:          0 RPM  (min = 10546 RPM, div = 128)  ALARM
Sys Temp:    +39.0°C  (high = -17.0°C, hyst =  -3.0°C)  ALARM  sensor = thermistor
CPU Temp:    +34.5°C  (high = +80.0°C, hyst = +75.0°C)  sensor = diode
AUX Temp:    +47.0°C  (high = +80.0°C, hyst = +75.0°C)  sensor = thermistor
cpu0_vid:   +1.375 V

al@ubuntu-desktop1:~$

Можно вытаскивать в монитор любые параметры.
al@ubuntu-desktop1:~$ sensors | grep "CPU Temp"
CPU Temp:    +35.0°C  (high = +80.0°C, hyst = +75.0°C)  sensor = diode
al@ubuntu-desktop1:~$
Или еще добавить
| cut ...  или
| awk ...
и вывести уже совсем что надо конкретно.

Оффлайн truegeek

  • FPGA Designer
  • Почётный модератор
  • Старожил
  • *
  • Сообщений: 4214
  • аЦкий схемотехник
    • Просмотр профиля
Re: Монитор переменных
« Ответ #4 : 22 Июля 2009, 13:55:21 »
у меня установлен и апач и пхп и мускуль и даже есть сервер с этими ребятами, просто нет времени на подобные игрища, надо свой проект доделывать, никак руки не доходят

Оффлайн alexander.pronin

  • Автор темы
  • Старожил
  • *
  • Сообщений: 2539
    • Просмотр профиля
Re: Монитор переменных
« Ответ #5 : 22 Июля 2009, 14:09:00 »
Когда попробуете, сообщите свое мнение. Мне интересно мнение людей.
Дальше я сделаю справа меню, для выбора объектов (мониторов, трендов, выборок из БД, визуализации объктов и т.д.).
Добавлю OPC-сервер.
И потихоньку сделаю среду АСУТП. ;D

Оффлайн truegeek

  • FPGA Designer
  • Почётный модератор
  • Старожил
  • *
  • Сообщений: 4214
  • аЦкий схемотехник
    • Просмотр профиля
Re: Монитор переменных
« Ответ #6 : 22 Июля 2009, 14:50:41 »
И потихоньку сделаю среду АСУТП. ;D
один  :2funny:

Оффлайн alexander.pronin

  • Автор темы
  • Старожил
  • *
  • Сообщений: 2539
    • Просмотр профиля
Re: Монитор переменных
« Ответ #7 : 22 Июля 2009, 15:03:14 »
Я не спешу. Что делать, никого зажечь не удалось. Все, что проходило, все было на готовых скадах. Последние на Intouch. Была еще итерактивная документация, а сейчас будет вообще голяк.

Оффлайн alexander.pronin

  • Автор темы
  • Старожил
  • *
  • Сообщений: 2539
    • Просмотр профиля
Re: Монитор переменных
« Ответ #8 : 27 Июля 2009, 11:45:00 »
Столкнулся с небольшой проблемой с переносом монитора на другой компьютер из-за прав. Даю скрипт для преодоления трудностей и текушую картинку (исходники выложу позже, если кому-то интересно).

#!/bin/sh
# Скрипт установит права 755 для всех папок и всех файлов внутри
# Запуск ./setAsess.sh
find ./ -name "*" | xargs chmod 755

Оффлайн alexander.pronin

  • Автор темы
  • Старожил
  • *
  • Сообщений: 2539
    • Просмотр профиля
Re: Монитор переменных
« Ответ #9 : 23 Сентября 2009, 14:21:32 »
Чтобы не плодить темы выкладываю сюда Modbus модуль. Он может быть использован для сбора информации на сервер или промежуточный сервер сбора информации от контроллеров.
Модуль написан на C#.
Использование стандартного варианта (метода ReadExisting в события DataReceived) на прием не подходит, т.к. он ориентирован на работу с строчным текстом. Удалось обойтись без делегатов. При желании можно сделать модуль компонентом, но пока смысла в этом я не увидел.
Конфигурация находится в конфигурационных файлах. Работающие приложение практически не загружает процессор.
Гнуть и ломать не возбраняется и даже приветствуется. Если что-то не ясно - спрашивайте.


Оффлайн zilog82

  • Активист
  • *
  • Сообщений: 420
  • Hello, World!!!
    • Просмотр профиля
Re: Монитор переменных
« Ответ #10 : 23 Сентября 2009, 14:30:26 »
классно! давно такую штуку хотел, руки не доходили. автору РЕСПЕКТ и спасибо!!!

Оффлайн alexander.pronin

  • Автор темы
  • Старожил
  • *
  • Сообщений: 2539
    • Просмотр профиля
Re: Монитор переменных
« Ответ #11 : 23 Сентября 2009, 14:52:02 »
Попробуйте и жду Ваш отзыв о функционировании.

Пользователь решил продолжить мысль 24 Сентября 2009, 16:23:36:
Добавил событие по приему буфера и проверил с модбасовским контроллером. Упростил встраивавание.

// Main.cs created with MonoDevelop
// User: pronin-ae at 10:00 14.09.2009
//
//
using System;
//using System.ComponentModel;
using System.IO;
using System.Collections;
using System.IO.Ports;
using System.Threading;

namespace ModbusComponent
{
   public delegate void ModbusDataReceved(byte[] buf);      
   
//   Modbus   functions
   enum FunctionModbus : byte{
//      ReadCoilStatus=1,           

//      ReadInputStatus=2,
//      ForceSingleCoil=5,           

      LoopBackDiagnosticTest=8,  //echo function: 01 08 0000 1234 (ED7C)

//      ForceMultipleCoils=15,       

//      ReportSlaveID   =17,         

      UserFunction=65             

   };



// pages of user Modbus functions 65

   enum UnderFunctionModbus : byte {

//      ReadCurrent=0,             

//      ReadUstavki=1,             

//      ReadSrab=2,                 

//      BreakerInfo =3,             

//      ReadPNU=5,

//      Write_Value_PNU=6,

//      Write_PUSK_PNU=7,

//      Write_STOP_PNU=8,

//      InfoBreak   =20,             

//      ReadIOStatus =24,
      Empty=255

   };      
//----------------------------
   public class mbEvent
   {
      public event ModbusDataReceved FlagEvent;
      public void OnFlagEvent(byte[] buffer)
      {
         if(FlagEvent!=null) FlagEvent(buffer);
      }
   }
//----------------------------         
      
      
   public class Modbus//:Component
   {
      public mbEvent evt = new mbEvent();
      // портовые настройки
      System.IO.Ports.SerialPort SPort1;
      string Name="/dev/ttyUSB0";
      int BaudRate=9600;
      int DataBits=8;
      StopBits stopBits=StopBits.One;
      int readBufferSize=1024;
      int writeBufferSize=1024;
      int readTimeout=20;
      int writeTimeout=20;
      // модбасовские настройки
      const ushort MagicValue= ((ushort)0xa001);

      byte MySlaveAddress=1;
      bool master=true;
      public bool Master {
         get {return (master);}
         set {master=value;}
      }
      
      ushort KS_in;

        ushort KS_out;

      public byte[] rb;
      byte[] wb;
      int Pointer_in=0;

      int Pointer_out=0;
      bool stop;
      public bool Stop {
         get {return (stop);}
         set {stop=value;}
      }
      Thread Thr;
      
// конструктор   
      public Modbus()
      {
         ConfigParse();
         Console.WriteLine("Parameters of Port: Name={0}, BR={1}, bits={2}, rdBuf={3}, wrBuf={4}",Name,BaudRate,DataBits,readBufferSize,writeBufferSize);
         Console.WriteLine("Parameters of ModBus: SL={0}, Master={1}",MySlaveAddress,Master);
         SPort1 =new System.IO.Ports.SerialPort(this.Name);
         SPort1.BaudRate=this.BaudRate;
         SPort1.StopBits=this.stopBits;
         SPort1.DataBits=this.DataBits;
         SPort1.ReadTimeout=this.readTimeout;
         SPort1.WriteTimeout=this.writeTimeout;
         SPort1.ReadBufferSize=this.readBufferSize;
         SPort1.WriteBufferSize=this.writeBufferSize;
         rb = new byte[this.readBufferSize+1] ;
         wb = new byte[this.writeBufferSize+1] ;
         try {
         SPort1.Open();
         }
         catch (IOException) {
            Console.WriteLine("Error Opening of Port");
            return;
         }
         Console.WriteLine("Serial Port opened");
         Thr = new Thread(Receve); // готовим поток на прием
         string strName;
         if(Master) strName="Master";
            else strName="Slave";
         Thr.Name = "Receve"+strName;
         Thr.Start();
      }
      
// Парсим конфигурационный файл Modbus.cnf      
      void ConfigParse()
      {
         string str;   
         FileStream fin;
         try {
            fin= new FileStream("Modbus.cnf",FileMode.Open);
         }
         catch(FileNotFoundException) {
            Console.WriteLine("File Modbus.cnf not found");
            return;
         }
         StreamReader str_fin = new StreamReader(fin);
         while((str=str_fin.ReadLine()) != null)
         {
            str = str.Trim(); // удаляем пробелы в начале и конце строки
            if((str.Length>0) && (str[0]!='#')) // удаляем строки комментариев
            {
               char [] sep = {' ','=','\t',';'}; // разбиваем строку на части
               string[] pars;
               pars = str.Split(sep);
               // удаляем пустые строки через коллекцию
               ArrayList al=new ArrayList();
               for(int i=0; i<pars.Length;i++)
                  al.Add(pars);
             M1:
               foreach(string s in al) {
                  if(s.Length==0) {
                     al.Remove(s);
                     goto M1; // C# позволяет делать такую чушь без последствий
                  }
               }
//               Console.WriteLine("{0} {1}",al[0],al[1]);
               
               switch ((string)al[0]){
               case "PortName":
                   Name=(string)al[1];
                  break;
               case "DataBits":
                  try {
                   DataBits=Int32.Parse((string)al[1]);
                  }
                  catch (FormatException) {
                        Console.WriteLine("Error DataBits");
                  }
                  catch (OverflowException) {
                        Console.WriteLine("Error DataBits");
                  }
                  break;
               case "BaudRate":
                  try {
                   BaudRate=Int32.Parse((string)al[1]);
                  }
                  catch (FormatException) {
                        Console.WriteLine("Error BaudRate");
                  }
                  catch (OverflowException) {
                        Console.WriteLine("Error BaudRate");
                  }
                  break;
               case "readBufferSize":
                  try {
                   readBufferSize=Int32.Parse((string)al[1]);
                  }
                  catch (FormatException) {
                        Console.WriteLine("Error readBufferSize");
                  }
                  catch (OverflowException) {
                        Console.WriteLine("Error readBufferSize");
                  }
                  break;
               case "writeBufferSize":
                  try {
                   writeBufferSize=Int32.Parse((string)al[1]);
                  }
                  catch (FormatException) {
                        Console.WriteLine("Error writeBufferSize");
                  }
                  catch (OverflowException) {
                        Console.WriteLine("Error writeBufferSize");
                  }
                  break;
               case "MySlaveAddress":
                  try {
                   MySlaveAddress=Byte.Parse((string)al[1]);
                  }
                  catch (FormatException) {
                        Console.WriteLine("Error MySlaveAddress");
                  }
                  catch (OverflowException) {
                        Console.WriteLine("Error MySlaveAddress");
                  }
                  break;
               case "Master":
                  try {
                     
                   Master=Boolean.Parse((string)al[1]);
                  }
                  catch (FormatException) {
                        Console.WriteLine("Error Master");
                  }
                  catch (OverflowException) {
                        Console.WriteLine("Error Master");
                  }
                  break;
               default:
                  break;
                  
               }
            }
         }
         str_fin.Close();
      }
      
// деструктор      
      ~Modbus()
      {
         if(SPort1.IsOpen) {
            SPort1.Close();
            Console.WriteLine("Serial Port closed");
            Thr.Abort();
            Console.WriteLine("Thread aborted");
         }
//         Dispose(false);
      }
      
// Расчет CRC      
      ushort CalcCRC16(ushort CRC16, byte a)

      {

         ushort temp=CRC16;

//         temp=XOR(temp,(ushort)a);

         temp ^= a;

         for (int i=0;i<8;i++) {

            if((temp&1)!=0) {

               temp/=2;

               temp^=MagicValue;

            }

            else temp/=2;

         }

         return temp;

      }
      
// запись байта в буфер с подсчетом КС      

        void WriteChar(byte ch) {

                wb[Pointer_out++]=ch;

                KS_out=CalcCRC16(KS_out, ch);

        }

      
// прием данных   в потоке
      public void Receve()
      {
         Pointer_in=0;
         int Bytes=0;
         Console.WriteLine("Receve Thread");
         if(!SPort1.IsOpen)
         {
            Console.WriteLine("Serial Port not opened");
            return;
         }
         
         while(!Stop) {
            if(Bytes==0) Thread.Sleep(5);
            try {
               Bytes=0;
               Bytes=SPort1.Read(rb,0,this.readBufferSize);
               Pointer_in += Bytes;
            }
            catch(TimeoutException) {
               if((Pointer_in!=0)&&((rb[0]==MySlaveAddress)&&(!Master))|Master){
                  // Обработка принятых данных по таймауту если
                  // что-то приняли сейчас
                  // для кс==0 и
                  //Для мастера - принимается все
                  //Для слейва - если SL его                   
//                  Console.WriteLine("Read Timeout. Receve All {0} Current {1}",Pointer_in,Bytes);
                  KS_in=0xffff;

                  for(int i=0;i<Pointer_in;i++) {
                     KS_in=CalcCRC16(KS_in, rb);

                  }
                  if(KS_in==0) {
//                     Console.WriteLine("KS is OK");
                     if(!Master) {
                        Console.WriteLine("Answer for Slave");
                        byte SL=MySlaveAddress;
                        byte Func=(byte)FunctionModbus.LoopBackDiagnosticTest;
                        byte Page=(byte)UnderFunctionModbus.Empty;
                        Send(SL,Func,Page);
                     }
                     else {
                        // здесь можно инициировать событие по приему для мастера
                        evt.OnFlagEvent(rb);
//                        Console.WriteLine("Receve (only) for Master");
//                        Console.WriteLine("\n Answer (echo) from SL={0}",rb[0]);
                        Pointer_in=0;
                     }
                  }
                  else {Console.WriteLine("KS is bad");}
                  Pointer_in=0;
               }
               }
               catch(IOException) {
                  Console.WriteLine("IOException error.");
                  Stop=true;
               }
            }
         Console.WriteLine("Поток для приема данных закрыт");
      }
      
// передача данных      
      public void Send(byte SL, byte Func, byte Page) {
//         Console.WriteLine("Data send");
         try {
            if(SPort1.IsOpen) {
                   KS_out=0xffff;

               Pointer_out=0;
               WriteChar(SL);
               WriteChar(Func);
               switch((FunctionModbus) Func) {
                        case FunctionModbus.LoopBackDiagnosticTest:

                                WriteChar(0);

                                WriteChar(0);

                                WriteChar(0x12);

                                WriteChar(0x34);

                        break;

                        case FunctionModbus.UserFunction:

                                WriteChar(Page);

                        break;

                        default:

                        break;

               }
               //CRC16

               wb[Pointer_out++]=(byte)KS_out;

               wb[Pointer_out++]=(byte)(KS_out>>8);


               SPort1.Write(wb,0,Pointer_out);
            }
            else {
               Console.WriteLine("Serial Port not opened");
            }
         }
         catch(TimeoutException) {
            Console.WriteLine("Write Timeout");
         }
//         Console.WriteLine("Data sended");
      }
   }
//-------------------------------------------------------------------   
// временный тестовый класс для мастера и слайва   
   class Demo
   {
      void handler1(byte[] buf)
      {
         Console.WriteLine("\nСлучилось событие по приему буфера мастером SL={0}",buf[0]);
         
      }
      
      public static void Main()
      {
         Demo d = new Demo();
         d.Run();
      }
      
      public void Run()
      {
         Modbus mb = new Modbus();
         mb.evt.FlagEvent+= new ModbusDataReceved(handler1); // добавим событие по приему буфера для мастера
         byte SL;
         byte Func;
         byte Page;
         Console.WriteLine(@"
----------------
0 - Device scaning (echo test)
Enter - exit
----------------");
         string str = Console.ReadLine();
         if(str=="0") {
            
            if(mb.Master) // мастер
            {
               for (byte i=1;i<255;i++)
               {
                  SL=i;
                  Func=(byte)FunctionModbus.LoopBackDiagnosticTest;
                  Page=(byte)UnderFunctionModbus.Empty;
                  mb.Send(SL,Func,Page); // запрос
//                  Console.Write("SL={0} ",SL);
                  Console.Write(".");
                  Thread.Sleep(50);
               }
            }
         }
         
//         Console.ReadLine();
         mb.Stop=true;
         
         Console.WriteLine("End");
      }
   }
//-------------------------------------------------------------------   
}
« Последнее редактирование: 24 Сентября 2009, 16:23:36 от alexander.pronin »

Оффлайн alexander.pronin

  • Автор темы
  • Старожил
  • *
  • Сообщений: 2539
    • Просмотр профиля
Re: Монитор переменных
« Ответ #12 : 29 Сентября 2009, 14:43:12 »
Последний вариант Modbus модуля.
Пока никаких изменений с ним не планирую.
В примере юзерской части добавил как организуется режим spy для просмотра и логирования обменов между мастером и слейвами.
Чуть позже выложу сюда tcp варианты сервера и клиента тоже на до диез для комплекта.

 

Страница сгенерирована за 0.021 секунд. Запросов: 22.