Qt实现Kermit协议(二)

3 实现

3.1 Kermit

该模块是Kermit协议实现类。

3.1.1 Kermit定义

/*|<------Included in CHECK----->||                |+------+-----+-----+------+------+- - -+-------+| MARK | LEN | SEQ | TYPE | DATA | CHECK |<terminator>+------+-----+-----+------+------+- - -+-------+|            ||<--LEN-32 characters-->|MARK A real control character, usually CTRL-A.LEN One character, length of remainder of packet + 32, max 95SEQ One character, packet sequence number + 32, modulo 64TYPE One character, an uppercase letterCHECK One, two, or three characters, as negotiated.<terminator> Any control character required for reading the packet.
*/class Kermit
{
public:Kermit();enum Code {NUL = 0x00,MARK = 0x01,END_CHAR = 0x0D};enum Type {S = 0x53, //Send Initiation. I’m about to send files, and here are my parameters.F = 0x46, //File Header, the name of the file which is about to come.D = 0x44, //File DataZ = 0x5A, //End of File.B = 0x42, //Break Transmission, end of transaction.Y = 0x59, //AcknowledgmentN = 0x4E, //Negative AcknowledgmentE = 0x45  //Fatal Error};enum Size {MinLen = 3,MaxLen = 94,MaxSize = MaxLen + 6};enum State {SSNUL = 0,SSINT = 1,SSFIL = 2,SSDAT = 3,SSEND = 4,SSBRK = 5};protected:virtual void on_init(int seq, const char* data, int size);virtual void on_file_header(int seq, const char* data, int size);virtual void on_data(int seq, const char* data, int size);virtual void on_end(int seq, const char* data, int size);virtual void on_break(int seq, const char* data, int size);virtual void on_ack(int seq, const char* data, int size);virtual void on_nack(int seq, const char* data, int size);virtual void on_error(int seq, const char* data, int size);virtual int write(char const *data, int size) = 0;virtual int read(char *data, int size) = 0;virtual char getc() = 0;protected:void send_init();void send_data(int n, const char* data, int len);void send_end(int n);void send_break(int n);void send_ack(int n);void send_nack(int n);bool recv_packet();void resend();int encode(char a, char* data);int decode(const char* data, char& a);
private:int tochar(int x) { return x + 32; }int unchar(int x) { return int(x - 32); }int ctl(int x) { return x^64; }int check(const char* p);int check(int sum, const char* begin, const char* end);int spack(char type, int n, const char* data, int len);bool send_packet(const char* data, int size);
private:char data_[MaxSize];int maxl = MaxLen;int time = 10;int npad = 0;int padc = 64;int eol = END_CHAR;char qctl = '#';int last_size = 0;
};

虚函数列表:

  • on_init 处理发送标识包(包括最大数据包size/time/npad/padc/eol/qctl)并发送出应答包。
  • on_file_header 处理文件头包
  • on_data 处理文件数据包
  • on_end 处理文件结束包
  • on_break 处理中断传输包
  • on_ack 处理应答包
  • on_nack 处理否定应答包
  • on_error 处理错误包
  • write 向串口写数据
  • read 从串口读数据
  • getc 从串口读取一个字符

函数列表:

  • send_init 发送发送标识包
  • send_data 发送文件数据包
  • send_end 发送文件结束包
  • send_break 发送中断传输包
  • send_ack 发送应答包
  • send_nack 发送否定应答包
  • recv_packet 接收数据包并分发处理
  • resend 重发数据
  • encode 编码数据
  • decode 解码数据

3.1.2 Kermit实现

  • on_init/on_file_header/on_data/on_end/on_break/on_ack/on_nack/on_error
void Kermit::on_init(int /*seq*/, const char* data, int size)
{if(size > 0)maxl  = unchar(data[0]);if(size > 1)time  = unchar(data[1]);if(size > 2)npad  = unchar(data[2]);if(size > 3)padc  = unchar(data[3]);if(size > 4)eol  = unchar(data[4]);if(size > 5)qctl  = data[5];char d[6];d[0] = tochar(maxl);d[1] = tochar(time);d[2] = tochar(npad);d[3] = tochar(padc);d[4] = tochar(eol);d[5] = qctl;spack(Y, 0, d, sizeof (d));
}void Kermit::on_file_header(int seq, const char* data, int size) {std::cout << "on_file_header(" << seq << "," << std::string(data, size) << std::endl;
}void Kermit::on_data(int seq, const char* data, int size) {std::cout << "on_data(" << seq << "," << std::string(data, size) << std::endl;
}void Kermit::on_end(int seq, const char* data, int size) {std::cout << "on_end(" << seq << "," << std::string(data, size) << std::endl;
}void Kermit::on_break(int seq, const char* data, int size) {std::cout << "on_break(" << seq << "," << std::string(data, size) << std::endl;
}void Kermit::on_ack(int seq, const char* data, int size)
{if(seq != 0)return;if(size > 0)maxl  = unchar(data[0]);if(size > 1)time  = unchar(data[1]);if(size > 2)npad  = unchar(data[2]);if(size > 3)padc  = unchar(data[3]);if(size > 4)eol  = unchar(data[4]);if(size > 5)qctl  = data[5];
}void Kermit::on_nack(int seq, const char* data, int size) {std::cout << "on_nack(" << seq << "," << std::string(data, size) << std::endl;
}void Kermit::on_error(int seq, const char* data, int size) {std::cout << "on_error(" << seq << "," << std::string(data, size) << std::endl;
}
  • send_init/send_data/send_end/send_break/send_ack/send_nack/resend
void Kermit::send_init()
{char data[6];data[0] = tochar(maxl);data[1] = tochar(time);data[2] = tochar(npad);data[3] = tochar(padc);data[4] = tochar(eol);data[5] = qctl;spack(S, 0, data, sizeof (data));
}void Kermit::send_data(int n, const char* data, int len) {spack(D, n, data, len);
}void Kermit::send_end(int n) {spack(Z, n, nullptr, 0);
}void Kermit::send_break(int n) {spack(B, n, nullptr, 0);
}
void Kermit::send_ack(int n) {spack(Y, n, nullptr, 0);
}void Kermit::send_nack(int n) {spack(N, n, nullptr, 0);
}void Kermit::resend() {send_packet(data_, last_size);
}

构造对应类型数据包并发送。

  • recv_packet
bool Kermit::recv_packet()
{char ch = getc();if(ch != MARK)return false;ch = getc();int length = unchar(ch);if(length < MinLen)return false;//SEQ  TYPE DATA CHECK <terminator>std::vector<char> data(length + 1, 0);if(read(data.data(), data.size()) != static_cast<int>(data.size()))return false;if(data.back() != eol)return false;uint16_t  old_check = unchar(data.at(data.size() - 2));uint16_t  new_check = check(ch, data.data(), data.data() + data.size() - 2);if(old_check != new_check)return false;char type = data[1];if(type == S)on_init(unchar(data[0]), data.data() + 2, data.size() - 4);else if(type == F)on_file_header(unchar(data[0]), data.data() + 2, data.size() - 4);else if(type == D)on_data(unchar(data[0]), data.data() + 2, data.size() - 4);else if(type == Z)on_end(unchar(data[0]), data.data() + 2, data.size() - 4);else if(type == Y)on_ack(unchar(data[0]), data.data() + 2, data.size() - 4);else if(type == N)on_nack(unchar(data[0]), data.data() + 2, data.size() - 4);else if(type == E)on_error(unchar(data[0]), data.data() + 2, data.size() - 4);return true;
}

接收数据包并校验,根据对应类型调用处理相应处理函数。

  • encode/decode
int Kermit::encode(char a, char* data)
{int a7 = a & 127;int size = 0;if (a7 < 32 || a7 == 127){data[size++] = qctl;a = ctl(a);}else if (a7 == qctl){data[size++] = qctl;}data[size++] = a;data[size] = '\0';return size;
}int Kermit::decode(const char* data, char &b)
{const char *d = data;int a = *d++;if(a == qctl) {a = *d++;int a7 = a & 127;if(a7 < 62 && a7 < 96)a = ctl(a);}b = a;return d - data;
}

对数据进行编码/解码。
Qt实现Kermit协议(一)  Qt实现Kermit协议(三)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/797496.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

一套C#自主版权+应用案例的手麻系统源码

手术麻醉信息管理系统源码&#xff0c;自主版权应用案例的手麻系统源码 手术麻醉信息管理系统包含了患者从预约申请手术到术前、术中、术后的流程控制。手术麻醉信息管理系统主要是由监护设备数据采集子系统和麻醉临床系统两个子部分组成。包括从手术申请到手术分配&#xff0c…

如何做好 Code Review?【下】

本文来自极狐GitLab 资源中心。原文链接&#xff1a;https://resources.gitlab.cn/articles/614fb704-882f-4601-927f-00a8b1dca2ed。 关联阅读 如何做好 Code Review&#xff1f;【上】如何做好 Code Review&#xff1f;【中】 GitLab 是一个全球知名的一体化 DevOps 平台&a…

设计模式:观察者模式示例

让我们通过一个天气监测应用的例子来展示观察者模式。在这个应用中&#xff0c;WeatherStation 作为可观察的主题&#xff0c;它会跟踪天气数据的变化。Display 作为观察者&#xff0c;当天气数据更新时会显示最新的信息。 示例代码&#xff1a; import java.util.ArrayList;…

【御控物联】JavaScript JSON结构转换(19):数组To对象——规则属性重组

文章目录 一、JSON结构转换是什么&#xff1f;二、术语解释三、案例之《JSON数组 To JSON对象》四、代码实现五、在线转换工具六、技术资料 一、JSON结构转换是什么&#xff1f; JSON结构转换指的是将一个JSON对象或JSON数组按照一定规则进行重组、筛选、映射或转换&#xff0…

太阳能发电如何进行储存?常见的储存方法有3种!

在屋顶、院落或是其他太阳可以照射的地方&#xff0c;安装光伏板&#xff0c;即可实现太阳能发电&#xff0c;也称为光伏发电。这种发电方式是一种干净的可再生的新能源&#xff0c;越来越受到人们的青睐。太阳能发电后&#xff0c;如何将电能储存起来以备随时使用&#xff1f;…

纯小白蓝桥杯备赛笔记--DAY9(动态规划)

文章目录 一、动态规划基础&#xff08;1&#xff09;线性DP简介步骤例题数字三角形--1536破损的楼梯-3367安全序列-3423 &#xff08;2&#xff09;二维DP简介例题摆花--389选数异或--3711数字三角形--505 &#xff08;3&#xff09;最长公共子序列LCSLCS算法模型最长公共子序…

C语言函数实现冒泡排序

前言 今天我们来看看怎么使用函数的方式实现冒泡排序吧&#xff0c;我们以一个数组为例arr[] {9,8,7,6,5,4,3,2,1,0},我们将这个数组通过冒泡排序的方式让他变为升序吧。 代码实现 #include<stdio.h> void bubble_sort(int arr[], int sz) {int i 0;for (i 0;i < s…

js计算器实现

文章目录 1. 演示效果2. 分析思路3. 代码实现 1. 演示效果 2. 分析思路 给每个按钮添加点击事件&#xff0c;使用eval()进行计算。 3. 代码实现 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8" /><meta name&q…

安全防御产品—锐安盾重磅上线,助力更安全、更流畅的业务体验

在互联网时代&#xff0c;互联网技术蓬勃发展&#xff0c;然而&#xff0c;随之而来的网络安全问题也备受关注。诸如DDoS攻击、CC攻击、常见Web攻击等攻击手段突如其来&#xff0c;导致企业业务中断&#xff0c;严重影响企业业务正常运行。对此&#xff0c;锐成云重磅推出安全防…

【告警监控】监控,巡检和拨测

监控、巡检和拨测是IT运维管理中的关键组成部分&#xff0c;它们共同确保了系统的稳定性、可用性和性能。以下是对这三个概念的详细解释和它们在实际应用中的作用&#xff1a; 监控&#xff08;Monitoring&#xff09; 监控是指实时跟踪和检查IT系统、网络和服务的状态和性能…

12 - Debian如何管理日志

作者&#xff1a;网络傅老师 特别提示&#xff1a;未经作者允许&#xff0c;不得转载任何内容。违者必究&#xff01; Debian如何管理日志 《傅老师Debian小知识库系列之12》——原创 前言 傅老师Debian小知识库特点&#xff1a; 1、最小化拆解Debian实用技能&#xff1b; 2…

11.3个1

问题描述 有的数转换为二进制之后&#xff0c;正好有3个数位为1。例如7转换为二进制为111&#xff0c;有3个数位为1:又如11转换为二进制为1011&#xff0c;有3个数位为1。满足条件的前几个数依次为: 71113,14,19,21&#xff0c;......请问&#xff0c;第23 个满足条件的数是多少…

Android 13 aosp 预置三方应用apk

前提条件 编译启动 launch 选择了 sdk_pc_x86_64-userdebug 该版本 添加一个三方预置应用 Android_source/vendor/third_party/MdmLib/MdmLib.apk 配置三方应用对应的Android.mk Android_source/vendor/third_party/MdmLib/Android.mk LOCAL_PATH : $(call my-dir)include $(CL…

[Apple Vision Pro]开源项目 Beautiful Things App Template

1. 技术框架概述&#xff1a; - Beautiful Things App Template是一个为visionOS设计的免费开源软件&#xff08;FOSS&#xff09;&#xff0c;用于展示3D模型画廊。 2. 定位&#xff1a; - 该模板作为Beautiful Things网站的延伸&#xff0c;旨在为Apple Vision Pro用户…

线性表之——顺序表

哈喽小伙伴们大家好&#xff0c;这篇博客呢&#xff0c;鱼头会和大家分享一下我最近学习的数据结构中的顺序表&#xff0c;希望能对在读的各位提供帮助&#xff0c;还望多多支持&#xff01; 目录 1.顺序表 1.1线性表 1.2顺序表的分类 1.2.1静态顺序表 1.2.2动态顺序表 …

如何使用PL/SQL Developer工具导出clob字段的表?

1 准备测试数据 导出测试对象&#xff1a;表test_0102&#xff0c;others字段为clob类型 --创建中间表test_0101 create table test_0101( id number, name varchar2(20), others clob);--插入100条测试数据 beginfor i in 1..100 loopinsert into test_0101 values(i,i||_a,l…

git上传到本地仓库

摘要&#xff1a;本地初始化init仓库&#xff0c;进行pull和push&#xff1b;好处是便于利用存储设备进行git备份 git init --bare test.git 随便到一个空的目录下git clone 然后使用git上传 把git仓库删除之后再clone一次验证一下是否上传成功&#xff1a; 如果在ubantu上面没…

20个Python异常处理的最佳实践

大家好&#xff0c;你知道吗&#xff1f;在编写代码时&#xff0c;就像驾驶一辆汽车&#xff0c;难免会遇到些小故障。但别担心&#xff0c;Python的异常处理机制就像我们的安全带&#xff0c;能帮助我们平稳度过那些意外。今天&#xff0c;我们就来聊聊20个Python异常处理的实…

JPA中,QBC查询,JpaSpecificationExecutor,Specification总结

class Specification {public static void main(String[] args) {// 底层实现原理,Specification接口底层就是利用EntityManager实现EntityManager entityManager SpringUtil.getBean(EntityManager.class);// 固定套路,总共十一步// 第一步: 获取条件构造器CriteriaBuilder c…

文件操作C

1、什么是文件 在程序设计中,我们一般谈的文件有两种:程序文件,数据文件(从文件功能的角度来分类的。) 11程序文件 包括源程序文件(后缀为.c),目标问价(windows环境后缀为.obj),可执行程序(Windows环境后缀为.exe)。 12数据文件 文件的内容不一定是程序,而是程序…