程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> 網頁編程 >> PHP編程 >> 關於PHP編程 >> PHP通過串口發短信,PHP串口發短信

PHP通過串口發短信,PHP串口發短信

編輯:關於PHP編程

PHP通過串口發短信,PHP串口發短信


隨技術進步,短信收發領域按時間先後產生了三種模式:BLOCK MODE,基於AT指令的TEXT MODE,基於AT指令的PDU MODE。其中,TEXT MODE比較簡單,多款諾基亞手機均支持此款模式。西門子的手機大多數只支持PDU MODE。PDU 模式是收發短信的一種方法,短信正文經過十六進制編碼後被傳送。目前,PDU已取代BLOCK MODE。

SMS是由Etsi所制定的一個規范(GSM 03.40 和GSM 03.38)。當使用7-bits編碼時,它可以發送最多160個字符;但用8-bit編碼,最多可以發送140個字符,通常無法直接通過手機顯示;還有用16-bit編碼時,最多70個字符,被用來顯示Unicode(UCS2)文本信息,可以被大多數的手機所顯示。

     今天討論的是PDU MODE,UCS2編碼,也就是說,最多只能發送70個字符,不管英文還是中文。
     假設現在要發送如下信息:“你好”。在沒有發送之前,要知道手機SIM卡所在地的短信中心號,例如移動的短信中心號:

      接收的手機號:13638197275
      杭州短信中心號:13800571500
      短信內容: 你好
    發送這條短信,要進行編碼後手機才會執行,編碼後會變成以下一串字符:
0891683180501705F011000D91683136187972F5000800044F60597D
   看不懂吧,從頭到尾把這串編碼解釋一下:
       08 – 指的是短信中心號的長度,也就是指(91)+(683180501705F0)的長度除以2,即 08 =(2+14)/ 2
       91 – 指的是短信息中心號碼類型。91是TON/NPI遵守International/E.164標准,指在號碼前需加‘+’號;此外還有其它數值,但91最常用。
       683180501705F0  - 短信息中心號碼。由於位置上略有處理,實際號碼應為:8613800571500(字母F是補足偶數長度添加的字符)。
       11 - 文件頭字節
       00 - 信息類型(TP-Message-Reference)
       0D - 被叫號碼長度
       91 - 被叫號碼類型

其實在實際處理中,我們通常把11000D91寫死在程序中,因為在國內,這些數據都是不會改變的。

       683136187972F5 - 被叫號碼,經過了位移處理,實際號碼為“8613638197275”。

    上面的(00 )+(0D )+(91 )+(683136187972F5 ),構成了整個短信的第二部份目的地址(TP-Destination-Address)。

    繼續...
    00 - 協議標識TP-PID,這裡一般為00
    08 - 數據編碼方案TP-DCS(TP-Data-Coding-Scheme),采用前面說的USC2(16bit)數據編碼
    00 - 有效期TP-VP(TP-Valid-Period)
    04  - 長度TP-UDL(TP-User-Data-Length),也就是信息長度/2的十六進04
    4F60597D 這裡就是短信內容了,實際內容為:“你好”

   根據以上情況,就可以寫出短信編碼的程序腳本了。

一、短信中心號碼處理:
1、將短信息中心號碼“+8613800571500”去掉+號,看長度是否為偶數,如果不是,最後添加F
=> “8613800571500F”
2、將奇數位和偶數位交換。
=> “683108501705F0″
3、將短信息中心號碼前面加上字符91,91是國際化的意思
=> “91683108501705F0″
4、算出長度,結果除2,格式化成2位的16進制字符串,16 / 2 = 8 => “08″
=> “0891683108501705F0″

二、手機號碼處理:
1、將手機號碼+8613638197275去掉+號,看看長度是否為偶數,如果不是,最後添加F
=> “8613638197275F”
2、將手機號碼奇數位和偶數位交換。
=> “683136187972F5″

三、短信息部分處理:
1、轉字符串轉換為Unicode代碼,
“你好”的unicode代碼 為4F60597D
2、將長度除2,保留兩位16進制數,即 4F60597D = 8 / 2 => “04″,
=> “044F60597D″

