yannstatic/static/2019/07/30/Lecteur-USB-RFID(NFC)-SCL3711.html

2755 lines
254 KiB
HTML
Raw Normal View History

2024-10-31 20:18:37 +01:00
<!DOCTYPE html><html lang="fr">
<head><meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no"><title>Lecteur USB RFID/NFC SCL3711 + RFID/Raspberry PI + RFID/Arduino - YannStatic</title>
<meta name="description" content="RFID NFC">
<link rel="canonical" href="https://static.rnmkcy.eu/2019/07/30/Lecteur-USB-RFID(NFC)-SCL3711.html"><link rel="alternate" type="application/rss+xml" title="YannStatic" href="/feed.xml">
<!-- - include head/favicon.html - -->
<link rel="shortcut icon" type="image/png" href="/assets/favicon/favicon.png"><link rel="stylesheet" href="/assets/css/main.css"><link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.0.13/css/all.css" ><!-- start custom head snippets --><link rel="stylesheet" href="/assets/css/expand.css">
<!-- end custom head snippets --><script>(function() {
window.isArray = function(val) {
return Object.prototype.toString.call(val) === '[object Array]';
};
window.isString = function(val) {
return typeof val === 'string';
};
window.hasEvent = function(event) {
return 'on'.concat(event) in window.document;
};
window.isOverallScroller = function(node) {
return node === document.documentElement || node === document.body || node === window;
};
window.isFormElement = function(node) {
var tagName = node.tagName;
return tagName === 'INPUT' || tagName === 'SELECT' || tagName === 'TEXTAREA';
};
window.pageLoad = (function () {
var loaded = false, cbs = [];
window.addEventListener('load', function () {
var i;
loaded = true;
if (cbs.length > 0) {
for (i = 0; i < cbs.length; i++) {
cbs[i]();
}
}
});
return {
then: function(cb) {
cb && (loaded ? cb() : (cbs.push(cb)));
}
};
})();
})();
(function() {
window.throttle = function(func, wait) {
var args, result, thisArg, timeoutId, lastCalled = 0;
function trailingCall() {
lastCalled = new Date;
timeoutId = null;
result = func.apply(thisArg, args);
}
return function() {
var now = new Date,
remaining = wait - (now - lastCalled);
args = arguments;
thisArg = this;
if (remaining <= 0) {
clearTimeout(timeoutId);
timeoutId = null;
lastCalled = now;
result = func.apply(thisArg, args);
} else if (!timeoutId) {
timeoutId = setTimeout(trailingCall, remaining);
}
return result;
};
};
})();
(function() {
var Set = (function() {
var add = function(item) {
var i, data = this._data;
for (i = 0; i < data.length; i++) {
if (data[i] === item) {
return;
}
}
this.size ++;
data.push(item);
return data;
};
var Set = function(data) {
this.size = 0;
this._data = [];
var i;
if (data.length > 0) {
for (i = 0; i < data.length; i++) {
add.call(this, data[i]);
}
}
};
Set.prototype.add = add;
Set.prototype.get = function(index) { return this._data[index]; };
Set.prototype.has = function(item) {
var i, data = this._data;
for (i = 0; i < data.length; i++) {
if (this.get(i) === item) {
return true;
}
}
return false;
};
Set.prototype.is = function(map) {
if (map._data.length !== this._data.length) { return false; }
var i, j, flag, tData = this._data, mData = map._data;
for (i = 0; i < tData.length; i++) {
for (flag = false, j = 0; j < mData.length; j++) {
if (tData[i] === mData[j]) {
flag = true;
break;
}
}
if (!flag) { return false; }
}
return true;
};
Set.prototype.values = function() {
return this._data;
};
return Set;
})();
window.Lazyload = (function(doc) {
var queue = {js: [], css: []}, sources = {js: {}, css: {}}, context = this;
var createNode = function(name, attrs) {
var node = doc.createElement(name), attr;
for (attr in attrs) {
if (attrs.hasOwnProperty(attr)) {
node.setAttribute(attr, attrs[attr]);
}
}
return node;
};
var end = function(type, url) {
var s, q, qi, cbs, i, j, cur, val, flag;
if (type === 'js' || type ==='css') {
s = sources[type], q = queue[type];
s[url] = true;
for (i = 0; i < q.length; i++) {
cur = q[i];
if (cur.urls.has(url)) {
qi = cur, val = qi.urls.values();
qi && (cbs = qi.callbacks);
for (flag = true, j = 0; j < val.length; j++) {
cur = val[j];
if (!s[cur]) {
flag = false;
}
}
if (flag && cbs && cbs.length > 0) {
for (j = 0; j < cbs.length; j++) {
cbs[j].call(context);
}
qi.load = true;
}
}
}
}
};
var load = function(type, urls, callback) {
var s, q, qi, node, i, cur,
_urls = typeof urls === 'string' ? new Set([urls]) : new Set(urls), val, url;
if (type === 'js' || type ==='css') {
s = sources[type], q = queue[type];
for (i = 0; i < q.length; i++) {
cur = q[i];
if (_urls.is(cur.urls)) {
qi = cur;
break;
}
}
val = _urls.values();
if (qi) {
callback && (qi.load || qi.callbacks.push(callback));
callback && (qi.load && callback());
} else {
q.push({
urls: _urls,
callbacks: callback ? [callback] : [],
load: false
});
for (i = 0; i < val.length; i++) {
node = null, url = val[i];
if (s[url] === undefined) {
(type === 'js' ) && (node = createNode('script', { src: url }));
(type === 'css') && (node = createNode('link', { rel: 'stylesheet', href: url }));
if (node) {
node.onload = (function(type, url) {
return function() {
end(type, url);
};
})(type, url);
(doc.head || doc.body).appendChild(node);
s[url] = false;
}
}
}
}
}
};
return {
js: function(url, callback) {
load('js', url, callback);
},
css: function(url, callback) {
load('css', url, callback);
}
};
})(this.document);
})();
</script><script>
(function() {
var TEXT_VARIABLES = {
version: '2.2.6',
sources: {
font_awesome: 'https://use.fontawesome.com/releases/v5.0.13/css/all.css',
jquery: '/assets/js/jquery.min.js',
leancloud_js_sdk: '//cdn.jsdelivr.net/npm/leancloud-storage@3.13.2/dist/av-min.js',
chart: 'https://cdn.bootcss.com/Chart.js/2.7.2/Chart.bundle.min.js',
gitalk: {
js: 'https://cdn.bootcss.com/gitalk/1.2.2/gitalk.min.js',
css: 'https://cdn.bootcss.com/gitalk/1.2.2/gitalk.min.css'
},
valine: 'https://unpkg.com/valine/dist/Valine.min.js'
},
site: {
toc: {
selectors: 'h1,h2,h3'
}
},
paths: {
search_js: '/assets/search.js'
}
};
window.TEXT_VARIABLES = TEXT_VARIABLES;
})();
</script>
</head>
<body>
<div class="root" data-is-touch="false">
<div class="layout--page js-page-root"><!----><div class="page__main js-page-main page__viewport hide-footer has-aside has-aside cell cell--auto">
<div class="page__main-inner"><div class="page__header d-print-none"><header class="header"><div class="main">
<div class="header__title">
<div class="header__brand"><svg id="svg" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="400" height="478.9473684210526" viewBox="0, 0, 400,478.9473684210526"><g id="svgg"><path id="path0" d="M308.400 56.805 C 306.970 56.966,303.280 57.385,300.200 57.738 C 290.906 58.803,278.299 59.676,269.200 59.887 L 260.600 60.085 259.400 61.171 C 258.010 62.428,256.198 63.600,255.645 63.600 C 255.070 63.600,252.887 65.897,252.598 66.806 C 252.460 67.243,252.206 67.600,252.034 67.600 C 251.397 67.600,247.206 71.509,247.202 72.107 C 247.201 72.275,246.390 73.190,245.400 74.138 C 243.961 75.517,243.598 76.137,243.592 77.231 C 243.579 79.293,241.785 83.966,240.470 85.364 C 239.176 86.740,238.522 88.365,237.991 91.521 C 237.631 93.665,236.114 97.200,235.554 97.200 C 234.938 97.200,232.737 102.354,232.450 104.472 C 232.158 106.625,230.879 109.226,229.535 110.400 C 228.933 110.926,228.171 113.162,226.434 119.500 C 226.178 120.435,225.795 121.200,225.584 121.200 C 225.373 121.200,225.200 121.476,225.200 121.813 C 225.200 122.149,224.885 122.541,224.500 122.683 C 223.606 123.013,223.214 123.593,223.204 124.600 C 223.183 126.555,220.763 132.911,219.410 134.562 C 218.443 135.742,217.876 136.956,217.599 138.440 C 217.041 141.424,215.177 146.434,214.532 146.681 C 214.240 146.794,214.000 147.055,214.000 147.261 C 214.000 147.467,213.550 148.086,213.000 148.636 C 212.450 149.186,212.000 149.893,212.000 150.208 C 212.000 151.386,208.441 154.450,207.597 153.998 C 206.319 153.315,204.913 150.379,204.633 147.811 C 204.365 145.357,202.848 142.147,201.759 141.729 C 200.967 141.425,199.200 137.451,199.200 135.974 C 199.200 134.629,198.435 133.224,196.660 131.311 C 195.363 129.913,194.572 128.123,193.870 125.000 C 193.623 123.900,193.236 122.793,193.010 122.540 C 190.863 120.133,190.147 118.880,188.978 115.481 C 188.100 112.928,187.151 111.003,186.254 109.955 C 185.358 108.908,184.518 107.204,183.847 105.073 C 183.280 103.273,182.497 101.329,182.108 100.753 C 181.719 100.177,180.904 98.997,180.298 98.131 C 179.693 97.265,178.939 95.576,178.624 94.378 C 178.041 92.159,177.125 90.326,175.023 87.168 C 174.375 86.196,173.619 84.539,173.342 83.486 C 172.800 81.429,171.529 79.567,170.131 78.785 C 169.654 78.517,168.697 77.511,168.006 76.549 C 167.316 75.587,166.594 74.800,166.402 74.800 C 166.210 74.800,164.869 73.633,163.421 72.206 C 160.103 68.936,161.107 69.109,146.550 69.301 C 133.437 69.474,128.581 70.162,126.618 72.124 C 126.248 72.495,125.462 72.904,124.872 73.033 C 124.282 73.163,123.088 73.536,122.219 73.863 C 121.349 74.191,119.028 74.638,117.061 74.858 C 113.514 75.254,109.970 76.350,108.782 77.419 C 107.652 78.436,100.146 80.400,97.388 80.400 C 95.775 80.400,93.167 81.360,91.200 82.679 C 90.430 83.195,89.113 83.804,88.274 84.031 C 85.875 84.681,78.799 90.910,74.400 96.243 L 73.400 97.456 73.455 106.028 C 73.526 117.055,74.527 121.238,77.820 124.263 C 78.919 125.273,80.400 127.902,80.400 128.842 C 80.400 129.202,81.075 130.256,81.900 131.186 C 83.563 133.059,85.497 136.346,86.039 138.216 C 86.233 138.886,87.203 140.207,88.196 141.153 C 89.188 142.098,90.000 143.104,90.000 143.388 C 90.000 144.337,92.129 148.594,92.869 149.123 C 93.271 149.410,93.600 149.831,93.600 150.059 C 93.600 150.286,93.932 150.771,94.337 151.136 C 94.743 151.501,95.598 153.004,96.237 154.475 C 96.877 155.947,97.760 157.351,98.200 157.596 C 98.640 157.841,99.900 159.943,101.000 162.267 C 102.207 164.817,103.327 166.644,103.825 166.876 C 104.278 167.087,105.065 168.101,105.573 169.130 C 107.658 173.348,108.097 174.093,110.006 176.647 C 111.103 178.114,112.000 179.725,112.000 180.227 C 112.000 181.048,113.425 183.163,114.678 184.200 C 115.295 184.711,117.396 188.733,117.720 190.022 C 117.855 190.562,118.603 191.633,119.381 192.402 C 120.160 193.171,121.496 195.258,122.351 197.039 C 123.206 198.820,124.167 200.378,124.487 200.501 C 124.807 200.624,125.953 202.496,127.034 204.662 C 128.114 206.828,129.676 209.299,130.505 210.153 C 131.333 211.007,132.124 212.177,132.262 212.753 C 132.618 214.239,134.291 217.048,136.288 219.5
" href="/">YannStatic</a></div><!--<button class="button button--secondary button--circle search-button js-search-toggle"><i class="fas fa-search"></i></button>--><!-- <li><button class="button button--secondary button--circle search-button js-search-toggle"><i class="fas fa-search"></i></button></li> -->
<!-- Champ de recherche -->
<div id="searchbox" class="search search--dark" style="visibility: visible">
<div class="main">
<div class="search__header"></div>
<div class="search-bar">
<div class="search-box js-search-box">
<div class="search-box__icon-search"><i class="fas fa-search"></i></div>
<input id="search-input" type="text" />
<!-- <div class="search-box__icon-clear js-icon-clear">
<a><i class="fas fa-times"></i></a>
</div> -->
</div>
</div>
</div>
</div>
<!-- Script pointing to search-script.js -->
<script>/*!
* Simple-Jekyll-Search
* Copyright 2015-2020, Christian Fei
* Licensed under the MIT License.
*/
(function(){
'use strict'
var _$Templater_7 = {
compile: compile,
setOptions: setOptions
}
const options = {}
options.pattern = /\{(.*?)\}/g
options.template = ''
options.middleware = function () {}
function setOptions (_options) {
options.pattern = _options.pattern || options.pattern
options.template = _options.template || options.template
if (typeof _options.middleware === 'function') {
options.middleware = _options.middleware
}
}
function compile (data) {
return options.template.replace(options.pattern, function (match, prop) {
const value = options.middleware(prop, data[prop], options.template)
if (typeof value !== 'undefined') {
return value
}
return data[prop] || match
})
}
'use strict';
function fuzzysearch (needle, haystack) {
var tlen = haystack.length;
var qlen = needle.length;
if (qlen > tlen) {
return false;
}
if (qlen === tlen) {
return needle === haystack;
}
outer: for (var i = 0, j = 0; i < qlen; i++) {
var nch = needle.charCodeAt(i);
while (j < tlen) {
if (haystack.charCodeAt(j++) === nch) {
continue outer;
}
}
return false;
}
return true;
}
var _$fuzzysearch_1 = fuzzysearch;
'use strict'
/* removed: const _$fuzzysearch_1 = require('fuzzysearch') */;
var _$FuzzySearchStrategy_5 = new FuzzySearchStrategy()
function FuzzySearchStrategy () {
this.matches = function (string, crit) {
return _$fuzzysearch_1(crit.toLowerCase(), string.toLowerCase())
}
}
'use strict'
var _$LiteralSearchStrategy_6 = new LiteralSearchStrategy()
function LiteralSearchStrategy () {
this.matches = function (str, crit) {
if (!str) return false
str = str.trim().toLowerCase()
crit = crit.trim().toLowerCase()
return crit.split(' ').filter(function (word) {
return str.indexOf(word) >= 0
}).length === crit.split(' ').length
}
}
'use strict'
var _$Repository_4 = {
put: put,
clear: clear,
search: search,
setOptions: __setOptions_4
}
/* removed: const _$FuzzySearchStrategy_5 = require('./SearchStrategies/FuzzySearchStrategy') */;
/* removed: const _$LiteralSearchStrategy_6 = require('./SearchStrategies/LiteralSearchStrategy') */;
function NoSort () {
return 0
}
const data = []
let opt = {}
opt.fuzzy = false
opt.limit = 10
opt.searchStrategy = opt.fuzzy ? _$FuzzySearchStrategy_5 : _$LiteralSearchStrategy_6
opt.sort = NoSort
opt.exclude = []
function put (data) {
if (isObject(data)) {
return addObject(data)
}
if (isArray(data)) {
return addArray(data)
}
return undefined
}
function clear () {
data.length = 0
return data
}
function isObject (obj) {
return Boolean(obj) && Object.prototype.toString.call(obj) === '[object Object]'
}
function isArray (obj) {
return Boolean(obj) && Object.prototype.toString.call(obj) === '[object Array]'
}
function addObject (_data) {
data.push(_data)
return data
}
function addArray (_data) {
const added = []
clear()
for (let i = 0, len = _data.length; i < len; i++) {
if (isObject(_data[i])) {
added.push(addObject(_data[i]))
}
}
return added
}
function search (crit) {
if (!crit) {
return []
}
return findMatches(data, crit, opt.searchStrategy, opt).sort(opt.sort)
}
function __setOptions_4 (_opt) {
opt = _opt || {}
opt.fuzzy = _opt.fuzzy || false
opt.limit = _opt.limit || 10
opt.searchStrategy = _opt.fuzzy ? _$FuzzySearchStrategy_5 : _$LiteralSearchStrategy_6
opt.sort = _opt.sort || NoSort
opt.exclude = _opt.exclude || []
}
function findMatches (data, crit, strategy, opt) {
const matches = []
for (let i = 0; i < data.length && matches.length < opt.limit; i++) {
const match = findMatchesInObject(data[i], crit, strategy, opt)
if (match) {
matches.push(match)
}
}
return matches
}
function findMatchesInObject (obj, crit, strategy, opt) {
for (const key in obj) {
if (!isExcluded(obj[key], opt.exclude) && strategy.matches(obj[key], crit)) {
return obj
}
}
}
function isExcluded (term, excludedTerms) {
for (let i = 0, len = excludedTerms.length; i < len; i++) {
const excludedTerm = excludedTerms[i]
if (new RegExp(excludedTerm).test(term)) {
return true
}
}
return false
}
/* globals ActiveXObject:false */
'use strict'
var _$JSONLoader_2 = {
load: load
}
function load (location, callback) {
const xhr = getXHR()
xhr.open('GET', location, true)
xhr.onreadystatechange = createStateChangeListener(xhr, callback)
xhr.send()
}
function createStateChangeListener (xhr, callback) {
return function () {
if (xhr.readyState === 4 && xhr.status === 200) {
try {
callback(null, JSON.parse(xhr.responseText))
} catch (err) {
callback(err, null)
}
}
}
}
function getXHR () {
return window.XMLHttpRequest ? new window.XMLHttpRequest() : new ActiveXObject('Microsoft.XMLHTTP')
}
'use strict'
var _$OptionsValidator_3 = function OptionsValidator (params) {
if (!validateParams(params)) {
throw new Error('-- OptionsValidator: required options missing')
}
if (!(this instanceof OptionsValidator)) {
return new OptionsValidator(params)
}
const requiredOptions = params.required
this.getRequiredOptions = function () {
return requiredOptions
}
this.validate = function (parameters) {
const errors = []
requiredOptions.forEach(function (requiredOptionName) {
if (typeof parameters[requiredOptionName] === 'undefined') {
errors.push(requiredOptionName)
}
})
return errors
}
function validateParams (params) {
if (!params) {
return false
}
return typeof params.required !== 'undefined' && params.required instanceof Array
}
}
'use strict'
var _$utils_9 = {
merge: merge,
isJSON: isJSON
}
function merge (defaultParams, mergeParams) {
const mergedOptions = {}
for (const option in defaultParams) {
mergedOptions[option] = defaultParams[option]
if (typeof mergeParams[option] !== 'undefined') {
mergedOptions[option] = mergeParams[option]
}
}
return mergedOptions
}
function isJSON (json) {
try {
if (json instanceof Object && JSON.parse(JSON.stringify(json))) {
return true
}
return false
} catch (err) {
return false
}
}
var _$src_8 = {};
(function (window) {
'use strict'
let options = {
searchInput: null,
resultsContainer: null,
json: [],
success: Function.prototype,
searchResultTemplate: '<li><a href="{url}" title="{desc}">{title}</a></li>',
templateMiddleware: Function.prototype,
sortMiddleware: function () {
return 0
},
noResultsText: 'No results found',
limit: 10,
fuzzy: false,
debounceTime: null,
exclude: []
}
let debounceTimerHandle
const debounce = function (func, delayMillis) {
if (delayMillis) {
clearTimeout(debounceTimerHandle)
debounceTimerHandle = setTimeout(func, delayMillis)
} else {
func.call()
}
}
const requiredOptions = ['searchInput', 'resultsContainer', 'json']
/* removed: const _$Templater_7 = require('./Templater') */;
/* removed: const _$Repository_4 = require('./Repository') */;
/* removed: const _$JSONLoader_2 = require('./JSONLoader') */;
const optionsValidator = _$OptionsValidator_3({
required: requiredOptions
})
/* removed: const _$utils_9 = require('./utils') */;
window.SimpleJekyllSearch = function (_options) {
const errors = optionsValidator.validate(_options)
if (errors.length > 0) {
throwError('You must specify the following required options: ' + requiredOptions)
}
options = _$utils_9.merge(options, _options)
_$Templater_7.setOptions({
template: options.searchResultTemplate,
middleware: options.templateMiddleware
})
_$Repository_4.setOptions({
fuzzy: options.fuzzy,
limit: options.limit,
sort: options.sortMiddleware,
exclude: options.exclude
})
if (_$utils_9.isJSON(options.json)) {
initWithJSON(options.json)
} else {
initWithURL(options.json)
}
const rv = {
search: search
}
typeof options.success === 'function' && options.success.call(rv)
return rv
}
function initWithJSON (json) {
_$Repository_4.put(json)
registerInput()
}
function initWithURL (url) {
_$JSONLoader_2.load(url, function (err, json) {
if (err) {
throwError('failed to get JSON (' + url + ')')
}
initWithJSON(json)
})
}
function emptyResultsContainer () {
options.resultsContainer.innerHTML = ''
}
function appendToResultsContainer (text) {
options.resultsContainer.innerHTML += text
}
function registerInput () {
options.searchInput.addEventListener('input', function (e) {
if (isWhitelistedKey(e.which)) {
emptyResultsContainer()
debounce(function () { search(e.target.value) }, options.debounceTime)
}
})
}
function search (query) {
if (isValidQuery(query)) {
emptyResultsContainer()
render(_$Repository_4.search(query), query)
}
}
function render (results, query) {
const len = results.length
if (len === 0) {
return appendToResultsContainer(options.noResultsText)
}
for (let i = 0; i < len; i++) {
results[i].query = query
appendToResultsContainer(_$Templater_7.compile(results[i]))
}
}
function isValidQuery (query) {
return query && query.length > 0
}
function isWhitelistedKey (key) {
return [13, 16, 20, 37, 38, 39, 40, 91].indexOf(key) === -1
}
function throwError (message) {
throw new Error('SimpleJekyllSearch --- ' + message)
}
})(window)
}());
</script>
<!-- Configuration -->
<script>
SimpleJekyllSearch({
searchInput: document.getElementById('search-input'),
resultsContainer: document.getElementById('results-container'),
json: '/search.json',
//searchResultTemplate: '<li><a href="https://static.rnmkcy.eu{url}">{date}&nbsp;{title}</a></li>'
searchResultTemplate: '<li><a href="{url}">{date}&nbsp;{title}</a></li>'
})
</script>
<!-- Fin déclaration champ de recherche --></div><nav class="navigation">
<ul><li class="navigation__item"><a href="/archive.html">Etiquettes</a></li><li class="navigation__item"><a href="/htmldoc.html">Documents</a></li><li class="navigation__item"><a href="/liens_ttrss.html">Liens</a></li><li class="navigation__item"><a href="/aide-jekyll-text-theme.html">Aide</a></li></ul>
</nav></div>
</header>
</div><div class="page__content"><div class ="main"><div class="grid grid--reverse">
<div class="col-main cell cell--auto"><!-- start custom main top snippet --><div id="results-container" class="search-result js-search-result"></div><!-- end custom main top snippet -->
<article itemscope itemtype="http://schema.org/Article"><div class="article__header"><header><h1 style="color:Tomato;">Lecteur USB RFID/NFC SCL3711 + RFID/Raspberry PI + RFID/Arduino</h1></header></div><meta itemprop="headline" content="Lecteur USB RFID/NFC SCL3711 + RFID/Raspberry PI + RFID/Arduino"><div class="article__info clearfix"><ul class="left-col menu"><li>
2024-11-08 14:10:33 +01:00
<a class="button button--secondary button--pill button--sm" style="color:#00FFFF" href="/archive.html?tag=outils">outils</a>
2024-10-31 20:18:37 +01:00
</li><li>
2024-11-08 14:10:33 +01:00
<a class="button button--secondary button--pill button--sm" style="color:#00FFFF" href="/archive.html?tag=arduino">arduino</a>
2024-10-31 20:18:37 +01:00
</li><li>
2024-11-08 14:10:33 +01:00
<a class="button button--secondary button--pill button--sm" style="color:#00FFFF" href="/archive.html?tag=raspberry">raspberry</a>
2024-10-31 20:18:37 +01:00
</li></ul><ul class="right-col menu"><li>
<i class="far fa-calendar-alt"></i>&nbsp;<span title="Création" style="color:#FF00FF">30&nbsp;juil.&nbsp;2019</span>
<span title="Modification" style="color:#00FF7F">14&nbsp;janv.&nbsp;2023</span></li></ul></div><meta itemprop="datePublished" content="2023-01-14T00:00:00+01:00">
<meta itemprop="keywords" content="outils,arduino,raspberry"><div class="js-article-content">
<div class="layout--article"><!-- start custom article top snippet -->
<style>
#myBtn {
display: none;
position: fixed;
bottom: 10px;
right: 10px;
z-index: 99;
font-size: 12px;
font-weight: bold;
border: none;
outline: none;
background-color: white;
color: black;
cursor: pointer;
padding: 5px;
border-radius: 4px;
}
#myBtn:hover {
background-color: #555;
}
</style>
<button onclick="topFunction()" id="myBtn" title="Haut de page">&#8679;</button>
<script>
//Get the button
var mybutton = document.getElementById("myBtn");
// When the user scrolls down 20px from the top of the document, show the button
window.onscroll = function() {scrollFunction()};
function scrollFunction() {
if (document.body.scrollTop > 20 || document.documentElement.scrollTop > 20) {
mybutton.style.display = "block";
} else {
mybutton.style.display = "none";
}
}
// When the user clicks on the button, scroll to the top of the document
function topFunction() {
document.body.scrollTop = 0;
document.documentElement.scrollTop = 0;
}
</script>
<!-- end custom article top snippet -->
<div class="article__content" itemprop="articleBody"><details>
<summary><b>Afficher/cacher Sommaire</b></summary>
<!-- affichage sommaire -->
<div class="toc-aside js-toc-root"></div>
</details><h2 id="rfid-nfc">RFID NFC</h2>
<p>La Radio Identification, ou RFID (en anglais Radio Frequency Identification) est une technologie permettant didentifier et caractériser un objet grâce à une étiquette émettant des ondes radio.</p>
<p>La RFID fait partie des technologies de localisation en temps réel (RTLS : Real Time Localisation System) et est utilisée principalement dans le cadre du traçage de marchandises dans de nombreux secteurs : retail, santé, transport et logistique, militaire et automobile.</p>
<p>Ainsi, le NFC est un dérivé de la technologie RFID mais présente quelques spécificités. La différence principale entre la RFID et le NFC réside dans le fait que la technologie NFC permet un transfert de données limité. Enfin, la technologie NFC fonctionne à très faible distance, quelques centimètres seulement contre plusieurs mètres pour la RFID.</p>
<p>Quest-ce que la technologie RFID et comment fonctionne-t-elle?</p>
<p>Le système d identification par radiofréquence comprend deux composants principaux: un transpondeur/étiquette attaché à un objet à identifier et un émetteur-récepteur également appelé interrogateur/lecteur.</p>
<p><img src="/images/How-RFID-Technology-Works-Reader-Writer-System-Tag-Communication.jpg" alt="" width="600" /></p>
<p>Un lecteur se compose dun module radiofréquence et dune antenne générant un champ électromagnétique haute fréquence. Dautre part, létiquette est généralement un périphérique passif, ce qui signifie quelle ne contient pas de batterie. Au lieu de cela, il contient une puce qui stocke et traite les informations, ainsi quune antenne pour recevoir et transmettre un signal.</p>
<p>Pour lire les informations encodées sur une étiquette, celle-ci est placée à proximité du lecteur (il nest pas nécessaire que celle-ci se trouve dans la ligne de vue directe du lecteur). Un lecteur génère un champ électromagnétique qui fait que les électrons se déplacent à travers lantenne de létiquette et alimentent ensuite la puce.</p>
<p><code class="language-plaintext highlighter-rouge">&lt;iframe src="/files/Passive-RFID-System-Working.mp4" width="640" height="360" frameborder="0" &gt;&lt;/iframe&gt;</code></p>
<video width="640" height="480" controls="">
<source src="/files/Passive-RFID-System-Working.mp4" type="video/mp4" />
</video>
<p>La puce alimentée à lintérieur de létiquette répond ensuite en renvoyant ses informations stockées au lecteur sous la forme dun autre signal radio. Ceci sappelle la rétrodiffusion. La rétrodiffusion, ou la modification de londe électromagnétique / RF, est détectée et interprétée par le lecteur qui envoie ensuite les données à un ordinateur ou à un microcontrôleur.</p>
<h2 id="liens">Liens</h2>
<ul>
<li><a href="http://blogmotion.fr/internet/securite/gen1-gen2-gen3-nfc-mifare-1k-18004">Présentation des générations de tags Mifare (NFC 13,56 MHz)</a></li>
<li><a href="https://www.latelierdugeek.fr/tag/mfoc/">mfoc LAtelier du Geek</a></li>
<li><a href="https://blandais.github.io/mifare/fr">Cloner un tag Mifare avec un PN532</a></li>
<li><a href="https://www.unicoda.com/?p=3350">Clone parfait dune puce RFID</a></li>
<li><a href="https://smartlockpicking.com/slides/Confidence_A_2018_Practical_Guide_To_Hacking_RFID_NFC.pdf">A 2018 practical guide to hacking NFC/RFID … - Smart lockpicking (pdf)</a></li>
<li><a href="https://net-security.fr/security/copier-un-badge-nfc-avec-kali-linux-android/">Copier un badge NFC avec Kali Linux &amp; Android</a></li>
</ul>
<h2 id="lecteur-usbrfid-scl3711">Lecteur USB/RFID SCL3711</h2>
<p><img src="/images/usb-rfid-scl3711.png" alt="" /><br />
Specifications</p>
<p>Operates in the following modes:</p>
<ul>
<li>ISO/IEC 14443A/MIFARE® Reader/Writer</li>
<li>FeliCa Reader/Writer</li>
<li>ISO/IEC 14443B Reader/Writer</li>
<li>ISO/IEC 14443A/MIFARE Classic® 1K or MIFARE Classic® 4K emulation</li>
<li>FeliCa Card emulation</li>
<li>ISO/IEC 18092, ECMA 340 Peer-to-Peer</li>
</ul>
<h3 id="installer-outils-et-librairies-pcsc">Installer outils et librairies PC/SC</h3>
<p>sur debian :<br />
<code class="language-plaintext highlighter-rouge">sudo apt-get update &amp;&amp; sudo apt-get install pcscd libpcsclite1 pcsc-tools</code></p>
<p>sur archlinux:<br />
<code class="language-plaintext highlighter-rouge">sudo pacman -S ccid opensc pcsc-tools nfcutils mfoc</code></p>
<p>Brancher votre lecteur RFID (si ça nest pas déjà fait).</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo dmesg
</code></pre></div></div>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>[ 5115.395318] usb 2-1: new full-speed USB device number 3 using xhci_hcd
[ 5115.576126] usb 2-1: New USB device found, idVendor=04e6, idProduct=5591, bcdDevice= 2.07
[ 5115.576132] usb 2-1: New USB device strings: Mfr=1, Product=2, SerialNumber=0
[ 5115.576135] usb 2-1: Product: SCL3711-NFC&amp;RW
[ 5115.576137] usb 2-1: Manufacturer: SCM Micro
[ 5115.635559] nfc: nfc_init: NFC Core ver 0.1
[ 5115.635587] NET: Registered protocol family 39
[ 5115.644154] usb 2-1: NFC: NXP PN533 firmware ver 2.7 now attached
[ 5115.646729] usbcore: registered new interface driver pn533_usb
[ 7314.588412] usb 2-1: USB disconnect, device number 3
[ 7314.588667] pn533_usb 2-1:1.0: NFC: NXP PN533 NFC device disconnected
[ 7318.093305] usb 2-1: new full-speed USB device number 4 using xhci_hcd
[ 7318.268850] usb 2-1: New USB device found, idVendor=04e6, idProduct=5591, bcdDevice= 2.07
[ 7318.268856] usb 2-1: New USB device strings: Mfr=1, Product=2, SerialNumber=0
[ 7318.268860] usb 2-1: Product: SCL3711-NFC&amp;RW
[ 7318.268862] usb 2-1: Manufacturer: SCM Micro
[ 7318.273599] usb 2-1: NFC: NXP PN533 firmware ver 2.7 now attached
</code></pre></div></div>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>lsusb
</code></pre></div></div>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Bus 002 Device 004: ID 04e6:5591 SCM Microsystems, Inc. SCL3711-NFC&amp;RW
</code></pre></div></div>
<p>Après insertion, archlinux va alors charger automatiquement en arrière plan des modules qui vont perturber les NFC Tools.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>lsmod |grep pn533
</code></pre></div></div>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>pn533_usb 20480 0
pn533 45056 1 pn533_usb
nfc 135168 1 pn533
</code></pre></div></div>
<p>Pour décharger ces modules, toujours dans votre fenêtre du terminal, entrez les commandes suivantes.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo modprobe -r pn533_usb
sudo modprobe -r pn533
</code></pre></div></div>
<h3 id="vérifier-le-fonctionnement-du-lecteur">Vérifier le fonctionnement du lecteur</h3>
<p>Pour être sûr que le lecteur fonctionne correctement avec les <strong>NFC Tools</strong>, poser un tag RFID sur le lecteur et lancer la commande suivante</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>nfc-list
</code></pre></div></div>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>nfc-list uses libnfc 1.7.1
NFC device: SCM Micro / SCL3711-NFC&amp;RW opened
1 ISO14443A passive target(s) found:
ISO/IEC 14443A (106 kbps) target:
ATQA (SENS_RES): 00 04
UID (NFCID1): 3d 51 1f 70
SAK (SEL_RES): 08
</code></pre></div></div>
<h3 id="extraire-les-clés-de-chiffrement-de-la-puce-rfid-vierge-dans-un-fichier">Extraire les clés de chiffrement de la puce RFID vierge dans un fichier</h3>
<p>Pour pouvoir écrire sur une puce RFID, il faut en posséder les clés de chiffrement. Une sorte de mot de passe qui permet dencoder et de décoder les informations de la puce. Ces clés de chiffrements vont être stockées avec le contenu de la clé, dans un fichier. Ce fichier nous servira lors de létape finale pour copier les données de la puce originale sur la puce chinoise.</p>
<p>Pour lancer lextraction des clés de chiffrement, placez votre puce sur le lecteur et saisissez dans un terminal la commande suivante.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo mfoc -P 500 -O carte-vierge.dmp
</code></pre></div></div>
<p>Les clés de chiffrement seront stockées dans le fichier « carte-vierge.dmp ».</p>
<h3 id="copiez-le-contenu-de-la-puce-rfid-dorigine-dans-un-fichier">Copiez le contenu de la puce RFID dorigine dans un fichier</h3>
<p>Maintenant que les clés de chiffrement de la puce chinoise sont extraites, il va falloir faire de même avec la puce originale. Cette opération va copier les clés de chiffrement et le contenu de la puce dorigine dans un fichier. Ce fichier contiendra toutes les données de la puce, ainsi que son UID. Cest en quelques sorte une « sauvegarde » de votre puce RFID. Nhésitez pas à la conserver en lieu sûr, ainsi si vous perdez votre puce RFID vous pourrez en créer de nouvelles à lidentique à partir de ce fichier de sauvegarde.</p>
<p>Pour ce faire, placez la puce originale sur votre lecteur, et entrez la commande suivante :</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo mfoc -P 500 -O carte-originale.dmp
</code></pre></div></div>
<p>Vous laurez surement compris, cette commande va créer un fichier « carte-originale.dmp » cest le fameux fichier de sauvegarde de votre puce originale.</p>
<h3 id="ecrire-le-contenu-de-la-puce-originale-sur-la-puce-vierge">Ecrire le contenu de la puce originale sur la puce vierge</h3>
<p>On arrive au bout ! Vous nêtes plus quà une dernière commande de la victoire ! Maintenant que lon possède une copie du contenu de la puce originale, ainsi que les clés de chiffrement de la puce chinoise, nous allons pouvoir transférer le contenu et lUID de la puce originale sur la puce chinoise.</p>
<p>Pour se faire, et toujours dans le terminal, saisissez la commande suivante.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo nfc-mfclassic W a carte-originale.dmp carte-vierge.dmp
</code></pre></div></div>
<p><img src="/images/nfc-write.png" alt="" /><br />
Lopération devrait prendre 1 grosse seconde avant daboutir sur un message de succès. Si vous êtes attentifs, vous remarquerez que la seule différence par rapport au précédent article est le fait que le « W » est écrit en capital. ça nest pas une erreur, cela demande au lecteur de transférer le contenu de la puce ainsi que le bloc 0 qui contient lUID. En cas de succès, un message devrait vous confirmer lécriture de 64 secteurs sur 64</p>
<h3 id="nfc-tools--gui">NFC Tools GUI</h3>
<p><a href="https://www.wakdev.com/apps/nfc-tools-pc-mac.html">NFC Tools GUI</a> est un logiciel multiplate-forme: il fonctionne sur Mac, Windows et Linux.
Vous pouvez lire et écrire vos puces NFC grâce à une interface utilisateur simple et lisible.</p>
<p><strong>Prérequis</strong></p>
<ul>
<li>Un lecteur NFC compatible, avec pilotes associés et bibliothèque PC/SC.
<ul>
<li>Lecteurs NFC testés :
<ul>
<li>ACR122U, ACR122T, ACR1255, ACR1256, ACR1252U, ACR1222L, ACR1255U-J1, SCM SCL3711, uTrust 3700F, Sony RC-S380 (Windows only) …</li>
</ul>
</li>
</ul>
</li>
<li>Des puces NFC compatibles.
<ul>
<li>Puces NFC testées :
<ul>
<li>Mifare Ultralight, Mifare Ultralight C, NTAG203, NTAG210, NTAG212, NTAG213, NTAG215, NTAG216 , Mifare Classic 1k/4k, …</li>
</ul>
</li>
</ul>
</li>
</ul>
<p><strong>Installation sur Linux</strong></p>
<ul>
<li>Télécharger l<a href="https://apps.wakdev.com/ntgui/releases/linux/nfctools-latest.AppImage">image (.AppImage)</a><br />
<code class="language-plaintext highlighter-rouge">sudo -s</code><br />
<code class="language-plaintext highlighter-rouge">wget -O /usr/local/bin/nfctoolsgui.AppImage https://apps.wakdev.com/ntgui/releases/linux/nfctools-latest.AppImage</code><br />
<code class="language-plaintext highlighter-rouge">chmod +x /usr/local/bin/nfctoolsgui.AppImage</code></li>
<li>Définir les droits dexécution: chmod +x nfctools-lastest.AppImage</li>
<li>Connectez votre lecteur NFC à votre ordinateur</li>
<li>Ouvrez lapplication <strong>nfctoolsgui.AppImage</strong></li>
</ul>
<h2 id="lecteur--rfid-rc522raspberry-pi">Lecteur RFID RC522/Raspberry Pi</h2>
<p><a href="https://pimylifeup.com/raspberry-pi-rfid-rc522/">How to setup a Raspberry Pi RFID RC522 Chip</a></p>
<p>Les puces RFID sont de plus en plus utilisées pour des systèmes didentification, de gestion dinventaire, de paiement, ou pour de la domotique,</p>
<p>Comment lire des cartes RFID avec la Raspberry Pi et un lecteur RFID RC522 ?</p>
<p>À la fin du tutoriel, vous serez capable de lire un badge RFID, vérifier si cest bien celui attendu, et allumer une LED verte ou rouge, selon le résultat. Il ne vous restera plus quà adapter cet exemple de base pour le projet de votre choix !</p>
<h3 id="matériel-nécessaire">matériel nécessaire</h3>
<ul>
<li>Une raspberry pi</li>
<li>Son alimentation</li>
<li>Une carte MicroSD</li>
<li>Un lecteur RFID RC522</li>
<li>Un ensemble de câbles, LEDs, résistances et plaques de test</li>
</ul>
<h3 id="lecteur-rfid-rc522">lecteur RFID RC522</h3>
<p><img src="/images/rfid-rc522.png" alt="" width="200" /></p>
<table>
<thead>
<tr>
<th>RFC522</th>
<th>Spécifications</th>
</tr>
</thead>
<tbody>
<tr>
<td>Frequency Range</td>
<td>13.56 MHz ISM Band</td>
</tr>
<tr>
<td>Host Interface</td>
<td>SPI / I2C / UART</td>
</tr>
<tr>
<td>Operating Supply Voltage</td>
<td>2.5 V to 3.3 V</td>
</tr>
<tr>
<td>Max. Operating Current</td>
<td>13-26mA</td>
</tr>
<tr>
<td>Min. Current(Power down)</td>
<td>10µA</td>
</tr>
<tr>
<td>Logic Inputs</td>
<td>5V Tolerant</td>
</tr>
<tr>
<td>Read Range</td>
<td>5 cm</td>
</tr>
</tbody>
</table>
<p><img src="/images/rfc522-pinouts.png" alt="" width="400" /></p>
<ul>
<li><strong><em>VCC</em></strong> alimente le module. Cela peut être nimporte où de 2,5 à 3,3 volts. Vous pouvez le connecter à la sortie 3.3V de votre Arduino. Noubliez pas que le connecter à une broche 5V détruira probablement votre module!</li>
<li><strong><em>RST</em></strong> est une entrée pour la réinitialisation et la mise hors tension. Lorsque cette broche devient faible, la mise hors tension matérielle est activée. Cela désactive tous les récepteurs de courant internes, y compris loscillateur et les broches dentrée, sont déconnectés du monde extérieur. Sur le front montant, le module est réinitialisé.</li>
<li><strong><em>GND</em></strong> est la broche de terre et doit être connecté à la broche GND de lArduino.</li>
<li><strong><em>IRQ</em></strong> est une broche dinterruption pouvant alerter le microcontrôleur lorsque létiquette RFID se trouve à proximité.</li>
<li>La broche <strong><em>MISO/SCL/Tx</em></strong> fait office de sortie maître-esclave lorsque linterface SPI est activée, agit comme horloge série lorsque linterface I2C est activée et agit comme sortie de données série lorsque linterface UART est activée.</li>
<li><strong><em>MOSI (Master Out Slave In)</em></strong> est lentrée SPI du module RC522.</li>
<li><strong><em>SCK (Serial Clock)</em></strong> accepte les impulsions dhorloge fournies par le bus maître SPI, cest-à-dire Arduino.</li>
<li>La broche <strong><em>SS/SDA/Rx</em></strong> agit comme entrée de signal lorsque linterface SPI est activée, agit comme données série lorsque linterface I2C est activée et agit comme entrée de données série lorsque linterface UART est activée. Cette broche est généralement marquée en la recouvrant dun carré afin de pouvoir être utilisée comme référence pour identifier les autres broches.</li>
</ul>
<h3 id="les-ports-gpio-du-rasberry-pi">Les ports GPIO du Rasberry Pi</h3>
<p>Un port GPIO transmet un signal relativement binaire (pas de courant ou du courant). Dans le cas de la Raspberry Pi, les ports GPIO travaillent en 3.3 V et environ 20 mA.<br />
Les ports GPIO sont donc un moyen simple de communiquer ou de contrôler des éléments physiques.</p>
<p>Les modèles les plus récents de la Raspberry Pi disposent de 40 connectiques GPIO, qui se divisent en différentes catégories avec des usages spécifiques.</p>
<ul>
<li>Power + : Alimentation électrique continue</li>
<li>GND : Ground = Retour à la terre</li>
<li>I2C : Protocole série synchrone</li>
<li>SPI : Autre protocole série synchrone</li>
<li>UART : Protocole asynchrone + conversion communication série vers parallèle.</li>
<li>GPIO : Port général qui peut éventuellement être transformé en I2C ou SPI.<br />
<img src="/images/Raspberry-Pi-GPIO-pinouts.png" alt="" width="400" /></li>
</ul>
<h3 id="connexion-du-lecteur-rfid-rc522-au-raspberry-pi">Connexion du lecteur RFID RC522 au Raspberry Pi</h3>
<p>les ports du lecteur et le port GPIO de la raspberry pi<br />
<img src="/images/gpio-raspberry-rc522.png" alt="" width="400" /></p>
<h3 id="branchement-des-leds">Branchement des leds</h3>
<p>Connecter la résistance de 1.2k entre la masse (GND) et les 2 cathodes des leds.<br />
Lanode de la led rouge sur GPIO02 Pin 3 du raspberry pi
Lanode de la led verte sur GPIO03 Pin 5 du raspberry pi</p>
<h3 id="activer-le-protocole-spi-de-la-raspberry-pi">Activer le protocole SPI de la Raspberry Pi</h3>
<p>Avant décrire le programme, activons le protocole SPI sur notre Raspberry Pi afin de pouvoir utiliser le module RFID. Lancer la commande <code class="language-plaintext highlighter-rouge">sudo raspi-config</code>, sur votre raspberry, puis de choisir <strong>Interfacing Options, SPI, Yes</strong> et enfin <strong>Finish</strong>.</p>
<h3 id="installer-la-librairie-pi-rc522">Installer la librairie pi-rc522</h3>
<p>La librairie Python3 pi-rc522 permet de contrôler le lecteur RC522.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo pip3 install pi-rc522
</code></pre></div></div>
<h3 id="programme-de-lecture-identifiant-badge-rfid">Programme de lecture identifiant badge RFID</h3>
<p>Chaque badge RFID possède un identifiant unique. Cest en lisant cet identifiant et en le comparant à une liste didentifiants autorisés que lon peut savoir si un badge est autorisé.<br />
Ecrire un programme dans le dossier <strong>/home/pi/electronic</strong> pour lire lidentifiant unique dun badge RFID. <br />
Création fichier <strong>read_rfid_uid.py</strong></p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">#!/usr/bin/env python3.5
#-- coding: utf-8 --
</span>
<span class="kn">import</span> <span class="n">RPi.GPIO</span> <span class="k">as</span> <span class="n">GPIO</span> <span class="c1">#Importe la bibliothèque pour contrôler les GPIOs
</span><span class="kn">from</span> <span class="n">pirc522</span> <span class="kn">import</span> <span class="n">RFID</span>
<span class="kn">import</span> <span class="n">time</span>
<span class="n">GPIO</span><span class="p">.</span><span class="nf">setmode</span><span class="p">(</span><span class="n">GPIO</span><span class="p">.</span><span class="n">BOARD</span><span class="p">)</span> <span class="c1">#Définit le mode de numérotation (Board)
</span><span class="n">GPIO</span><span class="p">.</span><span class="nf">setwarnings</span><span class="p">(</span><span class="bp">False</span><span class="p">)</span> <span class="c1">#On désactive les messages d'alerte
</span>
<span class="n">rc522</span> <span class="o">=</span> <span class="nc">RFID</span><span class="p">()</span> <span class="c1">#On instancie la lib
</span>
<span class="nf">print</span><span class="p">(</span><span class="sh">'</span><span class="s">En attente d</span><span class="se">\'</span><span class="s">un badge (pour quitter, Ctrl + c): </span><span class="sh">'</span><span class="p">)</span> <span class="c1">#On affiche un message demandant à l'utilisateur de passer son badge
</span>
<span class="c1">#On va faire une boucle infinie pour lire en boucle
</span><span class="k">while</span> <span class="bp">True</span> <span class="p">:</span>
<span class="n">rc522</span><span class="p">.</span><span class="nf">wait_for_tag</span><span class="p">()</span> <span class="c1">#On attnd qu'une puce RFID passe à portée
</span> <span class="p">(</span><span class="n">error</span><span class="p">,</span> <span class="n">tag_type</span><span class="p">)</span> <span class="o">=</span> <span class="n">rc522</span><span class="p">.</span><span class="nf">request</span><span class="p">()</span> <span class="c1">#Quand une puce a été lue, on récupère ses infos
</span>
<span class="k">if</span> <span class="ow">not</span> <span class="n">error</span> <span class="p">:</span> <span class="c1">#Si on a pas d'erreur
</span> <span class="p">(</span><span class="n">error</span><span class="p">,</span> <span class="n">uid</span><span class="p">)</span> <span class="o">=</span> <span class="n">rc522</span><span class="p">.</span><span class="nf">anticoll</span><span class="p">()</span> <span class="c1">#On nettoie les possibles collisions, ça arrive si plusieurs cartes passent en même temps
</span>
<span class="k">if</span> <span class="ow">not</span> <span class="n">error</span> <span class="p">:</span> <span class="c1">#Si on a réussi à nettoyer
</span> <span class="nf">print</span><span class="p">(</span><span class="sh">'</span><span class="s">Vous avez passé le badge avec l</span><span class="se">\'</span><span class="s">id : {}</span><span class="sh">'</span><span class="p">.</span><span class="nf">format</span><span class="p">(</span><span class="n">uid</span><span class="p">))</span> <span class="c1">#On affiche l'identifiant unique du badge RFID
</span> <span class="n">time</span><span class="p">.</span><span class="nf">sleep</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span> <span class="c1">#On attend 1 seconde pour ne pas lire le tag des centaines de fois en quelques milli-secondes
</span></code></pre></div></div>
<p>Une fois le fichier enregistré, on en autorise lexécution avec la commande :</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo chmod +x /home/pi/electronic/read_rfid_uid.py
</code></pre></div></div>
<p>Nous pouvons maintenant démarrer le programme en lappelant avec la commande :</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>/home/pi/electronic/read_rfid_uid.py
</code></pre></div></div>
<p>À chaque fois que vous passerez un badge RFID devant le lecteur, son identifiant unique sera affiché !</p>
<h3 id="afficher-si-un-badge-est-valide-ou-non">afficher si un badge est valide ou non</h3>
<p>Maintenant que nous pouvons lire lidentifiant unique dun badge, il ne nous reste plus quà adapter le code précédent pour comparer lidentifiant lu à un identifiant écrit dans le programme.<br />
Nous allons donc modifier un peu le programme précédent pour quil compare luid lu à celui écris dans le programme, et allumer la led rouge ou verte selon le résultat.<br />
Copiez donc le fichier précédent, dans un nouveau fichier <strong>verify_rfid.py</strong> et modifier le pour le code ci-dessous</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">#!/usr/bin/env python3.5
#-- coding: utf-8 --
</span>
<span class="kn">import</span> <span class="n">RPi.GPIO</span> <span class="k">as</span> <span class="n">GPIO</span> <span class="c1">#Importe la bibliothèque pour contrôler les GPIOs
</span><span class="kn">from</span> <span class="n">pirc522</span> <span class="kn">import</span> <span class="n">RFID</span>
<span class="kn">import</span> <span class="n">time</span>
<span class="n">GPIO</span><span class="p">.</span><span class="nf">setmode</span><span class="p">(</span><span class="n">GPIO</span><span class="p">.</span><span class="n">BOARD</span><span class="p">)</span> <span class="c1">#Définit le mode de numérotation (Board)
</span><span class="n">GPIO</span><span class="p">.</span><span class="nf">setwarnings</span><span class="p">(</span><span class="bp">False</span><span class="p">)</span> <span class="c1">#On désactive les messages d'alerte
</span>
<span class="n">LED_RED</span> <span class="o">=</span> <span class="mi">3</span> <span class="c1">#Définit le numéro du port GPIO qui alimente la led rouge
</span><span class="n">LED_GREEN</span> <span class="o">=</span> <span class="mi">5</span> <span class="c1">#Définit le numéro du port GPIO qui alimente la led verte
</span><span class="n">RFID_UID</span> <span class="o">=</span> <span class="p">[</span><span class="mi">21</span><span class="p">,</span> <span class="mi">35</span><span class="p">,</span> <span class="mi">5</span><span class="p">,</span> <span class="mi">43</span><span class="p">,</span> <span class="mi">57</span><span class="p">]</span> <span class="c1">#Définit l'UID du badge RFID
</span>
<span class="c1">#Définit la fonction permettant d'allumer une led
</span><span class="k">def</span> <span class="nf">turn_led_on</span> <span class="p">(</span><span class="n">led</span><span class="p">)</span> <span class="p">:</span>
<span class="n">GPIO</span><span class="p">.</span><span class="nf">setup</span><span class="p">(</span><span class="n">led</span><span class="p">,</span> <span class="n">GPIO</span><span class="p">.</span><span class="n">OUT</span><span class="p">)</span> <span class="c1">#Active le contrôle du GPIO
</span> <span class="n">GPIO</span><span class="p">.</span><span class="nf">output</span><span class="p">(</span><span class="n">led</span><span class="p">,</span> <span class="n">GPIO</span><span class="p">.</span><span class="n">HIGH</span><span class="p">)</span> <span class="c1">#Allume la led
</span>
<span class="c1">#Définit la fonction permettant d'éteindre une led
</span><span class="k">def</span> <span class="nf">turn_led_off</span> <span class="p">(</span><span class="n">led</span><span class="p">)</span> <span class="p">:</span>
<span class="n">GPIO</span><span class="p">.</span><span class="nf">setup</span><span class="p">(</span><span class="n">led</span><span class="p">,</span> <span class="n">GPIO</span><span class="p">.</span><span class="n">OUT</span><span class="p">)</span> <span class="c1">#Active le contrôle du GPIO
</span> <span class="n">GPIO</span><span class="p">.</span><span class="nf">output</span><span class="p">(</span><span class="n">led</span><span class="p">,</span> <span class="n">GPIO</span><span class="p">.</span><span class="n">LOW</span><span class="p">)</span> <span class="c1">#Eteind la led
</span>
<span class="c1">#Définit la fonction permettant d'allumer la rouge et éteindre la verte
</span><span class="k">def</span> <span class="nf">turn_red_on</span> <span class="p">()</span> <span class="p">:</span>
<span class="nf">turn_led_off</span><span class="p">(</span><span class="n">LED_GREEN</span><span class="p">)</span> <span class="c1">#Eteind la led verte
</span> <span class="nf">turn_led_on</span><span class="p">(</span><span class="n">LED_RED</span><span class="p">)</span> <span class="c1">#Allume la led rouge
</span>
<span class="c1">#Définit la fonction permettant d'allumer la verte et éteindre la rouge
</span><span class="k">def</span> <span class="nf">turn_green_on</span> <span class="p">()</span> <span class="p">:</span>
<span class="nf">turn_led_off</span><span class="p">(</span><span class="n">LED_RED</span><span class="p">)</span> <span class="c1">#Eteind la led rouge
</span> <span class="nf">turn_led_on</span><span class="p">(</span><span class="n">LED_GREEN</span><span class="p">)</span> <span class="c1">#Allume la led verte
</span>
<span class="n">rc522</span> <span class="o">=</span> <span class="nc">RFID</span><span class="p">()</span> <span class="c1">#On instancie la lib
</span>
<span class="nf">print</span><span class="p">(</span><span class="sh">'</span><span class="s">En attente d</span><span class="se">\'</span><span class="s">un badge (pour quitter, Ctrl + c): </span><span class="sh">'</span><span class="p">)</span> <span class="c1">#On affiche un message demandant à l'utilisateur de passer son badge
</span>
<span class="c1">#On va faire une boucle infinie pour lire en boucle
</span><span class="k">while</span> <span class="bp">True</span> <span class="p">:</span>
<span class="n">rc522</span><span class="p">.</span><span class="nf">wait_for_tag</span><span class="p">()</span> <span class="c1">#On attnd qu'une puce RFID passe à portée
</span> <span class="p">(</span><span class="n">error</span><span class="p">,</span> <span class="n">tag_type</span><span class="p">)</span> <span class="o">=</span> <span class="n">rc522</span><span class="p">.</span><span class="nf">request</span><span class="p">()</span> <span class="c1">#Quand une puce a été lue, on récupère ses infos
</span>
<span class="k">if</span> <span class="ow">not</span> <span class="n">error</span> <span class="p">:</span> <span class="c1">#Si on a pas d'erreur
</span> <span class="p">(</span><span class="n">error</span><span class="p">,</span> <span class="n">uid</span><span class="p">)</span> <span class="o">=</span> <span class="n">rc522</span><span class="p">.</span><span class="nf">anticoll</span><span class="p">()</span> <span class="c1">#On nettoie les possibles collisions, ça arrive si plusieurs cartes passent en même temps
</span>
<span class="k">if</span> <span class="ow">not</span> <span class="n">error</span> <span class="p">:</span> <span class="c1">#Si on a réussi à nettoyer
</span> <span class="k">if</span> <span class="n">RFID_UID</span> <span class="o">==</span> <span class="n">uid</span> <span class="p">:</span>
<span class="nf">print</span><span class="p">(</span><span class="sh">'</span><span class="s">Badge {} autorisé !</span><span class="sh">'</span><span class="p">.</span><span class="nf">format</span><span class="p">(</span><span class="n">uid</span><span class="p">))</span>
<span class="nf">turn_green_on</span><span class="p">()</span>
<span class="k">else</span> <span class="p">:</span>
<span class="nf">print</span><span class="p">(</span><span class="sh">'</span><span class="s">Badge {} interdit !</span><span class="sh">'</span><span class="p">.</span><span class="nf">format</span><span class="p">(</span><span class="n">uid</span><span class="p">))</span>
<span class="nf">turn_red_on</span><span class="p">()</span>
<span class="n">time</span><span class="p">.</span><span class="nf">sleep</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span> <span class="c1">#On attend 1 seconde pour ne pas lire le tag des centaines de fois en quelques milli-secondes
</span></code></pre></div></div>
<p>Il ne vous reste plus quà lancer le programme et tester !<br />
Vous pouvez ensuite adapter le code pour vos propres projets, comme créer un serrure connectée, ou encore un jukebox utilisant des tags RFID !<br />
Pour info, vous pouvez récupérer lensemble du code de ce tutoriel sur le <a href="https://github.com/RaspbianFrance/rfid">Github de Raspberry Pi FR</a>.</p>
<h2 id="lecteur-rfid-rc522arduino">Lecteur RFID RC522/Arduino</h2>
<ul>
<li><a href="https://ouiaremakers.com/posts/tutoriel-diy-arduino-rfid-rc522">Arduino RFID RC522</a></li>
<li><a href="https://lastminuteengineers.com/how-rfid-works-rc522-arduino-tutorial/">What is RFID? How It Works? Interface RC522 RFID Module with Arduino</a></li>
</ul>
<h3 id="interfacer-le-module-rfid-rc522-avec-arduino">Interfacer le module RFID RC522 avec Arduino</h3>
<p>Pour commencer, connectez la broche VCC du module à 3,3 V sur lArduino et la broche GND à la terre. La broche RST peut être connectée à nimporte quelle broche numérique sur lArduino. Dans notre cas, il est connecté à la broche numérique n ° 5. La broche IRQ nest pas connectée car la bibliothèque Arduino que nous allons utiliser ne la prend pas en charge.<br />
Nous en sommes maintenant aux broches utilisées pour la communication SPI. Comme le module RC522 nécessite beaucoup de transfert de données, il donnera les meilleures performances lorsquil est connecté aux broches SPI matérielles dun microcontrôleur. Les broches SPI matérielles sont beaucoup plus rapides que le “bit-bang” du code dinterface à laide dun autre ensemble de broches.</p>
<blockquote>
<p>Notez que chaque carte Arduino a différentes broches SPI qui doivent être connectées en conséquence. Pour les cartes Arduino telles que UNO / Nano V3.0, ces broches sont numériques 13 (SCK), 12 (MISO), 11 (MOSI) et 10 (SS).</p>
</blockquote>
<p>Si vous avez un Mega, les pins sont différents! Vous voudrez utiliser les technologies numériques 50 (MISO), 51 (MOSI), 52 (SCK) et 53 (SS). Reportez-vous au tableau ci-dessous pour une compréhension rapide.</p>
<table>
<thead>
<tr>
<th>_</th>
<th>MOSI</th>
<th>MISO</th>
<th>SCK</th>
<th>CS</th>
</tr>
</thead>
<tbody>
<tr>
<td>Arduino Uno</td>
<td>11</td>
<td>12</td>
<td>13</td>
<td>10</td>
</tr>
<tr>
<td>Arduino Nano</td>
<td>11</td>
<td>12</td>
<td>13</td>
<td>10</td>
</tr>
<tr>
<td>Arduino Mega</td>
<td>51</td>
<td>50</td>
<td>52</td>
<td>53</td>
</tr>
</tbody>
</table>
<p>Si vous utilisez une carte Arduino différente de celle mentionnée ci-dessus, il est conseillé de vérifier la <a href="https://www.arduino.cc/en/Reference/SPI">documentation officielle</a> dArduino avant de poursuivre.</p>
<p><img src="/images/Arduino-Wiring-Fritzing-Connections-with-RC522-RFID-Reader-Writer-Module.png" alt="" width="600" /><br />
Une fois que tout est connecté, vous êtes prêt</p>
<p>Les différents branchements</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>+-----------+----------+---------------------------------------------------------------+--------------------------+---------------+
| | PCD | Arduino | Teensy | ESP8266 |
| +----------+-------------+---------+---------+-----------------+-----------+--------+--------+--------+---------------+
| | MFRC522 | Uno / 101 | Mega | Nano v3 |Leonardo / Micro | Pro Micro | 2.0 | ++ 2.0 | 3.1 | Wemos D1 mini |
+-----------+----------+-------------+---------+---------+-----------------+-----------+--------+--------+--------+---------------+
| Signal | Pin | Pin | Pin | Pin | Pin | Pin | Pin | Pin | Pin | Pin |
+===========+==========+=============+=========+=========+=================+===========+========+========+========+===============+
| RST/Reset | RST | 9 [1]_ | 5 [1]_ | D9 | RESET / ICSP-5 | RST | 7 | 4 | 9 | D3 |
+-----------+----------+-------------+---------+---------+-----------------+-----------+--------+--------+--------+---------------+
| SPI SS | SDA [3]_ | 10 [2]_ | 53 [2]_ | D10 | 10 | 10 | 0 | 20 | 10 | D8 |
+-----------+----------+-------------+---------+---------+-----------------+-----------+--------+--------+--------+---------------+
| SPI MOSI | MOSI | 11 / ICSP-4 | 51 | D11 | ICSP-4 | 16 | 2 | 22 | 11 | D7 |
+-----------+----------+-------------+---------+---------+-----------------+-----------+--------+--------+--------+---------------+
| SPI MISO | MISO | 12 / ICSP-1 | 50 | D12 | ICSP-1 | 14 | 3 | 23 | 12 | D6 |
+-----------+----------+-------------+---------+---------+-----------------+-----------+--------+--------+--------+---------------+
| SPI SCK | SCK | 13 / ICSP-3 | 52 | D13 | ICSP-3 | 15 | 1 | 21 | 13 | D5 |
+-----------+----------+-------------+---------+---------+-----------------+-----------+--------+--------+--------+---------------+
</code></pre></div></div>
<h3 id="code-arduino---lecture-dune-étiquette-rfid">Code Arduino - Lecture dune étiquette RFID</h3>
<p>Communiquer avec le module RFID RC522 est un travail fastidieux, mais heureusement pour nous, il existe une bibliothèque appelée bibliothèque MFRC522 qui simplifie la lecture et lécriture sur les étiquettes RFID. Merci à Miguel Balboa. Commencez par télécharger la bibliothèque en visitant le <a href="https://github.com/miguelbalboa/rfid">dépôt GitHub</a> ou <a href="https://lastminuteengineers.com/libraries/rfid-master.zip">télécharger le zip</a>:</p>
<p>Pour linstaller, ouvrez lEDI Arduino, accédez à Esquisse&gt; Inclure la bibliothèque&gt; Ajouter une bibliothèque .ZIP, puis sélectionnez le fichier rfid-master.zip que vous venez de télécharger. Si vous avez besoin de plus de détails sur linstallation dune bibliothèque, consultez ce tutoriel sur linstallation dune bibliothèque Arduino .</p>
<p>Une fois la bibliothèque installée, ouvrez le sous-menu Exemples et sélectionnez MFRC522&gt; DumpInfo, exemple desquisse.<br />
<img src="/images/MFRC522-Library-Sketch-DumpInfo.png" alt="" width="400" /><br />
Cette esquisse nécrira aucune donnée sur la balise. Il vous indique simplement sil a réussi à lire la balise et affiche des informations à ce sujet. Cela peut être très utile avant dessayer un nouveau tag!</p>
<p>Allez au début de lesquisse et assurez-vous que le RST_PIN est correctement initialisé. Dans notre cas, nous utilisons la broche numérique 5 alors changez-le en 5!<br />
<img src="/images/MFRC522-Library-Sketch-DumpInfo-RST-pin.png" alt="" width="400" /> <br />
OK, chargez maintenant le croquis et ouvrez le moniteur de série. Dès que vous rapprochez le tag du module, vous obtiendrez probablement le résultat suivant. Ne déplacez pas le tag tant que toutes les informations ne sont pas affichées.<br />
<img src="/images/MFRC522-Library-DumpInfo-Output.png" alt="" width="400" /> <br />
Il affiche toutes les informations utiles sur la balise, y compris son identifiant unique (UID), sa taille et 1K de mémoire.</p>
<h3 id="disposition-de-la-mémoire-mifare-classic-1k">Disposition de la mémoire MIFARE Classic 1K</h3>
<p>La mémoire 1K de la balise est organisée en <strong>16 secteurs</strong> (de 0 à 15) Chaque secteur est divisé en <strong>4 blocs</strong> (blocs 0 à 3). Chaque bloc peut stocker 16 octets de données (de 0 à 15).</p>
<p>Cela nous dit sûrement que nous avons<br />
16 secteurs x 4 blocs x 16 octets de données = 1024 octets = 1K de mémoire</p>
<p>Lensemble de la mémoire 1K avec les secteurs, les blocs et les données est mis en évidence ci-dessous.<br />
<img src="/images/MFRC522-Library-DumpInfo-Memory-Layout.png" alt="" width="400" /> <br />
<img src="/images/3D-Representation-MIFARE-Classic-1K-Memory-Map-Layout.png" alt="" width="400" /> <br />
<em>Représentation 3D de la disposition de la carte mémoire MIFARE Classic 1K</em></p>
<p>Le bloc 3 de chaque secteur est appelé <strong>secteur</strong> et contient des informations appelées <strong>bits daccès</strong> permettant daccorder un <strong>accès</strong> en lecture et en écriture aux blocs restants dun secteur. Cela signifie que seuls les 3 derniers blocs (blocs 0, 1 et 2) de chaque secteur sont réellement disponibles pour le stockage de données, ce qui signifie que nous avons 48 octets par secteur de 64 octets disponibles pour notre propre usage.</p>
<p>De plus, le bloc 0 du secteur 0 est connu sous le nom de fabricant. Le fabricant contient les données du fabricant du circuit intégré, ainsi que l <strong>identificateur unique (UID)</strong>. Le bloc fabricant est surligné en rouge ci-dessous.<br />
<img src="/images/MFRC522-Library-DumpInfo-Manufacturer-Block.png" alt="" width="400" /></p>
<blockquote>
<p><strong>ATTENTION Il est très risqué décraser le bloc du fabricant (Manufacturer Block), cela pourrait verrouiller définitivement la carte.</strong></p>
</blockquote>
<h3 id="code-arduino---écrire-une-étiquette-rfid">Code Arduino - Écrire une étiquette RFID</h3>
<p>Considérant que vous avez lu avec succès létiquette RFID, nous allons passer à notre prochain test. Lesquisse suivante fera une démonstration de base de lécriture de données personnalisées sur une étiquette RFID. Essayez le croquis avant de commencer sa ventilation détaillée.</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">#include</span> <span class="cpf">&lt;SPI.h&gt;</span><span class="c1"> //include the SPI bus library</span><span class="cp">
#include</span> <span class="cpf">&lt;MFRC522.h&gt;</span><span class="c1"> //include the RFID reader library</span><span class="cp">
</span>
<span class="cp">#define SS_PIN 10 //slave select pin
#define RST_PIN 5 //reset pin
</span>
<span class="n">MFRC522</span> <span class="nf">mfrc522</span><span class="p">(</span><span class="n">SS_PIN</span><span class="p">,</span> <span class="n">RST_PIN</span><span class="p">);</span> <span class="c1">// instatiate a MFRC522 reader object.</span>
<span class="n">MFRC522</span><span class="o">::</span><span class="n">MIFARE_Key</span> <span class="n">key</span><span class="p">;</span> <span class="c1">//create a MIFARE_Key struct named 'key', which will hold the card information</span>
<span class="c1">//this is the block number we will write into and then read.</span>
<span class="kt">int</span> <span class="n">block</span><span class="o">=</span><span class="mi">2</span><span class="p">;</span>
<span class="n">byte</span> <span class="n">blockcontent</span><span class="p">[</span><span class="mi">16</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span><span class="s">"Last-Minute-Engg"</span><span class="p">};</span> <span class="c1">//an array with 16 bytes to be written into one of the 64 card blocks is defined</span>
<span class="c1">//byte blockcontent[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; //all zeros. This can be used to delete a block.</span>
<span class="c1">//This array is used for reading out a block.</span>
<span class="n">byte</span> <span class="n">readbackblock</span><span class="p">[</span><span class="mi">18</span><span class="p">];</span>
<span class="kt">void</span> <span class="nf">setup</span><span class="p">()</span>
<span class="p">{</span>
<span class="n">Serial</span><span class="p">.</span><span class="n">begin</span><span class="p">(</span><span class="mi">9600</span><span class="p">);</span> <span class="c1">// Initialize serial communications with the PC</span>
<span class="n">SPI</span><span class="p">.</span><span class="n">begin</span><span class="p">();</span> <span class="c1">// Init SPI bus</span>
<span class="n">mfrc522</span><span class="p">.</span><span class="n">PCD_Init</span><span class="p">();</span> <span class="c1">// Init MFRC522 card (in case you wonder what PCD means: proximity coupling device)</span>
<span class="n">Serial</span><span class="p">.</span><span class="n">println</span><span class="p">(</span><span class="s">"Scan a MIFARE Classic card"</span><span class="p">);</span>
<span class="c1">// Prepare the security key for the read and write functions.</span>
<span class="k">for</span> <span class="p">(</span><span class="n">byte</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="mi">6</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
<span class="n">key</span><span class="p">.</span><span class="n">keyByte</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="mh">0xFF</span><span class="p">;</span> <span class="c1">//keyByte is defined in the "MIFARE_Key" 'struct' definition in the .h file of the library</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="kt">void</span> <span class="nf">loop</span><span class="p">()</span>
<span class="p">{</span>
<span class="c1">// Look for new cards</span>
<span class="k">if</span> <span class="p">(</span> <span class="o">!</span> <span class="n">mfrc522</span><span class="p">.</span><span class="n">PICC_IsNewCardPresent</span><span class="p">())</span> <span class="p">{</span>
<span class="k">return</span><span class="p">;</span>
<span class="p">}</span>
<span class="c1">// Select one of the cards</span>
<span class="k">if</span> <span class="p">(</span> <span class="o">!</span> <span class="n">mfrc522</span><span class="p">.</span><span class="n">PICC_ReadCardSerial</span><span class="p">())</span>
<span class="p">{</span>
<span class="k">return</span><span class="p">;</span>
<span class="p">}</span>
<span class="n">Serial</span><span class="p">.</span><span class="n">println</span><span class="p">(</span><span class="s">"card selected"</span><span class="p">);</span>
<span class="c1">//the blockcontent array is written into the card block</span>
<span class="n">writeBlock</span><span class="p">(</span><span class="n">block</span><span class="p">,</span> <span class="n">blockcontent</span><span class="p">);</span>
<span class="c1">//read the block back</span>
<span class="n">readBlock</span><span class="p">(</span><span class="n">block</span><span class="p">,</span> <span class="n">readbackblock</span><span class="p">);</span>
<span class="c1">//uncomment below line if you want to see the entire 1k memory with the block written into it.</span>
<span class="c1">//mfrc522.PICC_DumpToSerial(&amp;(mfrc522.uid));</span>
<span class="c1">//print the block contents</span>
<span class="n">Serial</span><span class="p">.</span><span class="n">print</span><span class="p">(</span><span class="s">"read block: "</span><span class="p">);</span>
<span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">j</span><span class="o">=</span><span class="mi">0</span> <span class="p">;</span> <span class="n">j</span><span class="o">&lt;</span><span class="mi">16</span> <span class="p">;</span> <span class="n">j</span><span class="o">++</span><span class="p">)</span>
<span class="p">{</span>
<span class="n">Serial</span><span class="p">.</span><span class="n">write</span> <span class="p">(</span><span class="n">readbackblock</span><span class="p">[</span><span class="n">j</span><span class="p">]);</span>
<span class="p">}</span>
<span class="n">Serial</span><span class="p">.</span><span class="n">println</span><span class="p">(</span><span class="s">""</span><span class="p">);</span>
<span class="p">}</span>
<span class="c1">//Write specific block </span>
<span class="kt">int</span> <span class="nf">writeBlock</span><span class="p">(</span><span class="kt">int</span> <span class="n">blockNumber</span><span class="p">,</span> <span class="n">byte</span> <span class="n">arrayAddress</span><span class="p">[])</span>
<span class="p">{</span>
<span class="c1">//this makes sure that we only write into data blocks. Every 4th block is a trailer block for the access/security info.</span>
<span class="kt">int</span> <span class="n">largestModulo4Number</span><span class="o">=</span><span class="n">blockNumber</span><span class="o">/</span><span class="mi">4</span><span class="o">*</span><span class="mi">4</span><span class="p">;</span>
<span class="kt">int</span> <span class="n">trailerBlock</span><span class="o">=</span><span class="n">largestModulo4Number</span><span class="o">+</span><span class="mi">3</span><span class="p">;</span><span class="c1">//determine trailer block for the sector</span>
<span class="k">if</span> <span class="p">(</span><span class="n">blockNumber</span> <span class="o">&gt;</span> <span class="mi">2</span> <span class="o">&amp;&amp;</span> <span class="p">(</span><span class="n">blockNumber</span><span class="o">+</span><span class="mi">1</span><span class="p">)</span><span class="o">%</span><span class="mi">4</span> <span class="o">==</span> <span class="mi">0</span><span class="p">){</span><span class="n">Serial</span><span class="p">.</span><span class="n">print</span><span class="p">(</span><span class="n">blockNumber</span><span class="p">);</span><span class="n">Serial</span><span class="p">.</span><span class="n">println</span><span class="p">(</span><span class="s">" is a trailer block:"</span><span class="p">);</span><span class="k">return</span> <span class="mi">2</span><span class="p">;}</span>
<span class="n">Serial</span><span class="p">.</span><span class="n">print</span><span class="p">(</span><span class="n">blockNumber</span><span class="p">);</span>
<span class="n">Serial</span><span class="p">.</span><span class="n">println</span><span class="p">(</span><span class="s">" is a data block:"</span><span class="p">);</span>
<span class="c1">//authentication of the desired block for access</span>
<span class="n">byte</span> <span class="n">status</span> <span class="o">=</span> <span class="n">mfrc522</span><span class="p">.</span><span class="n">PCD_Authenticate</span><span class="p">(</span><span class="n">MFRC522</span><span class="o">::</span><span class="n">PICC_CMD_MF_AUTH_KEY_A</span><span class="p">,</span> <span class="n">trailerBlock</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">key</span><span class="p">,</span> <span class="o">&amp;</span><span class="p">(</span><span class="n">mfrc522</span><span class="p">.</span><span class="n">uid</span><span class="p">));</span>
<span class="k">if</span> <span class="p">(</span><span class="n">status</span> <span class="o">!=</span> <span class="n">MFRC522</span><span class="o">::</span><span class="n">STATUS_OK</span><span class="p">)</span> <span class="p">{</span>
<span class="n">Serial</span><span class="p">.</span><span class="n">print</span><span class="p">(</span><span class="s">"PCD_Authenticate() failed: "</span><span class="p">);</span>
<span class="n">Serial</span><span class="p">.</span><span class="n">println</span><span class="p">(</span><span class="n">mfrc522</span><span class="p">.</span><span class="n">GetStatusCodeName</span><span class="p">(</span><span class="n">status</span><span class="p">));</span>
<span class="k">return</span> <span class="mi">3</span><span class="p">;</span><span class="c1">//return "3" as error message</span>
<span class="p">}</span>
<span class="c1">//writing the block </span>
<span class="n">status</span> <span class="o">=</span> <span class="n">mfrc522</span><span class="p">.</span><span class="n">MIFARE_Write</span><span class="p">(</span><span class="n">blockNumber</span><span class="p">,</span> <span class="n">arrayAddress</span><span class="p">,</span> <span class="mi">16</span><span class="p">);</span>
<span class="c1">//status = mfrc522.MIFARE_Write(9, value1Block, 16);</span>
<span class="k">if</span> <span class="p">(</span><span class="n">status</span> <span class="o">!=</span> <span class="n">MFRC522</span><span class="o">::</span><span class="n">STATUS_OK</span><span class="p">)</span> <span class="p">{</span>
<span class="n">Serial</span><span class="p">.</span><span class="n">print</span><span class="p">(</span><span class="s">"MIFARE_Write() failed: "</span><span class="p">);</span>
<span class="n">Serial</span><span class="p">.</span><span class="n">println</span><span class="p">(</span><span class="n">mfrc522</span><span class="p">.</span><span class="n">GetStatusCodeName</span><span class="p">(</span><span class="n">status</span><span class="p">));</span>
<span class="k">return</span> <span class="mi">4</span><span class="p">;</span><span class="c1">//return "4" as error message</span>
<span class="p">}</span>
<span class="n">Serial</span><span class="p">.</span><span class="n">println</span><span class="p">(</span><span class="s">"block was written"</span><span class="p">);</span>
<span class="p">}</span>
<span class="c1">//Read specific block</span>
<span class="kt">int</span> <span class="nf">readBlock</span><span class="p">(</span><span class="kt">int</span> <span class="n">blockNumber</span><span class="p">,</span> <span class="n">byte</span> <span class="n">arrayAddress</span><span class="p">[])</span>
<span class="p">{</span>
<span class="kt">int</span> <span class="n">largestModulo4Number</span><span class="o">=</span><span class="n">blockNumber</span><span class="o">/</span><span class="mi">4</span><span class="o">*</span><span class="mi">4</span><span class="p">;</span>
<span class="kt">int</span> <span class="n">trailerBlock</span><span class="o">=</span><span class="n">largestModulo4Number</span><span class="o">+</span><span class="mi">3</span><span class="p">;</span><span class="c1">//determine trailer block for the sector</span>
<span class="c1">//authentication of the desired block for access</span>
<span class="n">byte</span> <span class="n">status</span> <span class="o">=</span> <span class="n">mfrc522</span><span class="p">.</span><span class="n">PCD_Authenticate</span><span class="p">(</span><span class="n">MFRC522</span><span class="o">::</span><span class="n">PICC_CMD_MF_AUTH_KEY_A</span><span class="p">,</span> <span class="n">trailerBlock</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">key</span><span class="p">,</span> <span class="o">&amp;</span><span class="p">(</span><span class="n">mfrc522</span><span class="p">.</span><span class="n">uid</span><span class="p">));</span>
<span class="k">if</span> <span class="p">(</span><span class="n">status</span> <span class="o">!=</span> <span class="n">MFRC522</span><span class="o">::</span><span class="n">STATUS_OK</span><span class="p">)</span> <span class="p">{</span>
<span class="n">Serial</span><span class="p">.</span><span class="n">print</span><span class="p">(</span><span class="s">"PCD_Authenticate() failed (read): "</span><span class="p">);</span>
<span class="n">Serial</span><span class="p">.</span><span class="n">println</span><span class="p">(</span><span class="n">mfrc522</span><span class="p">.</span><span class="n">GetStatusCodeName</span><span class="p">(</span><span class="n">status</span><span class="p">));</span>
<span class="k">return</span> <span class="mi">3</span><span class="p">;</span><span class="c1">//return "3" as error message</span>
<span class="p">}</span>
<span class="c1">//reading a block</span>
<span class="n">byte</span> <span class="n">buffersize</span> <span class="o">=</span> <span class="mi">18</span><span class="p">;</span><span class="c1">//we need to define a variable with the read buffer size, since the MIFARE_Read method below needs a pointer to the variable that contains the size... </span>
<span class="n">status</span> <span class="o">=</span> <span class="n">mfrc522</span><span class="p">.</span><span class="n">MIFARE_Read</span><span class="p">(</span><span class="n">blockNumber</span><span class="p">,</span> <span class="n">arrayAddress</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">buffersize</span><span class="p">);</span><span class="c1">//&amp;buffersize is a pointer to the buffersize variable; MIFARE_Read requires a pointer instead of just a number</span>
<span class="k">if</span> <span class="p">(</span><span class="n">status</span> <span class="o">!=</span> <span class="n">MFRC522</span><span class="o">::</span><span class="n">STATUS_OK</span><span class="p">)</span> <span class="p">{</span>
<span class="n">Serial</span><span class="p">.</span><span class="n">print</span><span class="p">(</span><span class="s">"MIFARE_read() failed: "</span><span class="p">);</span>
<span class="n">Serial</span><span class="p">.</span><span class="n">println</span><span class="p">(</span><span class="n">mfrc522</span><span class="p">.</span><span class="n">GetStatusCodeName</span><span class="p">(</span><span class="n">status</span><span class="p">));</span>
<span class="k">return</span> <span class="mi">4</span><span class="p">;</span><span class="c1">//return "4" as error message</span>
<span class="p">}</span>
<span class="n">Serial</span><span class="p">.</span><span class="n">println</span><span class="p">(</span><span class="s">"block was read"</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div></div>
<p>Lesquisse commence par inclure les bibliothèques MFRC522 et SPI, définissant les broches Arduino auxquelles le RC522 est connecté et instanciant un objet lecteur MFRC522.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>#include &lt;SPI.h&gt;//include the SPI bus library
#include &lt;MFRC522.h&gt;//include the RFID reader library
#define SS_PIN 10 //slave select pin
#define RST_PIN 5 //reset pin
MFRC522 mfrc522(SS_PIN, RST_PIN); // instatiate a MFRC522 reader object.
MFRC522::MIFARE_Key key;//create a MIFARE_Key struct named 'key', which will hold the card information
</code></pre></div></div>
<p>Ensuite, nous devons définir un bloc dans lequel nous allons stocker nos données. Ici le secteur 0 bloc 2 est sélectionné. Noubliez pas de ne jamais sélectionner le bloc 3 dun secteur. Lécriture dans un bloc segment de secteur peut rendre le bloc inutilisable.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>//this is the block number we will write into and then read.
int block=2;
</code></pre></div></div>
<p>Ensuite, nous définissons un tableau de 16 octets nommé blockcontent[16] qui contient le message que nous voulons écrire dans le bloc. Vous pouvez supprimer nimporte quel bloc en écrivant des zéros.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>byte blockcontent[16] = {"Last-Minute-Engg"}; //an array with 16 bytes to be written into one of the 64 card blocks is defined
//byte blockcontent[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; //all zeros. This can be used to delete a block.
</code></pre></div></div>
<p>Ensuite, nous devons définir un tableau de 18 octets nommé readbackblock [18] . Ceci peut être utilisé pour lire le contenu écrit. Attendez… 18 octets? Cela ne devrait-il pas être 16 octets? La réponse est non. La méthode MIFARE_Read de la bibliothèque MFRC522 nécessite un tampon dau moins 18 octets pour contenir les 16 octets dun bloc.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>//This array is used for reading out a block.
byte readbackblock[18];
</code></pre></div></div>
<p>Dans la fonction Setup: nous initialisons les communications série avec le PC, la bibliothèque SPI et lobjet MFRC522. Nous devons également préparer la clé de sécurité pour les fonctions de lecture et décriture. Ici, les six octets de clé sont définis sur 0xFF. Comme les cartes du kit sont neuves et que les clés nont jamais été définies, elles sont 0xFF. Si nous avions une carte programmée par quelquun dautre, nous aurions besoin de connaître la clé pour pouvoir y accéder. Cette clé devrait alors être stockée dans «clé» à la place.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Serial.begin(9600); // Initialize serial communications with the PC
SPI.begin(); // Init SPI bus
mfrc522.PCD_Init(); // Init MFRC522 card (in case you wonder what PCD means: proximity coupling device)
Serial.println("Scan a MIFARE Classic card");
// Prepare the security key for the read and write functions.
for (byte i = 0; i &lt; 6; i++) {
key.keyByte[i] = 0xFF; //keyByte is defined in the "MIFARE_Key" 'struct' definition in the .h file of the library
}
</code></pre></div></div>
<p>En boucle: nous recherchons dabord si une carte est en vue. Si oui, cette carte est sélectionnée pour les besoins de lécriture et de la lecture.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>// Look for new cards
if ( ! mfrc522.PICC_IsNewCardPresent()) {
return;
}
// Select one of the cards
if ( ! mfrc522.PICC_ReadCardSerial())
{
return;
}
Serial.println("card selected");
</code></pre></div></div>
<p>Il est maintenant très facile décrire le bloc, il suffit dappeler une fonction personnalisée appelée writeBlock() qui prend deux paramètres - lun est le numéro de bloc sur lequel nous souhaitons écrire les données et les données elles-mêmes.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>//the blockcontent array is written into the card block
writeBlock(block, blockcontent);
</code></pre></div></div>
<p>Pour vérifier si lopération décriture a réussi, nous devons relire le contenu du bloc. Cela peut être fait en utilisant la fonction personnalisée appelée readBlock() qui prend à nouveau deux paramètres: lun est le numéro de bloc et lautre est array pour stocker le contenu du bloc. Vous pouvez utiliser la fonction PICC_DumpToSerial() si vous souhaitez voir la totalité de la mémoire 1k avec le bloc écrit dans celle-ci.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>//read the block back
readBlock(block, readbackblock);
//uncomment below line if you want to see the entire 1k memory with the block written into it.
//mfrc522.PICC_DumpToSerial(&amp;(mfrc522.uid));
</code></pre></div></div>
<p>Enfin, nous imprimons le contenu du tableau readbackblock en utilisant une boucle for et affichons le contenu sur le moniteur série.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>//print the block contents
Serial.print("read block: ");
for (int j=0 ; j&lt;16 ; j++)
{
Serial.write (readbackblock[j]);
}
Serial.println("");
</code></pre></div></div>
<p>La sortie sur le moniteur série ressemblera à ceci.<br />
<img src="/images/RC522-RFID-Writing-Tag-Code-Sketch-Output.png" alt="" width="400" /></p>
<h3 id="autre-exemple-lectureécriture">Autre exemple lecture/écriture</h3>
<p>On prend lexemple nommé <strong>ReadAndWrite.ino</strong> joint avec la bibliothèque MFR522</p>
<blockquote>
<p>ATTENTION : Les données seront inscrites dans le tag, dans le secteur #1 (blocs #4 à #7).</p>
</blockquote>
<p>Résultat sur la console</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Scan a MIFARE Classic PICC to demonstrate read and write.
Using key (for A and B): FF FF FF FF FF FF
BEWARE: Data will be written to the PICC, in sector #1
Card UID: 17 F9 B3 BF
PICC type: MIFARE 1KB
Authenticating using key A...
Current data in sector:
1 7 00 00 00 00 00 00 FF 07 80 69 FF FF FF FF FF FF [ 0 0 1 ]
6 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 [ 0 0 0 ]
5 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 [ 0 0 0 ]
4 01 02 03 04 05 06 07 08 09 0A FF 0B 0C 0D 0E 0F [ 0 0 0 ]
Reading data from block 4 ...
Data in block 4:
01 02 03 04 05 06 07 08 09 0A FF 0B 0C 0D 0E 0F
Authenticating again using key B...
Writing data into block 4 ...
0F 0E 0D 0C 0B 0A 09 08 07 06 05 04 03 02 01 25
Reading data from block 4 ...
Data in block 4:
0F 0E 0D 0C 0B 0A 09 08 07 06 05 04 03 02 01 25
Checking result...
Number of bytes that match = 16
Success :-)
Current data in sector:
1 7 00 00 00 00 00 00 FF 07 80 69 FF FF FF FF FF FF [ 0 0 1 ]
6 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 [ 0 0 0 ]
5 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 [ 0 0 0 ]
4 0F 0E 0D 0C 0B 0A 09 08 07 06 05 04 03 02 01 25 [ 0 0 0 ]
</code></pre></div></div>
<h3 id="système-de-contrôle-daccès-serrure-porte-avec-rfid">Système de contrôle daccès serrure porte avec RFID</h3>
<p>Créons un projet Arduino rapide pour montrer comment un simple module de lecteur RFID RC522 peut être utilisé pour créer un système de contrôle daccès par serrure de porte RFID . Notre programme analysera lidentifiant unique de chaque étiquette RFID lorsquil sera suffisamment proche pour être alimenté par le lecteur RC522. Si lUID de la balise correspond à une valeur prédéfinie (balise principale) stockée dans la mémoire Arduino, laccès sera accordé. Et si nous analysons toute balise inconnue, laccès sera refusé.<br />
<img src="/images/RC522-RFID-Reader-Writer-Door-Lock-Access-Control-Arduino-Project.gif" alt="" /><br />
<em>Sortie du projet Arduino de contrôle daccès de serrure de porte</em></p>
<p>Bien entendu, ce projet pourrait être interfacé pour ouvrir des portes, allumer un relais, allumer une LED ou toute autre chose à laquelle vous pouvez penser.</p>
<p>Si vous nêtes pas familier avec les écrans LCD 16 × 2 caractères, envisagez de lire le didacticiel <a href="https://lastminuteengineers.com/arduino-1602-character-lcd-tutorial/">Interfacing 16×2 Character LCD Module with Arduino</a>.</p>
<p>Avant de télécharger du code et de balayer des balises, examinons le schéma de circuit du projet.</p>
<p><img src="/images/Arduino-Wiring-Fritzing-Connections-with-RC522-RFID-Reader-LCD.jpg" alt="" width="600" /> <br />
<em>Câblage du module graveur de lecteur RC522 RFID avec Arduino UNO et écran LCD 16 × 2 caractères</em></p>
<p>Cest tout! Maintenant, essayez le schéma ci-dessous.</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">#include</span> <span class="cpf">&lt;SPI.h&gt;</span><span class="cp">
#include</span> <span class="cpf">&lt;MFRC522.h&gt;</span><span class="cp">
#include</span> <span class="cpf">&lt;LiquidCrystal.h&gt;</span><span class="cp">
</span>
<span class="cp">#define RST_PIN 9
#define SS_PIN 10
</span>
<span class="n">byte</span> <span class="n">readCard</span><span class="p">[</span><span class="mi">4</span><span class="p">];</span>
<span class="n">String</span> <span class="n">MasterTag</span> <span class="o">=</span> <span class="s">"20C3935E"</span><span class="p">;</span> <span class="c1">// REPLACE this Tag ID with your Tag ID!!!</span>
<span class="n">String</span> <span class="n">tagID</span> <span class="o">=</span> <span class="s">""</span><span class="p">;</span>
<span class="c1">// Create instances</span>
<span class="n">MFRC522</span> <span class="nf">mfrc522</span><span class="p">(</span><span class="n">SS_PIN</span><span class="p">,</span> <span class="n">RST_PIN</span><span class="p">);</span>
<span class="n">LiquidCrystal</span> <span class="nf">lcd</span><span class="p">(</span><span class="mi">7</span><span class="p">,</span> <span class="mi">6</span><span class="p">,</span> <span class="mi">5</span><span class="p">,</span> <span class="mi">4</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">2</span><span class="p">);</span> <span class="c1">//Parameters: (rs, enable, d4, d5, d6, d7) </span>
<span class="kt">void</span> <span class="nf">setup</span><span class="p">()</span>
<span class="p">{</span>
<span class="c1">// Initiating</span>
<span class="n">SPI</span><span class="p">.</span><span class="n">begin</span><span class="p">();</span> <span class="c1">// SPI bus</span>
<span class="n">mfrc522</span><span class="p">.</span><span class="n">PCD_Init</span><span class="p">();</span> <span class="c1">// MFRC522</span>
<span class="n">lcd</span><span class="p">.</span><span class="n">begin</span><span class="p">(</span><span class="mi">16</span><span class="p">,</span> <span class="mi">2</span><span class="p">);</span> <span class="c1">// LCD screen</span>
<span class="n">lcd</span><span class="p">.</span><span class="n">clear</span><span class="p">();</span>
<span class="n">lcd</span><span class="p">.</span><span class="n">print</span><span class="p">(</span><span class="s">" Access Control "</span><span class="p">);</span>
<span class="n">lcd</span><span class="p">.</span><span class="n">setCursor</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">);</span>
<span class="n">lcd</span><span class="p">.</span><span class="n">print</span><span class="p">(</span><span class="s">"Scan Your Card&gt;&gt;"</span><span class="p">);</span>
<span class="p">}</span>
<span class="kt">void</span> <span class="nf">loop</span><span class="p">()</span>
<span class="p">{</span>
<span class="c1">//Wait until new tag is available</span>
<span class="k">while</span> <span class="p">(</span><span class="n">getID</span><span class="p">())</span>
<span class="p">{</span>
<span class="n">lcd</span><span class="p">.</span><span class="n">clear</span><span class="p">();</span>
<span class="n">lcd</span><span class="p">.</span><span class="n">setCursor</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span>
<span class="k">if</span> <span class="p">(</span><span class="n">tagID</span> <span class="o">==</span> <span class="n">MasterTag</span><span class="p">)</span>
<span class="p">{</span>
<span class="n">lcd</span><span class="p">.</span><span class="n">print</span><span class="p">(</span><span class="s">" Access Granted!"</span><span class="p">);</span>
<span class="c1">// You can write any code here like opening doors, switching on a relay, lighting up an LED, or anything else you can think of.</span>
<span class="p">}</span>
<span class="k">else</span>
<span class="p">{</span>
<span class="n">lcd</span><span class="p">.</span><span class="n">print</span><span class="p">(</span><span class="s">" Access Denied!"</span><span class="p">);</span>
<span class="p">}</span>
<span class="n">lcd</span><span class="p">.</span><span class="n">setCursor</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">);</span>
<span class="n">lcd</span><span class="p">.</span><span class="n">print</span><span class="p">(</span><span class="s">" ID : "</span><span class="p">);</span>
<span class="n">lcd</span><span class="p">.</span><span class="n">print</span><span class="p">(</span><span class="n">tagID</span><span class="p">);</span>
<span class="n">delay</span><span class="p">(</span><span class="mi">2000</span><span class="p">);</span>
<span class="n">lcd</span><span class="p">.</span><span class="n">clear</span><span class="p">();</span>
<span class="n">lcd</span><span class="p">.</span><span class="n">print</span><span class="p">(</span><span class="s">" Access Control "</span><span class="p">);</span>
<span class="n">lcd</span><span class="p">.</span><span class="n">setCursor</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">);</span>
<span class="n">lcd</span><span class="p">.</span><span class="n">print</span><span class="p">(</span><span class="s">"Scan Your Card&gt;&gt;"</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="c1">//Read new tag if available</span>
<span class="n">boolean</span> <span class="nf">getID</span><span class="p">()</span>
<span class="p">{</span>
<span class="c1">// Getting ready for Reading PICCs</span>
<span class="k">if</span> <span class="p">(</span> <span class="o">!</span> <span class="n">mfrc522</span><span class="p">.</span><span class="n">PICC_IsNewCardPresent</span><span class="p">())</span> <span class="p">{</span> <span class="c1">//If a new PICC placed to RFID reader continue</span>
<span class="k">return</span> <span class="nb">false</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">if</span> <span class="p">(</span> <span class="o">!</span> <span class="n">mfrc522</span><span class="p">.</span><span class="n">PICC_ReadCardSerial</span><span class="p">())</span> <span class="p">{</span> <span class="c1">//Since a PICC placed get Serial and continue</span>
<span class="k">return</span> <span class="nb">false</span><span class="p">;</span>
<span class="p">}</span>
<span class="n">tagID</span> <span class="o">=</span> <span class="s">""</span><span class="p">;</span>
<span class="k">for</span> <span class="p">(</span> <span class="kt">uint8_t</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="mi">4</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// The MIFARE PICCs that we use have 4 byte UID</span>
<span class="c1">//readCard[i] = mfrc522.uid.uidByte[i];</span>
<span class="n">tagID</span><span class="p">.</span><span class="n">concat</span><span class="p">(</span><span class="n">String</span><span class="p">(</span><span class="n">mfrc522</span><span class="p">.</span><span class="n">uid</span><span class="p">.</span><span class="n">uidByte</span><span class="p">[</span><span class="n">i</span><span class="p">],</span> <span class="n">HEX</span><span class="p">));</span> <span class="c1">// Adds the 4 bytes in a single String variable</span>
<span class="p">}</span>
<span class="n">tagID</span><span class="p">.</span><span class="n">toUpperCase</span><span class="p">();</span>
<span class="n">mfrc522</span><span class="p">.</span><span class="n">PICC_HaltA</span><span class="p">();</span> <span class="c1">// Stop reading</span>
<span class="k">return</span> <span class="nb">true</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<p>Le programme est assez simple. Au début, nous incluons les bibliothèques nécessaires, définissons des broches Arduino, créons des instances dobjets LCD et MFRC522 et définissons une balise principale.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>#include &lt;SPI.h&gt;
#include &lt;MFRC522.h&gt;
#include &lt;LiquidCrystal.h&gt;
#define RST_PIN 9
#define SS_PIN 10
byte readCard[4];
String MasterTag = "20C3935E"; // REPLACE this Tag ID with your Tag ID!!!
String tagID = "";
// Create instances
MFRC522 mfrc522(SS_PIN, RST_PIN);
LiquidCrystal lcd(7, 6, 5, 4, 3, 2); //Parameters: (rs, enable, d4, d5, d6, d7)
</code></pre></div></div>
<p>Dans la fonction de configuration, nous initialisons linterface SPI, lobjet MFRC522 et le LCD. Ensuite, nous imprimons le message de bienvenue sur lécran LCD.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>void setup()
{
// Initiating
SPI.begin(); // SPI bus
mfrc522.PCD_Init(); // MFRC522
lcd.begin(16, 2); // LCD screen
lcd.clear();
lcd.print(" Access Control ");
lcd.setCursor(0, 1);
lcd.print("Scan Your Card&gt;&gt;");
}
</code></pre></div></div>
<p>En boucle, nous attendons que la nouvelle balise soit scannée. Une fois que cela est fait, nous comparons la balise inconnue avec la balise principale définie avant la fonction de configuration. Cest tout! Si son identifiant correspond à lidentifiant principal, laccès est accordé sinon refusé.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>void loop()
{
//Wait until new tag is available
while (getID())
{
lcd.clear();
lcd.setCursor(0, 0);
if (tagID == MasterTag)
{
lcd.print(" Access Granted!");
// You can write any code here like opening doors, switching on a relay, lighting up an LED, or anything else you can think of.
}
else
{
lcd.print(" Access Denied!");
}
lcd.setCursor(0, 1);
lcd.print(" ID : ");
lcd.print(tagID);
delay(2000);
lcd.clear();
lcd.print(" Access Control ");
lcd.setCursor(0, 1);
lcd.print("Scan Your Card&gt;&gt;");
}
}
</code></pre></div></div>
<p>Lessentiel dans le projet est une fonction personnalisée appelée <code class="language-plaintext highlighter-rouge">getID()</code> . Une fois la nouvelle carte recherchée, à lintérieur dune boucle for (<code class="language-plaintext highlighter-rouge">for loop</code>), il convertit 4 octets dUID en chaîne et se concatène pour créer une seule chaîne.</p>
<p><code class="language-plaintext highlighter-rouge">
boolean getID()
{
// Getting ready for Reading PICCs
if ( ! mfrc522.PICC_IsNewCardPresent()) { //If a new PICC placed to RFID reader continue
return false;
}
if ( ! mfrc522.PICC_ReadCardSerial()) { //Since a PICC placed get Serial and continue
return false;
}
tagID = "";
for ( uint8_t i = 0; i &lt; 4; i++) { // The MIFARE PICCs that we use have 4 byte UID
//readCard[i] = mfrc522.uid.uidByte[i];
tagID.concat(String(mfrc522.uid.uidByte[i], HEX)); // Adds the 4 bytes in a single String variable
}
tagID.toUpperCase();
mfrc522.PICC_HaltA(); // Stop reading
return true;
}</code></p>
</div>
<div class="d-print-none"><footer class="article__footer"><meta itemprop="dateModified" content="2019-07-30T00:00:00+02:00"><!-- start custom article footer snippet -->
<!-- end custom article footer snippet -->
<!--
<div align="right"><a type="application/rss+xml" href="/feed.xml" title="S'abonner"><i class="fa fa-rss fa-2x"></i></a>
&emsp;</div>
-->
</footer>
<div class="article__section-navigator clearfix"><div class="previous"><span>PRÉCÉDENT</span><a href="/2019/07/30/Communiquer-entre-RaspberryPi-et-Arduino-en-utilisant-SPI.html">Raspberry Pi + Arduino + SPI</a></div><div class="next"><span>SUIVANT</span><a href="/2019/07/31/Arduino-Ecran-LCD.html">Arduino Ecran LCD</a></div></div></div>
</div>
<script>(function() {
var SOURCES = window.TEXT_VARIABLES.sources;
window.Lazyload.js(SOURCES.jquery, function() {
$(function() {
var $this ,$scroll;
var $articleContent = $('.js-article-content');
var hasSidebar = $('.js-page-root').hasClass('layout--page--sidebar');
var scroll = hasSidebar ? '.js-page-main' : 'html, body';
$scroll = $(scroll);
$articleContent.find('.highlight').each(function() {
$this = $(this);
$this.attr('data-lang', $this.find('code').attr('data-lang'));
});
$articleContent.find('h1[id], h2[id], h3[id], h4[id], h5[id], h6[id]').each(function() {
$this = $(this);
$this.append($('<a class="anchor d-print-none" aria-hidden="true"></a>').html('<i class="fas fa-anchor"></i>'));
});
$articleContent.on('click', '.anchor', function() {
$scroll.scrollToAnchor('#' + $(this).parent().attr('id'), 400);
});
});
});
})();
</script>
</div><section class="page__comments d-print-none"></section></article><!-- start custom main bottom snippet -->
<!-- end custom main bottom snippet -->
</div>
</div></div></div></div>
</div><script>(function() {
var SOURCES = window.TEXT_VARIABLES.sources;
window.Lazyload.js(SOURCES.jquery, function() {
var $body = $('body'), $window = $(window);
var $pageRoot = $('.js-page-root'), $pageMain = $('.js-page-main');
var activeCount = 0;
function modal(options) {
var $root = this, visible, onChange, hideWhenWindowScroll = false;
var scrollTop;
function setOptions(options) {
var _options = options || {};
visible = _options.initialVisible === undefined ? false : show;
onChange = _options.onChange;
hideWhenWindowScroll = _options.hideWhenWindowScroll;
}
function init() {
setState(visible);
}
function setState(isShow) {
if (isShow === visible) {
return;
}
visible = isShow;
if (visible) {
activeCount++;
scrollTop = $(window).scrollTop() || $pageMain.scrollTop();
$root.addClass('modal--show');
$pageMain.scrollTop(scrollTop);
activeCount === 1 && ($pageRoot.addClass('show-modal'), $body.addClass('of-hidden'));
hideWhenWindowScroll && window.hasEvent('touchstart') && $window.on('scroll', hide);
$window.on('keyup', handleKeyup);
} else {
activeCount > 0 && activeCount--;
$root.removeClass('modal--show');
$window.scrollTop(scrollTop);
activeCount === 0 && ($pageRoot.removeClass('show-modal'), $body.removeClass('of-hidden'));
hideWhenWindowScroll && window.hasEvent('touchstart') && $window.off('scroll', hide);
$window.off('keyup', handleKeyup);
}
onChange && onChange(visible);
}
function show() {
setState(true);
}
function hide() {
setState(false);
}
function handleKeyup(e) {
// Char Code: 27 ESC
if (e.which === 27) {
hide();
}
}
setOptions(options);
init();
return {
show: show,
hide: hide,
$el: $root
};
}
$.fn.modal = modal;
});
})();
</script><div class="modal modal--overflow page__search-modal d-print-none js-page-search-modal"><script>
(function () {
var SOURCES = window.TEXT_VARIABLES.sources;
window.Lazyload.js(SOURCES.jquery, function() {
// search panel
var search = (window.search || (window.search = {}));
var useDefaultSearchBox = window.useDefaultSearchBox === undefined ?
true : window.useDefaultSearchBox ;
var $searchModal = $('.js-page-search-modal');
var $searchToggle = $('.js-search-toggle');
var searchModal = $searchModal.modal({ onChange: handleModalChange, hideWhenWindowScroll: true });
var modalVisible = false;
search.searchModal = searchModal;
var $searchBox = null;
var $searchInput = null;
var $searchClear = null;
function getModalVisible() {
return modalVisible;
}
search.getModalVisible = getModalVisible;
function handleModalChange(visible) {
modalVisible = visible;
if (visible) {
search.onShow && search.onShow();
useDefaultSearchBox && $searchInput[0] && $searchInput[0].focus();
} else {
search.onShow && search.onHide();
useDefaultSearchBox && $searchInput[0] && $searchInput[0].blur();
setTimeout(function() {
useDefaultSearchBox && ($searchInput.val(''), $searchBox.removeClass('not-empty'));
search.clear && search.clear();
window.pageAsideAffix && window.pageAsideAffix.refresh();
}, 400);
}
}
$searchToggle.on('click', function() {
modalVisible ? searchModal.hide() : searchModal.show();
});
// Char Code: 83 S, 191 /
$(window).on('keyup', function(e) {
if (!modalVisible && !window.isFormElement(e.target || e.srcElement) && (e.which === 83 || e.which === 191)) {
modalVisible || searchModal.show();
}
});
if (useDefaultSearchBox) {
$searchBox = $('.js-search-box');
$searchInput = $searchBox.children('input');
$searchClear = $searchBox.children('.js-icon-clear');
search.getSearchInput = function() {
return $searchInput.get(0);
};
search.getVal = function() {
return $searchInput.val();
};
search.setVal = function(val) {
$searchInput.val(val);
};
$searchInput.on('focus', function() {
$(this).addClass('focus');
});
$searchInput.on('blur', function() {
$(this).removeClass('focus');
});
$searchInput.on('input', window.throttle(function() {
var val = $(this).val();
if (val === '' || typeof val !== 'string') {
search.clear && search.clear();
} else {
$searchBox.addClass('not-empty');
search.onInputNotEmpty && search.onInputNotEmpty(val);
}
}, 400));
$searchClear.on('click', function() {
$searchInput.val(''); $searchBox.removeClass('not-empty');
search.clear && search.clear();
});
}
});
})();
</script><div class="search search--dark">
<div class="main">
<div class="search__header">Recherche</div>
<div class="search-bar">
<div class="search-box js-search-box">
<div class="search-box__icon-search"><i class="fas fa-search"></i></div>
<input id="search-input" type="text" />
<div class="search-box__icon-clear js-icon-clear">
<a><i class="fas fa-times"></i></a>
</div>
</div>
<button class="button button--theme-dark button--pill search__cancel js-search-toggle">
Annuler</button>
</div>
<div id="results-container" class="search-result js-search-result"></div>
</div>
</div>
<!-- Script pointing to search-script.js -->
<script>/*!
* Simple-Jekyll-Search
* Copyright 2015-2020, Christian Fei
* Licensed under the MIT License.
*/
(function(){
'use strict'
var _$Templater_7 = {
compile: compile,
setOptions: setOptions
}
const options = {}
options.pattern = /\{(.*?)\}/g
options.template = ''
options.middleware = function () {}
function setOptions (_options) {
options.pattern = _options.pattern || options.pattern
options.template = _options.template || options.template
if (typeof _options.middleware === 'function') {
options.middleware = _options.middleware
}
}
function compile (data) {
return options.template.replace(options.pattern, function (match, prop) {
const value = options.middleware(prop, data[prop], options.template)
if (typeof value !== 'undefined') {
return value
}
return data[prop] || match
})
}
'use strict';
function fuzzysearch (needle, haystack) {
var tlen = haystack.length;
var qlen = needle.length;
if (qlen > tlen) {
return false;
}
if (qlen === tlen) {
return needle === haystack;
}
outer: for (var i = 0, j = 0; i < qlen; i++) {
var nch = needle.charCodeAt(i);
while (j < tlen) {
if (haystack.charCodeAt(j++) === nch) {
continue outer;
}
}
return false;
}
return true;
}
var _$fuzzysearch_1 = fuzzysearch;
'use strict'
/* removed: const _$fuzzysearch_1 = require('fuzzysearch') */;
var _$FuzzySearchStrategy_5 = new FuzzySearchStrategy()
function FuzzySearchStrategy () {
this.matches = function (string, crit) {
return _$fuzzysearch_1(crit.toLowerCase(), string.toLowerCase())
}
}
'use strict'
var _$LiteralSearchStrategy_6 = new LiteralSearchStrategy()
function LiteralSearchStrategy () {
this.matches = function (str, crit) {
if (!str) return false
str = str.trim().toLowerCase()
crit = crit.trim().toLowerCase()
return crit.split(' ').filter(function (word) {
return str.indexOf(word) >= 0
}).length === crit.split(' ').length
}
}
'use strict'
var _$Repository_4 = {
put: put,
clear: clear,
search: search,
setOptions: __setOptions_4
}
/* removed: const _$FuzzySearchStrategy_5 = require('./SearchStrategies/FuzzySearchStrategy') */;
/* removed: const _$LiteralSearchStrategy_6 = require('./SearchStrategies/LiteralSearchStrategy') */;
function NoSort () {
return 0
}
const data = []
let opt = {}
opt.fuzzy = false
opt.limit = 10
opt.searchStrategy = opt.fuzzy ? _$FuzzySearchStrategy_5 : _$LiteralSearchStrategy_6
opt.sort = NoSort
opt.exclude = []
function put (data) {
if (isObject(data)) {
return addObject(data)
}
if (isArray(data)) {
return addArray(data)
}
return undefined
}
function clear () {
data.length = 0
return data
}
function isObject (obj) {
return Boolean(obj) && Object.prototype.toString.call(obj) === '[object Object]'
}
function isArray (obj) {
return Boolean(obj) && Object.prototype.toString.call(obj) === '[object Array]'
}
function addObject (_data) {
data.push(_data)
return data
}
function addArray (_data) {
const added = []
clear()
for (let i = 0, len = _data.length; i < len; i++) {
if (isObject(_data[i])) {
added.push(addObject(_data[i]))
}
}
return added
}
function search (crit) {
if (!crit) {
return []
}
return findMatches(data, crit, opt.searchStrategy, opt).sort(opt.sort)
}
function __setOptions_4 (_opt) {
opt = _opt || {}
opt.fuzzy = _opt.fuzzy || false
opt.limit = _opt.limit || 10
opt.searchStrategy = _opt.fuzzy ? _$FuzzySearchStrategy_5 : _$LiteralSearchStrategy_6
opt.sort = _opt.sort || NoSort
opt.exclude = _opt.exclude || []
}
function findMatches (data, crit, strategy, opt) {
const matches = []
for (let i = 0; i < data.length && matches.length < opt.limit; i++) {
const match = findMatchesInObject(data[i], crit, strategy, opt)
if (match) {
matches.push(match)
}
}
return matches
}
function findMatchesInObject (obj, crit, strategy, opt) {
for (const key in obj) {
if (!isExcluded(obj[key], opt.exclude) && strategy.matches(obj[key], crit)) {
return obj
}
}
}
function isExcluded (term, excludedTerms) {
for (let i = 0, len = excludedTerms.length; i < len; i++) {
const excludedTerm = excludedTerms[i]
if (new RegExp(excludedTerm).test(term)) {
return true
}
}
return false
}
/* globals ActiveXObject:false */
'use strict'
var _$JSONLoader_2 = {
load: load
}
function load (location, callback) {
const xhr = getXHR()
xhr.open('GET', location, true)
xhr.onreadystatechange = createStateChangeListener(xhr, callback)
xhr.send()
}
function createStateChangeListener (xhr, callback) {
return function () {
if (xhr.readyState === 4 && xhr.status === 200) {
try {
callback(null, JSON.parse(xhr.responseText))
} catch (err) {
callback(err, null)
}
}
}
}
function getXHR () {
return window.XMLHttpRequest ? new window.XMLHttpRequest() : new ActiveXObject('Microsoft.XMLHTTP')
}
'use strict'
var _$OptionsValidator_3 = function OptionsValidator (params) {
if (!validateParams(params)) {
throw new Error('-- OptionsValidator: required options missing')
}
if (!(this instanceof OptionsValidator)) {
return new OptionsValidator(params)
}
const requiredOptions = params.required
this.getRequiredOptions = function () {
return requiredOptions
}
this.validate = function (parameters) {
const errors = []
requiredOptions.forEach(function (requiredOptionName) {
if (typeof parameters[requiredOptionName] === 'undefined') {
errors.push(requiredOptionName)
}
})
return errors
}
function validateParams (params) {
if (!params) {
return false
}
return typeof params.required !== 'undefined' && params.required instanceof Array
}
}
'use strict'
var _$utils_9 = {
merge: merge,
isJSON: isJSON
}
function merge (defaultParams, mergeParams) {
const mergedOptions = {}
for (const option in defaultParams) {
mergedOptions[option] = defaultParams[option]
if (typeof mergeParams[option] !== 'undefined') {
mergedOptions[option] = mergeParams[option]
}
}
return mergedOptions
}
function isJSON (json) {
try {
if (json instanceof Object && JSON.parse(JSON.stringify(json))) {
return true
}
return false
} catch (err) {
return false
}
}
var _$src_8 = {};
(function (window) {
'use strict'
let options = {
searchInput: null,
resultsContainer: null,
json: [],
success: Function.prototype,
searchResultTemplate: '<li><a href="{url}" title="{desc}">{title}</a></li>',
templateMiddleware: Function.prototype,
sortMiddleware: function () {
return 0
},
noResultsText: 'No results found',
limit: 10,
fuzzy: false,
debounceTime: null,
exclude: []
}
let debounceTimerHandle
const debounce = function (func, delayMillis) {
if (delayMillis) {
clearTimeout(debounceTimerHandle)
debounceTimerHandle = setTimeout(func, delayMillis)
} else {
func.call()
}
}
const requiredOptions = ['searchInput', 'resultsContainer', 'json']
/* removed: const _$Templater_7 = require('./Templater') */;
/* removed: const _$Repository_4 = require('./Repository') */;
/* removed: const _$JSONLoader_2 = require('./JSONLoader') */;
const optionsValidator = _$OptionsValidator_3({
required: requiredOptions
})
/* removed: const _$utils_9 = require('./utils') */;
window.SimpleJekyllSearch = function (_options) {
const errors = optionsValidator.validate(_options)
if (errors.length > 0) {
throwError('You must specify the following required options: ' + requiredOptions)
}
options = _$utils_9.merge(options, _options)
_$Templater_7.setOptions({
template: options.searchResultTemplate,
middleware: options.templateMiddleware
})
_$Repository_4.setOptions({
fuzzy: options.fuzzy,
limit: options.limit,
sort: options.sortMiddleware,
exclude: options.exclude
})
if (_$utils_9.isJSON(options.json)) {
initWithJSON(options.json)
} else {
initWithURL(options.json)
}
const rv = {
search: search
}
typeof options.success === 'function' && options.success.call(rv)
return rv
}
function initWithJSON (json) {
_$Repository_4.put(json)
registerInput()
}
function initWithURL (url) {
_$JSONLoader_2.load(url, function (err, json) {
if (err) {
throwError('failed to get JSON (' + url + ')')
}
initWithJSON(json)
})
}
function emptyResultsContainer () {
options.resultsContainer.innerHTML = ''
}
function appendToResultsContainer (text) {
options.resultsContainer.innerHTML += text
}
function registerInput () {
options.searchInput.addEventListener('input', function (e) {
if (isWhitelistedKey(e.which)) {
emptyResultsContainer()
debounce(function () { search(e.target.value) }, options.debounceTime)
}
})
}
function search (query) {
if (isValidQuery(query)) {
emptyResultsContainer()
render(_$Repository_4.search(query), query)
}
}
function render (results, query) {
const len = results.length
if (len === 0) {
return appendToResultsContainer(options.noResultsText)
}
for (let i = 0; i < len; i++) {
results[i].query = query
appendToResultsContainer(_$Templater_7.compile(results[i]))
}
}
function isValidQuery (query) {
return query && query.length > 0
}
function isWhitelistedKey (key) {
return [13, 16, 20, 37, 38, 39, 40, 91].indexOf(key) === -1
}
function throwError (message) {
throw new Error('SimpleJekyllSearch --- ' + message)
}
})(window)
}());
</script>
<!-- Configuration -->
<script>
SimpleJekyllSearch({
searchInput: document.getElementById('search-input'),
resultsContainer: document.getElementById('results-container'),
noResultsText: '<p>Aucun résultat!</p>',
json: '/search.json',
searchResultTemplate: '<li><a href="{url}">{date}&nbsp;{title}</a>&nbsp;(Création {create})</li>'
})
</script>
</div></div>
<script>(function() {
var SOURCES = window.TEXT_VARIABLES.sources;
window.Lazyload.js(SOURCES.jquery, function() {
function scrollToAnchor(anchor, duration, callback) {
var $root = this;
$root.animate({ scrollTop: $(anchor).position().top }, duration, function() {
window.history.replaceState(null, '', window.location.href.split('#')[0] + anchor);
callback && callback();
});
}
$.fn.scrollToAnchor = scrollToAnchor;
});
})();
(function() {
var SOURCES = window.TEXT_VARIABLES.sources;
window.Lazyload.js(SOURCES.jquery, function() {
function affix(options) {
var $root = this, $window = $(window), $scrollTarget, $scroll,
offsetBottom = 0, scrollTarget = window, scroll = window.document, disabled = false, isOverallScroller = true,
rootTop, rootLeft, rootHeight, scrollBottom, rootBottomTop,
hasInit = false, curState;
function setOptions(options) {
var _options = options || {};
_options.offsetBottom && (offsetBottom = _options.offsetBottom);
_options.scrollTarget && (scrollTarget = _options.scrollTarget);
_options.scroll && (scroll = _options.scroll);
_options.disabled !== undefined && (disabled = _options.disabled);
$scrollTarget = $(scrollTarget);
isOverallScroller = window.isOverallScroller($scrollTarget[0]);
$scroll = $(scroll);
}
function preCalc() {
top();
rootHeight = $root.outerHeight();
rootTop = $root.offset().top + (isOverallScroller ? 0 : $scrollTarget.scrollTop());
rootLeft = $root.offset().left;
}
function calc(needPreCalc) {
needPreCalc && preCalc();
scrollBottom = $scroll.outerHeight() - offsetBottom - rootHeight;
rootBottomTop = scrollBottom - rootTop;
}
function top() {
if (curState !== 'top') {
$root.removeClass('fixed').css({
left: 0,
top: 0
});
curState = 'top';
}
}
function fixed() {
if (curState !== 'fixed') {
$root.addClass('fixed').css({
left: rootLeft + 'px',
top: 0
});
curState = 'fixed';
}
}
function bottom() {
if (curState !== 'bottom') {
$root.removeClass('fixed').css({
left: 0,
top: rootBottomTop + 'px'
});
curState = 'bottom';
}
}
function setState() {
var scrollTop = $scrollTarget.scrollTop();
if (scrollTop >= rootTop && scrollTop <= scrollBottom) {
fixed();
} else if (scrollTop < rootTop) {
top();
} else {
bottom();
}
}
function init() {
if(!hasInit) {
var interval, timeout;
calc(true); setState();
// run calc every 100 millisecond
interval = setInterval(function() {
calc();
}, 100);
timeout = setTimeout(function() {
clearInterval(interval);
}, 45000);
window.pageLoad.then(function() {
setTimeout(function() {
clearInterval(interval);
clearTimeout(timeout);
}, 3000);
});
$scrollTarget.on('scroll', function() {
disabled || setState();
});
$window.on('resize', function() {
disabled || (calc(true), setState());
});
hasInit = true;
}
}
setOptions(options);
if (!disabled) {
init();
}
$window.on('resize', window.throttle(function() {
init();
}, 200));
return {
setOptions: setOptions,
refresh: function() {
calc(true, { animation: false }); setState();
}
};
}
$.fn.affix = affix;
});
})();
(function() {
var SOURCES = window.TEXT_VARIABLES.sources;
window.Lazyload.js(SOURCES.jquery, function() {
function toc(options) {
var $root = this, $window = $(window), $scrollTarget, $scroller, $tocUl = $('<ul class="toc toc--ellipsis"></ul>'), $tocLi, $headings, $activeLast, $activeCur,
selectors = 'h1,h2,h3', container = 'body', scrollTarget = window, scroller = 'html, body', disabled = false,
headingsPos, scrolling = false, hasRendered = false, hasInit = false;
function setOptions(options) {
var _options = options || {};
_options.selectors && (selectors = _options.selectors);
_options.container && (container = _options.container);
_options.scrollTarget && (scrollTarget = _options.scrollTarget);
_options.scroller && (scroller = _options.scroller);
_options.disabled !== undefined && (disabled = _options.disabled);
$headings = $(container).find(selectors).filter('[id]');
$scrollTarget = $(scrollTarget);
$scroller = $(scroller);
}
function calc() {
headingsPos = [];
$headings.each(function() {
headingsPos.push(Math.floor($(this).position().top));
});
}
function setState(element, disabled) {
var scrollTop = $scrollTarget.scrollTop(), i;
if (disabled || !headingsPos || headingsPos.length < 1) { return; }
if (element) {
$activeCur = element;
} else {
for (i = 0; i < headingsPos.length; i++) {
if (scrollTop >= headingsPos[i]) {
$activeCur = $tocLi.eq(i);
} else {
$activeCur || ($activeCur = $tocLi.eq(i));
break;
}
}
}
$activeLast && $activeLast.removeClass('active');
($activeLast = $activeCur).addClass('active');
}
function render() {
if(!hasRendered) {
$root.append($tocUl);
$headings.each(function() {
var $this = $(this);
$tocUl.append($('<li></li>').addClass('toc-' + $this.prop('tagName').toLowerCase())
.append($('<a></a>').text($this.text()).attr('href', '#' + $this.prop('id'))));
});
$tocLi = $tocUl.children('li');
$tocUl.on('click', 'a', function(e) {
e.preventDefault();
var $this = $(this);
scrolling = true;
setState($this.parent());
$scroller.scrollToAnchor($this.attr('href'), 400, function() {
scrolling = false;
});
});
}
hasRendered = true;
}
function init() {
var interval, timeout;
if(!hasInit) {
render(); calc(); setState(null, scrolling);
// run calc every 100 millisecond
interval = setInterval(function() {
calc();
}, 100);
timeout = setTimeout(function() {
clearInterval(interval);
}, 45000);
window.pageLoad.then(function() {
setTimeout(function() {
clearInterval(interval);
clearTimeout(timeout);
}, 3000);
});
$scrollTarget.on('scroll', function() {
disabled || setState(null, scrolling);
});
$window.on('resize', window.throttle(function() {
if (!disabled) {
render(); calc(); setState(null, scrolling);
}
}, 100));
}
hasInit = true;
}
setOptions(options);
if (!disabled) {
init();
}
$window.on('resize', window.throttle(function() {
init();
}, 200));
return {
setOptions: setOptions
};
}
$.fn.toc = toc;
});
})();
/*(function () {
})();*/
</script><script>
/* toc must before affix, since affix need to konw toc' height. */(function() {
var SOURCES = window.TEXT_VARIABLES.sources;
var TOC_SELECTOR = window.TEXT_VARIABLES.site.toc.selectors;
window.Lazyload.js(SOURCES.jquery, function() {
var $window = $(window);
var $articleContent = $('.js-article-content');
var $tocRoot = $('.js-toc-root'), $col2 = $('.js-col-aside');
var toc;
var tocDisabled = false;
var hasSidebar = $('.js-page-root').hasClass('layout--page--sidebar');
var hasToc = $articleContent.find(TOC_SELECTOR).length > 0;
function disabled() {
return $col2.css('display') === 'none' || !hasToc;
}
tocDisabled = disabled();
toc = $tocRoot.toc({
selectors: TOC_SELECTOR,
container: $articleContent,
scrollTarget: hasSidebar ? '.js-page-main' : null,
scroller: hasSidebar ? '.js-page-main' : null,
disabled: tocDisabled
});
$window.on('resize', window.throttle(function() {
tocDisabled = disabled();
toc && toc.setOptions({
disabled: tocDisabled
});
}, 100));
});
})();
(function() {
var SOURCES = window.TEXT_VARIABLES.sources;
window.Lazyload.js(SOURCES.jquery, function() {
var $window = $(window), $pageFooter = $('.js-page-footer');
var $pageAside = $('.js-page-aside');
var affix;
var tocDisabled = false;
var hasSidebar = $('.js-page-root').hasClass('layout--page--sidebar');
affix = $pageAside.affix({
offsetBottom: $pageFooter.outerHeight(),
scrollTarget: hasSidebar ? '.js-page-main' : null,
scroller: hasSidebar ? '.js-page-main' : null,
scroll: hasSidebar ? $('.js-page-main').children() : null,
disabled: tocDisabled
});
$window.on('resize', window.throttle(function() {
affix && affix.setOptions({
disabled: tocDisabled
});
}, 100));
window.pageAsideAffix = affix;
});
})();
</script><!---->
</div>
<script>(function () {
var $root = document.getElementsByClassName('root')[0];
if (window.hasEvent('touchstart')) {
$root.dataset.isTouch = true;
document.addEventListener('touchstart', function(){}, false);
}
})();
</script>
</body>
</html>