三菱FX5U 支持SMTP 协议,可利用Python 的Socket 通信按照三菱的协议格式进行通信,上位机作为客户端,PLC作为服务器
"""
author: alai
date:2018/05/01
"""
import socket
import time
import xlwt,xlrd,struct
from xlutils.copy import copy
import sys
import re,os,sys
data="ok"
class TcpThread(QThread):
trigger = pyqtSignal(str)
trigger1=pyqtSignal(str)
def __int__(self):
super(TcpThread, self).__init__()
# 分离出一个函数用于循环tcp 重连
def doConnect(self):
with open('IP_Address.txt', 'r')as fn:
s1 = fn.read()
host = ''.join(re.findall(r'IP:(.*)', s1)) # 服务器IP地址取出来,并转成字符串
port = int(''.join(re.findall(r'PORT:(.*)', s1))) # 从文本中提取端口号转成整数
BUFFSIZE = int(''.join(re.findall(r'BUFFSIZE:(.*)', s1))) # 从文本中提取字符长度转整数
ADDRESS = (''.join(re.findall(r'ADDRESS:(.*)', s1))) # 从文本中提取字符长度转整数
LENGTH = (''.join(re.findall(r'LENGTH:(.*)', s1))) # 从文本中提取字符长度转整数
print(host,port,ADDRESS,LENGTH)
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
sock.connect((host, port))
print("connect is ok")
except:
print('fail to setup socket connection')
return sock, BUFFSIZE,ADDRESS,LENGTH
# 发送数据
def tcpClient(self):
global glb_tag
glb_tag=0
global glb_data
sockLocal, BUFFSIZE,ADDRESS,LENGTH = self.doConnect()
while True:
# 等于0,那么一直查询
if glb_tag==0:
self.data1 = '500000FF03FF000018000004010000D*00'
self.data = self.data1+ADDRESS+LENGTH
# print(self.data)
try:
sockLocal.send(self.data.encode())
except socket.error:
print("\r\nsocket error,do reconnect ")
sockLocal.close()
time.sleep(1)
sockLocal, BUFFSIZE = self.doConnect()
except:
sockLocal.close()
print("other error")
time.sleep(1)
sockLocal, BUFFSIZE = self.doConnect()
time.sleep(0.5)
str1 = sockLocal.recv(BUFFSIZE).decode()
if str1[22:26]=="0001":
glb_tag=1
# 等于1,写入并等待结果
elif glb_tag==1:
# 发射信号,连接到datadisplay
self.trigger.emit(str1)
self.data1 = '500000FF03FF00001C000014010000D*00499900010001'
try:
sockLocal.send(self.data1.encode())
except socket.error:
print("\r\nsocket error,do reconnect ")
sockLocal.close()
time.sleep(1)
sockLocal, BUFFSIZE = self.doConnect()
except:
sockLocal.close()
print("other error")
time.sleep(1)
sockLocal, BUFFSIZE = self.doConnect()
time.sleep(0.3)
str1 = sockLocal.recv(BUFFSIZE).decode()
# print(glb_str1[16:18])
# 如果返回的数据长度是对应长度,那么不再写
if str1[16:18]=="04":
glb_tag = 0
# 等于2,PLC 数据查询
elif glb_tag==2:
self.data1='500000FF03FF000018000004010000D*00'
# 先转成字符串,然后填满四位
self.data2=("".join(re.findall("[D|d](\d+)",glb_data)))
self.data3=self.data2.zfill(4)
# print(glb_data+str(12))
# print(self.data2)
self.data=self.data1+self.data3+"0010"
# print(self.data)
try:
sockLocal.send(self.data.encode())
except socket.error:
print("\r\nsocket error,do reconnect ")
sockLocal.close()
time.sleep(1)
sockLocal, BUFFSIZE = self.doConnect()
except:
sockLocal.close()
print("other error")
time.sleep(1)
sockLocal, BUFFSIZE = self.doConnect()
time.sleep(0.3)
glb_tag = 0
str1 = sockLocal.recv(BUFFSIZE).decode()
# print(glb_str1)
self.trigger1.emit(str1)
# PLC数据写入
elif glb_tag==3:
# print("li")
self.data1='500000FF03FF00001C000014010000D*00'
# 先转成字符串,然后填满四位
self.data2=("".join(re.findall("(\d+)=",glb_data))).zfill(4)
self.data3=("".join(re.findall("=(\d+)",glb_data))).zfill(4)
# print(hex(int(self.data3)))
# 先转成16进制,然后匹配出来,舍掉0x,然后转成字符串,然后填满0
self.data4=("".join(re.findall("0x(\w+)",hex(int(self.data3))))).zfill(4)
self.data=self.data1+self.data2+"0001"+self.data4
# print(self.data)
try:
sockLocal.send(self.data.encode())
except socket.error:
print("\r\nsocket error,do reconnect ")
sockLocal.close()
time.sleep(1)
sockLocal, BUFFSIZE = self.doConnect()
except:
sockLocal.close()
print("other error")
time.sleep(1)
sockLocal, BUFFSIZE = self.doConnect()
time.sleep(0.3)
str1 = sockLocal.recv(BUFFSIZE).decode()
glb_tag = 2
# glb_str1 = sockLocal.recv(BUFFSIZE).decode()
def run(self):
#必须从run开始启动程序
# global data
self.tcpClient()