; -------------------------------------------------------------
; SICS Connectivity to IDL
;
; Philip Tregenna=Piggott March 2006
;
;-------------------------------------------------------------

function sicsconnect, unit, host, port,error=error
    socket, unit, host, port,error=error,connect_timeout=5
    ans = ''
    if error eq '' then readf, unit, ans
;    print,'ans = ',ans
    return,error
END
;--------------------------------------------------------------
FUNCTION sicslogon, unit,  user, password
    ans = ' '
    command = user + ' ' + password
    printf, unit, command
    readf, unit, ans
        match = STRMATCH(ans, '*OK*')
        RETURN, match
END
;----------------------------------------------------------
FUNCTION sicstransact, unit, command
   CATCH, Error_status
if Error_status ne 0 then begin
print, 'Error = ',!ERROR_STATE.MSG
catch, /cancel
return,'SICSConnectionLost'
endif

    response = ''
    ans = ' '
    void =''


    fullcommand = 'fulltransact ' + command
    printf, unit, fullcommand

       readf, unit, void
       while strpos(void,'TRANSACTIONSTART') eq -1 do begin
       readf, unit, void
       endwhile

    ;   print,'Error_status = ',error_status
       readf, unit, ans
       while STRMATCH(ans,'TRANSACTIONFINISHED') eq 0 do begin
       response+= ' ' + ans
       readf, unit, ans
       endwhile

return, response


END
;----------------------------------------------------------
FUNCTION sicstransactstrarr, unit, command
   CATCH, Error_status
if Error_status ne 0 then begin
catch, /cancel
return,'SICSConnectionLost'
endif

    response = 'Unable to Acquire String Array'
    ans = ' '
    void= ''

    fullcommand = 'fulltransact ' + command
    printf, unit, fullcommand

       readf, unit, void
       while strpos(void,'TRANSACTIONSTART') eq -1 do begin
       readf, unit, void
       endwhile

        ;   print,'Error_status = ',error_status
       readf, unit, ans
       while STRMATCH(ans,'TRANSACTIONFINISHED') eq 0 do begin
       response=[response,ans]
       readf, unit, ans
       endwhile

return, response


END
;----------------------------------------------------------
FUNCTION SicsMarsUpdate, event, unit, command, sicserrorlog
  IF (N_PARAMS() ne 4) THEN MESSAGE, 'Incorrect number of arguments'
error='error1' ; connection lost
errormessage=''
   CATCH, Error_status
if Error_status ne 0 then begin
print,'Error Message: ',!ERROR_STATE.MSG
catch, /cancel
if error eq 'error1' then begin
errormessage='Connection to SICS lost on '+systime()+'.'
sicserrorlog=[sicserrorlog,errormessage]
endif
;
if error eq 'error3' then begin
errormessage='Fatal Error at '+systime()+'.'+'.  Message: '+!ERROR_STATE.MSG
sicserrorlog=[sicserrorlog,errormessage]
endif
errorstructure={error:error, $
                sicserrorlog:sicserrorlog}
return,errorstructure
endif
;
ErrorGen=0 ;this is used only to identify the minor errors
;
;
fullcommand = 'fulltransact ' + command
printf, unit, fullcommand ;if this fails, error1 will be returned
;passed the first hurdle
;clear the buffer
void=''
       readf, unit, void
       while strpos(void,'TRANSACTIONSTART') eq -1 do begin
       readf, unit, void
       endwhile
;

ans=''
       readf, unit, ans
       while strpos(ans,'STARTDATA') eq -1 do begin
       if ans ne '' then begin
       ErrorGen=1
       errormessage='Error message encountered whilst acquiring MarsUpdate parameters at time '+systime()+'.  Message: '+ans
       sicserrorlog=[sicserrorlog,errormessage]
       print,errormessage
       endif
       readf, unit, ans
       ;what if sics does not issue the data? there will be no 'STARTDATA'
           if STRMATCH(ans,'TRANSACTIONFINISHED') eq 1 then begin
         error='error2' ; unable to issue the data
       errormessage='Unable to Acquire MarsUpdate Data at time '+systime()
       print,errormessage
       sicserrorlog=[sicserrorlog,errormessage]
       errorstructure={error:error, $
                sicserrorlog:sicserrorlog}
       return, errorstructure
           endif
       endwhile

