rbzk 0.1.3 → 0.1.6
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/README.md +304 -254
- data/lib/rbzk/cli/commands.rb +337 -55
- data/lib/rbzk/finger.rb +12 -1
- data/lib/rbzk/user.rb +34 -0
- data/lib/rbzk/version.rb +1 -1
- data/lib/rbzk/zk.rb +204 -0
- metadata +2 -2
data/lib/rbzk/cli/commands.rb
CHANGED
@@ -5,6 +5,7 @@ require 'thor'
|
|
5
5
|
require 'yaml'
|
6
6
|
require 'fileutils'
|
7
7
|
require 'date'
|
8
|
+
require 'time'
|
8
9
|
require 'rbzk'
|
9
10
|
require 'rbzk/cli/config'
|
10
11
|
require 'terminal-table'
|
@@ -75,6 +76,19 @@ module RBZK
|
|
75
76
|
end
|
76
77
|
end
|
77
78
|
|
79
|
+
desc "refresh [IP]", "Refresh device data"
|
80
|
+
|
81
|
+
def refresh(ip = nil)
|
82
|
+
# Use IP from options if not provided as argument
|
83
|
+
ip ||= options[:ip] || @config['ip']
|
84
|
+
|
85
|
+
with_connection(ip, options) do |conn|
|
86
|
+
puts "Refreshing device data..."
|
87
|
+
result = conn.refresh_data
|
88
|
+
puts "✓ Device data refreshed successfully!" if result
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
78
92
|
desc "users [IP]", "Get users from the device"
|
79
93
|
|
80
94
|
def users(ip = nil)
|
@@ -87,43 +101,33 @@ module RBZK
|
|
87
101
|
end
|
88
102
|
end
|
89
103
|
|
90
|
-
desc "logs [IP]", "Get attendance logs"
|
91
|
-
method_option :today, type: :boolean, desc: "Get only today's logs"
|
92
|
-
method_option :yesterday, type: :boolean, desc: "Get only yesterday's logs"
|
93
|
-
method_option :week, type: :boolean, desc: "Get this week's logs"
|
94
|
-
method_option :month, type: :boolean, desc: "Get this month's logs"
|
95
|
-
method_option :start_date, type: :string, desc: "Start date for custom range (YYYY-MM-DD)"
|
96
|
-
method_option :end_date, type: :string, desc: "End date for custom range (YYYY-MM-DD)"
|
97
|
-
method_option :limit, type: :numeric, default: 25, desc: "Limit the number of logs displayed (default: 25, use 0 for all)"
|
98
|
-
|
99
104
|
# Add aliases for common log commands
|
100
105
|
desc "logs-today [IP]", "Get today's attendance logs"
|
101
106
|
map "logs-today" => "logs"
|
102
107
|
|
103
108
|
def logs_today(ip = nil)
|
104
|
-
|
105
|
-
invoke :logs, [ ip ], today: true
|
109
|
+
invoke :logs, [ ip ], { today: true }.merge(options)
|
106
110
|
end
|
107
111
|
|
108
112
|
desc "logs-yesterday [IP]", "Get yesterday's attendance logs"
|
109
113
|
map "logs-yesterday" => "logs"
|
110
114
|
|
111
115
|
def logs_yesterday(ip = nil)
|
112
|
-
invoke :logs, [ ip ], yesterday: true
|
116
|
+
invoke :logs, [ ip ], { yesterday: true }.merge(options)
|
113
117
|
end
|
114
118
|
|
115
119
|
desc "logs-week [IP]", "Get this week's attendance logs"
|
116
120
|
map "logs-week" => "logs"
|
117
121
|
|
118
122
|
def logs_week(ip = nil)
|
119
|
-
invoke :logs, [ ip ], week: true
|
123
|
+
invoke :logs, [ ip ], { week: true }.merge(options)
|
120
124
|
end
|
121
125
|
|
122
126
|
desc "logs-month [IP]", "Get this month's attendance logs"
|
123
127
|
map "logs-month" => "logs"
|
124
128
|
|
125
129
|
def logs_month(ip = nil)
|
126
|
-
invoke :logs, [ ip ], month: true
|
130
|
+
invoke :logs, [ ip ], { month: true }.merge(options)
|
127
131
|
end
|
128
132
|
|
129
133
|
desc "logs-all [IP]", "Get all attendance logs without limit"
|
@@ -177,10 +181,19 @@ module RBZK
|
|
177
181
|
def logs_custom(start_date, end_date, ip = nil)
|
178
182
|
# Use IP from options if not provided as argument
|
179
183
|
ip ||= options[:ip] || @config['ip']
|
180
|
-
invoke :logs, [ ip ], start_date: start_date, end_date: end_date
|
184
|
+
invoke :logs, [ ip ], { start_date: start_date, end_date: end_date }.merge(options)
|
181
185
|
end
|
182
186
|
|
183
|
-
desc "logs [IP]", "Get
|
187
|
+
desc "logs [IP]", "Get attendance logs"
|
188
|
+
method_option :today, type: :boolean, desc: "Get only today's logs"
|
189
|
+
method_option :yesterday, type: :boolean, desc: "Get only yesterday's logs"
|
190
|
+
method_option :week, type: :boolean, desc: "Get this week's logs"
|
191
|
+
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)"
|
184
197
|
|
185
198
|
def logs(ip = nil)
|
186
199
|
# Use IP from options if not provided as argument
|
@@ -195,21 +208,21 @@ module RBZK
|
|
195
208
|
# Filter logs based on options
|
196
209
|
title = if options[:today]
|
197
210
|
today = Date.today
|
198
|
-
logs =
|
211
|
+
logs = filter_logs_by_datetime(logs, today, today, options[:start_time], options[:end_time])
|
199
212
|
"Today's Attendance Logs (#{today})"
|
200
213
|
elsif options[:yesterday]
|
201
214
|
yesterday = Date.today - 1
|
202
|
-
logs =
|
215
|
+
logs = filter_logs_by_datetime(logs, yesterday, yesterday, options[:start_time], options[:end_time])
|
203
216
|
"Yesterday's Attendance Logs (#{yesterday})"
|
204
217
|
elsif options[:week]
|
205
218
|
today = Date.today
|
206
219
|
start_of_week = today - today.wday
|
207
|
-
logs =
|
220
|
+
logs = filter_logs_by_datetime(logs, start_of_week, today, options[:start_time], options[:end_time])
|
208
221
|
"This Week's Attendance Logs (#{start_of_week} to #{today})"
|
209
222
|
elsif options[:month]
|
210
223
|
today = Date.today
|
211
224
|
start_of_month = Date.new(today.year, today.month, 1)
|
212
|
-
logs =
|
225
|
+
logs = filter_logs_by_datetime(logs, start_of_month, today, options[:start_time], options[:end_time])
|
213
226
|
"This Month's Attendance Logs (#{start_of_month} to #{today})"
|
214
227
|
elsif options[:start_date] && options[:end_date]
|
215
228
|
begin
|
@@ -219,8 +232,8 @@ module RBZK
|
|
219
232
|
# Print debug info
|
220
233
|
puts "Filtering logs from #{start_date} to #{end_date}..." if options[:verbose]
|
221
234
|
|
222
|
-
# Use the
|
223
|
-
logs =
|
235
|
+
# Use the filter_logs_by_datetime method
|
236
|
+
logs = filter_logs_by_datetime(logs, start_date, end_date, options[:start_time], options[:end_time])
|
224
237
|
|
225
238
|
"Attendance Logs (#{start_date} to #{end_date})"
|
226
239
|
rescue ArgumentError
|
@@ -235,8 +248,8 @@ module RBZK
|
|
235
248
|
# Print debug info
|
236
249
|
puts "Filtering logs from #{start_date} onwards..." if options[:verbose]
|
237
250
|
|
238
|
-
# Use the
|
239
|
-
logs =
|
251
|
+
# Use the filter_logs_by_datetime method
|
252
|
+
logs = filter_logs_by_datetime(logs, start_date, end_date, options[:start_time], options[:end_time])
|
240
253
|
|
241
254
|
"Attendance Logs (#{start_date} to #{end_date})"
|
242
255
|
rescue ArgumentError
|
@@ -252,8 +265,8 @@ module RBZK
|
|
252
265
|
# Print debug info
|
253
266
|
puts "Filtering logs from #{start_date} to #{end_date}..." if options[:verbose]
|
254
267
|
|
255
|
-
# Use the
|
256
|
-
logs =
|
268
|
+
# Use the filter_logs_by_datetime method
|
269
|
+
logs = filter_logs_by_datetime(logs, start_date, end_date, options[:start_time], options[:end_time])
|
257
270
|
|
258
271
|
"Attendance Logs (#{start_date} to #{end_date})"
|
259
272
|
rescue ArgumentError
|
@@ -327,6 +340,236 @@ module RBZK
|
|
327
340
|
end
|
328
341
|
end
|
329
342
|
|
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
|
346
|
+
|
347
|
+
def unlock_door(ip = nil)
|
348
|
+
# Use IP from options if not provided as argument
|
349
|
+
ip ||= options[:ip] || @config['ip']
|
350
|
+
|
351
|
+
# Get the unlock time
|
352
|
+
time = options[:time] || 3
|
353
|
+
|
354
|
+
with_connection(ip, options) do |conn|
|
355
|
+
puts "Unlocking door for #{time} seconds..."
|
356
|
+
result = conn.unlock(time)
|
357
|
+
puts "✓ Door unlocked successfully!" if result
|
358
|
+
end
|
359
|
+
end
|
360
|
+
|
361
|
+
desc "door-state [IP]", "Get the door lock state"
|
362
|
+
map "door-state" => :door_state
|
363
|
+
|
364
|
+
def door_state(ip = nil)
|
365
|
+
# Use IP from options if not provided as argument
|
366
|
+
ip ||= options[:ip] || @config['ip']
|
367
|
+
|
368
|
+
with_connection(ip, options) do |conn|
|
369
|
+
state = conn.get_lock_state
|
370
|
+
puts "Door state: #{state ? 'Open' : 'Closed'}"
|
371
|
+
end
|
372
|
+
end
|
373
|
+
|
374
|
+
desc "write-lcd [IP] LINE_NUMBER TEXT", "Write text to LCD display"
|
375
|
+
map "write-lcd" => :write_lcd
|
376
|
+
|
377
|
+
def write_lcd(line_number, text, ip = nil)
|
378
|
+
# Use IP from options if not provided as argument
|
379
|
+
ip ||= options[:ip] || @config['ip']
|
380
|
+
|
381
|
+
# Convert line_number to integer
|
382
|
+
line_number = line_number.to_i
|
383
|
+
|
384
|
+
with_connection(ip, options) do |conn|
|
385
|
+
puts "Writing text to LCD line #{line_number}..."
|
386
|
+
result = conn.write_lcd(line_number, text)
|
387
|
+
puts "✓ Text written to LCD successfully!" if result
|
388
|
+
end
|
389
|
+
end
|
390
|
+
|
391
|
+
desc "clear-lcd [IP]", "Clear the LCD display"
|
392
|
+
map "clear-lcd" => :clear_lcd
|
393
|
+
|
394
|
+
def clear_lcd(ip = nil)
|
395
|
+
# Use IP from options if not provided as argument
|
396
|
+
ip ||= options[:ip] || @config['ip']
|
397
|
+
|
398
|
+
with_connection(ip, options) do |conn|
|
399
|
+
puts "Clearing LCD display..."
|
400
|
+
result = conn.clear_lcd
|
401
|
+
puts "✓ LCD cleared successfully!" if result
|
402
|
+
end
|
403
|
+
end
|
404
|
+
|
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
|
414
|
+
|
415
|
+
def add_user(ip = nil)
|
416
|
+
# Use IP from options if not provided as argument
|
417
|
+
ip ||= options[:ip] || @config['ip']
|
418
|
+
|
419
|
+
with_connection(ip, options) do |conn|
|
420
|
+
puts "Adding/updating user..."
|
421
|
+
|
422
|
+
result = conn.set_user(
|
423
|
+
uid: options[:uid],
|
424
|
+
name: options[:name] || "",
|
425
|
+
privilege: options[:privilege] || 0,
|
426
|
+
password: options[:password] || "",
|
427
|
+
group_id: options[:group_id] || "",
|
428
|
+
user_id: options[:user_id] || "",
|
429
|
+
card: options[:card] || 0
|
430
|
+
)
|
431
|
+
|
432
|
+
puts "✓ User added/updated successfully!" if result
|
433
|
+
end
|
434
|
+
end
|
435
|
+
|
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
|
440
|
+
|
441
|
+
def delete_user(ip = nil)
|
442
|
+
# Use IP from options if not provided as argument
|
443
|
+
ip ||= options[:ip] || @config['ip']
|
444
|
+
|
445
|
+
# Ensure at least one of uid or user_id is provided
|
446
|
+
if options[:uid].nil? && (options[:user_id].nil? || options[:user_id].empty?)
|
447
|
+
puts "Error: You must provide either --uid"
|
448
|
+
return
|
449
|
+
end
|
450
|
+
|
451
|
+
with_connection(ip, options) do |conn|
|
452
|
+
puts "Deleting user..."
|
453
|
+
|
454
|
+
# Use the User object with delete_user
|
455
|
+
result = conn.delete_user(uid: options[:uid])
|
456
|
+
|
457
|
+
if result
|
458
|
+
puts "✓ User deleted successfully!"
|
459
|
+
else
|
460
|
+
puts "✗ User not found or could not be deleted."
|
461
|
+
end
|
462
|
+
end
|
463
|
+
end
|
464
|
+
|
465
|
+
desc "get-templates [IP]", "Get all fingerprint templates"
|
466
|
+
map "get-templates" => :get_templates
|
467
|
+
|
468
|
+
def get_templates(ip = nil)
|
469
|
+
# Use IP from options if not provided as argument
|
470
|
+
ip ||= options[:ip] || @config['ip']
|
471
|
+
|
472
|
+
with_connection(ip, options) do |conn|
|
473
|
+
puts "Getting fingerprint templates..."
|
474
|
+
templates = conn.get_templates
|
475
|
+
|
476
|
+
if templates && !templates.empty?
|
477
|
+
puts "✓ Found #{templates.size} fingerprint templates:"
|
478
|
+
|
479
|
+
# Use Terminal::Table for pretty output
|
480
|
+
table = ::Terminal::Table.new do |t|
|
481
|
+
t.title = "Fingerprint Templates"
|
482
|
+
t.headings = [ 'UID', 'Finger ID', 'Valid', 'Size' ]
|
483
|
+
|
484
|
+
templates.each do |template|
|
485
|
+
t << [
|
486
|
+
template.uid,
|
487
|
+
template.fid,
|
488
|
+
template.valid == 1 ? 'Yes' : 'No',
|
489
|
+
template.size
|
490
|
+
]
|
491
|
+
end
|
492
|
+
end
|
493
|
+
|
494
|
+
puts table
|
495
|
+
else
|
496
|
+
puts "✓ No fingerprint templates found"
|
497
|
+
end
|
498
|
+
end
|
499
|
+
end
|
500
|
+
|
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
|
506
|
+
|
507
|
+
def get_user_template(ip = nil)
|
508
|
+
# Use IP from options if not provided as argument
|
509
|
+
ip ||= options[:ip] || @config['ip']
|
510
|
+
|
511
|
+
# Ensure at least one of uid or user_id is provided
|
512
|
+
if options[:uid].nil? && (options[:user_id].nil? || options[:user_id].empty?)
|
513
|
+
puts "Error: You must provide either --uid or --user-id"
|
514
|
+
return
|
515
|
+
end
|
516
|
+
|
517
|
+
with_connection(ip, options) do |conn|
|
518
|
+
puts "Getting user fingerprint template..."
|
519
|
+
|
520
|
+
# Extract parameters from options
|
521
|
+
uid = options[:uid] || 0
|
522
|
+
user_id = options[:user_id] || ""
|
523
|
+
finger_id = options[:finger_id] || 0
|
524
|
+
|
525
|
+
template = conn.get_user_template(uid: uid, temp_id: finger_id, user_id: user_id)
|
526
|
+
|
527
|
+
if template
|
528
|
+
puts "✓ Found fingerprint template:"
|
529
|
+
puts " User ID: #{template.uid}"
|
530
|
+
puts " Finger ID: #{template.fid}"
|
531
|
+
puts " Valid: #{template.valid == 1 ? 'Yes' : 'No'}"
|
532
|
+
puts " Size: #{template.size} bytes"
|
533
|
+
else
|
534
|
+
puts "✗ Fingerprint template not found"
|
535
|
+
end
|
536
|
+
end
|
537
|
+
end
|
538
|
+
|
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
|
544
|
+
|
545
|
+
def delete_template(ip = nil)
|
546
|
+
# Use IP from options if not provided as argument
|
547
|
+
ip ||= options[:ip] || @config['ip']
|
548
|
+
|
549
|
+
# Ensure at least one of uid or user_id is provided
|
550
|
+
if options[:uid].nil? && (options[:user_id].nil? || options[:user_id].empty?)
|
551
|
+
puts "Error: You must provide either --uid or --user-id"
|
552
|
+
return
|
553
|
+
end
|
554
|
+
|
555
|
+
with_connection(ip, options) do |conn|
|
556
|
+
puts "Deleting fingerprint template..."
|
557
|
+
|
558
|
+
# Extract parameters from options
|
559
|
+
uid = options[:uid] || 0
|
560
|
+
user_id = options[:user_id] || ""
|
561
|
+
finger_id = options[:finger_id] || 0
|
562
|
+
|
563
|
+
result = conn.delete_user_template(uid: uid, temp_id: finger_id, user_id: user_id)
|
564
|
+
|
565
|
+
if result
|
566
|
+
puts "✓ Fingerprint template deleted successfully!"
|
567
|
+
else
|
568
|
+
puts "✗ Fingerprint template not found or could not be deleted"
|
569
|
+
end
|
570
|
+
end
|
571
|
+
end
|
572
|
+
|
330
573
|
desc "test-voice [IP]", "Test the device voice"
|
331
574
|
method_option :index, type: :numeric, desc: "Sound index to play (0-35, default: 0)"
|
332
575
|
map "test-voice" => :test_voice
|
@@ -376,6 +619,42 @@ module RBZK
|
|
376
619
|
end
|
377
620
|
end
|
378
621
|
|
622
|
+
desc "restart [IP]", "Restart the device"
|
623
|
+
|
624
|
+
def restart(ip = nil)
|
625
|
+
# Use IP from options if not provided as argument
|
626
|
+
ip ||= options[:ip] || @config['ip']
|
627
|
+
|
628
|
+
if yes?("Are you sure you want to restart the device? (y/N)")
|
629
|
+
with_connection(ip, options.merge(skip_disconnect_after_yield: true)) do |conn|
|
630
|
+
puts "Restarting device..."
|
631
|
+
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."
|
634
|
+
end
|
635
|
+
else
|
636
|
+
puts "Operation cancelled."
|
637
|
+
end
|
638
|
+
end
|
639
|
+
|
640
|
+
desc "poweroff [IP]", "Power off the device"
|
641
|
+
|
642
|
+
def poweroff(ip = nil)
|
643
|
+
# Use IP from options if not provided as argument
|
644
|
+
ip ||= options[:ip] || @config['ip']
|
645
|
+
|
646
|
+
if yes?("Are you sure you want to power off the device? (y/N)")
|
647
|
+
with_connection(ip, options.merge(skip_disconnect_after_yield: true)) do |conn|
|
648
|
+
puts "Powering off device..."
|
649
|
+
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."
|
652
|
+
end
|
653
|
+
else
|
654
|
+
puts "Operation cancelled."
|
655
|
+
end
|
656
|
+
end
|
657
|
+
|
379
658
|
desc "config", "Show current configuration"
|
380
659
|
|
381
660
|
def config
|
@@ -425,26 +704,30 @@ module RBZK
|
|
425
704
|
end
|
426
705
|
|
427
706
|
def with_connection(ip, options = {})
|
428
|
-
|
707
|
+
local_opts = options.dup # Use a copy for local modifications and access
|
708
|
+
skip_disconnect = local_opts.delete(:skip_disconnect_after_yield) || false
|
709
|
+
|
710
|
+
puts "Connecting to ZKTeco device at #{ip}:#{local_opts[:port] || @config['port'] || 4370}..." # Use local_opts
|
429
711
|
puts "Please ensure the device is powered on and connected to the network."
|
430
712
|
|
713
|
+
conn = nil # Initialize conn for safety in ensure block
|
431
714
|
begin
|
432
715
|
# Create ZK instance with options from config and command line
|
433
716
|
zk_options = {
|
434
|
-
port:
|
435
|
-
timeout:
|
436
|
-
password:
|
437
|
-
verbose:
|
438
|
-
force_udp:
|
439
|
-
omit_ping:
|
440
|
-
encoding:
|
717
|
+
port: local_opts[:port] || @config['port'] || 4370, # Use local_opts
|
718
|
+
timeout: local_opts[:timeout] || @config['timeout'] || 30, # Use local_opts
|
719
|
+
password: local_opts[:password] || @config['password'] || 0, # Use local_opts
|
720
|
+
verbose: local_opts[:verbose] || @config['verbose'] || false, # Use local_opts
|
721
|
+
force_udp: local_opts[:force_udp] || @config['force_udp'] || false, # Use local_opts
|
722
|
+
omit_ping: local_opts[:no_ping] || @config['no_ping'] || false, # Use local_opts
|
723
|
+
encoding: local_opts[:encoding] || @config['encoding'] || 'UTF-8' # Use local_opts
|
441
724
|
}
|
442
725
|
|
443
726
|
zk = RBZK::ZK.new(ip, **zk_options)
|
444
727
|
conn = zk.connect
|
445
728
|
|
446
729
|
if conn.connected?
|
447
|
-
puts "✓ Connected successfully!" unless
|
730
|
+
puts "✓ Connected successfully!" unless local_opts[:quiet] # Use local_opts
|
448
731
|
yield conn if block_given?
|
449
732
|
else
|
450
733
|
puts "✗ Failed to connect to device."
|
@@ -458,12 +741,16 @@ module RBZK
|
|
458
741
|
rescue => e
|
459
742
|
puts "✗ Unexpected Error: #{e.message}"
|
460
743
|
puts "An unexpected error occurred while communicating with the device."
|
461
|
-
puts e.backtrace.join("\n") if
|
744
|
+
puts e.backtrace.join("\n") if local_opts[:verbose] # Use local_opts
|
462
745
|
ensure
|
463
746
|
if conn && conn.connected?
|
464
|
-
|
465
|
-
|
466
|
-
|
747
|
+
if skip_disconnect
|
748
|
+
puts "Skipping disconnect as device is undergoing restart/poweroff." unless local_opts[:quiet] # Use local_opts
|
749
|
+
else
|
750
|
+
puts "Disconnecting from device..." unless local_opts[:quiet] # Use local_opts
|
751
|
+
conn.disconnect
|
752
|
+
puts "✓ Disconnected" unless local_opts[:quiet] # Use local_opts
|
753
|
+
end
|
467
754
|
end
|
468
755
|
end
|
469
756
|
end
|
@@ -496,31 +783,26 @@ module RBZK
|
|
496
783
|
end
|
497
784
|
end
|
498
785
|
|
499
|
-
def
|
500
|
-
|
501
|
-
|
502
|
-
|
503
|
-
|
786
|
+
def filter_logs_by_datetime(logs, start_date, end_date, start_time = nil, end_time = nil)
|
787
|
+
start_datetime_str = "#{start_date.strftime('%Y-%m-%d')} #{start_time || '00:00:00'}"
|
788
|
+
end_datetime_str = "#{end_date.strftime('%Y-%m-%d')} #{end_time || '23:59:59'}"
|
789
|
+
|
790
|
+
start_datetime = Time.parse(start_datetime_str)
|
791
|
+
end_datetime = Time.parse(end_datetime_str)
|
504
792
|
|
505
793
|
if options[:verbose]
|
506
|
-
puts "Filtering logs from #{
|
507
|
-
puts "Total logs before filtering: #{
|
794
|
+
puts "Filtering logs from #{start_datetime} to #{end_datetime}..."
|
795
|
+
puts "Total logs before filtering: #{logs.size}"
|
508
796
|
end
|
509
797
|
|
510
|
-
|
511
|
-
|
512
|
-
logs.each do |log|
|
513
|
-
log_date_str = log.timestamp.strftime('%Y-%m-%d')
|
514
|
-
if log_date_str >= start_date_str && log_date_str <= end_date_str
|
515
|
-
filtered_logs << log
|
516
|
-
end
|
798
|
+
filtered_logs = logs.select do |log|
|
799
|
+
log.timestamp >= start_datetime && log.timestamp <= end_datetime
|
517
800
|
end
|
518
801
|
|
519
802
|
if options[:verbose]
|
520
|
-
puts "Filtered logs: #{filtered_logs.size} of #{
|
803
|
+
puts "Filtered logs: #{filtered_logs.size} of #{logs.size}"
|
521
804
|
end
|
522
805
|
|
523
|
-
# Return the filtered logs
|
524
806
|
filtered_logs
|
525
807
|
end
|
526
808
|
|
data/lib/rbzk/finger.rb
CHANGED
@@ -2,13 +2,24 @@
|
|
2
2
|
|
3
3
|
module RBZK
|
4
4
|
class Finger
|
5
|
-
attr_accessor :uid, :fid, :valid, :template
|
5
|
+
attr_accessor :uid, :fid, :valid, :template, :size
|
6
6
|
|
7
7
|
def initialize(uid, fid, valid, template = "")
|
8
8
|
@uid = uid
|
9
9
|
@fid = fid
|
10
10
|
@valid = valid
|
11
11
|
@template = template
|
12
|
+
@size = template.length
|
13
|
+
end
|
14
|
+
|
15
|
+
# Pack the finger data into a binary string (full data)
|
16
|
+
def repack
|
17
|
+
[@size + 6, @uid, @fid, @valid].pack('S<S<CC') + @template
|
18
|
+
end
|
19
|
+
|
20
|
+
# Pack only the template data into a binary string
|
21
|
+
def repack_only
|
22
|
+
[@size].pack('S<') + @template
|
12
23
|
end
|
13
24
|
|
14
25
|
def to_s
|
data/lib/rbzk/user.rb
CHANGED
@@ -27,6 +27,40 @@ module RBZK
|
|
27
27
|
@card = card
|
28
28
|
end
|
29
29
|
|
30
|
+
# Pack the user data into a binary string for ZK6 devices (size 29)
|
31
|
+
def repack29
|
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<')
|
36
|
+
end
|
37
|
+
|
38
|
+
# Pack the user data into a binary string for ZK8 devices (size 73)
|
39
|
+
def repack73
|
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]
|
47
|
+
end
|
48
|
+
|
49
|
+
# Check if the user is disabled
|
50
|
+
def is_disabled?
|
51
|
+
(@privilege & 1) != 0
|
52
|
+
end
|
53
|
+
|
54
|
+
# Check if the user is enabled
|
55
|
+
def is_enabled?
|
56
|
+
!is_disabled?
|
57
|
+
end
|
58
|
+
|
59
|
+
# Get the user type
|
60
|
+
def usertype
|
61
|
+
@privilege & 0xE
|
62
|
+
end
|
63
|
+
|
30
64
|
def to_s
|
31
65
|
"#{@uid} #{@user_id} #{@name} #{@privilege} #{@password} #{@group_id} #{@card}"
|
32
66
|
end
|
data/lib/rbzk/version.rb
CHANGED