rbzk 0.1.7 → 0.1.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/lib/rbzk/zk.rb CHANGED
@@ -14,48 +14,45 @@ module RBZK
14
14
  end
15
15
 
16
16
  def test_ping
17
- begin
18
- Timeout.timeout(5) do
19
- s = TCPSocket.new(@ip, @port)
20
- s.close
21
- return true
22
- end
23
- rescue Timeout::Error, Errno::ECONNREFUSED, Errno::EHOSTUNREACH, SocketError => e
24
- return false
25
- rescue => e
26
- return false
17
+ Timeout.timeout(5) do
18
+ s = TCPSocket.new(@ip, @port)
19
+ s.close
20
+ return true
27
21
  end
22
+ rescue Timeout::Error, Errno::ECONNREFUSED, Errno::EHOSTUNREACH, SocketError
23
+ false
24
+ rescue StandardError
25
+ false
28
26
  end
29
27
 
30
28
  def test_tcp
31
- begin
32
- client = Socket.new(Socket::AF_INET, Socket::SOCK_STREAM)
33
- client.setsockopt(Socket::SOL_SOCKET, Socket::SO_RCVTIMEO, [ 10, 0 ].pack('l_*'))
29
+ client = Socket.new(Socket::AF_INET, Socket::SOCK_STREAM)
30
+ client.setsockopt(Socket::SOL_SOCKET, Socket::SO_RCVTIMEO, [ 10, 0 ].pack('l_*'))
34
31
 
35
- sockaddr = Socket.pack_sockaddr_in(@port, @ip)
36
- begin
37
- client.connect(sockaddr)
38
- result = 0 # Success code
39
- rescue Errno::EISCONN
40
- result = 0 # Already connected
41
- rescue => e
42
- # Some exceptions (e.g., Socket::ResolutionError) don't provide errno
43
- result = e.respond_to?(:errno) ? e.errno : 1 # Connection failed
44
- end
45
-
46
- client.close
47
- return result
48
- rescue => e
32
+ sockaddr = Socket.pack_sockaddr_in(@port, @ip)
33
+ begin
34
+ client.connect(sockaddr)
35
+ result = 0 # Success code
36
+ rescue Errno::EISCONN
37
+ result = 0 # Already connected
38
+ rescue StandardError => e
49
39
  # Some exceptions (e.g., Socket::ResolutionError) don't provide errno
50
- return e.respond_to?(:errno) ? e.errno : 1
40
+ result = e.respond_to?(:errno) ? e.errno : 1 # Connection failed
51
41
  end
42
+
43
+ client.close
44
+ result
45
+ rescue StandardError => e
46
+ # Some exceptions (e.g., Socket::ResolutionError) don't provide errno
47
+ e.respond_to?(:errno) ? e.errno : 1
52
48
  end
53
49
  end
54
50
 
55
51
  class ZK
56
52
  include RBZK::Constants
57
53
 
58
- def initialize(ip, port: 4370, timeout: 60, password: 0, force_udp: false, omit_ping: false, verbose: false, encoding: 'UTF-8')
54
+ def initialize(ip, port: 4370, timeout: 60, password: 0, force_udp: false, omit_ping: false, verbose: false,
55
+ encoding: 'UTF-8')
59
56
  # Initialize the ZK device connection
60
57
  RBZK::User.encoding = encoding
61
58
  @address = [ ip, port ]
@@ -79,6 +76,8 @@ module RBZK
79
76
  @data = nil
80
77
  @connected = false
81
78
  @next_uid = 1
79
+ @next_user_id = '1'
80
+ @user_packet_size = 28
82
81
 
83
82
  # Storage for user and attendance data
84
83
  @users = {}
@@ -104,22 +103,20 @@ module RBZK
104
103
  # Create helper for ping and TCP tests
105
104
  @helper = ZKHelper.new(ip, port)
106
105
 
107
- if @verbose
108
- puts "ZK instance created for device at #{@ip}:#{@port}"
109
- puts "Using #{@force_udp ? 'UDP' : 'TCP'} mode"
110
- end
106
+ return unless @verbose
107
+
108
+ puts "ZK instance created for device at #{@ip}:#{@port}"
109
+ puts "Using #{@force_udp ? 'UDP' : 'TCP'} mode"
111
110
  end
112
111
 
113
112
  def connect
114
113
  return self if @connected
115
114
 
116
115
  # Skip ping check if requested
117
- if !@omit_ping && !@helper.test_ping
118
- raise RBZK::ZKNetworkError, "Can't reach device (ping #{@ip})"
119
- end
116
+ raise RBZK::ZKNetworkError, "Can't reach device (ping #{@ip})" if !@omit_ping && !@helper.test_ping
120
117
 
121
118
  # Set user packet size if TCP connection is available
122
- if !@force_udp && @helper.test_tcp == 0
119
+ if !@force_udp && @helper.test_tcp.zero?
123
120
  @user_packet_size = 72 # Default for ZK8
124
121
  end
125
122
 
@@ -129,9 +126,7 @@ module RBZK
129
126
  @session_id = 0
130
127
  @reply_id = USHRT_MAX - 1
131
128
 
132
- if @verbose
133
- puts "Sending connect command to device"
134
- end
129
+ puts 'Sending connect command to device' if @verbose
135
130
 
136
131
  begin
137
132
  cmd_response = send_command(CMD_CONNECT)
@@ -139,9 +134,7 @@ module RBZK
139
134
 
140
135
  # Authenticate if needed
141
136
  if cmd_response[:code] == CMD_ACK_UNAUTH
142
- if @verbose
143
- puts "try auth"
144
- end
137
+ puts 'try auth' if @verbose
145
138
 
146
139
  command_string = make_commkey(@password, @session_id)
147
140
  cmd_response = send_command(CMD_AUTH, command_string)
@@ -150,23 +143,17 @@ module RBZK
150
143
  # Check response status
151
144
  if cmd_response[:status]
152
145
  @connected = true
153
- return self
146
+ self
154
147
  else
155
- if cmd_response[:code] == CMD_ACK_UNAUTH
156
- raise RBZK::ZKErrorResponse, "Unauthenticated"
157
- end
148
+ raise RBZK::ZKErrorResponse, 'Unauthenticated' if cmd_response[:code] == CMD_ACK_UNAUTH
158
149
 
159
- if @verbose
160
- puts "Connect error response: #{cmd_response[:code]}"
161
- end
150
+ puts "Connect error response: #{cmd_response[:code]}" if @verbose
162
151
 
163
152
  raise RBZK::ZKErrorResponse, "Invalid response: Can't connect"
164
153
  end
165
- rescue => e
154
+ rescue StandardError => e
166
155
  @connected = false
167
- if @verbose
168
- puts "Connection error: #{e.message}"
169
- end
156
+ puts "Connection error: #{e.message}" if @verbose
170
157
  raise e
171
158
  end
172
159
  end
@@ -178,11 +165,11 @@ module RBZK
178
165
  def disconnect
179
166
  return unless @connected
180
167
 
181
- self.send_command(CMD_EXIT)
182
- self.recv_reply
168
+ send_command(CMD_EXIT)
169
+ recv_reply
183
170
 
184
171
  @connected = false
185
- @socket.close if @socket
172
+ @socket&.close
186
173
 
187
174
  @socket = nil
188
175
  @tcp = nil
@@ -191,32 +178,30 @@ module RBZK
191
178
  end
192
179
 
193
180
  def enable_device
194
- self.send_command(CMD_ENABLEDEVICE)
195
- self.recv_reply
181
+ cmd_response = send_command(CMD_ENABLEDEVICE)
182
+ raise RBZK::ZKErrorResponse, "Can't enable device" unless cmd_response && cmd_response[:status]
183
+
184
+ @is_enabled = true
196
185
  true
197
186
  end
198
187
 
199
188
  def disable_device
200
- cmd_response = self.send_command(CMD_DISABLEDEVICE)
201
- if cmd_response[:status]
202
- @is_enabled = false
203
- true
204
- else
205
- raise RBZK::ZKErrorResponse, "Can't disable device"
206
- end
189
+ cmd_response = send_command(CMD_DISABLEDEVICE)
190
+ raise RBZK::ZKErrorResponse, "Can't disable device" unless cmd_response[:status]
191
+
192
+ @is_enabled = false
193
+ true
207
194
  end
208
195
 
209
196
  def get_firmware_version
210
197
  command = CMD_GET_VERSION
211
198
  response_size = 1024
212
- response = self.send_command(command, "", response_size)
199
+ response = send_command(command, '', response_size)
213
200
 
214
- if response && response[:status]
215
- firmware_version = @data.split("\x00")[0]
216
- firmware_version.to_s
217
- else
218
- raise RBZK::ZKErrorResponse, "Can't read firmware version"
219
- end
201
+ raise RBZK::ZKErrorResponse, "Can't read firmware version" unless response && response[:status]
202
+
203
+ firmware_version = @data.split("\x00")[0]
204
+ firmware_version.to_s
220
205
  end
221
206
 
222
207
  def get_serialnumber
@@ -224,15 +209,14 @@ module RBZK
224
209
  command_string = "~SerialNumber\x00".b
225
210
  response_size = 1024
226
211
 
227
- response = self.send_command(command, command_string, response_size)
212
+ response = send_command(command, command_string, response_size)
228
213
 
229
- if response && response[:status]
230
- serialnumber = @data.split("=", 2)[1]&.split("\x00")[0] || ""
231
- serialnumber = serialnumber.gsub("=", "")
232
- serialnumber.to_s
233
- else
234
- raise RBZK::ZKErrorResponse, "Can't read serial number"
235
- end
214
+ raise RBZK::ZKErrorResponse, "Can't read serial number" unless response && response[:status]
215
+
216
+ serialnumber_field = @data.split('=', 2)[1]
217
+ serialnumber = serialnumber_field ? serialnumber_field.split("\x00")[0] : ''
218
+ serialnumber = serialnumber.gsub('=', '')
219
+ serialnumber.to_s
236
220
  end
237
221
 
238
222
  def get_mac
@@ -240,14 +224,12 @@ module RBZK
240
224
  command_string = "MAC\x00".b
241
225
  response_size = 1024
242
226
 
243
- response = self.send_command(command, command_string, response_size)
227
+ response = send_command(command, command_string, response_size)
244
228
 
245
- if response && response[:status]
246
- mac = @data.split("=", 2)[1]&.split("\x00")[0] || ""
247
- mac.to_s
248
- else
249
- raise RBZK::ZKErrorResponse, "Can't read MAC address"
250
- end
229
+ raise RBZK::ZKErrorResponse, "Can't read MAC address" unless response && response[:status]
230
+
231
+ mac = @data.split('=', 2)[1]&.split("\x00")&.[](0) || ''
232
+ mac.to_s
251
233
  end
252
234
 
253
235
  def get_device_name
@@ -255,13 +237,14 @@ module RBZK
255
237
  command_string = "~DeviceName\x00".b
256
238
  response_size = 1024
257
239
 
258
- response = self.send_command(command, command_string, response_size)
240
+ response = send_command(command, command_string, response_size)
259
241
 
260
242
  if response && response[:status]
261
- device = @data.split("=", 2)[1]&.split("\x00")[0] || ""
243
+ device_field = @data.split('=', 2)[1]
244
+ device = device_field ? device_field.split("\x00")[0] : ''
262
245
  device.to_s
263
246
  else
264
- ""
247
+ ''
265
248
  end
266
249
  end
267
250
 
@@ -270,13 +253,16 @@ module RBZK
270
253
  command_string = "ZKFaceVersion\x00".b
271
254
  response_size = 1024
272
255
 
273
- response = self.send_command(command, command_string, response_size)
256
+ response = send_command(command, command_string, response_size)
274
257
 
275
- if response && response[:status]
276
- version = @data.split("=", 2)[1]&.split("\x00")[0] || ""
277
- version.to_i rescue 0
278
- else
279
- nil
258
+ return unless response && response[:status]
259
+
260
+ version_field = @data.split('=', 2)[1]
261
+ version = version_field ? version_field.split("\x00")[0] : ''
262
+ begin
263
+ version.to_i
264
+ rescue StandardError
265
+ 0
280
266
  end
281
267
  end
282
268
 
@@ -285,13 +271,16 @@ module RBZK
285
271
  command_string = "~ExtendFmt\x00".b
286
272
  response_size = 1024
287
273
 
288
- response = self.send_command(command, command_string, response_size)
274
+ response = send_command(command, command_string, response_size)
289
275
 
290
- if response && response[:status]
291
- fmt = @data.split("=", 2)[1]&.split("\x00")[0] || ""
292
- fmt.to_i rescue 0
293
- else
294
- nil
276
+ return unless response && response[:status]
277
+
278
+ fmt_field = @data.split('=', 2)[1]
279
+ fmt = fmt_field ? fmt_field.split("\x00")[0] : ''
280
+ begin
281
+ fmt.to_i
282
+ rescue StandardError
283
+ 0
295
284
  end
296
285
  end
297
286
 
@@ -300,15 +289,14 @@ module RBZK
300
289
  command_string = "~Platform\x00".b
301
290
  response_size = 1024
302
291
 
303
- response = self.send_command(command, command_string, response_size)
292
+ response = send_command(command, command_string, response_size)
304
293
 
305
- if response && response[:status]
306
- platform = @data.split("=", 2)[1]&.split("\x00")[0] || ""
307
- platform = platform.gsub("=", "")
308
- platform.to_s
309
- else
310
- raise RBZK::ZKErrorResponse, "Can't read platform name"
311
- end
294
+ raise RBZK::ZKErrorResponse, "Can't read platform name" unless response && response[:status]
295
+
296
+ platform_field = @data.split('=', 2)[1]
297
+ platform = platform_field ? platform_field.split("\x00")[0] : ''
298
+ platform = platform.gsub('=', '')
299
+ platform.to_s
312
300
  end
313
301
 
314
302
  def get_fp_version
@@ -316,32 +304,35 @@ module RBZK
316
304
  command_string = "~ZKFPVersion\x00".b
317
305
  response_size = 1024
318
306
 
319
- response = self.send_command(command, command_string, response_size)
307
+ response = send_command(command, command_string, response_size)
320
308
 
321
- if response && response[:status]
322
- version = @data.split("=", 2)[1]&.split("\x00")[0] || ""
323
- version = version.gsub("=", "")
324
- version.to_i rescue 0
325
- else
326
- raise RBZK::ZKErrorResponse, "Can't read fingerprint version"
309
+ raise RBZK::ZKErrorResponse, "Can't read fingerprint version" unless response && response[:status]
310
+
311
+ version_field = @data.split('=', 2)[1]
312
+ version = version_field ? version_field.split("\x00")[0] : ''
313
+ version = version.gsub('=', '')
314
+ begin
315
+ version.to_i
316
+ rescue StandardError
317
+ 0
327
318
  end
328
319
  end
329
320
 
330
321
  def restart
331
- self.send_command(CMD_RESTART)
332
- self.recv_reply
322
+ send_command(CMD_RESTART)
323
+ recv_reply
333
324
  true
334
325
  end
335
326
 
336
327
  def poweroff
337
- self.send_command(CMD_POWEROFF)
338
- self.recv_reply
328
+ send_command(CMD_POWEROFF)
329
+ recv_reply
339
330
  true
340
331
  end
341
332
 
342
333
  def test_voice(index = 0)
343
334
  command_string = [ index ].pack('L<')
344
- response = self.send_command(CMD_TESTVOICE, command_string)
335
+ response = send_command(CMD_TESTVOICE, command_string)
345
336
 
346
337
  if response && response[:status]
347
338
  true
@@ -354,20 +345,18 @@ module RBZK
354
345
  # @param time [Integer] define delay in seconds
355
346
  # @return [Boolean] true if successful, raises exception otherwise
356
347
  def unlock(time = 3)
357
- command_string = [time * 10].pack('L<')
358
- response = self.send_command(CMD_UNLOCK, command_string)
348
+ command_string = [ time * 10 ].pack('L<')
349
+ response = send_command(CMD_UNLOCK, command_string)
359
350
 
360
- if response && response[:status]
361
- true
362
- else
363
- raise RBZK::ZKErrorResponse, "Can't open door"
364
- end
351
+ raise RBZK::ZKErrorResponse, "Can't open door" unless response && response[:status]
352
+
353
+ true
365
354
  end
366
355
 
367
356
  # Get the lock state
368
357
  # @return [Boolean] true if door is open, false otherwise
369
358
  def get_lock_state
370
- response = self.send_command(CMD_DOORSTATE_RRQ)
359
+ response = send_command(CMD_DOORSTATE_RRQ)
371
360
 
372
361
  if response && response[:status]
373
362
  true
@@ -381,38 +370,32 @@ module RBZK
381
370
  # @param text [String] text to write
382
371
  # @return [Boolean] true if successful, raises exception otherwise
383
372
  def write_lcd(line_number, text)
384
- command_string = [line_number, 0].pack('s<c') + ' ' + text.encode(@encoding, invalid: :replace, undef: :replace)
385
- response = self.send_command(CMD_WRITE_LCD, command_string)
373
+ command_string = "#{[ line_number, 0 ].pack('s<c')} #{text.encode(@encoding, invalid: :replace, undef: :replace)}"
374
+ response = send_command(CMD_WRITE_LCD, command_string)
386
375
 
387
- if response && response[:status]
388
- true
389
- else
390
- raise RBZK::ZKErrorResponse, "Can't write lcd"
391
- end
376
+ raise RBZK::ZKErrorResponse, "Can't write lcd" unless response && response[:status]
377
+
378
+ true
392
379
  end
393
380
 
394
381
  # Clear LCD
395
382
  # @return [Boolean] true if successful, raises exception otherwise
396
383
  def clear_lcd
397
- response = self.send_command(CMD_CLEAR_LCD)
384
+ response = send_command(CMD_CLEAR_LCD)
398
385
 
399
- if response && response[:status]
400
- true
401
- else
402
- raise RBZK::ZKErrorResponse, "Can't clear lcd"
403
- end
386
+ raise RBZK::ZKErrorResponse, "Can't clear lcd" unless response && response[:status]
387
+
388
+ true
404
389
  end
405
390
 
406
391
  # Refresh the device data
407
392
  # @return [Boolean] true if successful, raises exception otherwise
408
393
  def refresh_data
409
- response = self.send_command(CMD_REFRESHDATA)
394
+ response = send_command(CMD_REFRESHDATA)
410
395
 
411
- if response && response[:status]
412
- true
413
- else
414
- raise RBZK::ZKErrorResponse, "Can't refresh data"
415
- end
396
+ raise RBZK::ZKErrorResponse, "Can't refresh data" unless response && response[:status]
397
+
398
+ true
416
399
  end
417
400
 
418
401
  # Create or update user by uid
@@ -425,23 +408,17 @@ module RBZK
425
408
  # @param card [Integer] card number
426
409
  # @return [Boolean] true if successful, raises exception otherwise
427
410
  def set_user(uid: nil, name: '', privilege: 0, password: '', group_id: '', user_id: '', card: 0)
428
- # If uid is not provided, use next_uid
429
411
  if uid.nil?
412
+ ensure_user_metadata!
430
413
  uid = @next_uid
431
- if user_id.empty?
432
- user_id = @next_user_id
433
- end
414
+ user_id = @next_user_id if user_id.empty? && @next_user_id
434
415
  end
435
416
 
436
- # If user_id is not provided, use uid as string
437
- if user_id.empty?
438
- user_id = uid.to_s # ZK6 needs uid2 == uid
439
- end
417
+ # If uid is not provided, use next_uid
418
+ user_id = uid.to_s if user_id.nil? || user_id.empty? # ZK6 needs uid2 == uid
440
419
 
441
420
  # Validate privilege
442
- if privilege != USER_DEFAULT && privilege != USER_ADMIN
443
- privilege = USER_DEFAULT
444
- end
421
+ privilege = USER_DEFAULT if privilege != USER_DEFAULT && privilege != USER_ADMIN
445
422
  privilege = privilege.to_i
446
423
 
447
424
  # Create command string based on user_packet_size
@@ -449,73 +426,79 @@ module RBZK
449
426
  group_id = 0 if group_id.empty?
450
427
 
451
428
  begin
452
- command_string = [uid, privilege].pack('S<C') +
453
- password.encode(@encoding, invalid: :replace, undef: :replace).ljust(5, "\x00")[0...5] +
454
- name.encode(@encoding, invalid: :replace, undef: :replace).ljust(8, "\x00")[0...8] +
455
- [card.to_i, 0, group_id.to_i, 0, user_id.to_i].pack('L<CS<S<L<')
456
- rescue => e
457
- if @verbose
458
- puts "Error packing user: #{e.message}"
459
- end
429
+ command_string = [ uid, privilege ].pack('S<C') +
430
+ password.encode(@encoding, invalid: :replace, undef: :replace).ljust(5, "\x00")[0...5] +
431
+ name.encode(@encoding, invalid: :replace, undef: :replace).ljust(8, "\x00")[0...8] +
432
+ [ card.to_i, 0, group_id.to_i, 0, user_id.to_i ].pack('L<CS<S<L<')
433
+ rescue StandardError => e
434
+ puts "Error packing user: #{e.message}" if @verbose
460
435
  raise RBZK::ZKErrorResponse, "Can't pack user"
461
436
  end
462
437
  else
463
438
  # For other firmware versions
464
439
  name_pad = name.encode(@encoding, invalid: :replace, undef: :replace).ljust(24, "\x00")[0...24]
465
- card_str = [card.to_i].pack('L<')[0...4]
466
- command_string = [uid, privilege].pack('S<C') +
467
- password.encode(@encoding, invalid: :replace, undef: :replace).ljust(8, "\x00")[0...8] +
468
- name_pad +
469
- card_str + "\x00" +
470
- group_id.encode(@encoding, invalid: :replace, undef: :replace).ljust(7, "\x00")[0...7] +
471
- "\x00" +
472
- user_id.encode(@encoding, invalid: :replace, undef: :replace).ljust(24, "\x00")[0...24]
440
+ card_str = [ card.to_i ].pack('L<')[0...4]
441
+ command_string = "#{[ uid,
442
+ privilege ].pack('S<C')}#{password.encode(@encoding, invalid: :replace, undef: :replace).ljust(8,
443
+ "\x00")[0...8]}#{name_pad}#{card_str}\u0000#{group_id.encode(@encoding, invalid: :replace, undef: :replace).ljust(7,
444
+ "\x00")[0...7]}\u0000#{user_id.encode(@encoding, invalid: :replace, undef: :replace).ljust(
445
+ 24, "\x00"
446
+ )[0...24]}"
473
447
  end
474
448
 
475
449
  # Send command
476
- response = self.send_command(CMD_USER_WRQ, command_string, 1024)
450
+ response = send_command(CMD_USER_WRQ, command_string, 1024)
477
451
 
478
452
  if response && response[:status]
479
453
  # Update next_uid and next_user_id if necessary
480
- self.refresh_data
481
- if @next_uid == uid
482
- @next_uid += 1
483
- end
484
- if @next_user_id == user_id
485
- @next_user_id = @next_uid.to_s
486
- end
454
+ refresh_data
455
+ @next_uid += 1 if @next_uid == uid
456
+ @next_user_id = @next_uid.to_s if @next_user_id == user_id
487
457
  true
488
458
  else
489
- raise RBZK::ZKErrorResponse, "Can't set user"
459
+ code = response[:code] if response
460
+ data_msg = @data && !@data.empty? ? " Data: #{format_as_python_bytes(@data)}" : ''
461
+ raise RBZK::ZKErrorResponse, "Can't set user (device response: #{code || 'NO_CODE'})#{data_msg}"
490
462
  end
491
463
  end
492
464
 
465
+ def ensure_user_metadata!
466
+ @next_uid ||= 1
467
+ @next_user_id ||= '1'
468
+ @user_packet_size ||= 28
469
+
470
+ return unless @next_uid <= 1 || @next_user_id.nil? || @user_packet_size.nil?
471
+
472
+ get_users
473
+ rescue StandardError => e
474
+ puts "Warning: unable to refresh user metadata before creating user: #{e.message}" if @verbose
475
+ @next_uid ||= 1
476
+ @next_user_id ||= '1'
477
+ @user_packet_size ||= 28
478
+ end
479
+ private :ensure_user_metadata!
480
+
493
481
  # Delete user by uid
