Leosac  0.7.0
OpenSourceAccessControl
WiegandPinNBitsOnly.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2014-2016 Leosac
3 
4  This file is part of Leosac.
5 
6  Leosac is free software: you can redistribute it and/or modify
7  it under the terms of the GNU Affero General Public License as published by
8  the Free Software Foundation, either version 3 of the License, or
9  (at your option) any later version.
10 
11  Leosac is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  GNU Affero General Public License for more details.
15 
16  You should have received a copy of the GNU Affero General Public License
17  along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19 
20 #include "WiegandPinNBitsOnly.hpp"
22 #include <tools/log.hpp>
23 
24 using namespace Leosac::Module::Wiegand;
25 using namespace Leosac::Module::Wiegand::Strategy;
26 
27 template <unsigned int NbBits>
29  WiegandReaderImpl *reader, std::chrono::milliseconds pin_timeout,
30  char pin_end_key)
31  : PinReading(reader)
32  , pin_timeout_(pin_timeout)
33  , pin_end_key_(pin_end_key)
34  , ready_(false)
35 {
36  last_update_ = std::chrono::system_clock::now();
37 }
38 
39 template <unsigned int NbBits>
41 {
42  // If we receive 4 bits per key, the
43  // data looks like this:
44  // buffer[0] = 0101 ...
45  // ^^^^ key pressed.
46  // For 8 bits mode, it looks like this:
47  // buffer[0] = 1010 0101
48  // ~bits^^^^ ^^^^ key value
49  // If this example, the key pressed is '5'.
50  DEBUG("Buffer value = " << (unsigned int)input);
51  unsigned int n = 0;
52  for (int i = 0; i < 4; ++i)
53  {
54  bool v = ((input >> (7 - i)) & 0x01);
55  if (NbBits == 8)
56  v = !v;
57  n |= v << (3 - i);
58  }
59  // this deduced from manual testing. Value for '#' and '*'.
60  // 10 -> *
61  // 11 -> #
62  if (n == 10)
63  return '*';
64  else if (n == 11)
65  return '#';
66  else
67  return std::to_string(n).at(0);
68 }
69 
70 template <unsigned int NbBits>
72 {
73  static_assert(NbBits == 4 || NbBits == 8,
74  "Must either be 4 or 8 bits per key pressed");
75  using namespace std::chrono;
76  auto elapsed_ms =
77  duration_cast<milliseconds>(system_clock::now() - last_update_);
78 
79  if (!reader_->counter())
80  {
81  if (elapsed_ms > pin_timeout_)
82  end_of_input();
83  return;
84  }
85 
86  if (reader_->counter() != NbBits)
87  {
88  WARN("Expected number of bits invalid. ("
89  << reader_->counter() << " but we expected " << NbBits << ")");
90  reset();
91  return;
92  }
93 
94  last_update_ = system_clock::now();
95  char c = extract_from_raw(reader_->buffer()[0]);
96  if (c == pin_end_key_)
97  {
98  end_of_input();
99  }
100  else
101  inputs_ += c;
102  reader_->read_reset();
103 }
104 
105 template <unsigned int NbBits>
107 {
108  if (inputs_.length())
109  ready_ = true;
110  else
111  ready_ = false;
112 }
113 
114 template <unsigned int NbBits>
116 {
117  return ready_;
118 }
119 
120 template <unsigned int NbBits>
121 void WiegandPinNBitsOnly<NbBits>::signal(zmqpp::socket &sock)
122 {
123  assert(ready_);
124  assert(inputs_.length());
125  DEBUG("Sending PIN Code: " << inputs_);
126  zmqpp::message msg;
128  << inputs_;
129  sock.send(msg);
130  reset();
131 }
132 
133 template <unsigned int NbBits>
134 const std::string &WiegandPinNBitsOnly<NbBits>::get_pin() const
135 {
136  return inputs_;
137 }
138 
139 template <unsigned int NbBits>
141 {
142  reader_->read_reset();
143  ready_ = false;
144  inputs_ = "";
145  last_update_ = std::chrono::system_clock::now();
146 }
147 
148 namespace Leosac
149 {
150 namespace Module
151 {
152 namespace Wiegand
153 {
154 namespace Strategy
155 {
156 template class WiegandPinNBitsOnly<4>;
157 template class WiegandPinNBitsOnly<8>;
158 }
159 }
160 }
161 }
virtual void timeout() override
This is called when the module detect a timeout.
virtual void signal(zmqpp::socket &sock) override
Tells the strategy implementation to send a message to the application containing the received creden...
An implementation class that represents a Wiegand Reader.
Interface for a strategy that read a PIN code.
Definition: PinReading.hpp:37
This is the header file for a generated source file, GitSHA1.cpp.
virtual bool completed() const override
Did the strategy gather needed data? If this function returns true, that means that the strategy impl...
int counter() const
Returns the number of bits read.
Definition: log.hpp:35
WiegandPinNBitsOnly(WiegandReaderImpl *reader, std::chrono::milliseconds pin_timeout, char pin_end_key)
Create a strategy that read N bits-per-key PIN code.
virtual const std::string & get_pin() const override
Retrieve the pin code that was read from the reader.
bool ready_
Are we ready to submit the PIN code ?
char extract_from_raw(uint8_t input) const
Extract the character that was pressed from raw data.
Message formatting when using a simple PIN code.
virtual void reset() override
Reset the strategy, meaning that the next time timeout() is called the behavior should be the same th...
void read_reset()
Reset the "read state" of the reader, effectively cleaning the wiegand-bit-buffer and resetting the c...
Definition: log.hpp:38
Provide support for Wiegand devices.
Definition: Autodetect.hpp:29
const unsigned char * buffer() const
Return a pointer to internal buffer memory.
const std::string & name() const
Returns the name of this reader.