;+
; Project     : SOHO - CDS     
;                   
; Name        : EMON_RELAYS_LOG
;               
; Purpose     : Updates the history of any CDS relay use.
;               
; Explanation : Checks the telemetry files for changes in state of any of the
;               CDS relays. The history of relay changes is kept in a SAVE
;               file as a structure array.  Each structure element
;               has the tags PAR, TIME, STATE and DESC.  When that
;               structure is recalled (see GT_RELAYS_HIST) then users can
;               select data of interest as required.
;
;               This program requires write access to the directory 
;               $CDS_ENG_DATA_W and should only be used by operations 
;               personnel.  It is anticipated that this procedure will be
;               run on a daily base by the operations staff. Anyone just 
;               wanting to analyse relay use should recall the saved data 
;               structure by using procedure GT_RELAYS_HIST (qv).  
;               Use of that procedure only requires read access to the 
;               $CDS_ENG_DATA directory.
;               
; Use         : IDL> emon_relays_log,/all_cdrom     
;                            would check all tm files in $CDS_CDROM_DATA
;
;
;
;    
; Inputs      : None
;               
; Opt. Inputs : DOY   - day of year for file name.  Only one day at a time is
;                       allowed.
;
;         
;               
; Outputs     : SAVEd structure array in $CDS_ENG_DATA_W/relays_log save 
;               file is updated.
;               
; Opt. Outputs: None.
;
;               
; Keywords    : RELAY_DATA  - strarr giving times and raw data read
;               RECORD      - records the relay states with times of changes
;               QUIET       - if present, information is not written to screen
;               ALL_CDROM   - use all tm files in $CDS_CDROM_DATA
;               STATUS      - set to 0/1 on exit for error/success
;
; Calls       :
;
; Common      : Needs EMON_ERR.COM
;               
; Restrictions: Input telemetry files are assumed to be in $CDS_CDROM_DATA 
;               directory (first) and then looked for in $CDS_TM_DATA unless
;               the ALL_CDROM keyword is set. $CDS_ENG_DATA_W must be defined.
;
;               See also note on use under "Explanation" section above.
;               
; Side effects: None
;               
; Category    : Telemetry, engineering
;               
; Prev. Hist. : None
;
; Written     : C D Pike, RAL, 22-Aug-95
;               
; Modified    : Updated name of evar used.                 CDP, 20-Oct-95
;               Changed evar name to CDS_ENG_DATA_W.       CDP, 23-Oct-95
;               Fix bug when nothing found.                CDP, 28-Nov-95
;               Rework to speed things up.                 CDP, 10-Apr-96
;               Rework file input to match EMON_MECH_LOG.  CDP, 11-Apr-96
;               Increase storage to cope with 10 days and
;               cut duplicates.                            CDP, 12-Apr-96
;               Limit array to 10 days @ 8 secs telm.      CDP, 15-Apr-96
;		Version 9, William Thompson, GSFC, 17-Apr-1996
;			Call itself recursively when used with /ALL_CDROM
;               Temporary patch for testing.  CDP, 18-Apr-96
;               Fix bug when only one new entry.  CDP, 7-May-96
;               Trap when no TM files to process.  CDP, 15-Apr-97
;               Fix potential integer  round off bug.  CDP, 14-May-97
;
; Version     : Version 13, 14-May-97
;-            

pro emon_relays_log, file, relay_data=relay_data, record=record, quiet=quiet,$
                           all_cdrom=all_cdrom, status=status

;
;  common for variables
;
@emon_err.com

;
;  before do any work, check env. var. is set for storage
;
ev = getenv('CDS_ENG_DATA_W')
if ev eq '' then begin
   if not keyword_set(quiet) then begin
      print,'Environment variable CDS_ENG_DATA_W is not defined.'
   endif
   status = 0
   return
endif

;
;  input can be
;               none (+ ALL_CDROM keyword) - use all files in $CDS_CDROM_DATA 
;               doy    (specific day of year number, all files)
;               CDS  UTC structure (use all files from that day)
;               CDS  date string (use all files from it)
;               Specific file name (use only it)
;

