欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

樹莓派.GPRS.短信接收器

 更新時(shí)間:2017年10月29日 09:12:50   作者:幻河  
這篇文章主要介紹了樹莓派.GPRS.短信接收器的相關(guān)知識(shí),需要的朋友可以參考下

起因

曾經(jīng)用過西門子出的短信貓, 好處是直接有SDK開發(fā)包, 不會(huì)硬件開發(fā)也能直接使用

缺點(diǎn)也是明顯的, 就是只支持Windows系統(tǒng), 另外就是在Windows下工作很不穩(wěn)定, 隔開幾天就會(huì)出現(xiàn)收不到短信的毛病, 要斷電重啟設(shè)備才有機(jī)會(huì)恢復(fù)(還不是必然恢復(fù))

后來在地府(DFRobot)發(fā)現(xiàn)了新品"Gravity: UART A6 GSM & GPRS 無線通信模塊",買來試了一下發(fā)現(xiàn)可用(不過不清楚地府的A6和外面常見的SIM800系列、SIM900系列有什么不同), 而且可以自己寫驅(qū)動(dòng)支持Linux下運(yùn)行,完美

期間也碰到一些小坑, 記錄一下。 

需求清單

 - 自動(dòng)初始化GPRS模塊

 - 接收短信并能解析出重要元素(包括:來電號(hào)碼/時(shí)間/短信內(nèi)容)

 - 把解析到的短信內(nèi)容上傳到服務(wù)器保存

 - 清除已閱短信

 - 支持Linux系統(tǒng)

 - 開發(fā)語言:JAVA

硬件清單

 - 樹莓派2代B型(3代串口使用上有區(qū)別,需要另外的方法處理)
 - Gravity: UART A6 GSM & GPRS 無線通信模塊
 - USB無線網(wǎng)卡(可選)
 - USB電源適配器2個(gè)(重要,為什么要2個(gè)后面會(huì)說明)
 - 16GB TF卡一張
 - 可以接收短信的手機(jī)卡1張(必須是移動(dòng)或聯(lián)通的卡, 電信的不支持)

接線方法

(樹莓派40PIN引腳圖)

(A6引腳說明)

樹莓派     A6
--------------------------------------

GPIO15    RX

GPIO16    TX

GND       GND

重要: A6模塊的電源需要單獨(dú)供電?。?!

A6模塊不能直接從樹莓派上的GPIO 5V針腳接電,因?yàn)殡娏鞑蛔悖?/p>

最開始的時(shí)候, 我是從樹莓派上取電供給A6, 結(jié)果串口怎么都無法通信,剛開始還以為是波特率的問題,結(jié)果折騰了半天后, 留意到A6上有個(gè)藍(lán)燈(上面寫著SLEEP)有明暗變化, 不穩(wěn)定,感覺像是電壓不穩(wěn)定一樣, 果斷試了一下把A6外接電源,然后A6才正常工作! 可以從藍(lán)燈看得出來,亮度較高,且穩(wěn)定(不閃爍)

資料準(zhǔn)備

 - 樹莓派系統(tǒng)(用NOOBS或Raspbian都可以)

 - pi4j (JAVA支持包)

 - AT指令知識(shí)

樹莓派系統(tǒng)安裝方法可以自行搜索,或看我之前發(fā)過的文章

系統(tǒng)裝好后還涉及到如何把GPIO15(TX)和GPIO16(RX)啟用的問題, 見這篇文章:《兩個(gè)樹莓派通過串口通信》

pi4j是個(gè)能讓JAVA訪問樹莓派40個(gè)GPIO的支持包, 可以上官網(wǎng)下載安裝,傳送門>>>

最重要和容易掉坑的是關(guān)于接收短信的AT指令部分,下面要詳細(xì)講解

這里需要做的功能是利用A6接收短信,涉及到以下指令

* 第一步:初始化GPRS.模塊

* AT      握手 / SIM卡檢測等
* AT+CPIN?   查詢是否檢測到SIM卡
* AT+CSQ    信號(hào)質(zhì)量測試,值為0-31,31表示最好
* AT+CCID    讀取SIM的CCID(SIM卡背面20位數(shù)字),可以檢測是否有SIM卡或者是否接觸良好
* AT+CREG?    檢測是否注冊網(wǎng)絡(luò)

------以上指令用于初始化模塊,一般接線沒問題,波特率設(shè)置沒問題的話都是比較容易調(diào)通

* 第二步:初始化GPRS.設(shè)置短信模式及短信接收參數(shù)

* 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設(shè)置有關(guān))

極易掉坑系列,逐個(gè)講解:

設(shè)置短信格式指令:AT+CMGF=1

分2種短信格式: 0-PDU, 1-文本格式

如果設(shè)置的是PDU模式, 那么你收到的短信就是這樣 的:

+CIEV: "MESSAGE",1

+CMT: ,32
0891683110200005F0040BA18126601728F00000710102610272230E74747A0E4ACF416110BD3CA703

如何讀懂PDU要另外翻閱專業(yè)文章, 這里如果你不使用發(fā)短信功能的話,建議不要采用PDU格式

PDU格式的好處是可以發(fā)中文短信!

好, 如果設(shè)置是文本格式,收到的短信就類似下面這樣的:

+CIEV: "MESSAGE",1

+CMT: "test again ,中文也試試

直接就能看到短信內(nèi)容,中文也一樣可以顯示出來(注意它可以GB2312或GBK編碼)

然后就有問題產(chǎn)生了, 新短信來時(shí)是上面這樣的格式, 短信內(nèi)容是可以獲取了, 但特么為什么看不出是誰(手機(jī)號(hào))發(fā)來的呢?下面就是入坑的時(shí)候:

看不到手機(jī)號(hào)怎么辦, 你可以試試這個(gè)指令:

AT+CMGL="ALL"

它能讀出存在SIM卡上的短信(包括已讀和未讀,以及外發(fā)時(shí)存著的短信),執(zhí)行后收到的內(nèi)容大概是這個(gè)樣子:

+CMGL: 2,"REC READ","106907931100",,"2017/06/02,10:15:21+08",160,134
【小米】[小米移動(dòng)]您2017年5月共消費(fèi)0.75元,當(dāng)前余額99.05元。其中:數(shù)據(jù)流量費(fèi)0.05元;語音通信費(fèi)0.7元;短/彩信費(fèi)+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
【小米】[小米移動(dòng)]您2017年6月共消費(fèi)1.32元,當(dāng)前余額97.88元。其中:數(shù)據(jù)流量費(fèi)1.32元;語音通信費(fèi)0元;短/彩信費(fèi)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
【小米】[小米移動(dòng)]您2017年7月共消費(fèi)0.81元,當(dāng)前余額97.01元。其中:數(shù)據(jù)流量費(fèi)0.81元;語音通信費(fèi)0元;短/彩信費(fèi)0元AT+CMGD=2


好! 很明顯你要的信息都有了, 來電號(hào)碼/時(shí)間/短信內(nèi)容, 似乎可以用了喔!

但是這時(shí)你會(huì)發(fā)現(xiàn)剛收到的信息不一定在這個(gè)清單里! 這是怎么回事呢? 我反正查閱了很多資料,費(fèi)了大量的時(shí)間也不知怎么回事

后來才發(fā)現(xiàn)這個(gè)指令(查看SIM卡內(nèi)存情況):

AT+CPMS?

執(zhí)行后你可能會(huì)看到這個(gè)結(jié)果:

+CPMS: "MT",0,50,"SM",1,50,"ME",0,50

OK

重點(diǎn)關(guān)注"SM"后面第1個(gè)數(shù)字"1"代表當(dāng)前存了多少條短信, 第2個(gè)數(shù)字"50"代表存儲(chǔ)上限

"SM"表示SIM卡, 其它2個(gè)一個(gè)代表手機(jī)設(shè)備, 另一個(gè)是手機(jī)內(nèi)存

然后你給A6發(fā)個(gè)新短信, 有可能發(fā)現(xiàn)這個(gè)"1"不會(huì)增加! 為什么收到的新短信不存到SIM卡上呢?

然后就找到這個(gè)指令

AT+CNMI=<mode>,<mt>,<bm>,<ds>,<bfr>

