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才能發送成功。