wireless-rb 0.1.0 → 0.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/CHANGELOG.md +49 -0
- data/README-zh.md +37 -2
- data/README.md +34 -3
- data/docs/architecture-zh.md +4 -4
- data/lib/wireless/ap_session.rb +113 -52
- data/lib/wireless/collector.rb +49 -36
- data/lib/wireless/configuration.rb +0 -2
- data/lib/wireless/coverage.rb +15 -5
- data/lib/wireless/fields.rb +25 -20
- data/lib/wireless/h3c/{authentication_parser.rb → authentication.rb} +4 -4
- data/lib/wireless/h3c/command_output.rb +44 -3
- data/lib/wireless/h3c/configuration.rb +21 -5
- data/lib/wireless/h3c/document.rb +32 -0
- data/lib/wireless/h3c/parsers/display_current_configuration.rb +143 -69
- data/lib/wireless/h3c/parsers/display_dot1x_connection.rb +4 -2
- data/lib/wireless/h3c/parsers/display_lldp_neighbor_information_verbose.rb +34 -10
- data/lib/wireless/h3c/parsers/display_mac_authentication_connection.rb +4 -2
- data/lib/wireless/h3c/parsers/display_wlan_ap_all_verbose.rb +37 -11
- data/lib/wireless/h3c/parsers/display_wlan_ap_model_all.rb +5 -5
- data/lib/wireless/h3c/parsers/display_wlan_bss_all_verbose.rb +6 -6
- data/lib/wireless/h3c/parsers/display_wlan_client_security_block_mac.rb +2 -2
- data/lib/wireless/h3c/parsers/display_wlan_client_verbose.rb +14 -8
- data/lib/wireless/h3c/parsers/display_wlan_statistics_client_ip_conflict.rb +2 -2
- data/lib/wireless/h3c/profile.rb +6 -3
- data/lib/wireless/h3c/record_parser.rb +138 -0
- data/lib/wireless/huawei/parser.rb +86 -0
- data/lib/wireless/huawei/parsers/display_ap_all.rb +14 -0
- data/lib/wireless/huawei/parsers/display_station_all.rb +14 -0
- data/lib/wireless/huawei/profile.rb +22 -0
- data/lib/wireless/observation.rb +2 -0
- data/lib/wireless/parser_registry.rb +2 -1
- data/lib/wireless/projection.rb +4 -0
- data/lib/wireless/runtime_parser.rb +16 -11
- data/lib/wireless/snapshot.rb +2 -1
- data/lib/wireless/terminal.rb +32 -0
- data/lib/wireless/version.rb +1 -1
- data/lib/wireless.rb +0 -2
- metadata +9 -20
- data/lib/wireless/h3c/session_parser.rb +0 -58
- data/lib/wireless/h3c/verbose_parser.rb +0 -82
- data/lib/wireless/h3c_runtime.rb +0 -18
- data/lib/wireless/huawei_runtime.rb +0 -65
|
@@ -1,82 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require_relative "parser"
|
|
4
|
-
|
|
5
|
-
module Wireless
|
|
6
|
-
module H3c
|
|
7
|
-
# 为 H3C 详细命令回显共享词元切分与类型化字段处理。
|
|
8
|
-
class VerboseParser < Parser
|
|
9
|
-
private
|
|
10
|
-
|
|
11
|
-
# 切分含引号的命令值,不将其作为 Ruby 代码解释。
|
|
12
|
-
def tokens(text, issues)
|
|
13
|
-
text.lines.each_with_index.each_with_object([]) do |(line, index), fields|
|
|
14
|
-
row = line.strip
|
|
15
|
-
next if row.empty? || /\A[-=]+\z/.match?(row)
|
|
16
|
-
if (match = /\A([^:]+?)\s*:\s*(.*)\z/.match(row))
|
|
17
|
-
label = match[1].downcase.gsub(/\s+/, " ")
|
|
18
|
-
next if /\A(?:total|number of aps|connected|remaining|maximum|current number|(?:local|server|sync) ap licenses|(?:current|max|bound) bss number)\b/.match?(label)
|
|
19
|
-
fields << [ label, Fields.value(match[2]), index + 1 ]
|
|
20
|
-
elsif (match = /\A:\s*(\S.*)\z/.match(row)) && fields.last&.first == "poe status"
|
|
21
|
-
fields.last[1] = [ fields.last[1], match[1] ].compact.join("\n")
|
|
22
|
-
elsif /\A(?:NSS\d+\s+[\d, ]+|TID \d+\s+(?:In|Out|Both)|[\d., ]+(?:Mbps)?)\z/.match?(row)
|
|
23
|
-
next
|
|
24
|
-
else
|
|
25
|
-
issues << { code: :unrecognized_line, line: index + 1 }
|
|
26
|
-
end
|
|
27
|
-
end
|
|
28
|
-
end
|
|
29
|
-
|
|
30
|
-
# 更新当前记录前,先应用字段专用转换。
|
|
31
|
-
def assign_field(record, mapping, label, raw, issues, line, details:)
|
|
32
|
-
if record && (field = mapping[label])
|
|
33
|
-
safely(issues, line) do
|
|
34
|
-
# 优先使用运行带宽;80+80MHz 等歧义值保持原义,不截断为单个数值。
|
|
35
|
-
if field == :channel_width
|
|
36
|
-
(record[:details] ||= {})[label.tr(" ", "_").to_sym] = raw
|
|
37
|
-
return if label == "channel bandwidth" && record[:details].key?(:operating_bandwidth)
|
|
38
|
-
end
|
|
39
|
-
record[field] = convert(field, raw)
|
|
40
|
-
end
|
|
41
|
-
elsif details
|
|
42
|
-
(details[:details] ||= {})[label.tr(" -", "__").to_sym] = label.end_with?("url") ? !raw.nil? && !raw.strip.empty? : raw
|
|
43
|
-
else
|
|
44
|
-
issues << { code: :unrecognized_field, line: line }
|
|
45
|
-
end
|
|
46
|
-
end
|
|
47
|
-
|
|
48
|
-
# 按声明的归一化规则转换已知字段。
|
|
49
|
-
def convert(field, raw)
|
|
50
|
-
case field
|
|
51
|
-
when :mac_address, :client_mac, :bssid then Fields.mac(raw)
|
|
52
|
-
when :management_ip, :client_ip, :client_ipv6, :ip_address, :ipv6_address then Fields.ip(raw)
|
|
53
|
-
when :ap_id, :radio_id then Fields.integer(raw)&.to_s
|
|
54
|
-
when :client_count, :online_seconds, :uptime_seconds
|
|
55
|
-
%i[online_seconds uptime_seconds].include?(field) ? Fields.duration(raw) : Fields.integer(raw)
|
|
56
|
-
when :vlan, :initial_vlan_id, :authorized_vlan_id then Fields.integer(raw, max: 4094)
|
|
57
|
-
when :channel then Fields.channel(raw)
|
|
58
|
-
when :channel_width then Fields.width(raw)
|
|
59
|
-
when :band then Fields.band(raw)
|
|
60
|
-
when :noise_dbm then Fields.number(raw, unit: "dBm")&.then { |number| number if number.negative? }
|
|
61
|
-
when :utilization
|
|
62
|
-
number = Fields.number(raw, unit: "%")
|
|
63
|
-
raise ArgumentError, "Invalid wireless utilization" if number && !(0..100).cover?(number)
|
|
64
|
-
number&.round
|
|
65
|
-
else raw
|
|
66
|
-
end
|
|
67
|
-
end
|
|
68
|
-
|
|
69
|
-
# 解析非负计数,同时保留未知值。
|
|
70
|
-
def count(text, noun)
|
|
71
|
-
/(?:Total(?: number of)?\s+(?:#{noun})|Total|Current BSS number)\s*:\s*(\d+)\s*$/i.match(text)&.[](1)&.to_i
|
|
72
|
-
end
|
|
73
|
-
|
|
74
|
-
# 隔离单个格式错误字段,同时保留无关记录数据。
|
|
75
|
-
def safely(issues, line)
|
|
76
|
-
yield
|
|
77
|
-
rescue ArgumentError, IPAddr::InvalidAddressError
|
|
78
|
-
issues << { code: :invalid_field, line: line }
|
|
79
|
-
end
|
|
80
|
-
end
|
|
81
|
-
end
|
|
82
|
-
end
|
data/lib/wireless/h3c_runtime.rb
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require_relative "runtime_parser"
|
|
4
|
-
|
|
5
|
-
module Wireless
|
|
6
|
-
# 保留 H3C 公共入口,具体 CLI 语法由独立命令类负责。
|
|
7
|
-
class H3cRuntime
|
|
8
|
-
# 绑定 H3C 运行解析器,并保留既有公共入口。
|
|
9
|
-
def initialize(model: nil)
|
|
10
|
-
@parser = RuntimeParser.new(model: model)
|
|
11
|
-
end
|
|
12
|
-
|
|
13
|
-
# 将单个 H3C 运行维度委派给共享无线解析入口。
|
|
14
|
-
def parse(name, text, complete:)
|
|
15
|
-
@parser.parse(name, text, platform: :h3c, complete: complete)
|
|
16
|
-
end
|
|
17
|
-
end
|
|
18
|
-
end
|
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require_relative "fields"
|
|
4
|
-
require_relative "observation"
|
|
5
|
-
|
|
6
|
-
module Wireless
|
|
7
|
-
# 仅支持有证据的 Huawei 表格格式,区分不支持维度与空清单。
|
|
8
|
-
class HuaweiRuntime
|
|
9
|
-
# 解析支持的 Huawei AP 或客户端汇总,其余维度标记为不支持。
|
|
10
|
-
def parse(name, text, complete:)
|
|
11
|
-
unless %i[access_points clients].include?(name)
|
|
12
|
-
return Observation.new(name: name, status: :unsupported, issues: [ { code: :unsupported_platform_dimension } ])
|
|
13
|
-
end
|
|
14
|
-
records, issues = [], []
|
|
15
|
-
header = false
|
|
16
|
-
total = nil
|
|
17
|
-
text.lines.each_with_index do |line, index|
|
|
18
|
-
row = line.strip
|
|
19
|
-
next if row.empty? || /\A[-=]+\z/.match?(row)
|
|
20
|
-
if (match = /\ATotal\s*:\s*(\d+)\z/i.match(row))
|
|
21
|
-
total = match[1].to_i
|
|
22
|
-
elsif name == :access_points ? /\AID\s+MAC\s+Name\s+Group\s+IP\s+Type\s+State\s+STA\s+Uptime\b/i.match?(row) : /\ASTA MAC\s+AP ID\s+Ap name\s+Rf\/WLAN\b/i.match?(row)
|
|
23
|
-
header = true
|
|
24
|
-
elsif /\ATotal AP information:|\A(?:nor|fault|idle|stdby)\s*:/i.match?(row)
|
|
25
|
-
next
|
|
26
|
-
elsif !header
|
|
27
|
-
issues << { code: :missing_header, line: index + 1 }
|
|
28
|
-
else
|
|
29
|
-
begin
|
|
30
|
-
records << (name == :access_points ? ap(row.split) : client(row.split))
|
|
31
|
-
rescue ArgumentError, IPAddr::InvalidAddressError
|
|
32
|
-
issues << { code: :invalid_row, line: index + 1 }
|
|
33
|
-
end
|
|
34
|
-
end
|
|
35
|
-
end
|
|
36
|
-
issues << { code: :missing_header } unless header
|
|
37
|
-
result = Fields.result(records, issues: issues, complete: complete, total: total, identity: [ name == :access_points ? :name : :client_mac ])
|
|
38
|
-
Observation.new(name: name, **result.to_h)
|
|
39
|
-
end
|
|
40
|
-
|
|
41
|
-
private
|
|
42
|
-
|
|
43
|
-
# 归一化控制器报告的单条 AP 记录。
|
|
44
|
-
def ap(columns)
|
|
45
|
-
raise ArgumentError, "Invalid AP row" unless columns.size == 9
|
|
46
|
-
id, mac, name, group, ip, model, state, clients, uptime = columns
|
|
47
|
-
{ ap_id: Fields.integer(id).to_s, mac_address: Fields.mac(mac), name: name, group_name: group,
|
|
48
|
-
management_ip: Fields.ip(Fields.value(ip)), model: model, operational_status: Fields.online_status(state),
|
|
49
|
-
client_count: Fields.integer(clients), uptime_seconds: Fields.duration(Fields.value(uptime)) }
|
|
50
|
-
end
|
|
51
|
-
|
|
52
|
-
# 归一化控制器报告的单条无线客户端记录。
|
|
53
|
-
def client(columns)
|
|
54
|
-
raise ArgumentError, "Invalid station row" unless columns.size == 15
|
|
55
|
-
mac, ap_id, ap_name, radio_wlan, band, protocol, rates, rssi, vlan, ip, ssid, state, ipv6, _ac_id, uptime = columns
|
|
56
|
-
raise ArgumentError, "Invalid station identity" unless /\A\d+\/\d+\z/.match?(radio_wlan)
|
|
57
|
-
rx, tx = Fields.rates(rates)
|
|
58
|
-
signal = Fields.number(Fields.value(rssi), unit: "dBm")
|
|
59
|
-
{ client_mac: Fields.mac(mac), ap_id: Fields.integer(ap_id).to_s, ap_name: ap_name, radio_id: radio_wlan.split("/").first,
|
|
60
|
-
band: Fields.band(band), protocol: protocol, rx_rate_mbps: rx, tx_rate_mbps: tx, signal_dbm: signal == 0 ? nil : signal,
|
|
61
|
-
vlan: Fields.integer(vlan, max: 4094), client_ip: Fields.ip(Fields.value(ip)), ssid: ssid, operational_status: state,
|
|
62
|
-
client_ipv6: Fields.ip(Fields.value(ipv6)), uptime_seconds: Fields.duration(Fields.value(uptime)) }
|
|
63
|
-
end
|
|
64
|
-
end
|
|
65
|
-
end
|