您的位置:首页 > 编程语言 > Qt开发

qt ok6410 gprs模块发送中文短信

2013-08-26 18:17 211 查看
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才能发送成功。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: