lib-tl1-huawei 0.1.8 → 0.1.9

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.
Files changed (107) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +30 -0
  3. data/.ruby-version +1 -1
  4. data/Gemfile +1 -2
  5. data/README.md +189 -22
  6. data/Rakefile +8 -3
  7. data/lib/lib/tl1/huawei/message/exception.rb +7 -6
  8. data/lib/lib/tl1/huawei/message/input.rb +6 -3
  9. data/lib/lib/tl1/huawei/message/login.rb +5 -3
  10. data/lib/lib/tl1/huawei/message/logout.rb +2 -1
  11. data/lib/lib/tl1/huawei/message/lst_bms_version.rb +1 -1
  12. data/lib/lib/tl1/huawei/message/lst_board.rb +4 -10
  13. data/lib/lib/tl1/huawei/message/lst_dev.rb +7 -12
  14. data/lib/lib/tl1/huawei/message/lst_emf_sys_info.rb +5 -2
  15. data/lib/lib/tl1/huawei/message/lst_frame.rb +4 -7
  16. data/lib/lib/tl1/huawei/message/lst_gem_connection.rb +7 -10
  17. data/lib/lib/tl1/huawei/message/lst_gem_port.rb +4 -8
  18. data/lib/lib/tl1/huawei/message/lst_gpon_auto_find.rb +6 -8
  19. data/lib/lib/tl1/huawei/message/lst_gpon_ddm_info.rb +4 -5
  20. data/lib/lib/tl1/huawei/message/lst_gpon_line_profile.rb +1 -0
  21. data/lib/lib/tl1/huawei/message/lst_gpon_nni_perf.rb +4 -5
  22. data/lib/lib/tl1/huawei/message/lst_gpon_nni_port.rb +1 -1
  23. data/lib/lib/tl1/huawei/message/lst_gpon_ont_eth_port_detail.rb +5 -9
  24. data/lib/lib/tl1/huawei/message/lst_gpon_ont_eth_port_perf.rb +5 -8
  25. data/lib/lib/tl1/huawei/message/lst_gpon_ont_port_mac.rb +6 -10
  26. data/lib/lib/tl1/huawei/message/lst_gpon_port.rb +4 -5
  27. data/lib/lib/tl1/huawei/message/lst_gpon_port_detail.rb +4 -6
  28. data/lib/lib/tl1/huawei/message/lst_gpon_port_perf.rb +4 -5
  29. data/lib/lib/tl1/huawei/message/lst_gpon_sfp.rb +4 -6
  30. data/lib/lib/tl1/huawei/message/lst_gpon_srv_profile.rb +1 -0
  31. data/lib/lib/tl1/huawei/message/lst_ont.rb +6 -15
  32. data/lib/lib/tl1/huawei/message/lst_ont_dba_prof.rb +5 -9
  33. data/lib/lib/tl1/huawei/message/lst_ont_ddm_detail.rb +4 -7
  34. data/lib/lib/tl1/huawei/message/lst_ont_detail.rb +6 -10
  35. data/lib/lib/tl1/huawei/message/lst_ont_eth_port_perf.rb +6 -12
  36. data/lib/lib/tl1/huawei/message/lst_ont_eth_vlan_switch_pair.rb +8 -10
  37. data/lib/lib/tl1/huawei/message/lst_ont_ip_config.rb +5 -8
  38. data/lib/lib/tl1/huawei/message/lst_ont_ip_info.rb +5 -10
  39. data/lib/lib/tl1/huawei/message/lst_ont_port.rb +6 -13
  40. data/lib/lib/tl1/huawei/message/lst_ont_port_detail.rb +6 -13
  41. data/lib/lib/tl1/huawei/message/lst_ont_pots_state.rb +5 -10
  42. data/lib/lib/tl1/huawei/message/lst_ont_queue_shaping.rb +6 -11
  43. data/lib/lib/tl1/huawei/message/lst_ont_run_info.rb +5 -10
  44. data/lib/lib/tl1/huawei/message/lst_ont_vag_voip.rb +5 -10
  45. data/lib/lib/tl1/huawei/message/lst_ont_voip_pstn_user.rb +7 -18
  46. data/lib/lib/tl1/huawei/message/lst_ont_wan.rb +5 -10
  47. data/lib/lib/tl1/huawei/message/lst_onu_nni_ddm_detail.rb +4 -5
  48. data/lib/lib/tl1/huawei/message/lst_port.rb +5 -15
  49. data/lib/lib/tl1/huawei/message/output.rb +43 -137
  50. data/lib/lib/tl1/huawei/message/response.rb +10 -4
  51. data/lib/lib/tl1/huawei/message/response_body.rb +107 -0
  52. data/lib/lib/tl1/huawei/message/shake_hand.rb +2 -1
  53. data/lib/lib/tl1/huawei/message.rb +1 -0
  54. data/lib/lib/tl1/huawei/version.rb +1 -1
  55. data/sig/lib/tl1/huawei/message/exception.rbs +10 -0
  56. data/sig/lib/tl1/huawei/message/input.rbs +41 -0
  57. data/sig/lib/tl1/huawei/message/login.rbs +13 -0
  58. data/sig/lib/tl1/huawei/message/logout.rbs +11 -0
  59. data/sig/lib/tl1/huawei/message/lst_bms_version.rbs +10 -0
  60. data/sig/lib/tl1/huawei/message/lst_board.rbs +26 -0
  61. data/sig/lib/tl1/huawei/message/lst_dev.rbs +29 -0
  62. data/sig/lib/tl1/huawei/message/lst_emf_sys_info.rbs +11 -0
  63. data/sig/lib/tl1/huawei/message/lst_frame.rbs +15 -0
  64. data/sig/lib/tl1/huawei/message/lst_gem_connection.rbs +33 -0
  65. data/sig/lib/tl1/huawei/message/lst_gem_port.rbs +31 -0
  66. data/sig/lib/tl1/huawei/message/lst_gpon_auto_find.rbs +27 -0
  67. data/sig/lib/tl1/huawei/message/lst_gpon_ddm_info.rbs +25 -0
  68. data/sig/lib/tl1/huawei/message/lst_gpon_line_profile.rbs +14 -0
  69. data/sig/lib/tl1/huawei/message/lst_gpon_nni_perf.rbs +25 -0
  70. data/sig/lib/tl1/huawei/message/lst_gpon_nni_port.rbs +14 -0
  71. data/sig/lib/tl1/huawei/message/lst_gpon_ont_eth_port_detail.rbs +31 -0
  72. data/sig/lib/tl1/huawei/message/lst_gpon_ont_eth_port_perf.rbs +29 -0
  73. data/sig/lib/tl1/huawei/message/lst_gpon_ont_port_mac.rbs +33 -0
  74. data/sig/lib/tl1/huawei/message/lst_gpon_port.rbs +25 -0
  75. data/sig/lib/tl1/huawei/message/lst_gpon_port_detail.rbs +27 -0
  76. data/sig/lib/tl1/huawei/message/lst_gpon_port_perf.rbs +25 -0
  77. data/sig/lib/tl1/huawei/message/lst_gpon_sfp.rbs +27 -0
  78. data/sig/lib/tl1/huawei/message/lst_gpon_srv_profile.rbs +14 -0
  79. data/sig/lib/tl1/huawei/message/lst_ont.rbs +38 -0
  80. data/sig/lib/tl1/huawei/message/lst_ont_dba_prof.rbs +31 -0
  81. data/sig/lib/tl1/huawei/message/lst_ont_ddm_detail.rbs +29 -0
  82. data/sig/lib/tl1/huawei/message/lst_ont_detail.rbs +30 -0
  83. data/sig/lib/tl1/huawei/message/lst_ont_eth_port_perf.rbs +35 -0
  84. data/sig/lib/tl1/huawei/message/lst_ont_eth_vlan_switch_pair.rbs +31 -0
  85. data/sig/lib/tl1/huawei/message/lst_ont_ip_config.rbs +29 -0
  86. data/sig/lib/tl1/huawei/message/lst_ont_ip_info.rbs +31 -0
  87. data/sig/lib/tl1/huawei/message/lst_ont_port.rbs +37 -0
  88. data/sig/lib/tl1/huawei/message/lst_ont_port_detail.rbs +37 -0
  89. data/sig/lib/tl1/huawei/message/lst_ont_pots_state.rbs +31 -0
  90. data/sig/lib/tl1/huawei/message/lst_ont_queue_shaping.rbs +33 -0
  91. data/sig/lib/tl1/huawei/message/lst_ont_run_info.rbs +32 -0
  92. data/sig/lib/tl1/huawei/message/lst_ont_vag_voip.rbs +33 -0
  93. data/sig/lib/tl1/huawei/message/lst_ont_voip_pstn_user.rbs +35 -0
  94. data/sig/lib/tl1/huawei/message/lst_ont_wan.rbs +33 -0
  95. data/sig/lib/tl1/huawei/message/lst_onu_nni_ddm_detail.rbs +25 -0
  96. data/sig/lib/tl1/huawei/message/lst_port.rbs +34 -0
  97. data/sig/lib/tl1/huawei/message/output.rbs +95 -0
  98. data/sig/lib/tl1/huawei/message/response.rbs +20 -0
  99. data/sig/lib/tl1/huawei/message/response_body.rbs +22 -0
  100. data/sig/lib/tl1/huawei/message/shake_hand.rbs +11 -0
  101. data/sig/lib/tl1/huawei/message.rbs +9 -0
  102. data/sig/lib/tl1/huawei/version.rbs +7 -0
  103. data/sig/lib/tl1/huawei.rbs +16 -2
  104. metadata +75 -11
  105. data/.idea/.gitignore +0 -8
  106. data/.idea/misc.xml +0 -4
  107. data/.idea/remote-mappings.xml +0 -16
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2e35fe42f5b11d5bdb4bf4e96b1b6255937e3e30c8a6d8aad054f4bd3d5af648
4
- data.tar.gz: 8375e47ed4d6090ecf2f98c912ce88e87cf865ed8a0ad93face865aa9086c168
3
+ metadata.gz: fa419db9b636262d5c1508225bfc2964dba1048640badd89617cfaf1d391cf83
4
+ data.tar.gz: 59b962716fe07cdbac297b0445270735dbe4e4a26d18fe2fb707338b97cc53da
5
5
  SHA512:
6
- metadata.gz: 0646ece3ee2007d1e21066543782a0c4ddf826b80df76e6d4ee297a00e3692d02fc09045dfcaee582ab0a8f0f319e2cd6498d78d820576fefefb04901395f40c
7
- data.tar.gz: f8c668c1706b9cda0f3320d447ea19ea411ab58d3d37e3d389de851d019f2b1b4a52e399a3d18ae2a58eb4f0632814c6fbc3a7d30305ab8c623a16b5f0bc8bc9
6
+ metadata.gz: 8db89037f1ef25ad794a573dfac262d6141869102d2ac419029ae1016328d059f502df49ea478bb0cce56e5683f80b69aa0b1878e259deea3da6f9b23e78c504
7
+ data.tar.gz: '09972d8cb1b8b53aaf874e25e32d69aef2c63ff30d211e0de715e16f04692eddf8b969038cb156fc18389ccdfefc4c24ffa89af51587f09343244ef4ed49fff6'
data/.rubocop.yml ADDED
@@ -0,0 +1,30 @@
1
+ AllCops:
2
+ TargetRubyVersion: 3.4
3
+ NewCops: enable
4
+ SuggestExtensions: false
5
+ Exclude:
6
+ - 'tmp/**/*'
7
+ - 'vendor/**/*'
8
+
9
+ # Named TL1 fields are part of the public command API; positional arguments keep
10
+ # the default limit.
11
+ Metrics/ParameterLists:
12
+ CountKeywordArgs: false
13
+
14
+ # Protocol field maps and expected response data are declarative collections.
15
+ Metrics/MethodLength:
16
+ CountAsOne: ['array', 'hash', 'heredoc']
17
+
18
+ # Example groups collect independent tests; individual examples remain checked.
19
+ Metrics/BlockLength:
20
+ AllowedMethods: ['describe']
21
+
22
+ # GB (general block) and CC (completion code) are public lib-tl1 keywords.
23
+ Naming/MethodParameterName:
24
+ AllowedNames: ['cc', 'gb']
25
+
26
+ # Response is a public OpenStruct subclass with dynamic, mutable TL1 columns.
27
+ # Replacing it with a fixed Struct or Hash would change the record API.
28
+ Style/OpenStructUse:
29
+ Exclude:
30
+ - 'lib/lib/tl1/huawei/message/response.rb'
data/.ruby-version CHANGED
@@ -1 +1 @@
1
- ruby-3.0.2
1
+ 3.4
data/Gemfile CHANGED
@@ -8,5 +8,4 @@ gemspec
8
8
  gem 'rake', '~> 13.0'
