Java使用短信猫发信息(向串口发送AT指令)

使用Java发送短信息的方式有两种:

1>使用第三方平台的http请求进行发送,优点是接口简单,使用方便,发送的效率高,多条可以同时发送,缺点是短信平台,三大运营商不提供接口,都是第三方平台,但是第三方平台不稳定,如果倒闭,将意味着这套代码请求的服务器倒闭,则代码失效,需要再找另外的第三方公司;

2>硬件设备,短信猫,比如深圳宏电的H6221GPRS Mode模块,优点是发送稳定,不会出现担心第三方平台倒闭而重写代码的风险,缺点是需要硬件,资费是正常的短信价格,一台设备同一时间只能发送一条信息,成本较高;

下面给出使用短信猫发信息的Java代码:

下载所需jar包

1,字符编码转换工具类:

<span style="font-size:18px;">package sms;
/**
 * 短信发送字符编码工具类
 * @author Anlw
 *
 */
public class StringUtil {
	/**
	 * 将PDU编码的十六进制字符串 如“4F60597DFF01” 转换成unicode "\u4F60\u597D\uFF01"
	 * @param str 要转化的字符串
	 * @return 转换后的十六进制字符串
	 */
	public static String analyseStr(String str) {
		StringBuffer sb = new StringBuffer();
		if (!(str.length() % 4 == 0))
			return str;
		for (int i = 0; i < str.length(); i++) {
			if (i == 0 || i % 4 == 0) {
				sb.append("\\u");
			}
			sb.append(str.charAt(i));
		}
		return Unicode2GBK(sb.toString());
	}

	/**
	 * 将unicode编码 "\u4F60\u597D\uFF01" 转换成中文 "你好!"
	 * @param dataStr 要转化的字符串
	 * @return 转换后的中文字符串
	 */
	public static String Unicode2GBK(String str) {
		int index = 0;
		StringBuffer buffer = new StringBuffer();
		while (index < str.length()) {
			if (!"\\u".equals(str.substring(index, index + 2))) {
				buffer.append(str.charAt(index));
				index++;
				continue;
			}
			String charStr = "";
			charStr = str.substring(index + 2, index + 6);
			char letter = 0;
			try{letter = (char) Integer.parseInt(charStr, 16);}catch (Exception e) {}
			buffer.append(letter);
			index += 6;
		}
		return buffer.toString();
	}

	/**
	 * 将中文字符串转换成Unicode
	 * @param str 要转换的中文字符串
	 * @return 转换后的Unicode
	 */
	public static String GBK2Unicode(String str) {

		StringBuffer result = new StringBuffer();

		for (int i = 0; i < str.length(); i++) {

			char chr1 = (char) str.charAt(i);

			if (!isNeedConvert(chr1)) {

				result.append(chr1);

				continue;

			}
			try{result.append("\\u" + Integer.toHexString((int) chr1));}catch (Exception e) {}

		}

		return result.toString();

	}

	/**
	 * 在中文字符串转换成Unicode方法中判断是否需要转换
	 * @param para 要转化的字符
	 * @return boolean
	 */
	public static boolean isNeedConvert(char para) {
		return ((para & (0x00FF)) != para);

	}

	/**
	 * 使用Sms 的 SendSms()方法发送短信时,调用此方法将其短信内容转换成十六进制
	 * @param msg 短信内容
	 * @return 转换后的十六进制短信
	 */
	public static final String encodeHex(String str) {
		byte[] bytes = null;
		try {
			bytes = str.getBytes("GBK");
		} catch (java.io.UnsupportedEncodingException e) {
			e.printStackTrace();
		}
		StringBuffer buff = new StringBuffer(bytes.length * 4);
		String b = "";
		char a;
		int n = 0;
		int m = 0;
		for (int i = 0; i < bytes.length; i++) {
			try{b = Integer.toHexString(bytes[i]);}catch (Exception e) {}
			if (bytes[i] > 0) {
				buff.append("00");
				buff.append(b);
				n = n + 1;
			} else {
				a = str.charAt((i - n) / 2 + n);
				m = a;
				try{b = Integer.toHexString(m);}catch (Exception e) {}
				buff.append(b.substring(0, 4));

				i = i + 1;
			}
		}
		return buff.toString();
	}
}</span>
2,端口实体类,包括操作端口的方法:
<span style="font-size:18px;">package sms;

import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.Random;

import javax.comm.CommPortIdentifier;
import javax.comm.NoSuchPortException;
import javax.comm.PortInUseException;
import javax.comm.SerialPort;
import javax.comm.UnsupportedCommOperationException;
/**
 * 串口操作实现类
 * @author Anlw
 *
 */
