better from_hash example
[Biblio-RFID.git] / lib / RFID / Biblio / RFID501.pm
1 package RFID::Biblio::RFID501;
2
3 use warnings;
4 use strict;
5
6 use Data::Dump qw(dump);
7
8 =head1 NAME
9
10 RFID::Biblio::RFID501 - RFID Standard for Libraries
11
12 =head1 DESCRIPTION
13
14 This module tries to decode tag format as described in document
15
16   RFID 501: RFID Standards for Libraries
17
18 L<http://solutions.3m.com/wps/portal/3M/en_US/3MLibrarySystems/Home/Resources/CaseStudiesAndWhitePapers/RFID501/>
19
20 Goal is to be compatibile with existing 3M Alphanumeric tag format
21 which, as far as I know, isn't specificed anywhere. My documentation about
22 this format is available at
23
24 L<http://saturn.ffzg.hr/rot13/index.cgi?hitchhikers_guide_to_rfid>
25
26 =head1 Data model
27
28 =head2 3M Alphanumeric tag
29
30  0   04 is 00 tt   i [4 bit] = number of item in set    [1 .. i .. s]
31                    s [4 bit] = total items in set
32                    tt [8 bit] = item type
33
34  1   dd dd dd dd   dd [16 bytes] = barcode data
35  2   dd dd dd dd
36  3   dd dd dd dd
37  4   dd dd dd dd
38
39  5   bb bl ll ll   b [12 bit] = branch [unsigned]
40                    l [20 bit] = library [unsigned]
41
42  6   cc cc cc cc   c [32 bit] = custom signed integer
43
44 =head2 3M Manufacturing Blank
45
46  0   55 55 55 55
47  1   55 55 55 55
48  2   55 55 55 55
49  3   55 55 55 55
50  4   55 55 55 55
51  5   55 55 55 55
52  6   00 00 00 00 
53
54 =head2 Generic blank
55
56  0   00 00 00 00
57  1   00 00 00 00
58  2   00 00 00 00
59
60 =head1 METHODS
61
62 =head2 to_hash
63
64   my $hash = RFID::Biblio::Decode::RFID501->to_hash( $bytes );
65
66   my $hash = RFID::Biblio::Decode::RFID501->to_hash( [ 'blk1', 'blk2', ... , 'blk7' ] );
67
68 =head2 from_hash
69
70   my $blocks = RFID::Biblio::Decode::RFID->from_hash({ content => "1301234567" });
71
72 =head2 blank
73
74   my $blocks = RFID::Biblio::Decode::RFID->blank;
75
76 =cut
77
78 my $item_type = {
79         1 => 'Book',
80         6 => 'CD/CD ROM',
81         2 => 'Magazine',
82         13 => 'Book with Audio Tape',
83         9 => 'Book with CD/CD ROM',
84         0 => 'Other',
85
86         5 => 'Video',
87         4 => 'Audio Tape',
88         3 => 'Bound Journal',
89         8 => 'Book with Diskette',
90         7 => 'Diskette',
91 };
92
93 sub to_hash {
94         my ( $self, $data ) = @_;
95
96         return unless $data;
97
98         $data = join('', @$data) if ref $data eq 'ARRAY';
99
100         warn "## to_hash ",dump($data);
101
102         my ( $u1, $set_item, $u2, $type, $content, $br_lib, $custom, $zero ) = unpack('C4Z16Nl>l',$data);
103         my $hash = {
104                 u1 => $u1,      # FIXME 0x04
105                 set => ( $set_item & 0xf0 ) >> 4,
106                 total => ( $set_item & 0x0f ),
107
108                 u2 => $u2,      # FIXME 0x00
109
110                 type => $type,
111                 type_label => $item_type->{$type},
112
113                 content => $content,
114
115                 branch => $br_lib >> 20,
116                 library => $br_lib & 0x000fffff,
117
118                 custom => $custom,
119         };
120
121         warn "expected first byte to be 0x04, not $u1\n"   if $u1 != 4;
122         warn "expected third byte to be 0x00, not $u2\n"   if $u2 != 0;
123         warn "expected last block to be zero, not $zero\n" if $zero != 0;
124
125         return $hash;
126 }
127
128 sub from_hash {
129         my ( $self, $hash ) = @_;
130
131         warn "## from_hash ",dump($hash);
132
133         return pack('C4Z16Nl>l',
134                 0x04,
135                 ( $hash->{set} << 4 ) | ( $hash->{total} & 0x0f ),
136                 0x00,
137                 $hash->{type},
138
139                 $hash->{content},
140
141                 ( $hash->{branch} << 20 ) | ( $hash->{library} & 0x000fffff ),
142
143                 $hash->{custom},
144                 0x00,
145         );
146 }
147
148 sub blank {
149
150         return ( "\x55" x ( 5 * 4 ) ) . ( "\x00" x 4 );
151
152 }
153
154 1;