9
9
 
10
10
  gem 'rspec', '~> 3.0'
11
- gem 'rubocop', group: 'development'
12
-
11
+ gem 'rubocop', '~> 1.91.0', group: 'development'
data/README.md CHANGED
@@ -1,47 +1,214 @@
1
- # Lib::Tl1::Huawei
1
+ # Lib::TL1::Huawei
2
2
 
3
- Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/lib/tl1/huawei`. To experiment with that code, run `bin/console` for an interactive prompt.
3
+ A Ruby library for building commands and parsing TL1 NBI responses from Huawei iManager U2000.
4
+ It extends `lib-tl1`, using its fields and TL1 frame parser to read Huawei metadata
5
+ and tables. It provides a subset of queries for devices, GPON/ONT, GEM, profiles,
6
+ optical parameters, statistics, IP/WAN, VLAN and VoIP, as well as session commands.
4
7
 
5
- TODO: Delete this and the text above, and describe your gem
8
+ The library does not establish TCP/TLS connections, send commands, maintain sessions
9
+ or assemble multipart responses. These are the responsibility of the application using the gem.
6
10
 
7
11
  ## Installation
8
12
 
9
- Add this line to your application's Gemfile:
13
+ Ruby `>= 3.4.0` is required. Older Ruby versions are no longer supported.
14
+ Add the following to your application's `Gemfile`:
10
15
 
11
- ```ruby
16
+ ```gemfile
12
17
  gem 'lib-tl1-huawei'
13
18
  ```
14
19
 
15
- And then execute:
20
+ Then run `bundle install`. The gem depends on `lib-tl1 ~> 0.1.2`
21
+ and `ostruct >= 0.1.0, < 1.0`; Bundler installs them automatically.
22
+ The entry point is `require 'lib/tl1/huawei'`, and the namespace is `Lib::TL1::Huawei`.
16
23
 
17
- $ bundle install
24
+ ## Building a command
18
25
 
19
- Or install it yourself as:
26
+ This example builds an `LST-ONTDETAIL` command to query details for ONT 3 on
27
+ port 2, slot 8, frame 0 of device 1. `CTAG` is a request identifier that lets the
28
+ application match a response to its command. Set it with `message.ctag` before
29
+ calling `to_s` to produce the TL1 command string.
20
30
 
