rbzk 0.1.6 → 0.1.7

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: dc6b7b78fa88e4e3cbea5a63aff9a333e1dea98a796de0cc2ab1a8d875f10a64
4
- data.tar.gz: ab1527c24665247a5de3393fdf83a9aa0f4c74fe9fe933554ed105968584b56e
3
+ metadata.gz: 1290a1fd6cc12310c5471f045a47e0c8d5b598326d7e5db899bde02ec6bc96ee
4
+ data.tar.gz: 172c829144c8aa97e998c19803d5d19fd9d379f38c93170295f149f4a163c2c0
5
5
  SHA512:
6
- metadata.gz: ee91215cdd36830c39e259ab1e42384c8f155d896cb52254105aaf6d36b4167fc7becbd9b4cb632631e32ef23ce2ac57c2de3ecc32990857a56b74a25e26b2d2
7
- data.tar.gz: 9bad7c48f98845263d7183362ae7d19a453035747100605e05f6523a0dafd5d9ce9e264dcbfdf2950c297dcff448027716f9edc1a41c18196d89acf4e5942e8e
6
+ metadata.gz: 4ee4a5a83b9f129158ea253868b4033d6c0013360d67fe05ba7518a67c6baaf971eeaf764ef447638a0e029a927524ccc51e7871ef0c22ea89b98d3608579542
7
+ data.tar.gz: 75af5b6ac2c57fe3e0dce24be118ac1fc69cb941d8d78bb8d706da6913ddcc9cf36e669c12e2f114c366eded3be18da5e3bec956e071657250a0812acf57810d
data/README.md CHANGED
@@ -229,7 +229,7 @@ else
229
229
  # Status: Check-in, Check-out, etc. (Refer to ZK documentation for specific status codes)
230
230
  puts " Status: #{log.status}"
231
231
  # Punch: Fingerprint, Password, Card, etc. (Refer to ZK documentation)
232
- puts " Punch Type: #{log.punch}"
232
+ puts " Punch Type: #{log.punch_name}"
233
233
  puts " Timestamp: #{log.timestamp.strftime('%Y-%m-%d %H:%M:%S')}"
234
234
  puts "---"
235
235
  end
data/bin/console CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- require "bundler/setup"
4
- require "rbzk"
3
+ require 'bundler/setup'
4
+ require 'rbzk'
5
5
 
6
6
  # You can add fixtures and/or initialization code here to make experimenting
7
7
  # with your gem easier. You can also use a different console, if you like.
@@ -10,5 +10,5 @@ require "rbzk"
10
10
  # require "pry"
11
11
  # Pry.start
12
12
 
13
- require "irb"
13
+ require 'irb'
14
14
  IRB.start(__FILE__)
@@ -12,6 +12,25 @@ module RBZK
12
12
  @uid = uid
13
13
  end
14
14
 
15
+ # Helper predicate for check-in (punch==0)
16
+ def check_in?
17
+ @punch == 0
18
+ end
19
+
20
+ # Helper predicate for check-out (punch==1)
21
+ def check_out?
22
+ @punch == 1
23
+ end
24
+
25
+ # Human readable punch name (0=Check In, 1=Check Out)
26
+ def punch_name
27
+ case @punch
28
+ when 0 then 'Check In'
29
+ when 1 then 'Check Out'
30
+ else "Punch (#{@punch})"
31
+ end
32
+ end
33
+
15
34
  def to_s
16
35
  "#{@user_id} #{@timestamp} #{@status} #{@punch} #{@uid}"
17
36
  end
@@ -13,7 +13,6 @@ require 'terminal-table'
13
13
  module RBZK
14
14
  module CLI
15
15
  class Commands < Thor
16
-
17
16
  # Global options
18
17
  class_option :ip, type: :string, desc: 'IP address of the device'
19
18
  class_option :port, type: :numeric, desc: 'Port number (default: 4370)'
@@ -24,10 +23,13 @@ module RBZK
24
23
  class_option :no_ping, type: :boolean, desc: 'Skip ping check'
25
24
  class_option :encoding, type: :string, desc: 'Encoding for strings (default: UTF-8)'
26
25
 
27
- desc "info [IP]", "Get device information"
26
+ def self.exit_on_failure?
27
+ true
28
+ end
28
29
 
29
- def info(ip = nil)
30
+ desc 'info [IP]', 'Get device information'
30
31
 
32
+ def info(ip = nil)
31
33
  # Use IP from options if not provided as argument
32
34
  ip ||= options[:ip] || @config['ip']
33
35
 
@@ -59,16 +61,16 @@ module RBZK
59
61
  if defined?(::Terminal) && defined?(::Terminal::Table)
60
62
  # Pretty table output
61
63
  table = ::Terminal::Table.new do |t|
62
- t.title = "Device Information"
64
+ t.title = 'Device Information'
63
65
  device_info.each do |key, value|
64
- t << [ key, value ]
66
+ t << [key, value]
65
67
  end
66
68
  end
67
69
 
68
70
  puts table
69
71
  else
70
72
  # Fallback plain text output
71
- puts "Device Information:"
73
+ puts 'Device Information:'
72
74
  device_info.each do |key, value|
73
75
  puts "#{key}: #{value}"
74
76
  end
@@ -76,61 +78,61 @@ module RBZK
76
78
  end
77
79
  end
78
80
 
79
- desc "refresh [IP]", "Refresh device data"
81
+ desc 'refresh [IP]', 'Refresh device data'
80
82
 
81
83
  def refresh(ip = nil)
82
84
  # Use IP from options if not provided as argument
83
85
  ip ||= options[:ip] || @config['ip']
84
86
 
85
87
  with_connection(ip, options) do |conn|
86
- puts "Refreshing device data..."
88
+ puts 'Refreshing device data...'
87
89
  result = conn.refresh_data
88
- puts "✓ Device data refreshed successfully!" if result
90
+ puts '✓ Device data refreshed successfully!' if result
89
91
  end
90
92
  end
91
93
 
92
- desc "users [IP]", "Get users from the device"
94
+ desc 'users [IP]', 'Get users from the device'
93
95
 
94
96
  def users(ip = nil)
95
97
  # Use IP from options if not provided as argument
96
98
  ip ||= options[:ip] || @config['ip']
97
99
  with_connection(ip, options) do |conn|
98
- puts "Getting users..."
100
+ puts 'Getting users...'
99
101
  users = conn.get_users
100
102
  display_users(users)
101
103
  end
102
104
  end
103
105
 
104
106
  # Add aliases for common log commands
105
- desc "logs-today [IP]", "Get today's attendance logs"
106
- map "logs-today" => "logs"
107
+ desc 'logs-today [IP]', "Get today's attendance logs"
108
+ map 'logs-today' => 'logs'
107
109
 
108
110
  def logs_today(ip = nil)
