qt ok6410 gprs模塊發送中文短信

ok6410自帶的模塊沒有發送中文短信的測試程序,裏面的測試程序時text模式的只能發送英文短信,由於工作中用到這個模塊,而且需要發送中文短信,經過一段時間的調試,而且在網上找了很多的資料,終於調試通過了,現在把代碼貼出來,記錄一下。

發送中文短信,其實只有幾步,使用串口發送AT+cmGF=0 回車,at+cmgs=發送的長度 然後就是pnone+unicode的短信內容了。代碼如下:

#include <QtGui/QApplication>
#include "QtSMS.h"
#include <iconv.h>
#include "codeconvertor.h"
#include <QDebug>
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
//    QTextCodec::setCodecForTr(QTextCodec::codecForName("unicode"));
    QtSMS w;
    w.OpenCom("/dev/ttySAC1",115200);
    w.SendSms("123abc,,//?????/?//】【[]{}[jj』『』『、、|||、、||\\\"、、、////```````098jjsk愛!","13062669576");
//    w.show();
//    qDebug() << CodeConvertor::_tuf8ToUnicode("工作愉快!").data();
//    qDebug()<<"\"5DE54F5C61095FEBFF01\"";




    return a.exec();
}


#include "QtSMS.h"
#include "ui_QtSMS.h"
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <termio.h>
#include "codeconvertor.h"
QtSMS::QtSMS(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::QtSMS)
{
    ui->setupUi(this);
//    OpenCom("ttySAC1",115200);


//    SendSms("您好!","13062669576");




    iDelNum=1;
    isAllDel = false;
    iTotalSms=50;
//    DelAllSms();
//    sendAT(7);
//    qDebug()<<unicodeToString("0500034902015C0A656C768452A8611F57305E265BA26237FF0C52A8611F57305E2654C1724C8FFD6C42201C65F65C1A3001597D73A9300163A27D22201D30025F53524D5E106237603B4F59989D4E3A0039002E003400315143FF0C51764E2D672C6708901A75284F59989D4E3A0039002E003400315143300256DE590D0031003100314E8689E34F59989D");


}


QtSMS::~QtSMS()
{
    myCom->close();
    delete ui;
}
int QtSMS::openSerialPort()
{
    int fd = -1;




    fd = ::open("/dev/ttySAC1", O_RDWR|O_NONBLOCK);
  if (fd < 0) {


    return -1;
  }


  termios serialAttr;
  memset(&serialAttr, 0, sizeof serialAttr);


    cfsetispeed(&serialAttr,B115200);
    cfsetospeed(&serialAttr,B115200);




    serialAttr.c_cflag &= ~CSIZE;
    serialAttr.c_cflag |= CS8;




        serialAttr.c_iflag = IGNPAR;


  if (tcsetattr(fd, TCSANOW, &serialAttr) != 0) {


    return -1;
  }
  return fd;
}
int QtSMS::OpenCom(const char* pStrPort,int iBaudRate)
{
#if 1
    this->myCom = new QextSerialPort(pStrPort, QextSerialPort::EventDriven);
    switch(iBaudRate) {
    case 9600:
        myCom->setBaudRate(BAUD9600);
        break;
    case 115200:
        myCom->setBaudRate(BAUD115200);
        break;
    default:
        myCom->setBaudRate(BAUD9600);
        break;
    }




    myCom->setFlowControl(FLOW_OFF);
    myCom->setParity(PAR_NONE);
    myCom->setDataBits(DATA_8);
    myCom->setStopBits(STOP_1);


    if (myCom->open(QIODevice::ReadWrite) == true) {
        connect(myCom, SIGNAL(readyRead()), this, SLOT(onReadyRead()));
        connect(myCom, SIGNAL(dsrChanged(bool)), this, SLOT(onDsrChanged(bool)));
        if (!(myCom->lineStatus() & LS_DSR))
            qDebug() << "warning: device is not turned on";
        qDebug() << "listening for data on" << myCom->portName();
    }
    else {
        qDebug() << "device failed to open:" << myCom->errorString();
    }


//    connect(myCom,SIGNAL(readyRead()),this,SLOT(slotReadMesg()));


#else
    my_fd=this->openSerialPort();
#endif
    return 1;
}
void QtSMS::onReadyRead()
{
    QByteArray bytes;
    int a = myCom->bytesAvailable();
    bytes.resize(a);
    myCom->read(bytes.data(), bytes.size());
    qDebug() << "bytes read:" << bytes.size();
    qDebug() << "bytes:" << bytes;
}
void QtSMS::onDsrChanged(bool status)
{
    if (status)
        qDebug() << "device was turned on";
    else
        qDebug() << "device was turned off";
}
void QtSMS::SendSms(QString qStrSend,QString qStrNum)
{


    sendAT(1);
    convertPhone(qStrNum);
    convertMesg(qStrSend);
    sleep(2);
    sendAT(2);
    sleep(2);
    sendAT(3);
    sleep(3);




}




void QtSMS::DelAllSms()
{
    isAllDel = true;
    iDelNum=1;
    sendAT(6);
}


SmsInfo QtSMS::GetSms()
{
    while(m_SmsList.size()!=0)
    {
        QString qStrSms = m_SmsList.back();     //讀取最後一個
        int iSms;


        char *ptr = (char*)qStrSms.toStdString().c_str();
        sscanf(ptr,"%d",&iSms);
        cout<<"iSms ===="<<iSms<<endl;




        ptr=strstr(ptr,",");
        ptr++;
        m_SmsList.pop_back();       //去掉最後一個
        DecodePdu(ptr);


//        iDelNum = iSms;
//        sendAT(6);
//        isAllDel = false;


    }


    SmsInfo sms;
    return  sms;
}




void QtSMS::sendAT(int iOrder)
{
    QString qStrCmd;


    switch(iOrder)
    {
    case 1:
    {
        //設置短信格式
        qStrCmd= "AT+CMGF=0\r";
        myCom->write(qStrCmd.toAscii());
//#endif
        break;
    }


    case 2:
    {
        //發送短信長度指令
        int iLength=strlen(m_SendCont.toStdString().c_str())/2;
        qDebug()<<"sms======len:"<<iLength;
        qStrCmd=QString("%1%2\r").arg("AT+CMGS=").arg(iLength-9);


        myCom->write(qStrCmd.toAscii());
        break;
    }


    case 3:
    {
        //發送短信內容指令
        //         myCom->write("0011000D91683166051461F70008011600680065006C006C006F00204F60597D0021000D000A\x01a");
        qDebug()<<"sms======cont:"<<m_SendCont;
        myCom->write((m_SendCont+"\x01a").toStdString().c_str());
        break;
    }


    case 4:
    {
        //短信容量查詢指令
        qStrCmd = "AT+CPMS?\r";
        myCom->write(qStrCmd.toAscii());
        break;
    }


    case 5:
    {
        //設置新短信通知指令
        qStrCmd="AT+CNMI=2,1\r";
        myCom->write(qStrCmd.toAscii());
        break;
    }


    case 6:
    {
        //短信刪除指令


        qStrCmd= tr("AT+CMGD=%1\r").arg(iDelNum);
        qDebug()<<qStrCmd;
        myCom->write(qStrCmd.toAscii());
        break;
    }


    case 7:
    {
        //讀取未讀短信


        qStrCmd= "AT+CMGL=0\r";
        qDebug()<<qStrCmd;
        myCom->write(qStrCmd.toAscii());
        break;
    }


    default:
        break;
    }
}




QString QtSMS::stringToUnicode(QString str)
{
    // 這裏傳來的字符串一定要加tr,main函數裏可以加 QTextCodec::setCodecForTr(QTextCodec::codecForLocale());


    //  例如:str=tr("你好");


    const QChar *q;




    QChar qtmp;


    QString str0, strout;


    int num;


    q=str.unicode();


    int len=str.count();


    for(int i=0;i<len;i++)


    {
        qtmp =(QChar)*q++;


        num= qtmp.unicode();


//        if(num<255)


//            strout+="00"; //英文或數字前加"00"


        str0=str0.setNum(num,16);//變成十六進制數


        strout+=str0;
    }
    return strout;
}