public class Port {
	private CommPortIdentifier portId;
	private SerialPort serialPort;
	private OutputStreamWriter out;
	private InputStreamReader in;
	private String COMname;

	public String getCOMname() {
		return COMname;
	}

	public void setCOMname(String mname) {
		COMname = mname;
	}

	public CommPortIdentifier getPortId() {
		return portId;
	}

	public void setPortId(CommPortIdentifier portId) {
		this.portId = portId;
	}

	public SerialPort getSerialPort() {
		return serialPort;
	}

	public void setSerialPort(SerialPort serialPort) {
		this.serialPort = serialPort;
	}

	public OutputStreamWriter getOut() {
		return out;
	}

	public void setOut(OutputStreamWriter out) {
		this.out = out;
	}

	public InputStreamReader getIn() {
		return in;
	}

	public void setIn(InputStreamReader in) {
		this.in = in;
	}

	public boolean isused = true;

	public boolean isIsused() {
		return isused;
	}

	public void setIsused(boolean isused) {
		this.isused = isused;
	}

	/**
	 * 构造器打开com口 
	 * @param portName
	 * @return
	 */	
	public Port(String portName) {
		try {
			portId = CommPortIdentifier.getPortIdentifier(portName);
			if (portId == null) {
				System.out.println("port is null");
			}
			try {
				serialPort = (SerialPort) portId.open(getrechargeablePassword(), 20000);
			} catch (PortInUseException e) {
				System.gc();
				System.out.println("COM端口被占用,请选择正确的COM端口!!");
			}
			// 下面是得到用于和COM口通讯的输入、输出流。
			try {
				in = new InputStreamReader(serialPort.getInputStream());
				out = new OutputStreamWriter(serialPort.getOutputStream());
			} catch (Exception e) {
				System.gc();
			}
			// 下面是初始化COM口的传输参数,如传输速率:9600等
			try {
				serialPort.setSerialPortParams(9600, SerialPort.DATABITS_8, SerialPort.STOPBITS_1,
						SerialPort.PARITY_NONE);
				setCOMname(portId.getName());
				setIsused(true);
			} catch (Exception e) {
				System.gc();
			}

		} catch (NoSuchPortException e) {
			System.gc();
			System.out.println("无此COM端口,请选择正确的COM端口!!");
		}
	}

	// 获取密码
	public static String getrechargeablePassword() {
		Random random = new Random();
		char[] codeSequence = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q',
				'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'c',
				'b', 'd', 'f', 'e', 'g', 'h', 'j', 'i', 'l', 'k', 'n', 'm', 'o', 'p', 'q', 'r', 's', 't', 'u', 'w',
				'v' };
		String strRand = "";
		for (int i = 0; i < 18; i++) {
			strRand = strRand + String.valueOf(codeSequence[random.nextInt(59)]);
		}
		return strRand;
	}

	/**
	 * 关闭COM口
	 * @return boolean
	 */
	public void close() {
		try {
			in.close();
			out.close();
			serialPort.close();
			System.gc();
			setIsused(false);
		} catch (Exception e) {
		}
		
	}

	/**
	 * 向串口中写入字符串命令
	 * @param s 字符串命令
	 * @throws Exception 异常
	 */
	public void writeln(String s) throws Exception {
		out.write(s);
		out.write('\r');
		out.flush();
	}

	/**
	 * 读取COM命令的返回字符串
	 * @return 结果字符串
	 * @throws Exception
	 */
	public String read() throws Exception {
		int n, i;
		char c;
		String answer = "";
		for (i = 0; i < 100; i++) {
			while (in.ready()) {
				n = in.read();
				if (n != -1) {
					c = (char) n;
					answer = answer + c;
					Thread.sleep(1);
				} else
					break;
			}
			if (answer.indexOf("OK") != -1) {
				break;
			}
			Thread.sleep(100);
		}
		return answer;
	}

	/**
	 * 向串口发送AT指令
	 * @param atcommand 指令内容
	 * @return 指令返回结果
	 * @throws java.rmi.RemoteException
	 */
	public String sendAT(String atcommand) throws java.rmi.RemoteException {
		String returnStr = "";
		try {
			Thread.sleep(100);
			writeln(atcommand);
			Thread.sleep(80);
			returnStr = read();
			Thread.sleep(150);
		} catch (Exception e) {
			System.gc();
		}
		return returnStr;
	}
}
</span>
3,短信息载体实体类:
<span style="font-size:18px;">package sms;
/**
 * 短信实体类
 * @author Anlw
 *
 */
public class CommonSms{

	//内容
	private String smstext;
	//发送者
	private String sender;
	//接收者
	private String recver;
	//状态
	private String state;

	public String getSmstext() {
		return smstext;
	}
	public void setSmstext(String smstext) {
		this.smstext = smstext;
	}
	public String getSender() {
		return sender;
	}
	public void setSender(String sender) {
		this.sender = sender;
	}
	public String getRecver() {
		return recver;
	}
	public void setRecver(String recver) {
		this.recver = recver;
	}
	public String getState() {
		return state;
	}
	public void setState(String state) {
		this.state = state;
	}
	

	
}
</span>
4,发送核心代码:
<span style="font-size:18px;">package sms;

import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;

import javax.comm.CommPortIdentifier;

/**
 * 短信息发送
 * @author Anlw
 *
 */
public class Sms {

	private CommonSms commonsms;
	private static char symbol1 = 13;
	private static String strReturn = "", atCommand = "";

	private boolean SendSms(Port myport) {
		if (!myport.isIsused()) {
			System.out.println("COM通讯端口未正常打开!");
			return false;
		}
		setMessageMode(myport, 1);
		// 空格
		char symbol2 = 34;
		// ctrl~z 发送指令
		char symbol3 = 26;
		try {
			atCommand = "AT+CSMP=17,169,0,08" + String.valueOf(symbol1);
			strReturn = myport.sendAT(atCommand);
			if (strReturn.indexOf("OK", 0) != -1) {
				atCommand = "AT+CMGS=" + commonsms.getRecver() + String.valueOf(symbol1);
				strReturn = myport.sendAT(atCommand);
				atCommand = StringUtil.encodeHex(commonsms.getSmstext().trim()) + String.valueOf(symbol3)
						+ String.valueOf(symbol1);
				strReturn = myport.sendAT(atCommand);
				if (strReturn.indexOf("OK") != -1 && strReturn.indexOf("+CMGS") != -1) {
					System.out.println("短信发送成功!!");
					return true;
				}
			}
		} catch (Exception ex) {
			System.out.println("短信发送失败!!");
			return false;
		}
		System.out.println("COM端口被占用,请选择正确的COM端口!!");
		System.out.println("短信发送失败!!");
		return false;
	}
	/**
	 * 设置消息模式 
	 * @param op
	 * 0-pdu 1-text(默认1 文本方式 )
	 * @return
	 */
	private boolean setMessageMode(Port myport, int op) {
		try {
			String atCommand = "AT+CMGF=" + String.valueOf(op) + String.valueOf(symbol1);
			String strReturn = myport.sendAT(atCommand);
			if (strReturn.indexOf("OK", 0) != -1) {
				return true;
			}
			return false;
		} catch (Exception ex) {
			ex.printStackTrace();
			return false;
		}
	}

	/**
	 * 号码,内容,发送短信息
	 * @param phone
	 * @param countstring
	 * @throws Exception
	 */
	private static void send(String phone, String countstring, String com) {
		Sms s = new Sms();
		CommonSms cs = new CommonSms();
		cs.setRecver(phone);
		cs.setSmstext(countstring);
		s.setCommonsms(cs);
		Port myort = new Port(com);
		s.SendSms(myort);
		myort.close();
	}
        //短信的字符限制为70,加锁,因为每次只能发送一条,其他的要等待
	public static synchronized void sendSms(String phone, String str, String com) {
		if (str.length() > 70) {
			String done = str.substring(0, 70);
			Sms.send(phone, done, com);
			String todo = str.substring(70, str.length());
			Sms.sendSms(phone, todo, com);
		} else {
			Sms.send(phone, str, com);
		}
	}

	private void setCommonsms(CommonSms commonsms) {
		this.commonsms = commonsms;
	}

	//获取计算机所有可用端口
	public static List<String> getComPort() {

		Enumeration enumeration = CommPortIdentifier.getPortIdentifiers();
		CommPortIdentifier portId;
		List<String> list = new ArrayList<String>();
		while (enumeration.hasMoreElements()) {
			portId = (CommPortIdentifier) enumeration.nextElement();
			if (portId.getPortType() == CommPortIdentifier.PORT_SERIAL) {
				list.add(portId.getName());
			}
		}
		return list;
	}
}</span>

5,测试类:

<span style="font-size:18px;">package sms;

public class Test {
	public static void main(String[] args) {
		 final String str1 = "嘿嘿";
		 		
				
		 final String str2 = "嘻嘻";
		
		Sms.sendSms("13311220311", "str1heihei", "COM6");
//		new Thread(new Runnable() {
//
//			@Override
//			public void run() {
//				Sms.sendSms("13311220311", str1, "COM6");
//			}
//		}).start();
//		new Thread(new Runnable() {
//
//			@Override
//			public void run() {
//				Sms.sendSms("13311220311", str2, "COM6");
//			}
//		}).start();
	}
}
</span>



  • 1
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值