109
- invoke :logs, [ ip ], { today: true }.merge(options)
111
+ invoke :logs, [ip], { today: true }.merge(options)
110
112
  end
111
113
 
112
- desc "logs-yesterday [IP]", "Get yesterday's attendance logs"
113
- map "logs-yesterday" => "logs"
114
+ desc 'logs-yesterday [IP]', "Get yesterday's attendance logs"
115
+ map 'logs-yesterday' => 'logs'
114
116
 
115
117
  def logs_yesterday(ip = nil)
116
- invoke :logs, [ ip ], { yesterday: true }.merge(options)
118
+ invoke :logs, [ip], { yesterday: true }.merge(options)
117
119
  end
118
120
 
119
- desc "logs-week [IP]", "Get this week's attendance logs"
120
- map "logs-week" => "logs"
121
+ desc 'logs-week [IP]', "Get this week's attendance logs"
122
+ map 'logs-week' => 'logs'
121
123
 
122
124
  def logs_week(ip = nil)
123
- invoke :logs, [ ip ], { week: true }.merge(options)
125
+ invoke :logs, [ip], { week: true }.merge(options)
124
126
  end
125
127
 
126
- desc "logs-month [IP]", "Get this month's attendance logs"
127
- map "logs-month" => "logs"
128
+ desc 'logs-month [IP]', "Get this month's attendance logs"
129
+ map 'logs-month' => 'logs'
128
130
 
129
131
  def logs_month(ip = nil)
130
- invoke :logs, [ ip ], { month: true }.merge(options)
132
+ invoke :logs, [ip], { month: true }.merge(options)
131
133
  end
132
134
 
133
- desc "logs-all [IP]", "Get all attendance logs without limit"
135
+ desc 'logs-all [IP]', 'Get all attendance logs without limit'
134
136
 
135
137
  def logs_all(ip = nil)
136
138
  # Use IP from options if not provided as argument
@@ -138,7 +140,7 @@ module RBZK
138
140
 
139
141
  with_connection(ip, options) do |conn|
140
142
  # Get attendance logs
141
- puts "Getting all attendance logs (this may take a while)..."
143
+ puts 'Getting all attendance logs (this may take a while)...'
142
144
  logs = conn.get_attendance_logs
143
145
  total_logs = logs.size
144
146
  puts "Total logs: #{total_logs}" if options[:verbose]
@@ -150,15 +152,17 @@ module RBZK
150
152
  if defined?(::Terminal) && defined?(::Terminal::Table)
151
153
  # Pretty table output
152
154
  table = ::Terminal::Table.new do |t|
153
- t.title = "All Attendance Logs (Showing All Records)"
154
- t.headings = [ 'User ID', 'Time', 'Status' ]
155
+ t.title = 'All Attendance Logs (Showing All Records)'
156
+ t.headings = ['UID', 'User ID', 'Time', 'Status', 'Punch Type']
155
157
 
156
158
  # Show all logs in the table
157
159
  logs.each do |log|
158
160
  t << [
161
+ log.uid,
159
162
  log.user_id,
160
163
  log.timestamp.strftime('%Y-%m-%d %H:%M:%S'),
161
- format_status(log.status)
164
+ log.status,
165
+ log.punch_name
162
166
  ]
163
167
  end
164
168
  end
@@ -167,7 +171,7 @@ module RBZK
167
171
  else
168
172
  # Fallback plain text output
169
173
  logs.each do |log|
170
- puts " User ID: #{log.user_id}, Time: #{log.timestamp.strftime('%Y-%m-%d %H:%M:%S')}, Status: #{format_status(log.status)}"
174
+ puts " UID: #{log.uid}, User ID: #{log.user_id}, Time: #{log.timestamp.strftime('%Y-%m-%d %H:%M:%S')}, Status: #{format_status(log.status)}, Punch: #{log.punch_name}"
171
175
  end
172
176
  end
173
177
  else
@@ -176,31 +180,32 @@ module RBZK
176
180
  end
177
181
  end
178
182
 
179
- desc "logs-custom START_DATE END_DATE [IP]", "Get logs for a custom date range (YYYY-MM-DD)"
183
+ desc 'logs-custom START_DATE END_DATE [IP]', 'Get logs for a custom date range (YYYY-MM-DD)'
180
184
 
181
185
  def logs_custom(start_date, end_date, ip = nil)
182
186
  # Use IP from options if not provided as argument
183
187
  ip ||= options[:ip] || @config['ip']
184
- invoke :logs, [ ip ], { start_date: start_date, end_date: end_date }.merge(options)
188
+ invoke :logs, [ip], { start_date: start_date, end_date: end_date }.merge(options)
185
189
  end
186
190
 
187
- desc "logs [IP]", "Get attendance logs"
191
+ desc 'logs [IP]', 'Get attendance logs'
188
192
  method_option :today, type: :boolean, desc: "Get only today's logs"
189
193
  method_option :yesterday, type: :boolean, desc: "Get only yesterday's logs"
190
194
  method_option :week, type: :boolean, desc: "Get this week's logs"
191
195
  method_option :month, type: :boolean, desc: "Get this month's logs"
192
- method_option :start_date, type: :string, desc: "Start date for custom range (YYYY-MM-DD)"
193
- method_option :end_date, type: :string, desc: "End date for custom range (YYYY-MM-DD)"
194
- method_option :start_time, type: :string, desc: "Start time for custom range (HH:MM)"
195
- method_option :end_time, type: :string, desc: "End time for custom range (HH:MM)"
196
- method_option :limit, type: :numeric, default: 25, desc: "Limit the number of logs displayed (default: 25, use 0 for all)"
196
+ method_option :start_date, type: :string, desc: 'Start date for custom range (YYYY-MM-DD)'
197
+ method_option :end_date, type: :string, desc: 'End date for custom range (YYYY-MM-DD)'
198
+ method_option :start_time, type: :string, desc: 'Start time for custom range (HH:MM)'
199
+ method_option :end_time, type: :string, desc: 'End time for custom range (HH:MM)'
200
+ method_option :limit, type: :numeric, default: 25,
201
+ desc: 'Limit the number of logs displayed (default: 25, use 0 for all)'
197
202
 
198
203
  def logs(ip = nil)
199
204
  # Use IP from options if not provided as argument
200
205
  ip ||= options[:ip] || @config['ip']
201
206
  with_connection(ip, options) do |conn|
202
207
  # Get attendance logs
203
- puts "Getting attendance logs..."
208
+ puts 'Getting attendance logs...'
204
209
  logs = conn.get_attendance_logs
205
210
  total_logs = logs.size
206
211
  puts "Total logs: #{total_logs}" if options[:verbose]
@@ -222,7 +227,8 @@ module RBZK
222
227
  elsif options[:month]
223
228
  today = Date.today
224
229
  start_of_month = Date.new(today.year, today.month, 1)
