Tcp方式采集CNC兄弟設備數據


先說下為了采集CNC兄弟設備的數據可謂是一波三折。

因為首次接觸brother設備(CNC)是直接在設備上設置IP、用戶名、密碼,然后直連PC,用Ftp可以查看和下載CNC brother設備里的數據庫文件(NC文件)。其實我們最關心的是CNC的“工件計數”,經確認CNC可以實時的將計數寫入WKCNTR.NC文件,現在理論上已經沒有問題了,可是后面還有很多坑。

我們剛開始是用dotnet來做的,寫好demo程序連接brother測試,可是怎么都無法下載,一直提示“基礎連接關閉,協議沖突”之類的異常,查資料發現下載后文件保存的是在中文目錄下,立馬移動文件保存位置保證都在英文目錄下,還真的好了!這下太好了。

后來我們就按照這個demo開始編寫正式代碼,結果怎么都無法下載,試了好多台設備都不行,真的莫名其妙、一頭霧水。並且提示的異常都是“基礎連接關閉,協議沖突”,這次可不是中文目錄的問題了。於是就在google上查資料,各種方法都試了,結果還是不行,不能一頭撞死南牆,最后放棄了。

靈光一閃,為什么不用python試試呢,於是隨手寫了個demo程序,也就有了上一篇隨筆《遠程監控顯示brother數控機床數據》,結果真的好了很輕松就搞定了,並且所有的16台CNC brother設備都可以正常采集數據,按照30秒頻率將采集到的數據寫入數據庫(mariadb),別慌到這里才是歡喜了一半。

真正運行起來穩定性可沒那么好,剛開始16台都好好的,沒過1天就有一台出現問題,現象是可以ping通,可以連接到設備,也可以登錄,還可以列出設備上所有的文件,但就是無法下載,結果就是超時。后來經過不斷調查發現,如果我同時開兩個連接都訪問這個文件,那么有一個失敗超時,另一個居然可以下載讀取,太奇妙了,沒找到好的辦法之前就用這個下下策吧。結果第三天又有一台出現問題,可以ping通,就不讓連接了,就好像brother設備上沒有開啟ftp服務一樣。本來好好的,就出現這種莫名其妙的問題,到這里簡直郁悶到極點。

總之對這種方案不滿意,也考慮到還有4台brother CNC設備沒有ftp服務可以利用,於是找設備科找brother的操作手冊參考書,看是否有其他方法。結果在第五章關於通信,還真的找到了,Tcp通訊協議在眼前一亮,再細看具體的指令協議,只能看懂指令必須以%開始,以%結束,里面的就不懂了。只好再撥打供應商電話,說明情況請求兩個%之間的內容怎么寫,供應商回復:%CLOD    WKCNTR     + 換行 + 00%

趕緊將指令貼在網絡調試助手里,隨便連接一台brother,結果真的返回數據了,目標工件計數就在返回的數據里面,接下來的就是解析返回字符串了,這都不是問題。結果不僅16台新的brother設備可以采集到數據,4台老的也可以,並且效率要比ftp要高很多。

下面就把最重要的部分代碼貼出來:

 1         private int GetCncDada(string ip)
 2         {
 3             TcpClient client = new TcpClient();
 4             int cnc = -1;
 5             try
 6             {
 7                 client.Connect(new IPEndPoint(IPAddress.Parse(ip), 10000));
 8                 if (client.Connected)
 9                 {
10                     var networkStream = client.GetStream();
11                     var buffer = Encoding.UTF8.GetBytes("%CLOD    WKCNTR    \r\n00%");
12                     networkStream.Write(buffer, 0, buffer.Length);
13                     networkStream.ReadTimeout = 3000;
14                     var readBuffer = new byte[1024];
15                     var len = networkStream.Read(readBuffer, 0, readBuffer.Length);
16                     var result = Encoding.UTF8.GetString(readBuffer, 0, len);
17                     //_logger.Debug(result);
18                     networkStream.Close(3000);
19 
20                     var lines = result.Split(new[] { Environment.NewLine }, StringSplitOptions.None);
21                     foreach (var line in lines)
22                     {
23                         if (line.StartsWith("A01"))
24                         {
25                             var fields = line.Split(',');
26                             _logger.Debug("工件計數 = " + fields[2].Trim());
27                             cnc = Convert.ToInt32(fields[2].Trim());
28                             break;
29                         }
30                     }
31                 }
32                 return cnc;
33             }
34             catch (Exception err)
35             {
36                 _logger.Error(err);
37                 return cnc;
38             }
39             finally
40             {
41                 if (client.Connected)
42                 {
43                     client.Close();
44                 }
45             }
46 
47         }

 以下是python版的代碼:

 1 # coding: utf8
 2 import socket
 3 import pymysql
 4 import os
 5 import time
 6 cnc_config = [('J01', "192.168.1.40"), ('J02', "192.168.1.41"), ('J03', "192.168.1.42"), ('J04', "192.168.1.43"),
 7               ('J22', "192.168.1.44"), ('J21', "192.168.1.45"), ('J20', "192.168.1.46"), ('J19', "192.168.1.47"),
 8               ('J18', "192.168.1.48"), ('J17', "192.168.1.49"), ('J16', "192.168.1.50"), ('J15', "192.168.1.51"),
 9               ('J14', "192.168.1.52"), ('J13', "192.168.1.53"), ('J12', "192.168.1.54"), ('J11', "192.168.1.55"),
10               ('J37', "192.168.1.56"), ('J36', "192.168.1.57"), ('J35', "192.168.1.58"), ('J34', "192.168.1.59")]
11 
12 
13 def get_from_brother(ip='127.0.0.1', port=10000):
14     client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
15     client.settimeout(3)
16     try:
17         client.connect((ip, port))
18         instruct = '%CLOD    WKCNTR    ' + os.linesep + '00%'
19         client.send(instruct.encode())
20         lines = client.recv(1024).decode().split(os.linesep)
21         lines = [line for line in lines if line.startswith('A01')]  # 選出以A01開頭的行
22         fields = lines[0].split(',')  # 拆分出字段,第3個字段就是目標[工件計數]
23         return int(fields[2].strip())
24     except Exception as e:
25         print(ip, e)
26         return -1
27     finally:
28         client.close()
29 
30 
31 def save_db(name='J44', qty=-1):
32     try:
33         conn = pymysql.Connect(user='root', password='1234', database='dademes', charset='utf8')
34         cus = conn.cursor()
35         if qty == -1:
36             cus.execute('update kbequipment set running=%s where name=%s', ('關機', name))
37         else:
38             cus.execute('update kbequipment set running=%s, status=%s where name=%s', ('正常', qty, name))
39         conn.commit()
40         cus.close()
41         conn.close()
42     except Exception as e:
43         print('機台號=%s保存數據異常,%s' % (name, e))
44 
45 if __name__ == '__main__':
46     while True:
47         try:
48             for cnc_name, ip in cnc_config:
49                 print('正在讀取機台號=%s,ip=%s' % (cnc_name, ip))
50                 qty = get_from_brother(ip=ip)
51                 save_db(qty=qty, name=cnc_name)
52         except Exception as e:
53             print('__main__', e)
54         finally:
55             print('CNC數據讀取完畢...30秒后再次讀取...')
56             time.sleep(30)

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM