最后由 Tabing010102 更新于 2025年4月28日
契机是2020年1月的华为UPS2000-G-1KRTS电池挂了报警,但是没有远程手可以关掉报警,于是就翻出来协议文档看能否远程关掉
华为的文档链接:UPS2000-(1kVA-3kVA) Modbus协议开发指南 – Huawei
由于笔者对modbus并不熟,于是随机去GitHub找了个开源的GUI轮椅,最后找到了OpenModScan,这玩意应该可以发送自定义指令。
首先设置连接信息,根据文档,USB/RS232的传输速率是9600bps
关闭报警声音主要查看的是文档中的“配置与控制信号表”部分,这里对应的地址是N1046
(N
在单机时为为1
,因此应该是11046
),写该值的指令应该为“01 06 2B 26 00 01 A0 25
”,其中“01 06
”代表写设备1
,2B 26
为写入地址11046
的16进制表示,00 01
为写入的值(根据文档,1
代表“是”),最后的A0 25
为计算的crc值。
OpenModScan设置完后默认只有读地址值,下面为自定义信息(User Msg)的操作流程,以读取单机ECO的变量的值为例:


如果OpenModScan报“Resource Busy”之类的错误,可以检查是不是有其他程序(如nut)等占用串口,我这里就是因为nut driver占用串口,临时使用了sudo systemctl stop nut-driver@ups
停止,其中ups
是设置的设备名
(然而由于单机ECO无法远程写,而又恰好忘记给新到的机器设置,最后还是远程手了)
附一个计算指令crc的py石山:
def modbus_crc(data_hex):
data_bytes = bytes.fromhex(data_hex)
crc = 0xFFFF
for byte in data_bytes:
crc ^= byte
for _ in range(8):
if crc & 0x0001:
crc = (crc >> 1) ^ 0xA001
else:
crc >>= 1
crc &= 0xFFFF
crc_low = crc & 0xFF
crc_high = (crc >> 8) & 0xFF
return f"{crc_low:02X}{crc_high:02X}"
while True:
data = input("Input data: ")
print(f"crc = {modbus_crc(data)}")
# Read beep (11046)
# 01 03 2B 26 00 01 6C 25
# Write beep = 0
# 01 06 2B 26 00 01 A0 25
# Read ECO (11031)
# 01 03 2B 17 00 01 3D EA
# Read Auto Start (11044)
# 01 03 2B 24 00 01 CD E5
# Write Auto Start = 1
# 01 06 2B 24 00 01 01 E5
Views: 1