這個(gè)指令比較復(fù)雜, 它負(fù)責(zé)設(shè)置收到新短信后的處理機(jī)制, 下面是參數(shù)含義

    <mode>控制通知TE的方式.
    0 - 先將通知緩存起來,再按照<mt>的值進(jìn)行發(fā)送.
    1 - 在數(shù)據(jù)線空閑的情況下,通知TE,否則,不通知TE.
    2 - 數(shù)據(jù)線空閑時(shí),直接通知TE;否則先將通知緩存起來,待數(shù)據(jù)線空閑時(shí)再行發(fā)送.
    3 - 直接通知TE.在數(shù)據(jù)線被占用的情況下,通知TE的消息將混合在數(shù)據(jù)中一起傳輸.
    <mt>設(shè)置短消息存儲(chǔ)和通知TE的內(nèi)容.
    0 - 接受的短消息存儲(chǔ)到默認(rèn)的內(nèi)存位置(包括class 3),不通知TE.
    1 - 接收的短消息儲(chǔ)存到默認(rèn)的內(nèi)存位置,并且向TE發(fā)出通知(包括class 3).通知的形式為:+CMTI:"SM",<index>
    2 - 對(duì)于class 2短消息,儲(chǔ)存到SIM卡,并且向TE發(fā)出通知;對(duì)于其他class,直接將短消息轉(zhuǎn)發(fā)到TE:+CMT:[<alpha>],<length><CR><LF><pdu>(PDU模式)
         或者+CMT:<oa>,[<alpha>,]<scts>[,<tooa>,<fo>,<pid>,<dcs>,<sca>,<tosca>,<length>]<CR><LF><data>(text模式)
    3 - 對(duì)于class 3短消息,直接轉(zhuǎn)發(fā)到TE,同<mt>=2;對(duì)于其他class,同<mt>=1. 
    <bm>設(shè)置小區(qū)廣播
    0 - 小區(qū)廣播不通知
    2 - 新的小區(qū)廣播通知,返回+CBM:;length;;CR;;LF;;pdu;
    3 - Class3格式的小區(qū)廣播通知,使用bm=2格式
    <ds>狀態(tài)報(bào)告
    0 - 狀態(tài)報(bào)告不通知
    1 - 新的狀態(tài)報(bào)告通知,返回:+CDS:;length;;CR;;LF;;pdu;
    2 - 如果新的狀態(tài)報(bào)告存儲(chǔ)到ME,則返回:+CDSI:;mem;,;index;

相信看完你已經(jīng)蒙圈, 我就是, 如果你看得懂, 那恭喜了!

我在這里采用的參數(shù)是

AT+CNMI=2,1,0,1,1        收接通知,并存在指定位置

這時(shí)再測試一下發(fā)條新短信給A6

+CIEV: "MESSAGE",1

+CMTI: "SM",0

現(xiàn)在不顯示短信內(nèi)容了(反正顯示也沒用, 因?yàn)闆]來電號(hào)碼), 但"SM"后面仍然是0!

這時(shí)再用AT+CMGL="ALL" 你會(huì)發(fā)現(xiàn)短信依然沒存到卡上, 結(jié)果當(dāng)然也沒法看到短信內(nèi)容及來電號(hào)碼等信息啦

這是怎么回事裂

后來發(fā)現(xiàn)這個(gè)AT+CNMI跟剛才說的指令(AT+CPMS)息息相關(guān),再來查一下:

AT+CPMS?
+CPMS: "MT",0,50,"SM",1,50,"ME",0,50

OK

注意看, 如果你看到的和上面差不多, 會(huì)發(fā)現(xiàn)有"MT"和"ME"存在, 這時(shí)收到短信雖然在CNMI告訴A6收到短信要存下來啊! 但是A6找不到"MT"和"ME",結(jié)果存儲(chǔ)失敗!

我們現(xiàn)在是希望它收到短信后能存在SIM卡上, 所以要設(shè)置一下:

AT+CPMS="SM","SM","SM"

 再發(fā)條短信試試效果:

+CIEV: "MESSAGE",1

+CMTI: "SM",1

現(xiàn)在看到"SM"后面是1了! 后面這個(gè)1表示的是短信存儲(chǔ)的SIM卡內(nèi)存的位置

然后可以用指令查看短信內(nèi)容了, 這里有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
【小米】[小米移動(dòng)]您2017年5月共消費(fèi)0.75元,當(dāng)前余額99.05元。其中:數(shù)據(jù)流量費(fèi)0.05元;語音通信費(fèi)0.7元;短/彩信費(fèi)+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
【小米】[小米移動(dòng)]您2017年6月共消費(fèi)1.32元,當(dāng)前余額97.88元。其中:數(shù)據(jù)流量費(fèi)1.32元;語音通信費(fèi)0元;短/彩信費(fèi)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
【小米】[小米移動(dòng)]您2017年7月共消費(fèi)0.81元,當(dāng)前余額97.01元。其中:數(shù)據(jù)流量費(fèi)0.81元;語音通信費(fèi)0元;短/彩信費(fèi)0元AT+CMGD=2

小結(jié)一下正確獲取短信的姿勢(流程):

AT+CMGF=1
AT+CSDH=1
AT+CPMS="SM","SM","SM"
AT+CNMI=2,1,0,1,1

PS: 其中有一條指令沒解釋:AT+CSDH=1

這個(gè)留給大家查資料

好, 接下來只需要寫出Java代碼分析短信內(nèi)容即可.

程序部分

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 -->", "監(jiān)聽串口(GPIO15-Tx / GPIO16-Rx)數(shù)據(jù)并寫入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];  //數(shù)據(jù)緩沖區(qū)  
  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模塊不成功, 請檢查模塊工作狀態(tài)燈, 以及SIM卡是否接觸良好..."+trydelay);
    Thread.sleep(trydelay+=1000);
    isinit = initGPRS(serial);
    if(trydelay>(10*1000)){return;}  //檢測10次都不成功時(shí), 退出程序
   }
   /**初始化短信參數(shù)**/
   isinit = initGPRS_SMS(serial);
   trydelay = 2000;
   while(!isinit){
    System.out.println("初始化短信參數(shù)不成功, 請檢查模塊工作狀態(tài)燈, 以及SIM卡是否接觸良好.");
    Thread.sleep(trydelay+=1000);
    isinit = initGPRS_SMS(serial);
    if(trydelay>(10*1000)){return;}  //檢測10次都不成功時(shí), 退出程序
   }
   //每次開機(jī)時(shí)嘗試讀取一次存儲(chǔ)卡中的短信
   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("設(shè)置失敗!");
   }
   //下面進(jìn)入主程序
   System.out.println("進(jìn)入短信監(jiān)聽程序:");
   long old_msg_delay = 60000;   //設(shè)置舊短信搜索間隔時(shí)間(毫秒),在SIM卡內(nèi)存中搜索數(shù)據(jù)
   long old_msg_count = 0;    //舊短信計(jì)時(shí)器
   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("發(fā)送獲取SIM卡內(nèi)存中的所有信息的指令");
     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();    //此處接收到的數(shù)據(jù)上限是1024
      //System.out.print(new String(serial.read(), "utf-8"));
     }
     serial.flush();
    }
    if(data!=null){
     //接收到數(shù)據(jù)
     String cc = new String(data, "GBK");  //處理中文
     System.out.println("cc:"+cc);
     if(cc!=null && !cc.trim().equals("")){
      //處理數(shù)據(jù)
      /**
       * 有新短信時(shí):
       * +CIEV: "MESSAGE",1
       * 
       * +CMTI: "SM",1
       */
      if(cc.indexOf("+CMTI")!=-1){
       index = getIndexFromNewSMS(cc);
       System.out.println("發(fā)現(xiàn)新短信.index:"+index);
       sendCMD(serial, "AT+CMGR="+index);
      }
      if(cc.indexOf("+CMGR")!=-1){
       String[] contents = getContentFromIndex(index, cc);
       System.out.println("[AT+CMGR=index]讀取存在卡上的短信內(nèi)容.分析后:");
       if(contents!=null){
        System.out.println("新短信內(nèi)容:");
        for(String tt : contents){
         System.out.println(tt);
        }
        //保存讀到的短信 -> 服務(wù)器
        if(sendDataToServer(contents)){
         //刪除已讀出的短信
         System.out.println("刪除已讀出的新短信.index:"+contents[0]);
         delSMSByIndex(serial, Integer.parseInt(contents[0]));
        }
       }else{
        System.out.println("新短信內(nèi)容:null");
       }
      }
      /**
       * 查詢舊短信時(shí):
       * 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\"]存在卡上的短信內(nèi)容.分析后:");
       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[]) 轉(zhuǎn)換成 String時(shí)出錯(cuò)");
     }
    }
    //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;
  }
 }
 /**
  * 把短信上傳到服務(wù)器中
  * @param contents 數(shù)組
    [0] - 短信位置索引
    [1] - 電話號(hào)碼
    [2] - 日期+時(shí)間 2017/10/26 11:37:03+08
    [3] - 短信內(nèi)容
  * @return
  */
 public static boolean sendDataToServer(String[] contents){
  System.out.println("嘗試上傳短信數(shù)據(jù)");
  try{
   //移除時(shí)間中的時(shí)區(qū) +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("數(shù)據(jù)上傳成功!");
    return true;
   }else if(resurl.trim().equals("401")){
    System.out.println("這個(gè)電話號(hào)碼和短信內(nèi)容已上傳過, 數(shù)據(jù)重復(fù)!");
    System.out.println("清除SIM卡上的短信!");
    return true;
   }
  }catch(Exception e){
   e.printStackTrace();
   return false;
  }
  return false;
 }
 /**
  * 解析返回的短信內(nèi)容
  * @return
  */
 public static String[] getContentFromIndex(int index, String res){
  try{
   System.out.println("嘗試讀取短信...getContentFromIndex.res:"+res);
   if(res.indexOf("OK")!=-1){
    System.out.println("獲取短信成功,解析內(nèi)容...");
    /**
     * +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;   //數(shù)據(jù)獲取成功
    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;
    //處理雙引號(hào)
    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 表示所讀取的內(nèi)存位置出錯(cuò),一般是指定位置無短信內(nèi)容所致
    System.out.println("獲取短信失敗,錯(cuò)誤內(nèi)容...");
    return null;
   }
  }catch(Exception e){
   e.printStackTrace();
  }
  return null;
 }
 /**
  * 有新短信時(shí),獲取短信內(nèi)容: 
  * +CIEV: "MESSAGE",1
  * 
  * +CMTI: "SM",1
  * 
  * @return index 短信所在的內(nèi)存位置 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]
  【小米】[小米移動(dòng)]您2017年6月共消費(fèi)1.32元,當(dāng)前余額97.88元。其中:數(shù)據(jù)流量費(fèi)1.32元;語音通信費(fèi)0元;短/彩信費(fèi)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"
  【小米】[小米移動(dòng)]您2017年7月共消費(fèi)0.81元,當(dāng)前余額97.01元。其中:數(shù)據(jù)流量費(fèi)0.81元;語音通信費(fèi)0元;短/彩信費(fèi)0元
  OK
  @return 數(shù)組
    [0] - 短信位置索引
    [1] - 電話號(hào)碼
    [2] - 日期+時(shí)間
    [3] - 短信內(nèi)容
  */
 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條
   }
  }
  //處理雙引號(hào)
  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 信號(hào)質(zhì)量測試,值為0-31,31表示最好
  *   AT+CCID 100ms 讀取SIM的CCID(SIM卡背面20位數(shù)字),可以檢測是否有SIM卡或者是否接觸良好
  *   AT+CREG? 500ms 檢測是否注冊網(wǎng)絡(luò)
  * @return
  */
 public static boolean initGPRS(Serial serial){
  if(!serial.isOpen()){return false;}  //串口未準(zhǔn)備好
  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模塊未準(zhǔn)備好, 請檢查電源和串口波特率是否正確!");
    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卡未準(zhǔn)備好!");
    return false;
   }
   System.out.println(" ...[正常]\r\n");
   //System.out.println("AT+CPIN?.res:"+res);
   System.out.print("\r\n信號(hào)質(zhì)量測試,值為0-31,31表示最好...");
   res = new String(sendCMD(serial, "AT+CSQ"));
   if(res.indexOf("ERROR")!=-1){
    System.out.println("信號(hào)質(zhì)量測試檢測失敗");
    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(" ...信號(hào)強(qiáng)度:["+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.設(shè)置短信模式及短信接收參數(shù)
  *   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設(shè)置有關(guān))
  * 
  * 設(shè)置好后, 收到短信:
  *   +CIEV: "MESSAGE",1
  *   +CMTI: "SM",1   表示存儲(chǔ)位置index=1
  * @return
  */
 public static boolean initGPRS_SMS(Serial serial){
  if(!serial.isOpen()){return false;}  //串口未準(zhǔn)備好
  String res = new String();
  try{
   System.out.print("\r\n設(shè)置短信格式...");
   res = new String(sendCMD(serial, "AT+CMGF=1"));
   if(res.indexOf("OK")==-1){
    System.out.println("設(shè)置失敗!");
    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("設(shè)置失敗!");
    return false;
   }
   System.out.println(" ...[DONE]\r\n");
   Thread.sleep(100);
   System.out.print("\r\n設(shè)置信息保存位置...");
   res = new String(sendCMD(serial, "AT+CPMS=\"SM\",\"SM\",\"SM\""));
   if(res.indexOf("OK")==-1){
    System.out.println("設(shè)置失敗!");
    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("設(shè)置失敗!");
    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;  //每條指令超時(shí)上限 5秒
  long timecount = 0;   //計(jì)時(shí)器
  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()

主要是用于上傳保存短信, 大家替換成自己的方式即可

總結(jié)

以上所述是小編給大家介紹的樹莓派.GPRS.短信接收器,希望對(duì)大家有所幫助!

相關(guān)文章

  • 劍指Offer之Java算法習(xí)題精講排列與N叉樹

    劍指Offer之Java算法習(xí)題精講排列與N叉樹

    跟著思路走,之后從簡單題入手,反復(fù)去看,做過之后可能會(huì)忘記,之后再做一次,記不住就反復(fù)做,反復(fù)尋求思路和規(guī)律,慢慢積累就會(huì)發(fā)現(xiàn)質(zhì)的變化
    2022-03-03
  • 優(yōu)化常見的java排序算法

    優(yōu)化常見的java排序算法

    這篇文章主要介紹了Java編程中快速排序算法的實(shí)現(xiàn)及相關(guān)算法優(yōu)化,快速排序算法的最差時(shí)間復(fù)雜度為(n^2),最優(yōu)時(shí)間復(fù)雜度為(n\log n),存在優(yōu)化的空間,需要的朋友可以參考下
    2021-07-07
  • SpringMVC 中文亂碼的解決方案

    SpringMVC 中文亂碼的解決方案

    這篇文章主要介紹了SpringMVC 中文亂碼的解決方案,幫助大家更好的理解和學(xué)習(xí)使用SpringMVC,感興趣的朋友可以了解下
    2021-04-04
  • 淺析springcloud 整合 zipkin-server 內(nèi)存日志監(jiān)控

    淺析springcloud 整合 zipkin-server 內(nèi)存日志監(jiān)控

    Zipkin是一款開源的分布式實(shí)時(shí)數(shù)據(jù)追蹤系統(tǒng)(Distributed Tracking System),其主要功能是聚集來自各個(gè)異構(gòu)系統(tǒng)的實(shí)時(shí)監(jiān)控?cái)?shù)據(jù)。這篇文章主要介紹了springcloud 整合 zipkin-server 內(nèi)存日志監(jiān)控,需要的朋友可以參考下
    2019-11-11
  • Springboot+Shiro+Jwt實(shí)現(xiàn)權(quán)限控制的項(xiàng)目實(shí)踐

    Springboot+Shiro+Jwt實(shí)現(xiàn)權(quán)限控制的項(xiàng)目實(shí)踐

    如今的互聯(lián)網(wǎng)已經(jīng)成為前后端分離的時(shí)代,所以本文在使用SpringBoot整合Shiro框架的時(shí)候會(huì)聯(lián)合JWT一起搭配使用,具有一定的參考價(jià)值,感興趣的可以了解一下
    2023-09-09
  • Java字節(jié)流和字符流總結(jié)IO流!

    Java字節(jié)流和字符流總結(jié)IO流!

    下面小編就為大家?guī)硪黄狫ava IO流字節(jié)流和字符流的實(shí)例講解。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2021-07-07
  • 如何通過jstack命令dump線程信息

    如何通過jstack命令dump線程信息

    這篇文章主要介紹了如何通過jstack命令dump線程信息,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-07-07
  • Java策略模式取代if else

    Java策略模式取代if else

    在策略模式(Strategy Pattern)中,一個(gè)類的行為或其算法可以在運(yùn)行時(shí)更改。這種類型的設(shè)計(jì)模式屬于行為型模式。在策略模式中,我們創(chuàng)建表示各種策略的對(duì)象和一個(gè)行為隨著策略對(duì)象改變而改變的 context 對(duì)象。策略對(duì)象改變 context 對(duì)象的執(zhí)行算法
    2021-10-10
  • java日期相關(guān)類實(shí)例詳解

    java日期相關(guān)類實(shí)例詳解

    這篇文章主要介紹了java日期相關(guān)類實(shí)例詳解,小編覺得還是挺不錯(cuò)的,這里分享給大家,供需要的朋友參考。
    2017-10-10
  • java實(shí)現(xiàn)兩個(gè)文件的異或運(yùn)算

    java實(shí)現(xiàn)兩個(gè)文件的異或運(yùn)算

    這篇文章主要為大家詳細(xì)介紹了java實(shí)現(xiàn)兩個(gè)文件的異或運(yùn)算,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-07-07

最新評(píng)論