首页 > 代码库 > Java应用短信猫

Java应用短信猫

首先确定短信猫正常连接到主机,并安装SIM卡。
先用超级终端测试短息猫能不能用。
安装minicom:
#sudo apt-get install minicom
安装完成后,执行
#sudo minicom -s

java开发短信猫在Ubuntu下使用 - 暗夜血狂 - 暗夜的博客

使用光标上下选择:Serial port setup,如下图

java开发短信猫在Ubuntu下使用 - 暗夜血狂 - 暗夜的博客

 按A,设置端口号,COM1对应/dev/ttyS0,
按E,修改波特率、奇偶校验等,我的短信猫波特率用的是默认,
按F,将Hardware Flow Control变为NO,
按Enter键,返回,
选择Save setup as dfl,即作为默认配置,
选择Exit,进入到Minicom:

java开发短信猫在Ubuntu下使用 - 暗夜血狂 - 暗夜的博客

 输入at,按Enter,若打印出ok,则正常。
输入at+cmgf=1,设置短信格式,1是文本格式,0是PDF格式,
输入at+cmgs=xxxxx,接收手机号码,Enter,接着输入内容,按Ctrl+Z,等待,
界面打印OK,手机接收短信。
超级终端成功,接下来调试Java代码,我使用的jar包是jssc-2.8.0.jar
下面是代码:

package com.sendSMS;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import jssc.SerialPort;
import jssc.SerialPortEvent;
import jssc.SerialPortEventListener;
import jssc.SerialPortException;
import jssc.SerialPortList;
public class Sender {
private String msgCenterPhone;
private String portName;
private int baud;
private int parity;
private int stop;
private int data;
private int gsmType;
private SerialPort serialPort;
/** AT+CMGS= */
public final static byte[] SMS_STRUCTOR = {
0x41, 0x54, 0x2B, 0x43, 0x4D, 0x47, 0x53, 0x3D};
/** AT+CMGF=0 */
public final static byte[] SMS_PDU_HEADER = {
0x41, 0x54, 0x2B, 0x43, 0x4D, 0x47, 0x46, 0x3D, 0x30};
public final static byte[] SMS_HEADER_START = {
0x41, 0x54, 0x2B, 0x43, 0x4D, 0x47, 0x53, 0x3D};
public final static byte[] SMS_HEADER_END = {
0x0D};
public final static byte[] SMS_CONTENT_END = {
0x1A};
public void setCenterPhone(String phoneNumber) {
this.msgCenterPhone = phoneNumber;
}
public void setSerialPort(String portName) {
this.portName = portName;
}
public void setParams(int baudRate, int parity, int stop, int data) {
this.baud = baudRate;
this.parity = parity;
this.stop = stop;
this.data =http://www.mamicode.com/ data;
}
public void setGSMType(int gsmType) {
this.gsmType = gsmType;
}
public Sender() {
//msgCenterPhone = msgCenterPhone.trim();
portName = "COM10";
baud = 115200;
parity = 0;
stop = 1;
data = 8;
gsmType = 2;
}
public Sender(String phoneNo, String portName, int gsmType) {
msgCenterPhone = phoneNo;
this.portName = portName;
baud = 115200;
parity = 0;
stop = 1;
data = 8;
this.gsmType = gsmType;
}
/**
* 确认发送格式并发送短信,将长短信分为N条正常短信
* @param mobileSendAlarmInfo
* @return 1:发送成功;-1:发送失败
*/
public int sendSMS(String destPhone, String content){
/**
* 发送成功标志
*/
int succeedFlag = 0;
serialPort = new SerialPort(this.portName);
try {
System.out.println("Port opened:" + serialPort.openPort());
System.out.println("Params setted:" + serialPort.setParams(115200, 8 , 1, 0));
System.out.println("Send PDU Header" + serialPort.writeBytes(SMS_PDU_HEADER));
System.out.println("Send Header End" + serialPort.writeBytes(SMS_HEADER_END));
int timeout = 0;
while (true) {
Thread.sleep(100);
byte[] b = new byte[21];
b = serialPort.readBytes();
if (timeout > 50) {
System.out.println("Time Out");
return succeedFlag = -1;
}
if (b == null) {
timeout++;
continue;
}
String s = new String(b);
if (s.indexOf("OK") != -1) { //‘OK‘
System.out.println("Set PDU Successful!");
break;
}
}
int[] tpduLength = new int[1];
String pack = packStrMessage(destPhone, content, msgCenterPhone,
tpduLength);
System.out.println("Send Header Start" + serialPort.writeBytes(SMS_HEADER_START));
String strLength = (tpduLength[0] < 100 ?
("0" + Integer.toString(tpduLength[0])) :
Integer.toString(tpduLength[0]));
System.out.println("Send Header Length"+ serialPort.writeBytes(strLength.getBytes()));
System.out.println("Send Header End" + serialPort.writeBytes(SMS_HEADER_END));
Thread.sleep(100);
timeout = 0;
while (true) {
Thread.sleep(100);
byte[] b = new byte[21];
b = serialPort.readBytes();

if (timeout > 50) {
System.out.println("Time Out");
return succeedFlag = -1;
}
if (b == null) {
timeout++;
continue;
}
String s = new String(b);
if (s.indexOf(‘>‘) != -1) { //‘>‘
System.out.println("Title Successful!");
break;
}
if (s.indexOf("ERROR") != -1) { //‘R‘
System.out.println("Error");
return succeedFlag = -1;
}
}
System.out.println("Send Content: " + serialPort.writeBytes(pack.getBytes()));
System.out.println("Send Contend End: " + serialPort.writeBytes(SMS_CONTENT_END));
System.out.println("Send Header End: " + serialPort.writeBytes(SMS_HEADER_END));
timeout = 0;
while (true) {
Thread.sleep(100);
byte[] b = new byte[21];
b = serialPort.readBytes();
if (timeout > 50) {
System.out.println("Time Out");
return succeedFlag = -1;
}
if (b == null) {
timeout++;
continue;
}
String s = new String(b);
System.out.println(s);
//System.exit(0);
if (s.indexOf("OK") != -1) { //‘>‘
System.out.println("Content Successful!");
serialPort.closePort();
return succeedFlag = 1;
}
if (s.indexOf("ERROR") != -1) { //‘R‘
System.out.println("Error");
return succeedFlag = -1;
}
}    
} catch (SerialPortException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return succeedFlag;
}
private String packStrMessage(String destPhone, String content,
String centerPhone, int[] tpduLength) {
if (destPhone == null || content == null || centerPhone == null)
return "";
//encode the SCA
byte[] sca = new byte[3];
sca[0] = (byte) (0x00);
sca[1] = (byte) 0x11;
sca[2] = (byte) 0x00;
//encode TPDU
if (!destPhone.startsWith("86")) //add china code 86 to dest phone. 81 为日本的代码
destPhone = "86" + destPhone;
int length;
int destLength = length = destPhone.length();
if (length % 2 != 0) { //if the dest code is odd , then add ‘F‘
destPhone += "F";
length++;
}
//content += new String( new char[]{ 0x00 } );
char[] ccontent = content.toCharArray();
int contentLength = ccontent.length;
/* Data Length
* Dest Phone(encoding) | Data(encoding)
* _________|__________ | _____|________
* The tpdu‘ sample byte 11 00 0D 91 68 31 19 01 28 14 F1 00 00 00 05 D4 E2 94 0A 02
* | | | | | | |
* | | | TON/NPI | | VP Validity Period
* | | Dest Phone Length(Number) | DCS Data Coding Scheme(00-ASCII , 08-UCS2)
* | MR Message Reference PID Protocol ID
* 8 Bits MTI,RD,VPF,SRR,UDHI,RP,MMS,SRI
* so 4 + phoneLength / 2 + 3 + 1 + contenLength is the tpdu length
*/
byte[] tpdu = new byte[2 + length / 2 + 3 + 1 + contentLength * 2];
int index = 0;
tpdu[index++] = (byte) destLength;
tpdu[index++] = (byte) 0x91;
for (int i = 0; i < length; i += 2) {
tpdu[index++] = swap(destPhone.substring(i, i + 2), 16);
}
tpdu[index++] = 0x00;
tpdu[index++] = 0x08; //UCS2
tpdu[index++] = (byte) 0xA7;
tpdu[index++] = (byte) (contentLength * 2);
for (int i = 0; i < contentLength; i++) {
if (i < ccontent.length) {
tpdu[index++] = (byte) (ccontent[i] >> 8);
tpdu[index++] = (byte) (ccontent[i] & 0x00FF);
} else {
tpdu[index++] = (byte) (0xFF);
tpdu[index++] = (byte) (0xFF);
}
}
//copy sca and tpdu to ret
int scaLength = sca.length;
tpduLength[0] = tpdu.length + 2;
byte[] ret = new byte[scaLength + tpdu.length];
System.arraycopy(sca, 0, ret, 0, scaLength);
System.arraycopy(tpdu, 0, ret, scaLength, tpdu.length);
String r = new String();
for (int i = 0; i < ret.length; i++) {
String s = Integer.toHexString( (char) ret[i] & 0x00ff);
if (s.length() == 1)
s = "0" + s;
r += s;
}
//System.out.println( r );
return r;
}
//swap the string and parse it as specail radix byte,just same binary code.
//note: the s must has two length string.
//eg. swap( "12" , 16 ) will return byte 33
//eg. swap( "68" , 16 ) will return byte -122
public static byte swap(String s, int radix) {
byte b1 = Byte.parseByte(s.substring(0, 1), radix);
byte b2 = Byte.parseByte(s.substring(1, 2), radix);
return (byte) (b2 * radix + b1);
}
public String toString() {
StringBuffer sb = new StringBuffer();
sb.append("The SMS Properties:\n");
sb.append("\nSerial Port=" + serialPort);
sb.append("\nBaud=" + baud);
sb.append("\nData Bits=" + data);
sb.append("\nStop Bit=" + stop);
sb.append("\nParity=" + parity);
sb.append("\nSMS Center Phone=" + msgCenterPhone);
return sb.toString();
}
public static void main(String[] args) {
Sender sender = new Sender("13800210500", "/dev/ttyS0", 2);//SIM卡所在地短信中心号码、端口号、SIM卡类型默认2即可
int code = sender.sendSMS("xxxxxxxxxxx", "Just for a test");//接收号码、内容
System.out.println(code);
}
}

编译,还是不行,看下log,好吧,是权限问题,接下来在超级终端中运行:
#sudo chmod 777 /dev/ttyS0
再次编译,手机接到短信了,OK。

在Windows中把端口号换成"COM1"就行了。