if n_params() eq 0  then begin
   if keyword_set(all_cdrom) then begin
      ff = findfile(concat_dir('$CDS_CDROM_DATA','tm.*'),count=count)
      if count eq 0 then begin
         if not keyword_set(quiet) then begin
            print,'No telemetry files found in CDS_CDROM_DATA '
         endif
         status = 0
         return
      endif
;
;  Determine all the dates from the filenames.  Process the dates recursively,
;  and return.
;
      break_file,ff,disk,dir,name,ext
      date = strmid(ext,1,2) + '-' + strmid(ext,4,3)
      date = date(uniq(date))
      for i = 0,n_elements(date)-1 do begin
         emon_relays_log, date(i), quiet=quiet, status=status
;         emon_relays_log, date(i), relay_data=rd, record=rc, quiet=quiet, $
;		status=status
;         if status eq 0 then return
;         if i eq 0 then begin
;            relay_data = rd
;            record = rc
;         end else begin
;            relay_data = [[relay_data], [rd]]
;            record = [[record], [rc]]
;         endelse
      endfor
      return
   endif else begin
      if not keyword_set(quiet) then begin
         print,'USE: emon_relays_log, DOY or CDS date or tm file name or none+keyword.'
      endif
      status = 0
      return
   endelse
endif else begin


;
;  DOY specified
;

   if datatype(file(0),1) eq 'Integer' or datatype(file(0),1) eq 'Long' then begin
      cdoy = strmid(string(file+1000,form='(i4)'),1,3)
      date = anytim2cal(doy2utc(file))
      year = strmid(date,7,2)
      ff = findfile(concat_dir('$CDS_CDROM_DATA',$
                    'tm.'+year+'_'+cdoy+'*'),count=count)
      if count eq 0 then ff = findfile(concat_dir('$CDS_TM_DATA',$
                                       'tm.'+year+'_'+cdoy+'*'),count=count)
      if count eq 0 then begin
         print,'No telemetry files found for DOY ',file
         status = 0
         return
      endif
   endif

;
;  CDS UTC structure
;
   if datatype(file(0),1) eq 'Structure' then begin
      date = anytim2cal(file)
      doy = utc2doy(file)
      cdoy = strmid(string(file+1000,form='(i4)'),1,3)
      year = strmid(date,7,2)
      ff = findfile(concat_dir('$CDS_CDROM_DATA',$
                    'tm.'+year+'_'+cdoy+'*'),count=count)
      if count eq 0 then ff = findfile(concat_dir('$CDS_TM_DATA',$
                                       'tm.'+year+'_'+cdoy+'*'),count=count)
      if count eq 0 then begin
         print,'No telemetry files found for UTC ',file
         status = 0
         return
      endif
   endif
   

                   
;
;  CDS date/time string or telemetry file name (check for directory already
;  being there)
;
   if datatype(file(0),1) eq 'String' then begin
      break_file, file, disk, direct, f, ext
      if direct(0) eq '' then begin
          if strmid(file(0),0,2) ne 'tm' then begin
             date = anytim2cal(file)
             doy = utc2doy(str2utc(file))
             cdoy = strmid(string(doy+1000,form='(i4)'),1,3)
             year = strmid(date,7,2)
             ff = findfile(concat_dir('$CDS_CDROM_DATA',$
                           'tm.'+year+'_'+cdoy+'*'),count=count)
             if count eq 0 then ff = findfile(concat_dir('$CDS_TM_DATA',$
                                     'tm.'+year+'_'+cdoy+'*'),count=count)
             if count eq 0 then begin
                print,'No telemetry files found for date ',file
                status = 0
                return
             endif
          endif else begin
             for i=0,n_elements(file)-1 do begin
                 if i eq 0 then begin
                    ff = findfile(concat_dir('$CDS_CDROM_DATA',$
                                  file(0)+'*'),count=count)
                    if count eq 0 then ff = findfile(concat_dir('$CDS_TM_DATA',$
                                                     file(0)+'*'),count=count)
                 endif else begin
                    ff = [ff,findfile(concat_dir('$CDS_CDROM_DATA',$
                                  file(i)+'*'),count=count)]
                    if count eq 0 then ff = [ff,findfile(concat_dir('$CDS_TM_DATA',$
                                             file(i)+'*'),count=count)]
                 endelse
             endfor
             if count eq 0 then begin
                print,'No telemetry files of that name found.',file
                status = 0
                return
             endif
          endelse
      endif else begin
          ff = file
      endelse
   endif

endelse

;
;  try and make sure no funnies got through
;
break_file,ff,disk,dir,f,ext
n = where(strlen(ext) eq 10,count)
if count gt 0 then begin
   ff = ff(n)
endif else begin
   print,'No valid files found.'
   status = 0
   return
endelse

;
;  for info 
;
if not keyword_set(quiet) then begin
   print,'Using data files.....'
   print_str,ff
endif


;
;  read details of the parameters
;
get_mask_etc, mask



;
;  We require those parameters that can indicate relay status.
;  Note that items 8 and 11 (A_POS_EG12V and A_POS_EM12V) are voltage 
;  readings which are used in lieu of a relay status. ASEFILS has calibrated
;  values of FIL1 or FIL2, all the others are OFF or ON.
;

pname = ['ASEGHV1',$
         'ASEGHV2',$
         'ASEGHV3',$
         'ASEGHV4',$
         'ASECOMP',$
         'ASEFIL',$
         'ASEFILS',$
         'ASEG5V',$
         'A+EG12V',$
         'ASEHTRS',$
         'ASEM5V',$
         'A+EM12V',$
         'ASEVSBY',$
         'ASEVDS',$
         'ASEVHV',$
         'ASEVHTR']

;
;  load supplementary data for these names only
;
emask = strarr(18,n_elements(pname))
for i=0,n_elements(pname)-1 do begin
   n = where(mask(0,*) eq pname(i))
   if n(0) ge 0 then emask(*,i) = mask(*,n(0))
endfor

;
;  now rename the +/- ones for tm_calib
;
pname(8)  = 'A_POS_EG12V'       
pname(11) = 'A_POS_EM12V'       


;
;  these are the ones for which data value 1 means 'ON'
;
n0 = where(emask(10,*) eq 'ON')

;
;  these are the ones for which data value means 'FIL1' or 'FIL2'
;
n1 = where(emask(10,*) eq 'FIL1')

;
;  these are the ones for which data value is calibrated numerically
;
n2 = where(emask(10,*) eq '0')


;
;  initialise the variables
;
packet_no = -1L
engcount = 0L
packet   = bytarr(306)

;
;  accumulation array (allow for 1 complete day @ 2 sec intervals)
;
relay_data = strarr(n_elements(pname)+1,45000)



;
;  loop on the TM files found
;
for kk=0L,n_elements(ff)-1 do begin
   openr, eng_lun, ff(kk), /get_lun, error=err
   if err ne 0 then begin
      bell
      print,'Error opening data file ', ff(kk)
      status = 0
      return
   endif
   
   if not keyword_set(quiet) then print,'Reading data file ', ff(kk)
   
   while (not eof(eng_lun)) do begin
      data = lonarr(n_elements(pname))
      readu,eng_lun,packet
      if packet(18) eq '0a'x then begin
         time = anytim2cal(obt2tai(packet(12:17)))
         for i=0,n_elements(pname)-1 do begin
            temp = (strmid(emask(5,i),2,4))(0)
            hex2dec,temp,pmask,/quiet
            offset = fix(emask(3,i))
            type = emask(2,i)
            case type of
              'B': begin
                     if pmask gt 0 then begin
                       data(i) = fix(packet(offset) and pmask)
                     endif else begin
                       data(i) = fix(packet(offset))
                     endelse
                   end
              'W': begin
                     temp = byteswap((fix(packet,offset,1))(0))
                     if pmask gt 0 then begin
                       data(i) = unsign(temp) and long(pmask)
                     endif else begin
                       data(i) = unsign(temp)
                     endelse
                   end
              'L': begin
                       data(i) = (long(packet,offset,1))(0)
                   end
             else: data(i) = 0
            endcase
         endfor
      
         packet_no = packet_no + 1
         relay_data(0,packet_no) = time
         relay_data(1:n_elements(pname),packet_no) = string(data)
         if (packet_no mod 100) eq 0 and not keyword_set(quiet) then begin
            print,'Read Eng A packet # ',packet_no,form='(a,i5)'
         endif 
      endif
   endwhile

;
;  free data file, ready for more 
;
   free_lun, eng_lun

endfor

;
;  trim array for return
;
n = where(relay_data(0,*) ne '')
if n(0) ge 0 then relay_data = relay_data(*,n)

;
;  save description of parameter
;
ptitle = strarr(n_elements(pname))

;
;  calibrate each parameter's values
;
for i=0,n_elements(pname)-1 do begin
   d = tm_calib(pname(i),relay_data(i+1,*),words)
   relay_data(i+1,*) = string(d)
   if words(0) eq 'title' then ptitle(i)=words(1) else ptitle(i)=words(2)
endfor

;
;  make the voltage readings into pseudo-relay stati by
;  assuming any voltage < 5.0 volts means it is OFF.
;
n = where(relay_data(9,*) le 5.0)
relay_data(9,*) = '1'
if n(0) ge 0 then relay_data(9,n) = '0'
 
n = where(relay_data(12,*) le 5.0)
relay_data(12,*) = '1'
if n(0) ge 0 then relay_data(12,n) = '0'

;
;  find the changes of mode
;
for i=0,n_elements(pname)-1 do begin
   d = fix(relay_data(i+1,*))-shift(fix(relay_data(i+1,*)),1)
   d(0) = d(1)
   d(n_elements(d)-1) = d(n_elements(d)-2)
   relay_data(i+1,*) = string(d)
endfor
 
;
;  and record them
;
record = strarr(4,1000)
nst = 0
for i=0,n_elements(pname)-1 do begin
   n = where(relay_data(i+1,*) gt 0)
   if n(0) ge 0 then begin
      nch = n_elements(n)
      record(0,nst:nst+nch-1) = pname(i)
      record(1,nst:nst+nch-1) = relay_data(0,n)
      record(2,nst:nst+nch-1) = 'ON'
      record(3,nst:nst+nch-1) = ptitle(i)
      nst = nst + nch
   endif
   n = where(relay_data(i+1,*) lt 0)
   if n(0) ge 0 then begin
      nch = n_elements(n)
      record(0,nst:nst+nch-1) = pname(i)
      record(1,nst:nst+nch-1) = relay_data(0,n)
      record(2,nst:nst+nch-1) = 'OFF'
      record(3,nst:nst+nch-1) = ptitle(i)
      nst = nst + nch
   endif
endfor

;
;  tidy strings
;
n = where(record(2,*) ne '',count)
if count gt 0 then begin
   record = record(*,n)
endif else begin
   if not keyword_set(quiet) then print,'Nothing found.'
   status = 1
   return
endelse

;
;  sort by time
;
n = sort(record(1,*))
record = record(*,n)

;
;  make structure for i/o
;
r = {par:'',time:'',state:'',desc:''}
relay = r
rs = replicate(r,n_elements(record)/4)
if n_elements(record) gt 4 then begin
   rs.par   = reform(record(0,*))
   rs.time  = reform(record(1,*))
   rs.state = reform(record(2,*))
   rs.desc  = reform(record(3,*))
endif else begin
   rs.par   = record(0)
   rs.time  = record(1)
   rs.state = record(2)
   rs.desc  = record(3)
endelse

;
;  print out unless quiet
;
if not keyword_set(quiet) then begin
   record(0,*) = strpad(record(0,*),14,/after)
   record(1,*) = strpad(record(1,*),20,/after)
   record(2,*) = strpad(record(2,*),5,/after)
   record(3,*) = strpad(record(3,*),42,/after)
   print,record(*,*),form='(4a)'
endif

;
;  pick up old records if any, sort and save
;
rfile = concat_dir('$CDS_ENG_DATA_W','relays_log')
if file_exist(rfile) then begin
   restore,file=rfile
   relay = concat_struct(relay,rs)
;
;  kill duplicates
;
   text = strcompress(relay.par+relay.time+relay.state+relay.desc,/rem)
   nnd = uniq(text(sort(text)))
   if nnd(0) ge 0 then relay = relay(nnd)

   save,relay,file=rfile,/xdr
   if not keyword_set(quiet) then print,'Relay history updated OK.'
endif else begin
   if not keyword_set(quiet) then print,'Previous relay history not found.'
   relay = rs
   save,relay,file=rfile,/xdr
   if not keyword_set(quiet) then print,'Relay history started OK.'
endelse
status = 1
   
end