QString QtSMS::unicodeToString(QString str)
{
    //例如 str="4F60597D";
//    qDebug()<<str;
    int temp[400];


    QChar qchar[100];


    QString strOut;


    bool ok;


    int count=str.count();


    int len=count/4;


    for(int i=0;i<count;i+=4)
    {


        temp[i]=str.mid(i,4).toInt(&ok,16);//每四位轉化爲16進制整型


        qchar[i/4]=temp[i];


        QString str0(qchar, len);


        strOut=str0;
    }


    qDebug()<<"wyz=========smsInfo:"<<strOut<<endl;
    return strOut;
}


int QtSMS::convertMesg(QString qStrMesg)
{






    qStrMesg=CodeConvertor::tuf8ToUnicode(qStrMesg);


    qDebug()<<"unicode is:"<<qStrMesg;
    int i=qStrMesg.length()/2;  //內容長度
    QString sHex;
    sHex.setNum(i,16);


    if(sHex.length()==1)
    {
        sHex="0"+sHex;
    }


    QString qStrMesgs;
    qStrMesgs = QString("%1%2").arg(sHex).arg(qStrMesg);


    m_SendCont+=qStrMesgs;


    return qStrMesgs.length();
}


int QtSMS::convertPhone(QString qStrPhone)
{
    int i=qStrPhone.length()+2;     //長度包括86
    QString sHex;
    sHex.setNum(i,16);      //轉成十六進制


    if(sHex.length()==1)
    {
        sHex="0"+sHex;
    }


    if(qStrPhone.length()%2 !=0)  //爲奇數位後面加F
    {
        qStrPhone+="F";
    }
    qDebug()<<"phone num is:"<<qStrPhone;
    //奇數位偶數位交換
    QString qStrTemp2;
    for(int i=0; i<qStrPhone.length(); i+=2)
    {
        qStrTemp2 +=qStrPhone.mid(i+1,1)+qStrPhone.mid(i,1);
    }
    qDebug()<<"phone num is:"<<qStrTemp2;
    //1100:固定,sHex:手機號碼的長度,不算+號,十六進制表示,91:發送到手機爲91,發送到小靈通爲81
    qStrTemp2="0891683108200105F01100"+sHex+"9168" +qStrTemp2+"000800";
    m_SendCont=qStrTemp2;


    return qStrTemp2.length();
}




int QtSMS::smsString2Bytes(const char* pSrc, unsigned char* pDst, int nSrcLength)
{
    for(int i=0; i<nSrcLength; i+=2)
    {
        // 輸出高4位


        if(*pSrc>='0' && *pSrc<='9')
        {
            *pDst = (*pSrc - '0') << 4;
        }
        else
        {
            *pDst = (*pSrc - 'A' + 10) << 4;
        }


        pSrc++;


        // 輸出低4位
        if(*pSrc>='0' && *pSrc<='9')
        {
            *pDst |= *pSrc - '0';
        }
        else
        {
            *pDst |= *pSrc - 'A' + 10;
        }
        pSrc++;
        pDst++;
    }


    // 返回目標數據長度
    return nSrcLength / 2;
}


QString QtSMS::smsSerializeNumbers(const char* pSrc, int nSrcLength)
{


    QString qStrTemp1(pSrc);
    QString qStrTemp2;
    for(int i=0; i<nSrcLength; i+=2)
    {
        qStrTemp2 +=qStrTemp1.mid(i+1,1)+qStrTemp1.mid(i,1);
    }


    if(qStrTemp2[nSrcLength-1] =='F')   //字符F去掉
    {
        qStrTemp2.chop(1);
    }


    return qStrTemp2;


}


SmsInfo QtSMS::DecodePdu(char * pStrSms)
{
    unsigned char tmp;       // 內部用的臨時字節變量


    smsString2Bytes(pStrSms, &tmp, 2);    // 取長度
    tmp = (tmp - 1) * 2;    // SMSC號碼串長度(中心號碼)


    pStrSms+=4+tmp+2;     //指針後移


    // 包含回覆地址,取回復地址信息
    smsString2Bytes(pStrSms, &tmp, 2);    // 取長度
    if(tmp & 1) tmp += 1;    // 調整奇偶性


    pStrSms += 4;          // 指針後移
    SmsInfo smsInfo;


    smsInfo.strPhoneNum=smsSerializeNumbers(pStrSms, tmp);    // 取TP-RA號碼(對方號碼)


    pStrSms += tmp+4;        // 指針後移
    smsInfo.strTime=convertTime(smsSerializeNumbers(pStrSms, 14));        // 服務時間戳字符串(短信時間)


    pStrSms += 16;       // 指針後移 


    smsInfo.strSms=unicodeToString(pStrSms);


    qDebug()<<smsInfo.strPhoneNum<<" "<<smsInfo.strTime<<" "<<  smsInfo.strSms<<endl;


    return smsInfo;
}


