prologix_gpib 0.4.4 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
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: