最近写了个解析指令集的,之前是一个大 switch,改动或者添加一条指令就非常麻烦。所以我就来啦!

之前我是这样的,拉跨的一批。

img

之后是这样的:

协议的拼凑

img

具体不同指令对应的不同参数部分用了键值对,键 -> 指令,值 -> 函数指针

img

像这样,把指令与函数对应起来,取值时就调这个函数,在函数中获取对应的参数。

是不是非常清晰了哇!我自己可都太爱这种方式了。

要是单片机中也能这样实现那可就太好了!

具体的代码

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "CRC16/crc.h"
#include <qstring.h>
#include "Conversion/conversion.h"
//QString str_uint8_t_to_str(uint8_t *udata,int length);
typedef QString (MainWindow::*function)(void);// 指令函数 typedef
QMap<QString, function> cmdmap_liftlamp;// 指令对应函数
QMap<QString, QString> cmdmap_liftlamp_parsing;// 指令对应解析
QMap<QString, QString> cmderrortype_liftlamp;
QMap<int, QString> cmdsend_liftlamp;
bool liftlampCycleSendEnable;
int liftlampCycleSendnumber;
int liftlampCycleSendnumber_max;
QMap<int, bool> cmdsend_liftlamp_checkbox;
extern CMDPARSING_UNION cmdprotocolparsing;
void MainWindow::vcmdmap_checkBox_status(){
    //----------------------- 发送遍历数组键值对 ---------------------//
    liftlampCycleSendnumber = 0;
    liftlampCycleSendnumber_max=6;
    cmdsend_liftlamp[0]="030101";
    cmdsend_liftlamp_checkbox[0]=ui->checkBox_ID->checkState();
    cmdsend_liftlamp[1]="030102";
    cmdsend_liftlamp_checkbox[1]=ui->checkBox_data->checkState();
    cmdsend_liftlamp[2]="03010D";
    cmdsend_liftlamp_checkbox[2]=ui->checkBox_lora_1->checkState();
    cmdsend_liftlamp[3]="030112";
    cmdsend_liftlamp_checkbox[3]=ui->checkBox_lora_AES->checkState();
    cmdsend_liftlamp[4]="03010F";
    cmdsend_liftlamp_checkbox[4]=ui->checkBox_lora_rate->checkState();
    cmdsend_liftlamp[5]="030113";
    cmdsend_liftlamp_checkbox[5]=ui->checkBox_current_value->checkState();
}
void vcmdmapInit_liftlamp(){
    //----------------------- 指令对应解析 ---------------------//
    cmdmap_liftlamp_parsing["010101"] = "任务执行";
    cmdmap_liftlamp_parsing["010102"] = "任务结束";
    cmdmap_liftlamp_parsing["010103"] = "开灯";
    cmdmap_liftlamp_parsing["010104"] = "关灯";
    cmdmap_liftlamp_parsing["020100"] = "设置进入";
    cmdmap_liftlamp_parsing["030101"] = "设置设备ID号";
    cmdmap_liftlamp_parsing["030102"] = "设置日期";
    cmdmap_liftlamp_parsing["030103"] = "设置设备资源";
    cmdmap_liftlamp_parsing["030104"] = "设置灯下降高度";
    cmdmap_liftlamp_parsing["030105"] = "设置极限高度";
    cmdmap_liftlamp_parsing["030106"] = "设置极限时间";
    cmdmap_liftlamp_parsing["030107"] = "自动设置极限时间开始";
    cmdmap_liftlamp_parsing["030108"] = "自动设置极限时间结束";
    cmdmap_liftlamp_parsing["030109"] = "设置工作时间";
    cmdmap_liftlamp_parsing["03010A"] = "设置科室、房间号";
    cmdmap_liftlamp_parsing["03010B"] = "设置科室、房间号、灯下降高度";
    cmdmap_liftlamp_parsing["03010C"] = "设置微波增益";
    cmdmap_liftlamp_parsing["03010D"] = "设置LoRa信道";
    cmdmap_liftlamp_parsing["03010E"] = "设置LoRa发送功率";
    cmdmap_liftlamp_parsing["03010F"] = "设置LoRa空速";
    cmdmap_liftlamp_parsing["030110"] = "设置LoRa Uart 波特率";
    cmdmap_liftlamp_parsing["030111"] = "设置LoRa信道、空速、功率";
    cmdmap_liftlamp_parsing["030112"] = "设置LoRa AES密钥";
    cmdmap_liftlamp_parsing["030113"] = "设置电机参考电压";
    cmdmap_liftlamp_parsing["03011A"] = "设置云平台下发参数";
    cmdmap_liftlamp_parsing["03011F"] = "清除故障标记";
    cmdmap_liftlamp_parsing["030120"] = "清除灯升降次数、灯点亮时间";
    cmdmap_liftlamp_parsing["030121"] = "系统恢复默认配制";
    cmdmap_liftlamp_parsing["030130"] = "保存设置并退出";
    cmdmap_liftlamp_parsing["030131"] = "退出设置不保存";
    cmdmap_liftlamp_parsing["040101"] = "获得设备状态";
    cmdmap_liftlamp_parsing["040102"] = "获得系统配制参数";
    cmdmap_liftlamp_parsing["040103"] = "获得电机电流、灯电流";
    cmdmap_liftlamp_parsing["040104"] = "获得设备工作状态";
    cmdmap_liftlamp_parsing["050100"] = "进入手动调试模式";
    cmdmap_liftlamp_parsing["060100"] = "退出手动调试模式";
    cmdmap_liftlamp_parsing["070101"] = "调试模式指令空闲";
    cmdmap_liftlamp_parsing["070102"] = "调试模式指令灯架上升";
    cmdmap_liftlamp_parsing["070103"] = "调试模式指令灯架下降";
    cmdmap_liftlamp_parsing["070104"] = "调试模式指令灯亮灭";
    cmdmap_liftlamp_parsing["080100"] = "透传指令";
    cmdmap_liftlamp_parsing["090100"] = "系统复位指令";
    cmdmap_liftlamp_parsing["AC0100"] = "接收到的数据有效";
    cmdmap_liftlamp_parsing["AC0101"] = "接收到的数据无效";
    cmdmap_liftlamp_parsing["FF0101"] = "设备工作状态";
    cmdmap_liftlamp_parsing["FF0102"] = "设备工作结束上传参数";
    cmdmap_liftlamp_parsing["FF0103"] = "系统配制参数";
    cmdmap_liftlamp_parsing["FF0104"] = "警告命令用于警告联网";
    //----------------------- 指令对应函数 ---------------------//
    cmdmap_liftlamp["设置设备ID号"]=&MainWindow::sprotocol_liftlampGetPar_ID;
    cmdmap_liftlamp["设置日期"]=&MainWindow::sprotocol_liftlampGetPar_DATA;
    cmdmap_liftlamp["设置LoRa信道"]=&MainWindow::sprotocol_liftlampGetPar_LORA_Channel;
    cmdmap_liftlamp["设置LoRa AES密钥"]=&MainWindow::sprotocol_liftlampGetPar_LORA_AES;
    cmdmap_liftlamp["设置LoRa空速"]=&MainWindow::sprotocol_liftlampGetPar_LORA_Rate;
    cmdmap_liftlamp["设置电机参考电压"]=&MainWindow::sprotocol_liftlampGetPar_MOTOR_Current;
    cmdmap_liftlamp["进入手动调试模式"]=&MainWindow::sprotocol_liftlampGetPar_void;
    cmdmap_liftlamp["退出手动调试模式"]=&MainWindow::sprotocol_liftlampGetPar_void;
    cmdmap_liftlamp["调试模式指令灯架上升"]=&MainWindow::sprotocol_liftlampGetPar_void;
    cmdmap_liftlamp["调试模式指令灯架下降"]=&MainWindow::sprotocol_liftlampGetPar_void;
    cmdmap_liftlamp["调试模式指令灯亮灭"]=&MainWindow::sprotocol_liftlampGetPar_void;
    cmdmap_liftlamp["获得系统配制参数"]=&MainWindow::sprotocol_liftlampGetPar_void;
    cmdmap_liftlamp["获得电机电流、灯电流"]=&MainWindow::sprotocol_liftlampGetPar_void;
}
void MainWindow::vprotocol_liftlamp_send_Auto(){
    // 使能了循环发送
    if(liftlampCycleSendEnable){
        while((liftlampCycleSendnumber<liftlampCycleSendnumber_max)&&(!cmdsend_liftlamp_checkbox.value(liftlampCycleSendnumber))){
            liftlampCycleSendnumber++;
        }
        if((liftlampCycleSendnumber)>=liftlampCycleSendnumber_max){
            liftlampCycleSendnumber=0;
            liftlampCycleSendEnable=false;
            // 配置完成后,写入记录
            vexcelCmdAddLog();
            // 配置完后把 ID 自增 1
            vcmdmap_Cycle_Send_Over_ID(true);
            return ;
        }
        vprotocol_liftlamp_send(cmdsend_liftlamp.value(liftlampCycleSendnumber));
        liftlampCycleSendnumber++;
    }
}
void MainWindow::vprotocol_liftlamp_send(QString value){
    // 拼接字符串
    QString qstring_context = "";
    // 帧头
    qstring_context.append("FB");
    // 添加指令
    qstring_context.append(value);
    // 添加状态
    qstring_context.append("00");
    // 添加源设备
    qstring_context.append("00000000");
    // 添加目标设备
    if(ui->tabWidget_factory->currentIndex()==0){
        qstring_context.append("00000000");
    }else{
        if(value=="040102"){
            qstring_context.append("00000000");
        }else{
            qstring_context.append(ui->lineEdit_liftlamp_ID->text());
        }
    }
    // 添加参数
    QString (MainWindow::*getpar)(void);
    getpar=cmdmap_liftlamp.value(cmdmap_liftlamp_parsing.value(value));
    qstring_context.append((this->*getpar)());
    // 计算 CRC
    QString str_crc=qstring_context;
    str_crc.remove(0,2);// 去掉帧头
    qstring_context.append(qstrCrcCalc(str_crc).mid(2,2)+qstrCrcCalc(str_crc).mid(0,2));
    //qstring_context.append(qstrCrcCalc(str_crc));
    // 添加帧尾
    qstring_context.append("FE");
    // 发送
    ServerPortSendData(qstring_context);
}
// 接收指令后的解析
void MainWindow::vprotocol_liftlamp_cmdparsing(int length){
    if(cmdprotocolparsing.info.data_head!=0xFB){
        // 找不到头
        memset(cmdprotocolparsing.byte,0,1024);
        return;
    }
    int datalength = (cmdprotocolparsing.byte[14]<<8)+cmdprotocolparsing.byte[13];
    if(datalength>=1024){
        datalength=1024;
    }
    // 判断 CRC
    uint16_t crccompare=uiCRC16Calc(cmdprotocolparsing.byte+1,datalength+15+3-4);
    cmdprotocolparsing.info.crc[1]=cmdprotocolparsing.byte[datalength+15+3-3];
    cmdprotocolparsing.info.crc[0]=cmdprotocolparsing.byte[datalength+15+3-2];
    cmdprotocolparsing.info.data_end=cmdprotocolparsing.byte[datalength+15+3-1];
    cmdprotocolparsing.byte[datalength+15+3-3]=0;
    cmdprotocolparsing.byte[datalength+15+3-2]=0;
    cmdprotocolparsing.byte[datalength+15+3-1]=0;
    //crc
    if(crccompare!=((cmdprotocolparsing.info.crc[0]<<8)+cmdprotocolparsing.info.crc[1])){
        return;
    }
    // 上行数据
    if(cmdprotocolparsing.info.status!=0x01){
        return;
    }
    // 设备为升降灯
    if(cmdprotocolparsing.info.devtype==0x01){
        int cmdlength = cmdprotocolparsing.info.parlen[0]+(cmdprotocolparsing.info.parlen[1]<<8);
        // 应答
        if(cmdprotocolparsing.info.cmd.DataByte==0xAC){
            // 有效
            if(cmdprotocolparsing.info.fun==0x00){
                if(CurrentButton == "自动获取"){
                    QString LampID = str_uint8_t_to_str(cmdprotocolparsing.info.sdevid,4);
                    if(LampID!=ui->lineEdit_liftlamp_ID->text()){
                        ui->lineEdit_liftlamp_ID->setText(LampID);
                    }
                }else if(CurrentButton == "进入调试"){
                }else if(CurrentButton == "上升"){
                }else if(CurrentButton == "下降"){
                }else if(CurrentButton == "开灯"){
                }else if(CurrentButton == "获取电流"){
                    // 判断长度
                    if(cmdlength==5+4){
                        // 长度没问题
                        //
                        //[0]:灯的工作状态
                        //1234 环境信噪比
                        //[5-6]:电机电流
                        //[7-8]:灯电流 FB AC 01 00 01 04 00 00 01 00 00 00 00 09 00 08 10 A1 E0 00 0A 00 01 00 DE DC FE
                        int motorcurrent = cmdprotocolparsing.info.par[5]+(cmdprotocolparsing.info.par[6]<<8);
                        int lampcurrent = cmdprotocolparsing.info.par[7]+(cmdprotocolparsing.info.par[8]<<8);
                        ui->lcdNumber_real_time_curent->display(motorcurrent);
                        ui->lcdNumber_real_time_curent_lamp->display(lampcurrent);
                    }
                }
            }
        }
    }
}
// 参数增加长度
QString sprotocol_liftlampMakeup_str_addlen(QString string,int length){
    QString string_c = string;
    uint8_t u8length[2];
    u8length[0]=length/2;
    u8length[1]=(length/2)>>8;
    string_c.insert(0,str_uint8_t_to_str(u8length,2));
    return string_c;
}
// 字符串补齐 并添加长度
QString sprotocol_liftlampMakeup_str_len(QString string,int length){
    QString string_complete;
    string_complete=string;
    while((string_complete.length()<length)||((string_complete.length()%2)!=0)){
        string_complete.insert(0,"0");
    }
    string_complete = sprotocol_liftlampMakeup_str_addlen(string_complete,length);
    return string_complete;
}
// 获取指令参数
QString MainWindow::sprotocol_liftlampGetPar_void(){
    static QString par="0000";
    return par;
}
QString MainWindow::sprotocol_liftlampGetPar_ID(){
    QString par=ui->lineEdit_liftlampID->text();
    par = sprotocol_liftlampMakeup_str_len(par,8);
    return par;
}
QString MainWindow::sprotocol_liftlampGetPar_DATA(){
    QString par=ui->lineEdit_liftlamp_data->text();
    par = sprotocol_liftlampMakeup_str_len(par,8);
    return par;
}
QString MainWindow::sprotocol_liftlampGetPar_LORA_Channel(){
    QString par=ui->lineEdit_lora_1->text();
    par = sprotocol_liftlampMakeup_str_len(par,2);
    return par;
}
QString MainWindow::sprotocol_liftlampGetPar_LORA_AES(){
    QString par=ui->lineEdit_lora_AES->text();
    par = sprotocol_liftlampMakeup_str_len(par,16*2);
    return par;
}
QString MainWindow::sprotocol_liftlampGetPar_LORA_Rate(){
    QString par=ui->lineEdit_lora_rate->text();
    par = sprotocol_liftlampMakeup_str_len(par,2);
    return par;
}
QString MainWindow::sprotocol_liftlampGetPar_MOTOR_Current(){
    QString par=ui->lineEdit_current_value->text();
    par = sprotocol_liftlampMakeup_str_len(par,4);
    return par;
}
QString MainWindow::sprotocol_liftlampGetPar_LAMP_Current(){
    QString par=ui->lineEdit_current_value_2->text();
    par = sprotocol_liftlampMakeup_str_len(par,4);
    return par;
}
更新于 阅读次数

请我喝[茶]~( ̄▽ ̄)~*

flechazo 微信支付

微信支付

flechazo 支付宝

支付宝

flechazo 贝宝

贝宝