· 4 years ago · Mar 19, 2021, 06:46 PM
1#!/bin/bash
2#THIS DRIVER WRITTEN BY MATTHEW VONA ARB FOR THE API 400 E
3#FOR QUESTIONS WRITE mailto:mvona@arb.ca.gov
4#-------------------------------------------------------------
5# THIS IS THE FUNCTION CALLED IN THE EVENT THAT CTRL+C IS PRESSED
6#DIR returns operating directory of the testd script
7port=8002
8#colocation=0
9DIR="$( cd -P "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
10while read line; do
11 eval $line
12done < Config/config
13has_run=0
14if [ -z $no_plots ]; then
15 bash ${DIR}/plotter.sh 1>/dev/null 2>/dev/null &
16 plotterid="$!"
17 bash ${DIR}/correlation.sh 1>/dev/null 2>/dev/null &
18 coreid="$!"
19 echo "$plotterid"
20fi
21
22
23function get_data () {
24 HOST="${1}"
25 data=`( echo open "${HOST} ${2}"
26 sleep 2
27 echo '$AE33:D001'
28 #sleep 2
29 #echo '$AE33:SG'
30 #echo "T LIST ALL"
31 sleep 2
32 echo "exit" ) | telnet 2>/dev/null`
33
34 echo "${data}" | grep '20[0-9]*/[0-9][0-9]/[0-9][0-9]' | sed 's/AE33>//g' | while read -r Date Time Timebase RefCh1 Sen1Ch1 Sen2Ch1 RefCh2 Sen1Ch2 Sen2Ch2 RefCh3 Sen1Ch3 Sen2Ch3 RefCh4 Sen1Ch4 Sen2Ch4 RefCh5 Sen1Ch5 Sen2Ch5 RefCh6 Sen1Ch6 Sen2Ch6 RefCh7 Sen1Ch7 Sen2Ch7 Flow1 Flow2 FlowC Pressure Temperature BB ContTemp SupplyTemp Status ContStatus DetectStatus LedStatus ValveStatus LedTemp BC11 BC12 BC1 BC21 BC22 BC2 BC31 BC32 BC3 BC41 BC42 BC4 BC51 BC52 BC5 BC61 BC62 BC6 BC71 BC72 BC7 K1 K2 K3 K4 K5 K6 K7 TapeAdvCount ID_com1 ID_com2 ID_com3 fields_i;
35 do
36 {
37 echo "AE33_${colocation}_Date=${Date} AE33_${colocation}_Time=${Time} AE33_${colocation}_Timebase=${Timebase} AE33_${colocation}_RefCh1=${RefCh1} AE33_${colocation}_Sen1Ch1=$Sen1Ch1 AE33_${colocation}_Sen2Ch1=$Sen2Ch1 "
38 echo "AE33_${colocation}_RefCh2=${RefCh2} AE33_${colocation}_Sen1Ch2=$Sen1Ch2 AE33_${colocation}_Sen2Ch2=$Sen2Ch2 AE33_${colocation}_RefCh3=$RefCh3 AE33_${colocation}_Sen1Ch3=$Sen1Ch3 AE33_${colocation}_Sen2Ch3=$Sen2Ch3 AE33_${colocation}_RefCh4=$RefCh4 AE33_${colocation}_Sen1Ch4=$Sen1Ch4 "
39 echo "AE33_${colocation}_Sen2Ch4=$Sen2Ch4 AE33_${colocation}_RefCh5=$RefCh5 AE33_${colocation}_Sen1Ch5=$Sen1Ch5 AE33_${colocation}_Sen2Ch5=$Sen2Ch5 AE33_${colocation}_RefCh6=$RefCh6 AE33_${colocation}_Sen1Ch6=$Sen1Ch6 AE33_${colocation}_Sen2Ch6=$Sen2Ch6 AE33_${colocation}_RefCh7=$RefCh7 "
40 echo "AE33_${colocation}_Sen1Ch7=$Sen1Ch7 AE33_${colocation}_Sen2Ch7=$Sen2Ch7 AE33_${colocation}_Flow1=$Flow1 AE33_${colocation}_Flow2=$Flow2 AE33_${colocation}_FlowC=$FlowC AE33_${colocation}_Pressure=$Pressure AE33_${colocation}_Temperature=$Temperature AE33_${colocation}_BB=${BB} "
41 echo "AE33_${colocation}_ContTemp=$ContTemp AE33_${colocation}_SupplyTemp=$SupplyTemp AE33_${colocation}_Status=$Status AE33_${colocation}_ContStatus=${ContStatus} AE33_${colocation}_DetectStatus=${DetectStatus} "
42 echo "AE33_${colocation}_LedStatus=$LedStatus AE33_${colocation}_ValveStatus=$ValveStatus AE33_${colocation}_LedTemp=$LedTemp AE33_${colocation}_BC11=$BC11 AE33_${colocation}_BC12=$BC12 AE33_${colocation}_BC_ONE=$BC1 AE33_${colocation}_BC21=$BC21 AE33_${colocation}_BC22=$BC22 "
43 echo "AE33_${colocation}_BC_TWO=$BC2 AE33_${colocation}_BC31=$BC31 AE33_${colocation}_BC32=$BC32 AE33_${colocation}_BC_THREE=$BC3 AE33_${colocation}_BC41=$BC41 AE33_${colocation}_BC42=$BC42 AE33_${colocation}_BC_FOUR=$BC4 AE33_${colocation}_BC51=$BC51 AE33_${colocation}_BC52=$BC52 AE33_${colocation}_BC_FIVE=$BC5 "
44 echo "AE33_${colocation}_BC61=$BC61 AE33_${colocation}_BC62=$BC62 AE33_${colocation}_BC_SIX=$BC6 AE33_${colocation}_BC71=$BC71 AE33_${colocation}_BC72=$BC72 AE33_${colocation}_BC_SEVEN=$BC7 AE33_${colocation}_K1=$K1 AE33_${colocation}_K2=$K2 AE33_${colocation}_K3=$K3 AE33_${colocation}_K4=$K4 AE33_${colocation}_K5=$K5 AE33_${colocation}_K6=$K6 AE33_${colocation}_K7=$K7 "
45 echo "AE33_${colocation}_TapeAdvCount=${TapeAdvCount} AE33_${colocation}_ID_com1=${ID_com1:+-999} AE33_${colocation}_ID_com2=${ID_com2:+-999} AE33_${colocation}_ID_com3=${ID_com3:+-999} AE33_${colocation}_fields_i=${fields_i:+-999} "
46 }
47 done
48}
49############################################
50# AUTO BACKFILL CODE : NOT USED HERE #
51############################################
52#TOLERANCE (MINUTES ACCEPTABLE BEFORE BACK FILL)
53#NOT USED HERE
54tolerance=5
55#THIS SECTION DETERMINES THE LAST TIME THAT THE CARBLOGGER WRITE PROCESS TOUCHED the .last_stamp file
56#AFTER CONVERTING TO MINUTES, IT REQUESTS THIS NUMBER OF RECORDS FROM THE APIT400
57function back_calc ()
58 {
59 #SECONDS SINCE 1970
60 current_time=`date "+%s"`
61 #SECONDS SINCE 1970 AT LAST DRIVER WRITE
62 last_accessed=`stat -c %X ${DIR}/.last_samp`
63 #CALCULATE THE NUMBER OF MINUTE RECORDS TO RETRIEVE
64 records=`echo "(${current_time} - ${last_accessed})/60" | bc`
65 #ROUND
66 records=`printf "%.0f" ${records}`
67 [[ $records -gt $tolerance ]] && back_fill "${1}" "${records}" "${3}"
68
69 }
70
71
72
73function back_fill ()
74 {
75 rm ${DIR}/.dbase_load
76 HOST="${dvc_prt}"
77 this_name=${rprt_nm}
78 (echo open "${HOST} $AE33:D001"
79 sleep 5
80 echo "D 400 REPORT \"CONC\" RECORDS=${2}"
81 sleep 5
82 echo "exit") | telnet >"${DIR}/.dump_file"
83
84 cat "${DIR}/.dump_file" | grep -e "[0-9]*:[0-9]*:[0-9]*" | while read A B C D E F G
85 do
86 F=`echo $F | sed 's/CONC1/O3/g'`
87 ts_day=`echo $B | awk '{ split($0,a,":"); print a[1] + 0 }'`
88 #echo "TSDAY: $ts_day "
89 ts_hour=`echo $B | awk '{ split($0,a,":"); print a[2] }'`
90 #echo "TSHOUR: ${ts_hour}"
91 ts_minute=`echo $B | awk '{ split($0,a,":"); print a[3] }'`
92 #echo "TSMINUTE: ${ts_minute}"
93 ts_year=`date "+%Y"`
94 #echo "TSYEAR: ${ts_year}"
95 #FILE WRITE FORMAT
96 y="${ts_year}"; n=$((${ts_day}-1));
97 date_string=`date -d "01/01/${y} + ${n} days" "+%m-%d-%Y"`
98 #date_string=$(date -d "${ts_year}-01-01 +$(( ${ts_day} - 1 ))days" "+%m-%d-%Y")
99 #echo "DATE_STRING: ${date_string}"
100 #FILE IDENTIFIER
101 file_id=`date -d "01/01/${y} + $n days" "+%Y-%d-%m"`
102 echo "FILE_ID: 00000-${file_id}"
103 echo "${this_name}::${date_string}_${ts_hour}:${ts_minute}::: *BACKFILL* ${F}" | sed 's/XXXX/-999/g'>>"Data/${saroad}-${file_id}"
104 ingest_string=`date -d "01/01/${y} + ${n} days" "+%Y-%m-%d" | tr -d "\n" && echo -n " ${ts_hour}:${ts_minute}"`
105 ingest_value=`echo -n ${F} | sed 's/O3=//g'`
106 #insert_statement='insert into carblogger.cl_ingests(parameter, value, LOG_TIME) values("'O3='","'${ingest_value}'","'${ingest_string}'");'
107 echo "'O3','${ingest_value}','0','${ingest_string}','O3='" | sed 's/XXXX/-999/g' >>${DIR}/.dbase_load
108
109 #echo "${insert_statement}" | mysql -u root --password=carblogger -A carblogger
110 done
111
112 mysql -u root --password=carblogger -h 127.0.0.1 -D carblogger -e "LOAD DATA LOCAL INFILE \"${DIR}/.dbase_load\" INTO TABLE cl_ingests FIELDS TERMINATED BY ',' ENCLOSED BY '\'' LINES TERMINATED BY '\n' (parameter,value,is_offline,LOG_TIME,data_label) SET updated = NOW(), COMMENT = \"BACKFILL\", SAMP_TIME = NULL;"
113}
114#REBOOT THE APIT400
115
116function reboot_inst ()
117 {
118 HOST="${dvc_prt}"
119 (echo open "${HOST} ${port}"
120 sleep 2
121 echo "exit") | telnet
122
123 }
124
125function set_time ()
126 {
127 my_time=`date '+%H:%M'`
128 my_date=`date '+%m/%d/%Y'`
129 HOST="${dvc_prt}"
130 (echo open "${HOST} ${port}"
131 sleep 2
132 echo "V 400 CURR_TIME=${my_time}"
133 sleep 2
134 echo "V 400 CURR_DATE=${my_date}"
135 sleep 2
136 echo "exit") | telnet
137 }
138
139
140cleanup()
141{
142 echo "Caught Signal ... cleaning up."
143 if !(rm -f Data/.locked > /dev/null); then
144 exit 1
145 fi
146 for i in `pgrep -P ${plotterid}`; do
147 kill -9 ${i}
148 done
149 kill -9 ${plotterid}
150 for i in `pgrep -P ${coreid}`; do
151 kill -9 ${i}
152 done
153 kill -9 ${coreid}
154
155
156
157 echo "Done cleanup ... quitting."
158 exit 0
159}
160
161#THE DIAGNOSTIC DATA (DIAG) ROUTINE TAKES THE DATA STREAM FROM THE API 400E
162#AND TESTS FOR THE RECOGNITION OF KEY WORDS IN EACH LINE OF OUTPUT.
163#IF THE KEY WORD IS DETECTED ON THAT LINE, A TEST IS PERFORMED.
164#IF THE TEST SUGGESTS THAT AN ERROR CONDITION EXISTS BASED UPON THE ALLOWABLE
165#RANGES SPECIFIED BY THE ARB CHECKSHEET, THE OFFENDING LINE IS WRITTEN OUT
166#TO A FILE IN THE Data DIRECTORY. THE NAME OF THE DESTINATION FILE IS
167#errors{HH}. THE FILES CAN THEN BE PARSED AND UTILIZED BY ANY ALERT PROGRAM?DAEMON.
168diag()
169{
170 this_name=$(cat ${DIR}/.usr$instance | grep -o "\-r [A-Za-z0-9]*" | awk '{ print $2 }')
171 thishour=`date "+%H"`
172 flow_tag="AE33_${colocation}_Flow1="
173 thisalert="errors$thishour"
174 while read DIAGS
175 do
176 awk -v flow_tag=${flow_tag} -v low_flow=${low_flow} -v upp_flow=${upp_flow} -v izs=${izs} -v name=${this_name} '
177
178{
179
180 # TEST THE FLOW RATE
181 if ($4 ~ /flow_tag/ )
182 {
183 if ((substr($4,12)+0)<=low_flow)
184 { print name " FLOW IS VERY LOW" $4 " is less than " low_flow" "$0 }
185 if ((substr($4,12)+0)>=upp_flow)
186 { print name " FLOW IS VERY HIGH" $4 " is greater than " upp_flow" "$0}
187 if (substr($4,12) ~ /XXXX/)
188 { print name " FLOW IS TOO LOW" $0 }
189 }
190
191}' >> "Data/$thisalert"
192done
193}
194#BEGIN WRITE
195#THIS FUNCTION HANDELS READ RIGHT HANDSHAKES BETWEEN VARIOUS DRIVERS
196#IN GENERAL, THE DATA IS PLACED IN THE VARIABLE $TIMESTAMP PRIOR TO CALL
197#NEXT, IT OPENS THE DATA DIRECTORY AND LOOKS FOR THE .locked FILE
198#IF IT EXISTS, IT HANGS OUT UNTIL IT DOESN'T EXIST. AT THAT POINT
199#IT CREATES A .locked FILE, AND APPENDS TO THE DATA RECORD.
200#FINALLY IT REMOVES THE .locked FILE IT HAS CREATED.
201#THIS FUNCTION ALSO PARSES THE .DISABLED FILE IN THE DRIVER FOLDER
202#AND TAKES A CHANNEL OFF LINE BY PREPENDING --DISABLED-- TO EACH LINE OF CONTENT IN THE DATA DIRECTORY
203#written by MJV
204write()
205{
206#CONFIRM THAT THERE IS NO HIDDEN FILE CALLED '.locked'
207 while [ -e "Data/.locked" ];
208 do
209 sleep .2;
210 done
211 echo "LOCKED" > "Data/.locked";
212 #PARSE THE .disabled File
213 channel_status=`cat "${DIR}/.disabled${instance}"`
214 #IF WE HAVE JUST STARTED THE DRIVER, CHECK TO SEE IF WE SHOULD BACKFILL
215
216
217 #IF THE FILE DOSEN'T EXIT OR IS NOT ACCESIBLE
218 #MAKES SURE A VALUE OF 0 IS USED
219 if [ `expr $channel_status + 0` -eq 1 ]; then
220 if !(echo "$data" | sed 's/^/'$timestamp'/g'| sed 's/BOX TEMP=/O3BOXTEMP=/g' | sed 's/$/'\-\-OFFLINE\-\-'/g'| tee -a "Data/$datafile" && touch ${DIR}/.last_samp && has_run=1 ); then
221 {
222 echo "GENERAL FAILURE WRITING TO RECORD: $#";
223 cleanup;
224 }
225 fi
226 else
227 if !(echo "$data" | sed 's/^/'$timestamp'/g'| sed 's/BOX TEMP=/O3BOXTEMP=/g' | tee -a "Data/$datafile" && touch ${DIR}/.last_samp && has_run=1); then
228 {
229 echo "GENERAL FAILURE WRITING TO RECORD: $#";
230 cleanup;
231 }
232 fi
233
234 fi
235 if !(rm -f "Data/.locked" > /dev/null); then
236 {
237 echo "GENERAL FAILURE REMOVING LOCK: $#";
238 exit 1;
239 }
240 fi
241 if !(timestamp="" && data=""); then
242 {
243 echo "GENERAL FAILURE CLEARING WRITE BUFFER: $#";
244 cleanup;
245 }
246 fi
247}
248
249#THIS IS THE ACTUAL COMMUNICATION WITH THE INSTRUMENT
250#THE TIMER CONTROL. AT THE BEGINING IT TESTS FOR THE
251#EXISTENCE IF TOGGLE VARRIABLES WHICH ARE UTILIZED BOTH BY
252#THE COMM ROUTINE runit() AND THE DIAGNOSTICS DATA ROUTINE
253#diag()
254runit()
255{
256#Date stamp
257today=`date "+%Y-%d-%m"`
258timestamp=$rprt_nm::`date "+%m-%d-%Y_%H:%M"`:::
259#THIS IS THE NAME OF THE DATA FILE RIGHT NOW
260datafile="$saroad-$today"
261#TALK TO THE INSTRUMENT, PRE-APPEND THE TIMESTAMP AND REPORTING NAME TO EACH
262#LINE OF OUTPUT AND tee TO THE DATA FILE, then pass to the diag routine.
263data=`get_data ${dvc_prt} ${port} | grep -v "^$"`
264write
265}
266#THIS IS THE FUNCTION RUN IN THE EVENT THAT THE REQUIRED PARAMETERS
267#ARE NOT ENTERED.
268usage()
269{
270clear
271cat << EOF
272usage: $0 options
273OPTIONS:
274-h display help
275-n the device identifier
276-r rprt_nm [rn]
277-o occurrence code
278-d dvc_prt [eg, 192.168.0.40]
279-c cmnd1 (e.g, LIST ALL\r ***DO NOT USE T LIST ALL***)
280-w wt_rsp1 [seconds]
281-l rsp_lngth [characters]
282-s SAROAD number of the station
283-U Uppler flow limit alert (OPTIONAL)
284-L Lower flow limit alert (OPTIONAL)
285Last updated 7/28/2009
286EOF
287}
288#HELP FUNCTION GIVES BACKGROUND ON THIS DRIVER
289help_me ()
290 {
291 clear
292 cat .help
293 exit 0
294 }
295def_opts ()
296 {
297 clear
298 cat .options
299 }
300
301##CLEAR ALL VARIABLES
302rprt_nm= ; dvc_prt= ; bd_rt= ; cmnd1= ; wt_rsp= ; rsp_lngth= ; izs_val= ;
303dvc_prt= ; frqncy= ; dtr= ; ctr= ; p8n1= ; izs= ; saroad= ; p8n1= ; id_nmbr= ;
304upp_flow=880 ; low_flow=550 ; instance=1; occurrence=0
305##INITIALIZE THE BUFFER
306return='NOT WRITTEN TO'
307##loop through all variables and parameters
308##Note that the position of the colon indicates the presence
309##of a parameter to collect. The h parameter simply
310##returns the help message.
311
312while getopts “hn:r:o:s:d:w:l:t:C:U:L:I:” OPTION
313do
314 case $OPTION in
315 U)
316 upp_flow=$OPTARG
317 ;;
318 L)
319 low_flow=$OPTARG
320 #PER R SMITH; SETTING LOW FLOW ALERT TO 550
321 #GLOBALLY. THIS WILL OVERWRITE ANY VALUE THE
322 #END USER CONFIGURES ON THEIR CARBLOGGER
323 #MENU.
324 low_flow=550
325 ;;
326 I)
327 instance=$OPTARG
328 ;;
329 s)
330 saroad=$OPTARG
331 ;;
332 r)
333 rprt_nm=$OPTARG
334 ;;
335 o)
336 colocation=$OPTARG
337 ;;
338 d)
339 dvc_prt=$OPTARG
340 ;;
341 w)
342 wt_rsp=$OPTARG
343 ;;
344 l)
345 rsp_lngth=$OPTARG
346 ;;
347 t)
348 dtr_val=$OPTARG
349 ;;
350 C)
351 ctr_val=$OPTARG
352 ;;
353 h)
354 help_me
355 exit 1
356 ;;
357 *)
358 usage
359 exit 1
360 ;;
361 esac
362done
363#CHECK FOR THE CRITICAL PARAMETERS, IF THEY ARE NOT PRESENT THEN
364#RUN THE USAGE FUNCTION WHICH RETURNS THE INSTRUCTIONS FOR PROPER USAGE
365#MUST HAVE r n d c w l i s
366if [ -z "$rprt_nm" ] || [ -z "$dvc_prt" ] || [ -z "$wt_rsp" ] || [ -z "$saroad" ] || [ -z "$colocation" ]
367then
368 {
369 usage
370 exit
371 }
372fi
373#back_calc "${dvc_prt}" "${saroad}" "${rprt_nm}"
374#back_calc "${dvc_prt}" "${saroad}" && exit
375 #INITIALIZED THE RAN VARIABLE. THIS IS USED TO TOGGLE THE TIMER GATE
376ran=0
377 #TRAP CTRL+C
378trap cleanup 1 2 3 6 15
379 #SETUP THE OPERATING LOOP
380 while :
381 do
382 day=$(date "+%d")
383 second=$(date "+%S")
384 minute=$(date "+%M")
385 hour=$(date "+%H")
386 if [ "$second" -eq "00" ] && [ "$ran" -eq "0" ]; then
387 {
388 #RUN THE RUNIT FUNCTION
389 runit
390 #TOGGLE THE RAN VARIABLE SO THAT THE PROCESS WILL NOT REPEAT
391 #UNTIL THE BEGINNING OF THE NEXT MINUTE.
392 ran=1
393 #WAIT FOR COMPLETION OF THE RUNIT FUNCTION AND THE VARIABLE
394 #SET
395 sleep 1
396 }
397 #AND WAIT ONE SECOND BEFORE CHECKING AGAIN
398 elif [ "$hour" -eq "00" ] && [ -z $time_set_run ] && [ "$minute" -eq "05" ]; then
399 {
400 #set_time
401 #time_set_run=1
402 sleep 60
403 }
404 elif [ "$hour" -eq "01" ] && [ "$minute" -eq "01" ] && [[ "$day" -eq "01" || "$day" -eq "15" ]] ; then
405 {
406 #reboot_inst
407 sleep 50
408 }
409 else
410 {
411 #WAIT ONE SECOND
412 sleep .5
413 #SET RAN TO 0
414 ran=0
415 #UNSET TIME_SET_RAN
416 #unset time_set_run
417 }
418 fi
419 done;
420exit;