prologix_gpib 0.4.4 → 0.5.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7ce983416d3fa34a8a34428381d564403c2f48664e153172066bebe1fe619f24
4
- data.tar.gz: 57abf8c3a078fb360684782852b9dfda21815519552ea3cba0ae90babc50bb6c
3
+ metadata.gz: '0291d4b1a403dbcfb0d04712ac0a56540557713e474c042e7f0e31230667063c'
4
+ data.tar.gz: bf2a09c534d2ed527ff86f40f536e4b50c17c528b327004c5fb74afae60b7e79
5
5
  SHA512:
6
- metadata.gz: dce9ffeab0971eade1b9e2b7d889b082e91580ccabaecd7ad39ae83bc502d2c3973e3ce3e7509832e7a207eb8d1a5f10aaf2a44a5a31e805a21198b07b045925
7
- data.tar.gz: a3b93b86db7d811de048a3cb38d56cf4a7c6a2e07ff51ef2975a9ceb978511275f3568a51d8b63e104ff4ace5bd8e64b26428fa95a2e52ea0587a269b7edd01d
6
+ metadata.gz: 8af96e69eb2c5e558b93986568053cb3c7a423d51cd80c7ab9482e95a4d253f79b1afaa807eaa726ccd088b92e278c1e5c6a58cc908ec3f33009f7b398b4621d
7
+ data.tar.gz: 3dc286605d8bd9bab02a61a3a653097b8037084689efb4731cf4856c76c28372834d929596d4fbf32532c0e32d21b6e0341a7f294f7348702b7f1e72fa409a37
data/Gemfile.lock CHANGED
@@ -1,11 +1,12 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- prologix_gpib (0.4.3)
5
- activesupport
6
- rubyserial
4
+ prologix_gpib (0.4.4)
5
+ activesupport (~> 7.0.1)
6
+ bindata (~> 2.4.10)
7
+ rubyserial (~> 0.6.0)
7
8
  terminal-table (~> 3.0.2)
8
- thor
9
+ thor (~> 1.2.1)
9
10
 
10
11
  GEM
11
12
  remote: https://rubygems.org/
@@ -15,6 +16,7 @@ GEM
15
16
  i18n (>= 1.6, < 2)
16
17
  minitest (>= 5.1)
17
18
  tzinfo (~> 2.0)
19
+ bindata (2.4.10)
18
20
  coderay (1.1.3)
19
21
  concurrent-ruby (1.1.9)
20
22
  ffi (1.15.5)
@@ -43,7 +45,6 @@ DEPENDENCIES
43
45
  prologix_gpib!
44
46
  pry
45
47
  rake (~> 10.0)
46
- rubyserial (~> 0.6)
47
48
 
48
49
  BUNDLED WITH
49
50
  2.2.32
data/README.md CHANGED
@@ -24,7 +24,7 @@ Or install it yourself as:
24
24
 
25
25
  ### CLI
26
26
 
27
- The gem comes with a simple cli for querying controllers:
27
+ The gem comes with a simple cli for finding controllers:
28
28
 
29
29
  ```bash
30
30
  $ plx list
@@ -52,22 +52,38 @@ $ plx info 0
52
52
 
53
53
  ```
54
54
 
55
- ### Playing in Console
55
+ ### Finding Controllers
56
56
 
57
- I'm enamoured by this interface, I'd like a more ruby like way of finding and connecting controllers, that works with Ethernet controllers too.
57
+ ```irb
58
+ irb(main):001:0> f = PrologixGpib::Finder.new
59
+ => #<PrologixGpib::Finder:0x00000001089844b0>
60
+ irb(main):002:0> controllers = f.avaliable_controllers
61
+ => {
62
+ :usb=>["/dev/tty.usbserial-PX9HPBMB", "/dev/tty.usbserial-PXEGWA9A"],
63
+ :lan=>["192.168.10.161", "192.168.10.165"]
64
+ }
58
65
 
59
- ```ruby
60
- irb(main):001:0> require 'prologix_gpib'
61
- => true
66
+ ```
62
67
 
63
- irb(main):002:0> paths = PrologixGpib.usb_paths
64
- => ["/dev/tty.usbserial-PX9HPBMB", "/dev/tty.usbserial-PXEGWA9A"]
68
+ ### Working with Controllers
65
69
 
66
- irb(main):003:0> device = PrologixGpib::UsbController.new(paths[0])
70
+ I'm not enamoured by this interface, I'd like a more ruby like way of finding and connecting controllers thats less clunky. It works for now, but may change as we refine the implementation.
71
+
72
+ ```ruby
73
+ irb(main):003:0> device = PrologixGpib::UsbController.new(controllers[:usb][0])
67
74
  => #<PrologixGpib::UsbController:0x00000001574c4098 @serial_port=#<Serial:0x00000001574bfef8 @config=#<RubySerial::Posix::Termios:0x00000001574bf728>, @fd=9, @open=true>>
