最近忙着调试设备, 之前的软件没什么时间更新, 最近的主要精力还是放在工作上
这个软件就是我为了方便通过串口调试设备写的, 虽然市面上很多很多串口工具, 但串口上报数据的可读性不强, 因为我们调试的设备大多都是16进制报文, 对于年迈的我来说实在是记不住, 于是就做了这么个软件
打开软件, 是一个普普通通的串口工具, 基础能力只有发报文, 收报文, 没什么特别的
但是软件的强大之处在于, 可以通过加载python脚本的方式, 适配任何设备的任何协议
比如我今天调试 moudbus 协议的电表, 调试时需要将mac处理后组装进报文中, 我之前用的串口调试助手是无能无力的, 只能在其他程序中组装好报文黏贴过来再发送, 费时费力
但我们可以通过python脚本, 预先将组装报文的功能定义成按钮, 我们甚至可以创建动态表单来添加组装报文的参数,这样一来灵活性大大提高
而且我们调试另一种设备时, 无需再度修改脚本, 而是直接再写一个新的脚本, 定义为B插件, 程序可以通过插件切换的方式为每种设备做定制化协议
另外我可以将报文解析方式写在脚本中, 将报文解析成我们能看懂的中文, 而不是16进制报文
插件还可触发自动任务, 比如设备上电后, 对设备时间进行修正, 或是设备初始化配置等
至于更多功能, 大家可下载软件进行探索
当然, 由于时间紧迫,程序有些地方还没做, 但目前我调我们公司的设备够用了, 想来应该能满足大家需求, 大家在使用中若发现什么问题, 可以留言告诉我
插件示例:
import binascii
必须导入这个包
from super_serial_sdk.plugin_base import PluginBase
class ExamplePlugin(PluginBase):
def init(self):
super().init()
"""插件名称务必唯一"""
self.name = "示例插件"
self.initialized = False- self.main_window = None
- def send_data(self, fc, data, mode):
- """发送数据到串口, 只是简化了方法名, 与直接调用下面的方法一样"""
- self.main_window.send_to_serial(fc, data, mode)
- """收到串口上报的二进制字节后, 在此方法中进行逻辑处理, 如解析, 解析完成后可将消息添加到聊天框中"""
- def on_received_data(self, byte_data: bytes):
- """
- 接收到串口数据后由主程序调用
- 这里实现插件的处理逻辑
- """
- if not self.initialized:
- self.initialize()
- # 示例处理:将接收到的hex数据显示为可读格式
- try:
- # 如果设备报文编码是ascii用这套
- # start_index = byte_data.find(b'+') + 1
- # imei_bytes = byte_data[start_index:]
- # mes = imei_bytes.decode('ascii') # 将字节转换为10进制字符串
- # 如果设备报文是十六进制, 则注释上面那几行, 解除下面这三行注释
- hex_string = binascii.hexlify(byte_data).decode('utf-8')
- hex_string_separated = ' '.join([hex_string[i:i + 2] for i in range(0, len(hex_string), 2)])
- mes = hex_string_separated.replace(' ', '')
- """后续会开放获取主页面中的编码复选框, 用户可视情况选择写死还是根据复选框来判断编码,
- 但一般情况下, 插件针对某种设备编码是一样的, 所以仍推荐插件中写死编码格式"""
- # 显示到对话框中
- if self.main_window:
- self.main_window.add_message_for_plugin(f"[{self.name}] 接收到的数据: {mes}", 1)
- except Exception as e:
- print(f"[示例插件] 处理数据时出错: {e}")
- # 无需关注
- def initialize(self):
- """
- 插件初始化,如注册命令、设置参数等
- """
- print("示例插件已初始化")
- self.initialized = True
- # main_window = self.main_window
- def get_input_text(self):
- """获取主窗口中输入的文本"""
- return self.main_window.input_text.toPlainText()
- def clear_input_text(self):
- """清空主窗口输入框中的文本"""
- self.main_window.input_text.clear()
- def on_reset_button_clicked(self):
- # 处理重置按钮点击事件
- self.main_window.add_message_for_plugin("正在重置设备...", 2)
- # 执行重置逻辑...
- """插件卸载时调用, 插件开发者无需关注"""
- def cleanup(self):
- # 插件卸载时清理按钮
- if hasattr(self, 'main_window'):
- self.main_window.clear_plugin_buttons(self.get_name())
- #无需关注
- def get_name(self) -> str:
- """
- 返回插件名称,用于下拉菜单显示
- """
- return self.name
- # 创建一个动态表单(示例, 若需要输入参数, 可参考此方法创建动态表单)
- def getDict(self, data):
- print(12321321)
- self.main_window.add_message_for_plugin(f"[{self.name}] 接收到数据: {data}", 1)
- def create_dialog(self, params, callback):
- """创建弹窗"""
- self.main_window.createDialog(params, callback)
- """添加自定义按钮"""
- def set_main_window(self, main_window):
- """
- 设置主窗口引用,以便插件可以调用主窗口的方法
- """
- self.main_window = main_window
- print("已设置主窗口引用")
- # 添加一个自定义按钮
- # 添加自定义按钮
- buttons_config = [
- ("创建表单", self.createDialogTest, "b5"),
- ("拉闸", self.on_test_button_clicked, "b6"),
- ("解析输入框报文", self.jiexiInput, "b7")
- ]
- for text, callback, button_id in buttons_config:
- main_window.add_plugin_button(
- plugin_name=self.get_name(),
- button_text=text,
- callback=callback,
- button_id=button_id
- )
- # 解析输入框报文
- def jiexiInput(self):
- # 获取输入框数据
- text = self.get_input_text()
- # 清空输入框数据
- self.cleanup()
- # 这里可以写解析输入框数据的逻辑
- """这是点击事件的示例, 用户可参考本方法自行定义, 绑定到按钮上"""
- def on_test_button_clicked(self):
- zhiling = "ab ac ad 01 00 00 00 00" # 示例报文
- # 向串口发送报文的方法, 这里基本都是组装报文的, 如果是写死的报文, 就不必处理, 直接发送到主窗口
- # 这里可以做很多事情, 如将动态表单获取的数据组装进报文, 获取输入框中的数据等等
- zhiling = zhiling.replace(" ", "")
- mac = self.get_input_text().replace(" ", "")
- if mac is not None and len(mac) == 6:
- zhiling = zhiling.replace("abacfd", mac)
- # 组装, 加减替换, 怎么操作都可以
- # 发送报文到串口, 这里我封装了处理指令的方法, 第一个参数是 指令描述, 第二个参数是报文, 第三个参数是报文编码方式 hex或 ascii
- self.main_window.send_to_serial("拉闸", zhiling, "hex")
- def createDialogTest(self):
- params = [
- {
- "title": "command",
- "placeholder": "请输入命令"
- },
- {
- "title": "description",
- "placeholder": "请输入命令描述"
- },
- {
- "title": "interval",
- "placeholder": "请输入时间间隔(s)"
- }
- ]
- self.create_dialog(params, self.getDict)
复制代码
简单收发
通过插件实时解析报文
切换插件2
切换插件1
自动任务
|