class SDN::CLI::Provisioner

Attributes

addr[R]
ns[R]
sdn[R]
win[R]

Public Class Methods

new(port, addr = nil) click to toggle source
# File lib/sdn/cli/provisioner.rb, line 8
def initialize(port, addr = nil)
  @sdn = Client.new(port)
  @reversed = false
  @pulse_count = 10

  if addr
    @addr = addr = Message.parse_address(addr)
  else
    puts "Discovering motor..."
    message = sdn.ensure(Message::GetNodeAddr.new)
    puts "Found #{message.node_type}"
    @addr = addr = message.src
  end

  puts "Preparing to provision motor #{Message.print_address(addr)}"

  message = sdn.ensure(Message::GetNodeLabel.new(addr))

  node_type = message.node_type
  @ns = ns = node_type == :st50ilt2 ? Message::ILT2 : Message

  print "Motor is currently labeled '#{message.label}'; what would you like to change it to (blank to leave alone)? "
  new_label = STDIN.gets

  unless new_label == "\n"
    new_label.strip!
    sdn.ensure(ns::SetNodeLabel.new(addr, new_label))
  end

  # make sure some limits exist
  unless ns == Message::ILT2
    limits = sdn.ensure(Message::GetMotorLimits.new(addr))
    if limits.up_limit.nil? || limits.down_limit.nil?
      sdn.ensure(Message::SetMotorLimits.new(addr, :delete, :up))
      sdn.ensure(Message::SetMotorLimits.new(addr, :delete, :down))
      sdn.ensure(Message::SetMotorLimits.new(addr, :current_position, :up))
      sdn.ensure(Message::SetMotorLimits.new(addr, :specified_position, :down, 500))
    end
  end

  Curses.init_screen
  begin
    Curses.noecho
    Curses.crmode
    Curses.nonl
    Curses.curs_set(0)
    @win = Curses.stdscr

    process
  rescue => e
    win.setpos(0, 0)
    win.addstr(e.inspect)
    win.addstr("\n")
    win.addstr(e.backtrace.join("\n"))
    win.refresh
    sleep 10
  ensure
    Curses.close_screen
  end
end

Public Instance Methods

ilt2?() click to toggle source
# File lib/sdn/cli/provisioner.rb, line 225
def ilt2?
  ns == Message::ILT2
end
print_help() click to toggle source
process() click to toggle source
# File lib/sdn/cli/provisioner.rb, line 69
def process
  win.keypad = true
  print_help
  refresh

  loop do
    char = win.getch
    case char
    when 27 # Esc
      stop
      refresh
    when Curses::Key::UP
      if ilt2?
        sdn.ensure(Message::ILT2::SetMotorPosition.new(addr, :up_limit))
      else
        sdn.ensure(Message::MoveTo.new(addr, :up_limit))
      end
      wait_for_stop
    when Curses::Key::DOWN
      if ilt2?
        sdn.ensure(Message::ILT2::SetMotorPosition.new(addr, :down_limit))
      else
        sdn.ensure(Message::MoveTo.new(addr, :down_limit))
      end
      wait_for_stop
    when Curses::Key::LEFT
      if @pos < @pulse_count
        sdn.ensure(Message::ILT2::SetMotorSettings.new(addr, reversed_int, @limit + @pulse_count - @pos, @pulse_count))
        refresh
      end
      sdn.ensure(Message::ILT2::SetMotorPosition.new(addr, :jog_up_pulses, @pulse_count))
      wait_for_stop
    when Curses::Key::RIGHT
      if @limit - @pos < @pulse_count
        sdn.ensure(Message::ILT2::SetMotorSettings.new(addr, reversed_int, @pos + @pulse_count, @pos))
        refresh
      end
      sdn.ensure(Message::ILT2::SetMotorPosition.new(addr, :jog_down_pulses, @pulse_count))
      wait_for_stop
    when 'u'
      if ilt2?
        sdn.ensure(Message::ILT2::SetMotorSettings.new(addr, reversed_int, @limit - @pos, 0))
      else
        sdn.ensure(Message::SetMotorLimits.new(addr, :current_position, :up))
      end
      refresh
    when 'l'
      if ilt2?
        sdn.ensure(Message::ILT2::SetMotorSettings.new(addr, reversed_int, @pos, @pos))
      else
        sdn.ensure(Message::SetMotorLimits.new(addr, :current_position, :down))
      end
      refresh
    when 'r'
      @reversed = !@reversed
      if ilt2?
        sdn.ensure(Message::ILT2::SetMotorSettings.new(addr, reversed_int, @limit, @limit - @pos))
      else
        sdn.ensure(Message::SetMotorDirection.new(addr, @reversed ? :reversed : :standard))
      end
      refresh
    when 'R'
      next unless ilt2?
      @reversed = !@reversed
      sdn.ensure(Message::ILT2::SetMotorSettings.new(addr, reversed_int, @limit, @pos))
      refresh
    when '<'
      @pulse_count /= 2 if @pulse_count > 5
      print_help
    when '>'
      @pulse_count *= 2
      print_help
    when 'q'
      break
    end
  end
end
refresh() click to toggle source
# File lib/sdn/cli/provisioner.rb, line 197
def refresh
  pos = sdn.ensure(ns::GetMotorPosition.new(addr))
  @pos = pos.position_pulses
  if ilt2?
    settings = sdn.ensure(Message::ILT2::GetMotorSettings.new(addr))
    @limit = settings.limit
  else
    limits = sdn.ensure(Message::GetMotorLimits.new(addr))
    @limit = limits.down_limit
    direction = sdn.ensure(Message::GetMotorDirection.new(addr))
    @reversed = direction.direction == :reversed
  end

  win.setpos(14, 0)
  win.addstr("Position: #{@pos}\n")
  win.addstr("Limit: #{@limit}\n")
  win.addstr("Reversed: #{@reversed}\n")
  win.refresh
end
reversed_int() click to toggle source
# File lib/sdn/cli/provisioner.rb, line 229
def reversed_int
  @reversed ? 1 : 0
end
stop() click to toggle source
# File lib/sdn/cli/provisioner.rb, line 217
def stop
  if ilt2?
    sdn.ensure(Message::ILT2::SetMotorPosition.new(addr, :stop))
  else
    sdn.ensure(Message::Stop.new(addr))
  end
end
wait_for_stop() click to toggle source
# File lib/sdn/cli/provisioner.rb, line 170
def wait_for_stop
  win.setpos(13, 0)
  win.addstr("Moving...\n")
  loop do
    win.nodelay = true
    stop if win.getch == 27 # Esc
    sdn.send(ns::GetMotorPosition.new(addr))
    sdn.receive do |message|
      next unless message.is_a?(ns::PostMotorPosition)
      last_pos = @pos
      @pos = message.position_pulses
      win.setpos(14, 0)
      win.addstr("Position: #{@pos}\n")

      if last_pos == @pos
        win.setpos(13, 0)
        win.addstr("\n")
        win.nodelay = false
        refresh
        return
      end
    end
    sleep 0.1
    
  end
end