68
75
 
69
76
  irb(main):004:0> device.config
70
- => {:device_name=>"Prologix GPIB-USB Controller", :firmware=>"6.101", :mode=>"Device", :device_address=>"9", :auto_read=>"NA", :read_timeout=>"NA", :eoi_assertion=>"Enabled", :eos=>"Append CR+LF", :eot=>"Enabled"}
77
+ => {
78
+ :device_name=>"Prologix GPIB-USB Controller",
79
+ :firmware=>"6.101", :mode=>"Device",
80
+ :device_address=>"9",
81
+ :auto_read=>"NA",
82
+ :read_timeout=>"NA",
83
+ :eoi_assertion=>"Enabled",
84
+ :eos=>"Append CR+LF",
85
+ :eot=>"Enabled"
86
+ }
71
87
 
72
88
  irb(main):005:0> device.address
73
89
  => "9"
@@ -79,7 +95,16 @@ irb(main):007:0> device.mode
79
95
  => "0"
80
96
 
81
97
  irb(main):008:0> device.config
82
- => {:device_name=>"Prologix GPIB-USB Controller", :firmware=>"6.101", :mode=>"Controller", :device_address=>"9", :auto_read=>"Disabled", :read_timeout=>"200", :eoi_assertion=>"Enabled", :eos=>"Append CR+LF", :eot=>"Enabled"}
98
+ => {
99
+ :device_name=>"Prologix GPIB-USB Controller",
100
+ :firmware=>"6.101", :mode=>"Controller",
101
+ :device_address=>"9",
102
+ :auto_read=>"Disabled",
103
+ :read_timeout=>"200",
104
+ :eoi_assertion=>"Enabled",
105
+ :eos=>"Append CR+LF",
106
+ :eot=>"Enabled"
107
+ }
83
108
  ```
84
109
 
85
110
  ### Firmware update
data/lan_test.rb ADDED
@@ -0,0 +1,17 @@
1
+ require 'prologix_gpib'
2
+ require 'socket'
3
+
4
+ class Scanner
5
+ def search(range, timeout = 0.1)
6
+ array = []
7
+ range.each do |x|
8
+ s = Socket.tcp("192.168.10.#{x}", 1234, connect_timeout: timeout)
9
+ s.write("++ver\r\n")
10
+ array << s.gets
11
+ rescue => error
12
+ puts error.inspect
13
+ next
14
+ end
15
+ array
16
+ end
17
+ end
@@ -8,21 +8,7 @@ module PrologixGpib
8
8
  desc 'list', 'List all connected controllers'
9
9
 
10
10
  def list
11
- if controllers_connected?
12
- table =
13
- Terminal::Table.new do |t|
14
- t.title = 'Prologix Controllers'
15
- t.headings = %w[index Controller Version Path]
16
- PrologixGpib.usb_paths.each.with_index do |path, index|
17
- device = PrologixGpib::UsbController.new(path)
18
- str = device.version.split('version')
19
- t.add_row [index.to_s, str[0], str[1], path]
20
- end
21
- end
22
- puts table
23
- else
24
- puts 'No Prologix Controllers available.'
25
- end
11
+ puts controller_table(PrologixGpib::Finder.new.avaliable_controllers)
26
12
  end
27
13
 
28
14
  desc 'info', 'Display Controller information'
@@ -42,6 +28,36 @@ module PrologixGpib
42
28
 
43
29
  private
44
30
 
31
+ def controller_table(controllers)
32
+ return 'No Prologix Controllers available.' unless controllers.length > 0
33
+
34
+ table =
35
+ Terminal::Table.new do |t|
36
+ t.title = 'Prologix Controllers'
37
+ t.headings = %w[index Controller Version Location]
38
+ end
39
+
40
+ index = 0
41
+ if controllers.key? :usb
42
+ controllers[:usb].each do |path|
43
+ device = PrologixGpib::UsbController.new(path)
44
+ str = device.version.split('version')
45
+ table.add_row [index.to_s, str[0], str[1], path]
46
+ index += 1
47
+ end
48
+ end
49
+
50
+ if controllers.key? :lan
51
+ controllers[:lan].each do |ip|
52
+ device = PrologixGpib::LanController.new(ip)
53
+ str = device.version.split('version')
54
+ table.add_row [index.to_s, str[0], str[1], ip]
55
+ index += 1
56
+ end
57
+ end
58
+ table
59
+ end
60
+
45
61
  def controllers_connected?
46
62
  PrologixGpib.usb_paths.count >= 1
47
63
  end
@@ -0,0 +1,120 @@
1
+ module PrologixGpib::Discovery
2
+ require 'socket'
3
+ require 'ipaddr'
4
+ require 'bindata'
5
+ require 'timeout'
6
+
7
+ class Error < StandardError
8
+ end
9
+
10
+ def avaliable_controllers
11
+ { usb: usb_device_paths, lan: lan_device_ips }
12
+ end
13
+
14
+ class IPAddr < BinData::Primitive
15
+ array :octets, type: :uint8, initial_length: 4
16
+
17
+ def set(val)
18
+ self.octets = val.split(/\./).map(&:to_i)
19
+ end
20
+
21
+ def get
22
+ self.octets.map(&:to_s).join('.')
23
+ end
24
+ end
25
+
26
+ class MacAddr < BinData::Primitive
27
+ array :octets, type: :uint8, initial_length: 6
28
+
29
+ def set(val)
30
+ self.octets = val.split(/:/).map(&:hex)
31
+ end
32
+
33
+ def get
34
+ self.octets.map { |octet| '%02x' % octet }.join(':')
35
+ end
36
+ end
37
+
38
+ class NFHeader < BinData::Record
39
+ endian :big
40
+ uint8 :magic
41
+ uint8 :identify
42
+ uint16 :seq
43
+ mac_addr :eth_addr
44
+ bit16 :reserved, initial_value: 0x0000
45
+ end
46
+
47
+ class NFIdentifyReply < BinData::Record
48
+ endian :big
49
+ nf_header :header
50
+ uint16 :uptime_days
51
+ uint8 :uptime_hrs
52
+ uint8 :uptime_mins
53
+ uint8 :uptime_secs
54
+ uint8 :mode
55
+ uint8 :alert
56
+ uint8 :ip_type
57
+ ip_addr :addr
58
+ ip_addr :netmask
59
+ string :ip_gw, read_length: 4
60
+ string :app_ver, read_length: 4
61
+ string :boot_ver, read_length: 4
62
+ string :hw_ver, read_length: 4
63
+ stringz :name
64
+ end
65
+
66
+ NF_MAGIC = 0x5a
67
+ HEADER_FMT = 'CCna8'
68
+ NF_IDENTIFY = 0
69
+ NF_IDENTIFY_REPLY = 1
70
+ BROADCAST_PORT = 3040
71
+ BROADCAST_ADDRESS = '255.255.255.255'
72
+ TIMEOUT = 1
73
+
74
+ private
75
+
76
+ def lan_device_ips
77
+ seq = rand(0..65_535)
78
+
79
+ # puts "Seq = #{seq}"
80
+ sock = UDPSocket.new
81
+ sock.setsockopt(:SOL_SOCKET, :SO_BROADCAST, true)
82
+
83
+ # data = [NF_MAGIC, NF_IDENTIFY, seq, "\xFF\xFF\xFF\xFF\xFF\xFF"].pack(HEADER_FMT)
84
+
85
+ data = NFHeader.new
86
+ data.magic = NF_MAGIC
87
+ data.identify = NF_IDENTIFY
88
+ data.seq = seq
89
+ data.eth_addr = 'FF:FF:FF:FF:FF:FF'
90
+
91
+ sock.send(data.to_binary_s, 0, BROADCAST_ADDRESS, BROADCAST_PORT)
92
+ array = []
93
+ begin
94
+ Timeout.timeout(TIMEOUT) do
95
+ while true
96
+ data, addr = sock.recvfrom(256)
97
+ reply = NFIdentifyReply.read(data)
98
+ next if array.include?(reply.addr)
99
+ array << reply.addr if reply.header.seq == seq && reply.header.identify == NF_IDENTIFY_REPLY
100
+ end
101
+ end
102
+ rescue Timeout::Error
103
+ sock.close
104
+ array
105
+ end
106
+ end
107
+
108
+ def usb_device_paths
109
+ path_str, dir =
110
+ if RubySerial::ON_LINUX
111
+ %w[ttyUSB /dev/]
112
+ elsif RubySerial::ON_WINDOWS
113
+ ['TODO: Implement find device for Windows', 'You lazy bugger']
114
+ else
115
+ %w[tty.usbserial /dev/]
116
+ end
117
+
118
+ Dir.glob("#{dir}#{path_str}*")
119
+ end
120
+ end
@@ -0,0 +1,2 @@
1
+ module PrologixGpib::Lan::Commands
2
+ end
@@ -1,3 +1,25 @@
1
1
  module PrologixGpib::Lan
2
- class Error < StandardError; end
3
- end
2
+ class Error < StandardError
3
+ end
4
+
5
+ DEVICE_PORT = 1234
6
+ EOL = "\r\n"
7
+
8
+ def initialize(ip, mode: :controller, address: 9)
9
+ @socket = TCPSocket.new ip, DEVICE_PORT
10
+
11
+ # open_serial_port(paths)
12
+ # flush
13
+ # self.mode = mode
14
+ # self.address = address
15
+ # self.auto = :disable
16
+ # self.eos = 0
17
+
18
+ yield self if block_given?
19
+ end
20
+
21
+ def version
22
+ @socket.send "++ver#{EOL}", 0
23
+ @socket.gets.chomp
24
+ end
25
+ end
@@ -1,6 +1,5 @@
1
1
  module PrologixGpib::Usb
2
2
  require 'timeout'
3
- require 'prologix_gpib/usb/commands'
4
3
 
5
4
  class Error < StandardError
6
5
  end
@@ -1,3 +1,3 @@
1
1
  module PrologixGpib
2
- VERSION = '0.4.4'
2
+ VERSION = '0.5.0'
3
3
  end
data/lib/prologix_gpib.rb CHANGED
@@ -3,7 +3,10 @@
3
3
  require 'rubyserial'
4
4
  require 'prologix_gpib/version'
5
5
  require 'prologix_gpib/lan'
6
+ require 'prologix_gpib/lan/commands'
6
7
  require 'prologix_gpib/usb'
8
+ require 'prologix_gpib/usb/commands'
9
+ require 'prologix_gpib/discovery'
7
10
  require 'prologix_gpib/cli'
8
11
 
9
12
  module PrologixGpib
@@ -14,36 +17,17 @@ module PrologixGpib
14
17
 
15
18
  class LanController
16
19
  include PrologixGpib::Lan
20
+ include PrologixGpib::Lan::Commands
21
+ end
22
+
23
+ class Finder
24
+ include PrologixGpib::Discovery
17
25
  end
18
26
 
19
- # Ideally this class needs to handle finding all avaliable Prologix GPIB controllers (USB and Ethernet),
20
- # But for now it simply passes the Prologix USB device paths onto the controller class
21
27
  # No windows serial support just yet.
22
28
  class << self
23
29
  def new
24
30
  self
25
31
  end
26
-
27
- # Find first avaliable Prologix controller and return a valid controller object
28
- def open; end
29
-
30
- def usb_paths
31
- usb_controller_paths
32
- end
33
-
34
- private
35
-
36
- def usb_controller_paths
37
- path_str, dir =
38
- if RubySerial::ON_LINUX
39
- %w[ttyUSB /dev/]
40
- elsif RubySerial::ON_WINDOWS
41
- ['TODO: Implement find device for Windows', 'You lazy bugger']
42
- else
43
- %w[tty.usbserial /dev/]
44
- end
45
-
46
- Dir.glob("#{dir}#{path_str}*")
47
- end
48
32
  end
49
33
  end
@@ -29,9 +29,10 @@ Gem::Specification.new do |spec|
29
29
  spec.require_paths = ['lib']
30
30
 
31
31
  spec.add_dependency 'activesupport', '~> 7.0.1'
32
+ spec.add_dependency 'bindata', '~> 2.4.10'
32
33
  spec.add_dependency 'rubyserial', '~> 0.6.0'
33
- spec.add_dependency 'thor', '~> 1.2.1'
34
34
  spec.add_dependency 'terminal-table', '~> 3.0.2'
35
+ spec.add_dependency 'thor', '~> 1.2.1'
35
36
 
36
37
  spec.add_development_dependency 'bundler', '~> 2.0'
37
38
  spec.add_development_dependency 'rake', '~> 10.0'
data/test_broadcast.rb ADDED
@@ -0,0 +1,50 @@
1
+ require 'socket'
2
+
3
+ def broadcast
4
+ addr = '255.255.255.255'
5
+ sock = UDPSocket.new
6
+ sock.setsockopt(:SOL_SOCKET, :SO_BROADCAST, true)
7
+
8
+ port = 3040
9
+
10
+ data = [90, 0, 11_111, "\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00"].pack('CCna8')
11
+ sock.send(data, 0, addr, port)
12
+
13
+ while true
14
+ r_data, r_addr = sock.recvfrom(2000) # if this number is too low it will drop the larger packets and never give them to you
15
+ p "From addr: #{r_addr}, msg: #{r_data}"
16
+ # p r_data.unpack('CCna8')
17
+ # puts ''
18
+ end
19
+
20
+ sock.close
21
+ end
22
+
23
+ # ❯ python
24
+
25
+ # WARNING: Python 2.7 is not recommended.
26
+ # This version is included in macOS for compatibility with legacy software.
27
+ # Future versions of macOS will not include Python 2.7.
28
+ # Instead, it is recommended that you transition to using 'python3' from within Terminal.
29
+
30
+ # Python 2.7.18 (default, Nov 13 2021, 06:17:34)
31
+ # [GCC Apple LLVM 13.0.0 (clang-1300.0.29.10) [+internal-os, ptrauth-isa=deployme on darwin
32
+ # Type "help", "copyright", "credits" or "license" for more information.
33
+ # >>> "Z\x00ST\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00".unpack("!2cH6s2x")
34
+ # Traceback (most recent call last):
35
+ # File "<stdin>", line 1, in <module>
36
+ # AttributeError: 'str' object has no attribute 'unpack'
37
+ # >>> struct.unpack("!2cH6s2x", "Z\x00ST\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00")
38
+ # Traceback (most recent call last):
39
+ # File "<stdin>", line 1, in <module>
40
+ # NameError: name 'struct' is not defined
41
+ # >>> import struct
42
+ # >>> struct.unpack("!2cH6s2x", "Z\x00ST\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00")
43
+ # ('Z', '\x00', 21332, '\xff\xff\xff\xff\xff\xff')
44
+ # >>> struct.unpack("!2cH6s2x", "Z\x00s|\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00")
45
+ # ('Z', '\x00', 29564, '\xff\xff\xff\xff\xff\xff')
46
+ # >>> struct.unpack("!2cH6s2x", 'Z\x00+g\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00')
47
+ # ('Z', '\x00', 11111, '\xff\xff\xff\xff\xff\xff')
48
+ # >>>
49
+ # 5a012b670021690100d700000000020324010000c0a80aa1ffffff00c0a80a01010300000101000001010000a5bba57bf645122ba7773d197aa7963448eb8c932a85527a24b3966096caa2ef
50
+ # "\x5a\x01\x2b\x67\x00\x21\x69\x01\x00\xd7\x00\x00\x00\x00\x02\x03\x24\x01\x00\x00\xc0\xa8\x0a\xa1\xff\xff\xff\x00\xc0\xa8\x0a\x01\x01\x03\x00\x00\x01\x01\x00\x00\x01\x01\x00\x00\xa5\xbb\xa5\x7b\xf6\x45\x12\x2b\xa7\x77\x3d\x19\x7a\xa7\x96\x34\x48\xeb\x8c\x93\x2a\x85\x52\x7a\x24\xb3\x96\x60\x96\xca\xa2\xef"
data/test_script.rb CHANGED
@@ -1,6 +1,45 @@
1
1
  #!/usr/bin/env ruby
2
- require 'prologix_gpib'
3
- paths = PrologixGpib.usb_paths
2
+ require 'bindata'
4
3
 
5
- device = PrologixGpib::UsbController.new(paths[0])
6
- puts device.config
4
+ class NFHeader < BinData::Record
5
+ endian :big
6
+ uint8 :magic
7
+ uint8 :identify
8
+ uint16 :seq
9
+ string :addr, read_length: 6
10
+ string :res, read_length: 2
11
+ end
12
+
13
+ class IPAddr < BinData::Primitive
14
+ array :octets, type: :uint8, initial_length: 4
15
+
16
+ def set(val)
17
+ self.octets = val.split(/\./).map(&:to_i)
18
+ end
19
+
20
+ def get
21
+ self.octets.map(&:to_s).join('.')
22
+ end
23
+ end
24
+
25
+ class NFIdentifyReply < BinData::Record
26
+ endian :big
27
+ nf_header :header
28
+ uint16 :uptime_days
29
+ uint8 :uptime_hrs
30
+ uint8 :uptime_mins
31
+ uint8 :uptime_secs
32
+ uint8 :mode
33
+ uint8 :alert
34
+ uint8 :ip_type
35
+ ip_addr :addr
36
+ ip_addr :netmask
37
+ string :ip_gw, read_length: 4
38
+ string :app_ver, read_length: 4
39
+ string :boot_ver, read_length: 4
40
+ string :hw_ver, read_length: 4
41
+ end
42
+
43
+ @identify = "Z\x00+g\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00"
44
+ @indentify_reply =
45
+ 'Z\x01+g\x00!i\x01\x00\xd7\x00\x00\x00\x00\x02\x03$\x01\x00\x00\xc0\xa8\n\xa1\xff\xff\xff\x00\xc0\xa8\n\x01\x01\x03\x00\x00\x01\x01\x00\x00\x01\x01\x00\x00\xa5\xbb\xa5{\xf6E\x12+\xa7w=\x19z\xa7\x964H\xeb\x8c\x93*\x85Rz$\xb3\x96`\x96\xca\xa2\xef'
data/test_server.rb ADDED
@@ -0,0 +1,35 @@
1
+ require 'socket'
2
+ require 'ipaddr'
3
+
4
+ class UDPTest
5
+ def listen
6
+ s = UDPSocket.new
7
+
8
+ # membership = IPAddr.new(multicast_addr).hton + IPAddr.new(bind_addr).hton
9
+ # s.setsockopt(:IPPROTO_UDP, :IP_ADD_MEMBERSHIP, membership)
10
+
11
+ s.bind('', 3040)
12
+ while true
13
+ data, addr = s.recvfrom(1024)
14
+ puts "addr = #{addr}\r\ndata ="
15
+ p data
16
+ end
17
+ end
18
+
19
+ def start_server
20
+ multi_addr = '225.1.1.1'
21
+ bind_addr = '0.0.0.0'
22
+
23
+ sock = UDPSocket.new
24
+ membership = IPAddr.new(multi_addr).hton + IPAddr.new(bind_addr).hton
25
+ sock.setsockopt(:IPPROTO_IP, :IP_ADD_MEMBERSHIP, membership)
26
+ sock.bind(bind_addr, 3040)
27
+ while true
28
+ data, addr = sock.recvfrom(2000) # if this number is too low it will drop the larger packets and never give them to you
29
+ p "From addr: #{addr}, msg: #{data}"
30
+ p data.unpack('CCna8')
31
+ puts ''
32
+ end
33
+ sock.close
34
+ end
35
+ end
data/udp_info.md ADDED
@@ -0,0 +1,30 @@
1
+ Hello Rob,
2
+
3
+ NetFinder uses UDP broadcast to locate and configure GPIB-ETH controllers on a network.
4
+ You can find an implementation of the protocol in the nfcli utility
5
+ http://prologix.biz/downloads/nfcli.tar.gz
6
+
7
+ Discovery
8
+
9
+ Create NF_IDENTIFY packet.
10
+ Set sequence to a random value
11
+ Set eth_addr to all ones
12
+ Broadcast NF_IDENTIFY datagram to port 3040/UDP.
13
+ Listen for NF_IDENTIFY_REPLY datagrams.
14
+ Verify sequence matches NF_IDENTIFY packet
15
+
16
+ Configuration
17
+
18
+ Create NF*ASSIGNMENT packet
19
+ Set sequence to a random value
20
+ Set eth_addr to MAC address of desired device Set ip_type to NF_IP_DYNAMIC or NF_IP_STATIC If ip_type is NF_IP_DYNAMIC specify ip, mask and gateway addresses.
21
+ Broadcast NF* ASSIGNMENT datagram to port 3040/UDP.
22
+ Listen for NF_ASSIGNMENT_REPLY datagrams.
23
+ Verify sequence matches that of NF_ASSIGNMENT packet Check result field for NF_SUCCESS
24
+
25
+ Notes:
26
+
27
+ 1. You may get multiple replies. Discard duplicate replies.
28
+ 2. All multi-byte values are in network order (big-endian)
29
+ 3. On multi-homed hosts, make sure broadcasts go out over all interfaces.
30
+ 4. NetFinder protocol only works within the same subnet as routers will not forward UDP broadcast packets.
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: prologix_gpib
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.4
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Rob Carruthers
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2022-01-12 00:00:00.000000000 Z
11
+ date: 2022-01-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -25,33 +25,33 @@ dependencies:
25
25
  - !ruby/object:Gem::Version
26
26
  version: 7.0.1
27
27
  - !ruby/object:Gem::Dependency
28
- name: rubyserial
28
+ name: bindata
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: 0.6.0
33
+ version: 2.4.10
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: 0.6.0
40
+ version: 2.4.10
41
41
  - !ruby/object:Gem::Dependency
42
- name: thor
42
+ name: rubyserial
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
45
  - - "~>"
46
46
  - !ruby/object:Gem::Version
47
- version: 1.2.1
47
+ version: 0.6.0
48
48
  type: :runtime
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
- version: 1.2.1
54
+ version: 0.6.0
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: terminal-table
57
57
  requirement: !ruby/object:Gem::Requirement
@@ -66,6 +66,20 @@ dependencies:
66
66
  - - "~>"
67
67
  - !ruby/object:Gem::Version
68
68
  version: 3.0.2
69
+ - !ruby/object:Gem::Dependency
70
+ name: thor
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: 1.2.1
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: 1.2.1
69
83
  - !ruby/object:Gem::Dependency
70
84
  name: bundler
71
85
  requirement: !ruby/object:Gem::Requirement
@@ -114,15 +128,21 @@ files:
114
128
  - bin/console
115
129
  - bin/setup
116
130
  - exe/plx
131
+ - lan_test.rb
117
132
  - lib/prologix_gpib.rb
118
133
  - lib/prologix_gpib/cli.rb
134
+ - lib/prologix_gpib/discovery.rb
119
135
  - lib/prologix_gpib/lan.rb
136
+ - lib/prologix_gpib/lan/commands.rb
120
137
  - lib/prologix_gpib/usb.rb
121
138
  - lib/prologix_gpib/usb/commands.rb
122
139
  - lib/prologix_gpib/version.rb
123
140
  - package.json
124
141
  - prologix_gpib.gemspec
142
+ - test_broadcast.rb
125
143
  - test_script.rb
144
+ - test_server.rb
145
+ - udp_info.md
126
146
  - yarn.lock
127
147
  homepage: https://github.com/robcarruthers/prologix_gpib
128
148
  licenses: