somfy_sdn 2.1.5 → 2.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/exe/somfy_sdn +69 -0
- data/lib/sdn/cli/mqtt/group.rb +12 -10
- data/lib/sdn/cli/mqtt/motor.rb +19 -14
- data/lib/sdn/cli/mqtt/p_queue.rb +18 -0
- data/lib/sdn/cli/mqtt/read.rb +125 -126
- data/lib/sdn/cli/mqtt/subscriptions.rb +186 -140
- data/lib/sdn/cli/mqtt/write.rb +39 -34
- data/lib/sdn/cli/mqtt.rb +84 -53
- data/lib/sdn/cli/provisioner.rb +56 -33
- data/lib/sdn/cli/simulator.rb +99 -65
- data/lib/sdn/client.rb +38 -24
- data/lib/sdn/message/control.rb +60 -30
- data/lib/sdn/message/get.rb +6 -2
- data/lib/sdn/message/helpers.rb +23 -22
- data/lib/sdn/message/ilt2/get.rb +6 -3
- data/lib/sdn/message/ilt2/master_control.rb +10 -7
- data/lib/sdn/message/ilt2/post.rb +7 -5
- data/lib/sdn/message/ilt2/set.rb +28 -19
- data/lib/sdn/message/post.rb +3 -5
- data/lib/sdn/message/set.rb +48 -22
- data/lib/sdn/message.rb +50 -34
- data/lib/sdn/version.rb +3 -1
- data/lib/sdn.rb +18 -12
- data/lib/somfy_sdn.rb +3 -1
- metadata +43 -13
- data/bin/somfy_sdn +0 -60
    
        data/lib/sdn/cli/mqtt.rb
    CHANGED
    
    | @@ -1,12 +1,15 @@ | |
| 1 | 
            -
             | 
| 2 | 
            -
            require 'uri'
         | 
| 3 | 
            -
            require 'set'
         | 
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 4 2 |  | 
| 5 | 
            -
            require  | 
| 6 | 
            -
            require  | 
| 7 | 
            -
            require  | 
| 8 | 
            -
             | 
| 9 | 
            -
            require  | 
| 3 | 
            +
            require "mqtt"
         | 
| 4 | 
            +
            require "uri"
         | 
| 5 | 
            +
            require "set"
         | 
| 6 | 
            +
             | 
| 7 | 
            +
            require "sdn/cli/mqtt/group"
         | 
| 8 | 
            +
            require "sdn/cli/mqtt/motor"
         | 
| 9 | 
            +
            require "sdn/cli/mqtt/p_queue"
         | 
| 10 | 
            +
            require "sdn/cli/mqtt/read"
         | 
| 11 | 
            +
            require "sdn/cli/mqtt/write"
         | 
| 12 | 
            +
            require "sdn/cli/mqtt/subscriptions"
         | 
| 10 13 |  | 
| 11 14 | 
             
            module SDN
         | 
| 12 15 | 
             
              module CLI
         | 
| @@ -22,7 +25,12 @@ module SDN | |
| 22 25 |  | 
| 23 26 | 
             
                  attr_reader :motors, :groups
         | 
