class SCPIsession

Introduction

SCPIsession manages network connections and connection state for SPCI sessions.

SCPIsession State Parameters

The object is controlled via changing the object’s state parameters. I know, that’s not much to go on. It’s really pretty simple. A few examples are probably the best way to understand it. See the mrSCPI readme.

SCPIsession State Parameters: Global behavior

SCPIsession State Parameters: Command string specification

SCPIsession State Parameters: Instrument I/O tuning

SCPIsession State Parameters: Connection Parameters

Connection parameters may only be set when an SCPIsession object is created (via new).

SCPIsession State Parameters: Output Control

SCPIsession State Parameters: Result processing

Strings returned from instruments can be processed via a standard set of transformations controlled by the options in this section. The actions occur in the order they are documented in this section. For example, operations after :result_split are applied each array element resulting from the split. If :result_type is nil, none of these actions are taken.

SCPIsession State Parameters: Result storage

SCPIsession State Parameters: Macros

The following pseudo-options are provided for connivance, and are equivalent to setting several other options simultaneously. Like all option-like entities, these pseudo-options take an argument. This argument must be provided even if the macro ignores it.

- Result processing & Output Control Macros
                                 :result_extract_block :result_split :result_chomp :result_strip :result_last_word :result_type :print_max_len :print_debug
  - :result_macro_bin (P) ....... false                 nil           false         false         false             :string      nil            false
  - :result_macro_block (P) ..... true                  nil           false         false         false             :string      nil            false
  - :result_macro_ascii (P) ..... false                 nil           true          true          false             :string      nil            false
  - :result_macro_debug (P) ..... false                 nil           true          true          false             :string      256            true
  - :result_macro_csv (P) ....... false                 ','           true          true          false             :string      nil            false

Public Class Methods

new(options) click to toggle source
# File src/mrSCPI.rb, line 428
def initialize(options)
  @re           = SCPIregexLibrary.instance
  @gblOpt       = Hash.new
  @tcpSocket    = nil
  @results      = Array.new
  @varList      = Hash.new
  @validProto   = [:raw, :soip, :lxi, :plgx, :t3k, :file]
  @validType    = [nil, :mixed, :string, :float, :int, :bool]
  @validSplits  = [nil, :char, :string, :space, :unpack, :block, :regex, :line, :csv, :ssv]
  @gblOptReqPsu = Set.new(PrintyPrintyBangBang.instance.validOptions + [ :url ])
  @gblOptReqNew = { :ip_address               => lambda { |x| (x.is_a?(String)) && (x.length > 1)               },
                    :net_port                 => lambda { |x| (x.is_a?(Integer)) && (x >= 0) && (x <= 65535)    },
                    :net_protocol             => lambda { |x| @validProto.member?(x)                            },
                  }
  @gblOptReqRun = { :cmd                      => lambda { |x| (x.is_a?(String)) && (x.length > 1)               },
                    :delay_after_complete     => lambda { |x| (x.is_a?(Integer)) && (x >= 0)                    },
                    :delay_before_first_read  => lambda { |x| (x.is_a?(Integer)) && (x >= 0)                    },
                    :eol                      => lambda { |x| (x.is_a?(String))                                 },
                    :execute_on_cmd           => lambda { |x| [true, false].member?(x)                          },
                    :name                     => lambda { |x| x.nil? || ((x.is_a?(String)) && (x.length > 0))   },
                    :print_cmd                => lambda { |x| [true, false].member?(x)                          },
                    #print_debug              Part of PrintyPrintyBangBang
                    #print_max_len            Part of PrintyPrintyBangBang
                    :print_raw_result         => lambda { |x| [true, false].member?(x)                          },
                    :print_result             => lambda { |x| [true, false].member?(x)                          },
                    :read_buffer_size         => lambda { |x| (x.is_a?(Integer)) && (x > 0)                     },
                    :read_eot_sentinel        => lambda { |x| x.nil? || ((x.is_a?(String)) && (x.length > 0))   },
                    :read_max_bytes           => lambda { |x| x.nil? || ((x.is_a?(Integer)) && (x > 0))         },
                    :read_retry_delay         => lambda { |x| (x.is_a?(Integer)) && (x >= 0)                    },
                    :read_timeout_first_byte  => lambda { |x| (x.is_a?(Integer)) && (x >= 0)                    },
                    :read_timeout_next_byte   => lambda { |x| (x.is_a?(Integer)) && (x >= 0)                    },
                    :result_chomp             => lambda { |x| [true, false].member?(x)                          },
                    :result_extract_block     => lambda { |x| [true, false].member?(x)                          },
                    :result_last_word         => lambda { |x| [true, false].member?(x)                          },
                    :result_split             => lambda { |x| @validSplits.member?(x)                           },
                    :result_split_arg         => lambda { |x| x.nil? || ((x.is_a?(String)) && (x.length > 0))   },
                    :result_squeeze           => lambda { |x| [true, false].member?(x)                          },
                    :result_strip             => lambda { |x| [true, false].member?(x)                          },
                    :result_type              => lambda { |x| @validType.member?(x)                             },
                    :scpi_prefix              => lambda { |x| x.is_a?(String)                                   },
                    :socket_close             => lambda { |x| [true, false].member?(x)                          },
                    :socket_close_write       => lambda { |x| [true, false].member?(x)                          },
                    :store_cmd                => lambda { |x| [true, false].member?(x)                          },
                    :store_last_in_ans        => lambda { |x| [true, false].member?(x)                          },
                    :store_named_in_var       => lambda { |x| [true, false].member?(x)                          },
                    :store_raw_results        => lambda { |x| [true, false].member?(x)                          },
                    :store_results            => lambda { |x| [true, false].member?(x)                          },
                    :var                      => lambda { |x| x.nil? || ((x.is_a?(String)) && (x.length > 0))   },
                  }

  # Set initial parameter values
  set({ #delay_after_complete     Set from proto
        #delay_before_first_read  Set from proto
        :eol                  =>        "\n",
        :execute_on_cmd       =>        true,
        :name                 =>         nil,
        :exit_0               =>       false,
        :exit_on_error        =>        true,
        :print_cmd            =>       false,
        :print_debug          =>       false,
        :print_max_len        =>         nil,
        :print_raw_result     =>       false,
        :print_result         =>       false,
        :read_buffer_size     =>     1048576,
        :read_eot_sentinel    =>         nil,
        :read_max_bytes       =>         nil,
        #read_retry_delay         Set from proto
        #read_timeout_first_byte  Set from proto
        #read_timeout_next_byte   Set from proto
        :result_chomp         =>       false,
        :result_extract_block =>       false,
        :result_last_word     =>       false,
        :result_split         =>         nil,
        :result_split_arg     =>         nil,
        :result_squeeze       =>       false,
        :result_strip         =>       false,
        :result_type          =>     :string,
        :scpi_prefix          =>          '',
        :socket_close         =>       false,
        :socket_close_write   =>       false,
        :store_cmd            =>        true,
        :store_last_in_ans    =>        true,
        :store_named_in_var   =>        true,
        :store_raw_results    =>        true,
        :store_results        =>        true,
        :var                  =>         nil,
      }.merge(options))
end

Public Instance Methods

command(cmd, options=nil) click to toggle source

While .set perfectly capable of setting the :cmd parameter, this method provides provides a more readable alternative.

# File src/mrSCPI.rb, line 635
def command(cmd, options=nil)
  if options && options.member?(:cmd) then
    PrintyPrintyBangBang.instance.logPrinter(1, "ERROR: :cmd must not appear in options list when calling 'command'!", self, 74)
  end
  # Set options first -- so we don't trigger automatic execution.
  if options
    set(options)
  end
  # Now set command by ourselves without the set method so we can execute the command ourselves and return a result if :execute_on_cmd is on
  @gblOpt[:cmd] = cmd
  if @gblOpt[:execute_on_cmd] then
    PrintyPrintyBangBang.instance.logPrinter(4, "DEBUG-4: Attempting automatic execution", self)
    return execute()
  end
end
execute() click to toggle source

This method executes the command specified by the :cmd parameter. This is method is completely unnecessary if the :execute_on_cmd parameter is non-nil.

# File src/mrSCPI.rb, line 691
def execute()
  time_exe_start = Time.now
  # Make sure all required options required by new are set and valid
  @gblOptReqRun.each do |k, validator|
    if !(validator.call(@gblOpt[k])) then
      PrintyPrintyBangBang.instance.logPrinter(1, "ERROR: Unable to execute.  Execution option is invalid: #{k.inspect} = #{@gblOpt[k].inspect}!", self, 76)
    end
  end
  PrintyPrintyBangBang.instance.logPrinter(4, "DEBUG-4: Execution options are good", self)
  # We are good to go!
  curCmd = @gblOpt[:cmd]
  strToSend = @gblOpt[:scpi_prefix] + @gblOpt[:cmd]
  if @gblOpt[:net_protocol] == :plgx then
    strToSend = strToSend + "\n"
  else
    strToSend = strToSend + @gblOpt[:eol]
  end
  if @gblOpt[:print_cmd] then
    PrintyPrintyBangBang.instance.outPrinter(">>#{strToSend.chomp.strip}>>", newline=true)
  end
  strWeGot = ''
  if @gblOpt[:net_protocol] == :file then
    PrintyPrintyBangBang.instance.logPrinter(4, "DEBUG-4: Opening file", self)
    begin
      strWeGot = open(curCmd, "rb").read();
    rescue
      PrintyPrintyBangBang.instance.logPrinter(1, "ERROR: Unable to open file #{curCmd}!", self, 87)
    end
    if @gblOpt[:print_raw_result] then
      PrintyPrintyBangBang.instance.outPrinter(strWeGot, newline=false)
    end
  else
    if [:raw, :soip, :plgx].member?(@gblOpt[:net_protocol]) then
      if @tcpSocket.nil? then
        PrintyPrintyBangBang.instance.logPrinter(4, "DEBUG-4: Opening Socket", self)
        begin
          @tcpSocket = TCPSocket.open(@gblOpt[:ip_address], @gblOpt[:net_port])
        rescue
          PrintyPrintyBangBang.instance.logPrinter(1, "ERROR: Unable to open TCP/IP socket!", self, 82)
        end
        if @gblOpt[:net_protocol] == :plgx then
          PrintyPrintyBangBang.instance.logPrinter(4, "DEBUG-4: Sending :plgx startup instructions", self)
          @tcpSocket.write("++mode 1\n")
          @tcpSocket.write("++savecfg 0\n")
          @tcpSocket.write("++auto 0\n")
          @tcpSocket.write("++eoi 1\n")
          # We only do these when we open the socket.  Unfortunatly that means we miss :eol and :read_timeout_next_byte changes after socket open... BUG TODO
          @tcpSocket.write("++read_tmo_ms #{[50, @gblOpt[:read_timeout_first_byte]-50].max}\n")
          @tcpSocket.write("++eos " + ({"\0d\0a" => '0', "\0d" => '1', "\0a" => '2'}[@gblOpt[:eol]] || '3') + "\n")
          #@tcpSocket.write("++ifc\n")
        end
      end
      PrintyPrintyBangBang.instance.logPrinter(3, "INFO: Sending Command: #{strToSend.inspect}", self)
      @tcpSocket.write(strToSend)
      if !(@gblOpt[:result_type].nil?) && (@gblOpt[:net_protocol] == :plgx) then
        PrintyPrintyBangBang.instance.logPrinter(4, "DEBUG-4: Sending :plgx ++read instruction.", self)
        @tcpSocket.write("++read eoi\n")
      end
      if @gblOpt[:socket_close_write] then
        PrintyPrintyBangBang.instance.logPrinter(4, "DEBUG-4: Closing TCP write connection.", self)
        @tcpSocket.close_write()
      end
      if !(@gblOpt[:result_type].nil?) then
        if @gblOpt[:delay_before_first_read] > 0 then
          PrintyPrintyBangBang.instance.logPrinter(4, "DEBUG-4: DELAY: Pre-read delay_time = #{@gblOpt[:delay_before_first_read]}ms.", self)
          sleep(@gblOpt[:delay_before_first_read]/1000.0)
        end
        PrintyPrintyBangBang.instance.logPrinter(4, "DEBUG-4: Read loop starting...", self)
        time_send = Time.now
        time_read = nil
        total_recvd = 0
        loop do
          begin
            recvd_data = @tcpSocket.recv_nonblock(@gblOpt[:read_buffer_size])
            strWeGot += recvd_data
            recvd_length = recvd_data.length()
            total_recvd += recvd_length
            if time_read.nil? then
              PrintyPrintyBangBang.instance.logPrinter(4, "DEBUG-4: Received #{recvd_length} bytes in first read.", self)
            else
              PrintyPrintyBangBang.instance.logPrinter(4, "DEBUG-4: Received #{recvd_length} bytes in last read.  Total of #{total_recvd} so far.", self)
            end
            time_read = Time.new
            if @gblOpt[:print_raw_result] then
              PrintyPrintyBangBang.instance.outPrinter(recvd_data, newline=false)
            end
            if recvd_length < 1 then
              if total_recvd == 0 then
                PrintyPrintyBangBang.instance.logPrinter(3, "INFO: Received no data.  Transmission complete.", self)
              else
                PrintyPrintyBangBang.instance.logPrinter(3, "INFO: Received nothing in last read.  Total of #{total_recvd}.  Transmission complete.", self)
              end
              break
            end
            if @gblOpt[:read_eot_sentinel] && recvd_data.include?(@gblOpt[:read_eot_sentinel]) then
              PrintyPrintyBangBang.instance.logPrinter(3, "INFO: Received #{total_recvd} bytes and EOT sentinel.  Transmission complete.", self)
              break
            end
            if @gblOpt[:read_max_bytes] && (total_recvd >= @gblOpt[:read_max_bytes]) then
              if total_recvd == @gblOpt[:read_max_bytes] then
                PrintyPrintyBangBang.instance.logPrinter(3, "INFO: Received #{total_recvd}.  As expected.  Transmission complete.", self)
              else
                PrintyPrintyBangBang.instance.logPrinter(2, "WARNING: Received #{total_recvd}.  Only expected #{@gblOpt[:read_max_bytes]}.  Transmission complete.", self)
              end
              break
            end
          rescue IO::WaitReadable
            time_now = Time.now
            if time_read.nil? then
              delta = time_now - time_send
              if delta > 1 then
                PrintyPrintyBangBang.instance.logPrinter(2, "WARNING: Instrument has not responded in #{delta} seconds", self)
              else
                PrintyPrintyBangBang.instance.logPrinter(3, "INFO: Instrument has not responded in #{delta} seconds", self)
              end
              if @gblOpt[:read_timeout_first_byte] < (delta*1000) then
                PrintyPrintyBangBang.instance.logPrinter(1, "ERROR: Giving up due to first byte timeout", self, nil);
                break
              else
                if @gblOpt[:read_retry_delay] > 0 then
                  PrintyPrintyBangBang.instance.logPrinter(4, "DEBUG-4: DELAY: io_retry_delay = #{@gblOpt[:delay_before_first_read]}ms.", self)
                  sleep(@gblOpt[:read_retry_delay]/1000.0)
                end
              end
            else
              delta = time_now-time_read
              if delta > 1 then
                PrintyPrintyBangBang.instance.logPrinter(3, "INFO: Received #{total_recvd} bytes. No new data received for #{delta} seconds", self)
              else
                PrintyPrintyBangBang.instance.logPrinter(4, "DEBUG-4: Received #{total_recvd} bytes. No new data received for #{delta} seconds", self)
              end
              if @gblOpt[:read_timeout_next_byte] < (1000*delta) then
                PrintyPrintyBangBang.instance.logPrinter(3, "INFO: Received #{total_recvd} bytes. Assuming no more data to receive.", self);
                break
              else
                if @gblOpt[:read_retry_delay] > 0 then
                  PrintyPrintyBangBang.instance.logPrinter(4, "DEBUG-4: DELAY: io_retry_delay = #{@gblOpt[:delay_before_first_read]}ms.", self)
                  sleep(@gblOpt[:read_retry_delay]/1000.0)
                end
              end
            end
            retry
          end
        end
      else
        PrintyPrintyBangBang.instance.logPrinter(4, "DEBUG-4: Not waiting for response from instrument (:result_type nil).", self)
      end
      if @gblOpt[:socket_close] || @gblOpt[:socket_close_write] then
        PrintyPrintyBangBang.instance.logPrinter(4, "DEBUG-4: Closing TCP connection.", self)
        @tcpSocket.close()
        @tcpSocket = nil
      end
    elsif @gblOpt[:net_protocol] == :t3k then
      PrintyPrintyBangBang.instance.logPrinter(3, "INFO: Sending Command: #{strToSend.inspect}", self)
      res = Net::HTTP.post_form(URI.parse("http://#{@gblOpt[:ip_address]}:#{@gblOpt[:net_port]}/Comm.html"), { 'COMMAND' => strToSend })
      if !(res.nil?) then
        if !(@gblOpt[:result_type].nil?) then
          strWeGot = res.body.sub(/^.*NAME="name">/m, '').sub(/<\/TEXTAREA.*$/m, '')
          if strWeGot.length > 0 then
            if @gblOpt[:result_type] && @gblOpt[:print_raw_result] then
              PrintyPrintyBangBang.instance.outPrinter(strWeGot, newline=false)
            end
          end
        end
      else
        PrintyPrintyBangBang.instance.logPrinter(1, "ERROR: unknown protocol: #{@gblOpt[:net_protocol].inspect}", self, 77)
      end
    end
  end
  time_exe_done = Time.now
  # Command execution is complete
  PrintyPrintyBangBang.instance.logPrinter(4, "DEBUG-4: Raw result string: #{strWeGot[0..100].inspect}", self)
  PrintyPrintyBangBang.instance.logPrinter(3, "INFO: Execution time: #{time_exe_done - time_exe_start}", self)

  thingyWeReturn = strWeGot
  if (@gblOpt[:result_extract_block]) && (thingyWeReturn.length >= 2) && (thingyWeReturn[0] == '#') then
    blockHeadLen = thingyWeReturn[1, 1].to_i(16)
    if (blockHeadLen.zero?) then
      thingyWeReturn = thingyWeReturn.slice(2)
    else
      blockBodyLen = thingyWeReturn[2, blockHeadLen].to_i()
      thingyWeReturn = thingyWeReturn[blockHeadLen+2, blockBodyLen]
    end
  end
  case @gblOpt[:result_split]
    when :char
      thingyWeReturn = thingyWeReturn.split(Regexp.new("[#{@gblOpt[:result_split_arg]}]", Regexp::EXTENDED | Regexp::MULTILINE))
    when :regex
      thingyWeReturn = thingyWeReturn.split(Regexp.new(@gblOpt[:result_split_arg],        Regexp::EXTENDED | Regexp::MULTILINE))
    when :space
      thingyWeReturn = thingyWeReturn.split(@re.a(:split_space))
    when :line
      thingyWeReturn = thingyWeReturn.split(@re.a(:split_line))
    when :csv
      thingyWeReturn = thingyWeReturn.split(@re.a(:split_csv))
    when :ssv
      thingyWeReturn = thingyWeReturn.split(@re.a(:split_ssv))
    when :string
      thingyWeReturn = thingyWeReturn.split(@gblOpt[:result_split_arg])
    when :unpack
      thingyWeReturn = thingyWeReturn.unpack(@gblOpt[:result_split_arg])
    when :block
      if (thingyWeReturn.length >= 2) && (thingyWeReturn[0] == '#') then
        blockHeadLen = thingyWeReturn[1, 1].to_i(16)
        if blockHeadLen.zero? then
          thingyWeReturn = [ thingyWeReturn[0, 2], thingyWeReturn.slice(2) ]
        else
          blockBodyLen = thingyWeReturn[2, blockHeadLen].to_i()
          thingyWeReturn = [ thingyWeReturn[0, blockHeadLen+2], thingyWeReturn[blockHeadLen+2, blockBodyLen] ]
        end
      else
        thingyWeReturn = [ "", thingyWeReturn ]
      end
    else
      thingyWeReturn = [ thingyWeReturn ]
  end
  if @gblOpt[:result_squeeze] then
    thingyWeReturn = thingyWeReturn.map { |x| (x.is_a?(String) ? x.gsub(@re.a(:split_space)) { |m| (m.match?(@re.a(:split_line)) ? "\n" : " "); } : x) }
  end
  if @gblOpt[:result_chomp] then
    thingyWeReturn = thingyWeReturn.map { |x| (x.is_a?(String) ? x.chomp : x) }
  end
  if @gblOpt[:result_strip] then
    thingyWeReturn = thingyWeReturn.map { |x| (x.is_a?(String) ? x.strip : x) }
  end
  if @gblOpt[:result_last_word] then
    thingyWeReturn = thingyWeReturn.map { |x| (x.is_a?(String) ? x.rstrip.sub(/^.* /, '') : x) }
  end
  if @gblOpt[:result_type] != :mixed then  # It can't be nil if we get to this line
    case @gblOpt[:result_type]
      when :string
        thingyWeReturn = thingyWeReturn.map(&:to_s)
      when :float
        thingyWeReturn = thingyWeReturn.map { |x| ((x.is_a?(String) || x.is_a?(Numeric)) ? x.to_f : x) }
      when :int
        # TODO: Add support for hex, oct, & binary integers
        thingyWeReturn = thingyWeReturn.map { |x| ((x.is_a?(String) || x.is_a?(Numeric)) ? x.to_f : x) }
      when :bool
        thingyWeReturn = thingyWeReturn.map { |x| (x.is_a?(String) ? (x.strip.match?(@re.a(:o488_TRUEx)) ? true : (x.strip.match?(@re.a(:o488_FALSEx)) ? false : nil)) : x) }
    end
  end
  if !(@gblOpt[:result_split]) then  # If we didn't split, then we return a scaler
    thingyWeReturn = thingyWeReturn.first
  end
  PrintyPrintyBangBang.instance.logPrinter(4, "DEBUG-4: Result we return: #{thingyWeReturn.to_s[0..100].inspect}", self)
  @results.push( { :name    => @gblOpt[:name],
                   :cmd_str => (@gblOpt[:store_cmd]         ? strToSend      : nil),
                   :ret_val => (@gblOpt[:store_results]     ? thingyWeReturn : nil),
                   :raw_str => (@gblOpt[:store_raw_results] ? strWeGot       : nil)
                 })
  if @gblOpt[:store_last_in_ans] then
    @varList['ANS'] = thingyWeReturn
  end
  if @gblOpt[:store_named_in_var] && @gblOpt[:name] then
    @varList[@gblOpt[:name]] = thingyWeReturn
  end
  if @gblOpt[:result_type] && @gblOpt[:print_result] then
    PrintyPrintyBangBang.instance.outPrinter(thingyWeReturn.to_s, newline=false)
  end
  if @gblOpt[:delay_after_complete] > 0 then
    PrintyPrintyBangBang.instance.logPrinter(4, "DEBUG-4: DELAY: between_timeout = #{@gblOpt[:delay_after_complete]}ms.", self)
    sleep(@gblOpt[:delay_after_complete]/1000.0)
  end
  return thingyWeReturn
end
expand(instr) click to toggle source

Return a new string with constructs like ${variable_name} & ${variable_name:default_value} expanded into the value of the variable(s).

# File src/mrSCPI.rb, line 668
def expand (instr)
  expCnt = 0
  instr.gsub!(@re.a(:mrs_varexp)) do |m|
    varName    = $1
    varDefault = $2
    expCnt += 1
    if @varList.member?(varName) then
      next @varList[varName]
    else
      if varDefault then
        next varDefault
      else
        PrintyPrintyBangBang.instance.logPrinter(1, "ERROR: Unknown variable (#{varName}) without default value!", self, 88)
        next s
      end
    end
  end
  return instr
end
result(index: -1, type: :ret_val) click to toggle source

After execution SCPI commands have several data elements stored, and this method provides access to that data.

  • index

    Specify SCPI command for which to return data.

    • An integer: Return the result at the given array index. Some notes:

      • This option is fast at O(1).

      • -1 is the last SCPI command

      • 0 is the first one.

    • A string: Return an array of all results with a matching :name ordered by index. Some notes:

      • An empty array is returned if no matches are found.

      • This option is slow at O(n) – n # results.

      • The option :store_named_in_var and the variable method are much faster; however, this only gets tht last result with the given name.

  • type

    A symbol specifing the data to return. The symbol must be one of:

    • :all

      A hash with all data

    • :name

      String with the command name/variable

    • :cmd_str

      String sent to the instrument

    • :ret_val

      Processed result from the command

    • :raw_str

      String received from the instrument

# File src/mrSCPI.rb, line 974
def result(index: -1, type: :ret_val)
  if index.instance_of?(String) then
    ret = @results.find_all { |x| x[:name] == index }
    if type == :all then
      return ret.clone
    else
      if !(ret.empty?) then
        return ret.map { |x| x[type] }.clone
      else
        return ret.clone
      end
    end
  else
    if type == :all then
      return @results[index].clone
    else
      return @results[index][type]
    end
  end
end
set(options=Hash.new) click to toggle source

Set state parameters – see the parameter list in the main documentation for the SCPIsession class.

# File src/mrSCPI.rb, line 519
def set(options=Hash.new)
  objectUnderConstruction = @gblOpt.empty?
  #---------------------------------------------------------------------------------------------------------------------------------------------------------------
  # Take care of pseudo-option :good_std_eot
  if options.member?(:good_std_eot) then
    if options[:good_std_eot] 
      options[:read_eot_sentinel] = "\n"
    else
      options[:read_eot_sentinel] = nil
    end
    options.delete(:good_std_eot)
  end
  #---------------------------------------------------------------------------------------------------------------------------------------------------------------
  # Take care of pseudo-options :result_macro_*
  { :result_macro_bin   => { :result_extract_block => false, :result_split => nil,  :result_chomp => false, :result_strip => false, :result_last_word => false, :result_type => :string, :print_max_len =>  nil, :print_debug => false },
    :result_macro_block => { :result_extract_block => true,  :result_split => nil,  :result_chomp => false, :result_strip => false, :result_last_word => false, :result_type => :string, :print_max_len =>  nil, :print_debug => false },
    :result_macro_ascii => { :result_extract_block => false, :result_split => nil,  :result_chomp => true,  :result_strip => true,  :result_last_word => false, :result_type => :string, :print_max_len =>  nil, :print_debug => false },
    :result_macro_debug => { :result_extract_block => false, :result_split => nil,  :result_chomp => true,  :result_strip => true,  :result_last_word => false, :result_type => :string, :print_max_len => 1024, :print_debug => true  },
    :result_macro_csv   => { :result_extract_block => false, :result_split => :csv, :result_chomp => true,  :result_strip => true,  :result_last_word => false, :result_type => :string, :print_max_len =>  nil, :print_debug => false },
  }.each do |macro_sym, macro_options|
    if options.member?(macro_sym) then
      macro_options.each do |macro_opt_sym, macro_opt_val|
        options[macro_opt_sym] = macro_opt_val
      end
      options.delete(macro_sym)
    end
  end
  #---------------------------------------------------------------------------------------------------------------------------------------------------------------
  # Take care of pseudo-options for PrintyPrintyBangBang
  PrintyPrintyBangBang.instance.set(options)
  #---------------------------------------------------------------------------------------------------------------------------------------------------------------
  # Take care of pseudo-option :echo
  if options.member?(:echo) then
    options[:print_cmd] = options[:echo]
    options[:print_result] = options[:echo]
    options.delete(:echo)
  end
  #---------------------------------------------------------------------------------------------------------------------------------------------------------------
  # Take care of pseudo-option :url -> zap it and expand it into :net_protocol, :ip_address, :net_port
  if options.member?(:url) then
    urlBits = SCPIrcFile.instance.urlParser(options[:url])
    if !(urlBits.nil?) then
      urlBits.each do |k, v|
        if !(v.nil?) then
          if (options.member?(k)) then
            PrintyPrintyBangBang.instance.logPrinter(3, "INFO: Explicit #{k.inspect} option (#{options[k].inspect}) overrode value in URL: #{options[:url].inspect}", self)
          else
            options[k] = v;
          end
        end
      end
    end
    options.delete(:url)
  end
  #---------------------------------------------------------------------------------------------------------------------------------------------------------------
  # Set values provided in arguments
  options.each do |k, v|
    if @gblOptReqNew.member?(k) || @gblOptReqRun.member?(k) || @gblOptReqPsu.member?(k) then
      if !(objectUnderConstruction) && @gblOptReqNew.member?(k) then
        PrintyPrintyBangBang.instance.logPrinter(1, "ERROR: Option can't be set post new: #{k.inspect}", self, 71)
      end
      @gblOpt[k] = v
    else
      PrintyPrintyBangBang.instance.logPrinter(1, "ERROR: Unknown Session Option: #{k.inspect} => #{v.inspect}", self, 72)
    end
  end
  #---------------------------------------------------------------------------------------------------------------------------------------------------------------
  # If we are constructing the object, then work harder
  if objectUnderConstruction then
    if !(@gblOpt.member?(:net_protocol)) then
      @gblOpt[:net_protocol] = :raw
    end
    # Apply rules to set unset options
    { :net_port                 => {:file=> nil, :raw=> 5025, :soip=> nil, :plgx=> 1234, :lxi => nil, :t3k=>  80},
      :delay_after_complete     => {:file=>   0, :raw=>    0, :soip=> 100, :plgx=>   50, :lxi =>   0, :t3k=> 200},
      :delay_before_first_read  => {:file=>   0, :raw=>  100, :soip=>  50, :plgx=>   10, :lxi =>   0, :t3k=>   0},
      :read_retry_delay         => {:file=>   0, :raw=>  200, :soip=> 200, :plgx=>  100, :lxi =>   0, :t3k=>   0},
      :read_timeout_first_byte  => {:file=>   0, :raw=> 1000, :soip=> 500, :plgx=>  600, :lxi =>   0, :t3k=>   0},
      :read_timeout_next_byte   => {:file=>   0, :raw=> 2000, :soip=> 100, :plgx=>   50, :lxi =>   0, :t3k=>   0}
    }.each do |k, defs|
      if !(@gblOpt.member?(k)) || @gblOpt[k].nil? then
        @gblOpt[k] = defs[@gblOpt[:net_protocol]]
        if @gblOpt[k].nil? then
          PrintyPrintyBangBang.instance.logPrinter(2, "WARNING: Could not set #{k} to a default value!", self)
        else
          PrintyPrintyBangBang.instance.logPrinter(4, "DEBUG-4: Successfully set #{k} to a default value!", self)
        end
      end
    end
    # Make sure all options required by new are set and valid
    @gblOptReqNew.each do |k, validator|
      if !(validator.call(@gblOpt[k])) then
        PrintyPrintyBangBang.instance.logPrinter(1, "ERROR: Option required by new is invalid: #{k} = #{@gblOpt[k].inspect}!", self, 73)
      end
    end
    if [:lxi].member?(@gblOpt[:net_protocol]) then # (TODO: Future Feature)
      PrintyPrintyBangBang.instance.logPrinter(1, "ERROR: :lxi is not currently supported -- it will be someday!!", self, 86)
    end
    PrintyPrintyBangBang.instance.logPrinter(4, "DEBUG-4: Object fully constructed.", self)
  else
  end
  #---------------------------------------------------------------------------------------------------------------------------------------------------------------
  @gblOpt.keys.sort.each do |k|
    PrintyPrintyBangBang.instance.logPrinter(8, "DEBUG-8: @gblOpt: #{(k.to_s+' ').ljust(25, '.')} #{@gblOpt[k].inspect}", self)
  end
  #---------------------------------------------------------------------------------------------------------------------------------------------------------------
  # If we got a :cmd & :execute_on_cmd is on, then we attempt to execute
  if options.member?(:cmd) && @gblOpt[:execute_on_cmd] then
    PrintyPrintyBangBang.instance.logPrinter(4, "DEBUG-4: Attempting automatic execution", self)
    return execute()
  end

end
variable(name, value=nil) click to toggle source

Access, or set when value is non-nil, a SCPIsession variable.

# File src/mrSCPI.rb, line 653
def variable (name, value=nil)
  if value.nil? then
    if @varList.member?(name) then
      return @varList[name]
    else
      PrintyPrintyBangBang.instance.logPrinter(1, "ERROR: Result not found with given name: #{name.inspect}!", self, 75)
    end
  else
    @varList[name]  = value
    return value
  end
end