rdm6300 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/lib/rdm6300.rb +138 -0
- metadata +58 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: de049d9e1aa342bf79fd57474de2068df2fc54a7a88750305771656c28f11a90
|
4
|
+
data.tar.gz: 567199ef4ae0818b72f0c64b7c47732a332deec14ac0132a9aaa50a57c2db27e
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: bf5e6ebfde8424c50a90b0f8e2822ec6ac863586a8722b4c4ade44241af398a162b5140cfc6f76b5677304868f915849b964e2dafe0a7ce4b1ef41ba193d8d17
|
7
|
+
data.tar.gz: a60e53446d3ab94efcb6f1b21d86dbc7082cc3ad626a76098437a08e094e0a3d757c15540869cb3d66f86d836dd227eb5ef3be4483116a1f26566245ea603284
|
data/lib/rdm6300.rb
ADDED
@@ -0,0 +1,138 @@
|
|
1
|
+
require 'serialport'
|
2
|
+
|
3
|
+
##
|
4
|
+
# This class reads 125kHz tags over an RS-232 serial port using the RDM6300 module
|
5
|
+
class Rdm6300
|
6
|
+
##
|
7
|
+
# Read 125kHz RFID tags from a serial port using the RDM6300 module as follows:
|
8
|
+
# rdm = Rdm6300.new('/dev/ttyS0')
|
9
|
+
# while true
|
10
|
+
# puts rdm.get_tag()
|
11
|
+
# end
|
12
|
+
#
|
13
|
+
# This will return a zero-padded string with the tag number.
|
14
|
+
|
15
|
+
# RDM6300 uses 0x02 to indicate the start of a tag
|
16
|
+
START_CODE = 0x02
|
17
|
+
# RDM6300 uses 0x03 to indicate the end of a tag
|
18
|
+
END_CODE = 0x03
|
19
|
+
# Valid tag data will always have a total length of 12 bytes over RS-232
|
20
|
+
VALID_LENGTH = 12
|
21
|
+
|
22
|
+
# The default serial port is /dev/ttyAMA0 since this is the primary serial port on a Raspberry Pi
|
23
|
+
#
|
24
|
+
# You will need to stop the Linux kernel using /dev/ttyAMA0 if you want to use it with the RDM6300
|
25
|
+
#
|
26
|
+
# On a Raspberry Pi 4 and Raspberry Pi OS, this can be done by adding enable_uart=1 and dtoverlay=disable-bt to /boot/config.txt
|
27
|
+
# and removing console=serial0,115200 from /boot/cmdline.txt
|
28
|
+
#
|
29
|
+
# The flush delay handles the situation where rogue RF triggers the RDM6300. Genuine tag data takes less than a second
|
30
|
+
# to transmit to the RDM6300. If there is tag data that takes longer than flush_delay to arrive, the input buffer is flushed.
|
31
|
+
# This improves the reliability of a long-running tag reader.
|
32
|
+
def initialize(serial_port_dev = '/dev/ttyAMA0', debug: false, flush_delay: 10)
|
33
|
+
@serial_port_dev = serial_port_dev
|
34
|
+
@debug = debug
|
35
|
+
@flush_delay = flush_delay
|
36
|
+
@serial_port = SerialPort.new(@serial_port_dev, 9600, 8, 1, SerialPort::NONE)
|
37
|
+
@serial_port.read_timeout = 0
|
38
|
+
end
|
39
|
+
|
40
|
+
# Closes the serial port
|
41
|
+
def close
|
42
|
+
@serial_port.close
|
43
|
+
end
|
44
|
+
|
45
|
+
# Waits for a tag to be presented and returns a zero-padded string with the tag id
|
46
|
+
def get_tag()
|
47
|
+
@received_bytes = []
|
48
|
+
@time_of_last_byte = Time.now
|
49
|
+
@receive_started = false
|
50
|
+
|
51
|
+
# Flush input buffer if partial data was received
|
52
|
+
@timeout_active = true
|
53
|
+
Thread.new do
|
54
|
+
while @timeout_active
|
55
|
+
sleep 1
|
56
|
+
if @receive_started and (Time.now - @time_of_last_byte) > @flush_delay
|
57
|
+
STDERR.puts "Received_bytes not empty after #{@flush_delay}s" if @debug
|
58
|
+
@time_of_last_byte = Time.now
|
59
|
+
@received_bytes = []
|
60
|
+
@receive_started = false
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
while true
|
66
|
+
byte = nil
|
67
|
+
begin
|
68
|
+
byte = @serial_port.readbyte
|
69
|
+
rescue EOFError => e
|
70
|
+
# This shouldn't happen if @serial_port.read_timeout == 0
|
71
|
+
STDERR.puts "Timed out reading serial data" if @debug
|
72
|
+
@time_of_last_byte = Time.now
|
73
|
+
@received_bytes = []
|
74
|
+
next
|
75
|
+
end
|
76
|
+
|
77
|
+
# check if this is the first byte received and it is valid. if not, reset
|
78
|
+
if !@receive_started and byte != START_CODE
|
79
|
+
STDERR.puts "Got initial byte but it is not #{START_CODE} (#{byte})" if @debug
|
80
|
+
reset_serial_buffer()
|
81
|
+
end
|
82
|
+
|
83
|
+
if !@receive_started and byte == START_CODE
|
84
|
+
@receive_started = true
|
85
|
+
@time_of_last_byte = Time.now
|
86
|
+
next
|
87
|
+
end
|
88
|
+
|
89
|
+
if byte > 127
|
90
|
+
STDERR.puts "Got invalid byte #{byte}, resetting" if @debug
|
91
|
+
reset_serial_buffer()
|
92
|
+
next
|
93
|
+
end
|
94
|
+
|
95
|
+
if byte == END_CODE
|
96
|
+
if @received_bytes.length == VALID_LENGTH
|
97
|
+
if checksum_is_valid?(@received_bytes)
|
98
|
+
@timeout_active = false
|
99
|
+
return '%010d' % @received_bytes[2..9].join.to_i(16)
|
100
|
+
else
|
101
|
+
STDERR.puts "Failed to verify checksum for received data" if @debug
|
102
|
+
end
|
103
|
+
else
|
104
|
+
STDERR.puts "Invalid number of bytes received (#{@received_bytes.length})" if @debug
|
105
|
+
end
|
106
|
+
reset_serial_buffer()
|
107
|
+
next
|
108
|
+
end
|
109
|
+
|
110
|
+
@received_bytes << byte.chr
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
# Resets the serial buffer, called after a tag is presented
|
115
|
+
def reset_serial_buffer()
|
116
|
+
@receive_started = false
|
117
|
+
@received_bytes = []
|
118
|
+
@serial_port.close
|
119
|
+
@serial_port = SerialPort.new(@serial_port_dev, 9600, 8, 1, SerialPort::NONE)
|
120
|
+
@time_of_last_byte = Time.now
|
121
|
+
end
|
122
|
+
|
123
|
+
# Checks if the tag checksum is valid
|
124
|
+
def checksum_is_valid?(received_bytes)
|
125
|
+
# Format is 10 data bytes then two checksum bytes
|
126
|
+
# Group the received bytes into pairs, convert from ascii to hex, then XOR them
|
127
|
+
pairs = []
|
128
|
+
received_bytes[0..9].each_with_index do |char, index|
|
129
|
+
next if index % 2 == 1
|
130
|
+
pairs << char + received_bytes[index + 1]
|
131
|
+
end
|
132
|
+
checksum = pairs.map { |pair| pair.to_i(16) }.inject(:^)
|
133
|
+
|
134
|
+
# Then compare to [10..12] of received_checksum
|
135
|
+
received_checksum = (received_bytes[10] + received_bytes[11]).to_i(16)
|
136
|
+
return checksum == received_checksum
|
137
|
+
end
|
138
|
+
end
|
metadata
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: rdm6300
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Luke Stutters
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2021-05-28 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: serialport
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.3'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.3'
|
27
|
+
description: rdm6300 is a Ruby library provides a simple interface for reading 125kHz
|
28
|
+
RFID tags over an RS-232 serial port using the RDM6300 module
|
29
|
+
email: lukestuts@gmail.com
|
30
|
+
executables: []
|
31
|
+
extensions: []
|
32
|
+
extra_rdoc_files: []
|
33
|
+
files:
|
34
|
+
- lib/rdm6300.rb
|
35
|
+
homepage: https://github.com/lukestuts/ruby-rdm6300
|
36
|
+
licenses:
|
37
|
+
- GPL-3.0
|
38
|
+
metadata: {}
|
39
|
+
post_install_message:
|
40
|
+
rdoc_options: []
|
41
|
+
require_paths:
|
42
|
+
- lib
|
43
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
49
|
+
requirements:
|
50
|
+
- - ">="
|
51
|
+
- !ruby/object:Gem::Version
|
52
|
+
version: '0'
|
53
|
+
requirements: []
|
54
|
+
rubygems_version: 3.0.3
|
55
|
+
signing_key:
|
56
|
+
specification_version: 4
|
57
|
+
summary: Read 125kHz RFID tags using the RDM6300 module
|
58
|
+
test_files: []
|