| 24 27 |  | 
| 25 | 
            -
                  def initialize( | 
| 28 | 
            +
                  def initialize(sdn,
         | 
| 29 | 
            +
                                 mqtt_uri,
         | 
| 30 | 
            +
                                 device_id: "somfy",
         | 
| 31 | 
            +
                                 base_topic: "homie",
         | 
| 32 | 
            +
                                 auto_discover: true,
         | 
| 33 | 
            +
                                 known_motors: [])
         | 
| 26 34 | 
             
                    @base_topic = "#{base_topic}/#{device_id}"
         | 
| 27 35 | 
             
                    @mqtt = ::MQTT::Client.new(mqtt_uri)
         | 
| 28 36 | 
             
                    @mqtt.set_will("#{@base_topic}/$state", "lost", retain: true)
         | 
| @@ -33,7 +41,7 @@ module SDN | |
| 33 41 |  | 
| 34 42 | 
             
                    @mutex = Mutex.new
         | 
| 35 43 | 
             
                    @cond = ConditionVariable.new
         | 
| 36 | 
            -
                    @ | 
| 44 | 
            +
                    @queue = PQueue.new
         | 
| 37 45 | 
             
                    @response_pending = false
         | 
| 38 46 | 
             
                    @broadcast_pending = false
         | 
| 39 47 |  | 
| @@ -43,11 +51,16 @@ module SDN | |
| 43 51 | 
             
                    clear_tree(@base_topic)
         | 
| 44 52 | 
             
                    publish_basic_attributes
         | 
| 45 53 |  | 
| 46 | 
            -
                    @sdn =  | 
| 54 | 
            +
                    @sdn = sdn
         | 
| 55 | 
            +
             | 
| 56 | 
            +
                    known_motors&.each do |addr|
         | 
| 57 | 
            +
                      addr = Message.parse_address(addr)
         | 
| 58 | 
            +
                      @queue.push(MessageAndRetries.new(Message::GetMotorPosition.new(addr), 5, 0))
         | 
| 59 | 
            +
                    end
         | 
| 47 60 |  | 
| 48 61 | 
             
                    Thread.abort_on_exception = true
         | 
| 49 | 
            -
                     | 
| 50 | 
            -
                     | 
| 62 | 
            +
                    Thread.new { read }
         | 
| 63 | 
            +
                    Thread.new { write }
         | 
| 51 64 | 
             
                    @mqtt.get { |packet| handle_message(packet.topic, packet.payload) }
         | 
| 52 65 | 
             
                  end
         | 
| 53 66 |  | 
| @@ -59,20 +72,19 @@ module SDN | |
| 59 72 | 
             
                    @mqtt.subscribe("#{@base_topic}/#{topic}")
         | 
| 60 73 | 
             
                  end
         | 
| 61 74 |  | 
| 62 | 
            -
                  def enqueue(message | 
| 75 | 
            +
                  def enqueue(message)
         | 
| 63 76 | 
             
                    @mutex.synchronize do
         | 
| 64 | 
            -
                       | 
| 65 | 
            -
             | 
| 66 | 
            -
             | 
| 67 | 
            -
             | 
| 68 | 
            -
                      end
         | 
| 77 | 
            +
                      break if @queue.include?(message)
         | 
| 78 | 
            +
             | 
| 79 | 
            +
                      @queue.push(message)
         | 
| 80 | 
            +
                      @cond.signal
         | 
| 69 81 | 
             
                    end
         | 
| 70 82 | 
             
                  end
         | 
| 71 83 |  | 
| 72 84 | 
             
                  def clear_tree(topic)
         | 
| 73 85 | 
             
                    @mqtt.subscribe("#{topic}/#")
         | 
| 74 86 | 
             
                    @mqtt.unsubscribe("#{topic}/#", wait_for_ack: true)
         | 
| 75 | 
            -
                     | 
| 87 | 
            +
                    until @mqtt.queue_empty?
         | 
| 76 88 | 
             
                      packet = @mqtt.get
         | 
| 77 89 | 
             
                      @mqtt.publish(packet.topic, nil, retain: true)
         | 
| 78 90 | 
             
                    end
         | 
| @@ -136,7 +148,7 @@ module SDN | |
| 136 148 | 
             
                    @mqtt.batch_publish do
         | 
| 137 149 | 
             
                      publish("#{addr}/$name", addr)
         | 
| 138 150 | 
             
                      publish("#{addr}/$type", node_type.to_s)
         | 
| 139 | 
            -
                      properties = %w | 
| 151 | 
            +
                      properties = %w[
         | 
| 140 152 | 
             
                        discover
         | 
| 141 153 | 
             
                        label
         | 
| 142 154 | 
             
                        state
         | 
| @@ -149,19 +161,17 @@ module SDN | |
| 149 161 | 
             
                        down-limit
         | 
| 150 162 | 
             
                        groups
         | 
| 151 163 | 
             
                        last-direction
         | 
| 152 | 
            -
                       | 
| 164 | 
            +
                      ] + (1..16).map { |ip| ["ip#{ip}-pulses", "ip#{ip}-percent"] }.flatten
         | 
| 153 165 |  | 
| 154 166 | 
             
                      unless node_type == :st50ilt2
         | 
| 155 | 
            -
                        properties. | 
| 156 | 
            -
             | 
| 157 | 
            -
             | 
| 158 | 
            -
             | 
| 159 | 
            -
             | 
| 160 | 
            -
             | 
| 161 | 
            -
             | 
| 162 | 
            -
             | 
| 163 | 
            -
                          slow-speed
         | 
| 164 | 
            -
                        }
         | 
| 167 | 
            +
                        properties.push("reset",
         | 
| 168 | 
            +
                                        "last-action-source",
         | 
| 169 | 
            +
                                        "last-action-cause",
         | 
| 170 | 
            +
                                        "up-limit",
         | 
| 171 | 
            +
                                        "direction",
         | 
| 172 | 
            +
                                        "up-speed",
         | 
| 173 | 
            +
                                        "down-speed",
         | 
| 174 | 
            +
                                        "slow-speed")
         | 
| 165 175 | 
             
                      end
         | 
| 166 176 |  | 
| 167 177 | 
             
                      publish("#{addr}/$properties", properties.join(","))
         | 
| @@ -178,7 +188,7 @@ module SDN | |
| 178 188 |  | 
| 179 189 | 
             
                      publish("#{addr}/state/$name", "Current state of the motor")
         | 
| 180 190 | 
             
                      publish("#{addr}/state/$datatype", "enum")
         | 
| 181 | 
            -
                      publish("#{addr}/state/$format", Message::PostMotorStatus::STATE.keys.join( | 
| 191 | 
            +
                      publish("#{addr}/state/$format", Message::PostMotorStatus::STATE.keys.join(","))
         | 
| 182 192 |  | 
| 183 193 | 
             
                      publish("#{addr}/control/$name", "Control motor")
         | 
| 184 194 | 
             
                      publish("#{addr}/control/$datatype", "enum")
         | 
| @@ -226,22 +236,22 @@ module SDN | |
| 226 236 |  | 
| 227 237 | 
             
                      publish("#{addr}/last-direction/$name", "Direction of last motion")
         | 
| 228 238 | 
             
                      publish("#{addr}/last-direction/$datatype", "enum")
         | 
| 229 | 
            -
                      publish("#{addr}/last-direction/$format", Message::PostMotorStatus::DIRECTION.keys.join( | 
| 239 | 
            +
                      publish("#{addr}/last-direction/$format", Message::PostMotorStatus::DIRECTION.keys.join(","))
         | 
| 230 240 |  | 
| 231 241 | 
             
                      unless node_type == :st50ilt2
         | 
| 232 242 | 
             
                        publish("#{addr}/reset/$name", "Recall factory settings")
         | 
| 233 243 | 
             
                        publish("#{addr}/reset/$datatype", "enum")
         | 
| 234 | 
            -
                        publish("#{addr}/reset/$format", Message::SetFactoryDefault::RESET.keys.join( | 
| 244 | 
            +
                        publish("#{addr}/reset/$format", Message::SetFactoryDefault::RESET.keys.join(","))
         | 
| 235 245 | 
             
                        publish("#{addr}/reset/$settable", "true")
         | 
| 236 246 | 
             
                        publish("#{addr}/reset/$retained", "false")
         | 
| 237 247 |  | 
| 238 248 | 
             
                        publish("#{addr}/last-action-source/$name", "Source of last action")
         | 
| 239 249 | 
             
                        publish("#{addr}/last-action-source/$datatype", "enum")
         | 
| 240 | 
            -
                        publish("#{addr}/last-action-source/$format", Message::PostMotorStatus::SOURCE.keys.join( | 
| 250 | 
            +
                        publish("#{addr}/last-action-source/$format", Message::PostMotorStatus::SOURCE.keys.join(","))
         | 
| 241 251 |  | 
| 242 252 | 
             
                        publish("#{addr}/last-action-cause/$name", "Cause of last action")
         | 
| 243 253 | 
             
                        publish("#{addr}/last-action-cause/$datatype", "enum")
         | 
| 244 | 
            -
                        publish("#{addr}/last-action-cause/$format", Message::PostMotorStatus::CAUSE.keys.join( | 
| 254 | 
            +
                        publish("#{addr}/last-action-cause/$format", Message::PostMotorStatus::CAUSE.keys.join(","))
         | 
| 245 255 |  | 
| 246 256 | 
             
                        publish("#{addr}/up-limit/$name", "Up limit (always = 0)")
         | 
| 247 257 | 
             
                        publish("#{addr}/up-limit/$datatype", "integer")
         | 
| @@ -298,20 +308,39 @@ module SDN | |
| 298 308 |  | 
| 299 309 | 
             
                    sdn_addr = Message.parse_address(addr)
         | 
| 300 310 | 
             
                    @mutex.synchronize do
         | 
| 301 | 
            -
                       | 
| 311 | 
            +
                      # message priorities are:
         | 
| 312 | 
            +
                      # 0 - control
         | 
| 313 | 
            +
                      # 1 - follow-up (i.e. get position after control)
         | 
| 314 | 
            +
                      # 2 - get basic motor info
         | 
| 315 | 
            +
                      # 3 - get advanced motor info
         | 
| 316 | 
            +
                      # 4 - get group 1
         | 
| 317 | 
            +
                      # 5 - get ip 1
         | 
| 318 | 
            +
                      # 6 - get group 2
         | 
| 319 | 
            +
                      # 7 - get ip 2
         | 
| 320 | 
            +
                      # ...
         | 
| 321 | 
            +
                      # 50 - discover
         | 
| 322 | 
            +
             | 
| 323 | 
            +
                      # The Group and IP sorting makes it so you quickly get the most commonly used group
         | 
| 324 | 
            +
                      # and IP addresses, while the almost-never-used ones are pushed to the bottom of the list
         | 
| 325 | 
            +
             | 
| 326 | 
            +
                      @queue.push(MessageAndRetries.new(Message::GetNodeLabel.new(sdn_addr), 5, 2))
         | 
| 327 | 
            +
             | 
| 302 328 | 
             
                      case node_type
         | 
| 303 | 
            -
                      when :st30
         | 
| 304 | 
            -
                        @ | 
| 305 | 
            -
                        @ | 
| 306 | 
            -
                        @ | 
| 307 | 
            -
                        @ | 
| 308 | 
            -
                        (1..16).each { |ip|  | 
| 329 | 
            +
                      when :st30, 0x20 # no idea why 0x20, but that's what I get
         | 
| 330 | 
            +
                        @queue.push(MessageAndRetries.new(Message::GetMotorStatus.new(sdn_addr), 5, 2))
         | 
| 331 | 
            +
                        @queue.push(MessageAndRetries.new(Message::GetMotorLimits.new(sdn_addr), 5, 2))
         | 
| 332 | 
            +
                        @queue.push(MessageAndRetries.new(Message::GetMotorDirection.new(sdn_addr), 5, 3))
         | 
| 333 | 
            +
                        @queue.push(MessageAndRetries.new(Message::GetMotorRollingSpeed.new(sdn_addr), 5, 3))
         | 
| 334 | 
            +
                        (1..16).each { |ip| 
         | 
| 335 | 
            +
                        @queue.push(MessageAndRetries.new(Message::GetMotorIP.new(sdn_addr, ip), 5, 2 * ip + 3)) }
         | 
| 309 336 | 
             
                      when :st50ilt2
         | 
| 310 | 
            -
                        @ | 
| 311 | 
            -
                        @ | 
| 312 | 
            -
                        (1..16).each  | 
| 337 | 
            +
                        @queue.push(MessageAndRetries.new(Message::ILT2::GetMotorSettings.new(sdn_addr), 5, 2))
         | 
| 338 | 
            +
                        @queue.push(MessageAndRetries.new(Message::ILT2::GetMotorPosition.new(sdn_addr), 5, 2))
         | 
| 339 | 
            +
                        (1..16).each do |ip|
         | 
| 340 | 
            +
                          @queue.push(MessageAndRetries.new(Message::ILT2::GetMotorIP.new(sdn_addr, ip), 5, 2 * ip + 3))
         | 
| 341 | 
            +
                        end
         | 
| 313 342 | 
             
                      end
         | 
| 314 | 
            -
                      (1..16).each { |g| @ | 
| 343 | 
            +
                      (1..16).each { |g| @queue.push(MessageAndRetries.new(Message::GetGroupAddr.new(sdn_addr, g), 5, 2 * g + 2)) }
         | 
| 315 344 |  | 
| 316 345 | 
             
                      @cond.signal
         | 
| 317 346 | 
             
                    end
         | 
| @@ -320,19 +349,21 @@ module SDN | |
| 320 349 | 
             
                  end
         | 
| 321 350 |  | 
| 322 351 | 
             
                  def touch_group(group_addr)
         | 
| 323 | 
            -
                    group = @groups[Message.print_address(group_addr). | 
| 352 | 
            +
                    group = @groups[Message.print_address(group_addr).delete(".")]
         | 
| 324 353 | 
             
                    group&.publish(:motors, group.motors_string)
         | 
| 325 354 | 
             
                  end
         | 
| 326 355 |  | 
| 327 356 | 
             
                  def add_group(addr)
         | 
| 328 | 
            -
                    addr = addr. | 
| 357 | 
            +
                    addr = addr.delete(".")
         | 
| 329 358 | 
             
                    group = @groups[addr]
         | 
| 330 359 | 
             
                    return group if group
         | 
| 331 360 |  | 
| 332 361 | 
             
                    @mqtt.batch_publish do
         | 
| 333 362 | 
             
                      publish("#{addr}/$name", addr)
         | 
| 334 363 | 
             
                      publish("#{addr}/$type", "Shade Group")
         | 
| 335 | 
            -
                      publish("#{addr}/$properties", | 
| 364 | 
            +
                      publish("#{addr}/$properties",
         | 
| 365 | 
            +
                              "discover,control,jog-ms,jog-pulses,position-pulses,position-percent," \
         | 
| 366 | 
            +
                              "ip,reset,state,last-direction,motors")
         | 
| 336 367 |  | 
| 337 368 | 
             
                      publish("#{addr}/discover/$name", "Trigger Motor Discovery")
         | 
| 338 369 | 
             
                      publish("#{addr}/discover/$datatype", "enum")
         | 
| @@ -379,11 +410,11 @@ module SDN | |
| 379 410 |  | 
| 380 411 | 
             
                      publish("#{addr}/state/$name", "State of the motors")
         | 
| 381 412 | 
             
                      publish("#{addr}/state/$datatype", "enum")
         | 
| 382 | 
            -
                      publish("#{addr}/state/$format", Message::PostMotorStatus::STATE.keys.join( | 
| 413 | 
            +
                      publish("#{addr}/state/$format", "#{Message::PostMotorStatus::STATE.keys.join(",")},mixed")
         | 
| 383 414 |  | 
| 384 415 | 
             
                      publish("#{addr}/last-direction/$name", "Direction of last motion")
         | 
| 385 416 | 
             
                      publish("#{addr}/last-direction/$datatype", "enum")
         | 
| 386 | 
            -
                      publish("#{addr}/last-direction/$format", Message::PostMotorStatus::DIRECTION.keys.join( | 
| 417 | 
            +
                      publish("#{addr}/last-direction/$format", "#{Message::PostMotorStatus::DIRECTION.keys.join(",")},mixed")
         | 
| 387 418 |  | 
| 388 419 | 
             
                      publish("#{addr}/motors/$name", "Comma separated motor addresses that are members of this group")
         | 
| 389 420 | 
             
                      publish("#{addr}/motors/$datatype", "string")
         | 
    
        data/lib/sdn/cli/provisioner.rb
    CHANGED
    
    | @@ -1,12 +1,14 @@ | |
| 1 | 
            -
             | 
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            require "curses"
         | 
| 2 4 |  | 
| 3 5 | 
             
            module SDN
         | 
| 4 6 | 
             
              module CLI
         | 
| 5 7 | 
             
                class Provisioner
         | 
| 6 8 | 
             
                  attr_reader :win, :sdn, :addr, :ns
         | 
| 7 9 |  | 
| 8 | 
            -
                  def initialize( | 
| 9 | 
            -
                    @sdn =  | 
| 10 | 
            +
                  def initialize(sdn, addr = nil)
         | 
| 11 | 
            +
                    @sdn = sdn
         | 
| 10 12 | 
             
                    @reversed = false
         | 
| 11 13 | 
             
                    @pulse_count = 10
         | 
| 12 14 |  | 
| @@ -24,10 +26,11 @@ module SDN | |
| 24 26 | 
             
                    message = sdn.ensure(Message::GetNodeLabel.new(addr))
         | 
| 25 27 |  | 
| 26 28 | 
             
                    node_type = message.node_type
         | 
| 27 | 
            -
                    @ns = ns = node_type == :st50ilt2 ? Message::ILT2 : Message
         | 
| 29 | 
            +
                    @ns = ns = (node_type == :st50ilt2) ? Message::ILT2 : Message
         | 
| 28 30 |  | 
| 29 | 
            -
                    print "Motor is currently labeled '#{message.label}';  | 
| 30 | 
            -
             | 
| 31 | 
            +
                    print "Motor is currently labeled '#{message.label}'; " \
         | 
| 32 | 
            +
                          "what would you like to change it to (blank to leave alone)? "
         | 
| 33 | 
            +
                    new_label = $stdin.gets
         | 
| 31 34 |  | 
| 32 35 | 
             
                    unless new_label == "\n"
         | 
| 33 36 | 
             
                      new_label.strip!
         | 
| @@ -52,8 +55,10 @@ module SDN | |
| 52 55 | 
             
                      Curses.nonl
         | 
| 53 56 | 
             
                      Curses.curs_set(0)
         | 
| 54 57 | 
             
                      @win = Curses.stdscr
         | 
| 55 | 
            -
             | 
| 58 | 
            +
             | 
| 56 59 | 
             
                      process
         | 
| 60 | 
            +
                    rescue Interrupt
         | 
| 61 | 
            +
                      # exitting
         | 
| 57 62 | 
             
                    rescue => e
         | 
| 58 63 | 
             
                      win.setpos(0, 0)
         | 
| 59 64 | 
             
                      win.addstr(e.inspect)
         | 
| @@ -94,33 +99,44 @@ module SDN | |
| 94 99 | 
             
                        wait_for_stop
         | 
| 95 100 | 
             
                      when Curses::Key::LEFT
         | 
| 96 101 | 
             
                        if @pos < @pulse_count
         | 
| 97 | 
            -
                          sdn.ensure(Message::ILT2::SetMotorSettings.new(addr, | 
| 102 | 
            +
                          sdn.ensure(Message::ILT2::SetMotorSettings.new(addr,
         | 
| 103 | 
            +
                                                                         reversed_int,
         | 
| 104 | 
            +
                                                                         @limit + @pulse_count - @pos,
         | 
| 105 | 
            +
                                                                         @pulse_count))
         | 
| 98 106 | 
             
                          refresh
         | 
| 99 107 | 
             
                        end
         | 
| 100 | 
            -
                         | 
| 108 | 
            +
                        if ilt2?
         | 
| 109 | 
            +
                          sdn.ensure(Message::ILT2::SetMotorPosition.new(addr, :jog_up_pulses, @pulse_count))
         | 
| 110 | 
            +
                        else
         | 
| 111 | 
            +
                          sdn.ensure(Message::MoveOf.new(addr, :jog_up_pulses, @pulse_count))
         | 
| 112 | 
            +
                        end
         | 
| 101 113 | 
             
                        wait_for_stop
         | 
| 102 114 | 
             
                      when Curses::Key::RIGHT
         | 
| 103 115 | 
             
                        if @limit - @pos < @pulse_count
         | 
| 104 116 | 
             
                          sdn.ensure(Message::ILT2::SetMotorSettings.new(addr, reversed_int, @pos + @pulse_count, @pos))
         | 
| 105 117 | 
             
                          refresh
         | 
| 106 118 | 
             
                        end
         | 
| 107 | 
            -
                         | 
| 119 | 
            +
                        if ilt2?
         | 
| 120 | 
            +
                          sdn.ensure(Message::ILT2::SetMotorPosition.new(addr, :jog_down_pulses, @pulse_count))
         | 
| 121 | 
            +
                        else
         | 
| 122 | 
            +
                          sdn.ensure(Message::MoveOf.new(addr, :jog_down_pulses, @pulse_count))
         | 
| 123 | 
            +
                        end
         | 
| 108 124 | 
             
                        wait_for_stop
         | 
| 109 | 
            -
                      when  | 
| 125 | 
            +
                      when "u"
         | 
| 110 126 | 
             
                        if ilt2?
         | 
| 111 127 | 
             
                          sdn.ensure(Message::ILT2::SetMotorSettings.new(addr, reversed_int, @limit - @pos, 0))
         | 
| 112 128 | 
             
                        else
         | 
| 113 129 | 
             
                          sdn.ensure(Message::SetMotorLimits.new(addr, :current_position, :up))
         | 
| 114 130 | 
             
                        end
         | 
| 115 131 | 
             
                        refresh
         | 
| 116 | 
            -
                      when  | 
| 132 | 
            +
                      when "l"
         | 
| 117 133 | 
             
                        if ilt2?
         | 
| 118 134 | 
             
                          sdn.ensure(Message::ILT2::SetMotorSettings.new(addr, reversed_int, @pos, @pos))
         | 
| 119 135 | 
             
                        else
         | 
| 120 136 | 
             
                          sdn.ensure(Message::SetMotorLimits.new(addr, :current_position, :down))
         | 
| 121 137 | 
             
                        end
         | 
| 122 138 | 
             
                        refresh
         | 
| 123 | 
            -
                      when  | 
| 139 | 
            +
                      when "r"
         | 
| 124 140 | 
             
                        @reversed = !@reversed
         | 
| 125 141 | 
             
                        if ilt2?
         | 
| 126 142 | 
             
                          sdn.ensure(Message::ILT2::SetMotorSettings.new(addr, reversed_int, @limit, @limit - @pos))
         | 
| @@ -128,18 +144,24 @@ module SDN | |
| 128 144 | 
             
                          sdn.ensure(Message::SetMotorDirection.new(addr, @reversed ? :reversed : :standard))
         | 
| 129 145 | 
             
                        end
         | 
| 130 146 | 
             
                        refresh
         | 
| 131 | 
            -
                      when  | 
| 147 | 
            +
                      when "R"
         | 
| 132 148 | 
             
                        next unless ilt2?
         | 
| 149 | 
            +
             | 
| 133 150 | 
             
                        @reversed = !@reversed
         | 
| 134 151 | 
             
                        sdn.ensure(Message::ILT2::SetMotorSettings.new(addr, reversed_int, @limit, @pos))
         | 
| 135 152 | 
             
                        refresh
         | 
| 136 | 
            -
                      when  | 
| 153 | 
            +
                      when "!"
         | 
| 154 | 
            +
                        next if ilt2?
         | 
| 155 | 
            +
             | 
| 156 | 
            +
                        sdn.send(Message::SetFactoryDefault.new(addr))
         | 
| 157 | 
            +
                        break
         | 
| 158 | 
            +
                      when "<"
         | 
| 137 159 | 
             
                        @pulse_count /= 2 if @pulse_count > 5
         | 
| 138 160 | 
             
                        print_help
         | 
| 139 | 
            -
                      when  | 
| 161 | 
            +
                      when ">"
         | 
| 140 162 | 
             
                        @pulse_count *= 2
         | 
| 141 163 | 
             
                        print_help
         | 
| 142 | 
            -
                      when  | 
| 164 | 
            +
                      when "q"
         | 
| 143 165 | 
             
                        break
         | 
| 144 166 | 
             
                      end
         | 
| 145 167 | 
             
                    end
         | 
| @@ -147,27 +169,29 @@ module SDN | |
| 147 169 |  | 
| 148 170 | 
             
                  def print_help
         | 
| 149 171 | 
             
                    win.setpos(0, 0)
         | 
| 150 | 
            -
                    win.addstr( | 
| 151 | 
            -
            Move the motor. Keys:
         | 
| 152 | 
            -
            Esc  stop movement
         | 
| 153 | 
            -
            \u2191    go to upper limit
         | 
| 154 | 
            -
            \u2193    go to lower limit
         | 
| 155 | 
            -
            \u2190    jog up #{@pulse_count} pulses
         | 
| 156 | 
            -
            \u2192    jog down #{@pulse_count} pulses
         | 
| 157 | 
            -
            >    increase jog size
         | 
| 158 | 
            -
            <    decrease jog size
         | 
| 159 | 
            -
            u    set upper limit at current position
         | 
| 160 | 
            -
            l    set lower limit at current position
         | 
| 161 | 
            -
            r    reverse motor
         | 
| 162 | 
            -
                     | 
| 172 | 
            +
                    win.addstr(<<~TEXT)
         | 
| 173 | 
            +
                      Move the motor. Keys:
         | 
| 174 | 
            +
                      Esc  stop movement
         | 
| 175 | 
            +
                      \u2191    go to upper limit
         | 
| 176 | 
            +
                      \u2193    go to lower limit
         | 
| 177 | 
            +
                      \u2190    jog up #{@pulse_count} pulses
         | 
| 178 | 
            +
                      \u2192    jog down #{@pulse_count} pulses
         | 
| 179 | 
            +
                      >    increase jog size
         | 
| 180 | 
            +
                      <    decrease jog size
         | 
| 181 | 
            +
                      u    set upper limit at current position
         | 
| 182 | 
            +
                      l    set lower limit at current position
         | 
| 183 | 
            +
                      r    reverse motor
         | 
| 184 | 
            +
                    TEXT
         | 
| 163 185 |  | 
| 164 186 | 
             
                    if ilt2?
         | 
| 165 187 | 
             
                      win.addstr("R    reverse motor (but leave position alone)\n")
         | 
| 188 | 
            +
                    else
         | 
| 189 | 
            +
                      win.addstr("!    factory reset\n")
         | 
| 166 190 | 
             
                    end
         | 
| 167 191 | 
             
                    win.addstr("q    quit\n")
         | 
| 168 192 | 
             
                    win.refresh
         | 
| 169 193 | 
             
                  end
         | 
| 170 | 
            -
             | 
| 194 | 
            +
             | 
| 171 195 | 
             
                  def wait_for_stop
         | 
| 172 196 | 
             
                    win.setpos(13, 0)
         | 
| 173 197 | 
             
                    win.addstr("Moving...\n")
         | 
| @@ -183,7 +207,6 @@ r    reverse motor | |
| 183 207 | 
             
                      end
         | 
| 184 208 |  | 
| 185 209 | 
             
                      sdn.receive(0.1) do |message|
         | 
| 186 | 
            -
             | 
| 187 210 | 
             
                        if message.is_a?(ns::PostMotorPosition)
         | 
| 188 211 | 
             
                          last_pos = @pos
         | 
| 189 212 | 
             
                          @pos = message.position_pulses
         | 
| @@ -198,7 +221,7 @@ r    reverse motor | |
| 198 221 | 
             
                          win.addstr("\n")
         | 
| 199 222 | 
             
                          win.nodelay = false
         | 
| 200 223 | 
             
                          refresh
         | 
| 201 | 
            -
                          return
         | 
| 224 | 
            +
                          return # rubocop:disable Lint/NonLocalExitFromIterator
         | 
| 202 225 | 
             
                        end
         | 
| 203 226 | 
             
                      end
         | 
| 204 227 | 
             
                      sleep 0.1
         |