225
- logs = filter_logs_by_datetime(logs, start_of_month, today, options[:start_time], options[:end_time])
230
+ logs = filter_logs_by_datetime(logs, start_of_month, today, options[:start_time],
231
+ options[:end_time])
226
232
  "This Month's Attendance Logs (#{start_of_month} to #{today})"
227
233
  elsif options[:start_date] && options[:end_date]
228
234
  begin
@@ -233,11 +239,12 @@ module RBZK
233
239
  puts "Filtering logs from #{start_date} to #{end_date}..." if options[:verbose]
234
240
 
235
241
  # Use the filter_logs_by_datetime method
236
- logs = filter_logs_by_datetime(logs, start_date, end_date, options[:start_time], options[:end_time])
242
+ logs = filter_logs_by_datetime(logs, start_date, end_date, options[:start_time],
243
+ options[:end_time])
237
244
 
238
245
  "Attendance Logs (#{start_date} to #{end_date})"
239
246
  rescue ArgumentError
240
- puts "Error: Invalid date format. Please use YYYY-MM-DD format."
247
+ puts 'Error: Invalid date format. Please use YYYY-MM-DD format.'
241
248
  return
242
249
  end
243
250
  elsif options[:start_date]
@@ -249,11 +256,12 @@ module RBZK
249
256
  puts "Filtering logs from #{start_date} onwards..." if options[:verbose]
250
257
 
251
258
  # Use the filter_logs_by_datetime method
252
- logs = filter_logs_by_datetime(logs, start_date, end_date, options[:start_time], options[:end_time])
259
+ logs = filter_logs_by_datetime(logs, start_date, end_date, options[:start_time],
260
+ options[:end_time])
253
261
 
254
262
  "Attendance Logs (#{start_date} to #{end_date})"
255
263
  rescue ArgumentError
256
- puts "Error: Invalid date format. Please use YYYY-MM-DD format."
264
+ puts 'Error: Invalid date format. Please use YYYY-MM-DD format.'
257
265
  return
258
266
  end
259
267
  elsif options[:end_date]
@@ -266,15 +274,16 @@ module RBZK
266
274
  puts "Filtering logs from #{start_date} to #{end_date}..." if options[:verbose]
267
275
 
268
276
  # Use the filter_logs_by_datetime method
269
- logs = filter_logs_by_datetime(logs, start_date, end_date, options[:start_time], options[:end_time])
277
+ logs = filter_logs_by_datetime(logs, start_date, end_date, options[:start_time],
278
+ options[:end_time])
270
279
 
271
280
  "Attendance Logs (#{start_date} to #{end_date})"
272
281
  rescue ArgumentError
273
- puts "Error: Invalid date format. Please use YYYY-MM-DD format."
282
+ puts 'Error: Invalid date format. Please use YYYY-MM-DD format.'
274
283
  return
275
284
  end
276
285
  else
277
- "All Attendance Logs"
286
+ 'All Attendance Logs'
278
287
  end
279
288
 
280
289
  # Display logs
@@ -288,15 +297,17 @@ module RBZK
288
297
  if defined?(::Terminal) && defined?(::Terminal::Table)
289
298
  # Pretty table output
290
299
  table = ::Terminal::Table.new do |t|
291
- t.title = title || "Attendance Logs"
292
- t.headings = [ 'User ID', 'Time', 'Status' ]
300
+ t.title = title || 'Attendance Logs'
301
+ t.headings = ['UID', 'User ID', 'Time', 'Status', 'Punch Type']
293
302
 
294
303
  # Show logs in the table based on limit
295
304
  display_logs.each do |log|
296
305
  t << [
306
+ log.uid,
297
307
  log.user_id,
298
308
  log.timestamp.strftime('%Y-%m-%d %H:%M:%S'),
299
- format_status(log.status)
309
+ log.status.to_s,
310
+ log.punch_name
300
311
  ]
301
312
  end
302
313
  end
@@ -310,12 +321,10 @@ module RBZK
310
321
  else
311
322
  # Fallback plain text output
312
323
  display_logs.each do |log|
313
- puts " User ID: #{log.user_id}, Time: #{log.timestamp.strftime('%Y-%m-%d %H:%M:%S')}, Status: #{format_status(log.status)}"
324
+ puts " UID: #{log.uid}, User ID: #{log.user_id}, Time: #{log.timestamp.strftime('%Y-%m-%d %H:%M:%S')}, Status: #{format_status(log.status)}, Punch: #{log.punch_name}"
314
325
  end
315
326
 
316
- if logs.size > display_logs.size
317
- puts " ... and #{logs.size - display_logs.size} more records"
318
- end
327
+ puts " ... and #{logs.size - display_logs.size} more records" if logs.size > display_logs.size
319
328
  end
320
329
  else
321
330
  puts "\nNo attendance records found"
@@ -323,26 +332,25 @@ module RBZK
323
332
  end
324
333
  end
325
334
 
326
- desc "clear-logs [IP]", "Clear attendance logs"
327
- map "clear-logs" => :clear_logs
335
+ desc 'clear-logs [IP]', 'Clear attendance logs'
336
+ map 'clear-logs' => :clear_logs
328
337
 
329
338
  def clear_logs(ip = nil)
330
-
331
339
  # Use IP from options if not provided as argument
332
340
  ip ||= options[:ip] || @config['ip']
333
341
  with_connection(ip, options) do |conn|
334
- puts "WARNING: This will delete all attendance logs from the device."
335
- return unless yes?("Are you sure you want to continue? (y/N)")
342
+ puts 'WARNING: This will delete all attendance logs from the device.'
343
+ return unless yes?('Are you sure you want to continue? (y/N)')
336
344
 
337
- puts "Clearing attendance logs..."
345
+ puts 'Clearing attendance logs...'
338
346
  result = conn.clear_attendance
339
- puts "✓ Attendance logs cleared successfully!" if result
347
+ puts '✓ Attendance logs cleared successfully!' if result
340
348
  end
341
349
  end
342
350
 
343
- desc "unlock [IP]", "Unlock the door"
344
- method_option :time, type: :numeric, default: 3, desc: "Unlock time in seconds (default: 3)"
345
- map "unlock" => :unlock_door
351
+ desc 'unlock [IP]', 'Unlock the door'
352
+ method_option :time, type: :numeric, default: 3, desc: 'Unlock time in seconds (default: 3)'
353
+ map 'unlock' => :unlock_door
346
354
 
347
355
  def unlock_door(ip = nil)
348
356
  # Use IP from options if not provided as argument
@@ -354,12 +362,12 @@ module RBZK
354
362
  with_connection(ip, options) do |conn|
355
363
  puts "Unlocking door for #{time} seconds..."
356
364
  result = conn.unlock(time)
357
- puts "✓ Door unlocked successfully!" if result
365
+ puts '✓ Door unlocked successfully!' if result
358
366
  end
359
367
  end
360
368
 
361
- desc "door-state [IP]", "Get the door lock state"
362
- map "door-state" => :door_state
369
+ desc 'door-state [IP]', 'Get the door lock state'
370
+ map 'door-state' => :door_state
363
371
 
364
372
  def door_state(ip = nil)
365
373
  # Use IP from options if not provided as argument
@@ -371,8 +379,8 @@ module RBZK
371
379
  end
372
380
  end
373
381
 
374
- desc "write-lcd [IP] LINE_NUMBER TEXT", "Write text to LCD display"
375
- map "write-lcd" => :write_lcd
382
+ desc 'write-lcd [IP] LINE_NUMBER TEXT', 'Write text to LCD display'
383
+ map 'write-lcd' => :write_lcd
376
384
 
377
385
  def write_lcd(line_number, text, ip = nil)
378
386
  # Use IP from options if not provided as argument
@@ -384,59 +392,59 @@ module RBZK
384
392
  with_connection(ip, options) do |conn|
385
393
  puts "Writing text to LCD line #{line_number}..."
386
394
  result = conn.write_lcd(line_number, text)
387
- puts "✓ Text written to LCD successfully!" if result
395
+ puts '✓ Text written to LCD successfully!' if result
388
396
  end
389
397
  end
390
398
 
391
- desc "clear-lcd [IP]", "Clear the LCD display"
392
- map "clear-lcd" => :clear_lcd
399
+ desc 'clear-lcd [IP]', 'Clear the LCD display'
400
+ map 'clear-lcd' => :clear_lcd
393
401
 
394
402
  def clear_lcd(ip = nil)
395
403
  # Use IP from options if not provided as argument
396
404
  ip ||= options[:ip] || @config['ip']
397
405
 
398
406
  with_connection(ip, options) do |conn|
399
- puts "Clearing LCD display..."
407
+ puts 'Clearing LCD display...'
400
408
  result = conn.clear_lcd
401
- puts "✓ LCD cleared successfully!" if result
409
+ puts '✓ LCD cleared successfully!' if result
402
410
  end
403
411
  end
404
412
 
405
- desc "add-user [IP]", "Add or update a user"
406
- method_option :uid, type: :numeric, desc: "User ID (generated by device if not provided)"
407
- method_option :name, type: :string, default: "", desc: "User name"
408
- method_option :privilege, type: :numeric, default: 0, desc: "User privilege (0=User, 14=Admin)"
409
- method_option :password, type: :string, default: "", desc: "User password"
410
- method_option :group_id, type: :string, default: "", desc: "Group ID"
411
- method_option :user_id, type: :string, default: "", desc: "Custom user ID"
412
- method_option :card, type: :numeric, default: 0, desc: "Card number"
413
- map "add-user" => :add_user
413
+ desc 'add-user [IP]', 'Add or update a user'
414
+ method_option :uid, type: :numeric, desc: 'User ID (generated by device if not provided)'
415
+ method_option :name, type: :string, default: '', desc: 'User name'
416
+ method_option :privilege, type: :numeric, default: 0, desc: 'User privilege (0=User, 14=Admin)'
417
+ method_option :password, type: :string, default: '', desc: 'User password'
418
+ method_option :group_id, type: :string, default: '', desc: 'Group ID'
419
+ method_option :user_id, type: :string, default: '', desc: 'Custom user ID'
420
+ method_option :card, type: :numeric, default: 0, desc: 'Card number'
421
+ map 'add-user' => :add_user
414
422
 
415
423
  def add_user(ip = nil)
416
424
  # Use IP from options if not provided as argument
417
425
  ip ||= options[:ip] || @config['ip']
418
426
 
419
427
  with_connection(ip, options) do |conn|
420
- puts "Adding/updating user..."
428
+ puts 'Adding/updating user...'
421
429
 
422
430
  result = conn.set_user(
423
431
  uid: options[:uid],
424
- name: options[:name] || "",
432
+ name: options[:name] || '',
425
433
  privilege: options[:privilege] || 0,
426
- password: options[:password] || "",
427
- group_id: options[:group_id] || "",
428
- user_id: options[:user_id] || "",
434
+ password: options[:password] || '',
435
+ group_id: options[:group_id] || '',
436
+ user_id: options[:user_id] || '',
429
437
  card: options[:card] || 0
430
438
  )
431
439
 
432
- puts "✓ User added/updated successfully!" if result
440
+ puts '✓ User added/updated successfully!' if result
433
441
  end
434
442
  end
435
443
 
436
- desc "delete-user [IP]", "Delete a user"
437
- method_option :uid, type: :numeric, desc: "User ID (generated by device)"
438
- method_option :user_id, type: :string, desc: "Custom user ID"
439
- map "delete-user" => :delete_user
444
+ desc 'delete-user [IP]', 'Delete a user'
445
+ method_option :uid, type: :numeric, desc: 'User ID (generated by device)'
446
+ method_option :user_id, type: :string, desc: 'Custom user ID'
447
+ map 'delete-user' => :delete_user
440
448
 
441
449
  def delete_user(ip = nil)
442
450
  # Use IP from options if not provided as argument
@@ -444,33 +452,33 @@ module RBZK
444
452
 
445
453
  # Ensure at least one of uid or user_id is provided
446
454
  if options[:uid].nil? && (options[:user_id].nil? || options[:user_id].empty?)
447
- puts "Error: You must provide either --uid"
455
+ puts 'Error: You must provide either --uid'
448
456
  return
449
457
  end
450
458
 
451
459
  with_connection(ip, options) do |conn|
452
- puts "Deleting user..."
460
+ puts 'Deleting user...'
453
461
 
454
462
  # Use the User object with delete_user
455
463
  result = conn.delete_user(uid: options[:uid])
456
464
 
457
465
  if result
458
- puts "✓ User deleted successfully!"
466
+ puts '✓ User deleted successfully!'
459
467
  else
460
- puts "✗ User not found or could not be deleted."
468
+ puts '✗ User not found or could not be deleted.'
461
469
  end
462
470
  end
463
471
  end
464
472
 
465
- desc "get-templates [IP]", "Get all fingerprint templates"
466
- map "get-templates" => :get_templates
473
+ desc 'get-templates [IP]', 'Get all fingerprint templates'
474
+ map 'get-templates' => :get_templates
467
475
 
468
476
  def get_templates(ip = nil)
469
477
  # Use IP from options if not provided as argument
470
478
  ip ||= options[:ip] || @config['ip']
471
479
 
472
480
  with_connection(ip, options) do |conn|
473
- puts "Getting fingerprint templates..."
481
+ puts 'Getting fingerprint templates...'
474
482
  templates = conn.get_templates
475
483
 
476
484
  if templates && !templates.empty?
@@ -478,8 +486,8 @@ module RBZK
478
486
 
479
487
  # Use Terminal::Table for pretty output
480
488
  table = ::Terminal::Table.new do |t|
