/*
* =====================================================================================
*
* Filename: gmesg.c
*
* =====================================================================================
*/
/* 头文件开始 1.编码转换需要iconv.h 2.对消息内容特殊转换需要gmesg.h */
/*{{{*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "gmesg.h"
#include "gport.h"
#define SLEEP3S 0
/*}}}*/
/* 头文件结束 1.编码转换需要iconv.h 2.对消息内容特殊转换需要gmesg.h */
/*
* === FUNCTION ======================================================================
* Name: init_gprs_pdu
* Description: 从数据库中读出默认设置的pdu数据
* =====================================================================================
*/
/*{{{*/
int init_gprs_pdu ( struct gprs_pdu **gpdu,char *signal )
{
sqlite3 *db = NULL;
int rc,i;
char *dbname = "gprsPdu.db";
char *ErrMsg = NULL;
char **dbResult = NULL;
char sql_select[MSIZE] = { 0 };
int nrow,ncolumn;
if ( NULL == signal )
{
strcpy(sql_select,"select * from gprs_pdu where id=1");
}
else
{
sprintf(sql_select,"select * from gprs_pdu where status = /'%s/'",signal);
}
rc = sqlite3_open(dbname,&db);
if ( sqlITE_OK != rc )
{
fprintf(stderr,"Cannot open database :%s/n",sqlite3_errmsg(db));
sqlite3_close(db);
return -1;
}
rc = sqlite3_get_table (db,sql_select,&dbResult,&nrow,&ncolumn,&ErrMsg);
i = ncolumn + 1; /* 去掉id字段 */
(*gpdu) = (struct gprs_pdu *) malloc (sizeof(struct gprs_pdu));
memset(*gpdu,sizeof(struct gprs_pdu));
strcpy( (*gpdu)->sim_attr,dbResult[i] );
i++;
strcpy( (*gpdu)->sim_center,dbResult[i] );
i++;
strcpy( (*gpdu)->phone_attr,dbResult[i] );
i++;
strcpy( (*gpdu)->phone,dbResult[i] );
i++;
strcpy( (*gpdu)->fix,dbResult[i] );
i++;
strcpy( (*gpdu)->gb2312_msg,dbResult[i] );
i++;
sqlite3_free_table( dbResult );
sqlite3_close(db);
return 0;
}
/* ----- end of function init_gprs_pdu ----- */
/*}}}*/
/*
* === FUNCTION ======================================================================
* Name: clear_gprs_pdu
* Description: 清除结构体struct gprs_pdu
* =====================================================================================
*/
/*{{{*/
int clear_gprs_pdu ( struct gprs_pdu *gpdu )
{
free(gpdu);
return 0;
}
/* ----- end of function clear_gprs_pdu ----- */
/*}}}*/
/*
* === FUNCTION ======================================================================
* Name: code_convert
* Description: 代码转换:从一种编码转为另一种编码
* =====================================================================================
*/
/*{{{*/
int code_convert(char *from_charset,char *to_charset,char *inbuf,int inlen,char *outbuf,int outlen )
{
iconv_t cd; /* 字符集转换描述符 */
char **pin = &inbuf; /* 被转换的编码 */
char **pout = &outbuf; /* 转换后的编码 */
/* iconv_open 申请编码转换描述符,对系统有依赖,可以使用iconv --list查看 */
cd = iconv_open(to_charset,from_charset);
if ( cd == 0 )
{
return -1;
}
memset(outbuf,outlen);
/* iconv 实现编码转换 */
if ( iconv(cd,pin,&inlen,pout,&outlen) == -1 )
{
return -1;
}
/* 关闭编码转换描述符 */
iconv_close(cd);
return 0;
}
/* ----- end of function code_convert ----- */
/*}}}*/
/*
* === FUNCTION ======================================================================
* Name: u2g
* Description: UNICODE码转为GB2312码
* =====================================================================================
*/
/*{{{*/
int u2g ( char *inbuf,int outlen )
{
//return code_convert("unicode","utf-8",inbuf,inlen,outbuf,outlen);
/* 交叉编译后在,开发板中个人使用下面的,iconv_open对系统有依赖 */
return code_convert("UTF-16","GB2312",outlen);
}
/* ----- end of function u2g ----- */
/*}}}*/
/*
* === FUNCTION ======================================================================
* Name: g2u
* Description: GB2312码转为UNICODE码
* =====================================================================================
*/
/*{{{*/
int g2u ( char *inbuf,int outlen )
{
/* 交叉编译后在,开发板中个人使用下面的,iconv_open对系统有依赖 */
/* GB2312 -> UTF-16 转换之后,前端会有多余字节 */
return code_convert("GB2312","UTF-16",outlen);
/* GB2312 -> UCS2 主机正常,在开发板上使用时会段错误,断点在iconv_open处,可能缺少lib*/
//return code_convert("GB2312","UCS2",outlen);
}
/* ----- end of function g2u ----- */
/*}}}*/
/*
* === FUNCTION ======================================================================
* Name: bytes2string
* Description: 将字节流转换成字符串,为了PDU编码作准备
* =====================================================================================
*/
/*{{{*/
int bytes2string ( const unsigned char *pSrc,char *pDst,int nSrcLength )
{
const char tab[] = "0123456789ABCDEF";
int i;
for ( i=0; i
{
*pDst++ = tab[*pSrc >> 4]; /* 取出高4位 */
*pDst++ = tab[*pSrc & 0x0f]; /* 取出底4位 */
pSrc++;
}
/* 加上结束标志 */
*pDst = '/0';
/* 返回字符串长度,将一个字节分成两个字符,所以长度乘以2 */
return nSrcLength*2;
}
/* ----- end of function bytes2string ----- */
/*}}}*/
/*
* === FUNCTION ======================================================================
* Name: switch_byte1
* Description: 实现字符串中相邻的字符交换,为了PDU编码作准备,电话号码相邻数字交换。
* =====================================================================================
*/
/*{{{*/
int switch_byte1 ( char *src,int len )
{
int i;
char tch;
for ( i=0; i
{
tch = *(src + i + 1);
*(src + i + 1) = *(src + i);
*(src + i) = tch;
}
return len;
}
/* ----- end of function switch_byte1 ----- */
/*}}}*/
/*
* === FUNCTION ======================================================================
* Name: switch_byte2
* Description: 与编码有关的函数,经过iconv转换(GB2312 -> UTF-16)的编码,再经字节流转变成字符串后,字符串
* 中的十六进制字符,顺序双对换,根据系统的不同,决定该函数是否需要调用.例如:
* 在宿主机上(Unbuntu)上需要调用,目标板(s3c2410)不需要.
* =====================================================================================
*/
/*{{{*/
int switch_byte2 ( char *src,int len )
{
int i;
char tch;
for ( i=0; i
{
/* 将第1个字符与第3个字符交换 */
tch = *(src + i + 2);
*(src + i + 2) = *(src + i);
*(src + i) = tch;
/* 将第2个字符与第4个字符交换 */
tch = *(src + i + 3);
*(src + i + 3) = *(src + i + 1);
*(src + i + 1) = tch;
/* eg. "1234" ---> "3412" */
}
return len;
}
/* ----- end of function switch_byte2 ----- */
/*}}}*/
/*
* === FUNCTION ======================================================================
* Name: change_sim_attr
* Description: 更改短信息中心地址长度和号码类型
* =====================================================================================
*/
/*{{{*/
int change_sim_attr ( const char *src,char *des )
{
printf ( "/nsrc : %s/n",src );
memset(des,strlen(des));
strcpy(des,src);
return 0;
}
/* ----- end of function make_sim_attr ----- */
/*}}}*/
/*
* === FUNCTION ======================================================================
* Name: change_sim_center
* Description: 更改短信息中心服务号码 (参数改变)
* =====================================================================================
*/
/*{{{*/
int change_sim_center ( const char *src,char *des )
{
memset(des,strlen(des));
strcat(des,"86");
strcat(des,src);
if( strlen(des)%2 != 0 )
{
strcat(des,"F");
}
return 0;
}
/* ----- end of function change_sim_center ----- */
/*}}}*/
/*
* === FUNCTION ======================================================================
* Name: change_phone_attr
* Description: 更改发送到目的地址(手机)的属性
* =====================================================================================
*/
/*{{{*/
int change_phone_attr ( const char *src,src);
return 0;
}
/* ----- end of function change_phone_attr ----- */
/*}}}*/
/*
* === FUNCTION ======================================================================
* Name: change_other_phone
* Description: 更改发送到目的手机号码 (参数改变)
* =====================================================================================
*/
/*{{{*/
int change_other_phone ( const char *src,src);
if ( strlen(des)%2 != 0 )
{
strcat(des,"F");
}
return 0;
}
/* ----- end of function change_other_phone ----- */
/*}}}*/
/*
* === FUNCTION ======================================================================
* Name: change_fix
* Description: 改变固定格式,详细请参考其他(没有不变的东西)
* =====================================================================================
*/
/*{{{*/
int change_fix ( const char *src,src);
return 0;
}
/* ----- end of function change_fix ----- */
/*}}}*/
/*
* === FUNCTION ======================================================================
* Name: change_gb2312_msg
* Description: 改变要发送的实际信息内容
* =====================================================================================
*/
/*{{{*/
int change_gb2312_msg ( const char *src,src);
return 0;
}
/* ----- end of function change_gb2312_msg ----- */
/*}}}*/
/*
* === FUNCTION ======================================================================
* Name: make_mesg
* Description: 该函数是该文件的'主'函数,它调动上面的函数来实现短信消息的内容合成。
* =====================================================================================
*/
/*{{{*/
int make_mesg ( char *src,char *dest,int src_len,int des_len )
{
int rc;
char b2s[MSIZE]; /* 字节流转换字符串 */
char nhex[6]; /* 计算消息的内容长度(十六进制表示)*/
char nhex_even[4] = {'0'}; /* PDU规则,长度为奇数前加0 */
g2u(src,src_len,dest,des_len); /* 将GB2312流转换成UTF-16 */
rc = bytes2string(dest,b2s,strlen(dest));
/* 开发板中不需要switch_byte2,主机上需要. 让我伤心的地方 */
//rc = switch_byte2(b2s,rc);
/* GB2312 -> UTF-16 转换之后,再经过字节流转换成字符串,前端多了4个字符. */
sprintf(nhex,"%X",(rc-4)/2); /* (GB2312 -> UTF-16)除以2是得到的汉字字符个数,在格式化输出十六进制 */
//sprintf(nhex,rc/2); /* 使用(GB2312 -> UCS2)时 */
/* 判断长度是否是偶数 */
if ( strlen(nhex)%2 == 1 )
{
/* 奇数 前端加0 */
strcat(nhex_even,nhex);
memset(dest,MSIZE);
strcpy(dest,nhex_even);
}
else
{
memset(dest,nhex);
}
strcat(dest,b2s+4); /* (GB2312 -> UTF-16)前面的4个字节是没用的 */
//strcat(dest,b2s); /* 使用(GB2312 -> UCS2)时 */
return strlen(dest);
}
/* ----- end of function make_mesg ----- */
/*}}}*/
/*
* === FUNCTION ======================================================================
* Name: make_content
* Description: 将不同部分的内容组合成完整PDU编码内容
* =====================================================================================
*/
/*{{{*/
int make_content(struct gprs_pdu *gpdu,char *content)
{
int nsim = 0; /* SIM用户识别卡所占字节(转换为十六进制)*/
char unicode_msg[MSIZE];
/* 1. 先将消息内容进行编码转换 */
make_mesg(gpdu->gb2312_msg,unicode_msg,strlen(gpdu->gb2312_msg),MSIZE);
/* 2. 短信消息中心号码数字奇偶转换 */
switch_byte1(gpdu->sim_center,strlen(gpdu->sim_center));
/* 3. 接受方手机号码数字奇偶转换 */
switch_byte1(gpdu->phone,strlen(gpdu->phone));
/* 4. 将短消息中心地址长度(16/2)和号码类型拼接到content数组中 */
strcat(content,gpdu->sim_attr);
/* 5. 将短信息中心号码拼接到content数组中 */
strcat(content,gpdu->sim_center);
/* 6. 计算SMSC(Short Message Server Center)相关内容的长度, */
nsim = strlen(content);
/* 7. 将接收方的手机号属性拼接到content数组中 */
strcat(content,gpdu->phone_attr);
/* 8. 将接受方的手机号拼接到content数组中 */
strcat(content,gpdu->phone);
/* 9. 将手机号后面的固定格式拼接到content数组中 */
strcat(content,gpdu->fix);
/* 10.将消息的实际内容拼接到content数组中 */
strcat(content,unicode_msg);
/* 11.返回:PDU总长度减去SIM用户识别卡所占字节*/
return (strlen(content) - nsim) ;
}
/* ----- end of function make_content ----- */
/*}}}*/
/*
* === FUNCTION ======================================================================
* Name: send_msg
* Description: 功能:发送信息
* =====================================================================================
*/
/*{{{*/
void send_msg ( int fd,char *content,int len,char *dail )
{
char cmd_buff[C_SIZE];
char call_buff[C_SIZE] = "ATD"; /* 拨号功能 */
int n_rw = 0;
printf("Start:/n");
/* 第一阶段:先发送 "AT" 命令,测试ARM与GPRS是否建立通信 */
write(fd,"AT/r",3);
printf("1. Send AT/n");
#ifdef SLEEP3S
sleep(3);
#endif
memset(cmd_buff,C_SIZE);
n_rw = read(fd,cmd_buff,C_SIZE);
printf("Receive %d bytes is %s/n",n_rw,cmd_buff);
/* 第二阶段:设置信息的模式 0:PDU,1:Plain */
write(fd,"AT+CMGF=0/r",10);
printf("2. Send AT+CMGF=0/n");
#ifdef SLEEP3S
sleep(3);
#endif
memset(cmd_buff,cmd_buff);
/* 第三阶段:PDU模式下发送消息密令 */
memset(cmd_buff,C_SIZE);
sprintf(cmd_buff,"AT+CMGS=%d/r",len);
write(fd,strlen(cmd_buff));
printf("3. Send %s/n",cmd_buff);
#ifdef SLEEP3S
sleep(3);
#endif
memset(cmd_buff,cmd_buff);
/* 第四阶段:发送消息内容,以0x1A结尾 */
strcat(content,"/x1a");
n_rw = write(fd,content,strlen(content));
printf("4. Send %d Message /n",n_rw);
#ifdef SLEEP3S
sleep(3);
#endif
memset(cmd_buff,cmd_buff);
/* 第五阶段:实现拨号 */
if ( NULL != dail )
{
sleep(10);
strncat(call_buff,dail,11);
printf("call_buff :%s/n",call_buff);
strcat(call_buff,";/r");
write(fd,call_buff,strlen(call_buff));
printf("Call some one!/n");
memset(cmd_buff,cmd_buff);
printf("/nEnd/n");
}
return ;
}
/* ----- end of function send_msg ----- */
/*}}}*/