494
482
  # @param uid [Integer] user ID that are generated from device
495
483
  # @return [Boolean] true if successful, raises exception otherwise
496
484
  def delete_user(uid: 0)
497
485
  # Send command
498
- command_string = [uid].pack('S<')
499
- response = self.send_command(CMD_DELETE_USER, command_string)
486
+ command_string = [ uid ].pack('S<')
487
+ response = send_command(CMD_DELETE_USER, command_string)
500
488
 
501
- if response && response[:status]
502
- self.refresh_data
503
- # Update next_uid if necessary
504
- if uid == (@next_uid - 1)
505
- @next_uid = uid
506
- end
507
- true
508
- else
509
- raise RBZK::ZKErrorResponse, "Can't delete user"
489
+ unless response && response[:status]
490
+ raise RBZK::ZKErrorResponse, "Can't delete user. User not found or other error."
510
491
  end
492
+
493
+ refresh_data
494
+ # Update next_uid if necessary
495
+ @next_uid = uid if uid == (@next_uid - 1)
496
+ true
511
497
  end
512
498
 
513
499
  # Helper method to read data with buffer (ZK6: 1503)
514
500
  def read_with_buffer(command, fct = 0, ext = 0)
515
-
516
- if @verbose
517
- puts "Reading data with buffer: command=#{command}, fct=#{fct}, ext=#{ext}"
518
- end
501
+ puts "Reading data with buffer: command=#{command}, fct=#{fct}, ext=#{ext}" if @verbose
519
502
 
520
503
  # Set max chunk size based on connection type
521
504
  max_chunk = @tcp ? 0xFFc0 : 16 * 1024
@@ -525,54 +508,39 @@ module RBZK
525
508
  # All in little-endian format
526
509
  command_string = [ 1, command, fct, ext ].pack('cs<l<l<')
527
510
 
528
- if @verbose
529
- puts "Command string: #{python_format(command_string)}"
530
- end
511
+ puts "Command string: #{python_format(command_string)}" if @verbose
531
512
 
532
513
  # Send the command to prepare the buffer
533
514
  response_size = 1024
534
- data = []
535
- start = 0
536
- response = self.send_command(CMD_PREPARE_BUFFER, command_string, response_size)
515
+ # local variables
516
+ response = send_command(CMD_PREPARE_BUFFER, command_string, response_size)
537
517
 
538
- if !response || !response[:status]
539
- raise RBZK::ZKErrorResponse, "Read with buffer not supported"
540
- end
518
+ raise RBZK::ZKErrorResponse, 'Read with buffer not supported' if !response || !response[:status]
541
519
 
542
520
  # Get data from the response
543
521
  data = @data
544
522
 
545
- if @verbose
546
- puts "Received #{data.size} bytes of data"
547
- end
523
+ puts "Received #{data.size} bytes of data" if @verbose
548
524
 
549
525
  # Check if we need more data
550
526
  if response[:code] == CMD_DATA
551
527
  if @tcp
552
- if @verbose
553
- puts "DATA! is #{data.size} bytes, tcp length is #{@tcp_length}"
554
- end
528
+ puts "DATA! is #{data.size} bytes, tcp length is #{@tcp_length}" if @verbose
555
529
 
556
530
  if data.size < (@tcp_length - 8)
557
531
  need = (@tcp_length - 8) - data.size
558
- if @verbose
559
- puts "need more data: #{need}"
560
- end
532
+ puts "need more data: #{need}" if @verbose
561
533
 
562
534
  # Receive more data to complete the buffer
563
535
  more_data = receive_raw_data(need)
564
536
 
565
- if @verbose
566
- puts "Read #{more_data.size} more bytes"
567
- end
537
+ puts "Read #{more_data.size} more bytes" if @verbose
568
538
 
569
539
  # Combine the data
570
540
  result = data + more_data
571
541
  return result, data.size + more_data.size
572
542
  else
573
- if @verbose
574
- puts "Enough data"
575
- end
543
+ puts 'Enough data' if @verbose
576
544
  size = data.size
577
545
  return data, size
578
546
  end
@@ -583,38 +551,30 @@ module RBZK
583
551
  end
584
552
 
585
553
  # Get the size from the first 4 bytes (unsigned long, little-endian)
586
- size = data[1..4].unpack('L<')[0]
554
+ size = data[1..4].unpack1('L<')
587
555
 
588
- if @verbose
589
- puts "size fill be #{size}"
590
- end
556
+ puts "size fill be #{size}" if @verbose
591
557
 
592
558
  # Calculate chunks
593
559
  remain = size % max_chunk
594
560
  # Calculate number of full-sized packets (integer division)
595
561
  packets = (size - remain).div(max_chunk)
596
562
 
597
- if @verbose
598
- puts "rwb: ##{packets} packets of max #{max_chunk} bytes, and extra #{remain} bytes remain"
599
- end
563
+ puts "rwb: ##{packets} packets of max #{max_chunk} bytes, and extra #{remain} bytes remain" if @verbose
600
564
 
601
565
  # Read chunks
602
566
  result_data = []
603
567
  start = 0
604
568
 
605
569
  packets.times do
606
- if @verbose
607
- puts "recieve chunk: prepare data size is #{max_chunk}"
608
- end
570
+ puts "recieve chunk: prepare data size is #{max_chunk}" if @verbose
609
571
  chunk = read_chunk(start, max_chunk)
610
572
  result_data << chunk
611
573
  start += max_chunk
612
574
  end
613
575
 
614
- if remain > 0
615
- if @verbose
616
- puts "recieve chunk: prepare data size is #{remain}"
617
- end
576
+ if remain.positive?
577
+ puts "recieve chunk: prepare data size is #{remain}" if @verbose
618
578
  chunk = read_chunk(start, remain)
619
579
  result_data << chunk
620
580
  start += remain
@@ -623,9 +583,7 @@ module RBZK
623
583
  # Free data (equivalent to Python's self.free_data())
624
584
  free_data
625
585
 
626
- if @verbose
627
- puts "_read w/chunk #{start} bytes"
628
- end
586
+ puts "_read w/chunk #{start} bytes" if @verbose
629
587
 
630
588
  # In Python: return b''.join(data), start
631
589
  result = result_data.join
@@ -635,8 +593,8 @@ module RBZK
635
593
  # Helper method to get data size from the current data
636
594
  def get_data_size
637
595
  if @data && @data.size >= 4
638
- size = @data[0...4].unpack('L<')[0]
639
- size
596
+ @data[0...4].unpack1('L<')
597
+
640
598
  else
641
599
  0
642
600
  end
@@ -650,12 +608,12 @@ module RBZK
650
608
  puts "tcp_length #{tcp_length}, size #{size}" if @verbose
651
609
 
652
610
  if tcp_length <= 0
653
- puts "Incorrect tcp packet" if @verbose
654
- return nil, "".b
611
+ puts 'Incorrect tcp packet' if @verbose
612
+ return nil, ''.b
655
613
  end
656
614
 
657
615
  if (tcp_length - 8) < size
658
- puts "tcp length too small... retrying" if @verbose
616
+ puts 'tcp length too small... retrying' if @verbose
659
617
 
660
618
  # Recursive call to handle smaller packet
661
619
  resp, bh = receive_tcp_data(data_recv, tcp_length - 8)
@@ -684,7 +642,7 @@ module RBZK
684
642
 
685
643
  # In Python: response = unpack('HHHH', data_recv[8:16])[0]
686
644
  # This unpacks 4 shorts (8 bytes) but only uses the first one
687
- response = data_recv[8...16].unpack('S<S<S<S<')[0]
645
+ response = data_recv[8...16].unpack1('S<S<S<S<')
688
646
 
689
647
  if received >= (size + 32)
690
648
  if response == CMD_DATA
@@ -692,28 +650,26 @@ module RBZK
692
650
 
693
651
  puts "resp complete len #{resp.size}" if @verbose
694
652
 
695
- return resp, data_recv[(size + 16)..]
653
+ [ resp, data_recv[(size + 16)..-1] ]
696
654
  else
697
655
  puts "incorrect response!!! #{response}" if @verbose
698
656
 
699
- return nil, "".b
657
+ [ nil, ''.b ]
700
658
  end
701
659
  else
702
660
  puts "try DATA incomplete (actual valid #{received - 16})" if @verbose
703
661
 
704
662
  data << data_recv[16...(size + 16)]
705
663
  size -= received - 16
706
- broken_header = "".b
664
+ broken_header = ''.b
707
665
 
708
- if size < 0
709
- broken_header = data_recv[size..]
666
+ if size.negative?
667
+ broken_header = data_recv[size..-1]
710
668
 
711
- if @verbose
712
- puts "broken: #{broken_header.bytes.map { |b| format('%02x', b) }.join}"
713
- end
669
+ puts "broken: #{broken_header.bytes.map { |b| format('%02x', b) }.join}" if @verbose
714
670
  end
715
671
 
716
- if size > 0
672
+ if size.positive?
717
673
  data_recv = receive_raw_data(size)
718
674
  data << data_recv
719
675
  end
@@ -732,14 +688,14 @@ module RBZK
732
688
  need = (@tcp_length - 8) - @data.size
733
689
  puts "need more data: #{need}" if @verbose
734
690
  more_data = receive_raw_data(need)
735
- return @data + more_data
691
+ @data + more_data
736
692
  else
737
- puts "Enough data" if @verbose
738
- return @data
693
+ puts 'Enough data' if @verbose
694
+ @data
739
695
  end
740
696
  else
741
697
  puts "_rc len is #{@data.size}" if @verbose
742
- return @data
698
+ @data
743
699
  end
744
700
  elsif @response == CMD_PREPARE_DATA
745
701
  data = []
@@ -749,10 +705,10 @@ module RBZK
749
705
 
750
706
  if @tcp
751
707
  if @data.size >= (8 + size)
752
- data_recv = @data[8..]
708
+ data_recv = @data[8..-1]
753
709
  else