四、組合
1、手機號碼前加上字符串 11000D91(1100:固定,0D:手機號碼的長度,不算+號,十六進制表示,91:發送
到手機為91,發送到小靈通為81),
即 11000D91 + 683136187972F5
=> 11000D91683136187972F5
2、手機號碼後加上 000800 和剛才的短信息內容,000800也寫死就可以了
即 11000D91683136187972F5 + 000800 + 044F60597D
=>  11000D91683136187972F5000800044F60597D
3、整條信息長度除以2,格式化成2位的十進制數
即 11000D91683136187972F5000800044F60597D => 38位 / 2 => 19

五、所以要發送的內容為
AT+CMGF=0 <回車> #此處為設定短信發送模式PDU
OK
AT+CMGS=19<回車>
> #輸入短信內容編碼

附加最終PHP代碼:

    <?php  
    // Requirement dio, use cmd install: pecl install dio  
    set_time_limit(0);  
      
    // Windows use COM1:  
    $fd=dio_open('/dev/ttyS0', O_RDWR);  
    if(!$fd)  
    {  
        die("打開串口ttyS0失敗");  
    }  
      
    // dio_tcsetattr() only Linux   
    // Windows 使用 exec('mode COM1: baud=9600 data=8 stop=1 parity=n xon=on');  
    dio_tcsetattr($fd, array(  
      'baud' => 9600,  
      'bits' => 8,  
      'stop'  => 1,  
      'parity' => 0  
    ));  
      
    //$ff=dio_stat($fd);  
    //print_r($ff);  
    //echo "GSM AT is start on ttyS0\n";  
      
    //短信中心號碼  
    $smsc = "8613800571500";  
    $invert_smsc = invertNumbers($smsc); // 轉換短信中心號碼  
    $inter = chr(13); // 回車字符  
      
    $ctrlz = chr(26); // ctrl+z  
      
    // 發送信息  
    $text   
       = '你好';  
    $send_to = '8613638197275';  
    $pdu_phone  = hex2str(utf82unicode($text));  
    $pdu_phone  = sprintf("%02X", strlen($pdu_phone)/2) . $pdu_phone;  
    $pdu_phone  = '11000D91' . invertNumbers($send_to) . '000800' . $pdu_phone;  
    $atcmd      = 'AT+CMGF=0' . $inter;  
    @dio_write($fd, $atcmd);  
    $atcmd      = 'AT+CMGS=' . sprintf("%d", strlen($pdu_phone)/2) . $inter;  
    @dio_write($fd, $atcmd);  
    $pdu_addr   = '0891' . invertNumbers($smsc);  
    $pdu_all    = $pdu_addr . $pdu_phone . $ctrlz . $inter;  
    @dio_write($fd, $pdu_all);  
    dio_close($fd);  
      
    // 我的是utf-8編碼   
    function utf82unicode($str)    
    {  
        return iconv("utf-8", "UCS-2BE", $str);  
    }  
       
    function hex2str($hexstring)    
    {  
        $str = '';  
        for($i = 0, $len = strlen($hexstring); $i < $len; $i++)  
        {  
            $str .= sprintf("%02X", ord(substr($hexstring, $i, 1)));  
        }  
        return $str;  
    }  
       
    function invertNumbers($msisdn)    
    {  
        $len = strlen($msisdn);  
        if ( 0 != fmod($len, 2) )   
        {  
            $msisdn .= "F";  
            $len = $len + 1;  
        }  
       
        for ($i=0; $i<$len; $i+=2)   
        {  
            $t = $msisdn[$i];  
            $msisdn[$i] = $msisdn[$i+1];  
            $msisdn[$i+1] = $t;  
        }  
        return $msisdn;  
    }  
       
    ?>  

 

  附1 :各地移動短信中心號碼   輸入當地移動局的短消息號碼: +8613800xxx500("+"號必須輸入), 其中xxx 為當地的電話區號。 --- 電話區號是三位的地區: 直接用電話區號替換xxx 即可。 例如:深圳電話區號是755, 移動的短消息中心號碼是:+8613800755500 --- 電話區號是兩位的地區: 請在區號後加"0"補足三位替換xxx。 例如:北京電話區號是10, 移動的短消息中心號碼是:+8613800100500 目前聯通165 網已在全國范圍內開展業務。 在使用短信業務之前,需設置短信中心服務號碼: 北京+8613010112500 上海+8613010314500 深圳+8613010888500 山東+8613010171500 江蘇+8613010341500 浙江+8613010360500 福建+8613010380500 四川+8613010811500 重慶+8613010831500 海南+8613010501500 黑龍江+8613010980500 吉林+8613010911500 天津+8613010130500 河北+8613010180500 內蒙古+8613010950500 山西+8613010701500 安徽+8613010305500 新疆+8613010969500 青海+8613010776500 甘肅+8613010879500 寧夏+8613010796500 貴州+8613010788500 雲南+8613010868500 湖南+8613010731500 湖北+8613010710500 廣東+8613010200500 廣西+8613010591500 河南+8613010761500 江西+8613010720500 遼寧+8613010240500   附2 :常用AT 指令: AT+CSMS 選擇短信息服務 AT+CPMS 選擇短信息內存 AT+CMGF 選擇短信息格式 AT+CSCA 短信息中心地址 AT+CNMI 顯示新收到的短信息 AT+CMGR 讀短信息 AT+CMGS 發送短信息 AT+CMGL 列出SIM 卡中短信息 AT+CMSS 從SIM 內存中發短信息 AT+CMGW 向SIM 內存中寫入待發短信息 AT+CMGD 刪除SIM 內存中的短信息 AT+CSCB 選擇蜂窩廣播信息   附3 :短信息的接收 接收短消息實質上就是從SIM 或緩存中讀出信息。這主要利用AT+CMGR 和AT+CMG L 兩條指令來完成,由於無線模塊不同的廠商對AT 指令集的解釋代碼和響應信息不一樣, 所以首先要確認能否與MODEM 建立起通信,一般用AT 指令完成此確認;然後用AT+CM GF 指令選定短消息的數據格式;在收到MODEM 的正確回答反以AT 指令完成讀出功能。 一般用AT+CMGL 讀取以前的信息,在收到MODEM 的RING(振鈴)數據時,用AT+CM GR 讀取實時信息。以下是用H6221-W 的接收SMS 的一個實例,它說明了PDU 模式的應 用。 操作過程如下({}內為注釋): 發送:AT 回答:OK {已建立聯接} 發送:AT+CMGF=0 {選用PDU 格式} 回答:OK {允許選擇PDU 格式} 發送:AT+CMGL=2 {列出已有的短信息} 回答:+CMGL:1,2,,24{1 表示信息個數,2 表示未發信息,24 表示信息總容量} 0D71683108370105F004000D81683179133208F10000026080410033802632184C F682D 95E0DC2B36D3D170A0243106933D97A0243106933D97A02451068B1983492608 OK 以上這組PDU 格式的十六進制字符串,不但包含了短消息的內容,同時包含了發送者 的號碼、短信息中心號碼、短消息發送時間等。 下面對信息內容進行分析: 0D:短信息中心地址(號碼)長度。 91:短信息中心號碼類型,91 是TON/NPI。TON/NPI 遵守International/E.164 標准, 指在號碼前需加'+'號;此外還可直有其他數值,但91 最常用。 683108370105F0:SMSC 短信息所使用的服務中心號碼13807310500。它經過十六 進制以字節為單位的高低半字節換位處理,號碼是奇數的添F,構成一個HEX 字節。 04:PDU 類型,文件頭字節。 0B:主叫號碼長度。 81:主叫號碼類型。 3179133208F1:0A 主叫號碼,也經過了處理,實際號碼為13973123801。 00:PID,為協議標識。 00:DCS 短信息編碼類型是GSM Default Alphabet,即由7 位ASCII 碼移位組成8 位 十六進制碼(octet),其方法見表2。 1sthex B0 A6 A5 A4 A3 A2 A1 A0 2ndhex C1 C0 B6 B5 B4 B3 B2 B1 3rdhex D2 D1 D0 C6 C5 C4 C3 C2 4thhex E3 E2 E1 E0 D6 D5 D4 D3 5thhex F4 F3 F2 F1 F0 E6 E5 E4 6thhex G5 G4 G3 G2 G1 G0 F6 F5 6thhex H6 H5 H4 H3 H2 H1 H0 G6 02608041003380:SCTS 短信息發送時間,02/06/08/14:00:33.08。 26:UDL 經處理後的8 位碼(octet)短信息字節長度,它小於消息ASCII 碼的長度。 32184CF682D95E30DC2B36D3D170A0243106933D97A0243106933D97A0245106 8B1983492608:UD 編碼後的PDU 數據,短信息內容“2002/06/08/13:48ID102OKID103 OK ID201FAIL”。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved