0

I am trying to attain data from an RFID reader I have attached to a serial port. The data is coming through as jumbled characters, which I have to convert to hex. I am getting an error trying to convert it to hex, when I do this:

puts "%02X" % key

I get this error: '%' : invalid value for Integer(): "\xE2\x10......"etc

It is almost converting it right as the "\xE2\x10..." etc is close to what it should be outputting, it should be 00 00 E2 00 10... etc. I'm not sure if there is another way to convert it to hex, I've also tried:

key.to_i.to_s(16)

and

key.hex

But both produce 0 as the output, which isn't correct. When I try to convert it to just an integer it converts it to a 0, I'm not sure why.

Here is the full code if that helps, most of it is taken from an example on the net:

require "serialport"
class RfidReader
 attr_accessor :key

 def initialize(port)
   port_str = "COM7"
   baud_rate = 9600
   data_bits = 8
   stop_bits = 1
   parity = SerialPort::NONE
   @sp = SerialPort.new(port_str, baud_rate, data_bits, stop_bits, parity)
   @key_parts = []
   @key_limit = 16 # number of slots in the RFID card.
   while true do
     main
   end
   @sp.close
 end

 def key_detected?
   @key_parts << @sp.getc
   if @key_parts.size >= @key_limit
     self.key = @key_parts.join()
     @key_parts = []
     true
   else
     false
   end
 end

 def main
   if key_detected?

    self.key.gsub!(/\0/, '')
    #puts self.key.hex
    #puts self.key.to_i.to_s(16)
    puts "%02X" % key
    #puts key



   end
 end
end

RfidReader.new("COM7")
Mark
  • 3
  • 1
  • What do the full bytes look like and what number do they represent? You're probably looking for [`String#unpack`](http://ruby-doc.org/core-2.0.0/String.html#method-i-unpack) in any case. – mu is too short Sep 17 '13 at 05:23
  • It's just a jumble of random characters, smiley faces, arrows all odd characters, I can't save them as half of them save as squares sorry. – Mark Sep 17 '13 at 05:50
  • You should be able to get the raw bytes with a hex dumper at least. Do you know what the bytes are supposed to represent? – mu is too short Sep 17 '13 at 05:59
  • Yep, it should look like this: 00 00 e2 00 10 18 74 13 01 92 04 60e5 e4 00 af ff. Not exactly sure, there should be an ID number and some data as far as I know. I tried running the outputted data through a hex dump and I did get the right value. I just need to get it to convert properly I guess. I'v added puts key.unpack('H') but I'm not sure if I'm using it right. It's only printing one character at a time, there should be a lot more. Sorry I'm probably doing something stupid, still learning. – Mark Sep 17 '13 at 06:08

1 Answers1

1

What you get is a string containing the bytestream from your RFID reader. Use String#unpack1 to convert the byte string to actual bytes (numbers).

random_bytes_from_reader = "\xE2\x10\x42\x23\xA9"
random_bytes_from_reader.unpack('C*') # assume we have unsigned chars
#=> [226, 16, 66, 35, 169]

You already figured out how to display them as hex strings with number.to_s(16).

1 Read the documentation! The param of unpack depends on the specification of your RFID reader. 'C*' was just a guess on my part.

tessi
  • 13,313
  • 3
  • 38
  • 50
  • I think that might be right, I'm getting an array of numbers ranging from 0-255. But when I try to convert them to hex using to_s(16) I get this error "wrong number of arguments <1 for 0> . After doing this: `unpacked_chars = key.unpack('C*').to_s(16)` – Mark Sep 17 '13 at 22:40
  • That comes because `unpack` returns an array of numbers. But you need to call `to_s` on the actual number. Try `key.unpack('C*').map {|num| num.to_s(16)}`. – tessi Sep 17 '13 at 23:03
  • Nevermind I got it to work, had to change it to an integer first using to_i. Thanks. – Mark Sep 17 '13 at 23:39