BayEOS-PHP
 All Data Structures Namespaces Files Functions Variables Pages
bayeos-fifo.php
Go to the documentation of this file.
1 #!/usr/bin/php
2 <?php
3 /*
4  * Command line script to read STDOUT and STDERR of
5  * an arbitrary shell script
6  *
7  * tries to parse STDOUT of shell script into timestamp (optional), array of values
8  *
9  *
10  */
11 
12 require_once 'BayEOSGatewayClient.php';
13 
14 /*
15  * Read configuration file and set some defaults
16  */
17 $config=parse_ini_file('/etc/bayeos-fifo.ini');
18 if(! isset($config['names'])){
19  $names=array();
20  for($i=0;$i<count($config['script']);$i++){
21  $names[$i]='Fifo.'.$i; //-> storage path /tmp/qliRouter$i ...
22  }
23 } else $names=$config['names'];
24 $config['writer_sleep_time']=0;
25 
26 //Extend BayEOSGatewayClient Class
28  private $data_fifo;
29  private $error_fifo;
30  private $data;
31  private $error;
32  private $fp_data;
33  private $fp_error;
34  private $pipes;
35  private $delim;
36  private $dec;
37  private $datetime_format;
38  private $tz;
39  private $pid_script;
40  private $origin;
41  private $indexed_frame;
42  private $data_type;
43 
44  protected function readData(){
45  //echo "readData called\n";
46  $timeout=$this->getOption('timeout',120);
47  $name=$this->names[$this->i];
48  while($timeout>0){
49  while(($c=fgetc($this->fp_data))!==FALSE){
50  $this->data.=$c;
51  }
52  while(($c=fgetc($this->fp_error))!==FALSE){
53  $this->error.=$c;
54  }
55 
56  if($pos=strpos($this->error,"\n")){
57  $line=trim(substr($this->error,0,$pos));
58  fwrite(STDERR,date('Y-m-d H:i:s')." $name: $line\n");
59  $this->error=substr($this->error,$pos+1);
60  }
61 
62 
63  if($pos=strpos($this->data,"\n"))
64  break;
65  usleep(10000);
66  $timeout-=.01;
67  }
68  if($timeout<=0) return FALSE;
69  $line=trim(substr($this->data,0,$pos));
70  $this->data=substr($this->data,$pos+1);
71  return $this->parseData($line);
72 
73  }
74 
75  protected function parseData($line){
76  $ts='';
77  $origin='';
78  if($this->origin){
79  $pos=strpos($line,$this->delim);
80  $origin=substr($line,0,$pos);
81  $line=substr($line,$pos+1);
82  }
83  if($this->datetime_format){
84  $pos=strpos($line,$this->delim);
85  $ts=substr($line,0,$pos);
86  $line=substr($line,$pos+1);
87  $ts_obj=DateTime::createFromFormat($this->datetime_format,$ts,new DateTimeZone($this->tz));
88  if(! $ts_obj){
89  fwrite(STDERR, date('Y-m-d H:i:s')." Timestamp parse error: $ts with ".$this->datetime_format."\n");
90  return FALSE;
91  }
92  $ts=floatval($ts_obj->format("U.u"));
93  }
94 
95  if($this->dec!='.') $line=str_replace($this->dec,'.',$line);
96  $tmp=explode($this->delim,trim($line));
97  $data=array();
98  for($i=0;$i<count($tmp);$i++){
99  if($this->indexed_frame){
100  list($key,$value)=explode(':',$tmp[$i]);
101  $key=intval($key);
102  if(! is_numeric($key))
103  fwrite(STDERR, date('Y-m-d H:i:s')."Non numeric key '$key'\n");
104  else
105  $data[$key]=$value;
106  } elseif($this->data_type<65) {
107  $data[$i]=(is_numeric($tmp[$i])?$tmp[$i]:NAN);
108  } elseif(is_numeric($tmp[$i]))
109  $data[$i]=$tmp[$i];
110 
111  }
112  return array('values'=>$data,'ts'=>$ts,'origin'=>$origin);
113  }
114 
115  protected function saveData($data){
116  //save data with timestamp
117  if($data['origin'])
118  $this->writer->saveOriginFrame($data['origin'],
119  BayEOS::createDataFrame($data['values'],$this->data_type,0),
120  $data['ts']);
121  else
122  $this->writer->saveDataFrame($data['values'],$this->data_type,0,$data['ts']);
123  }
124 
125  //private function to recursively find all childs
126  private function termChilds($pid){
127  exec("pgrep -P $pid",$res);
128  if(isset($res[0])) $this->termChilds($res[0]);
129  posix_kill($pid,SIGTERM);
130  $res2=pcntl_waitpid($pid,$status);
131 
132  echo date('Y-m-d H:i:s')." Terminated ".($pid==$this->pid_script?"sript":"child of").' '.$this->getOption('script').
133  " of ".$this->name." with pid ".$pid."\n";
134  }
135 
136  protected function initWriter(){
137  $name=$this->names[$this->i];
138 
139  $fifo=$this->options['tmp_dir'].'/'.str_replace(array('/','\\','"','\''),'_',$name);
140 
141  $this->data_fifo=$fifo.'.data.fifo';
142  posix_mkfifo($this->data_fifo,$this->getOption('data_fifo_mode',0600));
143  if(! is_writable($this->data_fifo))
144  die("Failed to create $fifo.data_fifo\n");
145  $this->error_fifo=$fifo.'.error.fifo';
146  posix_mkfifo($this->error_fifo,$this->getOption('error_fifo_mode',0600));
147  if(! is_writable($this->error_fifo))
148  die("Failed to create $fifo.error_fifo\n");
149 
150  $script=$this->getOption('script');
151  $tmp=explode(" ",$script);
152  if(! (is_executable($script) || is_executable($tmp[0])))
153  die("$script is not executable\n");
154 
155  //Start the script
156  $pid=pcntl_fork();
157  if ($pid == -1) {
158  die('Could not fork reader process!');
159  } else if ($pid) {
160  // We are the parent
161  //Signalhanlder to stop the script on SIGTERM
162  $this->pid_script=$pid;
163  declare(ticks = 1);
164  pcntl_signal(SIGTERM, function($signo) {
165  switch ($signo) {
166  case SIGTERM:
167  // Aufgaben zum Beenden bearbeiten
168  $this->termChilds($this->pid_script);
169  echo date('Y-m-d H:i:s')." Script ".$this->getOption('script')." for ".$this->name." with pid ".$this->pid_script." terminated.\n";
170  exit();
171  break;
172  }
173 
174  });
175 
176 
177  $this->fp_data=fopen($this->data_fifo,'r');
178  $this->fp_error=fopen($this->error_fifo,'r');
179  stream_set_blocking($this->fp_data, false);
180  stream_set_blocking($this->fp_error, false);
181  echo date('Y-m-d H:i:s')." Started script $script for $name with pid $pid\n";
182  $this->delim=$this->getOption('delim');
183  if($this->delim=='\t') $this->delim="\t";
184  $this->dec=$this->getOption('dec');
185  $this->tz=$this->getOption('tz');
186  $this->datetime_format=$this->getOption('datetime_format');
187  $this->origin=$this->getOption('origin');
188  $this->indexed_frame=$this->getOption('indexed_frame');
189  $this->data_type=intval($this->getOption('data_type'),0);
190  if($this->indexed_frame && $this->data_type<64){
191  echo date('Y-m-d H:i:s')." Notice: data_type ".$this->data_type.
192  " does not support indexed frames. Will use ".(($this->data_type&0xf)|0x40)." instead\n";
193  $this->data_type=($this->data_type&0xf)|0x40;
194  }
195 
196  } else {
197  // We are child:
198  exec("$script >".$this->data_fifo." 2>".$this->error_fifo." </dev/null");
199  exit();
200  }
201 
202  }
203 
204 }
205 
206 
207 
208 
210  array('data_type'=>0x1,
211  'delim'=>' ',
212  'dec'=>'.',
213  'origin'=>FALSE,
214  'indexed_frame'=>FALSE,
215  'tz'=>date_default_timezone_get()));
216 $my_client->run();
217 
218 
219 
220 
221 
222 
223 ?>
static createDataFrame($values, $type=0x1, $offset=0)
parseData($line)
Definition: bayeos-fifo.php:75
if(!isset($config['names'])) else $names
Definition: bayeos-fifo.php:23
saveData($data)
getOption($key, $default='')
$pos
Definition: dumpCat.php:12
$config
Definition: bayeos-fifo.php:17
$my_client