您好,登錄后才能下訂單哦!
小編給大家分享一下樹莓派.GPRS.短信接收器怎么用,相信大部分人都還不怎么了解,因此分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后大有收獲,下面讓我們一起去了解一下吧!
起因
曾經用過西門子出的短信貓, 好處是直接有SDK開發包, 不會硬件開發也能直接使用
缺點也是明顯的, 就是只支持Windows系統, 另外就是在Windows下工作很不穩定, 隔開幾天就會出現收不到短信的毛病, 要斷電重啟設備才有機會恢復(還不是必然恢復)
后來在地府(DFRobot)發現了新品"Gravity: UART A6 GSM & GPRS 無線通信模塊",買來試了一下發現可用(不過不清楚地府的A6和外面常見的SIM800系列、SIM900系列有什么不同), 而且可以自己寫驅動支持Linux下運行,完美
期間也碰到一些小坑, 記錄一下。
需求清單
- 自動初始化GPRS模塊
- 接收短信并能解析出重要元素(包括:來電號碼/時間/短信內容)
- 把解析到的短信內容上傳到服務器保存
- 清除已閱短信
- 支持Linux系統
- 開發語言:JAVA
硬件清單
- 樹莓派2代B型(3代串口使用上有區別,需要另外的方法處理)
- Gravity: UART A6 GSM & GPRS 無線通信模塊
- USB無線網卡(可選)
- USB電源適配器2個(重要,為什么要2個后面會說明)
- 16GB TF卡一張
- 可以接收短信的手機卡1張(必須是移動或聯通的卡, 電信的不支持)
接線方法
(樹莓派40PIN引腳圖)
(A6引腳說明)
樹莓派 A6
--------------------------------------
GPIO15 RX
GPIO16 TX
GND GND
重要: A6模塊的電源需要單獨供電!!!
A6模塊不能直接從樹莓派上的GPIO 5V針腳接電,因為電流不足!
最開始的時候, 我是從樹莓派上取電供給A6, 結果串口怎么都無法通信,剛開始還以為是波特率的問題,結果折騰了半天后, 留意到A6上有個藍燈(上面寫著SLEEP)有明暗變化, 不穩定,感覺像是電壓不穩定一樣, 果斷試了一下把A6外接電源,然后A6才正常工作! 可以從藍燈看得出來,亮度較高,且穩定(不閃爍)
資料準備
- 樹莓派系統(用NOOBS或Raspbian都可以)
- pi4j (JAVA支持包)
- AT指令知識
樹莓派系統安裝方法可以自行搜索,或看我之前發過的文章
系統裝好后還涉及到如何把GPIO15(TX)和GPIO16(RX)啟用的問題, 見這篇文章:《兩個樹莓派通過串口通信》
pi4j是個能讓JAVA訪問樹莓派40個GPIO的支持包, 可以上官網下載安裝,傳送門>>>
最重要和容易掉坑的是關于接收短信的AT指令部分,下面要詳細講解
這里需要做的功能是利用A6接收短信,涉及到以下指令
* 第一步:初始化GPRS.模塊
* AT 握手 / SIM卡檢測等
* AT+CPIN? 查詢是否檢測到SIM卡
* AT+CSQ 信號質量測試,值為0-31,31表示最好
* AT+CCID 讀取SIM的CCID(SIM卡背面20位數字),可以檢測是否有SIM卡或者是否接觸良好
* AT+CREG? 檢測是否注冊網絡
------以上指令用于初始化模塊,一般接線沒問題,波特率設置沒問題的話都是比較容易調通
* 第二步:初始化GPRS.設置短信模式及短信接收參數
* AT+CMGF=1 0-PDU, 1-文本格式
* AT+CSDH=1
* AT+CPMS="SM","SM","SM" 將信息保存在SIM卡中, SM-表示存在SIM卡上
* AT+CNMI=2,1,0,1,1 收接通知,并存在指定位置(與AT+CPMS設置有關)
極易掉坑系列,逐個講解:
設置短信格式指令:AT+CMGF=1
分2種短信格式: 0-PDU, 1-文本格式
如果設置的是PDU模式, 那么你收到的短信就是這樣 的:
+CIEV: "MESSAGE",1
+CMT: ,32
0891683110200005F0040BA18126601728F00000710102610272230E74747A0E4ACF416110BD3CA703
如何讀懂PDU要另外翻閱專業文章, 這里如果你不使用發短信功能的話,建議不要采用PDU格式
PDU格式的好處是可以發中文短信!
好, 如果設置是文本格式,收到的短信就類似下面這樣的:
+CIEV: "MESSAGE",1
+CMT: "test again ,中文也試試
直接就能看到短信內容,中文也一樣可以顯示出來(注意它可以GB2312或GBK編碼)
然后就有問題產生了, 新短信來時是上面這樣的格式, 短信內容是可以獲取了, 但特么為什么看不出是誰(手機號)發來的呢?下面就是入坑的時候:
看不到手機號怎么辦, 你可以試試這個指令:
AT+CMGL="ALL"
它能讀出存在SIM卡上的短信(包括已讀和未讀,以及外發時存著的短信),執行后收到的內容大概是這個樣子:
+CMGL: 2,"REC READ","106907931100",,"2017/06/02,10:15:21+08",160,134
【小米】[小米移動]您2017年5月共消費0.75元,當前余額99.05元。其中:數據流量費0.05元;語音通信費0.7元;短/彩信費+CMGL: 3,"REC READ","106907931100",,"2017/07/02,10:15:19+08",160,54
。查詢賬單 http://10046.mi.com 。+CMGL: 4,"REC READ","106907931100",,"2017/07/02,10:15:19+08",160,134
【小米】[小米移動]您2017年6月共消費1.32元,當前余額97.88元。其中:數據流量費1.32元;語音通信費0元;短/彩信費0元+CMGL: 5,"REC READ","106908761100",,"2017/08/02,10:15:30+08",160,54
。查詢賬單 http://10046.mi.com 。+CMGL: 6,"REC READ","106908761100",,"2017/08/02,10:15:30+08",160,134
【小米】[小米移動]您2017年7月共消費0.81元,當前余額97.01元。其中:數據流量費0.81元;語音通信費0元;短/彩信費0元AT+CMGD=2
好! 很明顯你要的信息都有了, 來電號碼/時間/短信內容, 似乎可以用了喔!
但是這時你會發現剛收到的信息不一定在這個清單里! 這是怎么回事呢? 我反正查閱了很多資料,費了大量的時間也不知怎么回事
后來才發現這個指令(查看SIM卡內存情況):
AT+CPMS?
執行后你可能會看到這個結果:
+CPMS: "MT",0,50,"SM",1,50,"ME",0,50
OK
重點關注"SM"后面第1個數字"1"代表當前存了多少條短信, 第2個數字"50"代表存儲上限
"SM"表示SIM卡, 其它2個一個代表手機設備, 另一個是手機內存
然后你給A6發個新短信, 有可能發現這個"1"不會增加! 為什么收到的新短信不存到SIM卡上呢?
然后就找到這個指令
AT+CNMI=<mode>,<mt>,<bm>,<ds>,<bfr>
這個指令比較復雜, 它負責設置收到新短信后的處理機制, 下面是參數含義
<mode>控制通知TE的方式.
0 - 先將通知緩存起來,再按照<mt>的值進行發送.
1 - 在數據線空閑的情況下,通知TE,否則,不通知TE.
2 - 數據線空閑時,直接通知TE;否則先將通知緩存起來,待數據線空閑時再行發送.
3 - 直接通知TE.在數據線被占用的情況下,通知TE的消息將混合在數據中一起傳輸.
<mt>設置短消息存儲和通知TE的內容.
0 - 接受的短消息存儲到默認的內存位置(包括class 3),不通知TE.
1 - 接收的短消息儲存到默認的內存位置,并且向TE發出通知(包括class 3).通知的形式為:+CMTI:"SM",<index>
2 - 對于class 2短消息,儲存到SIM卡,并且向TE發出通知;對于其他class,直接將短消息轉發到TE:+CMT:[<alpha>],<length><CR><LF><pdu>(PDU模式)
或者+CMT:<oa>,[<alpha>,]<scts>[,<tooa>,<fo>,<pid>,<dcs>,<sca>,<tosca>,<length>]<CR><LF><data>(text模式)
3 - 對于class 3短消息,直接轉發到TE,同<mt>=2;對于其他class,同<mt>=1.
<bm>設置小區廣播
0 - 小區廣播不通知
2 - 新的小區廣播通知,返回+CBM:;length;;CR;;LF;;pdu;
3 - Class3格式的小區廣播通知,使用bm=2格式
<ds>狀態報告
0 - 狀態報告不通知
1 - 新的狀態報告通知,返回:+CDS:;length;;CR;;LF;;pdu;
2 - 如果新的狀態報告存儲到ME,則返回:+CDSI:;mem;,;index;
相信看完你已經蒙圈, 我就是, 如果你看得懂, 那恭喜了!
我在這里采用的參數是
AT+CNMI=2,1,0,1,1 收接通知,并存在指定位置
這時再測試一下發條新短信給A6
+CIEV: "MESSAGE",1
+CMTI: "SM",0
現在不顯示短信內容了(反正顯示也沒用, 因為沒來電號碼), 但"SM"后面仍然是0!
這時再用AT+CMGL="ALL" 你會發現短信依然沒存到卡上, 結果當然也沒法看到短信內容及來電號碼等信息啦
這是怎么回事裂
后來發現這個AT+CNMI跟剛才說的指令(AT+CPMS)息息相關,再來查一下:
AT+CPMS?
+CPMS: "MT",0,50,"SM",1,50,"ME",0,50
OK
注意看, 如果你看到的和上面差不多, 會發現有"MT"和"ME"存在, 這時收到短信雖然在CNMI告訴A6收到短信要存下來啊! 但是A6找不到"MT"和"ME",結果存儲失敗!
我們現在是希望它收到短信后能存在SIM卡上, 所以要設置一下:
AT+CPMS="SM","SM","SM"
再發條短信試試效果:
+CIEV: "MESSAGE",1
+CMTI: "SM",1
現在看到"SM"后面是1了! 后面這個1表示的是短信存儲的SIM卡內存的位置
然后可以用指令查看短信內容了, 這里有2種方法
方法1,單條讀取(AT+CMGR=index)
AT+CMGR=1
+CMGR: "REC UNREAD","18620671820",,"2017/10/26,11:37:03+08",161,17,0,0,"+8613010200500",145,25
test again ,中文也試試
方法2,全部讀取(AT+CMGL="ALL")
+CMGL: 2,"REC READ","106907931100",,"2017/06/02,10:15:21+08",160,134
【小米】[小米移動]您2017年5月共消費0.75元,當前余額99.05元。其中:數據流量費0.05元;語音通信費0.7元;短/彩信費+CMGL: 3,"REC READ","106907931100",,"2017/07/02,10:15:19+08",160,54
。查詢賬單 http://10046.mi.com 。+CMGL: 4,"REC READ","106907931100",,"2017/07/02,10:15:19+08",160,134
【小米】[小米移動]您2017年6月共消費1.32元,當前余額97.88元。其中:數據流量費1.32元;語音通信費0元;短/彩信費0元+CMGL: 5,"REC READ","106908761100",,"2017/08/02,10:15:30+08",160,54
。查詢賬單 http://10046.mi.com 。+CMGL: 6,"REC READ","106908761100",,"2017/08/02,10:15:30+08",160,134
【小米】[小米移動]您2017年7月共消費0.81元,當前余額97.01元。其中:數據流量費0.81元;語音通信費0元;短/彩信費0元AT+CMGD=2
小結一下正確獲取短信的姿勢(流程):
AT+CMGF=1
AT+CSDH=1
AT+CPMS="SM","SM","SM"
AT+CNMI=2,1,0,1,1
PS: 其中有一條指令沒解釋:AT+CSDH=1
這個留給大家查資料
好, 接下來只需要寫出Java代碼分析短信內容即可.
程序部分
import java.io.IOException; import java.util.Date; import com.common.DateTimeUtil; import com.common.StringUtil; import com.pi4j.io.serial.Baud; import com.pi4j.io.serial.DataBits; import com.pi4j.io.serial.FlowControl; import com.pi4j.io.serial.Parity; import com.pi4j.io.serial.Serial; import com.pi4j.io.serial.SerialConfig; import com.pi4j.io.serial.SerialFactory; import com.pi4j.io.serial.SerialPort; import com.pi4j.io.serial.StopBits; import com.pi4j.util.CommandArgumentParser; import com.pi4j.util.Console; /** * This example code demonstrates how to perform serial communications using the Raspberry Pi. * * @author Robert Savage */ public class SerialListenSMS { /** * This example program supports the following optional command arguments/options: * "--device (device-path)" [DEFAULT: /dev/ttyAMA0] * "--baud (baud-rate)" [DEFAULT: 38400] * "--data-bits (5|6|7|8)" [DEFAULT: 8] * "--parity (none|odd|even)" [DEFAULT: none] * "--stop-bits (1|2)" [DEFAULT: 1] * "--flow-control (none|hardware|software)" [DEFAULT: none] * * @param args * @throws InterruptedException * @throws IOException */ public static void main(String args[]) throws InterruptedException, IOException { // !! ATTENTION !! // By default, the serial port is configured as a console port // for interacting with the Linux OS shell. If you want to use // the serial port in a software program, you must disable the // OS from using this port. // // Please see this blog article for instructions on how to disable // the OS console for this port: // https://www.cube-controls.com/2015/11/02/disable-serial-port-terminal-output-on-raspbian/ // create Pi4J console wrapper/helper // (This is a utility class to abstract some of the boilerplate code) final Console console = new Console(); // print program title/header console.title("<-- The Pi4J Project -->", "監聽串口(GPIO15-Tx / GPIO16-Rx)數據并寫入Memcached中"); // allow for user to exit program using CTRL-C console.promptForExit(); // create an instance of the serial communications class final Serial serial = SerialFactory.createInstance(); byte [] data = new byte[1024]; //數據緩沖區 try { // create serial config object SerialConfig config = new SerialConfig(); System.out.println(">>>"+SerialPort.getDefaultPort()); config.device(SerialPort.getDefaultPort()) // "/dev/ttyACM0" .baud(Baud._115200) .dataBits(DataBits._8) .parity(Parity.NONE) .stopBits(StopBits._1) .flowControl(FlowControl.NONE); // parse optional command argument options to override the default serial settings. if(args.length > 0){ config = CommandArgumentParser.getSerialConfig(config, args); } // display connection details console.box(" Connecting to: " + config.toString(), " Data received on serial port will be displayed below."); // open the default serial device/port with the configuration settings serial.open(config); serial.flush(); System.out.println("serial.isOpen():"+serial.isOpen()); /**初始化GPRS模塊**/ boolean isinit = initGPRS(serial); long trydelay = 2000; while(!isinit){ System.out.println("初始化GPRS模塊不成功, 請檢查模塊工作狀態燈, 以及SIM卡是否接觸良好..."+trydelay); Thread.sleep(trydelay+=1000); isinit = initGPRS(serial); if(trydelay>(10*1000)){return;} //檢測10次都不成功時, 退出程序 } /**初始化短信參數**/ isinit = initGPRS_SMS(serial); trydelay = 2000; while(!isinit){ System.out.println("初始化短信參數不成功, 請檢查模塊工作狀態燈, 以及SIM卡是否接觸良好."); Thread.sleep(trydelay+=1000); isinit = initGPRS_SMS(serial); if(trydelay>(10*1000)){return;} //檢測10次都不成功時, 退出程序 } //每次開機時嘗試讀取一次存儲卡中的短信 String res = new String(sendCMD(serial, "AT+CMGL=\"ALL\""), "GBK"); System.out.println("AT+CMGL=\"REC READ\".res:"+res); if(res.indexOf("OK")==-1){ System.out.println("設置失敗!"); } //下面進入主程序 System.out.println("進入短信監聽程序:"); long old_msg_delay = 60000; //設置舊短信搜索間隔時間(毫秒),在SIM卡內存中搜索數據 long old_msg_count = 0; //舊短信計時器 int index = 1; data = null; while(true){ System.out.print("."); if(!serial.isOpen()){ System.out.println("串口未打開, 退出程序"); break; } if(old_msg_count>=old_msg_delay){ // System.out.println("發送獲取SIM卡內存中的所有信息的指令"); sendCMD(serial, "AT+CMGL=\"ALL\""); old_msg_count = 0; }else{ old_msg_count+=1000; //System.out.println("old_msg_count..."+old_msg_count); } if(serial.available()>0){ while(serial.available()>0){ data=serial.read(); //此處接收到的數據上限是1024 //System.out.print(new String(serial.read(), "utf-8")); } serial.flush(); } if(data!=null){ //接收到數據 String cc = new String(data, "GBK"); //處理中文 System.out.println("cc:"+cc); if(cc!=null && !cc.trim().equals("")){ //處理數據 /** * 有新短信時: * +CIEV: "MESSAGE",1 * * +CMTI: "SM",1 */ if(cc.indexOf("+CMTI")!=-1){ index = getIndexFromNewSMS(cc); System.out.println("發現新短信.index:"+index); sendCMD(serial, "AT+CMGR="+index); } if(cc.indexOf("+CMGR")!=-1){ String[] contents = getContentFromIndex(index, cc); System.out.println("[AT+CMGR=index]讀取存在卡上的短信內容.分析后:"); if(contents!=null){ System.out.println("新短信內容:"); for(String tt : contents){ System.out.println(tt); } //保存讀到的短信 -> 服務器 if(sendDataToServer(contents)){ //刪除已讀出的短信 System.out.println("刪除已讀出的新短信.index:"+contents[0]); delSMSByIndex(serial, Integer.parseInt(contents[0])); } }else{ System.out.println("新短信內容:null"); } } /** * 查詢舊短信時: * AT+CMGL="ALL" * * +CMGL: 1,"REC READ","18620671820",,"2017/10/26,11:37:03+08",161,25 * just because the people11 * +CMGL: 2,"REC READ","18620671820",,"2017/10/26,11:37:03+08",161,25 * just because the people11 */ if(cc.indexOf("CMGL:")!=-1){ //獲取第1條短信 String[] contents = getContentFromStorageSMS(cc); System.out.println("[AT+CMGL=\"ALL\"]存在卡上的短信內容.分析后:"); for(String tt : contents){ System.out.println(tt); } //保存讀到的短信 if(sendDataToServer(contents)){ //刪除已讀出的短信 System.out.println("刪除已讀出的舊短信.index:"+contents[0]); delSMSByIndex(serial, Integer.parseInt(contents[0])); } } }else{ System.out.println("data:"+new String(data)); System.out.println("data(byte[]) 轉換成 String時出錯"); } } //if(cc!=null && !cc.trim().equals(""))System.out.println(cc); data = null; Thread.sleep(1000); } } catch(IOException ex) { console.println(" ==>> SERIAL SETUP FAILED : " + ex.getMessage()); return; } } /** * 把短信上傳到服務器中 * @param contents 數組 [0] - 短信位置索引 [1] - 電話號碼 [2] - 日期+時間 2017/10/26 11:37:03+08 [3] - 短信內容 * @return */ public static boolean sendDataToServer(String[] contents){ System.out.println("嘗試上傳短信數據"); try{ //移除時間中的時區 +08 2017/10/26 12:38:14+08...2017-10-26 12:38:14 String d = contents[2].substring(0,contents[2].lastIndexOf("+")); d = d.replace("/", "-").replace(" ", "%20"); StringBuffer url = new StringBuffer("http://192.168.6.2:9080/webService.do?method=saveSMSBank"); String vno = DateTimeUtil.dateToString(new Date(), "yyyyMMdd"); vno = StringUtil.encodePassword(vno, "MD5"); url.append("&vno=").append(vno); url.append("&smstype=0"); url.append("&port=2"); url.append("&recTime=").append(d); //need: 2013-12-05%2014:35:20 url.append("&phone=").append(contents[1]); url.append("&serialNo=0"); url.append("&nums=0"); url.append("&submitPort=0"); url.append("&sendid=").append(contents[1]); url.append("&sendtype=0"); url.append("&sendNo=0"); String xx = new String(contents[3].getBytes(), "UTF-8"); url.append("&txt=").append(java.net.URLEncoder.encode(xx, "UTF-8")); System.out.println("sendDataToServer().url:"+url.toString()); String resurl = StringUtil.getContentByUrl2(url.toString()); System.out.println("sendDataToServer().resurl:"+resurl); if(resurl.trim().equals("200")){ System.out.println("數據上傳成功!"); return true; }else if(resurl.trim().equals("401")){ System.out.println("這個電話號碼和短信內容已上傳過, 數據重復!"); System.out.println("清除SIM卡上的短信!"); return true; } }catch(Exception e){ e.printStackTrace(); return false; } return false; } /** * 解析返回的短信內容 * @return */ public static String[] getContentFromIndex(int index, String res){ try{ System.out.println("嘗試讀取短信...getContentFromIndex.res:"+res); if(res.indexOf("OK")!=-1){ System.out.println("獲取短信成功,解析內容..."); /** * +CMGR: "REC READ","18620671820",,"2017/10/26,11:37:03+08",161,17,0,0,"+8613010200500",145,25 * just because the people11 * * +CMGR: "REC READ","18620671820",,"2017/10/26,11:37:03+08",161,17,0,0,"+8613010200500",145,25 * ---------------- ------------- - ---------- ----------- --- -- - - ---------------- --- -- * [0] [1] [2] [3] [4] [5] [6][7][8] [9] [10][11] */ String[] ccs = res.split("\r\n"); String phone = new String(); String sendDate = new String(); String content = new String(); boolean isvalid = false; //數據獲取成功 for(int i=0;i<ccs.length;i++){ if(ccs[i].indexOf("CMGR:")!=-1){ String[] temp1 = ccs[i].split(","); phone = temp1[1]; sendDate = temp1[3]+" "+temp1[4]; content = ccs[i+1]; isvalid = true; break; //只處理1條 } } if(!isvalid)return null; //處理雙引號 phone = phone.substring(1,phone.length()-1); sendDate = sendDate.substring(1,sendDate.length()-1); String[] resu = new String[4]; resu[0] = String.valueOf(index); resu[1] = phone.trim(); resu[2] = sendDate; resu[3] = content; return resu; }else if(res.indexOf("CMS ERROR")!=-1){ //CMS ERROR:321 表示所讀取的內存位置出錯,一般是指定位置無短信內容所致 System.out.println("獲取短信失敗,錯誤內容..."); return null; } }catch(Exception e){ e.printStackTrace(); } return null; } /** * 有新短信時,獲取短信內容: * +CIEV: "MESSAGE",1 * * +CMTI: "SM",1 * * @return index 短信所在的內存位置 index */ public static int getIndexFromNewSMS(String cc){ try{ String[] ccs = cc.split("\r\n"); for(String v : ccs){ if(v.indexOf("CMTI: \"SM\",")!=-1){ String c = v.substring(v.indexOf(",")+1); return Integer.parseInt(c); } } }catch(Exception e){ e.printStackTrace(); } return 0; } /** * 查詢舊短信, 每次只抓1條: * +CMGL: 4,"REC READ","106907931100",,"2017/07/02,10:15:19+08" * -------- ---------- -------------- ----------- ------------ * [0] [1] [2] [3] [4] [5] 【小米】[小米移動]您2017年6月共消費1.32元,當前余額97.88元。其中:數據流量費1.32元;語音通信費0元;短/彩信費0元 +CMGL: 5,"REC READ","106908761100",,"2017/08/02,10:15:30+08" 。查詢賬單 http://10046.mi.com 。 +CMGL: 6,"REC READ","106908761100",,"2017/08/02,10:15:30+08" 【小米】[小米移動]您2017年7月共消費0.81元,當前余額97.01元。其中:數據流量費0.81元;語音通信費0元;短/彩信費0元 OK @return 數組 [0] - 短信位置索引 [1] - 電話號碼 [2] - 日期+時間 [3] - 短信內容 */ public static String[] getContentFromStorageSMS(String cc){ String[] ccs = cc.split("\r\n"); String smsIndex = new String(); String phone = new String(); String sendDate = new String(); String content = new String(); for(int i=0;i<ccs.length;i++){ if(ccs[i].indexOf("CMGL:")!=-1){ //smsIndex = Integer.parseInt(ccs[i].substring(ccs[i].indexOf("CMGL:")+5, ccs[i].indexOf(","))); smsIndex = ccs[i].substring(ccs[i].indexOf("CMGL:")+5, ccs[i].indexOf(",")); String[] temp1 = ccs[i].split(","); phone = temp1[2]; sendDate = temp1[4]+" "+temp1[5]; content = ccs[i+1]; break; //只處理1條 } } //處理雙引號 phone = phone.substring(1,phone.length()-1); sendDate = sendDate.substring(1,sendDate.length()-1); String[] res = new String[4]; res[0] = smsIndex.trim(); res[1] = phone.trim(); res[2] = sendDate; res[3] = content; return res; } /** * 刪除指定位置上的短信 * AT+CMGD=4 * @param index 短信索引位置 * @return */ public static boolean delSMSByIndex(Serial serial, int index){ String res = new String(sendCMD(serial, "AT+CMGD="+index)); System.out.println("AT+CMGD="+index+":"+res); //if(res.indexOf("OK")==-1){ // System.out.println("刪除["+index+"]位置的短信失敗!"); // return false; //} return true; } /** * * 初始化GPRS.模塊 * AT 100ms 握手 / SIM卡檢測等 * AT+CPIN? 100ms 查詢是否檢測到SIM卡 * AT+CSQ 100ms 信號質量測試,值為0-31,31表示最好 * AT+CCID 100ms 讀取SIM的CCID(SIM卡背面20位數字),可以檢測是否有SIM卡或者是否接觸良好 * AT+CREG? 500ms 檢測是否注冊網絡 * @return */ public static boolean initGPRS(Serial serial){ if(!serial.isOpen()){return false;} //串口未準備好 byte[] buffs = new byte[128]; try{ System.out.println("try send AT to module..."); //char cmd[] = {'A', 'T'}; //byte cmd[] = "AT".getBytes(); //buffs = sendCMD(serial, "AT".getBytes()); System.out.print("\r\nGPRS模塊檢測中..."); buffs = sendCMD(serial, "AT"); String res = new String(buffs); if(res.indexOf("OK")==-1){ System.out.println("GPRS模塊未準備好, 請檢查電源和串口波特率是否正確!"); return false; } System.out.println(" ...[正常]\r\n"); //System.out.println("AT.res:"+res); System.out.print("\r\n檢測SIM卡..."); res = new String(sendCMD(serial, "AT+CPIN?")); if(res.indexOf("READY")==-1){ System.out.println("SIM卡未準備好!"); return false; } System.out.println(" ...[正常]\r\n"); //System.out.println("AT+CPIN?.res:"+res); System.out.print("\r\n信號質量測試,值為0-31,31表示最好..."); res = new String(sendCMD(serial, "AT+CSQ")); if(res.indexOf("ERROR")!=-1){ System.out.println("信號質量測試檢測失敗"); return false; } /** * +CSQ: 24,99 */ String[] vs = res.split("\r\n"); for(String v : vs){ if(v.indexOf(":")!=-1){ String x = v.substring(v.indexOf(":")+1); //System.out.println("x:"+x); System.out.println(" ...信號強度:["+x.trim()+"]\r\n"); } } //System.out.println("AT+CSQ.res:"+res); res = new String(sendCMD(serial, "AT+CCID")); System.out.println("AT+CCID.res:"+res); res = new String(sendCMD(serial, "AT+CREG?")); System.out.println("AT+CREG.res:"+res); }catch(Exception e){ e.printStackTrace(); return false; } return true; } /** * * 初始化GPRS.設置短信模式及短信接收參數 * AT+CMGF=1 0-PDU, 1-文本格式 * AT+CSDH=1 * AT+CPMS="SM","SM","SM" 將信息保存在SIM卡中, SM-表示存在SIM卡上 * AT+CNMI=2,1,0,1,1 收接通知,并存在指定位置(與AT+CPMS設置有關) * * 設置好后, 收到短信: * +CIEV: "MESSAGE",1 * +CMTI: "SM",1 表示存儲位置index=1 * @return */ public static boolean initGPRS_SMS(Serial serial){ if(!serial.isOpen()){return false;} //串口未準備好 String res = new String(); try{ System.out.print("\r\n設置短信格式..."); res = new String(sendCMD(serial, "AT+CMGF=1")); if(res.indexOf("OK")==-1){ System.out.println("設置失敗!"); return false; } System.out.println(" ...[文本格式]\r\n"); Thread.sleep(100); System.out.print("\r\nAT+CSDH=1..."); res = new String(sendCMD(serial, "AT+CSDH=1")); if(res.indexOf("OK")==-1){ System.out.println("設置失敗!"); return false; } System.out.println(" ...[DONE]\r\n"); Thread.sleep(100); System.out.print("\r\n設置信息保存位置..."); res = new String(sendCMD(serial, "AT+CPMS=\"SM\",\"SM\",\"SM\"")); if(res.indexOf("OK")==-1){ System.out.println("設置失敗!"); return false; } System.out.println(" ...[SIM卡]\r\n"); Thread.sleep(100); System.out.print("\r\n收接通知,并存在指定位置..."); res = new String(sendCMD(serial, "AT+CNMI=2,1,0,1,1")); if(res.indexOf("OK")==-1){ System.out.println("設置失敗!"); return false; } System.out.println(" ...[DONE]\r\n"); Thread.sleep(100); }catch(Exception e){ e.printStackTrace(); return false; } return true; } //public static byte[] sendCMD(Serial serial, byte[] cmd){ public static byte[] sendCMD(Serial serial, String cmd){ long overtime = 10000; //每條指令超時上限 5秒 long timecount = 0; //計時器 byte[] buffs = new byte[128]; try { serial.writeln(cmd+"\r"); //serial.writeln("AT\r"); timecount = 0; while(timecount<overtime){ //System.out.print(serial.available()); if(serial.available()>0){ while(serial.available()>0){ buffs = serial.read(); //System.out.print(new String(serial.read())); //System.out.print(new String(buffs)); } serial.flush(); timecount = overtime; //exit while } timecount += 100; Thread.sleep(100); } //System.out.println("sendCMD:"+new String(buffs)); } catch (IllegalStateException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } return buffs; } } // END SNIPPET: serial-snippet
程序中的方法: sendDataToServer()
主要是用于上傳保存短信, 大家替換成自己的方式即可
以上是“樹莓派.GPRS.短信接收器怎么用”這篇文章的所有內容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內容對大家有所幫助,如果還想學習更多知識,歡迎關注億速云行業資訊頻道!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。