module Zklib::Helper

Public Instance Methods

check_valid(options) click to toggle source

Check validity of response

param options

|_ data  Data to check validity
# File lib/zklib/helper.rb, line 7
def check_valid(options)
  BinData::Uint16le.read(options[:data][0..-1]).snapshot == CMD_ACK_OK
end
create_checksum(options) click to toggle source

Create checksum for execution

param options

|_ data  Data to create checksum
# File lib/zklib/helper.rb, line 15
def create_checksum(options)
  data = options[:data]
  checksum = 0

  (0...data.length).step(2) do |i|
    checksum += (i == data.length - 1) ?
      BinData::Uint8le.read(data[i]).snapshot :
      BinData::Uint16le.read(data[i..-1]).snapshot
    checksum %= USHRT_MAX
  end

  chksum = USHRT_MAX - checksum - 1
  chksum
end
create_header(options) click to toggle source

Create header for execution

param options

|_ command         Command value
|_ checksum        Checksum
|_ session_id      Session ID
|_ reply_id        Reply ID
|_ command_string  Command string
# File lib/zklib/helper.rb, line 38
def create_header(options)
  header_buffer = StringIO.new
  binary_writer = BinData::Uint16le.new

  # Write command header
  binary_writer.value = options[:command]
  header_buffer.pos   = 0
  binary_writer.write(header_buffer)

  # Write checksum header
  binary_writer.value = options[:checksum]
  header_buffer.pos   = 2
  binary_writer.write(header_buffer)

  # Write session ID header
  binary_writer.value = options[:session_id]
  header_buffer.pos   = 4
  binary_writer.write(header_buffer)

  # Write reply ID header
  binary_writer.value = options[:reply_id]
  header_buffer.pos   = 6
  binary_writer.write(header_buffer)

  # Write command string header
  header_buffer.pos = 8
  header_buffer.write(options[:command_string])

  # Rewrite checksum header
  binary_writer.value = create_checksum(data: header_buffer.string)
  header_buffer.pos   = 2
  binary_writer.write(header_buffer)

  # Rewrite reply ID header
  binary_writer.value = (options[:reply_id] + 1) % USHRT_MAX
  header_buffer.pos   = 6
  binary_writer.write(header_buffer)

  header_buffer.string
end
decode_time(options) click to toggle source

Convert number of seconds to time

param options

|_ seconds  Time in seconds to decode
# File lib/zklib/helper.rb, line 83
def decode_time(options)
  time = options[:seconds]

  # Calculate second value
  second = time % 60
  time = (time - second) / 60

  # Calculate minute value
  minute = time % 60
  time = (time - minute) / 60

  # Calculate hour value
  hour = time % 24
  time = (time - hour) / 24

  # Calculate day value
  day = time % 31 + 1
  time = (time - day + 1) / 31

  # Calculate month value
  month = time % 12 + 1
  time = (time - month + 1) / 12

  # Calculate year value
  year = time + 2000

  Time.new(year, month, day, hour, minute, second)
end
decode_user_data(options) click to toggle source
# File lib/zklib/helper.rb, line 112
def decode_user_data(options)
  data = options[:data]

  {
    uid:      BinData::Uint16be.read(data[0..1]).snapshot,
    role:     BinData::Uint16le.read(data[2..3]).snapshot,
    password: nil,
    name:     nil,
    cardno:   nil,
    userid:   nil
  }
end
encode_time(options) click to toggle source

Convert time to number of seconds

param options

|_ time  Time object to encode
# File lib/zklib/helper.rb, line 129
def encode_time(options)
  time = options[:time]

  ((time.year % 100) * 12 * 31 + ((time.mon - 1) * 31) + time.day - 1) * (24 * 60 * 60) + (time.hour * 60 + time.min) * 60 + time.sec
end
execute_cmd(options) { |valid: true, data: data_recv| ... } click to toggle source

Execute command on attendance machine

param options

|_ command         Command to execute
|_ command_string  Command string
# File lib/zklib/helper.rb, line 140
def execute_cmd(options)
  command = options[:command]
  self.reply_id = USHRT_MAX - 1 if command == CMD_CONNECT
  header = create_header(
    command:        command,
    checksum:       0,
    session_id:     session_id,
    reply_id:       reply_id,
    command_string: options[:command_string]
  )

  # Send command
  socket = UDPSocket.new
  socket.bind('0.0.0.0', inport)
  socket.send(header, 0, ip, port)
  self.data_recv = socket.recvfrom(USHRT_MAX)[0] if IO.select([socket], nil, nil, 10)
  socket.close

  # Callback
  if data_recv && data_recv.length > 0
    self.session_id = BinData::Uint16le.read(data_recv[4..-1]).snapshot
    self.reply_id = BinData::Uint16le.read(data_recv[6..-1]).snapshot

    yield(valid: true, data: data_recv) if block_given?
  else
    yield(valid: false, error: 'Empty response') if block_given?
  end
end
receive_nonblock(options) click to toggle source

Receive data from non-blocking socket

param options

|_ socket  Socket to receive data from
# File lib/zklib/helper.rb, line 173
def receive_nonblock(options)
  return options[:socket].recvfrom_nonblock(USHRT_MAX)
rescue IO::WaitReadable
  IO.select([options[:socket]])

  retry
end