1. 程式人生 > >PHP操作串列埠 --- 操作傳送簡訊mod應用(真實專案)

PHP操作串列埠 --- 操作傳送簡訊mod應用(真實專案)

<span style="font-size:12px;"><strong>首先來一個模組應用的文件截圖:</strong></span>
<img src="https://img-blog.csdn.net/20140822184417003?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvd2Via28=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="" />




<?php
header('Content-type:text/html;charset=UTF-8');
/**
 *  PHP向串列埠傳送資料,操作簡訊model
 *  
 *  ===============簡訊 model 通訊協議說明========
 *  
 *  傳送資料協議格式:SMS13821987654#簡訊內容區
 *  其中:
 *		SMS:			固定指令
 *		13821987654:	為接收簡訊的手機號碼  		
 *  	#:				表示簡訊內容中文。可選值":",表示簡訊內容英文。本用例統一使用#,相容中英文。
 *  	簡訊內容區:	需要傳送的簡訊內容	
 *  如果簡訊內容為中文的指令編碼規則:
 *  	第一部分:SMS13821987654#---分別取各個字元的ASCII碼,然後轉換成對應的16進製表示值。每個字元佔1個位元組。如:53 4D 53 31 33 38 32 31 39 38 37 36 34 35 23
 *  	第二部分:簡訊內容區-------分別取各個字元的UNICODE編碼的16進製表示值,每個字元佔2個位元組。如:77 ed 4f e1 51 85 5b b9 53 3a
 *									(注:字串"簡訊內容"的Unicode編碼為:\u77ed\u4fe1\u5185\u5bb9\u533a)
 */

$tel = '13323332222';	// 接收簡訊的電話號碼
$sms = '《PHP也能幹大事之PHP與串列埠通訊》,@小蠻子&晚點,QQ:467166260';	// 簡訊內容

send($tel, $sms);


// 傳送簡訊
function send($tel, $sms){
	//include "php_serial.class.php";	// 載入php操作串列埠的類
	
	$serial = new phpSerial;
	$serial->deviceSet("COM3");			// 這個硬體裝置在COM3上
	
	if( $serial->deviceOpen() ){
		$code = format_tel('SMS'.$tel.'#').' '.format_sms($sms); // 格式:SMS13821987654#簡訊內容區
		$order = pack_arg($code);
		return $serial->sendMessage($order);
	}
	else
		return false;
}

 /**
 * 將形如“53 4D 53 31 33 39 35 30 30 36 35 30 30 30 23 4F 60 59 7D”的資料裝入一個二進位制字串進行組包,以待通訊
 */
 function pack_arg($str){
	$args = explode(' ', $str);
	$php = 'return pack("c*",';
	
	for($i=0; $i<count($args); $i++){
		$php = "{$php}0x{$args[$i]},";
	}
	$php = rtrim($php, ',');
	$php .= ');';
	
	return eval($php);
}

//=======================  兩個自定義工具函式 =====================
 /**
 * 將字串轉換成ACSII碼所對應的十六進位制,每個字元佔1個位元組。例:13518250288=>31 33 35 31 38 32 35 30 32 38 38
 */
function format_tel($str){
	$rt = '';
	for($i=0; $i<strlen($str); $i++) {
		$rt = $rt.' '.dechex(ord($str{$i}));
	}
	
	return trim($rt);
}

 /**
 * 取字串的unicode編碼的十六進位制表示方法,以2個位元組來表示一個字元。例:你好=>4F 60 59 7D  Aa=>00 65 00 97 
 */
function format_sms($str){
	$rt = '';
	
	for($i=0; $i < mb_strlen($str, 'UTF-8'); $i++){
		$c = mb_substr($str, $i, 1, 'UTF-8');
		$ord = ord($c);
		
		if($ord > 127) { //中文
			$tmp = strtolower(trim(json_encode($c), '"')); //形如:\U0E74
			$rt = $rt.' '.substr($tmp, 2, 2).' '.substr($tmp, 4, 2);
		} 
		else {
			$rt .= ' 00 '.dechex($ord);
		}
	}
	
	return trim($rt);
}

其中用到了一個類:php_serial.class.php

<?php
define ("SERIAL_DEVICE_NOTSET", 0);
define ("SERIAL_DEVICE_SET", 1);
define ("SERIAL_DEVICE_OPENED", 2);