754
710
  # [80, 80, 130, 125, 92, 7, 0, 0, 221, 5, 142, 172, 0, 0, 4, 0, 80, 7, 0, 0, 1, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 65, 98, 100, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 49, 0, 0, 0, 1, 0, 0, 0, 25, 0, 0, 0, 0, 254, 6, 119, 255, 255, 255, 255, 212, 10, 159, 127, 2, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 65, 110, 97, 115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 50, 0, 0, 0, 1, 0, 0, 0, 25, 0, 0, 0, 0, 254, 6, 119, 255, 255, 255, 255, 212, 10, 159, 127, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 83, 111, 110, 100, 111, 115, 44, 65, 98, 117, 107, 104, 100, 97, 105, 114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 51, 0, 0, 0, 1, 0, 0, 0, 25, 0, 0, 0, 0, 254, 6, 119, 255, 255, 255, 255, 212, 10, 159, 127, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 65, 116, 97, 0, 111, 115, 44, 65, 98, 117, 107, 104, 100, 97, 105, 114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 52, 0, 0, 0, 1, 0, 0, 0, 25, 0, 0, 0, 0, 254, 6, 119, 255, 255, 255, 255, 212, 10, 159, 127, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 77, 97, 121, 115, 0, 115, 44, 65, 98, 117, 107, 104, 100, 97, 105, 114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 53, 0, 0, 0, 1, 0, 0, 0, 25, 0, 0, 0, 0, 254, 6, 119, 255, 255, 255, 255, 212, 10, 159, 127, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 97, 119, 97, 110, 0, 44, 65, 98, 117, 107, 104, 100, 97, 105, 114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 54, 0, 0, 0, 1, 0, 0, 0, 25, 0, 0, 0, 0, 254, 6, 119, 255, 255, 255, 255, 212, 10, 159, 127, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 74, 101, 110, 97, 110, 0, 44, 65, 98, 117, 107, 104, 100, 97, 105, 114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 55, 0, 0, 0, 1, 0, 0, 0, 25, 0, 0, 0, 0, 254, 6, 119, 255, 255, 255, 255, 212, 10, 159, 127, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 70, 97, 114, 97, 104, 0, 44, 65, 98, 117, 107, 104, 100, 97, 105, 114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 56, 0, 0, 0, 1, 0, 0, 0, 25, 0, 0, 0, 0, 254, 6, 119, 255, 255, 255, 255, 212, 10, 159, 127, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 83, 97, 98, 114, 101, 101, 110, 0, 98, 117, 107, 104, 100, 97, 105, 114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 57, 0, 0, 0, 1, 0, 0, 0, 25, 0, 0, 0, 0, 254, 6, 119, 255, 255, 255, 255, 212, 10, 159, 127, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 83, 97, 101, 101, 100, 0, 110, 0, 98, 117, 107, 104, 100, 97, 105, 114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 49, 48, 0, 0, 1, 0, 0, 0, 25, 0, 0, 0, 0, 254, 6, 119, 255, 255, 255, 255, 212, 10, 159, 127, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 71, 111, 102, 114, 97, 110, 0, 0, 98, 117, 107, 104, 100, 97, 105, 114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 49, 49, 0, 0, 1, 0, 0, 0, 25, 0, 0, 0, 0, 254, 6, 119, 255, 255, 255, 255, 212, 10, 159, 127, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 97, 110, 105, 97, 0, 0, 0, 98, 117, 107, 104, 100, 97, 105, 114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 49, 50, 0, 0, 1, 0, 0, 0, 25, 0, 0, 0, 0, 254, 6, 119, 255, 255, 255, 255, 212, 10, 159, 127, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 83, 97, 109, 105, 97, 0, 0, 0, 98, 117, 107, 104, 100, 97, 105, 114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 49, 51, 0, 0, 1, 0, 0, 0, 25, 0, 0, 0, 0, 254, 6, 119, 255, 255, 255, 255, 212, 10, 159, 127, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 101, 101, 109, 0, 0, 0, 0, 98, 117, 107, 104, 100, 97, 105, 114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 49, 52, 0, 0, 1, 0, 0, 0, 25, 0, 0, 0, 0, 254, 6, 119, 255, 255, 255, 255, 212, 10, 159, 127, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 87, 97, 108, 97, 97, 0, 0, 0, 98, 117, 107, 104, 100, 97, 105, 114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 49, 53, 0, 0, 1, 0, 0, 0, 25, 0, 0, 0, 0, 254, 6, 119, 255, 255, 255, 255, 212, 10, 159, 127, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 97, 110, 101, 101, 109, 0, 0, 98, 117, 107, 104, 100, 97, 105, 114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 49, 54, 0, 0, 1, 0, 0, 0, 25, 0, 0, 0, 0, 254, 6, 119, 255, 255, 255, 255, 212, 10, 159, 127, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 79, 108, 97, 0, 101, 109, 0, 0, 98, 117, 107, 104, 100, 97, 105, 114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 49, 55, 0, 0, 1, 0, 0, 0, 25, 0, 0, 0, 0, 254, 6, 119, 255, 255, 255, 255, 212, 10, 159, 127, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 77, 97, 114, 97, 104, 0, 0, 0, 98, 117, 107, 104, 100, 97, 105, 114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 49, 56, 0, 0, 1, 0, 0, 0, 25, 0, 0, 0, 0, 254, 6, 119, 255, 255, 255, 255, 212, 10, 159, 127, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 83, 111, 110, 100, 111, 115, 72, 65, 0, 117, 107, 104, 100, 97, 105, 114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 49, 57, 0, 0, 1, 0, 0, 0, 25, 0, 0, 0, 0, 254, 6, 119, 255, 255, 255, 255, 212, 10, 159, 127, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 77, 111, 0, 100, 111, 115, 72, 65, 0, 117, 107, 104, 100, 97, 105, 114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 49, 52, 53, 0, 1, 0, 0, 0, 25, 0, 0, 0, 0, 254, 6, 119, 255, 255, 255, 255, 212, 10, 159, 127, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 65, 119, 115, 0, 111, 115, 72, 65, 0, 117, 107, 104, 100, 97, 105, 114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 49, 52, 54, 0, 1, 0, 0, 0, 25, 0, 0, 0, 0, 254, 6, 119, 255, 255, 255, 255, 212, 10, 159, 127, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 83, 97, 109, 97, 114, 97, 0, 65, 0, 117, 107, 104, 100, 97, 105, 114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 52, 53, 50, 0, 1, 0, 0, 0, 25, 0, 0, 0, 0, 254, 6, 119, 255, 255, 255, 255, 212, 10, 159, 127, 23, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 84, 97, 115, 110, 101, 101, 109, 0, 0, 117, 107, 104, 100, 97, 105, 114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 50, 48, 0, 0, 1, 0, 0, 0, 25, 0, 0, 0, 0, 254, 6, 119, 255, 255, 255, 255, 212, 10, 159, 127, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 69, 115, 114, 97, 97, 0, 109, 0, 0, 117, 107, 104, 100, 97, 105, 114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 50, 49, 0, 0, 1, 0, 0, 0, 25, 0, 0, 0, 0, 254, 6, 119, 255, 255, 255, 255, 212, 10, 159, 127, 25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 83, 97, 114, 97, 106, 0, 109, 0, 0, 117, 107, 104, 100, 97, 105, 114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 50, 49, 51, 53, 0, 0, 0, 0, 25, 0, 0, 0, 0, 254, 6, 119, 255, 255, 255, 255, 212, 10, 159, 127, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 65, 108, 97, 97, 110, 97, 115, 115, 101, 114, 0, 104, 100, 97, 105, 114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 50, 50, 0, 53, 0, 0, 0, 0, 25, 0, 0, 0, 0, 254, 6, 119, 255, 255, 255, 255, 212, 10, 159, 127, 80, 80, 130, 125, 8, 0, 0, 0, 208, 7, 73, 81, 226, 166, 4, 0]
755
- data_recv = @data[8..] + @socket.recv(size + 32)
711
+ data_recv = @data[8..-1] + @socket.recv(size + 32)
756
712
  end
757
713
 
758
714
  puts "data_recv: #{python_format(data_recv)}" if @verbose
@@ -762,36 +718,30 @@ module RBZK
762
718
  data << resp if resp
763
719
 
764
720
  # get CMD_ACK_OK
765
- if broken_header.size < 16
766
- data_recv = broken_header + @socket.recv(16)
767
- else
768
- data_recv = broken_header
769
- end
721
+ data_recv = if broken_header.size < 16
722
+ broken_header + @socket.recv(16)
723
+ else
724
+ broken_header
725
+ end
770
726
 
771
727
  if data_recv.size < 16
772
728
  puts "trying to complete broken ACK #{data_recv.size} /16"
773
- if @verbose
774
- puts "data_recv: #{data_recv.bytes.map { |b| "0x#{b.to_s(16).rjust(2, '0')}" }.join(' ')}"
775
- end
729
+ puts "data_recv: #{data_recv.bytes.map { |b| "0x#{b.to_s(16).rjust(2, '0')}" }.join(' ')}" if @verbose
776
730
  data_recv += @socket.recv(16 - data_recv.size) # TODO: CHECK HERE_!
777
731
  end
778
732
 
779
- if !test_tcp_top(data_recv)
780
- if @verbose
781
- puts "invalid chunk tcp ACK OK"
782
- end
733
+ unless test_tcp_top(data_recv)
734
+ puts 'invalid chunk tcp ACK OK' if @verbose
783
735
  return nil
784
736
  end
785
737
 
786
738
  # In Python: response = unpack('HHHH', data_recv[8:16])[0]
787
739
  # This unpacks 4 shorts (8 bytes) but only uses the first one
788
740
  # In Ruby, we need to use 'S<4' to unpack 4 shorts in little-endian format
789
- response = data_recv[8...16].unpack('S<4')[0]
741
+ response = data_recv[8...16].unpack1('S<4')
790
742
 
791
743
  if response == CMD_ACK_OK
792
- if @verbose
793
- puts "chunk tcp ACK OK!"
794
- end
744
+ puts 'chunk tcp ACK OK!' if @verbose
795
745
  return data.join
796
746
  end
797
747
 
@@ -800,40 +750,32 @@ module RBZK
800
750
  puts "data: #{data.map { |d| format_as_python_bytes(d) }.join(', ')}"
801
751
  end
802
752
 
803
- return nil
753
+ nil
804
754
  else
805
755
  # Non-TCP implementation
806
756
  loop do
807
757
  data_recv = @socket.recv(1024 + 8)
808
- response = data_recv[0...8].unpack('S<S<S<S<')[0]
758
+ response = data_recv[0...8].unpack1('S<S<S<S<')
809
759
 
810
- if @verbose
811
- puts "# packet response is: #{response}"
812
- end
760
+ puts "# packet response is: #{response}" if @verbose
813
761
 
814
762
  if response == CMD_DATA
815
- data << data_recv[8..]
763
+ data << data_recv[8..-1]
816
764
  size -= 1024
817
765
  elsif response == CMD_ACK_OK
818
766
  break
819
767
  else
820
- if @verbose
821
- puts "broken!"
822
- end
768
+ puts 'broken!' if @verbose
823
769
  break
824
770
  end
825
771
 
826
- if @verbose
827
- puts "still needs #{size}"
828
- end
772
+ puts "still needs #{size}" if @verbose
829
773
  end
830
774
 
831
- return data.join
775
+ data.join
832
776
  end
833
777
  else
834
- if @verbose
835
- puts "invalid response #{@response}"
836
- end
778
+ puts "invalid response #{@response}" if @verbose
837
779
  nil
838
780
  end
839
781
  end
@@ -841,27 +783,21 @@ module RBZK
841
783
  # Helper method to receive raw data (like Python's __recieve_raw_data)
842
784
  def receive_raw_data(size)
843
785
  data = []
844
- if @verbose
845
- puts "expecting #{size} bytes raw data"
846
- end
786
+ puts "expecting #{size} bytes raw data" if @verbose
847
787
 
848
- while size > 0
788
+ while size.positive?
849
789
  data_recv = @socket.recv(size)
850
790
  received = data_recv.size
851
791
 
852
792
  if @verbose
853
793
  puts "partial recv #{received}"
854
- if received < 100
855
- puts " recv #{data_recv.bytes.map { |b| "0x#{b.to_s(16).rjust(2, '0')}" }.join(' ')}"
856
- end
794
+ puts " recv #{data_recv.bytes.map { |b| "0x#{b.to_s(16).rjust(2, '0')}" }.join(' ')}" if received < 100
857
795
  end
858
796
 
859
797
  data << data_recv
860
798
  size -= received
861
799
 
862
- if @verbose
863
- puts "still need #{size}"
864
- end
800
+ puts "still need #{size}" if @verbose
865
801
  end
866
802
 
867
803
  data.join
@@ -870,13 +806,11 @@ module RBZK
870
806
  # Helper method to clear buffer (like Python's free_data)
871
807
  def free_data
872
808
  command = CMD_FREE_DATA
873
- response = self.send_command(command)
809
+ response = send_command(command)
874
810
 
875
- if response && response[:status]
876
- true
877
- else
878
- raise RBZK::ZKErrorResponse, "Can't free data"
879
- end
811
+ raise RBZK::ZKErrorResponse, "Can't free data" unless response && response[:status]
812
+
813
+ true
880
814
  end
881
815
 
882
816
  # Send data with buffer
@@ -885,15 +819,13 @@ module RBZK
885
819
  def send_with_buffer(buffer)
886
820
  max_chunk = 1024
887
821
  size = buffer.size
888
- self.free_data
822
+ free_data
889
823
 
890
824
  command = CMD_PREPARE_DATA
891
- command_string = [size].pack('L<')
892
- response = self.send_command(command, command_string)
825
+ command_string = [ size ].pack('L<')
826
+ response = send_command(command, command_string)
893
827
 
894
- if !response || !response[:status]
895
- raise RBZK::ZKErrorResponse, "Can't prepare data"
896
- end
828
+ raise RBZK::ZKErrorResponse, "Can't prepare data" if !response || !response[:status]
897
829
 
898
830
  remain = size % max_chunk
899
831
  packets = (size - remain) / max_chunk
@@ -904,7 +836,7 @@ module RBZK
904
836
  start += max_chunk
905
837
  end
906
838
 
907
- send_chunk(buffer[start, remain]) if remain > 0
839
+ send_chunk(buffer[start, remain]) if remain.positive?
908
840
 
909
841
  true
910
842
  end
@@ -914,22 +846,18 @@ module RBZK
914
846
  # @return [Boolean] true if successful, raises exception otherwise
915
847
  def send_chunk(command_string)
916
848
  command = CMD_DATA
917
- response = self.send_command(command, command_string)
849
+ response = send_command(command, command_string)
918
850
 
919
- if response && response[:status]
920
- true
921
- else
922
- raise RBZK::ZKErrorResponse, "Can't send chunk"
923
- end
851
+ raise RBZK::ZKErrorResponse, "Can't send chunk" unless response && response[:status]
852
+
853
+ true
924
854
  end
925
855
 
926
856
  # Helper method to read a chunk of data
927
857
  def read_chunk(start, size)
928
- if @verbose
929
- puts "Reading chunk: start=#{start}, size=#{size}"
930
- end
858
+ puts "Reading chunk: start=#{start}, size=#{size}" if @verbose
931
859
 
932
- 3.times do |_retries|
860
+ 3.times do |attempt|
933
861
  # In Python: command = const._CMD_READ_BUFFER (which is 1504)
934
862
  # In Ruby, we should use CMD_READ_BUFFER (1504) instead of CMD_READFILE_DATA (81)
935
863
  command = 1504 # CMD_READ_BUFFER
@@ -941,25 +869,21 @@ module RBZK
941
869
  response_size = @tcp ? size + 32 : 1024 + 8
942
870
 
943
871
  # In Python: cmd_response = self.__send_command(command, command_string, response_size)
944
- response = self.send_command(command, command_string, response_size)
872
+ response = send_command(command, command_string, response_size)
945
873
 
946
874
  if !response || !response[:status]
947
- if @verbose
948
- puts "Failed to read chunk on attempt #{_retries + 1}"
949
- end
875
+ puts "Failed to read chunk on attempt #{attempt + 1}" if @verbose
950
876
  next
951
877
  end
952
878
 
953
879
  # In Python: data = self.__recieve_chunk()
954
880
  data = receive_chunk
955
881
 
956
- if data
957
- if @verbose
958
- puts "Received chunk of #{data.size} bytes"
959
- end
882
+ next unless data
960
883
 
961
- return data
962
- end
884
+ puts "Received chunk of #{data.size} bytes" if @verbose
885
+
886
+ return data
963
887
  end
964
888
 
965
889
  # If we get here, all retries failed
@@ -968,12 +892,12 @@ module RBZK
968
892
 
969
893
  def get_users
970
894
  # Read sizes
971
- self.read_sizes
895
+ read_sizes
972
896
 
973
897
  puts "Device has #{@users} users" if @verbose
974
898
 
975
899
  # If no users, return empty array
976
- if @users == 0
900
+ if @users.zero?
977
901
  @next_uid = 1
978
902
  @next_user_id = '1'
979
903
  return []
@@ -981,46 +905,48 @@ module RBZK
981
905
 
982
906
  users = []
983
907
  max_uid = 0
984
- userdata, size = self.read_with_buffer(CMD_USERTEMP_RRQ, FCT_USER)
908
+ userdata, size = read_with_buffer(CMD_USERTEMP_RRQ, FCT_USER)
985
909
  puts "user size #{size} (= #{userdata.length})" if @verbose
986
910
 
987
911
  if size <= 4
988
- puts "WRN: missing user data"
912
+ puts 'WRN: missing user data'
989
913
  return []
990
914
  end
991
915
 
992
916
  total_size = userdata[0, 4].unpack1('L<')
993
917
  @user_packet_size = total_size / @users
994
918
 
995
- if ![ 28, 72 ].include?(@user_packet_size)
996
- puts "WRN packet size would be #{@user_packet_size}" if @verbose
997
- end
919
+ puts "WRN packet size would be #{@user_packet_size}" if ![ 28, 72 ].include?(@user_packet_size) && @verbose
998
920
 
999
921
  userdata = userdata[4..-1]
1000
922
 
1001
923
  if @user_packet_size == 28
1002
924
  while userdata.length >= 28
1003
- uid, privilege, password, name, card, group_id, timezone, user_id = userdata.ljust(28, "\x00")[0, 28].unpack('S<Ca5a8L<xCs<L<')
925
+ uid, privilege, password, name, card, group_id, timezone, user_id = userdata.ljust(28, "\x00")[0,
926
+ 28].unpack('S<Ca5a8L<xCs<L<')
1004
927
  max_uid = uid if uid > max_uid
1005
928
  password = password.split("\x00").first&.force_encoding(@encoding)&.encode('UTF-8', invalid: :replace)
1006
929
  name = name.split("\x00").first&.force_encoding(@encoding)&.encode('UTF-8', invalid: :replace)&.strip
1007
930
  group_id = group_id.to_s
1008
931
  user_id = user_id.to_s
1009
- name = "NN-#{user_id}" if !name
932
+ name ||= "NN-#{user_id}"
1010
933
  user = User.new(uid, name, privilege, password, group_id, user_id, card)
1011
934
  users << user
1012
- puts "[6]user: #{uid}, #{privilege}, #{password}, #{name}, #{card}, #{group_id}, #{timezone}, #{user_id}" if @verbose
935
+ if @verbose
936
+ puts "[6]user: #{uid}, #{privilege}, #{password}, #{name}, #{card}, #{group_id}, #{timezone}, #{user_id}"
937
+ end
1013
938
  userdata = userdata[28..-1]
1014
939
  end
1015
940
  else
1016
941
  while userdata.length >= 72
1017
- uid, privilege, password, name, card, group_id, user_id = userdata.ljust(72, "\x00")[0, 72].unpack('S<Ca8a24L<xa7xa24')
942
+ uid, privilege, password, name, card, group_id, user_id = userdata.ljust(72, "\x00")[0,
943
+ 72].unpack('S<Ca8a24L<xa7xa24')
1018
944
  max_uid = uid if uid > max_uid
1019
945
  password = password.split("\x00").first&.force_encoding(@encoding)&.encode('UTF-8', invalid: :replace)
1020
946
  name = name.split("\x00").first&.force_encoding(@encoding)&.encode('UTF-8', invalid: :replace)&.strip
1021
947
  group_id = group_id.split("\x00").first&.force_encoding(@encoding)&.encode('UTF-8', invalid: :replace)&.strip
1022
948
  user_id = user_id.split("\x00").first&.force_encoding(@encoding)&.encode('UTF-8', invalid: :replace)
1023
- name = "NN-#{user_id}" if !name
949
+ name ||= "NN-#{user_id}"
1024
950
  user = User.new(uid, name, privilege, password, group_id, user_id, card)
1025
951
  users << user
1026
952
  userdata = userdata[72..-1]
@@ -1032,12 +958,10 @@ module RBZK
1032
958
  @next_user_id = max_uid.to_s
1033
959
 
1034
960
  loop do
1035
- if users.any? { |u| u.user_id == @next_user_id }
1036
- max_uid += 1
1037
- @next_user_id = max_uid.to_s
1038
- else
1039
- break
1040
- end
961
+ break unless users.any? { |u| u.user_id == @next_user_id }
962
+
963
+ max_uid += 1
964
+ @next_user_id = max_uid.to_s
1041
965
  end
1042
966
 
1043
967
  users
@@ -1045,41 +969,33 @@ module RBZK
1045
969
 
1046
970
  def get_attendance_logs
1047
971
  # First, read device sizes to get record count
1048
- self.read_sizes
972
+ read_sizes
1049
973
 
1050
974
  # If no records, return empty array
1051
- if @records == 0
1052
- return []
1053
- end
975
+ return [] if @records.zero?
1054
976
 
1055
977
  # Get users for lookup
1056
- users = self.get_users
978
+ users = get_users
1057
979
 
1058
- if @verbose
1059
- puts "Found #{users.size} users"
1060
- end
980
+ puts "Found #{users.size} users" if @verbose
1061
981
 
1062
982
  logs = []
1063
983
 
1064
984
  # Read attendance data with buffer
1065
- attendance_data, size = self.read_with_buffer(CMD_ATTLOG_RRQ)
985
+ attendance_data, size = read_with_buffer(CMD_ATTLOG_RRQ)
1066
986
 
1067
987
  if size < 4
1068
- if @verbose
1069
- puts "WRN: no attendance data"
1070
- end
988
+ puts 'WRN: no attendance data' if @verbose
1071
989
  return []
1072
990
  end
1073
991
 
1074
992
  # Get total size from first 4 bytes
1075
- total_size = attendance_data[0...4].unpack('I')[0]
993
+ total_size = attendance_data[0...4].unpack1('I')
1076
994
 
1077
995
  # Calculate record size
1078
- record_size = @records > 0 ? total_size / @records : 0
996
+ record_size = @records.positive? ? total_size / @records : 0
1079
997
 
1080
- if @verbose
1081
- puts "record_size is #{record_size}"
1082
- end
998
+ puts "record_size is #{record_size}" if @verbose
1083
999
 
1084
1000
  # Remove the first 4 bytes (total size)
1085
1001
  attendance_data = attendance_data[4..-1]
@@ -1091,18 +1007,20 @@ module RBZK
1091
1007
  uid, status, timestamp_raw, punch = attendance_data[0...8].ljust(8, "\x00".b).unpack('S<C4sC')
1092
1008
 
1093
1009
  if @verbose
1094
- puts "Attendance data (hex): #{attendance_data[0...8].bytes.map { |b| "0x#{b.to_s(16).rjust(2, '0')}" }.join(' ')}"
1010
+ puts "Attendance data (hex): #{attendance_data[0...8].bytes.map do |b|
1011
+ "0x#{b.to_s(16).rjust(2, '0')}"
1012
+ end.join(' ')}"
1095
1013
  end
1096
1014
 
1097
1015
  attendance_data = attendance_data[8..-1]
1098
1016
 
1099
1017
  # Look up user by uid
1100
1018
  tuser = users.find { |u| u.uid == uid }
1101
- if !tuser
1102
- user_id = uid.to_s
1103
- else
1104
- user_id = tuser.user_id
1105
- end
1019
+ user_id = if !tuser
1020
+ uid.to_s
1021
+ else
1022
+ tuser.user_id
1023
+ end
1106
1024
 
1107
1025
  # Decode timestamp
1108
1026
  timestamp = decode_time(timestamp_raw)
@@ -1115,10 +1033,13 @@ module RBZK
1115
1033
  # Handle 16-byte records
1116
1034
  while attendance_data && attendance_data.size >= 16
1117
1035
  # In Python: user_id, timestamp, status, punch, reserved, workcode = unpack('<I4sBB2sI', attendance_data.ljust(16, b'\x00')[:16])
1118
- user_id_raw, timestamp_raw, status, punch, reserved, workcode = attendance_data[0...16].ljust(16, "\x00".b).unpack('L<4sCCa2L<')
1036
+ user_id_raw, timestamp_raw, status, punch, _reserved, _workcode = attendance_data[0...16].ljust(16,
1037
+ "\x00".b).unpack('L<4sCCa2L<')
1119
1038
 
1120
1039
  if @verbose
1121
- puts "Attendance data (hex): #{attendance_data[0...16].bytes.map { |b| "0x#{b.to_s(16).rjust(2, '0')}" }.join(' ')}"
1040
+ puts "Attendance data (hex): #{attendance_data[0...16].bytes.map do |b|
1041
+ "0x#{b.to_s(16).rjust(2, '0')}"
1042
+ end.join(' ')}"
1122
1043
  end
1123
1044
 
1124
1045
  attendance_data = attendance_data[16..-1]
@@ -1129,9 +1050,7 @@ module RBZK
1129
1050
  # Look up user by user_id and uid
1130
1051
  tuser = users.find { |u| u.user_id == user_id }
1131
1052
  if !tuser
1132
- if @verbose
1133
- puts "no uid #{user_id}"
1134
- end
1053
+ puts "no uid #{user_id}" if @verbose
1135
1054
  uid = user_id
1136
1055
  tuser = users.find { |u| u.uid.to_s == user_id }
1137
1056
  if !tuser
@@ -1155,10 +1074,13 @@ module RBZK
1155
1074
  # Handle 40-byte records (default)
1156
1075
  while attendance_data && attendance_data.size >= 40
1157
1076
  # In Python: uid, user_id, status, timestamp, punch, space = unpack('<H24sB4sB8s', attendance_data.ljust(40, b'\x00')[:40])
1158
- uid, user_id_raw, status, timestamp_raw, punch, space = attendance_data[0...40].ljust(40, "\x00".b).unpack('S<a24Ca4Ca8')
1077
+ uid, user_id_raw, status, timestamp_raw, punch, _space = attendance_data[0...40].ljust(40,
1078
+ "\x00".b).unpack('S<a24Ca4Ca8')
1159
1079
 
1160
1080
  if @verbose
1161
- puts "Attendance data (hex): #{attendance_data[0...40].bytes.map { |b| "0x#{b.to_s(16).rjust(2, '0')}" }.join(' ')}"
1081
+ puts "Attendance data (hex): #{attendance_data[0...40].bytes.map do |b|
1082
+ "0x#{b.to_s(16).rjust(2, '0')}"
1083
+ end.join(' ')}"
1162
1084
  end
1163
1085
 
1164
1086
  # Extract user_id from null-terminated string
@@ -1180,23 +1102,23 @@ module RBZK
1180
1102
 
1181
1103
  def decode_time(t)
1182
1104
  # Convert binary timestamp to integer
1183
- t = t.unpack("L<")[0]
1105
+ t = t.unpack1('L<')
1184
1106
 
1185
1107
  # Extract time components
1186
1108
  second = t % 60
1187
- t = t / 60
1109
+ t /= 60
1188
1110
 
1189
1111
  minute = t % 60
1190
- t = t / 60
1112
+ t /= 60
1191
1113
 
1192
1114
  hour = t % 24
1193
- t = t / 24
1115
+ t /= 24
1194
1116
 
1195
1117
  day = t % 31 + 1
1196
- t = t / 31
1118
+ t /= 31
1197
1119
 
1198
1120
  month = t % 12 + 1
1199
- t = t / 12
1121
+ t /= 12
1200
1122
 
1201
1123
  year = t + 2000
1202
1124
 
@@ -1208,7 +1130,7 @@ module RBZK
1208
1130
  # Match Python's __decode_timehex method
1209
1131
  def decode_timehex(timehex)
1210
1132
  # Extract time components
1211
- year, month, day, hour, minute, second = timehex.unpack("C6")
1133
+ year, month, day, hour, minute, second = timehex.unpack('C6')
1212
1134
  year += 2000
1213
1135
 
1214
1136
  # Create Time object
@@ -1217,23 +1139,20 @@ module RBZK
1217
1139
 
1218
1140
  def encode_time(t)
1219
1141
  # Calculate encoded timestamp
1220
- d = (
1142
+ (
1221
1143
  ((t.year % 100) * 12 * 31 + ((t.month - 1) * 31) + t.day - 1) *
1222
1144
  (24 * 60 * 60) + (t.hour * 60 + t.minute) * 60 + t.second
1223
1145
  )
1224
- d
1225
1146
  end
1226
1147
 
1227
1148
  def get_time
1228
1149
  command = CMD_GET_TIME
1229
1150
  response_size = 1032
1230
- response = self.send_command(command, "", response_size)
1151
+ response = send_command(command, '', response_size)
1231
1152
 
1232
- if response && response[:status]
1233
- decode_time(@data[0...4])
1234
- else
1235
- raise RBZK::ZKErrorResponse, "Can't get time"
1236
- end
1153
+ raise RBZK::ZKErrorResponse, "Can't get time" unless response && response[:status]
1154
+
1155
+ decode_time(@data[0...4])
1237
1156
  end
1238
1157
 
1239
1158
  def set_time(timestamp = nil)
@@ -1242,24 +1161,22 @@ module RBZK
1242
1161
 
1243
1162
  command = CMD_SET_TIME
1244
1163
  command_string = [ encode_time(timestamp) ].pack('L<')
1245
- response = self.send_command(command, command_string)
1164
+ response = send_command(command, command_string)
1246
1165
 
1247
- if response && response[:status]
1248
- true
1249
- else
1250
- raise RBZK::ZKErrorResponse, "Can't set time"
1251
- end
1166
+ raise RBZK::ZKErrorResponse, "Can't set time" unless response && response[:status]
1167
+
1168
+ true
1252
1169
  end
1253
1170
 
1254
1171
  def clear_attendance_logs
1255
- self.send_command(CMD_CLEAR_ATTLOG)
1256
- self.recv_reply
1172
+ send_command(CMD_CLEAR_ATTLOG)
1173
+ recv_reply
1257
1174
  true
1258
1175
  end
1259
1176
 
1260
1177
  def clear_data
1261
- self.send_command(CMD_CLEAR_DATA)
1262
- self.recv_reply
1178
+ send_command(CMD_CLEAR_DATA)
1179
+ recv_reply
1263
1180
  true
1264
1181
  end
1265
1182
 
@@ -1269,33 +1186,33 @@ module RBZK
1269
1186
 
1270
1187
  result = "b'"
1271
1188
  binary_string.each_byte do |byte|
1272
- case byte
1273
- when 0x0d # Carriage return - Python shows as \r
1274
- result += "\\r"
1275
- when 0x0a # Line feed - Python shows as \n
1276
- result += "\\n"
1277
- when 0x09 # Tab - Python shows as \t
1278
- result += "\\t"
1279
- when 0x07 # Bell - Python can show as \a or \x07
1280
- result += "\\x07"
1281
- when 0x08 # Backspace - Python shows as \b
1282
- result += "\\b"
1283
- when 0x0c # Form feed - Python shows as \f
1284
- result += "\\f"
1285
- when 0x0b # Vertical tab - Python shows as \v
1286
- result += "\\v"
1287
- when 0x5c # Backslash - Python shows as \\
1288
- result += "\\\\"
1289
- when 0x27 # Single quote - Python shows as \'
1290
- result += "\\'"
1291
- when 0x22 # Double quote - Python shows as \"
1292
- result += "\\\""
1293
- when 32..126 # Printable ASCII
1294
- result += byte.chr
1295
- else
1296
- # All other bytes - Python shows as \xHH
1297
- result += "\\x#{byte.to_s(16).rjust(2, '0')}"
1298
- end
1189
+ result += case byte
1190
+ when 0x0d # Carriage return - Python shows as \r
1191
+ '\\r'
1192
+ when 0x0a # Line feed - Python shows as \n
1193
+ '\\n'
1194
+ when 0x09 # Tab - Python shows as \t
1195
+ '\\t'
1196
+ when 0x07 # Bell - Python can show as \a or \x07
1197
+ '\\x07'
1198
+ when 0x08 # Backspace - Python shows as \b
1199
+ '\\b'
1200
+ when 0x0c # Form feed - Python shows as \f
1201
+ '\\f'
1202
+ when 0x0b # Vertical tab - Python shows as \v
1203
+ '\\v'
1204
+ when 0x5c # Backslash - Python shows as \\
1205
+ '\\\\'
1206
+ when 0x27 # Single quote - Python shows as \'
1207
+ "\\'"
1208
+ when 0x22 # Double quote - Python shows as \"
1209
+ '\"'
1210
+ when 32..126 # Printable ASCII
1211
+ byte.chr
1212
+ else
1213
+ # All other bytes - Python shows as \xHH
1214
+ "\\x#{byte.to_s(16).rjust(2, '0')}"
1215
+ end
1299
1216
  end
1300
1217
  result += "'"
1301
1218
  result
@@ -1310,7 +1227,7 @@ module RBZK
1310
1227
  puts "Python expected: #{python_expected}"
1311
1228
 
1312
1229
  if ruby_formatted != python_expected
1313
- puts "DIFFERENCE DETECTED!"
1230
+ puts 'DIFFERENCE DETECTED!'
1314
1231
  # Show byte-by-byte comparison
1315
1232
  ruby_bytes = binary_string.bytes
1316
1233
  # Parse Python bytes string (format: b'\x01\x02')
@@ -1346,16 +1263,27 @@ module RBZK
1346
1263
  end
1347
1264
 
1348
1265
  # Show differences
1349
- puts "Byte-by-byte comparison:"
1266
+ puts 'Byte-by-byte comparison:'
1350
1267
  max_len = [ ruby_bytes.length, python_bytes.length ].max
1351
1268
  (0...max_len).each do |j|
1352
1269
  ruby_byte = j < ruby_bytes.length ? ruby_bytes[j] : nil
1353
1270
  python_byte = j < python_bytes.length ? python_bytes[j] : nil
1354
- match = ruby_byte == python_byte ? "" : ""
1355
- puts " Byte #{j}: Ruby=#{ruby_byte.nil? ? 'nil' : "0x#{ruby_byte.to_s(16).rjust(2, '0')}"}, Python=#{python_byte.nil? ? 'nil' : "0x#{python_byte.to_s(16).rjust(2, '0')}"} #{match}"
1271
+ match = ruby_byte == python_byte ? '' : ''
1272
+ puts " Byte #{j}: Ruby=#{if ruby_byte.nil?
1273
+ 'nil'
1274
+ else
1275
+ "0x#{ruby_byte.to_s(16).rjust(2,
1276
+ '0')}"
1277
+ end}, Python=#{if python_byte.nil?
1278
+ 'nil'
1279
+ else
1280
+ "0x#{python_byte.to_s(16).rjust(
1281
+ 2, '0'
1282
+ )}"
1283
+ end} #{match}"
1356
1284
  end
1357
1285
  else
1358
- puts "Binary data matches exactly!"
1286
+ puts 'Binary data matches exactly!'
1359
1287
  end
1360
1288
  end
1361
1289
 
@@ -1373,70 +1301,62 @@ module RBZK
1373
1301
  def read_sizes
1374
1302
  command = CMD_GET_FREE_SIZES
1375
1303
  response_size = 1024
1376
- cmd_response = self.send_command(command, "", response_size)
1304
+ cmd_response = send_command(command, '', response_size)
1377
1305
 
1378
- if cmd_response && cmd_response[:status]
1379
- if @verbose
1380
- puts "Data hex: #{@data.bytes.map { |b| "0x#{b.to_s(16).rjust(2, '0')}" }.join(' ')}"
1381
- puts "Data Python format: #{python_format(@data)}"
1306
+ raise RBZK::ZKErrorResponse, "Can't read sizes" unless cmd_response && cmd_response[:status]
1307
+
1308
+ if @verbose
1309
+ puts "Data hex: #{@data.bytes.map { |b| "0x#{b.to_s(16).rjust(2, '0')}" }.join(' ')}"
1310
+ puts "Data Python format: #{python_format(@data)}"
1311
+ end
1312
+
1313
+ size = @data.size
1314
+ puts "Data size: #{size} bytes" if @verbose
1315
+
1316
+ if @data.size >= 80
1317
+ # In Python: fields = unpack('20i', self.__data[:80])
1318
+ # In Ruby, 'l<' is a signed 32-bit integer (4 bytes) in little-endian format, which matches Python's 'i'
1319
+ fields = @data[0...80].unpack('l<20')
1320
+
1321
+ puts "Unpacked fields: #{fields.inspect}" if @verbose
1322
+
1323
+ @users = fields[4]
1324
+ @fingers = fields[6]
1325
+ @records = fields[8]
1326
+ @dummy = fields[10] # ???
1327
+ @cards = fields[12]
1328
+ @fingers_cap = fields[14]
1329
+ @users_cap = fields[15]
1330
+ @rec_cap = fields[16]
1331
+ @fingers_av = fields[17]
1332
+ @users_av = fields[18]
1333
+ @rec_av = fields[19]
1334
+ @data = @data[80..-1]
1335
+
1336
+ # Check for face information (added to match Python implementation)
1337
+ if @data.size >= 12 # face info
1338
+ # In Python: fields = unpack('3i', self.__data[:12]) #dirty hack! we need more information
1339
+ face_fields = @data[0...12].unpack('l<3')
1340
+ @faces = face_fields[0]
1341
+ @faces_cap = face_fields[2]
1342
+
1343
+ puts "Face info: faces=#{@faces}, capacity=#{@faces_cap}" if @verbose
1382
1344
  end
1383
1345
 
1384
- size = @data.size
1385
1346
  if @verbose
1386
- puts "Data size: #{size} bytes"
1347
+ puts "Device info: users=#{@users}, fingers=#{@fingers}, records=#{@records}"
1348
+ puts "Capacity: users=#{@users_cap}, fingers=#{@fingers_cap}, records=#{@rec_cap}"
1387
1349
  end
1388
1350
 
1389
- if @data.size >= 80
1390
- # In Python: fields = unpack('20i', self.__data[:80])
1391
- # In Ruby, 'l<' is a signed 32-bit integer (4 bytes) in little-endian format, which matches Python's 'i'
1392
- fields = @data[0...80].unpack('l<20')
1393
-
1394
- if @verbose
1395
- puts "Unpacked fields: #{fields.inspect}"
1396
- end
1397
-
1398
- @users = fields[4]
1399
- @fingers = fields[6]
1400
- @records = fields[8]
1401
- @dummy = fields[10] # ???
1402
- @cards = fields[12]
1403
- @fingers_cap = fields[14]
1404
- @users_cap = fields[15]
1405
- @rec_cap = fields[16]
1406
- @fingers_av = fields[17]
1407
- @users_av = fields[18]
1408
- @rec_av = fields[19]
1409
- @data = @data[80..-1]
1410
-
1411
- # Check for face information (added to match Python implementation)
1412
- if @data.size >= 12 # face info
1413
- # In Python: fields = unpack('3i', self.__data[:12]) #dirty hack! we need more information
1414
- face_fields = @data[0...12].unpack('l<3')
1415
- @faces = face_fields[0]
1416
- @faces_cap = face_fields[2]
1417
-
1418
- if @verbose
1419
- puts "Face info: faces=#{@faces}, capacity=#{@faces_cap}"
1420
- end
1421
- end
1422
-
1423
- if @verbose
1424
- puts "Device info: users=#{@users}, fingers=#{@fingers}, records=#{@records}"
1425
- puts "Capacity: users=#{@users_cap}, fingers=#{@fingers_cap}, records=#{@rec_cap}"
1426
- end
1427
-
1428
- return true
1429
- end
1430
- else
1431
- raise RBZK::ZKErrorResponse, "Can't read sizes"
1351
+ return true
1432
1352
  end
1433
1353
 
1434
1354
  false
1435
1355
  end
1436
1356
 
1437
1357
  def get_free_sizes
1438
- self.send_command(CMD_GET_FREE_SIZES)
1439
- reply = self.recv_reply
1358
+ send_command(CMD_GET_FREE_SIZES)
1359
+ reply = recv_reply
1440
1360
 
1441
1361
  if reply && reply.size >= 8
1442
1362
  sizes_data = reply[8..-1].unpack('S<*')
@@ -1456,11 +1376,11 @@ module RBZK
1456
1376
  def get_templates
1457
1377
  fingers = []
1458
1378
 
1459
- self.send_command(CMD_PREPARE_DATA, [ FCT_FINGERTMP ].pack('C'))
1460
- self.recv_reply
1379
+ send_command(CMD_PREPARE_DATA, [ FCT_FINGERTMP ].pack('C'))
1380
+ recv_reply
1461
1381
 
1462
- data_size = self.recv_long
1463
- templates_data = self.recv_chunk(data_size)
1382
+ data_size = recv_long
1383
+ templates_data = recv_chunk(data_size)
1464
1384
 
1465
1385
  if templates_data && !templates_data.empty?
1466
1386
  offset = 0
@@ -1480,8 +1400,8 @@ module RBZK
1480
1400
  end
1481
1401
 
1482
1402
  def get_user_template(uid, finger_id)
1483
- self.send_command(CMD_GET_USERTEMP, [ uid, finger_id ].pack('S<S<'))
1484
- reply = self.recv_reply
1403
+ send_command(CMD_GET_USERTEMP, [ uid, finger_id ].pack('S<S<'))
1404
+ reply = recv_reply
1485
1405
 
1486
1406
  if reply && reply.size >= 8
1487
1407
  template_data = reply[8..-1]
@@ -1512,9 +1432,7 @@ module RBZK
1512
1432
  # Use connect_ex like Python (returns error code instead of raising exception)
1513
1433
  sockaddr = Socket.pack_sockaddr_in(@port, @ip)
1514
1434
  @socket.connect_nonblock(sockaddr)
1515
- if @verbose
1516
- puts "TCP socket connected successfully"
1517
- end
1435
+ puts 'TCP socket connected successfully' if @verbose
1518
1436
  rescue IO::WaitWritable
1519
1437
  # Socket is in progress of connecting
1520
1438
  ready = IO.select(nil, [ @socket ], nil, @timeout)
@@ -1523,42 +1441,30 @@ module RBZK
1523
1441
  @socket.connect_nonblock(sockaddr)
1524
1442
  rescue Errno::EISCONN
1525
1443
  # Already connected, which is fine
1526
- if @verbose
1527
- puts "TCP socket connected successfully"
1528
- end
1529
- rescue => e
1444
+ puts 'TCP socket connected successfully' if @verbose
1445
+ rescue StandardError => e
1530
1446
  # Connection failed
1531
- if @verbose
1532
- puts "TCP socket connection failed: #{e.message}"
1533
- end
1447
+ puts "TCP socket connection failed: #{e.message}" if @verbose
1534
1448
  raise e
1535
1449
  end
1536
1450
  else
1537
1451
  # Connection timed out
1538
- if @verbose
1539
- puts "TCP socket connection timed out"
1540
- end
1452
+ puts 'TCP socket connection timed out' if @verbose
1541
1453
  raise Errno::ETIMEDOUT
1542
1454
  end
1543
1455
  rescue Errno::EISCONN
1544
1456
  # Already connected, which is fine
1545
- if @verbose
1546
- puts "TCP socket already connected"
1547
- end
1457
+ puts 'TCP socket already connected' if @verbose
1548
1458
  end
1549
1459
  else
1550
1460
  # Create UDP socket (like Python's socket(AF_INET, SOCK_DGRAM))
1551
1461
  @socket = Socket.new(Socket::AF_INET, Socket::SOCK_DGRAM)
1552
1462
  @socket.setsockopt(Socket::SOL_SOCKET, Socket::SO_RCVTIMEO, [ @timeout, 0 ].pack('l_*'))
1553
1463
 
1554
- if @verbose
1555
- puts "UDP socket created successfully"
1556
- end
1557
- end
1558
- rescue => e
1559
- if @verbose
1560
- puts "Socket creation failed: #{e.message}"
1464
+ puts 'UDP socket created successfully' if @verbose
1561
1465
  end
1466
+ rescue StandardError => e
1467
+ puts "Socket creation failed: #{e.message}" if @verbose
1562
1468
  raise RBZK::ZKNetworkError, "Failed to create socket: #{e.message}"
1563
1469
  end
1564
1470
 
@@ -1584,24 +1490,18 @@ module RBZK
1584
1490
  end
1585
1491
 
1586
1492
  def ping
1587
- if @verbose
1588
- puts "Pinging device at #{@ip}:#{@port}..."
1589
- end
1493
+ puts "Pinging device at #{@ip}:#{@port}..." if @verbose
1590
1494
 
1591
1495
  # Try TCP ping first
1592
1496
  begin
1593
1497
  Timeout.timeout(5) do
1594
1498
  s = TCPSocket.new(@ip, @port)
1595
1499
  s.close
1596
- if @verbose
1597
- puts "TCP ping successful"
1598
- end
1500
+ puts 'TCP ping successful' if @verbose
1599
1501
  return true
1600
1502
  end
1601
1503
  rescue Timeout::Error, Errno::ECONNREFUSED, Errno::EHOSTUNREACH => e
1602
- if @verbose
1603
- puts "TCP ping failed: #{e.message}"
1604
- end
1504
+ puts "TCP ping failed: #{e.message}" if @verbose
1605
1505
  end
1606
1506
 
1607
1507
  # If TCP ping fails, try UDP ping
@@ -1612,23 +1512,17 @@ module RBZK
1612
1512
  ready = IO.select([ udp_socket ], nil, nil, 5)
1613
1513
 
1614
1514
  if ready
1615
- if @verbose
1616
- puts "UDP ping successful"
1617
- end
1515
+ puts 'UDP ping successful' if @verbose
1618
1516
  udp_socket.close
1619
- return true
1517
+ true
1620
1518
  else
1621
- if @verbose
1622
- puts "UDP ping timed out"
1623
- end
1519
+ puts 'UDP ping timed out' if @verbose
1624
1520
  udp_socket.close
1625
- return false
1626
- end
1627
- rescue => e
1628
- if @verbose
1629
- puts "UDP ping failed: #{e.message}"
1521
+ false
1630
1522
  end
1631
- return false
1523
+ rescue StandardError => e
1524
+ puts "UDP ping failed: #{e.message}" if @verbose
1525
+ false
1632
1526
  end
1633
1527
  end
1634
1528
 
@@ -1647,24 +1541,18 @@ module RBZK
1647
1541
 
1648
1542
  # In Python: if checksum > const.USHRT_MAX: checksum -= const.USHRT_MAX
1649
1543
  # Handle overflow immediately after each addition
1650
- if checksum > USHRT_MAX
1651
- checksum -= USHRT_MAX
1652
- end
1544
+ checksum -= USHRT_MAX if checksum > USHRT_MAX
1653
1545
 
1654
1546
  l -= 2
1655
1547
  end
1656
1548
 
1657
1549
  # Handle odd byte if present
1658
1550
  # In Python: if l: checksum = checksum + p[-1]
1659
- if l > 0
1660
- checksum += buf[i]
1661
- end
1551
+ checksum += buf[i] if l.positive?
1662
1552
 
1663
1553
  # Handle overflow
1664
1554
  # In Python: while checksum > const.USHRT_MAX: checksum -= const.USHRT_MAX
1665
- while checksum > USHRT_MAX
1666
- checksum -= USHRT_MAX
1667
- end
1555
+ checksum -= USHRT_MAX while checksum > USHRT_MAX
1668
1556
 
1669
1557
  # Bitwise complement
1670
1558
  # In Python: checksum = ~checksum
@@ -1672,9 +1560,7 @@ module RBZK
1672
1560
 
1673
1561
  # Handle negative values
1674
1562
  # In Python: while checksum < 0: checksum += const.USHRT_MAX
1675
- while checksum < 0
1676
- checksum += USHRT_MAX
1677
- end
1563
+ checksum += USHRT_MAX while checksum.negative?
1678
1564
 
1679
1565
  # Return the checksum
1680
1566
  checksum
@@ -1683,6 +1569,7 @@ module RBZK
1683
1569
  # Helper method to debug binary data in both Python and Ruby formats
1684
1570
  def debug_binary(name, data)
1685
1571
  return unless @verbose
1572
+
1686
1573
  puts "#{name} (hex): #{data.bytes.map { |b| "\\x#{b.to_s(16).rjust(2, '0')}" }.join('')}"
1687
1574
  puts "#{name} (Ruby): #{data.bytes.map { |b| "0x#{b.to_s(16).rjust(2, '0')}" }.join(' ')}"
1688
1575
  puts "#{name} (Python): #{format_as_python_bytes(data)}"
@@ -1694,18 +1581,18 @@ module RBZK
1694
1581
  top = [ MACHINE_PREPARE_DATA_1, MACHINE_PREPARE_DATA_2, length ].pack('S<S<I<')
1695
1582
 
1696
1583
  if @verbose
1697
- puts "TCP header components:"
1584
+ puts 'TCP header components:'
1698
1585
  puts " MACHINE_PREPARE_DATA_1: 0x#{MACHINE_PREPARE_DATA_1.to_s(16)}"
1699
1586
  puts " MACHINE_PREPARE_DATA_2: 0x#{MACHINE_PREPARE_DATA_2.to_s(16)}"
1700
1587
  puts " packet length: #{length}"
1701
- debug_binary("TCP header", top)
1702
- debug_binary("Full TCP packet", top + packet)
1588
+ debug_binary('TCP header', top)
1589
+ debug_binary('Full TCP packet', top + packet)
1703
1590
  end
1704
1591
 
1705
1592
  top + packet
1706
1593
  end
1707
1594
 
1708
- def create_header(command, command_string = "".b, session_id = 0, reply_id = 0)
1595
+ def create_header(command, command_string = ''.b, session_id = 0, reply_id = 0)
1709
1596
  # Ensure command_string is a binary string
1710
1597
  command_string = command_string.to_s.b
1711
1598
 
@@ -1720,35 +1607,33 @@ module RBZK
1720
1607
 
1721
1608
  # Update reply_id
1722
1609
  reply_id += 1
1723
- if reply_id >= USHRT_MAX
1724
- reply_id -= USHRT_MAX
1725
- end
1610
+ reply_id -= USHRT_MAX if reply_id >= USHRT_MAX
1726
1611
 
1727
1612
  # Create final header with updated values
1728
1613
  buf = [ command, checksum, session_id, reply_id ].pack('v4')
1729
1614
 
1730
1615
  if @verbose
1731
- puts "Header components:"
1616
+ puts 'Header components:'
1732
1617
  puts " Command: #{command}"
1733
1618
  puts " Checksum: #{checksum}"
1734
1619
  puts " Session ID: #{session_id}"
1735
1620
  puts " Reply ID: #{reply_id}"
1736
1621
 
1737
1622
  if !command_string.empty?
1738
- debug_binary("Command string", command_string)
1623
+ debug_binary('Command string', command_string)
1739
1624
  else
1740
- puts "Command string: (empty)"
1625
+ puts 'Command string: (empty)'
1741
1626
  end
1742
- debug_binary("Final header", buf)
1627
+ debug_binary('Final header', buf)
1743
1628
  end
1744
1629
 
1745
1630
  buf + command_string
1746
1631
  end
1747
1632
 
1748
- def send_command(command, command_string = "".b, response_size = 8)
1633
+ def send_command(command, command_string = ''.b, response_size = 8)
1749
1634
  # Check connection status (except for connect and auth commands)
1750
1635
  if command != CMD_CONNECT && command != CMD_AUTH && !@connected
1751
- raise RBZK::ZKErrorConnection, "Instance are not connected."
1636
+ raise RBZK::ZKErrorConnection, 'Instance are not connected.'
1752
1637
  end
1753
1638
 
1754
1639
  # In Python, command_string is a bytes object (b'')
@@ -1782,9 +1667,9 @@ module RBZK
1782
1667
  if @verbose
1783
1668
  puts "\nSending TCP packet:"
1784
1669
  puts "Note: In send_command, 'top' variable contains the full packet (header + command packet)"
1785
- puts "This is because create_tcp_top returns the full packet, not just the header"
1786
- debug_binary("Command packet (buf)", buf)
1787
- debug_binary("Full TCP packet (top)", top) # 'top' contains the full packet here
1670
+ puts 'This is because create_tcp_top returns the full packet, not just the header'
1671
+ debug_binary('Command packet (buf)', buf)
1672
+ debug_binary('Full TCP packet (top)', top) # 'top' contains the full packet here
1788
1673
  end
1789
1674
 
1790
1675
  @socket.send(top, 0)
@@ -1793,12 +1678,10 @@ module RBZK
1793
1678
 
1794
1679
  if @verbose
1795
1680
  puts "\nReceived TCP response:"
1796
- debug_binary("TCP response", @tcp_data_recv)
1681
+ debug_binary('TCP response', @tcp_data_recv)
1797
1682
  end
1798
1683
 
1799
- if @tcp_length == 0
1800
- raise RBZK::ZKNetworkError, "TCP packet invalid"
1801
- end
1684
+ raise RBZK::ZKNetworkError, 'TCP packet invalid' if @tcp_length.zero?
1802
1685
 
1803
1686
  @header = @tcp_data_recv[8..15].unpack('v4')
1804
1687
  @data_recv = @tcp_data_recv[8..-1]
@@ -1808,10 +1691,8 @@ module RBZK
1808
1691
  @data_recv = @socket.recv(response_size)
1809
1692
  @header = @data_recv[0..7].unpack('S<4')
1810
1693
  end
1811
- rescue => e
1812
- if @verbose
1813
- puts "Connection error during send: #{e.message}"
1814
- end
1694
+ rescue StandardError => e
1695
+ puts "Connection error during send: #{e.message}" if @verbose
1815
1696
  raise RBZK::ZKNetworkError, e.message
1816
1697
  end
1817
1698
 
@@ -1836,9 +1717,7 @@ module RBZK
1836
1717
 
1837
1718
  def recv_reply
1838
1719
  begin
1839
- if @verbose
1840
- puts "Waiting for TCP reply"
1841
- end
1720
+ puts 'Waiting for TCP reply' if @verbose
1842
1721
 
1843
1722
  # Set a timeout for the read operation
1844
1723
  Timeout.timeout(5) do
@@ -1849,15 +1728,11 @@ module RBZK
1849
1728
  # Parse TCP header
1850
1729
  tcp_format1, tcp_format2, tcp_length = tcp_header.unpack('S<S<I<')
1851
1730
 
1852
- if @verbose
1853
- puts "TCP header: format1=#{tcp_format1}, format2=#{tcp_format2}, length=#{tcp_length}"
1854
- end
1731
+ puts "TCP header: format1=#{tcp_format1}, format2=#{tcp_format2}, length=#{tcp_length}" if @verbose
1855
1732
 
1856
1733
  # Verify TCP header format
1857
1734
  if tcp_format1 != MACHINE_PREPARE_DATA_1 || tcp_format2 != MACHINE_PREPARE_DATA_2
1858
- if @verbose
1859
- puts "Invalid TCP header format: #{tcp_format1}, #{tcp_format2}"
1860
- end
1735
+ puts "Invalid TCP header format: #{tcp_format1}, #{tcp_format2}" if @verbose
1861
1736
  return nil
1862
1737
  end
1863
1738
 
@@ -1876,30 +1751,24 @@ module RBZK
1876
1751
  data_size = tcp_length - 8
1877
1752
 
1878
1753
  # Read data if available
1879
- data = ""
1880
- if data_size > 0
1881
- if @verbose
1882
- puts "Reading #{data_size} bytes of data"
1883
- end
1754
+ data = ''
1755
+ if data_size.positive?
1756
+ puts "Reading #{data_size} bytes of data" if @verbose
1884
1757
 
1885
1758
  # Read data in chunks to handle large responses (like Python implementation)
1886
1759
  remaining = data_size
1887
- while remaining > 0
1760
+ while remaining.positive?
1888
1761
  chunk_size = [ remaining, 4096 ].min
1889
1762
  chunk = @socket.read(chunk_size)
1890
1763
  if chunk.nil? || chunk.empty?
1891
- if @verbose
1892
- puts "Failed to read data chunk, got #{chunk.inspect}"
1893
- end
1764
+ puts "Failed to read data chunk, got #{chunk.inspect}" if @verbose
1894
1765
  break
1895
1766
  end
1896
1767
 
1897
1768
  data += chunk
1898
1769
  remaining -= chunk.size
1899
1770
 
1900
- if @verbose && remaining > 0
1901
- puts "Read #{chunk.size} bytes, #{remaining} remaining"
1902
- end
1771
+ puts "Read #{chunk.size} bytes, #{remaining} remaining" if @verbose && remaining.positive?
1903
1772
  end
1904
1773
  end
1905
1774
 
@@ -1910,47 +1779,33 @@ module RBZK
1910
1779
  @session_id = session_id
1911
1780
 
1912
1781
  # Check command type and handle accordingly (like Python implementation)
1913
- if command == CMD_ACK_OK
1914
- if @verbose
1915
- puts "Received ACK_OK"
1916
- end
1782
+ case command
1783
+ when CMD_ACK_OK
1784
+ puts 'Received ACK_OK' if @verbose
1917
1785
  return cmd_header + data
1918
- elsif command == CMD_ACK_ERROR
1919
- if @verbose
1920
- puts "Received ACK_ERROR"
1921
- end
1786
+ when CMD_ACK_ERROR
1787
+ puts 'Received ACK_ERROR' if @verbose
1922
1788
  return nil
1923
- elsif command == CMD_ACK_DATA
1924
- if @verbose
1925
- puts "Received ACK_DATA"
1926
- end
1927
- if data_size > 0
1928
- return cmd_header + data
1929
- else
1930
- return nil
1931
- end
1789
+ when CMD_ACK_DATA
1790
+ puts 'Received ACK_DATA' if @verbose
1791
+ return cmd_header + data if data_size.positive?
1792
+
1793
+ return nil
1794
+
1932
1795
  else
1933
- if @verbose
1934
- puts "Received unknown command: #{command}"
1935
- end
1796
+ puts "Received unknown command: #{command}" if @verbose
1936
1797
  return cmd_header + data
1937
1798
  end
1938
1799
  end
1939
1800
  rescue Timeout::Error => e
1940
- if @verbose
1941
- puts "Timeout waiting for response: #{e.message}"
1942
- end
1943
- raise RBZK::ZKErrorResponse, "Timeout waiting for response"
1801
+ puts "Timeout waiting for response: #{e.message}" if @verbose
1802
+ raise RBZK::ZKErrorResponse, 'Timeout waiting for response'
1944
1803
  rescue Errno::ECONNRESET, Errno::EPIPE => e
1945
- if @verbose
1946
- puts "Connection error during receive: #{e.message}"
1947
- end
1804
+ puts "Connection error during receive: #{e.message}" if @verbose
1948
1805
  raise RBZK::ZKNetworkError, "Connection error: #{e.message}"
1949
1806
  rescue Errno::EAGAIN, Errno::EWOULDBLOCK => e
1950
- if @verbose
1951
- puts "Timeout waiting for response: #{e.message}"
1952
- end
1953
- raise RBZK::ZKErrorResponse, "Timeout waiting for response"
1807
+ puts "Timeout waiting for response: #{e.message}" if @verbose
1808
+ raise RBZK::ZKErrorResponse, 'Timeout waiting for response'
1954
1809
  end
1955
1810
 
1956
1811
  nil
@@ -1960,31 +1815,25 @@ module RBZK
1960
1815
  if @data_recv && @data_recv.size >= 4
1961
1816
  data = @data_recv[0..3]
1962
1817
  @data_recv = @data_recv[4..-1]
1963
- return data.unpack('L<')[0]
1818
+ return data.unpack1('L<')
1964
1819
  end
1965
1820
 
1966
1821
  0
1967
1822
  end
1968
1823
 
1969
1824
  def recv_chunk(size)
1970
- if @verbose
1971
- puts "Receiving chunk of #{size} bytes"
1972
- end
1825
+ puts "Receiving chunk of #{size} bytes" if @verbose
1973
1826
 
1974
1827
  if @data_recv && @data_recv.size >= size
1975
1828
  data = @data_recv[0...size]
1976
1829
  @data_recv = @data_recv[size..-1]
1977
1830
 
1978
- if @verbose
1979
- puts "Received #{data.size} bytes from buffer"
1980
- end
1831
+ puts "Received #{data.size} bytes from buffer" if @verbose
1981
1832
 
1982
1833
  return data
1983
1834
  end
1984
1835
 
1985
- if @verbose
1986
- puts "Warning: No data available in buffer"
1987
- end
1836
+ puts 'Warning: No data available in buffer' if @verbose
1988
1837
 
1989
1838
  # Return empty string if no data is available
1990
1839
  ''
@@ -2001,11 +1850,11 @@ module RBZK
2001
1850
  k = 0
2002
1851
 
2003
1852
  32.times do |i|
2004
- if (key & (1 << i)) != 0
2005
- k = (k << 1 | 1)
2006
- else
2007
- k = k << 1
2008
- end
1853
+ k = if (key & (1 << i)) != 0
1854
+ (k << 1 | 1)
1855
+ else
1856
+ k << 1
1857
+ end
2009
1858
  end
2010
1859
 
2011
1860
  k += session_id
@@ -2038,9 +1887,7 @@ module RBZK
2038
1887
  # Note: The third byte is just B, not k[2] ^ B
2039
1888
  result = [ k_bytes[0] ^ b, k_bytes[1] ^ b, b, k_bytes[3] ^ b ].pack('C4')
2040
1889
 
2041
- if @verbose
2042
- puts "Final commkey bytes: #{result.bytes.map { |b| "0x#{b.to_s(16).rjust(2, '0')}" }.join(' ')}"
2043
- end
1890
+ puts "Final commkey bytes: #{result.bytes.map { |b| "0x#{b.to_s(16).rjust(2, '0')}" }.join(' ')}" if @verbose
2044
1891
 
2045
1892
  result
2046
1893
  end