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.
@@ -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 all attendance logs"
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 = filter_logs_by_date(logs, today, today)
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 = filter_logs_by_date(logs, yesterday, yesterday)
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 = filter_logs_by_date(logs, start_of_week, today)
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 = filter_logs_by_date(logs, start_of_month, today)
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 filter_logs_by_date method
223
- logs = filter_logs_by_date(logs, start_date, end_date)
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 filter_logs_by_date method
239
- logs = filter_logs_by_date(logs, start_date, end_date)
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 filter_logs_by_date method
256
- logs = filter_logs_by_date(logs, start_date, end_date)
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
- puts "Connecting to ZKTeco device at #{ip}:#{options[:port] || @config['port'] || 4370}..."
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: options[:port] || @config['port'] || 4370,
435
- timeout: options[:timeout] || @config['timeout'] || 30,
436
- password: options[:password] || @config['password'] || 0,
437
- verbose: options[:verbose] || @config['verbose'] || false,
438
- force_udp: options[:force_udp] || @config['force_udp'] || false,
439
- omit_ping: options[:no_ping] || @config['no_ping'] || false,
440
- encoding: options[:encoding] || @config['encoding'] || 'UTF-8'
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 options[:quiet]
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 options[:verbose]
744
+ puts e.backtrace.join("\n") if local_opts[:verbose] # Use local_opts
462
745
  ensure
463
746
  if conn && conn.connected?
464
- puts "Disconnecting from device..." unless options[:quiet]
465
- conn.disconnect
466
- puts "✓ Disconnected" unless options[:quiet]
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 filter_logs_by_date(logs, start_date, end_date)
500
- # Convert Date objects to strings for comparison
501
- total_logs = logs.size
502
- start_date_str = start_date.strftime('%Y-%m-%d')
503
- end_date_str = end_date.strftime('%Y-%m-%d')
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 #{start_date_str} to #{end_date_str}..."
507
- puts "Total logs before filtering: #{total_logs}"
794
+ puts "Filtering logs from #{start_datetime} to #{end_datetime}..."
795
+ puts "Total logs before filtering: #{logs.size}"
508
796
  end
509
797
 
510
- # Filter logs by date range using string comparison
511
- filtered_logs = []
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 #{total_logs}"
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
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module RBZK
4
- VERSION = "0.1.3"
4
+ VERSION = '0.1.6'
5
5
  end