/**
 * Serial port control class
 *
 * THIS PROGRAM COMES WITH ABSOLUTELY NO WARANTIES !
 * USE IT AT YOUR OWN RISKS !
 *
 * @author R閙y Sanchez <[email protected]
> * @thanks Aur閘ien Derouineau for finding how to open serial ports with windows * @thanks Alec Avedisyan for help and testing with reading * @copyright under GPL 2 licence */ class phpSerial { var $_device = null; var $_windevice = null; var $_dHandle = null; var $_dState = SERIAL_DEVICE_NOTSET; var $_buffer = ""; var $_os = ""; /** * This var says if buffer should be flushed by sendMessage (true) or manualy (false) * * @var bool */ var $autoflush = true; /** * Constructor. Perform some checks about the OS and setserial * * @return phpSerial */ function phpSerial () { setlocale(LC_ALL, "en_US"); $sysname = php_uname(); if (substr($sysname, 0, 5) === "Linux") { $this->_os = "linux"; if($this->_exec("stty --version") === 0) { register_shutdown_function(array($this, "deviceClose")); } else { trigger_error("No stty availible, unable to run.", E_USER_ERROR); } } elseif(substr($sysname, 0, 7) === "Windows") { $this->_os = "windows"; register_shutdown_function(array($this, "deviceClose")); } else { trigger_error("Host OS is neither linux nor windows, unable tu run.", E_USER_ERROR); exit(); } } // // OPEN/CLOSE DEVICE SECTION -- {START} // /** * Device set function : used to set the device name/address. * -> linux : use the device address, like /dev/ttyS0 * -> windows : use the COMxx device name, like COM1 (can also be used * with linux) * * @param string $device the name of the device to be used * @return bool */ function deviceSet ($device) { if ($this->_dState !== SERIAL_DEVICE_OPENED) { if ($this->_os === "linux") { if (preg_match("@^COM(\d+):
[email protected]
", $device, $matches)) { $device = "/dev/ttyS" . ($matches[1] - 1); } if ($this->_exec("stty -F " . $device) === 0) { $this->_device = $device; $this->_dState = SERIAL_DEVICE_SET; return true; } } elseif ($this->_os === "windows") { if (preg_match("@^COM(\d+):[email protected]", $device, $matches) and $this->_exec(exec("mode " . $device)) === 0) { $this->_windevice = "COM" . $matches[1]; $this->_device = "\\.\com" . $matches[1]; $this->_dState = SERIAL_DEVICE_SET; return true; } } trigger_error("Specified serial port is not valid", E_USER_WARNING); return false; } else { trigger_error("You must close your device before to set an other one", E_USER_WARNING); return false; } } /** * Opens the device for reading and/or writing. * * @param string $mode Opening mode : same parameter as fopen() * @return bool */ function deviceOpen ($mode = "r+b") { if ($this->_dState === SERIAL_DEVICE_OPENED) { trigger_error("The device is already opened", E_USER_NOTICE); return true; } if ($this->_dState === SERIAL_DEVICE_NOTSET) { trigger_error("The device must be set before to be open", E_USER_WARNING); return false; } if (!preg_match("@^[raw]\[email protected]", $mode)) { trigger_error("Invalid opening mode : ".$mode.". Use fopen() modes.", E_USER_WARNING); return false; } $this->_dHandle = @fopen($this->_device, $mode); if ($this->_dHandle !== false) { stream_set_blocking($this->_dHandle, 0); $this->_dState = SERIAL_DEVICE_OPENED; return true; } $this->_dHandle = null; trigger_error("Unable to open the device", E_USER_WARNING); return false; } /** * Closes the device * * @return bool */ function deviceClose () { if ($this->_dState !== SERIAL_DEVICE_OPENED) { return true; } if (fclose($this->_dHandle)) { $this->_dHandle = null; $this->_dState = SERIAL_DEVICE_SET; return true; } trigger_error("Unable to close the device", E_USER_ERROR); return false; } // // OPEN/CLOSE DEVICE SECTION -- {STOP} // // // CONFIGURE SECTION -- {START} // /** * Configure the Baud Rate * Possible rates : 110, 150, 300, 600, 1200, 2400, 4800, 9600, 38400, * 57600 and 115200. * * @param int $rate the rate to set the port in * @return bool */ function confBaudRate ($rate) { if ($this->_dState !== SERIAL_DEVICE_SET) { trigger_error("Unable to set the baud rate : the device is either not set or opened", E_USER_WARNING); return false; } $validBauds = array ( 110 => 11, 150 => 15, 300 => 30, 600 => 60, 1200 => 12, 2400 => 24, 4800 => 48, 9600 => 96, 19200 => 19, 38400 => 38400, 57600 => 57600, 115200 => 115200 ); if (isset($validBauds[$rate])) { if ($this->_os === "linux") { $ret = $this->_exec("stty -F " . $this->_device . " " . (int) $rate, $out); } elseif ($this->_os === "windows") { $ret = $this->_exec("mode " . $this->_windevice . " BAUD=" . $validBauds[$rate], $out); } else return false; if ($ret !== 0) { trigger_error ("Unable to set baud rate: " . $out[1], E_USER_WARNING); return false; } } } /** * Configure parity. * Modes : odd, even, none * * @param string $parity one of the modes * @return bool */ function confParity ($parity) { if ($this->_dState !== SERIAL_DEVICE_SET) { trigger_error("Unable to set parity : the device is either not set or opened", E_USER_WARNING); return false; } $args = array( "none" => "-parenb", "odd" => "parenb parodd", "even" => "parenb -parodd", ); if (!isset($args[$parity])) { trigger_error("Parity mode not supported", E_USER_WARNING); return false; } if ($this->_os === "linux") { $ret = $this->_exec("stty -F " . $this->_device . " " . $args[$parity], $out); } else { $ret = $this->_exec("mode " . $this->_windevice . " PARITY=" . $parity{0}, $out); } if ($ret === 0) { return true; } trigger_error("Unable to set parity : " . $out[1], E_USER_WARNING); return false; } /** * Sets the length of a character. * * @param int $int length of a character (5 <= length <= 8) * @return bool */ function confCharacterLength ($int) { if ($this->_dState !== SERIAL_DEVICE_SET) { trigger_error("Unable to set length of a character : the device is either not set or opened", E_USER_WARNING); return false; } $int = (int) $int; if ($int < 5) $int = 5; elseif ($int > 8) $int = 8; if ($this->_os === "linux") { $ret = $this->_exec("stty -F " . $this->_device . " cs" . $int, $out); } else { $ret = $this->_exec("mode " . $this->_windevice . " DATA=" . $int, $out); } if ($ret === 0) { return true; } trigger_error("Unable to set character length : " .$out[1], E_USER_WARNING); return false; } /** * Sets the length of stop bits. * * @param float $length the length of a stop bit. It must be either 1, * 1.5 or 2. 1.5 is not supported under linux and on some computers. * @return bool */ function confStopBits ($length) { if ($this->_dState !== SERIAL_DEVICE_SET) { trigger_error("Unable to set the length of a stop bit : the device is either not set or opened", E_USER_WARNING); return false; } if ($length != 1 and $length != 2 and $length != 1.5 and !($length == 1.5 and $this->_os === "linux")) { trigger_error("Specified stop bit length is invalid", E_USER_WARNING); return false; } if ($this->_os === "linux") { $ret = $this->_exec("stty -F " . $this->_device . " " . (($length == 1) ? "-" : "") . "cstopb", $out); } else { $ret = $this->_exec("mode " . $this->_windevice . " STOP=" . $length, $out); } if ($ret === 0) { return true; } trigger_error("Unable to set stop bit length : " . $out[1], E_USER_WARNING); return false; } /** * Configures the flow control * * @param string $mode Set the flow control mode. Availible modes : * -> "none" : no flow control * -> "rts/cts" : use RTS/CTS handshaking * -> "xon/xoff" : use XON/XOFF protocol * @return bool */ function confFlowControl ($mode) { if ($this->_dState !== SERIAL_DEVICE_SET) { trigger_error("Unable to set flow control mode : the device is either not set or opened", E_USER_WARNING); return false; } $linuxModes = array( "none" => "clocal -crtscts -ixon -ixoff", "rts/cts" => "-clocal crtscts -ixon -ixoff", "xon/xoff" => "-clocal -crtscts ixon ixoff" ); $windowsModes = array( "none" => "xon=off octs=off rts=on", "rts/cts" => "xon=off octs=on rts=hs", "xon/xoff" => "xon=on octs=off rts=on", ); if ($mode !== "none" and $mode !== "rts/cts" and $mode !== "xon/xoff") { trigger_error("Invalid flow control mode specified", E_USER_ERROR); return false; } if ($this->_os === "linux") $ret = $this->_exec("stty -F " . $this->_device . " " . $linuxModes[$mode], $out); else $ret = $this->_exec("mode " . $this->_windevice . " " . $windowsModes[$mode], $out); if ($ret === 0) return true; else { trigger_error("Unable to set flow control : " . $out[1], E_USER_ERROR); return false; } } /** * Sets a setserial parameter (cf man setserial) * NO MORE USEFUL ! * -> No longer supported * -> Only use it if you need it * * @param string $param parameter name * @param string $arg parameter value * @return bool */ function setSetserialFlag ($param, $arg = "") { if (!$this->_ckOpened()) return false; $return = exec ("setserial " . $this->_device . " " . $param . " " . $arg . " 2>&1"); if ($return{0} === "I") { trigger_error("setserial: Invalid flag", E_USER_WARNING); return false; } elseif ($return{0} === "/") { trigger_error("setserial: Error with device file", E_USER_WARNING); return false; } else { return true; } } // // CONFIGURE SECTION -- {STOP} // // // I/O SECTION -- {START} // /** * Sends a string to the device * * @param string $str string to be sent to the device * @param float $waitForReply time to wait for the reply (in seconds) */ function sendMessage ($str, $waitForReply = 0.1) { $this->_buffer .= $str; if ($this->autoflush === true) $this->flush(); usleep((int) ($waitForReply * 1000000)); } /** * Reads the port until no new datas are availible, then return the content. * * @pararm int $count number of characters to be read (will stop before * if less characters are in the buffer) * @return string */ function readPort ($count = 0) { if ($this->_dState !== SERIAL_DEVICE_OPENED) { trigger_error("Device must be opened to read it", E_USER_WARNING); return false; } if ($this->_os === "linux") { $content = ""; $i = 0; if ($count !== 0) { do { if ($i > $count) $content .= fread($this->_dHandle, ($count - $i)); else $content .= fread($this->_dHandle, 128); } while (($i += 128) === strlen($content)); } else { do { $content .= fread($this->_dHandle, 128); } while (($i += 128) === strlen($content)); } return $content; } elseif ($this->_os === "windows") { /* Do nohting : not implented yet */ } trigger_error("Reading serial port is not implemented for Windows", E_USER_WARNING); return false; } /** * Flushes the output buffer * * @return bool */ function flush () { if (!$this->_ckOpened()) return false; if (fwrite($this->_dHandle, $this->_buffer) !== false) { $this->_buffer = ""; return true; } else { $this->_buffer = ""; trigger_error("Error while sending message", E_USER_WARNING); return false; } } // // I/O SECTION -- {STOP} // // // INTERNAL TOOLKIT -- {START} // function _ckOpened() { if ($this->_dState !== SERIAL_DEVICE_OPENED) { trigger_error("Device must be opened", E_USER_WARNING); return false; } return true; } function _ckClosed() { if ($this->_dState !== SERIAL_DEVICE_CLOSED) { trigger_error("Device must be closed", E_USER_WARNING); return false; } return true; } function _exec($cmd, &$out = null) { $desc = array( 1 => array("pipe", "w"), 2 => array("pipe", "w") ); $proc = proc_open($cmd, $desc, $pipes); $ret = stream_get_contents($pipes[1]); $err = stream_get_contents($pipes[2]); fclose($pipes[1]); fclose($pipes[2]); $retVal = proc_close($proc); if (func_num_args() == 2) $out = array($ret, $err); return $retVal; } // // INTERNAL TOOLKIT -- {STOP} // } ?>


相關推薦

PHP操作串列 --- 操作傳送簡訊mod應用真實專案

<span style="font-size:12px;"><strong>首先來一個模組應用的文件截圖:</strong></span> <img src="https://img-blog.csdn.net/2014

如何在windows系統下用串列通訊完爆raspberry pi樹莓派

相關文章  在沒有網路,沒用鍵盤,沒有顯示器的情況下,控制樹莓派就成了一個問題。 通過串列埠通訊果斷的試用了一次發現效果不錯,下面就和大家一起分享一下。 所需裝置: 1.raspberry pi 板子一塊 2.一張SD卡(至少2G我們採用8G) 3.一根

stm32-串列接受不定長資料方法3種

方法1:串列埠接受資料,定時器來判斷超時是否接受資料完成。 方法2:DMA接受+IDLE中斷 實現思路:採用STM32F103的串列埠1,並配置成空閒中斷IDLE模式且使能DMA接收,並同時設定接收緩衝區和初始化DMA。那麼初始化完成之後,當外部給單片機發送資料的時候,

串列通訊】--執行緒應用1

一、前言: 關於串列埠通訊中的執行緒問題,本來是早就想總結一下的。但是在這兩個星期的學習過程中,發現自己原來的理解還是有很多的不全面的地方。通過兩個月的學習,自己對這塊的認識還是有了很大的提升,今

使用python在openwrt下操作串列傳送十六進位制資料

#!/usr/bin/python import serial from time import sleep ser = serial.Serial('/dev/ttyS0', 9600, timeout=0.5) print ser.port print ser.baudrate if

轉:Python通過pyserial控制串列操作

https://blog.csdn.net/lovelyaiq/article/details/48101487  你想通過串列埠讀寫資料,典型場景就是和一些硬體裝置打交道(比如一個機器人或感測器)。儘管你可以通過使用Python內建的I/O模組來完成這個任務,但對於序列通訊最好的選擇是使用 py

轉:神奇的python之python的串列操作pyserial

https://blog.csdn.net/qq_14997473/article/details/80875722:Python學習筆記——串列埠配置以及傳送資料 https://blog.csdn.net/ubuntu14/article/details/75335106:python實現串列埠

轉: python 操作串列

https://www.cnblogs.com/zhengweizhao/p/8426826.html import serial匯入模組 然後就可以用了 ser = serial.Serial(0) 是開啟第一個串列埠 print ser.portstr 能看到第一個串列埠的標識,window

c++串列操作

0. 前言   做串列埠方面的程式,使用CreateFile開啟串列埠通訊埠。在對串列埠操作之前,需要首先開啟串列埠。使用C++進行串列埠程式設計,如果採用VS開發,則可以直接藉助於串列埠通訊控制元件來操作,其次,直接呼叫Windows的底層API函式來控制串列埠通訊。   在Window 32

MFC操作串列,詳細 複製程式碼ActiveX控制元件和Windows API函式

/******************************************************************* *******函式功能:開啟串列埠裝置連結 *******函式名稱:OpenComm *******輸入引數:無 *******輸出引數:無 ***

python3操作串列

通過引用serial模組包,來操作串列埠。 1、檢視串列埠名稱 在Linux和Windows中,串列埠的名字規則不太一樣。需要事先檢視。 Linux下的檢視串列埠命令 [email protected]:~# ls -l /dev/ttyS* crw-rw---- 1 root dialou

樹莓派3B Wiring Pi 串列操作

Wiring Pi是為樹莓派提供的GPIO的介面庫,我目前只使用了串列埠的介面,下面也只介紹一下串列埠的使用。 串列埠操作提供了開啟串列埠、讀取資料、傳送資料、關閉串列埠介面。 int fd; if(wiringPiSetup() < 0)

C# 串列操作系列(1) -- 入門篇,一個標準的,簡陋的串列例子。

我假設讀者已經瞭解了c#的語法,本文是針對剛打算解除串列埠程式設計的朋友閱讀的,作為串列埠程式設計的入門範例,也是我這個系列的基礎。 我們的開發環境假定為vs2005(雖然我在用vs2010,但避免有些網友用2005,不支援lambda,避免不相容,就用2005來做例子)

C#控制檯操作串列例項例程

本文介紹一個C#控制檯下操作串列埠的範例程式,基於多執行緒的一個接收,一個傳送,可以用來作為參考,實測VS2010編譯使用通過。 using System; using System.Collections.Generic; using System.Linq; using

C# 串列操作系列(1) -- 入門篇,一個標準的,簡陋的串列例子

我假設讀者已經瞭解了c#的語法,本文是針對剛打算解除串列埠程式設計的朋友閱讀的,作為串列埠程式設計的入門範例,也是我這個系列的基礎。 我們的開發環境假定為vs2005(雖然我在用vs2010,但避免有些網友用2005,不支援lambda,避免不相容,就用2005來做例子

linux使用者層串列操作

  /* After the UART speed has been changed, the IOCTL is    * is called to set the line discipline to N_HW_BFG    */   ldisc = N_HW_BFG;   /* 選擇線路規程 */   i

Android串列操作,簡化android-serialport-api的demo

感謝分享:http://lpcjrflsa.iteye.com/blog/2097280最近在做android串列埠的開發,找到一個開源的串列埠類android-serialport-api。其主頁在這裡http://code.google.com/p/android-ser

C# 串列操作系列(5)--通訊庫雛形

串列埠是很簡單的,編寫基於串列埠的程式也很容易。新手們除了要面對一堆的生僻概念,以及跨執行緒訪問的細節,還有一個需要跨越的難題,就是協議解析,上一篇已經說明了: 一個二進位制格式的協議一般包含: 協議頭 + 資料段長度 + 資料  + 校驗 一個Ascii格式的文字協議,一般

silverlight 操作串列資料的程式碼

串列埠PINVOKE程式碼,需要對超時時間進行設定,如果全為0,則是無限等待。而不是獲取不到退出。 public class SerialWrapper : IDisposable { #region Enum public enum

【C#】串列操作實用類

publicclass PortData    {        publicevent PortDataReceivedEventHandle Received;        publicevent SerialErrorReceivedEventHandler Error;         public