我尝试使用 python 的串行模块(以及带有光学读取头的 USB 到串行转换器 (FTDI)。它使用 IEC 62056-21 中描述的协议)读取公用事业仪表。已知该设置可与其他软件一起使用。
在以 300bit/s 发送 b'/?!\r\n' 后,仪表会响应制造商、固件版本和切换通信速度的建议。因此程序确认速度并请求“数据读出模式” <ack>050<CR><LF>
,其中 5 是速度 9600。然后程序切换波特率。
一切都很好,直到波特率切换。正常行为是仪表发送以 开头<STX>
和结尾的数据帧,<ETX>
并包含几行以 结尾的文本<CR><LF>
。
但是缺少大约 9 行文本。该程序在第 9 行或第 10 行中间的某个地方赶上。有时我会得到一长串空字节。
这是代码(我留下了一些测试留下的评论):
import serial
import re
from time import sleep
def readframe():
buf=b''
while (buf == b'' or buf[-1] != b'\x03'):
buf+=ser.read(1)
print(buf)
return buf
ser =serial.Serial(port=PORT,baudrate=300,bytesize=serial.SEVENBITS,parity=serial.PARITY_EVEN,stopbits=serial.STOPBITS_ONE,timeout=5)
repeat=True
while repeat:
ser.setBaudrate(300)
sleep(1)
ser.write(b'/?!\r\n')
response=ser.readline()
print(response)
pattern = re.compile(r'/(...)(\d)\\@(.*)')
m=pattern.match(response.decode("ASCII"))
if not m:
repeat= True
else: repeat=False
manufacturer,speed,version=m.group(1,2,3)
speedcode=int(speed)
baudrates=(300,600,1200,2400,4800,9600,19200)
s=bytes([6,48,48+speedcode,48,13,10]) #option request data readout mode
print(s)
ser.write(s)
sleep(1)
ser.flush()
#ser.close()
#ser =serial.Serial(port=PORT,baudrate=baudrates[speedcode],bytesize=7,parity='E',stopbits=1,timeout=5)
ser.setBaudrate(9600)
#sleep(1)
#ser.setTimeout=None
frame=readframe()
ser.close()
我尝试了很多事情,比如刷新缓冲区、以不同的速度关闭和重新打开、插入暂停、读取行而不是字节、使用 inWaiting() 等等。我怀疑在切换波特率时没有缓冲一段时间,所以我丢失了一些数据。顺便说一句,我在 Windows 上使用它,Winpython 发行版(在我的工作场所,这就是为什么)串行模块的版本是 2.7。
下面是一个应该如何沟通的例子(带有时间和方向的沟通记录部分用德语)。使用我的程序,我只能从 0.2.0 的行中收到:
Komm: 11:29:57,62 -- Teilnehmer-Name = Lokale Schnittstelle
Komm: 11:29:58,34 -- Schnittstelle = SERIELL über COM-Port Nr: 4
Komm: 11:29:58,35 -- Komm Settings = 300,7,E,1
Send: 11:29:58,57 -- /?!<CR><LF>
Recv: 11:29:59,80 -- /ABB5\@V4.50 <CR><LF>
Send: 11:30:00,01 -- <ACK>050<CR><LF>
Komm: 11:30:00,31 -- Komm Settings = 9600,7,E,1
Recv: 11:30:00,57 -- <STX>0.0.0(00491465)<CR><LF>
Recv: 11:30:00,60 -- 0.9.1(112957)<CR><LF>
Recv: 11:30:00,66 -- 1.6.1(0000.00*kW)(0000000000)<CR><LF>
Recv: 11:30:00,73 -- 1.6.1*04(0000.00)(0000000000)<CR><LF>
Recv: 11:30:00,79 -- 1.6.2(0000.00*kW)(0000000000)<CR><LF>
Recv: 11:30:00,88 -- 1.6.2*04(0000.00)(0000000000)<CR><LF>
Recv: 11:30:00,91 -- 1.8.1(00000000*kWh)<CR><LF>
Recv: 11:30:00,94 -- 1.8.1*04(00000000)<CR><LF>
Recv: 11:30:00,97 -- 1.8.2(00000000*kWh)<CR><LF>
Recv: 11:30:01,02 -- 1.8.2*04(00000000)<CR><LF>
Recv: 11:30:01,05 -- 0.2.0(05F1)<CR><LF>
Recv: 11:30:01,08 -- !<CR><LF>
Recv: 11:30:01,09 -- <ETX>i Soll: i
Komm: 11:30:01,41 -- Seriell-Status = Geschlossen
感谢您的阅读,非常感谢您的帮助!