由于前段时间做的系统需要使用短信猫收发短信,所以研究了一下在Java下使用短信猫,网上很多资料都是使用的smslib的jar包来发送短信,但是这种方式只支持32的jdk,而我的系统使用的是linux的64位环境,所以最后采用了用RXTX串口通讯工具直接向短信猫发送AT指令的方式实现。

1. smslib.jar收发短信

java调用短信猫发送短信。 这里的短信猫主要使用RS232串口与服务器通信。smslib.jar 需要用到java串口通信需要用到的comm.jar,win32com.dll和javax.comm.properties。
下载地址:短信猫java二次开发包smslib及使用示例
具体的使用可以参考短信猫java二次开发包源代码smslib-3.5.4.jar

2. RXTX串口通讯工具和短信猫收发短信关键代码

2.1. 短信猫串口通讯工具 rxtx-2.2pre2-bins

Win64位系统将RXTXcomm.jar拷贝到\jre\lib\ext目录下,win64文件夹中的rxtxSerial.dll 拷贝到\jre\bin 目录下。
Linux系统将RXTXcomm.jar拷贝/jre/lib/ext 目录下,librxtxSerial.so文件拷贝到 /jre/lib/[machine type] (i386 for instance) 中
若运行时找不到rxtxSerial 类,则拷贝到/usr/lib/jvm/java-6-sun-1.6.0.26(根据情况而定)/jre/lib/[machine type] (i386/amd64)
以上jre目录都已当前jre运行环境目录为准

2.2 将发送的短信进行PDU格式编码

package com.rxtx.util;import java.util.regex.Matcher;
import java.util.regex.Pattern;import com.sms.util.Convert;/**** 发送pdu格式短信工具*/
public class SendUtil {static String regEx = "[\u4e00-\u9fa5]";//中文static Pattern pat = Pattern.compile(regEx);public static void main(String[] args) throws Exception {String text =encodeHex("test");System.out.print(text);}/*** 使用PDU方式发送消息 * @param phone* @param msg* @return AT指令*/public static final String PDUEncoder(String phone,String msg){String sendcontent ="";String len="";if(isContainsChinese(msg)){ //短信包含中文sendcontent= "0011000D91" + reverserNumber(phone) + "000801" + PDUUSC2ContentEncoder(msg) ;}else{sendcontent= "0011000D91" + reverserNumber(phone) + "000001" + PDU7BitContentEncoder(msg) ;}len = (sendcontent.length() - Integer.parseInt(sendcontent.substring(0, 2), 16) * 2 - 2) / 2 +"";  //计算长度if(len.length()<2) len="0"+len;
//      return "AT+CMGS=" + len + "\r" + sendcontent + String.valueOf(26);  //26 Ctrl+Z ascii码return len+","+sendcontent;}/*** 获取短信内容的字节数* @param txt* @return*/private static String getLength(String txt){int i = 0;String s = "";i = txt.length() * 2;i += 15;s = i+"";return s;}/*** 将手机号码转换为内存编码* @param phone* @return*/private static String reverserNumber(String phone){String str = "";//检查手机号码是否按照标准格式写,如果不是则补上if (phone.substring(0, 2) != "86"){phone = "86"+phone;}char[] c = getChar(phone);for (int i = 0; i <= c.length - 2; i += 2){str += c[i + 1]+"" + c[i];}return str;}private static char[] getChar(String phone){if (phone.length() % 2 == 0){return phone.toCharArray();}else{return (phone + "F").toCharArray();}}private static boolean isContainsChinese(String str){Matcher matcher = pat.matcher(str);boolean flg = false;if (matcher.find())    {flg = true;}return flg;}/*** 使用Sms 的 SendSms()方法发送短信时,调用此方法将其短信内容转换成十六进制* @param msg 短信内容* @return 转换后的十六进制短信*/public static final String encodeHex(String msg) {byte[] bytes = null;try {bytes = msg.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 = msg.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();}/*** 中文短信内容USC2编码* @param userData* @return*/private static String PDUUSC2ContentEncoder(String userData){String contentEncoding = encodeHex(userData);String length = Integer.toHexString(contentEncoding.length() / 2);//把value的值除以2并转化为十六进制字符串while(length.length()<2) length="0"+length;return length+contentEncoding.toUpperCase();}/*** 英文短信内容7Bit编码* @param userData*/public static String PDU7BitContentEncoder(String userData) {String result = "";String length = Integer.toHexString(userData.length());while(length.length()<2) length="0"+length;//7bit编码 用户数据长度:源字符串长度byte[] Bytes = userData.getBytes();String temp = "";                                     //存储中间字符串 二进制串String tmp;for (int i = userData.length(); i > 0; i--) {tmp = Convert.conver2HexStr(Bytes[i-1]);while (tmp.length() < 7) {tmp = "0" + tmp;}temp += tmp;}for (int i = temp.length() ; i > 0; i -= 8) {                   //每8位取位一个字符 即完成编码 同时高位取为低位if (i > 8) {String aa = Integer.toHexString(Integer.parseInt(temp.substring(i-8, i), 2));while(aa.length()<2) aa="0"+aa;result += aa;} else {String aa = Integer.toHexString(Integer.parseInt(temp.substring(0, i), 2));while(aa.length()<2) aa="0"+aa;result += aa;}}return length+result.toUpperCase();}
}

