yannstatic/static/2019/03/15/Olimex-A20-OlinuxIno-Micro-Compilation-Kernel-Debian-Stretch-GPIO.html

3272 lines
252 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>Olimex A20-OlinuxIno-Micro Kernel compilé + Debian 9 + GPIO - YannStatic</title>
<meta name="description" content="Carte olimex A20-OlinuxIno-Micro">
<link rel="canonical" href="https://static.rnmkcy.eu/2019/03/15/Olimex-A20-OlinuxIno-Micro-Compilation-Kernel-Debian-Stretch-GPIO.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;">Olimex A20-OlinuxIno-Micro Kernel compilé + Debian 9 + GPIO</h1></header></div><meta itemprop="headline" content="Olimex A20-OlinuxIno-Micro Kernel compilé + Debian 9 + GPIO"><div class="article__info clearfix"><ul class="left-col menu"><li>
<a class="button button--secondary button--pill button--sm"
href="/archive.html?tag=olimex">olimex</a>
</li></ul><ul class="right-col menu"><li>
<i class="far fa-calendar-alt"></i>&nbsp;<span title="Création" style="color:#FF00FF">15&nbsp;mars&nbsp;&nbsp;2019</span></li></ul></div><meta itemprop="datePublished" content="2019-03-15T00:00:00+01:00">
<meta itemprop="keywords" content="olimex"><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="carte-olimex-a20-olinuxino-micro">Carte olimex A20-OlinuxIno-Micro</h2>
<p><a href="https://www.olimex.com/Products/OLinuXino/A20/A20-OLinuXino-MICRO-4GB/resources/A20-OLinuXino-Micro.pdf">Documentation olimex</a></p>
<p><img src="/images/A20-olinuxino-micro-top.png" alt="alt text" title="Top view" /><br />
<img src="/images/A20-olinuxino-micro-bottom.png" alt="alt text" title="Bottom view" width="50%" /><br />
<a href="/files/a20-olinuxino-micro.jpg">Hardware</a></p>
<p><strong>Matériel</strong></p>
<ul>
<li>Carte olimex <a href="/files/A20-OLinuXino-Micro.pdf">A20-OLinuXino-MICRO </a></li>
<li>Bloc Alimentation 10V 1A</li>
<li>Carte micro SD min 4GO</li>
<li>SSD</li>
<li>Batterie Li-ion 3.7v 5000mAh</li>
</ul>
<p><strong>Liens</strong></p>
<ul>
<li><a href="https://www.denx.de/wiki/U-Boot">U-Boot wiki</a></li>
<li><a href="http://linux-sunxi.org/Device_Tree">Device Tree</a></li>
<li><a href="https://wiki.debian.org/InstallingDebianOn/Allwinner">Installing Debian On Allwinner</a></li>
<li><a href="https://en.opensuse.org/HCL:A20-OLinuXino-MICRO">HCL:A20-OLinuXino-MICRO</a></li>
<li><a href="https://saintgimp.org/2017/11/05/add-a-real-time-clock-to-a-beaglebone-black/">Add a real-time clock to a Beaglebone Black</a></li>
<li><a href="https://docs.armbian.com/User-Guide_Allwinner_overlays/">Armbian Device Tree overlays</a></li>
<li><a href="https://github.com/armbian/sunxi-DT-overlays/tree/master/examples">sunxi-DT-overlays</a></li>
<li><a href="https://www.olimex.com/forum/index.php?topic=3809.0"> Topic: [HowTo] Enable full duplex SPI </a></li>
<li><a href="http://linux-sunxi.org/SPIdev#Example_for_A10s_Olinuxino_Micro_UEXT_connector">SPIdev</a></li>
</ul>
<h2 id="compilation-kernel--debian-stretch">Compilation kernel + Debian Stretch</h2>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code> ____ _ _ _ _
/ ___|___ _ __ ___ _ __ (_) | __ _| |_(_) ___ _ __
| | / _ \| '_ ` _ \| '_ \| | |/ _` | __| |/ _ \| '_ \
| |__| (_) | | | | | | |_) | | | (_| | |_| | (_) | | | |
\____\___/|_| |_| |_| .__/|_|_|\__,_|\__|_|\___/|_| |_|
|_|
_ _
| | _____ _ __ _ __ ___| |
| |/ / _ \ '__| '_ \ / _ \ |
| &lt; __/ | | | | | __/ |
|_|\_\___|_| |_| |_|\___|_|
</code></pre></div></div>
<p>Compilation noyau linux pour processeur arm <a href="https://www.digikey.com/eewiki/display/linuxonarm/A20-OLinuXino-LIME">Carte olimex A20-OLinuXino-LIME et (MICRO)</a></p>
<p>Création dossier sur ~/media/dplus</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># aller dans le dossier</span>
<span class="nb">cd</span> ~/media/dplus/A20-OLinuXino-MICRO/
<span class="c"># ARM Cross Compiler: GCC</span>
<span class="c">#This is a pre-built (64bit) version of Linaro GCC that runs on generic linux, sorry (32bit) x86 users, it's time to upgrade...</span>
wget <span class="nt">-c</span> https://releases.linaro.org/components/toolchain/binaries/6.4-2018.05/arm-linux-gnueabihf/gcc-linaro-6.4.1-2018.05-x86_64_arm-linux-gnueabihf.tar.xz
<span class="nb">tar </span>xf gcc-linaro-6.4.1-2018.05-x86_64_arm-linux-gnueabihf.tar.xz
<span class="c">#</span>
<span class="nb">export </span><span class="nv">CC</span><span class="o">=</span><span class="sb">`</span><span class="nb">pwd</span><span class="sb">`</span>/gcc-linaro-6.4.1-2018.05-x86_64_arm-linux-gnueabihf/bin/arm-linux-gnueabihf-
<span class="nb">export </span><span class="nv">CC</span><span class="o">=</span>/home/yannick/media/dplus/A20-OLinuXino-MICRO/gcc-linaro-6.4.1-2018.05-x86_64_arm-linux-gnueabihf/bin/arm-linux-gnueabihf-
<span class="c">#Test Cross Compiler:</span>
<span class="k">${</span><span class="nv">CC</span><span class="k">}</span>gcc <span class="nt">--version</span>
<span class="c"># arm-linux-gnueabihf-gcc (Linaro GCC 6.4-2018.05) 6.4.1 20180425</span>
<span class="c"># Copyright (C) 2017 Free Software Foundation, Inc.</span>
<span class="c"># This is free software; see the source for copying conditions. There is NO</span>
<span class="c"># warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.</span>
<span class="c"># Das U-Boot the Universal Boot Loader: http://www.denx.de/wiki/U-Boot</span>
git clone https://github.com/u-boot/u-boot
<span class="nb">cd </span>u-boot/
git checkout v2019.01 <span class="nt">-b</span> tmp
<span class="c"># A20-OLinuXino-MICRO</span>
make <span class="nv">ARCH</span><span class="o">=</span>arm <span class="nv">CROSS_COMPILE</span><span class="o">=</span><span class="k">${</span><span class="nv">CC</span><span class="k">}</span> distclean
make <span class="nv">ARCH</span><span class="o">=</span>arm <span class="nv">CROSS_COMPILE</span><span class="o">=</span><span class="k">${</span><span class="nv">CC</span><span class="k">}</span> A20-OLinuXino_MICRO_defconfig
make <span class="nv">ARCH</span><span class="o">=</span>arm <span class="nv">CROSS_COMPILE</span><span class="o">=</span><span class="k">${</span><span class="nv">CC</span><span class="k">}</span>
<span class="c">#If you see the following error when compiling on Arch Linux arm : "ImportError: No module named _libfdt" </span>
<span class="c"># install dtc , sudo pacman -S dtc</span>
<span class="c"># This script will build the kernel, modules, device tree binaries and copy them to the deploy directory.</span>
<span class="nb">cd</span> ..
git clone https://github.com/RobertCNelson/armv7-lpae-multiplatform
<span class="nb">cd </span>armv7-lpae-multiplatform/
<span class="c"># For v4.17.x (Stable):</span>
git checkout origin/v4.17.x <span class="nt">-b</span> tmp
<span class="c"># Build:</span>
./build_kernel.sh
<span class="c"># https://www.linuxtopia.org/online_books/linux_kernel/kernel_configuration/ch09s05.html</span>
<span class="c"># lvm dans le kernel</span>
<span class="c"># Root File System</span>
<span class="c"># Debian 9 debian/temppwd root/root</span>
<span class="nb">cd</span> ..
wget <span class="nt">-c</span> https://rcn-ee.com/rootfs/eewiki/minfs/debian-9.8-minimal-armhf-2019-02-16.tar.xz
wget <span class="nt">-c</span> https://rcn-ee.com/rootfs/eewiki/minfs/debian-9.8-minimal-armhf-2019-02-16.tar.xz.sha256sum
<span class="c"># Verify:</span>
<span class="nb">sha256sum </span>debian-9.8-minimal-armhf-2019-02-16.tar.xz
<span class="c"># Extract:</span>
<span class="nb">tar </span>xf debian-9.8-minimal-armhf-2019-02-16.tar.xz
<span class="c"># Préparer SDcard</span>
<span class="c"># For these instruction we are assuming, DISK=/dev/mmcblk0, lsblk is very useful for determining the device id.</span>
<span class="nb">export </span><span class="nv">DISK</span><span class="o">=</span>/dev/sde
<span class="c">#Erase partition table/labels on microSD card:</span>
<span class="nb">sudo dd </span><span class="k">if</span><span class="o">=</span>/dev/zero <span class="nv">of</span><span class="o">=</span><span class="k">${</span><span class="nv">DISK</span><span class="k">}</span> <span class="nv">bs</span><span class="o">=</span>1M <span class="nv">count</span><span class="o">=</span>10
<span class="c">#Install Bootloader:</span>
<span class="nb">sudo dd </span><span class="k">if</span><span class="o">=</span>./u-boot/u-boot-sunxi-with-spl.bin <span class="nv">of</span><span class="o">=</span><span class="k">${</span><span class="nv">DISK</span><span class="k">}</span> <span class="nv">seek</span><span class="o">=</span>8 <span class="nv">bs</span><span class="o">=</span>1024
<span class="c">#Create Partition Layout:</span>
<span class="c">#With util-linux v2.26, sfdisk was rewritten and is now based on libfdisk.</span>
<span class="c">#sudo sfdisk --version</span>
<span class="c">#sfdisk from util-linux 2.27.1</span>
<span class="c">#sfdisk &gt;= 2.26.x</span>
<span class="nb">sudo </span>sfdisk <span class="k">${</span><span class="nv">DISK</span><span class="k">}</span> <span class="o">&lt;&lt;-</span><span class="no">__EOF__</span><span class="sh">
1M,,L,*
</span><span class="no">__EOF__
</span><span class="c">#Format Partition:</span>
<span class="c">#for: DISK=/dev/sdX</span>
<span class="nb">sudo </span>mkfs.ext4 <span class="nt">-L</span> rootfs <span class="k">${</span><span class="nv">DISK</span><span class="k">}</span>1
<span class="c">#Mount Partition:</span>
<span class="c">#On most systems these partitions may will be auto-mounted...</span>
<span class="nb">sudo mkdir</span> <span class="nt">-p</span> /media/rootfs/
<span class="c">#for: DISK=/dev/sdX</span>
<span class="nb">sudo </span>mount <span class="k">${</span><span class="nv">DISK</span><span class="k">}</span>1 /media/rootfs/
<span class="c"># version kernel</span>
<span class="nb">export </span><span class="nv">kernel_version</span><span class="o">=</span><span class="si">$(</span><span class="nb">cat </span>armv7-lpae-multiplatform/kernel_version<span class="si">)</span>
<span class="c"># copie root file system</span>
<span class="nb">sudo tar </span>xfvp ./<span class="k">*</span>-<span class="k">*</span>-<span class="k">*</span><span class="nt">-armhf-</span><span class="k">*</span>/armhf-rootfs-<span class="k">*</span>.tar <span class="nt">-C</span> /media/rootfs/
<span class="nb">sync
sudo chown </span>root:root /media/rootfs/
<span class="nb">sudo chmod </span>755 /media/rootfs/
<span class="c"># Setup extlinux.conf</span>
<span class="nb">sudo mkdir</span> <span class="nt">-p</span> /media/rootfs/boot/extlinux/
<span class="nb">sudo </span>sh <span class="nt">-c</span> <span class="s2">"echo 'label Linux </span><span class="k">${</span><span class="nv">kernel_version</span><span class="k">}</span><span class="s2">' &gt; /media/rootfs/boot/extlinux/extlinux.conf"</span>
<span class="nb">sudo </span>sh <span class="nt">-c</span> <span class="s2">"echo ' kernel /boot/vmlinuz-</span><span class="k">${</span><span class="nv">kernel_version</span><span class="k">}</span><span class="s2">' &gt;&gt; /media/rootfs/boot/extlinux/extlinux.conf"</span>
<span class="nb">sudo </span>sh <span class="nt">-c</span> <span class="s2">"echo ' append root=/dev/mmcblk0p1 ro rootfstype=ext4 rootwait quiet' &gt;&gt; /media/rootfs/boot/extlinux/extlinux.conf"</span>
<span class="nb">sudo </span>sh <span class="nt">-c</span> <span class="s2">"echo ' fdtdir /boot/dtbs/</span><span class="k">${</span><span class="nv">kernel_version</span><span class="k">}</span><span class="s2">/' &gt;&gt; /media/rootfs/boot/extlinux/extlinux.conf"</span>
<span class="c">#Copy Kernel Image</span>
<span class="c">#Kernel Image:</span>
<span class="nb">sudo cp</span> <span class="nt">-v</span> ./armv7-lpae-multiplatform/deploy/<span class="k">${</span><span class="nv">kernel_version</span><span class="k">}</span>.zImage /media/rootfs/boot/vmlinuz-<span class="k">${</span><span class="nv">kernel_version</span><span class="k">}</span>
<span class="c">#Copy Kernel Device Tree Binaries</span>
<span class="nb">sudo mkdir</span> <span class="nt">-p</span> /media/rootfs/boot/dtbs/<span class="k">${</span><span class="nv">kernel_version</span><span class="k">}</span>/
<span class="nb">sudo tar </span>xfv ./armv7-lpae-multiplatform/deploy/<span class="k">${</span><span class="nv">kernel_version</span><span class="k">}</span><span class="nt">-dtbs</span>.tar.gz <span class="nt">-C</span> /media/rootfs/boot/dtbs/<span class="k">${</span><span class="nv">kernel_version</span><span class="k">}</span>/
<span class="c">#Copy Kernel Modules</span>
<span class="nb">sudo tar </span>xfv ./armv7-lpae-multiplatform/deploy/<span class="k">${</span><span class="nv">kernel_version</span><span class="k">}</span><span class="nt">-modules</span>.tar.gz <span class="nt">-C</span> /media/rootfs/
<span class="c">#File Systems Table (/etc/fstab)</span>
<span class="nb">sudo </span>sh <span class="nt">-c</span> <span class="s2">"echo '/dev/sde1 / auto errors=remount-ro 0 1' &gt;&gt; /media/rootfs/etc/fstab"</span>
<span class="c">#Remove microSD/SD card</span>
<span class="nb">sync
sudo </span>umount /media/rootfs
</code></pre></div></div>
<h3 id="premier-boot">Premier boot</h3>
<p>On utilise une liaison USB/SERIAL et le logiciel minicom pour communiquer avec la carte olimex</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo minicom
</code></pre></div></div>
<p>Login <strong>debian</strong> et mot de passe <strong>temppwd</strong><br />
On passe en mode su ,<strong>sudo -s</strong><br />
Changer le mot de passe root</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>passwd root
</code></pre></div></div>
<p>locales</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>dpkg-reconfigure locales
</code></pre></div></div>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Generating locales (this might take a while)...
fr_FR.UTF-8... done
Generation complete.
</code></pre></div></div>
<p>Créer un utilisateur temporaire</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>useradd -m -g users -c 'oli debian' -s /bin/bash oli
passwd oli
</code></pre></div></div>
<p>Se connecter en utilisateur <strong>oli</strong><br />
On passe en mode <strong>su</strong></p>
<p>Renommer utilisateur <strong>debian</strong> en <strong>xo</strong></p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>usermod -l xo debian
usermod -d /home/xo -m xo
</code></pre></div></div>
<p>Cela change le nom dutilisateur et tout le reste, comme le groupe, le répertoire daccueil, lUID restera le même.<br />
Changer le mot de passe <strong>xo</strong></p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>passwd xo
</code></pre></div></div>
<p>Modifier sudoers pour accès sudo sans mot de passe à lutilisateur <strong>xo</strong></p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>su
echo "xo ALL=(ALL) NOPASSWD: ALL" &gt;&gt; /etc/sudoers
</code></pre></div></div>
<p>Mise à jour debian</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>apt update &amp;&amp; apt upgrade
</code></pre></div></div>
<p>Supprimer utilisateur <strong>oli</strong></p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>userdel -r oli
</code></pre></div></div>
<h3 id="connexion-via-ssh">Connexion via SSH</h3>
<p>Se connecter depuis un poste du réseau :</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>ssh xo@192.168.0.43
</code></pre></div></div>
<p>id utilisateur <strong>xo</strong></p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>id
</code></pre></div></div>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>uid=1000(xo) gid=1000(debian) groupes=1000(debian),4(adm),15(kmem),20(dialout),24(cdrom),25(floppy),29(a
udio),30(dip),44(video),46(plugdev),100(users),101(systemd-journal),108(i2c),110(netdev),113(bluetooth),
991(cloud9ide),992(xenomai),993(weston-launch),994(tisdk),995(spi),996(admin),997(eqep),998(pwm),999(gpi
o)
</code></pre></div></div>
<h3 id="fuseau-horaire-europeparis">Fuseau horaire Europe/Paris</h3>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo dpkg-reconfigure tzdata
</code></pre></div></div>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Current default time zone: 'Europe/Paris'
Local time is now: Fri Mar 15 08:48:43 CET 2019.
Universal Time is now: Fri Mar 15 07:48:43 UTC 2019.
</code></pre></div></div>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>timedatectl
</code></pre></div></div>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code> Local time: ven. 2019-03-15 08:49:02 CET
Universal time: ven. 2019-03-15 07:49:02 UTC
RTC time: ven. 2019-03-15 07:49:03
Time zone: Europe/Paris (CET, +0100)
Network time on: yes
NTP synchronized: yes
RTC in local TZ: no
</code></pre></div></div>
<h3 id="lvm-logical-volume-manager">LVM (Logical Volume Manager)</h3>
<p>Installer le paquet</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo apt install lvm2
</code></pre></div></div>
<p>Connecter un disque sata SSD M500 Crucial de 480Go<br />
Création des partitions sur /dev/sda</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo fdisk /dev/sda
</code></pre></div></div>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code># o table dos
# n partition 1 20G 83 Linux
# n partition 2 le reste
# t (partition 2) 8e Linux LVM
# w écriture et sortie
</code></pre></div></div>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo fdisk -l /dev/sda
</code></pre></div></div>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Disk /dev/sda: 447,1 GiB, 480103981056 bytes, 937703088 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 4096 bytes
I/O size (minimum/optimal): 4096 bytes / 4096 bytes
Disklabel type: dos
Disk identifier: 0xc4bcac58
Device Boot Start End Sectors Size Id Type
/dev/sda1 2048 41945087 41943040 20G 83 Linux
/dev/sda2 41945088 937703087 895758000 427,1G 8e Linux LVM
</code></pre></div></div>
<p>Création volume physique et logique lvm</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo -s
pvcreate /dev/sda2
vgcreate ssd-m500 /dev/sda2 # créer volume ssd-m500
lvcreate -l 109345 -n lv500 ssd-m500 # créer volume logique lv-data
</code></pre></div></div>
<p>Format type de fichier</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo -s
mkfs.ext4 /dev/sda1
mkfs.ext4 /dev/ssd-m500/lv500
</code></pre></div></div>
<h3 id="bascule-du-root-sdcard-sur-le-ssd">Bascule du root SDcard sur le SSD</h3>
<p>On passe en mode su</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo -s
</code></pre></div></div>
<p>Montage temporaire de lunité <strong>/dev/sda1</strong></p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>mkdir -p /mnt/temp # création point de montage temporaire
mount /dev/sda1 /mnt/temp
</code></pre></div></div>
<p>Copie des fichiers systèmes avec exclusion de certains dossiers</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>/usr/bin/rsync -a --progress --exclude={"boot","dev/*","proc/*","sys/*","tmp/*","run/*","mnt/*","media/*","lost+found"} / /mnt/temp
</code></pre></div></div>
<p>Démontage</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>umount /mnt/temp
</code></pre></div></div>
<p>Modification du boot<br />
Le dossier <strong>/boot</strong> reste sur la SDcard<br />
Le dossier <strong>root /</strong> est sur le disque SSD /dev/sda1</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>rm /boot/extlinux/.extlinux.conf.swp # supprimer le verrou
nano /boot/extlinux/extlinux.conf
</code></pre></div></div>
<p>Remplacer <code class="language-plaintext highlighter-rouge">root=/dev/mmcblk0p1 ro</code> par <code class="language-plaintext highlighter-rouge">root=/dev/sda1 rw</code> et sauver (Ctrl o et Ctrl x) <br />
Arrêt de la maquette</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>poweroff
</code></pre></div></div>
<p>Avant de relancer la maquette, la connecter via une lisaison USB/SERIE et logiciel “minicom” pour analyser la phase de boot</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>[...]
Found /boot/extlinux/extlinux.conf
Retrieving file: /boot/extlinux/extlinux.conf
189 bytes read in 36 ms (4.9 KiB/s)
1: Linux 4.17.17-armv7-lpae-x15
Retrieving file: /boot/vmlinuz-4.17.17-armv7-lpae-x15
8126976 bytes read in 475 ms (16.3 MiB/s)
append: root=/dev/sda1 rw rootfstype=ext4 rootwait quiet
Retrieving file: /boot/dtbs/4.17.17-armv7-lpae-x15/sun7i-a20-olinuxino-micro.dtb
40104 bytes read in 97 ms (403.3 KiB/s)
## Flattened Device Tree blob at 43000000
Booting using the fdt blob at 0x43000000
EHCI failed to shut down host controller.
EHCI failed to shut down host controller.
Loading Device Tree to 49ff3000, end 49fffca7 ... OK
Starting kernel ...
[ 0.004863] /cpus/cpu@0 missing clock-frequency property
[ 0.004912] /cpus/cpu@1 missing clock-frequency property
[FAILED] Failed to start Generic Board Startup.
See 'systemctl status generic-board-startup.service' for details.
[...]
</code></pre></div></div>
<blockquote>
<p>Le root sur /dev/sda1 est bien pris en compte <br />
Connexion utilisateur “xo” et vérification des points de montage par <code class="language-plaintext highlighter-rouge">mount</code></p>
</blockquote>
<p>Analyse des problèmes de boot<br />
<strong>systemctl status generic-board-startup.service</strong> , le script est inexistant , on désactive le service: <code class="language-plaintext highlighter-rouge">sudo systemctl disable generic-board-startup.service</code></p>
<h3 id="créer-une-sdcard-de-boot">Créer une SDcard de boot</h3>
<p>Créer une SDcard bootable avec uniquement le dossier <strong>/boot</strong> et le root sur /dev/sda1<br />
La SDcard peut être de taille faible (&lt;= 4Go) et de “class” inérieur à 10 <br />
Insérer la SDcard dans un lecteur USB/SDcard ,et connecter sur le poste ayant servi à la compilation du kernel <br />
Relever lunité par <code class="language-plaintext highlighter-rouge">dmesg</code></p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>[...]
[ 8008.686470] sde: sde1
[ 8008.690198] sd 4:0:0:0: [sde] Attached SCSI removable disk
</code></pre></div></div>
<p>Unité système <strong>/dev/sde</strong></p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>cd ~/media/dplus/A20-OLinuXino-MICRO/ # se position sur le dossier de compilation
export CC=`pwd`/gcc-linaro-6.4.1-2018.05-x86_64_arm-linux-gnueabihf/bin/arm-linux-gnueabihf-
### Préparer SDcard
# For these instruction we are assuming, DISK=/dev/mmcblk0, lsblk is very useful for determining the device id.
export DISK=/dev/sde
#Erase partition table/labels on microSD card:
sudo dd if=/dev/zero of=${DISK} bs=1M count=10
#Install Bootloader:
sudo dd if=./u-boot/u-boot-sunxi-with-spl.bin of=${DISK} seek=8 bs=1024
#Create Partition Layout:
#With util-linux v2.26, sfdisk was rewritten and is now based on libfdisk.
#sudo sfdisk --version
#sfdisk from util-linux 2.27.1
#sfdisk &gt;= 2.26.x
sudo sfdisk ${DISK} &lt;&lt;-__EOF__
1M,,L,*
__EOF__
#Format Partition:
#for: DISK=/dev/sdX
sudo mkfs.ext4 -L rootfs ${DISK}1
#Mount Partition:
#On most systems these partitions may will be auto-mounted...
sudo mkdir -p /media/rootfs/
#for: DISK=/dev/sdX
sudo mount ${DISK}1 /media/rootfs/
### Fin préparation SDcard
# version kernel
export kernel_version=$(cat armv7-lpae-multiplatform/kernel_version)
# copie root file system
sudo tar xfvp ./*-*-*-armhf-*/armhf-rootfs-*.tar -C /media/rootfs/
sync
sudo chown root:root /media/rootfs/
sudo chmod 755 /media/rootfs/
# Setup extlinux.conf avec unité /dev/sda1
sudo mkdir -p /media/rootfs/boot/extlinux/
sudo sh -c "echo 'label Linux ${kernel_version}' &gt; /media/rootfs/boot/extlinux/extlinux.conf"
sudo sh -c "echo ' kernel /boot/vmlinuz-${kernel_version}' &gt;&gt; /media/rootfs/boot/extlinux/extlinux.conf"
sudo sh -c "echo ' append root=/dev/mmcblk0p1 rw rootfstype=ext4 rootwait quiet' &gt;&gt; /media/rootfs/boot/extlinux/extlinux.conf"
sudo sh -c "echo ' fdtdir /boot/dtbs/${kernel_version}/' &gt;&gt; /media/rootfs/boot/extlinux/extlinux.conf"
#Copy Kernel Image
#Kernel Image:
sudo cp -v ./armv7-lpae-multiplatform/deploy/${kernel_version}.zImage /media/rootfs/boot/vmlinuz-${kernel_version}
#Copy Kernel Device Tree Binaries
sudo mkdir -p /media/rootfs/boot/dtbs/${kernel_version}/
sudo tar xfv ./armv7-lpae-multiplatform/deploy/${kernel_version}-dtbs.tar.gz -C /media/rootfs/boot/dtbs/${kernel_version}/
#Remove microSD/SD card
sync
sudo umount /media/rootfs
</code></pre></div></div>
<p>Insérer la SDcard dans la maquette A20-Olinuxino-MICRO et démarrer…</p>
<h3 id="hostname">Hostname</h3>
<p>Changer le nom</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo hostnamectl set-hostname srvxo
hostnamectl status
</code></pre></div></div>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code> Static hostname: srvxo
Icon name: computer
Machine ID: 4552d3d1987da57b28f058f15c8aae61
Boot ID: 4520edfe83454a9f9a61863276c1ab72
Operating System: Debian GNU/Linux 9 (stretch)
Kernel: Linux 4.17.17-armv7-lpae-x15
Architecture: arm
</code></pre></div></div>
<p>Il faut modifier le fichier <strong>/etc/hosts</strong> , remplacer <em>arm.localdomain</em> par <em>xoyize.xyz</em> et <em>arm</em> par <em>srvxo</em> sinon erreur</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo nano /etc/hosts
</code></pre></div></div>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>127.0.0.1 localhost
127.0.1.1 xoyize.xyz srvxo
# The following lines are desirable for IPv6 capable hosts
::1 localhost ip6-localhost ip6-loopback
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
</code></pre></div></div>
<p>Après modification</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>hostname --fqdn
xoyize.xyz
</code></pre></div></div>
<h3 id="réseau">Réseau</h3>
<p>http://variwiki.com/index.php?title=Static_IP_Address</p>
<p>Par défaut connman est utilisé</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>systemctl status connman
</code></pre></div></div>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>● connman.service - Connection service
Loaded: loaded (/lib/systemd/system/connman.service; enabled; vendor preset: enabled)
Active: active (running) since Fri 2019-03-15 10:58:13 CET; 3h 26min ago
Main PID: 262 (connmand)
Tasks: 1 (limit: 4915)
CGroup: /system.slice/connman.service
└─262 /usr/sbin/connmand -n
</code></pre></div></div>
<p>On relève interface filaire<br />
<code class="language-plaintext highlighter-rouge">connmanctl services</code><br />
<code class="language-plaintext highlighter-rouge">*AO Wired ethernet_02c20940f22b_cable</code></p>
<p>On passe en statique<br />
<code class="language-plaintext highlighter-rouge">sudo connmanctl config ethernet_02c20940f22b_cable --ipv4 manual 192.168.0.43 255.255.255.0 192.168.0.254</code><br />
<code class="language-plaintext highlighter-rouge">sudo connmanctl config ethernet_02c20940f22b_cable --nameservers 9.9.9.9</code></p>
<p>NextHop Freebox permet dattribuer une adresse IPV6<br />
2a01:e34:eebf:df3::/64 fe80::c2:9ff:fe40:f22b<br />
Debian Stretch A20-olinuxino-micro (compilation kernel)<br />
IPV4 : 192.168.0.43<br />
IPV6 : 2a01:e34:eebf:df3::1<br />
Domaine : xoyize.xyz</p>
<p><code class="language-plaintext highlighter-rouge">sudo connmanctl config ethernet_02c20940f22b_cable --ipv6 manual 2a01:e34:eebf:df3::1 64 fe80::224:d4ff:fea6:aa20</code></p>
<p>Redémarrer la machine et se connecter via SSH<br />
Vérifier adressage ip</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>ip addr
</code></pre></div></div>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>1: lo: &lt;LOOPBACK,UP,LOWER_UP&gt; mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: eth0: &lt;BROADCAST,MULTICAST,DYNAMIC,UP,LOWER_UP&gt; mtu 1500 qdisc mq state UP group default qlen 1000
link/ether 02:c2:09:40:f2:2b brd ff:ff:ff:ff:ff:ff
inet 192.168.0.43/24 brd 192.168.0.255 scope global eth0
valid_lft forever preferred_lft forever
inet6 2a01:e34:eebf:df3::1/64 scope global
valid_lft forever preferred_lft forever
inet6 fe80::c2:9ff:fe40:f22b/64 scope link
valid_lft forever preferred_lft forever
</code></pre></div></div>
<p>Message erreur<br />
<code class="language-plaintext highlighter-rouge">[ 1281.828853] ICMPv6: RA: ndisc_router_discovery failed to add default route</code><br />
Correction<br />
désactiver lannonce des routes<br />
<code class="language-plaintext highlighter-rouge">sudo nano /etc/sysctl.conf</code><br />
Ajouter <code class="language-plaintext highlighter-rouge">net.ipv6.conf.eth0.accept_ra=0</code><br />
Puis <code class="language-plaintext highlighter-rouge">sudo sysctl -p</code> pour une validation immédiate</p>
<h3 id="domaine-et-certificats">Domaine et certificats</h3>
<p><a href="https://yann.cinay.eu/2017/08/31/Acme-Certficats-Serveurs.html">Serveur , installer et renouveler les certificats SSL Lets encrypt </a><br />
Installation client acme</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>cd ~
sudo -s # en mode super utilisateur
apt install netcat socat -y # prérequis
git clone https://github.com/Neilpang/acme.sh.git
cd acme.sh
./acme.sh --install # --nocron
cd ..
rm -rf acme.sh/
</code></pre></div></div>
<p>Génération des certificats</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>/root/.acme.sh/acme.sh --dns dns_ovh --issue --keylength ec-384 -d xoyize.xyz -d *.xoyize.xyz
</code></pre></div></div>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>[vendredi 15 mars 2019, 20:08:10 (UTC+0100)] Your cert is in /root/.acme.sh/xoyize.xyz_ecc/xoyize.xyz.cer
[vendredi 15 mars 2019, 20:08:10 (UTC+0100)] Your cert key is in /root/.acme.sh/xoyize.xyz_ecc/xoyize.xyz.key
[vendredi 15 mars 2019, 20:08:10 (UTC+0100)] The intermediate CA cert is in /root/.acme.sh/xoyize.xyz_ecc/ca.cer
[vendredi 15 mars 2019, 20:08:10 (UTC+0100)] And the full chain certs is there: /root/.acme.sh/xoyize.xyz_ecc/fullchain.cer
</code></pre></div></div>
<h3 id="connexion-xoyizexyz-srvxo-avec-clés-ssh">Connexion xoyize.xyz (srvxo) avec clés SSH</h3>
<p>Pour éviter les blocages en sortie connexion SSH<br />
<code class="language-plaintext highlighter-rouge">sudo apt-get install libpam-systemd</code></p>
<p>Ajout clé publique <strong>shuttle.pub</strong> depuis <strong>poste appelant</strong></p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>scp ~/.ssh/xoyize.pub xo@192.168.0.43:/home/xo
</code></pre></div></div>
<p>Sur le <strong>poste distant</strong> création en mode utilisateur du dossier <strong>.ssh</strong> et des droits</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>mkdir ~/.ssh
chmod 700 ~/.ssh
</code></pre></div></div>
<p>Ajout de la clé publique</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>cat xoyize.pub &gt;&gt; ~/.ssh/authorized_keys
#modifier les droits
chmod 600 ~/.ssh/authorized_keys
#Effacer le fichier de la clé
rm xoyize.pub
</code></pre></div></div>
<p>Modification fichier configuration <strong>ssh</strong></p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo nano /etc/ssh/sshd_config
</code></pre></div></div>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Port 55035
PasswordAuthentication no
</code></pre></div></div>
<p>On relance le serveur ssh</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo systemctl restart sshd
</code></pre></div></div>
<p>Connexion</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>ssh xo@xoyize.xyz -p 55035 -i ~/.ssh/xoyize
</code></pre></div></div>
<h3 id="borg">Borg</h3>
<p>En mode su</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo -s
</code></pre></div></div>
<p>Installation BorgBackup en utilisant les dépôts “backports”</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>apt edit-sources # pour ajouter la ligne pour les dépôts "backports"
deb http://deb.debian.org/debian stretch-backports main contrib non-free
</code></pre></div></div>
<p>Votre fichier « /etc/apt/sources.list » a changé, veuillez lancer « apt-get update »</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>apt update
</code></pre></div></div>
<p>Installer borgbackup</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>apt -V -t=stretch-backports install borgbackup
</code></pre></div></div>
<p>Créer un point de montage <strong>srv</strong> pour les dépôts de sauvegarde</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>mkdir -p /srv/data
</code></pre></div></div>
<p>Ajouter au fichier <strong>/etc/fstab</strong></p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>/dev/ssd-m500/lv500 /srv/data ext4 defaults 0 2
</code></pre></div></div>
<p>Montage manuel</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>mount -a
</code></pre></div></div>
<p>créer un utilisateur dédié aux sauvegardes avec son home :</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>useradd borg --create-home --home-dir /srv/data/borg-backups/
</code></pre></div></div>
<p>Créer le dossier qui contiendra les clés publiques des serveurs ayany un accès pour leur sauvegarde</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>mkdir -p /srv/data/borg-backups/.ssh
</code></pre></div></div>
<p>Créer le fichier qui contiendra les clés publiques</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>touch /srv/data/borg-backups/.ssh/authorized_keys
</code></pre></div></div>
<p>Ajouter à ce fichier les clés publiques…</p>
<p>Opération à effectuer sur les serveurs distants qui effectuent leur sauvegarde sur <strong>xoyize.xyz</strong><br />
Il faut supprimer le fichier des “serveurs connus”<br />
<code class="language-plaintext highlighter-rouge">sudo rm /root/.ssh/known_hosts</code><br />
Puis lancer les commandes suivantes</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>set -e
BACKUP_DATE=`date +%Y-%m-%d-%Hh%M`
LOG_PATH=/var/log/borg-backup.log
export BORG_PASSPHRASE="`cat ~root/.borg/passphrase`"
export BORG_RSH='ssh -i /root/.ssh/yanspm_ed25519'
BORG_REPOSITORY=ssh://borg@xoyize.xyz:55035/srv/data/borg-backups/yanspm.com
BORG_ARCHIVE=${BORG_REPOSITORY}::${BACKUP_DATE}
borg create \
-v --stats --compression lzma,9 \
$BORG_ARCHIVE \
/bin /boot /etc /home /lib /lib64 /opt /root /sbin /srv /usr /var
</code></pre></div></div>
<p>Saisir “yes” à la question</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>The authenticity of host '[xoyize.xyz]:55035 ([2a01:e34:eebf:df3::1]:55035)' can't be established.
ECDSA key fingerprint is SHA256:mx9WOfQPFuwwlWfTCNJxhgw3HzCdlwleO9LwsmW1mtU.
Are you sure you want to continue connecting (yes/no)? yes
</code></pre></div></div>
<p>Vous devez avoir un message de ce type</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Creating archive at "ssh://borg@xoyize.xyz:55035/srv/data/borg-backups/yanspm.com::2019-03-15-20h48"
------------------------------------------------------------------------------
Archive name: 2019-03-15-20h48
Archive fingerprint: 4b4bbb019635953c4af2f523e03794b0e3071a402e352f0e7c80b3b097571781
Time (start): Fri, 2019-03-15 20:49:11
Time (end): Fri, 2019-03-15 20:49:48
Duration: 36.26 seconds
Number of files: 77105
Utilization of max. archive size: 0%
------------------------------------------------------------------------------
Original size Compressed size Deduplicated size
This archive: 3.76 GB 1.10 GB 4.30 MB
All archives: 51.14 GB 15.45 GB 1.37 GB
Unique chunks Total chunks
Chunk index: 79248 1075339
------------------------------------------------------------------------------
</code></pre></div></div>
<p>Le serveur distant est initialisé pour faire ces sauvegardes automatiquement (crontab)</p>
<hr />
<h3 id="parefeu-iptables">Parefeu (iptables)</h3>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code> ____ __
| _ \ __ _ _ __ ___ / _| ___ _ _
| |_) / _` | '__/ _ \ |_ / _ \ | | |
| __/ (_| | | | __/ _| __/ |_| |
|_| \__,_|_| \___|_| \___|\__,_|
</code></pre></div></div>
<p><a href="https://yann.cinay.eu/2018/10/08/Pare-feu-iptables-IPv4-IPv6-versions-bureau-et-serveur.html">Parefeu (firewall) iptables IPV4/IPV6 bureau/serveur</a></p>
<p>iptables est normalement installé par défaut sur les serveurs.Dans le cas contraire</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo apt install iptables # debian/ubuntu
</code></pre></div></div>
<p>Enusuite au choix</p>
<p>Scénarion A</p>
<ol>
<li>Création dun “service” <strong>init_firewall</strong> pour que le pare-feu soit lancé lors de la phase de boot du système.</li>
<li>Script <strong>/usr/local/sbin/config_firewall</strong> pour le serveur</li>
<li>Premier lancement <strong>/usr/local/sbin/config_firewall</strong> ,ensuite exécution automatique au démarrage</li>
</ol>
<p>Scénario B</p>
<ol>
<li>Script <strong>/usr/local/sbin/config_firewall</strong> pour le serveur</li>
<li>Commenter la dernière ligne <code class="language-plaintext highlighter-rouge">#/etc/init.d/init_firewall restart</code> du script précédent</li>
<li>Exécuter le script <strong>/usr/local/sbin/config_firewall</strong></li>
<li>
<p>Installer le paquet <strong>iptables-persistent</strong> pour définir des règles persistantes après un reboot.</p>
<p>sudo apt install iptables-persistent</p>
</li>
</ol>
<p>Pendant, linstallation du paquet, on vous est demande si vous souhaitez que les règles actuellement en cours dutilisation soient enregistrées dans le fichier .<br />
Valider Yes/Oui, pour IP V4 comme pour IP V6.</p>
<h3 id="nginx-php-mariadb">Nginx PHP Mariadb</h3>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code> _ _ _ ____ _ _ ____ _____ ____
| \ | | __ _(_)_ __ __ __ | _ \| | | | _ \___ |___ \
| \| |/ _` | | '_ \\ \/ / | |_) | |_| | |_) | / / __) |
| |\ | (_| | | | | |&gt; &lt; | __/| _ | __/ / /_ / __/
|_| \_|\__, |_|_| |_/_/\_\ |_| |_| |_|_| /_/(_)_____|
|___/
__ __ _ ____ ____
| \/ | __ _ _ __(_) __ _| _ \| __ )
| |\/| |/ _` | '__| |/ _` | | | | _ \
| | | | (_| | | | | (_| | |_| | |_) |
|_| |_|\__,_|_| |_|\__,_|____/|____/
</code></pre></div></div>
<p>Il exite une version de nginx pour debian stretch</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>nginx -v
nginx version: nginx/1.10.3
</code></pre></div></div>
<p>Supprimer le fichier par défaut</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code> sudo rm /etc/nginx/sites-enabled/default
</code></pre></div></div>
<p>Modifier le fichier /etc/nginx/nginx.conf<br />
Commenter la ligne<br />
<code class="language-plaintext highlighter-rouge"># include /etc/nginx/sites-enabled/*;</code></p>
<p><strong>Installer php7.2 OpenSSL et MariaDb</strong></p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code># PHP7.2
apt-get -y install apt-transport-https lsb-release ca-certificates
wget -O /etc/apt/trusted.gpg.d/php.gpg https://packages.sury.org/php/apt.gpg
sh -c 'echo "deb https://packages.sury.org/php/ $(lsb_release -sc) main" &gt; /etc/apt/sources.list.d/php.list'
apt update
# Le paquet php7.2-mcrypt est inexistant (si besoin ,installer php7.1-mcrypt)
apt install php7.2 php7.2-fpm php7.2-mysql php7.2-curl php7.2-json php7.2-gd php7.2-tidy php7.2-intl php7.2-imagick php7.2-xml php7.2-mbstring php7.2-zip -y
# Contenu fichier /etc/nginx/conf.d/default.conf
# back slash pour prise en compte request_filename
cat &gt; /etc/nginx/conf.d/default.conf &lt;&lt; EOF
server {
listen 80;
listen [::]:80;
root /var/www/ ;
location ~* \.php$ {
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass unix:/run/php/php7.2-fpm.sock; # PHP7.2
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param REMOTE_USER $remote_user;
fastcgi_param PATH_INFO $fastcgi_path_info;
fastcgi_param SCRIPT_FILENAME $request_filename;
}
}
EOF
# test php
echo "&lt;?php phpinfo(); ?&gt;" &gt; /var/www/index.php
# Réinitialiser
systemctl daemon-reload
# Activer nginx
systemctl enable nginx
# Relancer les services
systemctl restart nginx php7.2-fpm
#openssl
apt install openssl -y
# Installer MariaDb
apt install mariadb-server -y
# Générer un mot de passe pour mysql
echo $(head -c 12 /dev/urandom | openssl enc -base64) &gt; /etc/mysql/mdp
# fichier sql
# http://www.dbnewz.com/2008/07/14/mysql_secure_installation-pratique-mais-non-parametrable/
cat &gt; /tmp/mysql_secure.sql &lt;&lt; EOF
UPDATE mysql.user SET Password=PASSWORD('$(cat /etc/mysql/mdp)') WHERE User='root'; /* Met à jour le password de lutilisateur root */
DELETE FROM mysql.user WHERE User=''; /* Supprime les utilisateurs anonymes */
DELETE FROM mysql.user WHERE User='root' AND Host!='localhost'; /* Supprime la possibilité à un utilisateur root de se connecter à partir dun serveur distant */
DROP DATABASE test; /* Supprime la base de données test */
DELETE FROM mysql.db WHERE Db=test OR Db=test_%; /* Supprime les privilèges associés à la base test */
FLUSH PRIVILEGES; /* Applique les changements effectués précedemment concernant la gestion des droits */
EOF
# Exécuter la requête sql
mysql -uroot &lt; /tmp/mysql_secure.sql
</code></pre></div></div>
<h3 id="config-nginx">Config nginx</h3>
<p>Créer des liens</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo ln -s /root/.acme.sh/xoyize.xyz_ecc/fullchain.cer /etc/ssl/private/xoyize.xyz.fullchain.cer.pem;
sudo ln -s /root/.acme.sh/xoyize.xyz_ecc/xoyize.xyz.key /etc/ssl/private/xoyize.xyz.key.pem;
</code></pre></div></div>
<p>Le fichier de configuration <strong>/etc/nginx/conf.d/default.conf</strong></p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>server {
listen 80;
listen [::]:80;
## redirect http to https ##
server_name xoyize.xyz *.xoyize.xyz;
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name xoyize.xyz;
root /var/www/ ;
ssl_certificate /etc/ssl/private/xoyize.xyz.fullchain.cer.pem;
ssl_certificate_key /etc/ssl/private/xoyize.xyz.key.pem;
ssl_session_timeout 5m;
ssl_session_cache shared:SSL:50m;
# As suggested by https://cipherli.st/
ssl_ecdh_curve secp384r1;
ssl_prefer_server_ciphers on;
# Ciphers with intermediate compatibility
#----------------------------------------
# https://mozilla.github.io/server-side-tls/ssl-config-generator/?server=nginx-1.6.2&amp;openssl=1.0.1t&amp;hsts=yes&amp;profile=intermediate
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers 'ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:ECDHE-ECDSA-DES-CBC3-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA:!DSS';
# Follows the Web Security Directives from the Mozilla Dev Lab and the Mozilla Obervatory + Partners
# https://wiki.mozilla.org/Security/Guidelines/Web_Security
# https://observatory.mozilla.org/
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload";
add_header Content-Security-Policy "upgrade-insecure-requests";
add_header Content-Security-Policy-Report-Only "default-src https: data: 'unsafe-inline' 'unsafe-eval'";
add_header X-Content-Type-Options nosniff;
add_header X-XSS-Protection "1; mode=block";
add_header X-Download-Options noopen;
add_header X-Permitted-Cross-Domain-Policies none;
add_header X-Frame-Options "SAMEORIGIN";
index index.php index.html;
location ~* \.php$ {
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass unix:/run/php/php7.2-fpm.sock; # PHP7.2
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param REMOTE_USER $remote_user;
fastcgi_param PATH_INFO $fastcgi_path_info;
fastcgi_param SCRIPT_FILENAME $request_filename;
}
access_log /var/log/nginx/xoyize.xyz-access.log;
error_log /var/log/nginx/xoyize.xyz-error.log;
}
</code></pre></div></div>
<p>Vérifier et relancer nginx</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo nginx -t
sudo systemctl restart nginx
</code></pre></div></div>
<h2 id="control-gpio-i2c-and-spi-on-a20-olinuxino-micro">Control GPIO, I2C and SPI on A20-OLinuXino-MICRO</h2>
<p><a href="https://pypi.org/project/pyA20/">Control GPIO, I2C and SPI on A20-OLinuXino-MICRO</a></p>
<p><strong>Installer python-pip</strong></p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo apt install python-pip
</code></pre></div></div>
<p>Vérifier</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>pip -V
</code></pre></div></div>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>pip 9.0.1 from /usr/lib/python2.7/dist-packages (python 2.7)
</code></pre></div></div>
<p>The package pyA20 provide methods for controlling GPIO pins, I2C and SPI buses. Its written for A20-OLinuXino-MICRO, but it can be used with other boards. In this case proper operation is not guaranteed. You can check <a href="https://www.olimex.com/wiki/A20-OLinuXino-MICRO">wiki</a> for more information.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>pip install pyA20
</code></pre></div></div>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Collecting pyA20
Downloading https://files.pythonhosted.org/packages/dd/c2/ec7b33d0aacd1037635a50c5b6d238453415de2fd417de13d5d1545cb6d8/pyA20-0.2.12.tar.gz
Building wheels for collected packages: pyA20
Running setup.py bdist_wheel for pyA20 ... done
Stored in directory: /home/oli/.cache/pip/wheels/df/f9/ae/785545360d5558cf3589d53bb4ed0e79b7c94c9b3fac502641
Successfully built pyA20
Installing collected packages: pyA20
Successfully installed pyA20-0.2.12
</code></pre></div></div>
<blockquote>
<p><strong>Notes:</strong>When using GPIO make sure that the desired gpio is not used by another periphery.<br />
<strong>Using this library requires root access.</strong></p>
</blockquote>
<p><strong>GPIO methods</strong></p>
<p>The following methods are available:</p>
<ul>
<li>init() - Make initialization of the module. Must be called first.</li>
<li>getcfg() - Read current configuration of gpio.</li>
<li>setcfg() - Write configuration to gpio.</li>
<li>input() - Return current value of gpio.</li>
<li>output() - Set output value.</li>
<li>pullup() - Set pull-up/pull-down.</li>
</ul>
<p>The available constants are:</p>
<ul>
<li>HIGH - 1</li>
<li>LOW - 0</li>
<li>INPUT - 0</li>
<li>OUPTUT - 1</li>
<li>PULLUP - 1</li>
<li>PULLDOWN - 2</li>
</ul>
<p>The gpio are named two ways:</p>
<ul>
<li>By port name: PH0, PG2, PE10, etc. These can be imported from port module:</li>
</ul>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>&gt;&gt;&gt; from pyA20.gpio import port
&gt;&gt;&gt; dir(port)
</code></pre></div></div>
<ul>
<li>By connector name and pin number: gpio2p12, gpio3p8, lcdp18, uext1p3 and etc:</li>
</ul>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>&gt;&gt;&gt; from pyA20.gpio import connector
&gt;&gt;&gt; dir(connector)
</code></pre></div></div>
<p>Generally these constants are just an offset in the memory from the base GPIO address, so they can be assigned to a number type variable.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>&gt;&gt;&gt; led = port.PH2
&gt;&gt;&gt; print led
226
</code></pre></div></div>
<p>GPIO example consist of:</p>
<ul>
<li>Initialize gpio module</li>
<li>Initialize one gpio as output and another one as input</li>
<li>Polling input state and write corresponding output value</li>
</ul>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">#!/usr/bin/env python
</span>
<span class="kn">from</span> <span class="n">pyA20.gpio</span> <span class="kn">import</span> <span class="n">gpio</span>
<span class="kn">from</span> <span class="n">pyA20.gpio</span> <span class="kn">import</span> <span class="n">port</span>
<span class="kn">from</span> <span class="n">pyA20.gpio</span> <span class="kn">import</span> <span class="n">connector</span>
<span class="n">gpio</span><span class="p">.</span><span class="nf">init</span><span class="p">()</span> <span class="c1">#Initialize module. Always called first
</span>
<span class="n">gpio</span><span class="p">.</span><span class="nf">setcfg</span><span class="p">(</span><span class="n">port</span><span class="p">.</span><span class="n">PG9</span><span class="p">,</span> <span class="n">gpio</span><span class="p">.</span><span class="n">OUTPUT</span><span class="p">)</span> <span class="c1">#Configure LED1 as output
</span><span class="n">gpio</span><span class="p">.</span><span class="nf">setcfg</span><span class="p">(</span><span class="n">port</span><span class="p">.</span><span class="n">PG9</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span> <span class="c1">#This is the same as above
</span>
<span class="n">gpio</span><span class="p">.</span><span class="nf">setcfg</span><span class="p">(</span><span class="n">port</span><span class="p">.</span><span class="n">PE11</span><span class="p">,</span> <span class="n">gpio</span><span class="p">.</span><span class="n">INPUT</span><span class="p">)</span> <span class="c1">#Configure PE11 as input
</span><span class="n">gpio</span><span class="p">.</span><span class="nf">setcfg</span><span class="p">(</span><span class="n">port</span><span class="p">.</span><span class="n">PE11</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span> <span class="c1">#Same as above
</span>
<span class="n">gpio</span><span class="p">.</span><span class="nf">pullup</span><span class="p">(</span><span class="n">port</span><span class="p">.</span><span class="n">PE11</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span> <span class="c1">#Clear pullups
</span><span class="n">gpio</span><span class="p">.</span><span class="nf">pullup</span><span class="p">(</span><span class="n">port</span><span class="p">.</span><span class="n">PE11</span><span class="p">,</span> <span class="n">gpio</span><span class="p">.</span><span class="n">PULLDOWN</span><span class="p">)</span> <span class="c1">#Enable pull-down
</span><span class="n">gpio</span><span class="p">.</span><span class="nf">pullup</span><span class="p">(</span><span class="n">port</span><span class="p">.</span><span class="n">PE11</span><span class="p">,</span> <span class="n">gpio</span><span class="p">.</span><span class="n">PULLUP</span><span class="p">)</span> <span class="c1">#Enable pull-up
</span>
<span class="k">while</span> <span class="bp">True</span><span class="p">:</span>
<span class="k">if</span> <span class="n">gpio</span><span class="p">.</span><span class="nf">input</span><span class="p">(</span><span class="n">port</span><span class="p">.</span><span class="n">PE11</span><span class="p">)</span> <span class="o">==</span> <span class="mi">1</span><span class="p">:</span>
<span class="n">gpio</span><span class="p">.</span><span class="nf">output</span><span class="p">(</span><span class="n">port</span><span class="p">.</span><span class="n">PG9</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="n">gpio</span><span class="p">.</span><span class="nf">output</span><span class="p">(</span><span class="n">port</span><span class="p">.</span><span class="n">PG9</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">gpio</span><span class="p">.</span><span class="nf">output</span><span class="p">(</span><span class="n">port</span><span class="p">.</span><span class="n">PG9</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="n">gpio</span><span class="p">.</span><span class="nf">output</span><span class="p">(</span><span class="n">port</span><span class="p">.</span><span class="n">PG9</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span>
</code></pre></div></div>
<p><strong>I2C methods</strong></p>
<ul>
<li>init() - Make initialization of the module</li>
<li>open() - Begin communication with slave device</li>
<li>read() - Read from slave device</li>
<li>write() - Write data to slave device</li>
<li>close() - End communication with slave device</li>
</ul>
<p>I2C example:</p>
<ul>
<li>I2C module is imported</li>
<li>Bus number 2 is opened</li>
<li>Some data is written, then verified</li>
</ul>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">#!/usr/bin/env python
</span>
<span class="kn">from</span> <span class="n">pyA20.i2c</span> <span class="kn">import</span> <span class="n">i2c</span>
<span class="n">i2c</span><span class="p">.</span><span class="nf">init</span><span class="p">(</span><span class="sh">"</span><span class="s">/dev/i2c-2</span><span class="sh">"</span><span class="p">)</span> <span class="c1">#Initialize module to use /dev/i2c-2
</span><span class="n">i2c</span><span class="p">.</span><span class="nf">open</span><span class="p">(</span><span class="mh">0x55</span><span class="p">)</span> <span class="c1">#The slave device address is 0x55
</span>
<span class="c1">#If we want to write to some register
</span><span class="n">i2c</span><span class="p">.</span><span class="nf">write</span><span class="p">([</span><span class="mh">0xAA</span><span class="p">,</span> <span class="mh">0x20</span><span class="p">])</span> <span class="c1">#Write 0x20 to register 0xAA
</span><span class="n">i2c</span><span class="p">.</span><span class="nf">write</span><span class="p">([</span><span class="mh">0xAA</span><span class="p">,</span> <span class="mh">0x10</span><span class="p">,</span> <span class="mh">0x11</span><span class="p">,</span> <span class="mh">0x12</span><span class="p">])</span> <span class="c1">#Do continuous write with start address 0xAA
</span>
<span class="c1">#If we want to do write and read
</span><span class="n">i2c</span><span class="p">.</span><span class="nf">write</span><span class="p">([</span><span class="mh">0xAA</span><span class="p">])</span> <span class="c1">#Set address at 0xAA register
</span><span class="n">value</span> <span class="o">=</span> <span class="n">i2c</span><span class="p">.</span><span class="nf">read</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span> <span class="c1">#Read 1 byte with start address 0xAA
</span>
<span class="n">i2c</span><span class="p">.</span><span class="nf">close</span><span class="p">()</span> <span class="c1">#End communication with slave device
</span></code></pre></div></div>
<p><strong>SPI methods</strong></p>
<ul>
<li>open() - Open SPI bus with given configuration</li>
<li>read() - Read data from slave device without write</li>
<li>write() - Write data to slave device without read</li>
<li>xfer() - Do write and after that read</li>
<li>close() - Close SPI bus</li>
</ul>
<p>SPI example:</p>
<ul>
<li>SPI module is imported</li>
<li>Bus 2 with chip-select 0 is opened</li>
<li>Some data is transfered to slave device</li>
</ul>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">#!/usr/bin/env python
</span>
<span class="kn">from</span> <span class="n">pyA20.spi</span> <span class="kn">import</span> <span class="n">spi</span>
<span class="n">spi</span><span class="p">.</span><span class="nf">open</span><span class="p">(</span><span class="sh">"</span><span class="s">/dev/spidev2.0</span><span class="sh">"</span><span class="p">)</span>
<span class="c1">#Open SPI device with default settings
# mode : 0
# speed : 100000kHz
# delay : 0
# bits-per-word: 8
</span>
<span class="c1">#Different ways to open device
</span><span class="n">spi</span><span class="p">.</span><span class="nf">open</span><span class="p">(</span><span class="sh">"</span><span class="s">/dev/spidev2.0</span><span class="sh">"</span><span class="p">,</span> <span class="n">mode</span><span class="o">=</span><span class="mi">1</span><span class="p">)</span>
<span class="n">spi</span><span class="p">.</span><span class="nf">open</span><span class="p">(</span><span class="sh">"</span><span class="s">/dev/spidev2.0</span><span class="sh">"</span><span class="p">,</span> <span class="n">mode</span><span class="o">=</span><span class="mi">2</span><span class="p">,</span> <span class="n">delay</span><span class="o">=</span><span class="mi">0</span><span class="p">)</span>
<span class="n">spi</span><span class="p">.</span><span class="nf">open</span><span class="p">(</span><span class="sh">"</span><span class="s">/dev/spidev2.0</span><span class="sh">"</span><span class="p">,</span> <span class="n">mode</span><span class="o">=</span><span class="mi">3</span><span class="p">,</span> <span class="n">delay</span><span class="o">=</span><span class="mi">0</span><span class="p">,</span> <span class="n">bits_per_word</span><span class="o">=</span><span class="mi">8</span><span class="p">)</span>
<span class="n">spi</span><span class="p">.</span><span class="nf">open</span><span class="p">(</span><span class="sh">"</span><span class="s">/dev/spidev2.0</span><span class="sh">"</span><span class="p">,</span> <span class="n">mode</span><span class="o">=</span><span class="mi">0</span><span class="p">,</span> <span class="n">delay</span><span class="o">=</span><span class="mi">0</span><span class="p">,</span> <span class="n">bits_per_word</span><span class="o">=</span><span class="mi">8</span><span class="p">,</span> <span class="n">speed</span><span class="o">=</span><span class="mi">100000</span><span class="p">)</span>
<span class="n">spi</span><span class="p">.</span><span class="nf">write</span><span class="p">([</span><span class="mh">0x01</span><span class="p">,</span> <span class="mh">0x02</span><span class="p">])</span> <span class="c1">#Write 2 bytes to slave device
</span><span class="n">spi</span><span class="p">.</span><span class="nf">read</span><span class="p">(</span><span class="mi">2</span><span class="p">)</span> <span class="c1">#Read 2 bytes from slave device
</span><span class="n">spi</span><span class="p">.</span><span class="nf">xfer</span><span class="p">([</span><span class="mh">0x01</span><span class="p">,</span> <span class="mh">0x02</span><span class="p">],</span> <span class="mi">2</span><span class="p">)</span> <span class="c1">#Write 2 byte and then read 2 bytes.
</span>
<span class="n">spi</span><span class="p">.</span><span class="nf">close</span><span class="p">()</span> <span class="c1">#Close SPI bus
</span></code></pre></div></div>
<h2 id="controler-la-charge-de-la-batterie">Controler la charge de la batterie</h2>
<p><a href="http://linux-sunxi.org/AXP209">La documentation AXP209</a> <br />
<a href="/files/AXP209_Datasheet_v1.0en.pdf">APX209 (pdf)</a></p>
<p><img src="/images/axp209-0.png" alt="" /><br />
<img src="/images/axp209-1.png" alt="" /></p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>nano ~/battinfo.sh
</code></pre></div></div>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>#!/bin/sh
# This program gets the battery info from PMU
# Voltage and current charging/discharging
#
# Nota : temperature can be more than real because of self heating
#######################################################################
# Copyright (c) 2014 by RzBo, Bellesserre, France
#
# Permission is granted to use the source code within this
# file in whole or in part for any use, personal or commercial,
# without restriction or limitation.
#
# No warranties, either explicit or implied, are made as to the
# suitability of this code for any purpose. Use at your own risk.
#######################################################################
# force ADC enable for battery voltage and current
i2cset -y -f 1 0x34 0x82 0xC3
################################
#read Power status register @00h
POWER_STATUS=$(i2cget -y -f 1 0x34 0x00)
#echo $POWER_STATUS
BAT_STATUS=$(($(($POWER_STATUS&amp;0x02))/2)) # divide by 2 is like shifting rigth 1 times
#echo $(($POWER_STATUS&amp;0x02))
echo "BAT_STATUS="$BAT_STATUS
# echo $BAT_STATUS
################################
#read Power OPERATING MODE register @01h
POWER_OP_MODE=$(i2cget -y -f 1 0x34 0x01)
#echo $POWER_OP_MODE
CHARG_IND=$(($(($POWER_OP_MODE&amp;0x40))/64)) # divide by 64 is like shifting rigth 6 times
#echo $(($POWER_OP_MODE&amp;0x40))
echo "CHARG_IND="$CHARG_IND
# echo $CHARG_IND
BAT_EXIST=$(($(($POWER_OP_MODE&amp;0x20))/32)) # divide by 32 is like shifting rigth 5 times
#echo $(($POWER_OP_MODE&amp;0x20))
echo "BAT_EXIST="$BAT_EXIST
# echo $BAT_EXIST
################################
#read Charge control register @33h
CHARGE_CTL=$(i2cget -y -f 1 0x34 0x33)
echo "CHARGE_CTL="$CHARGE_CTL
# echo $CHARGE_CTL
################################
#read Charge control register @34h
CHARGE_CTL2=$(i2cget -y -f 1 0x34 0x34)
echo "CHARGE_CTL2="$CHARGE_CTL2
# echo $CHARGE_CTL2
################################
#read battery voltage 79h, 78h 0 mV -&gt; 000h, 1.1 mV/bit FFFh -&gt; 4.5045 V
BAT_VOLT_LSB=$(i2cget -y -f 1 0x34 0x79)
BAT_VOLT_MSB=$(i2cget -y -f 1 0x34 0x78)
#echo $BAT_VOLT_MSB $BAT_VOLT_LSB
BAT_BIN=$(( $(($BAT_VOLT_MSB &lt;&lt; 4)) | $(($(($BAT_VOLT_LSB &amp; 0xF0)) &gt;&gt; 4)) ))
BAT_VOLT=$(echo "($BAT_BIN*1.1)"|bc)
echo "Battery voltage = "$BAT_VOLT"mV"
###################
#read Battery Discharge Current 7Ah, 7Bh 0 mV -&gt; 000h, 0.5 mA/bit FFFh -&gt; 4.095 V
BAT_IDISCHG_LSB=$(i2cget -y -f 1 0x34 0x7B)
BAT_IDISCHG_MSB=$(i2cget -y -f 1 0x34 0x7A)
#echo $BAT_IDISCHG_MSB $BAT_IDISCHG_LSB
BAT_IDISCHG_BIN=$(( $(($BAT_IDISCHG_MSB &lt;&lt; 4)) | $(($(($BAT_IDISCHG_LSB &amp; 0xF0)) &gt;&gt; 4)) ))
BAT_IDISCHG=$(echo "($BAT_IDISCHG_BIN*0.5)"|bc)
echo "Battery discharge current = "$BAT_IDISCHG"mA"
###################
#read Battery Charge Current 7Ch, 7Dh 0 mV -&gt; 000h, 0.5 mA/bit FFFh -&gt; 4.095 V
BAT_ICHG_LSB=$(i2cget -y -f 1 0x34 0x7D)
BAT_ICHG_MSB=$(i2cget -y -f 1 0x34 0x7C)
#echo $BAT_ICHG_MSB $BAT_ICHG_LSB
BAT_ICHG_BIN=$(( $(($BAT_ICHG_MSB &lt;&lt; 4)) | $(($(($BAT_ICHG_LSB &amp; 0xF0)) &gt;&gt; 4)) ))
BAT_ICHG=$(echo "($BAT_ICHG_BIN*0.5)"|bc)
echo "Battery charge current = "$BAT_ICHG"mA"
</code></pre></div></div>
<p>power_status.sh</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>#!/bin/sh
# This program gets the power status (AC IN or BAT)
# I2C interface with AXP209
#
#######################################################################
# Copyright (c) 2014 by RzBo, Bellesserre, France
#
# Permission is granted to use the source code within this
# file in whole or in part for any use, personal or commercial,
# without restriction or limitation.
#
# No warranties, either explicit or implied, are made as to the
# suitability of this code for any purpose. Use at your own risk.
#######################################################################
#read Power status register @00h
POWER_STATUS=$(i2cget -y -f 1 0x34 0x00)
#echo $POWER_STATUS
# bit 7 : Indicates ACIN presence 0: ACIN does not exist; 1: ACIN present
#echo "bit 7 : Indicates ACIN presence 0: ACIN does not exist; 1: ACIN present"
#echo "bit 2 : Indicates that the battery current direction 0: battery discharge; 1: The battery is charged"
AC_STATUS=$(($(($POWER_STATUS&amp;0x80))/128)) # divide by 128 is like shifting rigth 8 times
#echo $(($POWER_STATUS&amp;0x80))
echo "AC_STATUS="$AC_STATUS
# echo $AC_STATUS
</code></pre></div></div>
<p>Lancement des scripts python</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo -s
./battinfo.sh
0xc5
BAT_STATUS=0
CHARG_IND=0
BAT_EXIST=1
CHARGE_CTL=0xc9
CHARGE_CTL2=0x45
Battery voltage = 3449.6mV
Battery discharge current = 0mA
Battery charge current = 0mA
</code></pre></div></div>
<h2 id="module-i2c-rtc-ds1307-real-time-clock">Module I2C RTC DS1307 (Real Time Clock)</h2>
<p>Liaisons entre le connecteur <strong>UEXT1</strong> de la carte <strong>A20-Olinuxino-MICRO</strong> et le module <strong>RTC DS1307 (5v) ou DS1338 (3.3v)</strong></p>
<table>
<thead>
<tr>
<th>UEXT1</th>
<th>Module RTC</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>1</strong> : +3.3v</td>
<td>Vcc</td>
</tr>
<tr>
<td><strong>2</strong> : GND</td>
<td>GND</td>
</tr>
<tr>
<td><strong>5</strong> : SCK</td>
<td>SCL</td>
</tr>
<tr>
<td><strong>6</strong> : SDA</td>
<td>SDA</td>
</tr>
</tbody>
</table>
<p><strong>ATTENTION : Utilisation du bus i2c-2</strong></p>
<p>Les i2c sur le système<br />
<code class="language-plaintext highlighter-rouge">ls /dev/i2c*</code><br />
<code class="language-plaintext highlighter-rouge">/dev/i2c-0 /dev/i2c-1 /dev/i2c-2</code></p>
<h3 id="i2c-tools">i2c-tools</h3>
<p>Installation outil de test et vérification bus i2c<br />
<code class="language-plaintext highlighter-rouge">sudo apt install i2c-tools</code></p>
<p>Les bus détectés
<code class="language-plaintext highlighter-rouge">sudo i2cdetect -l</code></p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>i2c-3 i2c mv64xxx_i2c adapter I2C adapter
i2c-1 i2c mv64xxx_i2c adapter I2C adapter
i2c-2 i2c mv64xxx_i2c adapter I2C adapter
i2c-0 i2c sun4i_hdmi_i2c adapter I2C adapter
</code></pre></div></div>
<p>Le module est connecté sur le bus 3<br />
<code class="language-plaintext highlighter-rouge">sudo i2cdetect -y 3</code></p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code> 0 1 2 3 4 5 6 7 8 9 a b c d e f
00: -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- 68 -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- --
</code></pre></div></div>
<p>On voit que le RPi a détecté un composant à ladresse 0x68 qui daprès la <a href="https://www.sparkfun.com/datasheets/Components/DS1307.pdf">doc constructeur</a> est ladresse par défaut.Il faut un élément logiciel pour le contrôler (pilote).</p>
<h3 id="pilote-du-module-ds1307">Pilote du module DS1307</h3>
<p>Le bus <strong>i2c</strong> et le pilote <strong>ds1307</strong> sont actifs dans la configuration du kernel compilé précédemment, sinon</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>#
# I2C support
#
CONFIG_I2C=y
#
# I2C RTC drivers
#
CONFIG_RTC_DRV_DS1307=y
</code></pre></div></div>
<h3 id="chargement-du-module-ds1307">Chargement du module DS1307</h3>
<p>Charger le module<br />
<code class="language-plaintext highlighter-rouge">sudo modprobe rtc_ds1307</code><br />
Préciser ladresse du composant 0x68<br />
<code class="language-plaintext highlighter-rouge">sudo -s</code><br />
<code class="language-plaintext highlighter-rouge">echo "ds1307 0x68" &gt; /sys/class/i2c-adapter/i2c-3/new_device</code><br />
On vient dassocier ladresse <strong>0x68</strong> au pilote <strong>rtc_ds1307</strong><br />
Vérification<br />
<code class="language-plaintext highlighter-rouge">dmesg | tail</code></p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>[ 1283.720988] rtc-ds1307 3-0068: registered as rtc1
[ 1283.721283] i2c i2c-3: new_device: Instantiated device ds1307 at 0x68
</code></pre></div></div>
<p>Le circuit est pris en charge et est utilisé par le système pour servir de première horloge temps réel sous la forme du fichier <strong>/dev/rtc1</strong></p>
<h3 id="mise-à-lheure">Mise à lheure</h3>
<p>On va mettre à lheure le module avec celle du système (à jour si connecté sur le réseau via ntp)<br />
<code class="language-plaintext highlighter-rouge">hwclock -f /dev/rtc1 -w</code><br />
Lecture de lheure sur le module<br />
<code class="language-plaintext highlighter-rouge">hwclock -f /dev/rtc1 -r</code></p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>2018-11-09 09:16:59.240428+0100
</code></pre></div></div>
<h3 id="chargement-automatique">Chargement automatique</h3>
<ul>
<li>Au démarrage on associe ladresse 0x68 au pilote rtc_ds1307 par le biais du fichier <strong>/etc/rc.local</strong></li>
<li>Puis on ajuste lheure système à celle de lhorloge matérielle</li>
</ul>
<p><em>Depuis la version 9 de Debian (Stretch), le script de démarrage rc.local nexiste plus, solution de contournement en utilisant Systemctl.</em></p>
<p>Créer le fichier suivant /etc/systemd/system/rc-local.service</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo nano /etc/systemd/system/rc-local.service
</code></pre></div></div>
<p>Copier le code suivant dans le fichier créé précédemment</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>[Unit]
Description=/etc/rc.local Compatibility
ConditionPathExists=/etc/rc.local
[Service]
Type=forking
ExecStart=/etc/rc.local start
TimeoutSec=0
StandardOutput=tty
RemainAfterExit=yes
SysVStartPriority=99
[Install]
WantedBy=multi-user.target
</code></pre></div></div>
<p>Créer le fichier /etc/rc.local</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo nano /etc/rc.local
</code></pre></div></div>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c">#!/bin/sh -e</span>
<span class="c">#</span>
<span class="c"># rc.local</span>
<span class="c">#</span>
<span class="c"># This script is executed at the end of each multiuser runlevel.</span>
<span class="c"># Make sure that the script will "exit 0" on success or any other</span>
<span class="c"># value on error.</span>
<span class="c">#</span>
<span class="c"># In order to enable or disable this script just change the execution</span>
<span class="c"># bits.</span>
<span class="c">#</span>
<span class="c"># By default this script does nothing.</span>
<span class="nv">I2CDIR</span><span class="o">=</span>/sys/class/i2c-adapter/i2c-3
<span class="k">if</span> <span class="o">[</span> <span class="nt">-d</span> <span class="s2">"</span><span class="nv">$I2CDIR</span><span class="s2">"</span> <span class="o">]</span><span class="p">;</span> <span class="k">then
</span><span class="nb">echo</span> <span class="s2">"ds1307 0x68"</span> <span class="o">&gt;</span> <span class="nv">$I2CDIR</span>/new_device
hwclock <span class="nt">-f</span> /dev/rtc1 <span class="nt">-s</span>
<span class="k">fi
</span><span class="nb">exit </span>0
</code></pre></div></div>
<p>Le chemin est stocké dans une variable <strong>I2CDIR</strong> et est utilisée pour tester si le répertoire existe :</p>
<ul>
<li>Dans le cas où il nexiste pas ,cela signifie que le pilote pour le support i2c ne sest pas chargé .</li>
<li>Si le répertoire existe ,la commande est exécuter pour déclarer le composant sur le bus et mettre à jour lheure système</li>
</ul>
<p>Ajouter lautorisation dexécution au script /etc/rc.local créer précédemment</p>
<p>sudo chmod +x /etc/rc.local</p>
<p>Finalement, activer le nouveau service rc-local au démarrage de votre serveur</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo systemctl enable rc-local
sudo systemctl daemon-reload
</code></pre></div></div>
<p>Désormais, lorsque votre serveur Linux va démarrer, le script rc.local que vous venez de créer sera exécuté.</p>
</div>
<div class="d-print-none"><footer class="article__footer"><meta itemprop="dateModified" content="2019-03-15T00:00:00+01: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/03/15/Debian_Stretch-VirtualBox.html">Virtuel "Debian Stretch" ouestline.net (VirtualBox/PC1)</a></div><div class="next"><span>SUIVANT</span><a href="/2019/03/16/Cubieboard2-Armbian-DebianStretch.html">Cubieboard2 Debian Stretch xoyize.xyz</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>