三菱PLCの「手順あり」とかいうクソに対応した

お疲れ様です。三菱PLCのソケット通信で「手順あり」「Keep-Alive使用」とかいう特級のクソにぶち当たったので、備忘録的にPythonでの実装をメモしておきます。

import socket

#PLCだと送受のポートが分かれてることがあるのでこんな感じになる
ip = "192.168.3.39"#IP,ポートなどは適当
port = 10000
port1 = 10001

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s1 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET,socket.SO_KEEPALIVE,1)#KEEP ALIVEを有効化
s1.setsockopt(socket.SOL_SOCKET,socket.SO_KEEPALIVE,1)#KEEP ALIVEを有効化
s.connect((ip, port))
s1.connect((ip, port1))

print("Connected")
#無限ループでまちうけ
#今回は 受信待機→受信→サブヘッダ応答→受信データに対して64byteのデータで返信 を想定
while True:
	receive = s.recv(4096)
	data1_1=bytearray(bytes(receive))
	print(data1_1)
	if receive != b"" and data1_1[0] == 0x60:#無限ループにするとウンコpythonが受信待機してくれなくなって無限にprintしやがるので回避。あとPLCとかいう汚物も手順ありでゴミを送ってくるので回避
		data2_1=bytearray([0xe0,0x00]) #サブヘッダ返答 これが無いと手順あり通信がうまくいかない くたばれ三菱
		s.sendall(data2_1)
		print(data2_1)
		data3_1=bytearray([0]*132)#64バイトのデータ+手順有に必要なゴミどもの送受を想定
		#print(data3_1)
		if data1_1[4]==0x31 and data1_1[5]==0x34:
			data3_1[0]=0x60#ヘッダ 手順ありだと必須
			data3_1[1]=0x00#ヘッダ 手順ありだと必須
			data3_1[2]=0x40#データ長
			data3_1[3]=0x00#データ長※データ長はデータ長までの部分を除いてフッタまでを含めた大きさ この場合10進数で64(byte)の意味。これも手順有では必須
			#あとはbytearrayで作った配列に送受したいデータをぶち込んでどうぞ
			s1.sendall(data3_1)
			print(data3_1)

s.close()

print("END")

サブヘッダとかヘッダってやつが難解で、三菱のマニュアルにちょこーーーーーーーーーーーーーーーーとしか書いてないんですよね。絶対PLCのLANカード買わせるためにあんな書き方したでしょ。

いいなと思ったら応援しよう!