BayEOS-PHP
 All Data Structures Namespaces Files Functions Variables Pages
phpXBee.php
Go to the documentation of this file.
1 <?php
2 require 'BayEOSSerialPHP.php';
22 define("XBEE_ESCAPE",pack("C",0x7d));
23 define("XBEE_DELIM",pack("C",0x7e));
24 define("XON",pack("C",0x11));
25 define("XOFF",pack("C",0x13));
26 class XBee extends phpSerial {
27  private $stack;
33  function XBee() {
34  $this->stack=array();
35  parent::phpSerial();
36  }
37 
44  public function confDefaults($device = '/dev/ttyUSB0') {
45  $this -> deviceSet($device);
46  $this -> confBaudRate(38400);
47  $this -> confParity('none');
48  $this -> confCharacterLength(8);
49  $this -> confStopBits(1);
50  $this -> confFlowControl('none');
51  }
52 
60  public function open($waitForOpened=0.1) {
61  $this -> deviceOpen();
62  usleep((int) ($waitForOpened * 1000000));
63  }
64 
69  public function close() {
70  $this -> deviceClose();
71  }
72 
80  public function send($frame , $waitForReply=0) {
81  $frame=XBEE_DELIM.$this->_escape($frame);
82  $this -> sendMessage($frame, $waitForReply);
83  //echo 'Send: '.array_pop(unpack('H*',$frame))."\n"; //debug
84  }
85 
86  public function read($count = 0){
87  $data = $this -> readPort($count);
88  //echo 'READ: '.array_pop(unpack('H*',$data))."\n";
89  if(! $data) return count($this->stack);
90  if(! isset($this->stack[0])){
91  $delim_pos=strpos($data,XBEE_DELIM);
92  if($delim_pos===FALSE) return 0;
93  else $data=substr($data,$delim_pos+1);
94  }
95 
96  $data=explode(XBEE_DELIM,$data);
97  $offset=count($this->stack)-1;
98  if($offset==-1) $offset=0;
99  for($i=0;$i<count($data);$i++){
100  $index=$i+$offset;
101  if(! isset($this->stack[$index]['ts']))
102  $this->stack[$index]['ts']=microtime(TRUE);
103  if(! isset($this->stack[$index]['rawframe']))
104  $this->stack[$index]['rawframe']='';
105  $this->stack[$index]['rawframe'].=$data[$i];
106  $this->stack[$index]['frame']=$this->_unescape($this->stack[$index]['rawframe']);
107  $this->stack[$index]['ok']=$this->_parseFrame($this->stack[$index]['frame']);
108  if(! $this->stack[$index]['ok'] && ($i+1)<count($data)){
109  //Invalid Frame!
110  unset($this->stack[$index]);
111  $offset--;
112  fwrite(STDERR,date('Y-m-d H:i:s').' '.$this->_device." : Invalid frame\n");
113  }
114  }
115 
116  $anz=count($this->stack);
117  //echo "Stackcount: $anz\n";
118  if(! $this->stack[$anz-1]['ok']) $anz--;
119  return $anz;
120  }
121 
122  public function getPANID(){
123  $this->send(pack('C7',0x00,0x04,0x08,0x01,0x49,0x44,0x69));
124 
125  while(($data=$this->getFrame())){
126  $f=$data['frame'];
127  //echo "Got:".array_pop(unpack('H*',$f))."\n";
128  if($f[2]==pack("C",0x88) && $f[4]=='I' && $f[5]=='D' && $f[6]==pack("C",0x0)){
129  return array_pop(unpack('n',substr($f,7,2)));
130  }
131  }
132  die("Could not get PANID\n");
133  }
134 
135  private function _parseFrame($frame){
136  if(strlen($frame)<3) return FALSE;
137  $length = substr($frame, 0, 2);
138  $checksum = substr($frame, -1);
139  $cmdData = substr($frame, 2, -1);
140  $calculatedChecksum = $this -> _calcChecksum($cmdData);
141  $calculatedLength = pack('n',strlen($cmdData));
142 
143  //echo "parseFrame: ".array_pop(unpack('H*',$frame.$calculatedChecksum.$checksum.$calculatedLength.$length))."\n";
144  if ($checksum === $calculatedChecksum && $length === $calculatedLength) {
145  return TRUE;
146  } else {
147  return FALSE;
148  }
149 
150  }
151 
152 
153 
160  protected function _calcChecksum($data) {
161  $checksum = 0;
162  for ($i = 0; $i < strlen($data); $i++) {
163  $checksum += ord($data[$i]);
164  }
165  $checksum = $checksum & 0xFF;
166  $checksum = 0xFF - $checksum;
167  $checksum = chr($checksum);
168  return $checksum;
169  }
170 
171 
172  public function getFrame($timeout=120){
173  while($this->read()==0 && $timeout>0){
174  $timeout-=0.01;
175  usleep(10000);
176  }
177  if($timeout<0) return FALSE;
178  return array_shift($this->stack);
179  }
180 
181  private function _escape($rawData){
182  $res='';
183  for($i=0;$i<strlen($rawData);$i++){
184  if(in_array($rawData[$i],array(XBEE_ESCAPE,XBEE_DELIM,XOFF,XOFF)))
185  $res.=XBEE_ESCAPE.(pack("C",0x20) ^ $rawData[$i]);
186  else $res.=$rawData[$i];
187  }
188  return $res;
189  }
190 
191  private function _unescape($rawData){
192  //echo "Unescape: ".array_pop(unpack('H*',$rawData))."\n";
193  $res='';
194  for($i=0;$i<strlen($rawData);$i++){
195  if($rawData[$i]===XBEE_ESCAPE){
196  //echo "got escape!!\n";
197  $i++;
198  if($i<strlen($rawData))
199  $res.=pack("C",0x20) ^ $rawData[$i];
200  } else $res.=$rawData[$i];
201  }
202  //echo "Unescape: ".array_pop(unpack('H*',$res))."\n";
203  return $res;
204  }
205 
206 }
207 
208 ?>
const XOFF
Definition: phpXBee.php:25
const XBEE_DELIM
Definition: phpXBee.php:23
$frame
Definition: testPHP.php:14
read($count=0)
Definition: phpXBee.php:86
deviceOpen($mode="r+b")
send($frame, $waitForReply=0)
Definition: phpXBee.php:80
confFlowControl($mode)
confStopBits($length)
$count
Definition: BayEOSWriter.php:8
readPort($count=0)
confBaudRate($rate)
sendMessage($str, $waitForReply=0.1)
const XBEE_ESCAPE
Definition: phpXBee.php:22
Definition: phpXBee.php:26
getFrame($timeout=120)
Definition: phpXBee.php:172
deviceSet($device)
confDefaults($device= '/dev/ttyUSB0')
Definition: phpXBee.php:44
_calcChecksum($data)
Definition: phpXBee.php:160
confCharacterLength($int)
close()
Definition: phpXBee.php:69
open($waitForOpened=0.1)
Definition: phpXBee.php:60
getPANID()
Definition: phpXBee.php:122
confParity($parity)
XBee()
Definition: phpXBee.php:33