21
- $ gem install lib-tl1-huawei
31
+ ```ruby
32
+ require 'lib/tl1/huawei'
33
+
34
+ message = Lib::TL1::Huawei::Message::LstOntDetail.new(
35
+ did: 1, frame_number: 0, slot_number: 8, port_number: 2, ont_id: 3
36
+ )
37
+ message.ctag = 101
38
+ puts message.to_s
39
+ # LST-ONTDETAIL::DID=1,FN=0,SN=8,PN=2,ONTID=3:101::;
40
+ ```
22
41
 
23
- ## Usage
42
+ `DID` is the device identifier in U2000. `DEV` means the device name by default,
43
+ but the `DevMean`/`DEVMEAN` setting can change its meaning to the IP address.
44
+ Choose `did:` or `dev:` according to the NBI configuration and the command's requirements.
45
+ The library does not read this configuration or validate the address against a device.
46
+
47
+ | Ruby argument | TL1 field | Meaning |
48
+ | --- | --- | --- |
49
+ | `frame_number:` | `FN` | OLT frame/shelf number |
50
+ | `slot_number:` | `SN` | Slot number |
51
+ | `port_number:` | `PN` | Port number |
52
+ | `ont_id:` | `ONTID` | ONT identifier on the port |
53
+ | `ont_name:` | `NAME` | ONT name, together with `DID` or `DEV` |
54
+ | `ont_alias:` | `ALIAS` | Alternative ONT addressing by alias |
55
+
56
+ For `LstOntDetail`, choose the ONT coordinates, a name with a device, or an alias alone;
57
+ do not combine all addressing variants. Available arguments depend on the constructor.
58
+ For example, `LstOnt` uses `onu_name:` for `NAME` and supports `ont_sn:` (`ONTSN`)
59
+ and `ont_pwd:` (`PWD`); `LstOntDbaProf` also maps `ont_pwd:` to `PWD`.
60
+ `LstGponAutoFind` sends `LST-GPONONTAUTOFIND` and accepts a serial number or an OLT location.
61
+ `LstGponNniPort` is a separate query for NNI ports with optional `SHOWOPTION`.
62
+ For example, `LstGponNniPort` supports `show_option: [:PSTAT]`;
63
+ the allowed `SHOWOPTION` fields differ between commands.
64
+
65
+ ## Reading responses and errors
66
+
67
+ Run the following examples from the repository directory, for example with `bundle exec ruby`.
68
+ The files in `spec/fixtures/huawei` are synthetic: they contain no subscriber data and
69
+ are not device session recordings. Fixtures and tests are not packaged in the installed gem.
24
70
 
25
- TODO: Write usage instructions here
71
+ ```ruby
72
+ require 'lib/tl1/huawei'
73
+
74
+ raw = File.binread('spec/fixtures/huawei/one_record.tl1')
75
+ output = Lib::TL1::Huawei::Message::Output.parse(raw, encoding: 'UTF-8')
76
+ puts output.ont_id # 1
77
+ puts output.first.name # Office west
78
+ puts output.first.rx_power # --
79
+ puts output.to_h[:blktotal] # 1
80
+ ```
26
81
 
27
- ## Development
82
+ `Output.parse` accepts one complete response. `response` is an array of
83
+ `Response` records based on `OpenStruct`; `first`, `each`, `map`, `[]` and `size` provide
84
+ collection operations. Column names are converted to lowercase, and records also support
85
+ snake_case names: `ontid` and `ont_id` read the same field.
86
+ Record getters are delegated directly from `Output` only when
87
+ `blktotal == 1` and `response.size == 1`. Use the collection for empty results or results
88
+ with multiple records; `respond_to?` follows the same delegation rule.
28
89
 
29
- After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
90
+ `blktag` is the packet number, `blkcount` is the number of records in that packet, and
91
+ `blktotal` is the total number of records, not packets. `to_h` returns the header,
92
+ `en`, `endesc`, counters, title and an array of hashes in `:response`. Field values remain
93
+ strings without unit conversion; `--` remains `--`, and an empty table cell remains an empty string.
30
94
 
31
- To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
95
+ ```ruby
96
+ require 'lib/tl1/huawei'
97
+
98
+ begin
99
+ raw = File.binread('spec/fixtures/huawei/error.tl1')
100
+ Lib::TL1::Huawei::Message::Output.parse(raw, encoding: 'UTF-8')
101
+ rescue Lib::TL1::Huawei::StandardError => error
102
+ puts "#{error.error_number}: #{error.message}"
103
+ # 123: Example device error.
104
+ end
105
+ ```
106
+
107
+ A nonzero `EN` identifies a Huawei error; `ENDESC` supplies its description.
108
+ Do not compare the description with a literal success message. Frame syntax errors can also
109
+ come from the `lib-tl1` parser and may raise exceptions other than `Lib::TL1::Huawei::StandardError`.
32
110
 
33
- ## Contributing
111
+ ## Encoding and API compatibility
34
112
 
35
- Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/lib-tl1-huawei. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/[USERNAME]/lib-tl1-huawei/blob/master/CODE_OF_CONDUCT.md).
113
+ The default `encoding: nil` preserves the bytes and encoding of the input `String`.
114
+ For `File.binread`, this means `ASCII-8BIT`, without guessing the server's encoding.
115
+ An explicit `encoding: 'UTF-8'`, `'GBK'` or `'ISO-8859-1'` interprets a copy of the input
116
+ bytes in the specified encoding and decodes it to UTF-8. Match it to the U2000 `CharSet`
117
+ configuration. Invalid data raises an exception; the parser does not replace characters.
118
+ Repeated reads and `to_h` do not change the source data or the encoding of record values.
119
+ `to_h` no longer forces conversion from ISO-8859-1.
36
120
 
37
- ## License
121
+ `reverse` returns a reversed copy of the collection without changing its order.
122
+ The broken delegator with the misspelled name `revers` has been removed; replace calls to it
123
+ with `reverse`. `LstDev#dev_type` reflects the constructor argument, and `show_option`
124
+ and the retained alias `showoption` return the same list of options.
38
125
 
39
- The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
126
+ `LstOntEthVlanSwitchPair` sends `LST-ONTETHVLANSWTICHPAIR`, with the intentional
127
+ spelling `SWTICHPAIR`. It replaces the previously sent
128
+ `LST-ONTETHVLANSWITCHPAIR`. The `ont_port_type:` argument is serialized in uppercase
129
+ (the default `:eth` produces `ETH`); `nil` omits the field, and the getter preserves the supplied argument.
40
130
 
41
- ## Code of Conduct
131
+ Tests use synthetic fixtures and do not establish compatibility with a live U2000 system.
132
+ The library implements a subset of U2000 commands and addressing variants; the class list is in
133
+ the [message loader](lib/lib/tl1/huawei/message.rb), and the maintained signatures are in
134
+ the [RBS signatures](sig/lib/tl1/), whose file layout mirrors `lib/lib/tl1/`.
42
135
 
43
- Everyone interacting in the Lib::Tl1::Huawei project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/[USERNAME]/lib-tl1-huawei/blob/master/CODE_OF_CONDUCT.md).
136
+ ## Development
137
+
138
+ Select a supported Ruby environment with RVM; `.ruby-version` specifies `3.4`,
139
+ and `.ruby-gemset` specifies `lib-tl1-huawei`. Use this gemset name when selecting another
140
+ supported Ruby version as well, for example `rvm use 4.0.2@lib-tl1-huawei --create`.
141
+ Install dependencies, including the `development` group, in the selected gemset and
142
+ run the local checks:
44
143
 
45
- ## NBI U2000 Port
46
- 9819
144
+ ```sh
145
+ bundle check
146
+ bundle install
147
+ bundle exec rake
148
+ ```
47
149
 
150
+ `bundle install` is only needed when `bundle check` reports missing dependencies.
151
+ The default Rake task runs RuboCop followed by RSpec. Use `bundle exec rake rubocop`
152
+ for lint only or `bundle exec rake spec` for tests only.
153
+ RuboCop settings live in `.rubocop.yml`, without an offense baseline.
154
+ The configuration preserves named TL1 parameters and the `gb`/`cc` protocol keywords,
155
+ counts multiline data literals as one expression for method length, and excludes
156
+ declarative RSpec `describe` groups from block length checks. Individual examples
157
+ and helpers retain the default limits. `Response` alone is exempt from
158
+ `Style/OpenStructUse` to preserve its public dynamic, mutable record API; all
159
+ other checks still apply to it. Fix new offenses in code instead of generating
160
+ exclusions; any rule adjustment needs an explicit design or compatibility reason.
161
+ The tests do not connect to U2000; they also execute the Ruby examples in this README.
162
+ CI runs RuboCop on Ruby 3.4 and tests on Ruby 3.4 and 4.0 for pull requests,
163
+ pushes to `master` and `v*` tags. Both checks must pass before release tag preparation.
164
+
165
+ ## Publishing
166
+
167
+ When a push to `master` changes `Lib::TL1::Huawei::VERSION` in
168
+ `lib/lib/tl1/huawei/version.rb`, the workflow runs the tests and creates a matching
169
+ `v<VERSION>` tag (for example, `v0.1.9`). It compares the versions before and after
170
+ the entire push, including pushes containing multiple commits. Unchanged versions,
171
+ initial branch creation and existing tags do not trigger an automatic release.
172
+ Existing tags are never moved.
173
+
174
+ Only a newly created tag enables the build and publication using
175
+ [RubyGems Trusted Publishing](https://guides.rubygems.org/trusted-publishing/).
176
+ Tags created by the workflow use `GITHUB_TOKEN`, which
177
+ [does not trigger another push workflow](https://docs.github.com/en/actions/how-tos/write-workflows/choose-when-workflows-run/trigger-a-workflow#triggering-a-workflow-from-a-workflow).
178
+ The dependent publishing job therefore runs in the same workflow after tag creation,
179
+ without a personal access token. A new `v*` tag pushed manually also runs the tests
180
+ and publishes, provided its name matches the version at the tagged commit.
181
+ Deleting or updating an existing tag does not publish a gem.
182
+
183
+ The workflow exchanges a GitHub Actions OIDC token for short-lived RubyGems credentials
184
+ through the official
185
+ [`configure-rubygems-credentials` action](https://github.com/rubygems/configure-rubygems-credentials).
186
+ Only the publishing job has `id-token: write`; it uses the `release` environment.
187
+ The tag preparation job has `contents: write`; repository rules must allow
188
+ `GITHUB_TOKEN` to create `v*` tags.
189
+
190
+ Before the first publication through this workflow, create the GitHub environment `release`
191
+ and register a trusted publisher for `lib-tl1-huawei` on RubyGems.org with these values:
192
+
193
+ | Setting | Value |
194
+ | --- | --- |
195
+ | Repository owner | `pwojcieszonek` |
196
+ | Repository name | `lib-tl1-huawei` |
197
+ | Workflow filename | `main.yml` |
198
+ | Environment | `release` |
199
+
200
+ The workflow filename is the basename of `.github/workflows/main.yml`.
201
+ The RubyGems and GitHub environment names must match. No `RUBYGEMS_AUTH_TOKEN` secret
202
+ is required by this workflow.
203
+ If the `release` environment restricts deployment branches or tags, allow both
204
+ `master` (automatic tags) and `v*` tags (manual tag pushes). Required environment
205
+ reviewers, if configured, still need to approve publication.
206
+
207
+ Set a new, unpublished version in `lib/lib/tl1/huawei/version.rb` before pushing a release
208
+ to `master`; RubyGems rejects attempts to publish an existing version again.
209
+ If publication fails after automatic tag creation, use GitHub Actions' **Re-run failed jobs**
210
+ to retry publication with the existing tag output. Re-running all jobs finds the
211
+ existing tag and skips the automatic release.
212
+ Local tests and `gem build lib-tl1-huawei.gemspec` do not publish the gem.
213
+
214
+ This project is available under the [MIT license](LICENSE.txt).
data/Rakefile CHANGED
@@ -1,8 +1,13 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "bundler/gem_tasks"
4
- require "rspec/core/rake_task"
3
+ require 'bundler/gem_tasks'
4
+ require 'rspec/core/rake_task'
5
5
 
6
6
  RSpec::Core::RakeTask.new(:spec)
7
7
 
8
- task default: :spec
8
+ desc 'Run RuboCop'
9
+ task :rubocop do
10
+ ruby '-S', 'rubocop'
11
+ end
12
+
13
+ task default: %i[rubocop spec]
@@ -1,15 +1,16 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Lib
2
4
  module TL1
3
5
  module Huawei
4
- class StandardError < StandardError
5
-
6
+ # Reports the Huawei EN error number alongside its ENDESC description.
7
+ class StandardError < ::StandardError
6
8
  attr_reader :error_number
7
9
 
8
- def initialize(msg = nil, en=nil)
9
- super(msg)
10
- @error_number = en
10
+ def initialize(message = nil, error_number = nil)
11
+ super(message)
12
+ @error_number = error_number
11
13
  end
12
-
13
14
  end
14
15
  end
15
16
  end
@@ -6,8 +6,8 @@ module Lib
6
6
  module TL1
7
7
  module Huawei
8
8
  module Message
9
+ # Serializes Huawei command parameters on top of the TL1 frame builder.
9
10
  class Input < Lib::TL1::Message::Input
10
-
11
11
  def initialize(command: nil, tid: nil, aid: nil, ctag: nil, gb: nil, payload: nil)
12
12
  command = self.class.name.split('::').last.sub(/(.)([A-Z])/, '\1-\2').upcase if command.nil?
13
13
  super
@@ -15,14 +15,17 @@ module Lib
15
15
 
16
16
  private
17
17
 
18
+ def set_attributes(**attributes)
19
+ attributes.each { |name, value| instance_variable_set("@#{name}", value) }
20
+ end
21
+
18
22
  def __show_option(*show_option)
19
23
  show_option.empty? ? nil : show_option.map { |option| option.to_s.delete('_') }.join(' ')
20
24
  end
21
25
 
22
26
  def hash_to_string(**hash)
23
- hash.reject { |k, v| v.nil? }.map { |k, v| "#{k.to_s.delete('_').upcase}=#{v.to_s}" }.join(',')
27
+ hash.compact.map { |key, value| "#{key.to_s.delete('_').upcase}=#{value}" }.join(',')
24
28
  end
25
-
26
29
  end
27
30
  end
28
31
  end
@@ -1,9 +1,12 @@
1
- require_relative "input"
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'input'
2
4
 
3
5
  module Lib
4
6
  module TL1
5
7
  module Huawei
6
8
  module Message
9
+ # Builds a LOGIN command from the NBI username and password.
7
10
  class Login < Lib::TL1::Huawei::Message::Input
8
11
  attr_reader :password, :username
9
12
 
@@ -12,9 +15,8 @@ module Lib
12
15
  @password = password
13
16
  super(payload: "UN=#{username},PWD=#{password}")
14
17
  end
15
-
16
18
  end
17
19
  end
18
20
  end
19
21
  end
20
- end
22
+ end
@@ -6,9 +6,10 @@ module Lib
6
6
  module TL1
7
7
  module Huawei
8
8
  module Message
9
+ # Builds a LOGOUT command to end an NBI session.
9
10
  class Logout < Lib::TL1::Huawei::Message::Input
10
11
  def initialize
11
- super
12
+ super(command: 'LOGOUT')
12
13
  end
13
14
  end
14
15
  end
@@ -6,8 +6,8 @@ module Lib
6
6
  module TL1
7
7
  module Huawei
8
8
  module Message
9
+ # Queries the NBI management system version.
9
10
  class LstBmsVersion < Lib::TL1::Huawei::Message::Input
10
-
11
11
  end
12
12
  end
13
13
  end
@@ -6,8 +6,8 @@ module Lib
6
6
  module TL1
7
7
  module Huawei
8
8
  module Message
9
+ # Queries boards by device, frame, slot, and board type.
9
10
  class LstBoard < Lib::TL1::Huawei::Message::Input
10
-
11
11
  attr_reader :dev, :did, :onu_locate_info, :frame_number, :slot_number, :board_type, :show_option
12
12
 
13
13
  def initialize(
@@ -19,13 +19,9 @@ module Lib
19
19
  board_type: nil,
20
20
  show_option: nil
21
21
  )
22
- @dev = dev
23
- @did = did
24
- @frame_number = frame_number
25
- @onu_locate_info = onu_locate_info
26
- @slot_number = slot_number
27
- @board_type = board_type
28
- @show_option = show_option
22
+ set_attributes(
23
+ dev:, did:, frame_number:, onu_locate_info:, slot_number:, board_type:, show_option:
24
+ )
29
25
 
30
26
  super(
31
27
  aid: hash_to_string(
@@ -39,10 +35,8 @@ module Lib
39
35
  payload: __show_option(*show_option)
40
36
  )
41
37
  end
42
-
43
38
  end
44
39
  end
45
40
  end
46
41
  end
47
42
  end
48
-
@@ -6,9 +6,11 @@ module Lib
6
6
  module TL1
7
7
  module Huawei
8
8
  module Message
9
+ # Queries devices and optionally selects returned device attributes.
9
10
  class LstDev < Lib::TL1::Huawei::Message::Input
11
+ attr_reader :did, :dev, :dev_ip, :dev_type, :dev_ver, :onu_locate_info, :show_option, :user_id
10
12
 
11
- attr_reader :did, :dev, :dev_ip, :dev_type, :dev_ver, :onu_locate_info, :showoption, :user_id
13
+ alias showoption show_option
12
14
 
13
15
  def initialize(
14
16
  did: nil,
@@ -20,15 +22,9 @@ module Lib
20
22
  show_option: [],
21
23
  user_id: nil
22
24
  )
23
-
24
- @did = did
25
- @dev = dev
26
- @dev_ip = dev_ip
27
- @dt = dev_type
28
- @dev_ver = dev_ver
29
- @onu_locate_info = onu_locate_info
30
- @show_option = show_option
31
- @user_id = user_id
25
+ set_attributes(
26
+ did:, dev:, dev_ip:, dev_type:, dev_ver:, onu_locate_info:, show_option:, user_id:
27
+ )
32
28
 
33
29
  super(
34
30
  aid: hash_to_string(
@@ -44,10 +40,9 @@ module Lib
44
40
  user_id: user_id
45
41
  )
46
42
  )
47
-
48
43
  end
49
44
  end
50
45
  end
51
46
  end
52
47
  end
53
- end
48
+ end
@@ -1,12 +1,15 @@
1
- require_relative "input"
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'input'
2
4
 
3
5
  module Lib
4
6
  module TL1
5
7
  module Huawei
6
8
  module Message
9
+ # Queries management system information.
7
10
  class LstEmfSysInfo < Lib::TL1::Huawei::Message::Input
8
11
  def initialize
9
- super
12
+ super(command: 'LST-EMFSYSINFO')
10
13
  end
11
14
  end
12
15
  end
@@ -6,24 +6,21 @@ module Lib
6
6
  module TL1
7
7
  module Huawei
8
8
  module Message
9
+ # Queries frames belonging to a device.
9
10
  class LstFrame < Lib::TL1::Huawei::Message::Input
10
-
11
11
  attr_reader :dev, :did, :frame_number, :show_option
12
12
 
13
13
  def initialize(dev: nil, did: nil, frame_number: nil, show_option: nil)
14
- @dev = dev
15
- @did = did
16
- @frame_number = frame_number
17
- @show_option = show_option
14
+ set_attributes(
15
+ dev:, did:, frame_number:, show_option:
16
+ )
18
17
  super(
19
18
  aid: hash_to_string(dev: dev, did: did, fn: frame_number),
20
19
  payload: __show_option(*show_option)
21
20
  )
22
21
  end
23
-
24
22
  end
25
23
  end
26
24
  end
27
25
  end
28
26
  end
29
-
@@ -5,22 +5,19 @@ module Lib
5
5
  module TL1
6
6
  module Huawei
7
7
  module Message
8
+ # Queries GEM connections by ONT, GEM port, and VLAN.
8
9
  class LstGemConnection < Lib::TL1::Huawei::Message::Input
9
- attr_reader :did, :dev, :frame_number, :slot_number, :port_number, :ont_id, :gem_port_id, :vlan_id, :show_option
10
+ attr_reader :did, :dev, :frame_number, :slot_number, :port_number, :ont_id, :gem_port_id, :vlan_id,
11
+ :show_option
10
12
 
11
13
  def initialize(
12
14
  did: nil, dev: nil, frame_number: nil, slot_number: nil, port_number: nil,
13
15
  ont_id: nil, gem_port_id: nil, vlan_id: nil, show_option: []
14
16
  )
15
- @did = did
16
- @dev = dev
17
- @frame_number = frame_number
18
- @slot_number = slot_number
19
- @port_number = port_number
20
- @ont_id = ont_id
21
- @gem_port_id = gem_port_id
22
- @vlan_id = vlan_id
23
- @show_option = show_option
17
+ set_attributes(
18
+ did:, dev:, frame_number:, slot_number:, port_number:, ont_id:, gem_port_id:, vlan_id:,
19
+ show_option:
20
+ )
24
21
  super(
25
22
  aid: hash_to_string(
26
23
  did: did, dev: dev, fn: frame_number, sn: slot_number, pn: port_number,
@@ -5,6 +5,7 @@ module Lib
5
5
  module TL1
6
6
  module Huawei
7
7
  module Message
8
+ # Queries GEM ports belonging to an ONT.
8
9
  class LstGemPort < Lib::TL1::Huawei::Message::Input
9
10
  attr_reader :did, :dev, :frame_number, :slot_number, :port_number, :ont_id, :gem_port_id, :show_option
10
11
 
@@ -12,14 +13,9 @@ module Lib
12
13
  did: nil, dev: nil, frame_number: nil, slot_number: nil, port_number: nil,
13
14
  ont_id: nil, gem_port_id: nil, show_option: []
14
15
  )
15
- @did = did
16
- @dev = dev
17
- @frame_number = frame_number
18
- @slot_number = slot_number
19
- @port_number = port_number
20
- @ont_id = ont_id
21
- @gem_port_id = gem_port_id
22
- @show_option = show_option
16
+ set_attributes(
17
+ did:, dev:, frame_number:, slot_number:, port_number:, ont_id:, gem_port_id:, show_option:
18
+ )
23
19
  super(
24
20
  aid: hash_to_string(
25
21
  did: did, dev: dev, fn: frame_number, sn: slot_number,
@@ -6,18 +6,16 @@ module Lib
6
6
  module TL1
7
7
  module Huawei
8
8
  module Message
9
- class LstGponNniPort < Lib::TL1::Huawei::Message::Input
10
-
9
+ # Queries automatically discovered ONTs by serial number or GPON port.
10
+ class LstGponAutoFind < Lib::TL1::Huawei::Message::Input
11
11
  attr_reader :did, :dev, :frame_number, :slot_number, :port_number, :ont_sn
12
12
 
13
13
  def initialize(did: nil, dev: nil, frame_number: nil, slot_number: nil, port_number: nil, ont_sn: nil)
14
- @did = did
15
- @dev = dev
16
- @frame_number = frame_number
17
- @slot_number = slot_number
18
- @port_number = port_number
19
- @ont_sn = ont_sn
14
+ set_attributes(
15
+ did:, dev:, frame_number:, slot_number:, port_number:, ont_sn:
16
+ )
20
17
  super(
18
+ command: 'LST-GPONONTAUTOFIND',
21
19
  aid: hash_to_string(
22
20
  did: did, dev: dev, fn: frame_number, sn: slot_number, pn: port_number, ont_sn: ont_sn
23
21
  )
@@ -6,15 +6,14 @@ module Lib
6
6
  module TL1
7
7
  module Huawei
8
8
  module Message
9
+ # Queries digital diagnostic monitoring values for a GPON port.
9
10
  class LstGponDdmInfo < Lib::TL1::Huawei::Message::Input
10
11
  attr_reader :did, :dev, :frame_number, :slot_number, :port_number
11
12
 
12
13
  def initialize(did: nil, dev: nil, frame_number: nil, slot_number: nil, port_number: nil)
13
- @did = did
14
- @dev = dev
15
- @frame_number = frame_number
16
- @slot_number = slot_number
17
- @port_number = port_number
14
+ set_attributes(
15
+ did:, dev:, frame_number:, slot_number:, port_number:
16
+ )
18
17
  super(
19
18
  aid: hash_to_string(
20
19
  did: did, dev: dev, fn: frame_number, sn: slot_number, pn: port_number
@@ -6,6 +6,7 @@ module Lib
6
6
  module TL1
7
7
  module Huawei
8
8
  module Message
9
+ # Queries GPON line profiles, with device and profile selectors in the payload.
9
10
  class LstGponLineProfile < Lib::TL1::Huawei::Message::Input
10
11
  attr_reader :did, :dev, :prof_id
11
12