使用python中的生成器实现周期性报文发送功能

使用python中的生成器实现周期性发送列表中数值的报文发送功能。

功能开发背景:提取cantest工具采集到的现场报文数据,希望使用原始的现场数据模拟验证程序现有逻辑,需要开发一个工具能够自动按照报文发送周期依次发送采集到的报文数据中的一个数值。

功能开发需求:多个报文发送对象共用同一个报文发送线程,多个对象间的报文发送周期不同,多个对象间的总报文发送数据长度不同,能够允许报文发送过程中断及恢复某个对象的报文发送。

功能开发实现逻辑:在固定发送对象某个数值的基础程序版本上增加新的功能,考虑使用python中生成器实现周期性提取对象数值发送报文的功能。

目前只需要发送两个对象的报文数据,先定义两个使用yield生成器:

    def yield_item_value_1(self):
        item_value_list = self.item_value_dict[item_list[0]]
        for i in range(len(item_value_list)):
            yield item_value_list[i]

    def yield_item_value_2(self):
        item_value_list = self.item_value_dict[item_list[1]]
        for i in range(len(item_value_list)):
            yield item_value_list[i]

报文发送线程中的run()函数:

    def run(self):
        # 实时更新item的被选状态
        self.get_checkbox_res_func()
        # 获取每个对象的实际物理值
        self.get_item_value_dict()
        self.item1_value_func = self.yield_item_value_1()
        self.item2_value_func = self.yield_item_value_2()
        while self.Flag:
            if any(msg_send_flag_dict.values()):
                # 每隔second秒执行func函数
                timer = Timer(0.01, self.tick_10ms_func)
                timer.start()
                self.send_working_msg(self.working_can_device, self.working_can_channel)
                timer.join()
            else:
                mes_info = "Goodbye *** 自动发送所有报文数据结束!!!"
                toastone = wx.MessageDialog(None, mes_info, "信息提示",
                                            wx.YES_DEFAULT | wx.ICON_QUESTION)
                if toastone.ShowModal() == wx.ID_YES:  # 如果点击了提示框的确定按钮
                    toastone.Destroy()  # 则关闭提示框
                break

报文周期性发送函数:

    def send_working_msg(self, can_device, device_id):
        for idx in range(len(item_list)):
            if msg_send_flag_dict[item_list[idx]] == 1:
                msg_id_idx = msg_operation_list.index("报文ID") - 1
                msg_id = eval(str(self.operation_dict[item_list[idx]][msg_id_idx]).strip())
                # 获取报文发送帧类型
                msg_type_idx = msg_operation_list.index("帧类型") - 1
                msg_type = str(self.operation_dict[item_list[idx]][msg_type_idx])
                msg_type = 1 if msg_type == "扩展帧" else 0
                # 获取报文发送周期
                msg_cycle_idx = msg_operation_list.index("周期(ms)") - 1
                msg_cycle = int(self.operation_dict[item_list[idx]][msg_cycle_idx])
                send_cycle = msg_cycle / 10
                if msg_tick_10ms_dict["_".join(["tick", "10ms", str(idx)])] >= send_cycle:
                    # 开始喂值
                    if idx == 0:
                        try:
                            item_phyValue = next(self.item1_value_func)
                        except StopIteration:
                            msg_send_flag_dict[item_list[idx]] = 0
                            continue
                    else:
                        try:
                            item_phyValue = next(self.item2_value_func)
                        except StopIteration:
                            msg_send_flag_dict[item_list[idx]] = 0
                            continue
                    msg_data = self.get_item_msg(item_list[idx], item_phyValue)
                    if send_msg(msg_id, msg_type, msg_data, can_device, device_id, 0):
                        print("发送报文成功")
                        # print("msg_data", msg_data)
                        msg_tick_10ms_dict["_".join(["tick", "10ms", str(idx)])] = 0
                    else:
                        pass
                        # print("发送报文失败")
                        # mes_info = "发送报文失败"
                        # toastone = wx.MessageDialog(None, mes_info, "信息提示",
                        #                             wx.YES_DEFAULT | wx.ICON_QUESTION)
                        # if toastone.ShowModal() == wx.ID_YES:  # 如果点击了提示框的确定按钮
                        #     toastone.Destroy()  # 则关闭提示框

功能实现逻辑的待优化点:存在多个对象就需要定义多个存储报文数据的生成器。

上述功能实现逻辑优化如下:

    def set_yield_func(self):
        item_yield_func_dict = dict()
        for i in range(len(item_list)):
            item_yield_func_dict[item_list[i]] = self.yield_item_value(i)
        return item_yield_func_dict

    def yield_item_value(self, item_idx):
        item_value_list = self.item_value_dict[item_list[item_idx]]
        for i in range(len(item_value_list)):
            yield item_value_list[i]

报文发送线程的run()函数中调用这个存储对象报文发送数据生成器的字典item_yield_func_dict:

    def run(self):
        # 实时更新item的被选状态
        self.get_checkbox_res_func()
        # 获取每个对象的实际物理值
        self.get_item_value_dict()
        self.item_yield_func_dict = self.set_yield_func()
        …………

从存储每个对象生成器的字典item_yield_func_dict中获取生成器对象:

                    try:
                        item_phyValue = next(self.item_yield_func_dict[item_list[idx]])
                    except StopIteration:
                        msg_send_flag_dict[item_list[idx]] = 0
                        continue
### 使用LSTM神经网络实现挖掘机报文行为识别 #### 数据预处理 为了有效利用LSTM进行挖掘机报文行为识别,首先需要对原始数据进行充分的预处理。由于传感器采集的数据可能存在时间戳不同步、时钟漂移等问题[^3],因此建议采取如下措施: - **清洗异常**:去除明显错误或缺失的时间戳记录; - **同步多源数据流**:确保来自多个传感器的数据能够在相同的时间刻度上对齐。 接着,针对挖掘机动态过程中产生的大量实时通信报文,应实施标准化操作,比如将所有数型字段缩放到0至1之间,这有助于加速模型收敛并提高泛化能力。 #### 特征工程设计 考虑到挖掘机工作状态复杂多样,在构建输入向量时不仅要考虑单一时刻的状态描述符,还应该引入历史上下文信息作为辅助判断依据。具体做法可参照以下几点: - 提取每条CAN总线消息的关键属性(ID, DLC, Data Bytes),形成基础维度集合; - 计算相邻两条记录间的时间间隔Δt,反映动作发生的频率特性; - 统计一段时间窗口内的特定事件发生次数,刻画周期性的作业模式; 上述过程生成的新特征矩阵应当具备合理的长度T以及固定的宽度F,以便于后续送入循环层计算。 #### 构建LSTM架构 基于前述准备好的序列化样本集,下面给出一个简单的Keras框架下定义LSTM结构的例子: ```python from tensorflow.keras.models import Sequential from tensorflow.keras.layers import LSTM, Dense, Dropout model = Sequential([ LSTM(units=64, input_shape=(T, F), return_sequences=True), Dropout(0.2), LSTM(units=32), Dropout(0.2), Dense(num_classes, activation='softmax') ]) ``` 这里`units`参数表示隐藏节点数,而`input_shape`则对应着前面提到过的(T,F),其中T代表时间轴上的跨度大小,F则是单帧内含有的要素数目。最后一层采用Softmax函数来完成类别概率分布估计的任务。 #### 模型训练配置 最后一步就是设定损失函数与优化算法,并启动迭代更新流程直至满足停止条件为止。对于分类问题而言,交叉熵通常是一个不错的选择;与此同时Adam以其良好的自适应性和稳定性著称,适合作为主导求解器。 ```python model.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['accuracy']) history = model.fit(X_train, y_train, epochs=EPOCHS, batch_size=BATCH_SIZE, validation_split=0.2) ``` 通过以上步骤即可搭建起一套完整的基于LSTM技术路线的行为检测系统原型版本。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

草莓仙生

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值