QString QtSMS::convertTime(QString qStrTime)
{
    QString qStrTemp="20";  //時間格式2012-07-12 18:56:04
    qStrTemp += qStrTime.mid(0,2)+"-"+qStrTime.mid(2,2)+"-"+qStrTime.mid(4,2)+" "+qStrTime.mid(6,2)+":"+qStrTime.mid(8,2)+":"+qStrTime.mid(10,2);
    return qStrTemp;
}

#include "codeconvertor.h"


#include <QDebug>


CodeConvertor::CodeConvertor()
{


}


QString CodeConvertor::tuf8ToUnicode(const QString &in)
{
    QString outstr;
    QByteArray byteArr = in.toLatin1();




    for (int i = 0;i < byteArr.length();) {
        if ((byteArr[i] & 0x80) == 0x00)//是英文
        {//0x0xxxxxx 只佔一個字節
            if (!(byteArr[i] & 0xf0)) {
                outstr += "0";
            }
            outstr+="00";
            outstr += QString::number((uint)byteArr[i] & 0x000000ff,16);
            ++i;
        }
        else
        {


            if ((byteArr[i] & 0xe0) == 0xc0)
            {//0x110xxxxx 0x10xxxxxx 佔兩個字節
                char t1 = byteArr[i] & 0x1f;//第一個字節的後五位 1
                char t2 = byteArr[++i] & 0x3f;//第而個字節的後六位 2
                char t3 = t2 | ((t1 & 0x03) << 6);//2
                char t4 = (t1 >> 2) & 07;//1
                if (!(t4 & 0xf0)) {
                    outstr += "0";
                }
                outstr += QString::number((uint)t4 & 0x000000ff,16);
                if (!(t3 & 0xf0)) {
                    outstr += "0";
                }
                outstr += QString::number((uint)t3 & 0x000000ff,16);
                ++i;


            }
            else
            {
                if ((byteArr[i] & 0xf0) == 0xe0)
                {//佔3個字節
                    char t1 = byteArr[i] & 0x0f;//1
                    char t2 = byteArr[++i] & 0x3f;//2
                    char t3 = byteArr[++i] & 0x3f;//3
                    char t4 = t3 | ((t2 & 0x03) << 6);//3
                    char t5 = ((t2 >> 2) & 0x0f) | ((t1 << 4) & 0xf0) ;//2
                    if (!(t5 & 0xf0)) {
                        outstr += "0";
                    }
                    outstr += QString::number((uint)t5 & 0x000000ff,16);
                    if (!(t4 & 0xf0)) {
                        outstr += "0";
                    }
                    outstr += QString::number((uint)t4 & 0x000000ff,16);


                    ++i;


                }


            }
        }
    }


    return outstr;


}
std::string CodeConvertor::_tuf8ToUnicode(const std::string &in)
{
    std::string outstr;
    char buf[3];
    for (int i = 0;i < in.length();) {
        if ((in[i] & 0x80) == 0x00)
        {//0x0xxxxxx 只佔一個字節
            CodeConvertor::charTo2Hex(in[i],buf);
            outstr += buf;
            ++i;
        }
        else
        {
            if ((in[i] & 0xe0) == 0xc0)
            {//0x110xxxxx 0x10xxxxxx 佔兩個字節
                char t1 = in[i] & 0x1f;//第一個字節的後五位 1
                char t2 = in[++i] & 0x3f;//第而個字節的後六位 2
                char t3 = t2 | ((t1 & 0x03) << 6);//2
                char t4 = (t1 >> 2) & 07;//1
                CodeConvertor::charTo2Hex(t4,buf);
                outstr += buf;
                CodeConvertor::charTo2Hex(t3,buf);
                outstr += buf;
                ++i;


            }
            else
            {
                if ((in[i] & 0xf0) == 0xe0)
                {//佔3個字節
                    char t1 = in[i] & 0x0f;//1
                    char t2 = in[++i] & 0x3f;//2
                    char t3 = in[++i] & 0x3f;//3
                    char t4 = t3 | ((t2 & 0x03) << 6);//3
                    char t5 = ((t2 >> 2) & 0x0f) | ((t1 << 4) & 0xf0) ;//2


                    CodeConvertor::charTo2Hex(t5,buf);
                    outstr += buf;


                    CodeConvertor::charTo2Hex(t4,buf);
                    outstr += buf;


                    ++i;


                }


            }
        }
    }
    return outstr;
}
void CodeConvertor::charTo2Hex(char in, char *out)
{
    char l = in & 0x0f;
    char h = (in & 0xf0) >> 4;
    int hh = h % 16;
    if (hh < 10) {
        out[0] = '0' + hh;
    } else {
        out[0] = hh - 10 + 'A';
    }
    int ll = l % 16;
    if (ll < 10) {
        out[1] = '0' + ll;
    } else {
        out[1] = ll - 10 + 'A';
    }


    out[2] = '\0';
}


#ifndef CODECONVERTOR_H
#define CODECONVERTOR_H


#include <QString>
#include <string>


class CodeConvertor
{
public:
    static QString tuf8ToUnicode(const QString &in);
    static std::string _tuf8ToUnicode(const std::string &in);
    static void charTo2Hex(char in,char *out);
private:
    CodeConvertor();


};


#endif // CODECONVERTOR_H

#ifndef QTSMS_H
#define QTSMS_H


#include <QMainWindow>
#include "qextserialport.h"
#include <QDebug>
#include <QTextCodec>
#include <iostream>
#include <list>




using namespace std;
namespace Ui {
class QtSMS;
}




struct SmsInfo{
    QString strPhoneNum;
    QString strTime;
    QString strSms;
};


class QtSMS : public QMainWindow
{
    Q_OBJECT


public:
    explicit QtSMS(QWidget *parent = 0);
    ~QtSMS();




    void sendAT(int iOrder);        //發送指令
    int convertMesg(QString);    //轉換字符串信息變成PDU格式
    int convertPhone(QString);  //電話號碼兩兩顛倒
    QString convertTime(QString);   //短信時間轉換成常用時間格式




    SmsInfo GetSms();       //獲取短信
    void SendSms(QString qStrSend,QString qStrNum);     //發送短信
    void DelAllSms();       //刪除短信


    QString stringToUnicode(QString str);       //字符串轉爲unicode
    QString unicodeToString(QString str);       //unicode轉爲字符串
    SmsInfo DecodePdu(char *);      //解碼接收短信內容


    int smsString2Bytes(const char* pSrc, unsigned char* pDst, int nSrcLength);     //// 可打印字符串轉換爲字節數據
    QString  smsSerializeNumbers(const char* pSrc,  int nSrcLength);    //// 兩兩顛倒的字符串轉換爲正常順序的字符串


    int OpenCom(const char* pStrPort,int iBaudRate);    //打開串口
    int openSerialPort();
private:
    int my_fd;
    QextSerialPort *myCom;      //第三方串口
    void chineseStrTo16Str(const QString& srcStr, QString& destStr);
    int Utf82Unicode(char* out,  int outsize , char* in,int insize);


private:
    Ui::QtSMS *ui;
    QString m_qStrInfo;     //串口接收的信息


    QString m_SendCont;     //整理好的短信發送內容


    list<QString> m_SmsList;    //收集短信


    int iDelNum;    //  刪除短信條數
    int iUsedSms;   //用過的短信條數
    int iTotalSms;      //總的短信條數


    bool isAllDel;      //是否全刪除標誌


private slots:
//    void slotReadMesg();
    void onReadyRead();
    void onDsrChanged(bool status);


};


#endif // QTSMS_H


有些代碼是我從網上找的,但是都修改了一下,然後調試通過了。可以發送英文字符+中文漢字,比如1111aaa愛你!!這樣子的,因爲發送的編碼必須是unicode所以必須轉換,linux+qt使用的都是utf-8 所以必須轉換爲unicode才能發送成功。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章