481
- t.title = "Fingerprint Templates"
482
- t.headings = [ 'UID', 'Finger ID', 'Valid', 'Size' ]
489
+ t.title = 'Fingerprint Templates'
490
+ t.headings = ['UID', 'Finger ID', 'Valid', 'Size']
483
491
 
484
492
  templates.each do |template|
485
493
  t << [
@@ -493,16 +501,16 @@ module RBZK
493
501
 
494
502
  puts table
495
503
  else
496
- puts "✓ No fingerprint templates found"
504
+ puts '✓ No fingerprint templates found'
497
505
  end
498
506
  end
499
507
  end
500
508
 
501
- desc "get-user-template [IP]", "Get a specific user's fingerprint template"
502
- method_option :uid, type: :numeric, desc: "User ID (generated by device)"
503
- method_option :user_id, type: :string, desc: "Custom user ID"
504
- method_option :finger_id, type: :numeric, default: 0, desc: "Finger ID (0-9)"
505
- map "get-user-template" => :get_user_template
509
+ desc 'get-user-template [IP]', "Get a specific user's fingerprint template"
510
+ method_option :uid, type: :numeric, desc: 'User ID (generated by device)'
511
+ method_option :user_id, type: :string, desc: 'Custom user ID'
512
+ method_option :finger_id, type: :numeric, default: 0, desc: 'Finger ID (0-9)'
513
+ map 'get-user-template' => :get_user_template
506
514
 
507
515
  def get_user_template(ip = nil)
508
516
  # Use IP from options if not provided as argument
@@ -510,37 +518,37 @@ module RBZK
510
518
 
511
519
  # Ensure at least one of uid or user_id is provided
512
520
  if options[:uid].nil? && (options[:user_id].nil? || options[:user_id].empty?)
513
- puts "Error: You must provide either --uid or --user-id"
521
+ puts 'Error: You must provide either --uid or --user-id'
514
522
  return
515
523
  end
516
524
 
517
525
  with_connection(ip, options) do |conn|
518
- puts "Getting user fingerprint template..."
526
+ puts 'Getting user fingerprint template...'
519
527
 
520
528
  # Extract parameters from options
521
529
  uid = options[:uid] || 0
522
- user_id = options[:user_id] || ""
530
+ user_id = options[:user_id] || ''
523
531
  finger_id = options[:finger_id] || 0
524
532
 
525
533
  template = conn.get_user_template(uid: uid, temp_id: finger_id, user_id: user_id)
526
534
 
527
535
  if template
528
- puts "✓ Found fingerprint template:"
536
+ puts '✓ Found fingerprint template:'
529
537
  puts " User ID: #{template.uid}"
530
538
  puts " Finger ID: #{template.fid}"
531
539
  puts " Valid: #{template.valid == 1 ? 'Yes' : 'No'}"
532
540
  puts " Size: #{template.size} bytes"
533
541
  else
534
- puts "✗ Fingerprint template not found"
542
+ puts '✗ Fingerprint template not found'
535
543
  end
536
544
  end
537
545
  end
538
546
 
539
- desc "delete-template [IP]", "Delete a specific fingerprint template"
540
- method_option :uid, type: :numeric, desc: "User ID (generated by device)"
541
- method_option :user_id, type: :string, desc: "Custom user ID"
542
- method_option :finger_id, type: :numeric, default: 0, desc: "Finger ID (0-9)"
543
- map "delete-template" => :delete_template
547
+ desc 'delete-template [IP]', 'Delete a specific fingerprint template'
548
+ method_option :uid, type: :numeric, desc: 'User ID (generated by device)'
549
+ method_option :user_id, type: :string, desc: 'Custom user ID'
550
+ method_option :finger_id, type: :numeric, default: 0, desc: 'Finger ID (0-9)'
551
+ map 'delete-template' => :delete_template
544
552
 
545
553
  def delete_template(ip = nil)
546
554
  # Use IP from options if not provided as argument
@@ -548,31 +556,31 @@ module RBZK
548
556
 
549
557
  # Ensure at least one of uid or user_id is provided
550
558
  if options[:uid].nil? && (options[:user_id].nil? || options[:user_id].empty?)
551
- puts "Error: You must provide either --uid or --user-id"
559
+ puts 'Error: You must provide either --uid or --user-id'
552
560
  return
553
561
  end
554
562
 
555
563
  with_connection(ip, options) do |conn|
556
- puts "Deleting fingerprint template..."
564
+ puts 'Deleting fingerprint template...'
557
565
 
558
566
  # Extract parameters from options
559
567
  uid = options[:uid] || 0
560
- user_id = options[:user_id] || ""
568
+ user_id = options[:user_id] || ''
561
569
  finger_id = options[:finger_id] || 0
562
570
 
563
571
  result = conn.delete_user_template(uid: uid, temp_id: finger_id, user_id: user_id)
564
572
 
565
573
  if result
566
- puts "✓ Fingerprint template deleted successfully!"
574
+ puts '✓ Fingerprint template deleted successfully!'
567
575
  else
568
- puts "✗ Fingerprint template not found or could not be deleted"
576
+ puts '✗ Fingerprint template not found or could not be deleted'
569
577
  end
570
578
  end
571
579
  end
572
580
 
573
- desc "test-voice [IP]", "Test the device voice"
574
- method_option :index, type: :numeric, desc: "Sound index to play (0-35, default: 0)"
575
- map "test-voice" => :test_voice
581
+ desc 'test-voice [IP]', 'Test the device voice'
582
+ method_option :index, type: :numeric, desc: 'Sound index to play (0-35, default: 0)'
583
+ map 'test-voice' => :test_voice
576
584
 
577
585
  def test_voice(ip = nil)
578
586
  # Use IP from options if not provided as argument
@@ -583,89 +591,89 @@ module RBZK
583
591
 
584
592
  # Print available sound indices if verbose
585
593
  if options[:verbose]
586
- puts "Available sound indices:"
587
- puts " 0: Thank You"
588
- puts " 1: Incorrect Password"
589
- puts " 2: Access Denied"
590
- puts " 3: Invalid ID"
591
- puts " 4: Please try again"
592
- puts " 5: Duplicate ID"
593
- puts " 6: The clock is flow"
594
- puts " 7: The clock is full"
595
- puts " 8: Duplicate finger"
596
- puts " 9: Duplicated punch"
597
- puts "10: Beep kuko"
598
- puts "11: Beep siren"
599
- puts "13: Beep bell"
600
- puts "18: Windows(R) opening sound"
601
- puts "20: Fingerprint not emolt"
602
- puts "21: Password not emolt"
603
- puts "22: Badges not emolt"
604
- puts "23: Face not emolt"
605
- puts "24: Beep standard"
606
- puts "30: Invalid user"
607
- puts "31: Invalid time period"
608
- puts "32: Invalid combination"
609
- puts "33: Illegal Access"
610
- puts "34: Disk space full"
611
- puts "35: Duplicate fingerprint"
612
- puts "51: Focus eyes on the green box"
594
+ puts 'Available sound indices:'
595
+ puts ' 0: Thank You'
596
+ puts ' 1: Incorrect Password'
597
+ puts ' 2: Access Denied'
598
+ puts ' 3: Invalid ID'
599
+ puts ' 4: Please try again'
600
+ puts ' 5: Duplicate ID'
601
+ puts ' 6: The clock is flow'
602
+ puts ' 7: The clock is full'
603
+ puts ' 8: Duplicate finger'
604
+ puts ' 9: Duplicated punch'
605
+ puts '10: Beep kuko'
606
+ puts '11: Beep siren'
607
+ puts '13: Beep bell'
608
+ puts '18: Windows(R) opening sound'
609
+ puts '20: Fingerprint not emolt'
610
+ puts '21: Password not emolt'
611
+ puts '22: Badges not emolt'
612
+ puts '23: Face not emolt'
613
+ puts '24: Beep standard'
614
+ puts '30: Invalid user'
615
+ puts '31: Invalid time period'
616
+ puts '32: Invalid combination'
617
+ puts '33: Illegal Access'
618
+ puts '34: Disk space full'
619
+ puts '35: Duplicate fingerprint'
620
+ puts '51: Focus eyes on the green box'
613
621
  end
614
622
 
615
623
  with_connection(ip, options) do |conn|
616
624
  puts "Testing device voice with index #{index}..."
617
625
  result = conn.test_voice(index)
618
- puts "✓ Voice test successful!" if result
626
+ puts '✓ Voice test successful!' if result
619
627
  end
620
628
  end
621
629
 
622
- desc "restart [IP]", "Restart the device"
630
+ desc 'restart [IP]', 'Restart the device'
623
631
 
624
632
  def restart(ip = nil)
625
633
  # Use IP from options if not provided as argument
626
634
  ip ||= options[:ip] || @config['ip']
627
635
 
628
- if yes?("Are you sure you want to restart the device? (y/N)")
636
+ if yes?('Are you sure you want to restart the device? (y/N)')
629
637
  with_connection(ip, options.merge(skip_disconnect_after_yield: true)) do |conn|
630
- puts "Restarting device..."
638
+ puts 'Restarting device...'
631
639
  result = conn.restart
632
- puts "✓ Device restart command sent successfully!" if result
633
- puts "The device will restart now. You may need to wait a few moments before reconnecting."
640
+ puts '✓ Device restart command sent successfully!' if result
641
+ puts 'The device will restart now. You may need to wait a few moments before reconnecting.'
634
642
  end
635
643
  else
636
- puts "Operation cancelled."
644
+ puts 'Operation cancelled.'
637
645
  end
638
646
  end
639
647
 
640
- desc "poweroff [IP]", "Power off the device"
648
+ desc 'poweroff [IP]', 'Power off the device'
641
649
 
642
650
  def poweroff(ip = nil)
643
651
  # Use IP from options if not provided as argument
644
652
  ip ||= options[:ip] || @config['ip']
645
653
 
646
- if yes?("Are you sure you want to power off the device? (y/N)")
654
+ if yes?('Are you sure you want to power off the device? (y/N)')
647
655
  with_connection(ip, options.merge(skip_disconnect_after_yield: true)) do |conn|
648
- puts "Powering off device..."
656
+ puts 'Powering off device...'
649
657
  result = conn.poweroff
650
- puts "✓ Device poweroff command sent successfully!" if result
651
- puts "The device will power off now. You will need to manually power it back on."
658
+ puts '✓ Device poweroff command sent successfully!' if result
659
+ puts 'The device will power off now. You will need to manually power it back on.'
652
660
  end
653
661
  else
654
- puts "Operation cancelled."
662
+ puts 'Operation cancelled.'
655
663
  end
656
664
  end
657
665
 
658
- desc "config", "Show current configuration"
666
+ desc 'config', 'Show current configuration'
659
667
 
660
668
  def config
661
- puts "RBZK Configuration"
662
- puts "=================="
669
+ puts 'RBZK Configuration'
670
+ puts '=================='
663
671
  @config.to_h.each do |key, value|
664
672
  puts "#{key}: #{value}"
665
673
  end
666
674
  end
667
675
 
668
- desc "config-set KEY VALUE", "Set a configuration value"
676
+ desc 'config-set KEY VALUE', 'Set a configuration value'
669
677
 
670
678
  def config_set(key, value)
671
679
  # Convert value to appropriate type
@@ -683,16 +691,16 @@ module RBZK
683
691
  puts "Configuration updated: #{key} = #{typed_value}"
684
692
  end
685
693
 
686
- desc "config-reset", "Reset configuration to defaults"
694
+ desc 'config-reset', 'Reset configuration to defaults'
687
695
 
688
696
  def config_reset
689
- if yes?("Are you sure you want to reset all configuration to defaults? (y/N)")
697
+ if yes?('Are you sure you want to reset all configuration to defaults? (y/N)')
690
698
  FileUtils.rm_f(@config.config_file)
691
699
  @config = RBZK::CLI::Config.new
692
- puts "Configuration reset to defaults."
700
+ puts 'Configuration reset to defaults.'
693
701
  invoke :config
694
702
  else
695
- puts "Operation cancelled."
703
+ puts 'Operation cancelled.'
696
704
  end
697
705
  end
698
706
 
@@ -708,7 +716,7 @@ module RBZK
708
716
  skip_disconnect = local_opts.delete(:skip_disconnect_after_yield) || false
709
717
 
710
718
  puts "Connecting to ZKTeco device at #{ip}:#{local_opts[:port] || @config['port'] || 4370}..." # Use local_opts
711
- puts "Please ensure the device is powered on and connected to the network."
719
+ puts 'Please ensure the device is powered on and connected to the network.'
712
720
 
713
721
  conn = nil # Initialize conn for safety in ensure block
714
722
  begin
@@ -727,29 +735,30 @@ module RBZK
727
735
  conn = zk.connect
728
736
 
729
737
  if conn.connected?
730
- puts "✓ Connected successfully!" unless local_opts[:quiet] # Use local_opts
738
+ puts '✓ Connected successfully!' unless local_opts[:quiet] # Use local_opts
731
739
  yield conn if block_given?
732
740
  else
733
- puts "✗ Failed to connect to device."
741
+ puts '✗ Failed to connect to device.'
734
742
  end
735
743
  rescue RBZK::ZKNetworkError => e
736
744
  puts "✗ Network Error: #{e.message}"
737
- puts "Please check the IP address and ensure the device is reachable."
745
+ puts 'Please check the IP address and ensure the device is reachable.'
738
746
  rescue RBZK::ZKErrorResponse => e
739
747
  puts "✗ Device Error: #{e.message}"
740
- puts "The device returned an error response."
741
- rescue => e
748
+ puts 'The device returned an error response.'
749
+ rescue StandardError => e
742
750
  puts "✗ Unexpected Error: #{e.message}"
743
- puts "An unexpected error occurred while communicating with the device."
751
+ puts 'An unexpected error occurred while communicating with the device.'
744
752
  puts e.backtrace.join("\n") if local_opts[:verbose] # Use local_opts
745
753
  ensure
746
754
  if conn && conn.connected?
747
755
  if skip_disconnect
748
- puts "Skipping disconnect as device is undergoing restart/poweroff." unless local_opts[:quiet] # Use local_opts
756
+ # Use local_opts
757
+ puts 'Skipping disconnect as device is undergoing restart/poweroff.' unless local_opts[:quiet]
749
758
  else
750
- puts "Disconnecting from device..." unless local_opts[:quiet] # Use local_opts
759
+ puts 'Disconnecting from device...' unless local_opts[:quiet] # Use local_opts
751
760
  conn.disconnect
752
- puts "✓ Disconnected" unless local_opts[:quiet] # Use local_opts
761
+ puts '✓ Disconnected' unless local_opts[:quiet] # Use local_opts
753
762
  end
754
763
  end
755
764
  end
@@ -761,8 +770,8 @@ module RBZK
761
770
 
762
771
  # Use Terminal::Table for pretty output
763
772
  table = ::Terminal::Table.new do |t|
764
- t.title = "Users"
765
- t.headings = [ 'UID', 'User ID', 'Name', 'Privilege', 'Password', 'Group ID', 'Card' ]
773
+ t.title = 'Users'
774
+ t.headings = ['UID', 'User ID', 'Name', 'Privilege', 'Password', 'Group ID', 'Card']
766
775
 
767
776
  users.each do |user|
768
777
  t << [
@@ -770,7 +779,7 @@ module RBZK
770
779
  user.user_id,
771
780
  user.name,
772
781
  format_privilege(user.privilege),
773
- (user.password.nil? || user.password.empty?) ? '(none)' : '(set)',
782
+ user.password.nil? || user.password.empty? ? '(none)' : '(set)',
774
783
  user.group_id,
775
784
  user.card
776
785
  ]
@@ -779,7 +788,7 @@ module RBZK
779
788
 
780
789
  puts table
781
790
  else
782
- puts "✓ No users found"
791
+ puts '✓ No users found'
783
792
  end
784
793
  end
785
794
 
@@ -799,32 +808,18 @@ module RBZK
799
808
  log.timestamp >= start_datetime && log.timestamp <= end_datetime
800
809
  end
801
810
 
802
- if options[:verbose]
803
- puts "Filtered logs: #{filtered_logs.size} of #{logs.size}"
804
- end
811
+ puts "Filtered logs: #{filtered_logs.size} of #{logs.size}" if options[:verbose]
805
812
 
806
813
  filtered_logs
807
814
  end
808
815
 
809
- def format_status(status)
810
- case status
811
- when 0 then "Check In"
812
- when 1 then "Check Out"
813
- when 2 then "Break Out"
814
- when 3 then "Break In"
815
- when 4 then "Overtime In"
816
- when 5 then "Overtime Out"
817
- else "Unknown (#{status})"
818
- end
819
- end
820
-
821
816
  def format_privilege(privilege)
822
817
  case privilege
823
- when 0 then "User"
824
- when 1 then "Enroller"
825
- when 2 then "Manager"
826
- when 3 then "Administrator"
827
- when 14 then "Super Admin"
818
+ when 0 then 'User'
819
+ when 1 then 'Enroller'
820
+ when 2 then 'Manager'
821
+ when 3 then 'Administrator'
822
+ when 14 then 'Super Admin'
828
823
  else "Unknown (#{privilege})"
829
824
  end
830
825
  end
@@ -42,7 +42,7 @@ module RBZK
42
42
  def save
43
43
  # Create the directory if it doesn't exist
44
44
  FileUtils.mkdir_p(File.dirname(@config_file))
45
-
45
+
46
46
  # Save the configuration
47
47
  File.open(@config_file, 'w') do |f|
48
48
  f.write(YAML.dump(@config))
@@ -68,7 +68,7 @@ module RBZK
68
68
  begin
69
69
  config = YAML.load_file(@config_file)
70
70
  return DEFAULT_CONFIG.merge(config) if config.is_a?(Hash)
71
- rescue => e
71
+ rescue StandardError => e
72
72
  warn "Error loading configuration file: #{e.message}"
73
73
  end
74
74
  end
@@ -2,7 +2,7 @@
2
2
 
3
3
  module RBZK
4
4
  module Constants
5
- USHRT_MAX = 65535
5
+ USHRT_MAX = 65_535
6
6
 
7
7
  # Command codes
8
8
  CMD_DB_RRQ = 7 # Read in some kind of data from the machine
@@ -121,8 +121,8 @@ module RBZK
121
121
  # Machine constants
122
122
  # These values are in little-endian format when packed
123
123
  # 0x5050 = 'PP' in ASCII when packed as '<H'
124
- MACHINE_PREPARE_DATA_1 = 20560 # 0x5050 = 'P' + 'P'*256 in little-endian
124
+ MACHINE_PREPARE_DATA_1 = 20_560 # 0x5050 = 'P' + 'P'*256 in little-endian
125
125
  # 0x7D82 = 0x827D in little-endian format
126
- MACHINE_PREPARE_DATA_2 = 32130 # 0x7D82
126
+ MACHINE_PREPARE_DATA_2 = 32_130 # 0x7D82
127
127
  end
128
128
  end
@@ -4,19 +4,19 @@ module RBZK
4
4
  class ZKError < StandardError; end
5
5
 
6
6
  class ZKNetworkError < ZKError
7
- def initialize(msg = "Network error")
7
+ def initialize(msg = 'Network error')
8
8
  super
9
9
  end
10
10
  end
11
11
 
12
12
  class ZKErrorConnection < ZKError
13
- def initialize(msg = "Connection error")
13
+ def initialize(msg = 'Connection error')
14
14
  super
15
15
  end
16
16
  end
17
17
 
18
18
  class ZKErrorResponse < ZKError
19
- def initialize(msg = "Invalid response")
19
+ def initialize(msg = 'Invalid response')
20
20
  super
21
21
  end
22
22
  end
data/lib/rbzk/finger.rb CHANGED
@@ -4,7 +4,7 @@ module RBZK
4
4
  class Finger
5
5
  attr_accessor :uid, :fid, :valid, :template, :size
6
6
 
7
- def initialize(uid, fid, valid, template = "")
7
+ def initialize(uid, fid, valid, template = '')
8
8
  @uid = uid
9
9
  @fid = fid
10
10
  @valid = valid
data/lib/rbzk/user.rb CHANGED
@@ -4,7 +4,7 @@ module RBZK
4
4
  class User
5
5
  attr_accessor :uid, :user_id, :name, :privilege, :password, :group_id, :card
6
6
 
7
- @@encoding = "UTF-8"
7
+ @@encoding = 'UTF-8'
8
8
 
9
9
  def self.encoding=(encoding)
10
10
  @@encoding = encoding
@@ -17,7 +17,7 @@ module RBZK
17
17
  # Match Python's User constructor exactly
18
18
  # In Python:
19
19
  # def __init__(self, uid, name, privilege, password='', group_id='', user_id='', card=0):
20
- def initialize(uid = 0, name = "", privilege = 0, password = "", group_id = "", user_id = "", card = 0)
20
+ def initialize(uid = 0, name = '', privilege = 0, password = '', group_id = '', user_id = '', card = 0)
21
21
  @uid = uid
22
22
  @name = name
23
23
  @privilege = privilege
@@ -30,20 +30,20 @@ module RBZK
30
30
  # Pack the user data into a binary string for ZK6 devices (size 29)
31
31
  def repack29
32
32
  [2, @uid, @privilege].pack('CS<C') +
33
- @password.encode(@@encoding, invalid: :replace, undef: :replace).ljust(5, "\x00")[0...5] +
34
- @name.encode(@@encoding, invalid: :replace, undef: :replace).ljust(8, "\x00")[0...8] +
35
- [@card, 0, @group_id.to_i, 0, @user_id.to_i].pack('L<CS<S<L<')
33
+ @password.encode(@@encoding, invalid: :replace, undef: :replace).ljust(5, "\x00")[0...5] +
34
+ @name.encode(@@encoding, invalid: :replace, undef: :replace).ljust(8, "\x00")[0...8] +
35
+ [@card, 0, @group_id.to_i, 0, @user_id.to_i].pack('L<CS<S<L<')
36
36
  end
37
37
 
38
38
  # Pack the user data into a binary string for ZK8 devices (size 73)
39
39
  def repack73
40
40
  [2, @uid, @privilege].pack('CS<C') +
41
- @password.encode(@@encoding, invalid: :replace, undef: :replace).ljust(8, "\x00")[0...8] +
42
- @name.encode(@@encoding, invalid: :replace, undef: :replace).ljust(24, "\x00")[0...24] +
43
- [@card, 1].pack('L<C') +
44
- @group_id.to_s.encode(@@encoding, invalid: :replace, undef: :replace).ljust(7, "\x00")[0...7] +
45
- "\x00" +
46
- @user_id.to_s.encode(@@encoding, invalid: :replace, undef: :replace).ljust(24, "\x00")[0...24]
41
+ @password.encode(@@encoding, invalid: :replace, undef: :replace).ljust(8, "\x00")[0...8] +
42
+ @name.encode(@@encoding, invalid: :replace, undef: :replace).ljust(24, "\x00")[0...24] +
43
+ [@card, 1].pack('L<C') +
44
+ @group_id.to_s.encode(@@encoding, invalid: :replace, undef: :replace).ljust(7, "\x00")[0...7] +
45
+ "\x00" +
46
+ @user_id.to_s.encode(@@encoding, invalid: :replace, undef: :replace).ljust(24, "\x00")[0...24]
47
47
  end
48
48
 
49
49
  # Check if the user is disabled
data/lib/rbzk/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module RBZK
4
- VERSION = '0.1.6'
4
+ VERSION = '0.1.7'
5
5
  end
data/lib/rbzk/zk.rb CHANGED
@@ -39,13 +39,15 @@ module RBZK
39
39
  rescue Errno::EISCONN
40
40
  result = 0 # Already connected
41
41
  rescue => e
42
- result = e.errno || 1 # Connection failed
42
+ # Some exceptions (e.g., Socket::ResolutionError) don't provide errno
43
+ result = e.respond_to?(:errno) ? e.errno : 1 # Connection failed
43
44
  end
44
45
 
45
46
  client.close
46
47
  return result
47
48
  rescue => e
48
- return e.errno || 1
49
+ # Some exceptions (e.g., Socket::ResolutionError) don't provide errno
50
+ return e.respond_to?(:errno) ? e.errno : 1
49
51
  end
50
52
  end
51
53
  end
data/lib/rbzk.rb CHANGED
@@ -4,13 +4,13 @@
4
4
  require 'bytes'
5
5
 
6
6
  # Internal dependencies
7
- require_relative "rbzk/version"
8
- require_relative "rbzk/constants"
9
- require_relative "rbzk/exceptions"
10
- require_relative "rbzk/user"
11
- require_relative "rbzk/attendance"
12
- require_relative "rbzk/finger"
13
- require_relative "rbzk/zk"
7
+ require_relative 'rbzk/version'
8
+ require_relative 'rbzk/constants'
9
+ require_relative 'rbzk/exceptions'
10
+ require_relative 'rbzk/user'
11
+ require_relative 'rbzk/attendance'
12
+ require_relative 'rbzk/finger'
13
+ require_relative 'rbzk/zk'
14
14
 
15
15
  module RBZK
16
16
  class Error < StandardError; end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rbzk
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.6
4
+ version: 0.1.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - Khaled AbuShqear
8
8
  bindir: bin
9
9
  cert_chain: []
10
- date: 2025-09-26 00:00:00.000000000 Z
10
+ date: 2025-10-20 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: bytes
@@ -24,33 +24,33 @@ dependencies:
24
24
  - !ruby/object:Gem::Version
25
25
  version: '0.1'
26
26
  - !ruby/object:Gem::Dependency
27
- name: thor
27
+ name: terminal-table
28
28
  requirement: !ruby/object:Gem::Requirement
29
29
  requirements:
30
30
  - - "~>"
31
31
  - !ruby/object:Gem::Version
32
- version: '1.2'
32
+ version: '3.0'
33
33
  type: :runtime
34
34
  prerelease: false
35
35
  version_requirements: !ruby/object:Gem::Requirement
36
36
  requirements:
37
37
  - - "~>"
38
38
  - !ruby/object:Gem::Version
39
- version: '1.2'
39
+ version: '3.0'
40
40
  - !ruby/object:Gem::Dependency
41
- name: terminal-table
41
+ name: thor
42
42
  requirement: !ruby/object:Gem::Requirement
43
43
  requirements:
44
44
  - - "~>"
45
45
  - !ruby/object:Gem::Version
46
- version: '3.0'
46
+ version: '1.2'
47
47
  type: :runtime
48
48
  prerelease: false
49
49
  version_requirements: !ruby/object:Gem::Requirement
50
50
  requirements:
51
51
  - - "~>"
52
52
  - !ruby/object:Gem::Version
53
- version: '3.0'
53
+ version: '1.2'
54
54
  - !ruby/object:Gem::Dependency
55
55
  name: bundler
56
56
  requirement: !ruby/object:Gem::Requirement