2.3 以text形式发送短信时短信编码成16进制

/*** 将其短信内容转换成十六进制* @param msg 短信内容* @return 转换后的十六进制短信*/public static final String encodeHex(String msg) {byte[] bytes = null;try {bytes = msg.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 = msg.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();}

2.4 接收短信时解析接收的字符串

/*** 解析MODEM返回来的字符串* 根据MODEM返回的字符串,解析成一个CommonSms的集合对象* @param str MODEM返回的字符串* @return*/public static List<CommonSms> analyseArraySMS(String str) {List<CommonSms> mesList = new ArrayList<CommonSms>();CommonSms cs;String[] messages;String temp;String[] t;if (str.indexOf("CMGL: ") == -1)return null;str = str.substring(0, str.indexOf("OK")).trim();messages = str.split("\n");if (messages.length < 2)return null;for (int i = 0; i < messages.length; i++) {cs = new CommonSms();if(messages[i].length()>=messages[i].indexOf("CMGL: ")+6){messages[i] = messages[i].substring(messages[i].indexOf("CMGL: ") + 6);}           t = messages[i].split(",");//CT5150if (t.length > 5) {t[0] = t[0].replaceAll(":", "");cs.setId(Integer.parseInt(t[0].trim()));temp = t[1].substring(t[1].indexOf('"') + 1,t[1].lastIndexOf('"')).trim();if (temp.equals("REC READ")) {cs.setState("已读");} else {cs.setState("未读");}cs.setSender((t[2].substring(t[2].indexOf('"') + 1, t[2].lastIndexOf('"')).trim()));//CT5150SimpleDateFormat df = new SimpleDateFormat("yy/MM/dd hh:mm:ss");String datestring = t[4].substring(t[4].indexOf('"') + 1) + " "+ t[5].substring(0, t[5].indexOf('"'));// 短信猫时间格式09/09/09// 20:18:01+32Date date = null;try {date = df.parse(datestring);} catch (Exception ex) {System.out.println(ex.getMessage());}cs.setDate(date);i++;cs.setSmstext(analyseStr(messages[i].trim()));mesList.add(cs);}}return mesList;}/*** 将编码的十六进制字符串 如“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 dataStr) {int index = 0;StringBuffer buffer = new StringBuffer();while (index < dataStr.length()) {if (!"\\u".equals(dataStr.substring(index, index + 2))) {buffer.append(dataStr.charAt(index));index++;continue;}String charStr = "";charStr = dataStr.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();}

2.5 发送和接收短信

这里发送短信的设置是,发送英文短信时使用PDU编码,发送中文时使用Text模式发送,这是因为英文短信只有使用PDU编码才会在接收时被识别为英文(这是开发时实践得出的并不知道是为什么)。

private CommonSms commonsms;private static char symbol1 = 13;private static String strReturn = "", atCommand = "";/*** 号码,内容,发送短信息* @param phone* @param countstring* @throws Exception*/public static void sendmsn(String phone,String countstring){Sms s = new Sms();// 发送测试       CommonSms cs=new CommonSms();cs.setRecver(phone);cs.setSmstext(countstring);s.setCommonsms(cs);Port myort=new Port("COM4");System.out.println(myort.isIsused()+"     "+myort.getCOMname());s.SendSms(myort,0);    s.setMessageMode(myort,1);List<CommonSms> recvlist = s.RecvSmsList(myort);if(recvlist!=null){for(CommonSms sms:recvlist){System.out.println("发送人:"+sms.getSender()+"  时间:"+sms.getDate()+"  状态:"+sms.getState());System.out.println("内容:"+sms.getSmstext());}}myort.close();}public boolean SendSms(Port myport,int op) {if(!myport.isIsused()){       System.out.println("COM通讯端口未正常打开!");        return false;}setMessageMode(myport,op);// 空格char symbol2 = 34;// ctrl~z 发送指令char symbol3 = 26;try {if(op==1){atCommand = "AT+CSMP=17,169,0,08" + String.valueOf(symbol1);strReturn = myport.sendAT(atCommand);System.out.println(strReturn);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;}}   }else if(op==0){String[] txt = SendUtil.PDUEncoder(commonsms.getRecver(), commonsms.getSmstext().trim()).split(",");atCommand = "AT+CMGS=" + txt[0] + String.valueOf(symbol1);strReturn = myport.sendAT(atCommand);strReturn = myport.sendAT(txt[1]+ String.valueOf(symbol3) + String.valueOf(symbol1));if (strReturn.indexOf("OK") != -1&& strReturn.indexOf("+CMGS") != -1) {System.out.println("短信发送成功...");return true;}}} catch (Exception ex) {ex.printStackTrace();           System.out.println("短信发送失败...");        return false;}   System.out.println("短信发送失败...");    return false;}/*** 设置消息模式 * @param op* 0-pdu 1-text(默认1 文本方式 )* @return*/public 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) {System.out.println("*************消息模式 设置成功************");return true;}return false;} catch (Exception ex) {ex.printStackTrace();return false;}}   /*** 读取所有短信 * @return CommonSms集合*/public List<CommonSms> RecvSmsList(Port myport) {if(!myport.isIsused()){System.out.println("System Message:  COM通讯端口未正常打开!");       return null;}List<CommonSms> listMes = new ArrayList<CommonSms>();try {atCommand = "AT+CMGL=\"REC UNREAD\"";
//          atCommand = "AT+CMGL=\"ALL\"";
//          AT+CMGL="REC UNREAD"代表显示未读短信清单
//                     AT+CMGL= "REC READ"代表显示已读短信清单
//                     AT+CMGL= "STO SENT"代表显示已发送的存储短信清单
//                     AT+CMGL= "STO UNSENT"代表显示未发送的存储短信清单
//                     AT+CMGL= "ALL"代表显示所有短信清单strReturn = myport.sendAT(atCommand);if(strReturn.contains("ERROR"))System.out.println("System Message:  读取短信出错!");listMes = StringUtil.analyseArraySMS(strReturn);} catch (Exception ex) {ex.printStackTrace();}return listMes;}

3. 短信猫串口相关问题

在使用短信猫时要填写短信猫的串口号,windows下很方便查看,直接填写COM4或者其他的就行,在linux下就有一点麻烦,下面介绍一下我在部署程序时查看串口号的方法,给大家一个参考。

(1)短信猫使用串口转usb连接服务器,那么端口可能是ttyUSB0
直接 ls /dev 查看设备信息,找到ttyUSB*,进而判断短信猫的串口
(2)tail -10 /var/log/messages 可以查看硬件设备插拔变化,查看短信猫是哪个设备
(3)短信猫直接通过串口连接服务器的话
# dmesg | grep tty 或者 setserial -g /dev/ttyS* 显示检测到的系统串口支持

一个简单示例:短信猫用rxtx收发短信Java示例
本文示例:Java 利用RXTX串口工具使用短信猫

Java 利用RXTX串口工具使用短信猫相关推荐

  1. Java调用SMSLib用单口短信猫发送短信详解

    技术园地 当前位置:短信猫网站主页 > 技术园地 > [转载]Java调用SMSLib用单口短信猫发送短信详解 发布时间:2017/02/09 点击量:620 SMSLib是Apache的 ...

  2. Java利用中国网建SMS短信通平台发送手机短信

    JAVA发送手机短信,流传有几种方法: (1)使用webservice接口发送手机短信,这个可以使用sina提供的webservice进行发送,但是需要进行注册; (2)使用短信mao的方式进行短信的 ...

  3. wavecom短信猫推荐RS232串口短信猫适于二次开发应用

    wavecom短信猫是指采用wavecom模块生产的短信猫设备,RS232是基于标准串口连接,与电脑串口直连,免驱动性能稳定,适于短信猫二次开发应用.兼容性好,支持的短信猫软件产品丰富. ‍‍基于RS ...

  4. 短信平台开发之短信猫资料简介

     短信猫 短信猫 所谓短信猫,其实是一种用来收发短信的设备,他和我们用的手机一样,需要手机SIM卡的支持,在需要收发短信的时候,在短信猫里面插入一张我们平时用的手机卡,插上电源,通过(USB或者串口. ...

  5. 短信平台的相关资料之短信猫

     短信猫 短信猫 所谓短信猫,其实是一种用来收发短信的设备,他和我们用的手机一样,需要手机SIM卡的支持,在需要收发短信的时候,在短信猫里面插入一张我们平时用的手机卡,插上电源,通过(USB或者串口. ...

  6. 短信猫(GSM MODEM)安装指南

    短信猫(GSM MODEM)安装指南 短信猫,又名GSM MODEM,专门针对短信应用设计,内含工业级短信发送模块,简化了通信接口,性能稳定可靠,符合各种商业和工业级短信应用要求, 支持向移动.联通以 ...

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

    使用Java发送短信息的方式有两种: 1>使用第三方平台的http请求进行发送,优点是接口简单,使用方便,发送的效率高,多条可以同时发送,缺点是短信平台,三大运营商不提供接口,都是第三方平台,但 ...

  8. 利用java实现的一个发送手机短信的小例子

    今天闲来无事,在微博上看到一个关于用java实现的一个发送手机短信的程序,看了看,写的不太相信,闲的没事,把他整理下来,以后可能用得着 JAVA发送手机短信,流传有几种方法:(1)使用webservi ...

  9. java 发送短信例子_利用java实现的一个发送手机短信的小例子

    今天闲来无事,在微博上看到一个关于用java实现的一个发送手机短信的程序,看了看,写的不太相信,闲的没事,把他整理下来,以后可能用得着 JAVA发送手机短信,流传有几种方法:(1)使用webservi ...

  10. 短信猫二次开发(java版)

    短信猫二次开发(java版) 短信猫 短信猫用于批量收/发短信或其它SIM卡服务. 短信猫与PC通过GSM无线网络交互. 交互过程可以分为三个层次: 1.物理层,即无线网络通信. 2.指令层,短信猫支 ...

最新文章

  1. 应用 | 红黄蓝的虐童惨案,其实可以用机器学习等技术来避免
  2. 一张图搞定OAuth2.0
  3. Python之与众不同
  4. spring aop 注释_使用Spring AOP,自定义注释和反射为您的应用程序审核基础结构
  5. Java基础学习总结(97)——合格的Java的架构师需要具备的技术知识
  6. 本地yum源安装teamviewer
  7. 使用夜神模拟器完美破解(反编译)微信小程序以及问题汇总
  8. android看视频掉帧,玩游戏看视频经常卡顿不顺畅?你只需这几步
  9. Landsat系列卫星数据应用介绍
  10. Android 文件管理器 文件缩略图标显示流程
  11. IE浏览器日期转换问题
  12. 微信小程序-视频弹幕的项目
  13. 【音乐系列】吉他学习入门基本知识
  14. 扫码器:壹码通(EMT 6621)二维码带多个回车换行处理
  15. 计算机辅助项目管理实验论文,计算机辅助项目管理B卷
  16. IP媒体服务器:3G视频业务的基石
  17. 数字IC设计——跨时钟域篇1(时钟域)
  18. 前端 纯源生js 数字流(全代码)
  19. 2022-2027年中国商用中央空调行业发展监测及投资战略研究报告
  20. (错误都已改正)AS608指纹+STM32串口通信录入或删除指纹

热门文章

  1. Python调用OpenCV接口实现网络摄像头录像和抓拍图片
  2. 2021年中国键合对准系统市场趋势报告、技术动态创新及2027年市场预测
  3. 计算机磁盘坏道怎么隔离,小科普 | 硬盘坏道就凉凉?把它隔离出去吧!(DLC)...
  4. 程序员35岁以后干什么?大龄程序员现状揭秘
  5. 国企程序员可以干多久
  6. excel两列数据对比找不同_Excel小白就不能用数据分析的办法找工作吗?
  7. Javafx Scene Builder使用教程
  8. Python开发系列课程(14) - 玩转正则表达式
  9. docker常用命令network篇
  10. 远程关闭计算机提示拒绝访问权限,win7系统远程关机拒绝访问的解决方法