企业温度监控


提出了一项任务,即提供“一些东西”来查看和控制工厂的温度。 已经安装了PLC 160控制器,并且通过RS-485接口( Wikipedia )连接了温度传感器。

控制器和传感器已安装在我之前。

有一个示例连接图:


使用CoDeSys( Wikipedia )进行查看。

没有温度历史,事故发生的时间也不知道。

开始


这个想法就是这样-与MySQL数据库一起创建一个WEB站点,并在其中存储有关温度和事故的信息。

初始任务:

  • 查看企业中任何计算机上的数据
  • 查看当前的崩溃和事件
  • 在线查看当前值
  • 更改警报记录的最大值和最小值

后来结果如下:

最大值和最小值不足以控制事故。

添加了一个临界最大值和一个临界最小值,以及温度恢复正常的时间。

  1. 如果温度超过最低或最高温度,但在时间T内恢复正常,则这是一次小事故(但记录为无关紧要的事故)。

    图片
  2. 如果温度超过临界最小值或临界最大值,则将立即导致严重事故。

    图片

需要区分访问:

  • 管理员-只为我)))
  • 技术人员-为每个传感器更改5个参数

    图片
    我必须及时添加事故参数的更改。 这样,例如,不会记录从00:00到09:00的事故。

    图片
  • 工程师-校准

    正确地,您需要使用带有COM端口的笔记本电脑来固定模块进行校准。 我决定通过WEB实现相同的功能,即 涉及校准的人员带着温度计来到传感器,并在现场显示实际值。

    图片
  • 其他所有人-视图

软件部分


通过局域网上的一堆PLC 160创建了一个虚拟机。
已安装CoDeSys。

配置了IP地址,以便计算机可以看到控制器。

图片

该项目位于路径c:\ project \ pro \上 ,名为my_work.pro

项目本身通过run.cmd文件启动

"C:\Program Files\3S Software\CoDeSys V2.3\Codesys.exe" "C:\project\pro\my_work.pro" /userlevel 0 /password 157999 /online 

应用程序启动run.cmd文件

 WinExec(Pchar(“c:\run.cmd”), SW_HIDE); 