;
readf, unit, ans ;first line should/could be blank
if ans eq '' then readf, unit, ans ; this should be the number of time bins
error='error2' ; unable to issue the data
equalsign=strpos(ans,'=')
if (equalsign eq -1) then begin
    if ans eq 'Random non deadly error' then begin
    errormessage=ans+' '+systime()
    endif else begin
    errormessage='Number of Time Bins at time '+systime()+'.  Message: '+ans
    endelse
       while STRMATCH(ans,'TRANSACTIONFINISHED') eq 0 do begin ; I can't do anything without the number of time bins
       readf, unit, ans
       endwhile
sicserrorlog=[sicserrorlog,errormessage]
errorstructure={error:error, $
                sicserrorlog:sicserrorlog}
return, errorstructure
endif
;passed the second hurdle
error='error3' ; the information acquired from sics upon issuing the command is not what was hoped for.
ans=strtrim((strsplit(ans,'=',/extract))[1],1)
;define number of time bins
notimebin=long(-1)
reads,ans,notimebin
;
readf, unit, ans ; this should be the time bins
error='error2' ; unable to issue the data
equalsign=strpos(ans,'=')
if (equalsign eq -1) then begin
errormessage='Time Bins Acquisition at time '+systime()+'.  Message: '+ans
       while STRMATCH(ans,'TRANSACTIONFINISHED') eq 0 do begin ; I can't do anything without the time bins
       readf, unit, ans
       endwhile
sicserrorlog=[sicserrorlog,errormessage]
errorstructure={error:error, $
                sicserrorlog:sicserrorlog}
return, errorstructure
endif
;passed the second hurdle
error='error3' ; the information acquired from sics upon issuing the command is not what was hoped for.
ans=strtrim((strsplit(ans,'=',/extract))[1],1)
;define data field
timebin=fltarr(notimebin)
reads,ans,timebin
timebin_space=(timebin[1]-timebin[0])/2.0
timebin+=timebin_space
nodata=24*notimebin
;
readf, unit, ans ; this should be the histogram data
error='error2' ; unable to issue the data
equalsign=strpos(ans,'=')
if (equalsign eq -1) then begin
errormessage='Histogram Data Acquisition at time '+systime()+'.  Message: '+ans
       while STRMATCH(ans,'TRANSACTIONFINISHED') eq 0 do begin ; I can't do anything without the histogram data
       readf, unit, ans
       endwhile
sicserrorlog=[sicserrorlog,errormessage]
errorstructure={error:error, $
                sicserrorlog:sicserrorlog}
return, errorstructure
endif
;passed the second hurdle
error='error3' ; the information acquired from sics upon issuing the command is not what was hoped for.
ans=strtrim((strsplit(ans,'=',/extract))[1],1)
;define data field
data=fltarr(nodata)
reads,ans,data
;
monitor1=long64(-1)
readf, unit, ans ; this should be the counts for monitor 1
equalsign=strpos(ans,'=')
if (equalsign eq -1) then begin
;monitor1=-1 ;already assigned in definition
ErrorGen=1
errormessage='Monitor 1 Data Acquisition at time '+systime()+'.  Message: '+ans
sicserrorlog=[sicserrorlog,errormessage]
print,errormessage
endif else begin
;error='error3' ; the information acquired from sics upon issuing the command is not what was hoped for.
ans=strtrim((strsplit(ans,'=',/extract))[1],1)
;define monitor field
reads,ans,monitor1
endelse
;
;
Angles_info=fltarr(10)
temp=float(0)
for i = 0,9 do begin
readf, unit, ans ; this should be the Angles_info
equalsign=strpos(ans,'=')
if (equalsign eq -1) then begin
temp=-1.0
ErrorGen=1
errormessage='Angle Info. Data Acquisition at time '+systime()+'.  Message: '+ans
sicserrorlog=[sicserrorlog,errormessage]
print,errormessage
endif else begin
ans=strtrim((strsplit(ans,'=',/extract))[1],1)
reads,ans,temp
endelse
Angles_info[i]=temp
endfor
;
;
Choppers_Info=fltarr(2,5)
;
for i = 0,4 do begin
readf, unit, ans ; this should be the ChopperPhases
equalsign=strpos(ans,'=')
if (equalsign eq -1) then begin
temp=-1.0
ErrorGen=1
errormessage='Chopper Phase Data Acquisition at time '+systime()+'.  Message: '+ans
sicserrorlog=[sicserrorlog,errormessage]
print,errormessage
endif else begin
ans=strtrim((strsplit(ans,'=',/extract))[1],1)
reads,ans,temp
endelse
Choppers_Info[0,i]=temp
endfor
;
;
for i = 0,4 do begin
readf, unit, ans ; this should be the ChopperSpeeds
equalsign=strpos(ans,'=')
if (equalsign eq -1) then begin
temp=-60.0
ErrorGen=1
errormessage='Chopper Speed Data Acquisition at time '+systime()+'.  Message: '+ans
sicserrorlog=[sicserrorlog,errormessage]
print,errormessage
endif else begin
ans=strtrim((strsplit(ans,'=',/extract))[1],1)
reads,ans,temp
endelse
Choppers_Info[1,i]=temp
endfor
;
target_reflection=''
readf, unit, ans ; this should be the target reflection
equalsign=strpos(ans,'=')
if (equalsign eq -1) then begin
target_reflection='002 Assumed'
ErrorGen=1
errormessage='Target Reflection Info. Acquisition at time '+systime()+'.  Message: '+ans
sicserrorlog=[sicserrorlog,errormessage]
print,errormessage
endif else begin
ans=strtrim((strsplit(ans,'=',/extract))[1],1)
reads,ans,target_reflection
endelse
;
;
Sample_Name=''
readf, unit, ans ; this should be the Sample Name
equalsign=strpos(ans,'=')
if (equalsign eq -1) then begin
Sample_Name='-1'
ErrorGen=1
errormessage='Sample Name Info. Acquisition at time '+systime()+'.  Message: '+ans
sicserrorlog=[sicserrorlog,errormessage]
print,errormessage
endif else begin
ans=strtrim((strsplit(ans,'=',/extract))[1],1)
reads,ans,Sample_Name
endelse
;
;
Start_time=''
readf, unit, ans ; this should be the Unix start time, the number of seconds after midnight 1970.
equalsign=strpos(ans,'=')
if (equalsign eq -1) then begin
Start_time='-1'
ErrorGen=1
errormessage='Start Time Info. Acquisition at time '+systime()+'.  Message: '+ans
sicserrorlog=[sicserrorlog,errormessage]
print,errormessage
endif else begin
ans=strtrim((strsplit(ans,'=',/extract))[1],1)
reads,ans,Start_time
endelse
;
;
TimeBinIndices=''
readf, unit, ans ; this should be the Unix start time, the number of seconds after midnight 1970.
equalsign=strpos(ans,'=')
if (equalsign eq -1) then begin
TimeBinIndices='-1'
ErrorGen=1
errormessage='TimeBinIndices Info. Acquisition at time '+systime()+'.  Message: '+ans
sicserrorlog=[sicserrorlog,errormessage]
print,errormessage
endif else begin
ans=strtrim((strsplit(ans,'=',/extract))[1],1)
reads,ans,TimeBinIndices
endelse
;
CounterPreset=''
readf, unit, ans ; this should be the counter preset, needed to estimate the end time
equalsign=strpos(ans,'=')
if (equalsign eq -1) then begin
CounterPreset='-1'
ErrorGen=1
errormessage='CounterPreset Info. Acquisition at time '+systime()+'.  Message: '+ans
sicserrorlog=[sicserrorlog,errormessage]
print,errormessage
endif else begin
ans=strtrim((strsplit(ans,'=',/extract))[1],1)
reads,ans,CounterPreset
endelse
;
Status=''
readf, unit, ans ; this should be the status
equalsign=strpos(ans,'=')
if (equalsign eq -1) then begin
Status='-1'
ErrorGen=1
errormessage='Status Info. Acquisition at time '+systime()+'.  Message: '+ans
sicserrorlog=[sicserrorlog,errormessage]
print,errormessage
endif else begin
ans=strtrim((strsplit(ans,'=',/extract))[1],1)
reads,ans,Status
endelse
;
Datanumber=''
readf, unit, ans ; this should be the Datanumber
equalsign=strpos(ans,'=')
if (equalsign eq -1) then begin
Datanumber='-1'
ErrorGen=1
errormessage='Datanumber Info. Acquisition at time '+systime()+'.  Message: '+ans
sicserrorlog=[sicserrorlog,errormessage]
print,errormessage
endif else begin
ans=strtrim((strsplit(ans,'=',/extract))[1],1)
reads,ans,Datanumber
endelse
;
Shutter=''
readf, unit, ans ; this should be the status
equalsign=strpos(ans,'=')
if (equalsign eq -1) then begin
Shutter='-1'
ErrorGen=1
errormessage='Shutter Info. Acquisition at time '+systime()+'.  Message: '+ans
sicserrorlog=[sicserrorlog,errormessage]
print,errormessage
endif else begin
ans=strtrim((strsplit(ans,'=',/extract))[1],1)
reads,ans,Shutter
endelse
;
while STRMATCH(ans,'TRANSACTIONFINISHED') eq 0 do begin
readf, unit, ans
endwhile
;
MarsUpdate_structure={notimebin:notimebin, $
                 timebin:timebin, $
                    data:data, $
                   monitor1:monitor1, $
                 Angles_info:Angles_info, $
                 Choppers_Info:Choppers_Info, $
                 target_reflection:target_reflection, $
                   Sample_Name:Sample_Name, $
                   ErrorGen:ErrorGen, $
                   sicserrorlog:sicserrorlog, $
                   Start_time:Start_time, $
                   TimeBinIndices:TimeBinIndices, $
                   CounterPreset:CounterPreset, $
                   Status:Status, $
                   Datanumber:Datanumber, $
                   shutter:shutter}
;
return,MarsUpdate_structure
END
;----------------------------------------------------------
FUNCTION sicscommand, event, unit, command,datatype=datatype,dimension=dimension,no_message=no_message
  IF (N_PARAMS() ne 3) THEN MESSAGE, 'Incorrect number of arguments'
if n_elements(datatype) eq 0 then datatype='string'
;tstart=systime(/seconds)
if datatype eq 'strarr' then begin
response=sicstransactstrarr(unit,command)
n=n_elements(response)
    if n gt 1 then begin
    data=response[1:*]
    wherenenull=where(data ne '', count)
       if count ne 0 then begin
       data=data[wherenenull]
       endif
    return,data
    endif else begin
    return,response
    endelse
endif else begin
response=sicstransact(unit,command)
endelse
if response eq 'SICSConnectionLost' then return,response
;print,'response = ',response
;telapsed=systime(/seconds)-tstart
;print,'Time to read in data = ',telapsed,datatype
equalsign=strpos(response,'=')
    if (equalsign eq -1) then begin
        print,'response = ',response
        if (n_elements(no_message) eq 0) then begin
           void = dialog_message(dialog_parent = event.top, $
        'The SICS command "'+command+'" failed.  A value of -1 will be assigned to the variable.')
        endif
    response=-1
    if datatype eq 'string' then response=string(-1)
    return,response
    endif
;    response=strmid(response,equalsign+2)
response=strtrim((strsplit(response,'=',/extract))[1],1)
if datatype eq 'string' then data=strtrim(response,2)
if datatype eq 'long' then data=long(response)
if datatype eq 'double' then data=double(response)
if datatype eq 'float' then data=float(response)
if datatype eq 'byte' then data=byte(response)
if datatype eq 'long64' then data=long64(response)
;
if datatype eq 'fltarr' then begin
    if n_elements(dimension) eq 0 then begin
        if (n_elements(no_message) eq 0) then begin
                void = dialog_message(dialog_parent = event.top, $
    'The dimension must be specified with array data types.  A value of -1 will be assigned to the variable.')
       endif
    return,-1
       endif
data=fltarr(dimension)
;tstart=systime(/seconds)
reads,response,data
;telapsed=systime(/seconds)-tstart
;print,'Time to convert data = ',telapsed
endif
;
if datatype eq 'intarr' then begin
    if n_elements(dimension) eq 0 then begin
        if (n_elements(no_message) eq 0) then begin
                void = dialog_message(dialog_parent = event.top, $
    'The dimension must be specified with array data types.  A value of -1 will be assigned to the variable.')
       endif
    return,-1
       endif
data=intarr(dimension)
reads,response,data
endif
;
if datatype eq 'lonarr' then begin
    if n_elements(dimension) eq 0 then begin
        if (n_elements(no_message) eq 0) then begin
                void = dialog_message(dialog_parent = event.top, $
    'The dimension must be specified with array data types.  A value of -1 will be assigned to the variable.')
       endif
    return,-1
       endif
data=lonarr(dimension)
reads,response,data
endif
;
if datatype eq 'lon64arr' then begin
    if n_elements(dimension) eq 0 then begin
        if (n_elements(no_message) eq 0) then begin
                void = dialog_message(dialog_parent = event.top, $
    'The dimension must be specified with array data types.  A value of -1 will be assigned to the variable.')
       endif
    return,-1
       endif
data=lon64arr(dimension)
reads,response,data
endif
;
if datatype eq 'strarr' then begin
    if n_elements(dimension) eq 0 then begin
        if (n_elements(no_message) eq 0) then begin
                void = dialog_message(dialog_parent = event.top, $
    'The dimension must be specified with array data types.  A value of -1 will be assigned to the variable.')
       endif
    return,-1
       endif
data=strarr(dimension)
reads,response,data
endif

return,data

end
;----------------------------------------------------------
FUNCTION SicsTempcommand, event, unit, command,no_message=no_message
  IF (N_PARAMS() ne 3) THEN MESSAGE, 'Incorrect number of arguments'
;
strans = ''
error='error1'
;
   CATCH, Error_status
if Error_status ne 0 then begin
catch, /cancel
    if error eq 'error1' then begin
    msg='SICSConnectionLost on '+systime()+'.'
    endif else begin
       if strpos(strans, 'ERROR') eq -1 then begin
        msg='SICS communication error '+systime()+' on trying to retrieve temperature. Message: '+!ERROR_STATE.MSG
       endif else begin
        msg='SICS communication error '+systime()+' on trying to retrieve temperature. Message: '+strans
       endelse
    while STRMATCH(strans,'TRANSACTIONFINISHED') eq 0 do begin
    readf, unit, strans
    endwhile
    endelse
    errorstructure={error:error, $
              msg:msg}
    return,errorstructure
endif
    fullcommand = 'fulltransact ' + command
    printf, unit, fullcommand
    void=''
       readf, unit, void
       while strpos(void,'TRANSACTIONSTART') eq -1 do begin
       readf, unit, void
       endwhile
        fltarr2ans=fltarr(2)
    dblarr2ans=dblarr(2)
readf, unit, strans
error='error2'
current_time=long64(strans)
REPEAT BEGIN
readf, unit, strans
    while strpos(strans,'*tt') ne -1 do begin
    identifier=strmid(strans,4,2)
    readf, unit, strans
           if strpos(strans,'*') eq -1 then begin
            reads,strans,dblarr2ans
           time_stamp=long64(dblarr2ans[0])-current_time
           temp_t=float(time_stamp)
           temp_t=make_array(1,value=temp_t)
           temp_v=float(dblarr2ans[1])
           temp_v=make_array(1,value=temp_v)
           readf, unit, strans
                while strpos(strans,'*') eq -1 do begin
          reads,strans,fltarr2ans
          temp_t=[temp_t,fltarr2ans[0]+temp_t[n_elements(temp_t)-1]]
          temp_v=[temp_v,fltarr2ans[1]]
                readf, unit, strans
                endwhile
         if n_elements(temp_t_struc) eq 0 then begin
         temp_t_struc=create_struct(identifier+'_time',temp_t)
         temp_v_struc=create_struct(identifier+'_variable',temp_v)
         endif else begin
         temp_t_struc=create_struct(temp_t_struc,identifier+'_time',temp_t)
         temp_v_struc=create_struct(temp_v_struc,identifier+'_variable',temp_v)
           endelse
           endif
    endwhile
ENDREP UNTIL STRMATCH(strans,'TRANSACTIONFINISHED')

if n_elements(temp_t_struc) eq 0 then begin
temperature_fields=create_struct('Empty',0)
return,temperature_fields
endif else begin
temperature_fields=create_struct(temp_t_struc,temp_v_struc)
return,temperature_fields
endelse


;printf, unit, 'transact graph -300 0 none -1 np 1000 tt.tr'
;repeat begin
;readf, unit, strans
;print,strans
;endrep until STRMATCH(strans,'TRANSACTIONFINISHED')

END
;----------------------------------------------------------
FUNCTION sicsexecute, event,unit, command,nowait=nowait,notransact=notransact
  IF (N_PARAMS() ne 3) THEN MESSAGE, 'Incorrect number of arguments'
   CATCH, Error_status
if Error_status ne 0 then begin
return,'SICSConnectionLost'
catch, /cancel
endif
    response = ''
    ans = ' '
    void = ' '

; sometimes it is useful to issue the command without transact, as MarsUpdate looks for this'; the buffer will be read
;dispsensed of at a later time
if n_elements(notransact) eq 1 then begin
       printf, unit, command
return,'notransact'
endif


    fullcommand = 'fulltransact ' + command
       printf, unit, fullcommand
if n_elements(nowait) eq 1 then return, 'nowait'


        readf, unit, void
       while strpos(void,'TRANSACTIONSTART') eq -1 do begin
       readf, unit, void
       endwhile


       readf, unit, ans
       while STRMATCH(ans,'TRANSACTIONFINISHED') eq 0 do begin
       response+= ' ' + ans
       readf, unit, ans
       endwhile

return, response
end
;----------------------------------------------------------
FUNCTION sicserrorcheck, event,unit
  IF (N_PARAMS() ne 2) THEN MESSAGE, 'Incorrect number of arguments'
   CATCH, Error_status
if Error_status ne 0 then begin
return,'SICSConnectionLost'
catch, /cancel
endif
command = 'exe info'
    response = 'none'
    ans = ' '

    fullcommand = 'transact ' + command
    printf, unit, fullcommand

       readf, unit, ans
       while STRMATCH(ans,'TRANSACTIONFINISHED') eq 0 do begin
       if strpos(strlowcase(ans),'warning') ne -1 then response = ans+'. Reported on '+systime()+ '.'
      ; if strpos(strlowcase(ans),'environment') ne -1 then response = ans
       readf, unit, ans
       endwhile

return, response
end
;----------------------------------------------------------
FUNCTION sicstranscomplete,event,unit
  IF (N_PARAMS() ne 2) THEN MESSAGE, 'Incorrect number of arguments'
    CATCH, Error_status
if Error_status ne 0 then begin
catch, /cancel
;print,'Error Message: ',!ERROR_STATE.MSG
return,'SICSConnectionLost'
endif
   response = ''
    ans = ' '


        readf, unit, ans
       while strpos(ans,'TRANSACTIONSTART') eq -1 do begin
       readf, unit, ans
       endwhile

       readf, unit, ans
       while STRMATCH(ans,'TRANSACTIONFINISHED') eq 0 do begin
       response+= ' ' + ans
       readf, unit, ans
       endwhile

return, response

end
;----------------------------------------------------------
FUNCTION sicsinterrupt, event,unit, command
   CATCH, Error_status
if Error_status ne 0 then begin
return,'SICSConnectionLost'
catch, /cancel
endif

    printf, unit, command


return, 'OK'
end

;----------------------------------------------------------
PRO sicsclose, unit
    printf, unit, 'SICSLOGOUT'
    free_lun,unit,/force
END
;----------------------------------------------------------

