;+ ;WIDGET Procedure: ; spp_ptp_recorder ;PURPOSE: ; Widget tool that opens a socket and records streaming data from a server (host) and can save it to a file ; or send to a user specified routine. This tool runs in the background. ; Keywords: ; SET_FILE_TIMERES : defines how often the current output file will be closed and a new one will be opened ; DIRECTORY: string prepended to fileformat when opening an output file. ; Author: ; Davin Larson - April 2011 ; ; $LastChangedBy: ali $ ; $LastChangedDate: 2021-09-24 16:07:57 -0700 (Fri, 24 Sep 2021) $ ; $LastChangedRevision: 30319 $ ; $URL: svn+ssh://thmsvn@ambrosia.ssl.berkeley.edu/repos/spdsoft/tags/spedas_5_0/projects/SPP/COMMON/spp_ptp_recorder.pro $ ; ;- PRO spp_ptp_recorder_event, ev ; recorder ; on_error,1 widget_control, ev.top, get_uvalue= info ; get all widget ID's wids = *info.wids localtime=1 dlevel=info.dlevel CASE ev.id OF ; Timed events wids.base: begin ; printdat,info on_ioerror, stream_error eofile =0 info.time_received = systime(1) widget_control,wids.base,set_uvalue=info if info.hfp gt 0 then begin ;; Switch file name if needed if info.file_timeres ne 0 then begin if info.time_received ge info.next_filechange then begin dprint,dlevel=dlevel,time_string(info.time_received,prec=3)+ ' Time to change files.' if info.dfp then begin spp_ptp_recorder_event,{top: ev.top, id:wids.dest_button} ; close old file - possible error that dfp might change! spp_ptp_recorder_event,{top: ev.top, id:wids.dest_button} ; open new file endif endif widget_control, ev.top, get_uvalue= info ; get all widget ID's info.next_filechange = info.file_timeres * ceil(info.time_received / info.file_timeres) widget_control,wids.base,set_uvalue=info endif if 1 then begin spp_ptp_lun_read,info.hfp,info.dfp,info=info widget_control,wids.base,set_uvalue=info msg = info.msg endif else begin on_ioerror, stream_error eofile =0 info.time_received = systime(1) widget_control,wids.base,set_uvalue=info buffer= bytarr(info.maxsize) b=buffer[0] i = 0L cnt =0L nhdr = 5 nb = nhdr while file_poll_input(info.hfp,timeout=0) && i lt info.maxsize do begin ; Read from stream one byte (or value) at a time b = bytarr(nb) readu,info.hfp,b buffer[i] = b i += nb if (nb eq nhdr) && (b[2] eq 3) && (b[3] eq 0) && b[4] eq 'bb'x then begin ; look at first few bytes to determine how large the packet is nb = swap_endian(uint(b,0) ,/swap_if_little_endian ) - nhdr ; dprint,dlevel=3,nb,i endif else if nb gt 10 then begin ; reset to read first few bytes on the next read nb = nhdr ; dprint,dlevel=3,nb endif else nb =1 cnt++ endwhile dt = systime(1) -info.time_received ; store_data,/append,'xrate',systime(1),dt/i*1e6 if debug(5) then begin dprint,dlevel=4,nb,cnt,i,dt, dt/i*1e6 endif if eofile eq 1 then begin stream_error: widget_control,wids.host_text,get_value=hostname widget_control,wids.host_port,get_value=hostport dprint,dlevel=dlevel+1,info.title_num+!error_state.msg endif if i gt 0 then begin ;; process data buffer = buffer[0:i-1] if keyword_set(info.dfp) then writeu,info.dfp, buffer ;swap_endian(buffer,/swap_if_little_endian) flush,info.dfp msg = string(/print,i,buffer[0:(i < 64)-1],format='(i6 ," bytes: ", 128(" ",Z02))') msg = time_string(info.time_received,tformat='hh:mm:ss - ',local=localtime) + msg endif else begin dummy = temporary(buffer) ; buffer=0 msg =time_string(info.time_received,tformat='hh:mm:ss - No data available',local=localtime) endelse if widget_info(/button_set,wids.proc_button) then begin widget_control,wids.proc_name,get_value = proc_name if keyword_set(proc_name) then call_procedure,proc_name[0],buffer ,info=info ;,time=info.time_received ; Execute exec_proc here endif endelse widget_control,wids.output_text,set_value=msg dprint,dlevel=dlevel+5,info.title_num+msg,/no_check widget_control,wids.poll_int,get_value = poll_int poll_int = float(poll_int) if poll_int le 0 then poll_int = 1 if 1 then begin poll_int = poll_int - (systime(1) mod poll_int) ; sample on regular boundaries endif if not keyword_set(eofile) then WIDGET_CONTROL, wids.base, TIMER=poll_int else begin widget_control,wids.host_button,timer=2 endelse endif return end wids.host_button : begin widget_control,wids.host_button,get_value=status widget_control,wids.host_text, get_value=server_name widget_control,wids.host_port, get_value=server_port server_n_port = server_name+':'+server_port case status of 'Connect to': begin *info.buffer_ptr = !null ; Get rid of previous buffer contents cache WIDGET_CONTROL, wids.host_button, set_value = 'Connecting',sensitive=0 WIDGET_CONTROL, wids.host_text, sensitive=0 WIDGET_CONTROL, wids.host_port, sensitive=0 socket,hfp,/get_lun,server_name,fix(server_port),error=error ,/swap_if_little_endian,connect_timeout=10 if keyword_set(error) then begin dprint,dlevel=dlevel-1,info.title_num+!error_state.msg+strtrim(error) ;strmessage(error) widget_control, wids.output_text, set_value=!error_state.msg WIDGET_CONTROL, wids.host_button, set_value = 'Failed:',sensitive=1 WIDGET_CONTROL, wids.host_text, sensitive=1 WIDGET_CONTROL, wids.host_port, sensitive=1 endif else begin dprint,dlevel=dlevel,info.title_num+'Connected to server: "'+server_n_port+'" Unit:'+strtrim(hfp) info.hfp = hfp WIDGET_CONTROL, wids.base, TIMER=1 ; , set_uvalue=hfp WIDGET_CONTROL, wids.host_button, set_value = 'Disconnect',sensitive=1 endelse end 'Disconnect': begin WIDGET_CONTROL, wids.host_button, set_value = 'Closing' ,sensitive=0 WIDGET_CONTROL, wids.host_text, sensitive=1 WIDGET_CONTROL, wids.host_port, sensitive=1 msg = 'Disconnected from server: "'+server_n_port+'"' widget_control, wids.output_text, set_value=msg dprint,dlevel=dlevel,info.title_num+msg free_lun,info.hfp info.hfp =0 wait,1 WIDGET_CONTROL, wids.host_button, set_value = 'Connect to',sensitive=1 end else: begin WIDGET_CONTROL, wids.host_text, sensitive=1 WIDGET_CONTROL, wids.host_port, sensitive=1 WIDGET_CONTROL, wids.host_button, set_value = 'Connect to',sensitive=1 dprint,info.title_num+'Error Recovery' end endcase end wids.dest_button: begin widget_control,ev.id,get_value=status widget_control,wids.dest_text, get_value=filename case status of 'Write to': begin if keyword_set(info.dfp) then begin free_lun,info.dfp info.dfp = 0 endif WIDGET_CONTROL, ev.id , set_value = 'Opening' ,sensitive=0 widget_control, wids.dest_text, get_value = fileformat,sensitive=0 filename = time_string(systime(1),tformat = fileformat[0]) ; Substitute time string widget_control,wids.host_text, get_value=hostname filename = str_sub(filename,'{HOST}',strtrim(hostname,2) ) widget_control,wids.host_port, get_value=hostport filename = str_sub(filename,'{PORT}',strtrim(hostport,2) ) ; Substitute port number widget_control, wids.dest_text, set_uvalue = fileformat,set_value=filename if keyword_set(filename) then begin file_open,'u',info.directory+filename, unit=dfp,dlevel=4,compress=-1,file_mode='666'o,dir_mode='777'o dprint,dlevel=dlevel,info.title_num+'Opened output file: '+file_info_string(info.directory+filename)+' Unit:'+strtrim(dfp) info.dfp = dfp info.filename= info.directory+filename widget_control, wids.dest_flush, sensitive=1 endif ; wait,1 WIDGET_CONTROL, ev.id, set_value = 'Close ',sensitive =1 end 'Close ': begin WIDGET_CONTROL, ev.id, set_value = 'Closing',sensitive=0 widget_control, wids.dest_flush, sensitive=0 widget_control, wids.dest_text ,get_uvalue= fileformat,get_value=filename if info.dfp gt 0 then begin free_lun,info.dfp info.dfp =0 endif ; wait,1 widget_control, wids.dest_text ,set_value= fileformat,sensitive=1 WIDGET_CONTROL, ev.id, set_value = 'Write to',sensitive=1 dprint,dlevel=dlevel,info.title_num+'Closed output file: '+file_info_string(info.directory+filename),no_check_events=1 end else: begin dprint,info.title_num+'Invalid State' end endcase end wids.dest_flush: begin spp_ptp_recorder_event,{top: ev.top, id:wids.dest_button} ; close old file spp_ptp_recorder_event,{top: ev.top, id:wids.dest_button} ; open new file end ; wids.host_text: begin ; widget_control,ev.id,get_value=value ; dprint,'"'+value+'"' ; end wids.proc_button: begin widget_control,wids.proc_name,get_value=proc_name widget_control,wids.proc_name,sensitive = (ev.select eq 0) info.run_proc = ev.select dprint,dlevel=2,info.title_num+'"'+proc_name+ '" is '+ (info.run_proc ? 'ON' : 'OFF') end wids.done: begin ; 'DONE' ; close files here! if info.hfp gt 0 then begin fs = fstat(info.hfp) dprint,dlevel=dlevel-1,info.title_num+'Closing '+fs.name free_lun,info.hfp endif if info.dfp gt 0 then begin fs = fstat(info.dfp) dprint,dlevel=dlevel-1,info.title_num+'Closing '+fs.name free_lun,info.dfp endif ptr_free,ptr_extract(info) WIDGET_CONTROL, ev.TOP, /DESTROY dprint,dlevel=dlevel-1,info.title_num+'Widget Closed' return end else: begin msg = string('Base ID is: ',wids.base) widget_control, wids.output_text, set_value=msg dprint,info.title_num+msg printdat,ev printdat,info end ENDCASE widget_control,wids.base,set_uvalue=info END ;PRO exec_proc_template,buffer,info=info ;; savetomain,buffer ;; savetomain,time ; ; n = n_elements(buffer) ; if n ne 0 then begin ; if debug(2) then begin ; dprint,time_string(info.time_received,prec=3) +''+ strtrim(n_elements(buffer)) ; n = n_elements(buffer) < 512 ; hexprint,buffer[0:n-1] ;,swap_endian(uint(buffer,0,n_elements(buffer)/2)) ; endif ; endif else print,format='(".",$)' ; ; return ;end PRO spp_ptp_recorder,base,title=title,ids=ids,host=host,port=port,destination=destination,exec_proc=exec_proc, $ set_connect=set_connect, set_output=set_output, pollinterval=pollinterval, set_file_timeres=set_file_timeres ,$ get_procbutton = get_procbutton,set_procbutton=set_procbutton,directory=directory, $ get_filename=get_filename,info=info if ~(keyword_set(base) && widget_info(base,/managed) ) then begin if not keyword_set(host) then host = 'localhost' if not keyword_set(port) then port = '2022' if not keyword_set(title) then title = 'SPP PTP Recorder' port=strtrim(port,2) if not keyword_set(destination) then destination = 'socket_{HOST}.{PORT}_YYYYMMDD_hhmmss.dat' ids = create_struct('base', WIDGET_BASE(/COLUMN, title=title ) ) ids = create_struct(ids,'host_base', widget_base(ids.base,/row, uname='HOST_BASE') ) ids = create_struct(ids,'host_button', widget_button(ids.host_base, uname='HOST_BUTTON',value='Connect to') ) ids = create_struct(ids,'host_text', widget_text(ids.host_base, uname='HOST_TEXT' ,VALUE=host ,/EDITABLE ,/NO_NEWLINE ) ) ids = create_struct(ids,'host_port', widget_text(ids.host_base, uname='HOST_PORT',xsize=6, value=port , /editable, /no_newline)) ids = create_struct(ids,'poll_int' , widget_text(ids.host_base, uname='POLL_INT',xsize=6,value='1',/editable,/no_newline)) ; if n_elements(directory) ne 0 then $ ; ids = create_struct(ids,'destdir_text', widget_text(ids.base, uname='DEST_DIRECTORY',xsize=40 ,/EDITABLE ,/NO_NEWLINE ,VALUE=directory)) ids = create_struct(ids,'dest_base', widget_base(ids.base,/row, uname='DEST_BASE')) ids = create_struct(ids,'dest_button', widget_button(ids.dest_base, uname='DEST_BUTTON',value='Write to')) ids = create_struct(ids,'dest_text', widget_text(ids.dest_base, uname='DEST_TEXT',xsize=40 ,/EDITABLE ,/NO_NEWLINE ,VALUE=destination)) ids = create_struct(ids,'dest_flush', widget_button(ids.dest_base,uname='DEST_FLUSH', value='New' ,sensitive=0)) ids = create_struct(ids,'output_text', WIDGET_TEXT(ids.base, uname='OUTPUT_TEXT')) ids = create_struct(ids,'proc_base', widget_base(ids.base,/row, uname='PROC_BASE')) ids = create_struct(ids,'proc_base2', widget_base(ids.proc_base ,/nonexclusive)) ids = create_struct(ids,'proc_button', widget_button(ids.proc_base2,uname='PROC_BUTTON',value='Procedure:')) ids = create_struct(ids,'proc_name', widget_text(ids.proc_base,xsize=35, uname='PROC_NAME', value = keyword_set(exec_proc) ? exec_proc :'exec_proc_template',/editable, /no_newline)) ids = create_struct(ids,'done', WIDGET_BUTTON(ids.proc_base, VALUE='Done', UNAME='DONE')) title_num = title+' ('+strtrim(ids.base,2)+'): ' if 1 then info = { socket_recorder } else begin info = {wids: ptr_new(), $ ; hostname:host, hostport:port, $ title: title, $ title_num: title_num, $ time_received: 0d, $ file_timeres: 0d, $ next_filechange: 1d20, $ hfp:0, $ directory:'' , $ fileformat:destination, $ filename:'', $ dfp:0 , $ maxsize:2L^23, $ buffer_ptr: ptr_new(), $ ; pollinterval:1., $ verbose:2, $ dlevel: 2, $ msg: '', $ exec_proc_ptr: ptr_new(), $ last_time: 0d, $ total_bytes: 0uL, $ process_rate : 0d, $ run_proc:keyword_set(set_procbutton) } endelse info.wids = ptr_new(ids) info.next_filechange = 1d20 info.title=title info.title_num = title_num info.fileformat = destination info.maxsize = 2L^23 info.buffer_ptr = ptr_new(!null) info.verbose =2 info.exec_proc_ptr = ptr_new(!null) info.run_proc = keyword_set(set_procbutton) ; info.buffer_ptr = ptr_new( bytarr( info.maxsize ) ) WIDGET_CONTROL, ids.base, SET_UVALUE=info WIDGET_CONTROL, ids.base, /REALIZE widget_control, ids.base, base_set_title=title_num XMANAGER, 'spp_ptp_recorder', ids.base,/no_block dprint,dlevel=dlevel,info.title_num+'Widget started' base = ids.base endif else begin widget_control, base, get_uvalue= info ; get all widget ID's ids = *info.wids endelse if size(/type,exec_proc) eq 7 then widget_control,ids.proc_name,set_value=exec_proc if size(/type,destination) eq 7 then widget_control,ids.dest_text,set_value=destination if size(/type,host) eq 7 then widget_control,ids.host_text,set_value=host if n_elements(port) eq 1 then widget_control,ids.host_port,set_value=strtrim(port,2) if n_elements(pollinterval) ne 0 then widget_control,ids.poll_int,set_value=strtrim(pollinterval,2) if n_elements(set_output) eq 1 && (keyword_set(info.dfp) ne keyword_set(set_output )) then spp_ptp_recorder_event, { id:ids.dest_button, top:ids.base } if n_elements(set_connect) eq 1 && (keyword_set(info.hfp) ne keyword_set(set_connect)) then spp_ptp_recorder_event, { id:ids.host_button, top:ids.base } if n_elements(set_procbutton) eq 1 then begin widget_control,ids.proc_button,set_button=set_procbutton spp_ptp_recorder_event, { top:ids.base, id:ids.proc_button, select: keyword_set(set_procbutton) } endif if n_elements(set_file_timeres) then begin info.file_timeres = set_file_timeres widget_control, base, set_uvalue= info endif if n_elements(directory) then begin info.directory = directory widget_control, base, set_uvalue= info endif get_procbutton = widget_info(ids.proc_button,/button_set) ;widget_control,ids.dest_text,get_value=get_filename get_filename = keyword_set(info.dfp) ? info.filename : '' END