Program Listing for File scanner.hpp
↰ Return to documentation for file (libspookyaction/include/pn532/scanner.hpp
)
//
// Created by spak on 1/18/23.
//
#ifndef PN532_SCANNER_HPP
#define PN532_SCANNER_HPP
#include <pn532/controller.hpp>
namespace pn532 {
class scanner;
enum struct post_interaction {
reject,
release,
retain,
abort
};
struct scanned_target {
std::uint8_t index = std::numeric_limits<std::uint8_t>::max();
target_type type = target_type::generic_passive_106kbps;
std::vector<std::uint8_t> nfcid{};
scanned_target() = default;
template <target_type Type>
scanned_target(std::uint8_t index_, poll_target<Type> const &entry);
scanned_target(std::uint8_t index_, any_poll_target const &entry);
[[nodiscard]] bool operator==(scanned_target const &other) const;
[[nodiscard]] bool operator!=(scanned_target const &other) const;
[[nodiscard]] bool operator<(scanned_target const &other) const;
[[nodiscard]] bool operator>(scanned_target const &other) const;
[[nodiscard]] bool operator<=(scanned_target const &other) const;
[[nodiscard]] bool operator>=(scanned_target const &other) const;
};
struct scanner_responder {
virtual void on_activation(scanner &scanner, scanned_target const &target) {}
virtual void on_release(scanner &scanner, scanned_target const &target) {}
virtual void on_leaving_rf(scanner &scanner, scanned_target const &target) {}
virtual void on_failed_scan(scanner &scanner, channel_error err) {}
[[nodiscard]] virtual std::vector<target_type> get_scan_target_types(scanner &scanner) const {
return controller::poll_all_targets;
}
[[nodiscard]] virtual bool should_interact(scanner &scanner, scanned_target const &target) const {
return true;
}
[[nodiscard]] virtual post_interaction interact(scanner &scanner, scanned_target const &target) {
return post_interaction::reject;
}
virtual ~scanner_responder() = default;
};
class scanner {
std::shared_ptr<controller> _ctrl = nullptr;
ms _timeout = 5s;
bool _stop = false;
std::vector<scanned_target> _rejection_list{};
std::vector<scanned_target> _in_rf{};
void update_rejection_list(scanner_responder &responder);
void update_in_rf_list(std::vector<any_poll_target> const &targets);
[[nodiscard]] bool is_in_rejection_list(scanned_target const &target) const;
public:
scanner() = default;
explicit scanner(std::shared_ptr<controller> ctrl, ms max_scan_interval = 5s);
scanner(scanner const &) = delete;
scanner &operator=(scanner const &) = delete;
scanner(scanner &&) noexcept = default;
scanner &operator=(scanner &&) noexcept = default;
[[nodiscard]] inline std::vector<scanned_target> const &in_rf() const;
[[nodiscard]] inline ms max_scan_interval() const;
inline void set_max_scan_interval(ms timeout);
void loop(scanner_responder &responder, bool init_and_test = true);
[[nodiscard]] controller &ctrl();
[[nodiscard]] controller const &ctrl() const;
void stop();
};
}// namespace pn532
namespace pn532 {
ms scanner::max_scan_interval() const {
return _timeout;
}
void scanner::set_max_scan_interval(ms timeout) {
_timeout = timeout;
}
std::vector<scanned_target> const &scanner::in_rf() const {
return _in_rf;
}
template <target_type Type>
scanned_target::scanned_target(std::uint8_t index_, poll_target<Type> const &entry) : index{index_}, type{Type} {
static constexpr auto BM = baudrate_modulation_of(Type);
if constexpr (std::is_base_of_v<poll_target_dep_passive<BM>, poll_target<Type>>) {
// Obtain NFCID3t from the atr_res_info, and the index from the target bit
index = entry.logical_index;
nfcid.resize(entry.atr_info.nfcid.size());
std::copy(std::begin(entry.atr_info.nfcid), std::end(entry.atr_info.nfcid), std::begin(nfcid));
} else if constexpr (std::is_base_of_v<target<BM>, poll_target<Type>>) {
// Obtain the logical index from the target bit, and then differentiate
index = entry.logical_index;
if constexpr (BM == baudrate_modulation::kbps106_iso_iec_14443_typea) {
nfcid = entry.nfcid;
} else if constexpr (BM == baudrate_modulation::kbps212_felica or BM == baudrate_modulation::kbps424_felica) {
nfcid.resize(entry.nfcid_2t.size());
std::copy(std::begin(entry.nfcid_2t), std::end(entry.nfcid_2t), std::begin(nfcid));
} else if constexpr (BM == baudrate_modulation::kbps106_iso_iec_14443_3_typeb) {
// Slice off the PUPI (Pseudo-Unique PICC Identifier) out of the atqb response
if (entry.atqb_response.size() >= 5) {
nfcid.resize(4);
std::copy_n(std::begin(entry.atqb_response) + 1, 4, std::begin(nfcid));
} else {
// Just use the whole atqb response
nfcid.resize(entry.atqb_response.size());
std::copy(std::begin(entry.atqb_response), std::end(entry.atqb_response), std::begin(nfcid));
}
} else if constexpr (BM == baudrate_modulation::kbps106_innovision_jewel_tag) {
// Use jewel id
nfcid.resize(entry.jewel_id.size());
std::copy(std::begin(entry.jewel_id), std::end(entry.jewel_id), std::begin(nfcid));
}
} else {
static_assert(std::is_base_of_v<poll_target_with_atr, poll_target<Type>>);
// Obtain NFCID3t from the atr_res_info, we cannot do anything about the index
nfcid.resize(entry.atr_info.nfcid.size());
std::copy(std::begin(entry.atr_info.nfcid), std::end(entry.atr_info.nfcid), std::begin(nfcid));
}
}
}// namespace pn532
#endif//PN532_SCANNER_HPP