我用DDE来获取温度值( Wikipedia

config.ini

 [CoDeSys] service=CoDeSys topic=C:\project\pro\my_work.pro item=C:\Program Files\3S Software\CoDeSys V2.3\ cmd=C:\run.cmd [db] host=127.0.0.1 port=3306 user=root key=keypassword db=workdb 

程序开始:

  1. 从“ config.ini”下载CoDeSys配置参数

    从“ config.ini”加载MySQL配置参数

    通过计时器(决定每分钟读取一次数据就足够了):

    • 使用MySQL获取传感器数量
    • 为每个传感器创建一个组件DDE.DDEConv

       DDE.DDEConv[…]:= TDdeClientConv.Create(Self) DDE.DDEConv[…].ServiceApplication:=”patchcodesys” DDE.DDEConv[…].SetLink(“name”,”patchdde”) 

      我们创建DDE.DDEItem组件并将其绑定到DDE.DDEConv组件:

       DDE.DDEItem[…]:=TDdeClientItem.Create(Self) DDE.DDEItem[…].DdeConv:=DDE.DDEConv[…] 

      我们通过MySQL传递传感器的名称:

       DDE.DDEItem[…].DdeItem:=MySQL.GetSensorName(…) 

      结果,我们获得了温度值:

       DDE.DDEItem[…].Text 

      我们为每个传感器保存当前温度值及其参数。

       MySQL.InsertTemp(MySQL.GetSensorName(...),””,INSQL(UMin[...]),INSQL(UMax[...]),INSQL(CRMin[...]),INSQL(CRMax[...])) 

    • 我们在当前日期和时间从MySQL获取:

      最低要求

       UMin[I…]:=OUTSQL(MySQL.GetMin(MySQL.GetSensorName(…))) 

      最大值

       UMax[…]:=OUTSQL(MySQL.GetMax(MySQL.GetSensorName(...))) 

      临界下限

       CRMin[…]:=OUTSQL(MySQL.GetCriticalMin(MySQL.GetSensorName(…))) 

      临界最大值

       CRMax[…]:=OUTSQL(MySQL.GetCriticalMax(MySQL.GetSensorName(…))) 

      时间

       CRTime[…]:=MySQL.GetCriticalTime(MySQL.GetSensorName(…)) 

      注意:“ 傻瓜保护”(如果最小值大于最大值,反之亦然),则我们将在适当的位置更改这些值。

       if (UMin[…]>=UMax[…]) then begin UM[…]:=UMin[…]; UMin[…]:=UMax[…]; UMax[…]:=UM[…]; end; 

    • 事故:

      如果没有意外,请创建一条记录

       MySQL.InsertCrash(FormatDateTime('yyyy-mm-dd hh:nn:ss', dt),FormatDateTime('yyyy-mm-dd hh:nn:ss', dt),MySQL.GetSensorName(...),…) 

      如果发生意外,我们会更新

       MySQL.UpdateCrash(MySQL.GetCrashID(MySQL.GetSensorName(...)),FormatDateTime('yyyy-mm-dd hh:nn:ss', dt),…) 

      事故结束,设置完成标志。

    网站


    PHP编写页面。

    主页(一段代码,不要踢太多):

     <?php require 'config.php'; session_start(); $page = isset( $_GET['page'] ) ? $_GET['page'] : ""; switch ( $page ) { case 'login': login(); break; case 'logout': logout(); break; case 'list': listpage(); break; ………………….. ?> 

    其余页面大致相同。 每个页面处理其数据。

    已经做了什么:

    • 传感器列表。 名称,程序的传感器名称,传感器类型。

      图片
    • 传感器按用途分组。

      图片
    • 添加了“事故状态”:在事故过程中,事故已完成,严重事故。
    • 实现添加用户及其角色。
    • 记录谁做了什么。
    • 存档所有事故。
    • 图表。

    拐杖


    1. CoDeSys程序启动时,将出现一个窗口:

      图片
      我们以编程方式将其关闭。

       W_WND_Button_Run: HWND: W_WND_RUN: HWND; C_Button_Message='Button'; C_CoDeSys_Message='CoDeSys'; W_WND_RUN := FindWindow(nil,C_CoDeSys_Message); if W_WND_RUN<>0 then begin W_WND_Button_Run:=FindWindowEx(W_WND_RUN, 0,C_Button_Message, nil); if W_WND_Button_Run<>0 then begin SendMessage(W_WND_Button_Run, WM_LBUTTONDOWN, 10, 10); SendMessage(W_WND_Button_Run, WM_LBUTTONUP, 10, 10); SendMessage(W_WND_Button_Run, WM_LBUTTONDOWN, 10, 10); SendMessage(W_WND_Button_Run, WM_LBUTTONUP, 10, 10); end; end; 

    2. 突然控制器被关闭。

      图片

       W_WND_Error:=FindWindow(nil,''); if W_WND_Error<>0 then begin W_WND_Button_Error:=FindWindowEx(W_WND_Error,0,'Button', nil); if W_WND_Button_Error<>0 then begin SendMessage(W_WND_Button_Error, WM_LBUTTONDOWN, 10, 10); SendMessage(W_WND_Button_Error, WM_LBUTTONUP, 10, 10); SendMessage(W_WND_Button_Error, WM_LBUTTONDOWN, 10, 10); SendMessage(W_WND_Button_Error, WM_LBUTTONUP, 10, 10); PostMessage(FindWindow(PChar(C_CoDeSys),nil), WM_QUIT, 0, 0); end; end; 

    3. 难以理解的挂起。

      图片

      我们重新启动应用程序。

       C_CLOSE_DEBUG='CoDeSys for Automation Alliance (debug)'; W_WND_CLOSE:=FindWindow(nil,C_CLOSE_DEBUG); if W_WND_CLOSE<>0 then begin KillProcess('Codesys.exe'); KillProcess('WerFault.exe'); PostMessage(FindWindow(PChar(C_Close_DEBUG),nil), WM_QUIT, 0, 0); PostMessage(FindWindow(PChar(C_CoDeSys),nil), WM_QUIT, 0, 0); MySQL.InsertLog('Error debug.. Kill process - codesys.exe and WerFault.exe'); MySQL.InsertLog('Restart programm'); RestartThisApp; end; //  function KillProcess(ExeName: string): LongBool; var B: BOOL; ProcList: THandle; PE: TProcessEntry32; begin Result := False; ProcList := CreateToolHelp32Snapshot(TH32CS_SNAPPROCESS, 0); PE.dwSize := SizeOf(PE); B := Process32First(ProcList, PE); while B do begin if (UpperCase(PE.szExeFile) = UpperCase(ExtractFileName(ExeName))) then Result := TerminateProcess(OpenProcess($0001, False, PE.th32ProcessID), 0); B:= Process32Next(ProcList, PE); end; CloseHandle(ProcList); end; //  procedure TForm1.RestartThisApp; begin ShellExecute(Handle, nil, PChar(Application.ExeName), nil, nil, SW_SHOWNORMAL); Application.Terminate; // or, if this is the main form, simply Close; end; 

    扎比克斯


    创建了一个地址为127.0.0.1的主机。

    它具有名为“传感器”的检测规则。

    图片

    图片

    数据元素的原型。

    图片

    原型触发器。

    图片

    添加到zabbix_agentd.conf

     UserParameter=sensors[*],/usr/lib/zabbix/alertscripts/sensors.sh UserParameter=crash[*],/usr/lib/zabbix/alertscripts/crash.sh $1 

    脚本本身:

    sensor.sh

     #!/bin/sh unset id unset res id=(`echo "select id FROM sensor WHERE type='1'" | mysql -uroot -p -D workdb -h 0.0.0.0 --default-character-set=utf8 2>/dev/null`) echo '{ "data": [' for (( count=1; count<${#id[@]}; count++ )) do res=(`echo "select name FROM sensor WHERE (type='1' and id='${id[$count]}') " | mysql -uroot -p -D workdb -h 0.0.0.0 --default-character-set=utf8 2>/dev/null `) r={${res[@]} l=${#r} res1=(`echo "select param FROM sensor WHERE (type='1' and id='${id[$count]}') " | mysql -uroot -p -D workdb -h 0.0.0.0 --default-character-set=utf8 2>/dev/null `) r1={${res1[@]} l1=${#r1} res2=(`echo "select ddename FROM sensor WHERE (type='1' and id='${id[$count]}') " | mysql -uroot -p -D workdb -h 0.0.0.0 --default-character-set=utf8 2>/dev/null `) r2={${res2[@]} l2=${#r2} res3=(`echo "select min FROM temp_${r2:17:l2} ORDER BY id DESC LIMIT 1 " | mysql -uroot -ps -D workdb -h 0.0.0.0 --default-character-set=utf8 2>/dev/null`) r3={${res3[@]} l3=${#r3} res4=(`echo "select max FROM temp_${r2:17:l2} ORDER BY id DESC LIMIT 1 " | mysql -uroot -p -D workdb -h 0.0.0.0 --default-character-set=utf8 2>/dev/null`) r4={${res4[@]} l4=${#r4} res5=(`echo "select cmin FROM temp_${r2:17:l2} ORDER BY id DESC LIMIT 1 " | mysql -uroot -p -D workdb -h 0.0.0.0 --default-character-set=utf8 2>/dev/null`) r5={${res5[@]} l5=${#r5}2>/dev/null res6=(`echo "select cmax FROM temp_${r2:17:l2} ORDER BY id DESC LIMIT 1 " | mysql -uroot -p -D workdb -h 0.0.0.0 --default-character-set=utf8 2>/dev/null`) r6={${res6[@]} l6=${#r6} res7=(`echo "select param FROM temp_${r2:17:l2} ORDER BY id DESC LIMIT 1 " | mysql -uroot -p -D workdb -h 0.0.0.0 --default-character-set=utf8 2>/dev/null`) r7={${res7[@]} l7=${#r7} s=$s'{ "{#SID}": "'${id[$count]}'", "{#SNAME}": "'${r:5:l}'", "{#SDDENAME}": "'${r2:17:l2}'" , "{#SPARAM}": "'${r7:7:l7}'", "{#SMIN}": "'${r3:5:l3}'", "{#SMAX}": "'${r4:5:l4}'", "{#SCMIN}": "'${r5:6:l5}'", "{#SCMAX}": "'${r6:6:l6}'" },' done a=${#s} b=${s: 0: $a-1} c=${#b} d=$b echo $d']}' 

    crash.sh

     #!/bin/sh a=$1 unset res res=(`echo "select flag, id_status FROM crash WHERE id_sensor='$a' ORDER BY id DESC LIMIT 1 " | mysql -uroot -p -D workdb -h 0.0.0.0 --default-character-set=utf8 2>/dev/null `) for (( count=2; count<${#res[@]}; count++ )) do s=$s' '${res[$count]} done b=${s:0:2} c=${s:3:4} if [ $b = 0 -a $c = 1 ] then echo 0 else echo 1 fi 

    然后通过zabbix,您可以发送到邮件和SMS等。

    结果


    结果是建立了一个企业温度监控系统,可以对当前和过去的事故进行回顾。

    图片

    阅读有关事故的更多信息。

    图片

    目前,增加了用于开/关门的传感器。

    优点:

    • 最低费用( 相对 )。
    • 加上业力(?)。
    • 监控已经运行了3年。

    缺点:

    • 故障点很多:控制器,网络, CoDeSys程序,虚拟机, MySQLIIS

    聚苯乙烯

    不要踢太多。 这是我的第一篇文章。

Source: https://habr.com/ru/post/zh-CN470822/


All Articles