2012-08-25 | #1 (permalink) |
论坛管理员
注册日期: 2009-06-30
帖子: 861
|
CDMA短信发送程序
CDMA短信发送程序
写了一个通过CDMA Modem发送短信的小程序,在桌面环境和嵌入式环境下测试通过。涉及到的内容有:串口编程、termios有关的终端IO设置、modem的设置、AT指令集的运用、GB2312字符集向UNICODE字符集编码的转换。测试所用的短信内容为:welcome to 成电。测试结果良好。程序中有关字符集编码转换的三个函数iconv_open()、iconv()、iconv_close()请参见GNU的文档;有关终端IO请参见《UNIX环境高级编程》;有关AT指令集的部分请参见WAVECOM公司的《CDMA AT command interface specification v1.78》。 1 /* 2 * $file: cdmasms_en.c 3 * $auth: rockins 4 * $desc: send English SMS via CDMA modem 5 * $date: Sun Jan 21 04:41:20 CST 2007 6 */ 7 #include <stdio.h> 8 #include <stdlib.h> 9 #include <errno.h> 10 #include <sys/types.h> 11 #include <sys/stat.h> 12 #include <fcntl.h> 13 #include <termios.h> 14 #include <iconv.h> 15 #include <unistd.h> 16 17 #define CTRL_Z "\x00\x1A" /*finish sms input*/ 18 #define CTRL_Z_LEN 2 /*length of CTRL_Z*/ 19 #define ESC "\x00\x1B" /*abort sms input*/ 20 #define ESC_LEN 2 /*length of ESC*/ 21 #define CR '\r' /*carriage return*/ 22 #define NL '\n' /*next line*/ 23 #define ST_REP "+CDS" /*sms-status-report*/ 24 25 #define SERIAL "/dev/ttyS1" /*serial port*/ 26 #define MAX_SZ 1024 /*buffer size*/ 27 #define SMS_LEN 140 /*max length of sms*/ 28 #define RETRY 20 /*retry time*/ 29 30 static int CDMAGB2312toUNICODEBIG(char *in, 31 size_t instrlen, char *out, size_t outbufsiz); 32 33 int 34 main(int argc, char *argv[]) 35 { 36 int CDMAFd; 37 int err = 0; 38 /*GB2312 message: welcome to 成电*/ 39 char message[] = "\x77\x65\x6C\x63\x6F\x6D\x65" 40 "\x20\x74\x6F\x20\xB3\xC9\xB5\xE7"; 41 42 /*check command-line*/ 43 if (argc != 3) { 44 printf("usage:%s tel sms\n", argv[0]); 45 printf("sms must be in English\n"); 46 exit(-1); 47 } 48 49 CDMAFd= CDMAOpenModem(SERIAL); 50 if (CDMAFd < 0) { 51 printf("open CDMA Modem %s failed!\n", SERIAL); 52 return (-1); 53 } 54 55 err = CDMASetModemParams(CDMAFd); 56 if (err < 0) 57 goto fail; 58 59 err = CDMAInitModem(CDMAFd); 60 if (err < 0) 61 goto fail; 62 63 err = CDMASendSMS(CDMAFd, argv[1], message); 64 if (err < 0) 65 goto fail; 66 67 CDMACloseModem(CDMAFd); 68 printf("send Chinese(Unicode) SMS success!\n"); 69 return (0); 70 71 fail: 72 CDMACloseModem(CDMAFd); 73 printf("send Chinese(Unicode) SMS failed!\n"); 74 return (-1); 75 } 76 77 /* 78 * open CDMA Modem device 79 * params: 80 * CDMADevice: device namde 81 * returns: 82 * non-negtive file descriptor if success, 83 * else -1 84 */ 85 int 86 CDMAOpenModem(char *CDMADevice) 87 { 88 int fd; 89 90 /* 91 * open CDMA serial port, O_NOCTTY means it's 92 * not a controll tty device, O_NDELAY means 93 * it's not block 94 */ 95 fd = open(CDMADevice, O_RDWR | O_NOCTTY); 96 if (fd < 0) { 97 perror("open()"); 98 return (-1); 99 } 100 return (fd); 101 } 102 103 /* 104 * close modem 105 */ 106 int 107 CDMACloseModem(int CDMAFd) 108 { 109 return (close(CDMAFd)); 110 } 111 112 /* 113 * establish working settings 114 * params: 115 * CDMAFd: file descriptor of CDMA modem 116 * returns: 117 * 0 if set success, else -1 118 * note(default setting): 119 * speed: 115200 bps 120 * databit: 8 bits 121 * parity: none 122 * stopbit: 1 bit 123 */ 124 int 125 CDMASetModemParams(int CDMAFd) 126 { 127 struct termios term_opt; 128 129 /* 130 * get current attributes 131 */ 132 tcgetattr(CDMAFd, &term_opt); 133 134 /* 135 * set attribute to 8N1 136 */ 137 term_opt.c_cflag &= ~CSIZE; 138 term_opt.c_cflag |= CS8; /*8 bit databit*/ 139 term_opt.c_cflag &= ~PARENB; /*disable parity*/ 140 term_opt.c_cflag &= ~CSTOPB; /*set 1 bit stopbit*/ 141 142 /* 143 * set in&out serial port speed to 115200 bps 144 */ 145 cfsetispeed(&term_opt, B115200); 146 cfsetospeed(&term_opt, B115200); 147 148 /* 149 * set to raw mode 150 */ 151 cfmakeraw(&term_opt); 152 153 /* 154 * set reading timeout to 5 seconds 155 */ 156 term_opt.c_cc[VMIN] = 0; 157 term_opt.c_cc[VTIME] = 100; /*timeout: 10 seconds*/ 158 159 /* 160 * make new attr be committed 161 */ 162 tcsetattr(CDMAFd, TCSANOW, &term_opt); 163 } 164 165 /* 166 * check if CDMA work correctly? 167 * params: 168 * CDMAFd: the file descritor of CDMA Modem 169 * returns: 170 * 0 if work healthy,else -1 171 * note: 172 * according AT command manual, if send "AT" to DCE and 173 * it response "OK", then can treat the device is 174 * working correctly. 175 */ 176 int 177 CDMAInitModem(int CDMAFd) 178 { 179 unsigned char cmd_buf[MAX_SZ]; 180 int retry; 181 int len; 182 183 /*flush data received and transimitted*/ 184 tcflush(CDMAFd, TCIOFLUSH); 185 186 /*issue AT command*/ 187 memset(cmd_buf, 0, MAX_SZ); 188 strncpy(cmd_buf, "AT\r", MAX_SZ); 189 len = write(CDMAFd, cmd_buf, strnlen(cmd_buf, MAX_SZ)); 190 if (len != strnlen(cmd_buf, MAX_SZ)) { 191 perror("write()"); 192 return (-1); 193 } 194 195 for (retry = 0; retry < RETRY; retry++) { 196 /*wait for 1 second*/ 197 sleep(1); 198 199 memset(cmd_buf, 0, MAX_SZ); 200 if ((len = read(CDMAFd, cmd_buf, MAX_SZ)) < 0) { 201 perror("read()"); 202 continue; 203 } 204 205 if (strstr(cmd_buf, "OK")) 206 return (0); 207 } 208 209 return (-1); 210 } 211 212 /* 213 * send SMS via the CDMA modem 214 * params: 215 * CDMAFd: file descriptor 216 * msg: message to send 217 * returns: 218 * 0 if success, else -1 219 * note: 220 * message must be in TEXT mode, 221 * CDMA do not support PDU mode as GSM does. 222 * tel must be 13xxxxxxxxx format, no +prefix, 223 * message should be pure English words. 224 */ 225 int 226 CDMASendSMS(int CDMAFd, char *phone, char *msg) 227 { 228 char buf[MAX_SZ]; /*command and response buffer*/ 229 int len; /*length written*/ 230 int cmd_len; /*AT command's length*/ 231 char *msg_p; /*point to msg*/ 232 int msg_len; /*msg's length, in bytes*/ 233 char conv_buf[MAX_SZ]; /*buff for encode conversion*/ 234 int conv_len; /*converted msg's length*/ 235 int retry; /*retry time*/ 236 237 /* AT+CMGF=1\r set in TEXT mode, whereas AT+CMGF=0\r 238 * is PDU mode, which is not supported by CDMA*/ 239 memset(buf, 0, MAX_SZ); 240 cmd_len = snprintf(buf, MAX_SZ, "AT+CMGF=1\r"); 241 len = write(CDMAFd, buf, cmd_len); 242 if (len != cmd_len) { 243 perror("write()"); 244 return (-1); 245 } 246 247 /*set language and encoding: 6,4 means Chinese,unicode*/ 248 memset(buf, 0, MAX_SZ); 249 cmd_len = snprintf(buf, MAX_SZ, "AT+WSCL=6,4\r"); 250 len = write(CDMAFd, buf, cmd_len); 251 if (len != cmd_len) { 252 perror("write()"); 253 return (-1); 254 } 255 256 /*convert from GB2312 to UNICODE*/ 257 msg_len = strnlen(msg, MAX_SZ); 258 memset(conv_buf, 0, MAX_SZ); 259 if ((conv_len = CDMAGB2312toUNICODEBIG(msg, msg_len, 260 conv_buf, MAX_SZ)) < 0) { 261 printf("convert encoding failed!\n"); 262 return (-1); 263 } 264 265 if (conv_len> SMS_LEN) { 266 printf("too long SMS,SMS must not be more than" 267 " 140 English words or 70 Chinese words\n"); 268 return (-1); 269 } 270 271 /*send message*/ 272 memset(buf, 0, MAX_SZ); 273 cmd_len = snprintf(buf, MAX_SZ, "AT+CMGS=\"%s\",%d\r", 274 phone, conv_len); 275 msg_p = buf + cmd_len; 276 memcpy(msg_p, conv_buf, conv_len); 277 msg_p = buf + cmd_len + conv_len; 278 279 /*below is critical area*/ 280 memcpy(msg_p, CTRL_Z, CTRL_Z_LEN); 281 len = write(CDMAFd, buf, cmd_len + conv_len + CTRL_Z_LEN); 282 if (len != (cmd_len + conv_len + CTRL_Z_LEN)) { 283 perror("write()"); 284 return (-1); 285 } 286 287 /*waiting for acknowledge from the SMS center*/ 288 for (retry = 0; retry < RETRY; retry++) { 289 /*wait for 1 second*/ 290 sleep(1); 291 292 len = 0; 293 memset(buf, 0, MAX_SZ); 294 if ((len = read(CDMAFd, buf, MAX_SZ)) > 0) { 295 printf("%s\n", buf); 296 297 /*positive acknoledge*/ 298 if (strstr(buf, ST_REP)) 299 return (0); 300 } 301 } 302 303 return (-1); 304 } 305 306 /* 307 * convert GB2312 to UNICODE 308 * params: 309 * in: input GB2312 string 310 * instrlen: input bytes number 311 * out: output UNICODE big-endian string 312 * outbufsiz: output buffer's size 313 * returns: 314 * if success return output encoding's 315 * length in byte; else return -1 316 */ 317 static int 318 CDMAGB2312toUNICODEBIG(char *in, size_t instrlen, 319 char *out, size_t outbufsiz) 320 { 321 char *in_p = in; 322 char *out_p = out; 323 size_t inbytesleft = instrlen; 324 size_t outbytesleft = outbufsiz; 325 size_t err = 0; 326 iconv_t cd; 327 328 cd = iconv_open("UNICODEBIG", "GB2312"); 329 if (cd == (iconv_t)(-1)) { 330 perror("iconv_open()"); 331 return (-1); 332 } 333 334 err = iconv(cd, &in_p, &inbytesleft, 335 &out_p, &outbytesleft); 336 if (err == (size_t)(-1)) { 337 perror("iconv()"); 338 return (-1); 339 } 340 341 err = iconv_close(cd); 342 if (err == -1) { 343 perror("iconv_close()"); 344 return (-1); 345 } 346 347 return (outbufsiz - outbytesleft); /*output encode length*/ 348 }
__________________
让世界倾听我们的笛声 |