BayEOS-PHP
 All Data Structures Namespaces Files Functions Variables Pages
bayeosSerial.php
Go to the documentation of this file.
1 <?php
2 require 'BayEOSSerialPHP.php';
3 
7 define("XBEE_ESCAPE",pack("C",0x7d));
8 define("XBEE_DELIM",pack("C",0x7e));
9 define("XON",pack("C",0x11));
10 define("XOFF",pack("C",0x13));
11 
12 define("API_DATA",pack("C",0x1));
13 define("API_ACK",pack("C",0x2));
14 
15 define("TX_OK",pack("C",0x1));
16 define("TX_CHECKSUM_FAILED",pack("C",0x2));
17 define("TX_BREAK",pack("C",0x3));
18 
19 class BaySerial extends phpSerial {
20  private $stack;
26  function BaySerial() {
27  $this->stack=array();
28  parent::phpSerial();
29  }
30 
37  public function confDefaults($device = '/dev/ttyUSB0') {
38  $this -> deviceSet($device);
39  $this -> confBaudRate(38400);
40  $this -> confParity('none');
41  $this -> confCharacterLength(8);
42  $this -> confStopBits(1);
43  $this -> confFlowControl('none');
44  }
45 
53  public function open($waitForOpened=0.1) {
54  $this -> deviceOpen();
55  usleep((int) ($waitForOpened * 1000000));
56  }
57 
62  public function close() {
63  $this -> deviceClose();
64  }
65 
73  public function send($frame , $api=API_DATA, $timeout=120) {
74  $frame=pack("C",strlen($frame)).$api.$frame.$this->_calcChecksum($api.$frame);
75  $frame=XBEE_DELIM.$this->_escape($frame);
76  //echo "SEND: ".array_pop(unpack('H*',$frame))."\n";
77  $this -> sendMessage($frame, 0);
78 
79  if($api!=API_DATA) return 0;
80 
81  if($res=$this->getFrame($timeout)===FALSE) return 2;
82  //echo 'Send: '.array_pop(unpack('H*',$frame))."\n"; //debug
83  if($res['api']!=API_ACK){
84  $this->sendTXBreak();
85  $this -> sendMessage($frame, 0);
86  }
87  if($res=$this->getFrame($timeout)===FALSE) return 2;
88 
89  if($res['api']===API_ACK){
90  if($res['frame']===TX_OK) return 0;
91  if($res['frame']===TX_CHECKSUM_FAILED) return 1;
92  if($res['frame']===TX_BREAK) return 3;
93  }
94  return 2;
95 
96  }
97 
98  public function read($count = 0){
99  $data = $this -> readPort($count);
100  //if($data) echo 'READ: '.array_pop(unpack('H*',$data))."\n";
101  if(! $data) return count($this->stack);
102  if(! isset($this->stack[0])){
103  $delim_pos=strpos($data,XBEE_DELIM);
104  if($delim_pos===FALSE) return 0;
105  else $data=substr($data,$delim_pos+1);
106  }
107 
108  $data=explode(XBEE_DELIM,$data);
109  $offset=count($this->stack)-1;
110  if($offset==-1) $offset=0;
111  for($i=0;$i<count($data);$i++){
112  $index=$i+$offset;
113  if(! isset($this->stack[$index]['ts']))
114  $this->stack[$index]['ts']=microtime(TRUE);
115  if(! isset($this->stack[$index]['rawframe']))
116  $this->stack[$index]['rawframe']='';
117  $this->stack[$index]['rawframe'].=$data[$i];
118  $this->stack[$index]['frame']=$this->_unescape($this->stack[$index]['rawframe']);
119  //echo "Stack[$index]: ".array_pop(unpack('H*',$this->stack[$index]['frame']))."\n";
120  switch($this->_parseFrame($this->stack[$index]['frame'])){
121  case 0:
122  $this->stack[$index]['ok']=TRUE;
123  break;
124  case 1:
125  unset($this->stack[$index]);
126  fwrite(STDERR,date('Y-m-d H:i:s').' '.$this->_device." : Checksum failure\n");
127  $offset--;
128  break;
129  case 2:
130  $this->stack[$index]['ok']=FALSE;
131  break;
132  }
133  if(isset($this->stack[$index]) && ! $this->stack[$index]['ok'] && ($i+1)<count($data)){
134  unset($this->stack[$index]);
135  $offset--;
136  fwrite(STDERR,date('Y-m-d H:i:s').' '.$this->_device." : Incomplete frame\n");
137  }
138  }
139 
140  $anz=count($this->stack);
141  //echo "Stackcount: $anz\n";
142  if($anz && ! $this->stack[$anz-1]['ok']) $anz--;
143  return $anz;
144  }
145 
146 
147  private function _parseFrame($frame){
148  if(strlen($frame)<3) return 2;
149  //echo "PARSE: ".array_pop(unpack('H*',$frame))."\n";
150  $length = substr($frame, 0, 1);
151  $checksum = substr($frame, -1);
152  $cmdData = substr($frame, 1, -1);
153  $calculatedChecksum = $this -> _calcChecksum($cmdData);
154  $calculatedLength = pack('C',strlen($cmdData)-1);
155 
156  //echo "parseFrame: ".array_pop(unpack('H*',$frame.$calculatedChecksum.$checksum.$calculatedLength.$length))."\n";
157  if ($checksum === $calculatedChecksum && $length === $calculatedLength) {
158  //echo "Frame OK\n";
159  $this->_sendAck(TX_OK);
160  return 0;
161  } else if($length === $calculatedLength) {
162  $this->_sendAck(TX_CHECKSUM_FAILED);
163  return 1;
164  } else {
165  return 2;
166  }
167 
168  }
169 
170  private function _sendAck($type){
171  $this->send($type,API_ACK);
172  }
173 
174  public function sendTXBreak(){
175  $this->_sendAck(TX_BREAK);
176  }
183  protected function _calcChecksum($data) {
184  $checksum = 0;
185  for ($i = 0; $i < strlen($data); $i++) {
186  $checksum += ord($data[$i]);
187  }
188  $checksum = $checksum & 0xFF;
189  $checksum = 0xFF - $checksum;
190  $checksum = chr($checksum);
191  return $checksum;
192  }
193 
194 
195  public function getFrame($timeout=120){
196  while($this->read()==0 && $timeout>0){
197  $timeout-=0.01;
198  usleep(10000);
199  }
200  if($timeout<0) return FALSE;
201 
202  $frame=array_shift($this->stack);
203  $frame['api']=substr($frame['frame'],1,1);
204  $frame['length']=substr($frame['frame'],0,1);
205  $frame['frame']=substr($frame['frame'],2,-1);
206 
207  return $frame;
208  }
209 
210  private function _escape($rawData){
211  $res='';
212  for($i=0;$i<strlen($rawData);$i++){
213  if(in_array($rawData[$i],array(XBEE_ESCAPE,XBEE_DELIM,XOFF,XOFF)))
214  $res.=XBEE_ESCAPE.(pack("C",0x20) ^ $rawData[$i]);
215  else $res.=$rawData[$i];
216  }
217  return $res;
218  }
219 
220  private function _unescape($rawData){
221  //echo "Unescape: ".array_pop(unpack('H*',$rawData))."\n";
222  $res='';
223  for($i=0;$i<strlen($rawData);$i++){
224  if($rawData[$i]===XBEE_ESCAPE){
225  //echo "got escape!!\n";
226  $i++;
227  if($i<strlen($rawData))
228  $res.=pack("C",0x20) ^ $rawData[$i];
229  } else $res.=$rawData[$i];
230  }
231  //echo "Unescape: ".array_pop(unpack('H*',$res))."\n";
232  return $res;
233  }
234 
235 }
236 
237 ?>
getFrame($timeout=120)
const TX_CHECKSUM_FAILED
$frame
Definition: testPHP.php:14
deviceOpen($mode="r+b")
const TX_BREAK
confFlowControl($mode)
confStopBits($length)
$count
Definition: BayEOSWriter.php:8
readPort($count=0)
_calcChecksum($data)
open($waitForOpened=0.1)
read($count=0)
confBaudRate($rate)
sendMessage($str, $waitForReply=0.1)
send($frame, $api=API_DATA, $timeout=120)
const XBEE_DELIM
Definition: bayeosSerial.php:8
const TX_OK
confDefaults($device= '/dev/ttyUSB0')
const XBEE_ESCAPE
Definition: bayeosSerial.php:7
deviceSet($device)
confCharacterLength($int)
const API_DATA
confParity($parity)
const XOFF
const API_ACK