yannstatic/static/2020/03/30/UPS-APC-Onduleur-USB.html

2743 lines
236 KiB
HTML
Raw Permalink 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>UPS APC (apcupsd) - Onduleur "Eaton Protection Station 800 USB" - YannStatic</title>
<meta name="description" content="LAPC UPS peut communiquer avec le système Linux via une connexion série RS-232 ou USB. En cas de panne de courant prolongée, si lAPC UPS perd la majeure pa...">
<link rel="canonical" href="https://static.rnmkcy.eu/2020/03/30/UPS-APC-Onduleur-USB.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;">UPS APC (apcupsd) - Onduleur "Eaton Protection Station 800 USB"</h1></header></div><meta itemprop="headline" content="UPS APC (apcupsd) - Onduleur "Eaton Protection Station 800 USB""><div class="article__info clearfix"><ul class="left-col menu"><li>
2024-11-08 14:10:33 +01:00
<a class="button button--secondary button--pill button--sm" style="color:#00FFFF" href="/archive.html?tag=divers">divers</a>
2024-10-31 20:18:37 +01:00
</li></ul><ul class="right-col menu"><li>
<i class="far fa-calendar-alt"></i>&nbsp;<span title="Création" style="color:#FF00FF">30&nbsp;mars&nbsp;&nbsp;2020</span>
<span title="Modification" style="color:#00FF7F">&nbsp;4&nbsp;nov.&nbsp;&nbsp;2020</span></li></ul></div><meta itemprop="datePublished" content="2020-11-04T00:00:00+01:00">
<meta itemprop="keywords" content="divers"><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><p><em>LAPC UPS peut communiquer avec le système Linux via une connexion série RS-232 ou USB. En cas de panne de courant prolongée, si lAPC UPS perd la majeure partie de sa capacité de batterie, il peut demander au boîtier Linux deffectuer un arrêt en toute sécurité.</em></p>
<h1 id="onduleur-eaton-protection-station-800-usb">Onduleur Eaton Protection Station 800 USB</h1>
<p><img src="/images/eaton-logo.png" alt="eaton" /></p>
<ul>
<li><a href="http://lit.powerware.com/ll_download.asp?file=Eaton_Protection_Station_650_800_Installation_and_user_manual_FR.pdf&amp;ctry=80">Eaton Protection Station - 650/800 - Manuel dinstallation et dutilisation</a></li>
<li>Définitions
<ul>
<li>UPS = Uninterruptable Power System</li>
<li>ASI = Alimentation Sans Interruption</li>
<li>Le périphérique UPS <strong>Eaton Protection Station 800 USB</strong> à gérer est de type “HID”</li>
</ul>
</li>
</ul>
<p><img src="/images/onduleur-eaton.png" alt="alt text" title="Eaton Protection Station 800 USB" /></p>
<table>
<thead>
<tr>
<th>No</th>
<th>Eaton Protection Station - 650/800</th>
</tr>
</thead>
<tbody>
<tr>
<td>7</td>
<td>4 prises filtrées.</td>
</tr>
<tr>
<td>8</td>
<td>4 prises secourues par batterie.</td>
</tr>
<tr>
<td>9</td>
<td>Voyant allumé, protection anti-surtensions active sur les 8 prises.</td>
</tr>
<tr>
<td>10</td>
<td>Voyant allumé, défaut de lAlimentation Sans Interruption.</td>
</tr>
<tr>
<td>11</td>
<td>Bouton de mise en service ou darrêt des prises secourues.</td>
</tr>
<tr>
<td>12</td>
<td>Disjoncteur de protection.</td>
</tr>
</tbody>
</table>
<p>Passer en mode su</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo -s
</code></pre></div></div>
<p>Connecter londuleur liaison USB sur un port disponible du serveur , vérifier par <code class="language-plaintext highlighter-rouge">dmesg</code></p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>dmesg | grep -i eaton
</code></pre></div></div>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>[24953.861513] usb 6-1: Manufacturer: EATON
[24956.055655] hid-generic 0003:0463:FFFF.0008: hiddev0,hidraw0: USB HID v10.10 Device [EATON Protection Station] on usb-0000:00:13.0-1/input0
</code></pre></div></div>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>lsusb | grep -i ups
</code></pre></div></div>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Bus 006 Device 010: ID 0463:ffff MGE UPS Systems UPS
</code></pre></div></div>
<p>Déterminer le numéro de série</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code> udevadm info --attribute-walk --name=/dev/usb/hiddev0 | egrep 'manufacturer|product|serial'
</code></pre></div></div>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code> ATTRS{product}=="Protection Station"
ATTRS{manufacturer}=="EATON"
ATTRS{serial}=="AN2E49008"
ATTRS{manufacturer}=="Linux 4.19.0-8-amd64 ohci_hcd"
ATTRS{product}=="OHCI PCI host controller"
ATTRS{serial}=="0000:00:13.0"
</code></pre></div></div>
<h1 id="apc-ups-apcupsd">APC UPS (apcupsd)</h1>
<ul>
<li><a href="https://www.pontikis.net/blog/apc-ups-master-slave-setup-apcupsd">How to Use APC UPS with Two or More Computers apcupsd Master Slave Setup</a></li>
<li><a href="https://doc.ubuntu-fr.org/ups_apc">Installer et configurer un UPS APC avec Ubuntu</a></li>
</ul>
<h2 id="installation">Installation</h2>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo pacman -S apcupsd # archlinux
sudo apt install apcupsd # debian
</code></pre></div></div>
<h2 id="configurer-londuleur-apc">Configurer londuleur APC</h2>
<p>Le fichier de configuration principal du démon APC UPS se trouve dans <strong>/etc/apcupsd/apcupsd.conf</strong>
Les lignes de texte sont modifiées pour prendre en charge un câble de style USB:</p>
<p>Avant:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>UPSCABLE smart
UPSTYPE smartups
DEVICE /dev/ttyS0
</code></pre></div></div>
<p>Après:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>UPSCABLE usb
UPSTYPE usb
# For USB UPSes, leave the DEVICE directive blank.
DEVICE
</code></pre></div></div>
<h2 id="tester">Tester</h2>
<p><strong>archlinux</strong> , activez et démarrez apcupsd.service</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo systemctl enable apcupsd.service &amp;&amp; systemctl start apcupsd.service
</code></pre></div></div>
<p><strong>debian</strong> , redémarrez apcupsd.service</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>systemctl restart apcupsd.service
</code></pre></div></div>
<p>Ensuite, attendez environ une minute et vérifiez que le démon fonctionne et surveille correctement la batterie:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>apcaccess status
</code></pre></div></div>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>APC : 001,028,0672
DATE : 2020-03-30 08:20:43 +0200
HOSTNAME : srvxo
VERSION : 3.14.14 (31 May 2016) debian
UPSNAME : srvxo
CABLE : USB Cable
DRIVER : USB UPS Driver
UPSMODE : Stand Alone
STARTTIME: 2020-03-30 07:56:20 +0200
MODEL : Protection Station
STATUS : ONLINE
LOADPCT : 25.0 Percent
BCHARGE : 100.0 Percent
TIMELEFT : 10.7 Minutes
MBATTCHG : 5 Percent
MINTIMEL : 3 Minutes
MAXTIME : 0 Seconds
OUTPUTV : 230.0 Volts
DWAKE : -1 Seconds
LOTRANS : 184.0 Volts
HITRANS : 264.0 Volts
ALARMDEL : 30 Seconds
NUMXFERS : 0
TONBATT : 0 Seconds
CUMONBATT: 0 Seconds
XOFFBATT : N/A
STATFLAG : 0x05000008
SERIALNO : AN2E49008
END APC : 2020-03-30 08:21:30 +0200
</code></pre></div></div>
<p>Pour tester entièrement votre configuration:</p>
<ol>
<li>Modifiez TIMEOUT de 0 à 1 dans le fichier /etc/apcupsd/apcupsd.conf</li>
<li>Coupez lalimentation murale de londuleur.</li>
<li>Observez que votre box Linux séteint rapidement.</li>
<li>Rebranchez londuleur</li>
<li>Allumez votre box Linux.</li>
<li>Remplacez TIMEOUT de 1 à 0 dans le fichier /etc/apcupsd/apcupsd.conf</li>
</ol>
<p>Il ne reste plus quà activer le service apcupsd</p>
<h3 id="test-de-communication">Test de communication</h3>
<p>À ce stade, vous devez vous assurer que <em>apcupsd</em> gère correctement la connexion à londuleur. Ce test suppose que vous disposez dun onduleur qui parle le protocole apcsmart, via USB ou un port série. Si vous avez un onduleur de signalisation de tension à lancienne, veuillez passer à la section suivante ( test de panne de courant simulé ).</p>
<p>Quand apcupsd détecte un problème, il génère un ÉVÉNEMENT (EVENT), qui consiste à envoyer un message au journal système puis à appeler le script apccontrol (normalement dans <strong>/etc/acpupsd/apccontrol</strong>) pour gérer lévénement.</p>
<p>Pour créer un événement, retirez la fiche du port série à larrière de votre ordinateur ou à larrière de londuleur. Dans les 6 secondes, apcupsd devrait détecter le manque de communications du port série et diffuser un message mural indiquant que les communications du port série ont été perdues:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Warning communications lost with UPS lost. # Communications d'avertissement perdues avec UPS perdu.
</code></pre></div></div>
<p>En même temps, il envoie le même message au journal système et au fichier EVENTS temporaire ( /etc/apcupsd/apcupsd.events ).</p>
<p>Rebranchez la prise du port série sur votre ordinateur et dans environ 12 secondes, apcupsd devrait rétablir les communications et diffuser et enregistrer le message suivant:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Communications with UPS restored. # Les communications avec UPS ont été rétablies.
</code></pre></div></div>
<p>Si ces messages sont enregistrés mais ne sont pas diffusés, soit vous avez la permission de mesg définie sur no (voir <code class="language-plaintext highlighter-rouge"> man wall</code> ou <code class="language-plaintext highlighter-rouge">man mesg</code> ), soit il y a un problème avec apccontrol. Si vous exécutez un gestionnaire de fenêtres tel que GNOME et que vous navez pas de fenêtre de console ouverte, vous risquez de ne pas recevoir les messages du wall . Cependant, vous devez les trouver dans votre fichier journal système (normalement /var/log/messages ) et dans le fichier EVENTS temporaire, /etc/apcupsd/apcupsd.events . Par exemple, pour observer ces événements dans le fichier EVENTS temporaire, vous pouvez effectuer une</p>
<p>tail -f /etc/apcupsd/apcupsd.events</p>
<blockquote>
<p>Remarque: si vous avez installé à partir du RPM, le fichier dévénements approprié peut être /var/log/apcupsd.events . Vous pouvez trouver le nom de fichier réel en vérifiant votre fichier apcupsd.conf avant dexécuter le test.Si vous nobservez pas ces messages, vous devez corriger ce problème avant de procéder à des tests supplémentaires.</p>
</blockquote>
<h3 id="test-de-panne-de-courant-simulé-simulated-power-fail-test">Test de panne de courant simulé (Simulated Power Fail Test)</h3>
<p>À ce stade, vous devez vérifier quen cas de panne de courant, apcupsd appelle correctement apccontrol. Ce test convient à tous les modèles donduleurs (intelligents ou muets).</p>
<p>Pour éviter la possibilité que apcupsd puisse arrêter votre système, localisez où réside apccontrol sur votre système (normalement, /etc/apcupsd/apccontrol. Déplacez ce script vers un autre emplacement, par exemple apccontrol.save et remplacez-le par le script trouvé dans examples / safe .apccontrol. Lorsque cela est fait, assurez-vous que la batterie de votre onduleur est complètement chargée et quil vous reste au moins 5 minutes dautonomie sur les batteries. Cela peut être fait en examinant les valeurs des variables BATTCHG et TIMELEFT dans limpression de <code class="language-plaintext highlighter-rouge">apcaccess status</code></p>
<p>Bien que cela ne soit pas nécessaire, par mesure de précaution supplémentaire, vous pouvez arrêter votre machine, retirer la fiche de londuleur que vous testez et brancher votre machine sur un autre onduleur ou directement dans le wall. Cela garantira que londuleur ne coupe pas lalimentation de votre machine au mauvais moment. Noubliez pas à la fin du test de rebrancher votre machine sur londuleur.</p>
<p>Vous pouvez également minimiser le risque dun arrêt inattendu en utilisant un système de fichiers de journalisation tel que EXT3 de Linux. Tous les lecteurs de disque modernes se garent en toute sécurité lorsquils séteignent, plutôt que de labourer de loxyde sur la surface denregistrement de votre disque. Ainsi, une puissance inattendue moindre doit frapper des fenêtres de synchronisation très étroites afin de jeter une transaction EXT3.</p>
<p>Pour commencer le test, retirez la fiche dalimentation de londuleur. La première fois que vous faites cela, psychologiquement, ce ne sera pas facile, mais après avoir débranché la prise plusieurs fois, vous pourrez même en profiter. Si tout se passe bien, apcupsd devrait détecter la panne de courant et imprimer plusieurs messages davertissement. Le premier devrait apparaître après 5 à 6 secondes et lire:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code> Warning power loss detected. # Avertissement: perte de puissance détectée.
</code></pre></div></div>
<p>Puis généralement 6 secondes plus tard, apcupsd est sûr que ce nest pas un effet transitoire, il envoie donc:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Power failure. Running on UPS batteries. # Panne électrique. Fonctionnant sur batteries UPS.
</code></pre></div></div>
<p>Après quelques secondes de plus (au total environ 15 secondes), rebranchez le cordon dalimentation et assurez-vous quapcupsd sait que lalimentation est revenue. Il devrait imprimer:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Power has returned... # Le pouvoir est revenu ...
</code></pre></div></div>
<p>Si vous nobservez pas les messages ci-dessus, veuillez corriger la situation avant de continuer. La cause la plus probable des problèmes est:</p>
<ul>
<li>apcupsd ne reconnaît pas la panne de courant car les directives de configuration ne sont pas correctes. Par exemple, un mauvais câble.</li>
<li>Le fichier /etc/apcupsd/apccontrol nexiste pas ou nest pas marqué comme exécutable.</li>
</ul>
<h3 id="test-darrêt-du-système-system-shutdown-test">Test darrêt du système (System Shutdown Test)</h3>
<p>Il sagit dun test intermédiaire que vous pouvez effectuer pour tous les modèles donduleurs avant deffectuer le test de mise hors tension complète. Modifiez dabord le fichier <strong>/etc/apcupsd/apccontrol</strong> afin que dans le cas killpower , la ligne qui ré-exécute apcupsd avec loption <code class="language-plaintext highlighter-rouge">--killpower</code> soit mise en commentaire. La ligne dorigine ressemble probablement à quelque chose comme:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>${APCUPSD} --killpower
</code></pre></div></div>
<p>quand il est commenté, il ressemble à:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>#${APCUPSD} --killpower
</code></pre></div></div>
<p>Maintenant, lorsque vous débranchez la prise dalimentation et que la minuterie expire ou que les piles sont épuisées (voir la section suivante pour plus de détails), le système doit être complètement arrêté.</p>
<p>Après avoir effectué ce test, assurez-vous de restaurer <strong>/etc/apcupsd/apccontrol</strong> à son état précédent.</p>
<h3 id="test-de-mise-hors-tension-totale-full-power-down-test">Test de mise hors tension totale (Full Power Down Test)</h3>
<p>Pour terminer les tests, vous devez procéder à un arrêt en cas de panne de courant de votre système. Ce test est applicable à tous les modèles dUPS. Veuillez faire une sauvegarde de votre système ou prendre dautres précautions avant dessayer pour éviter la possibilité de perte de données en raison dun problème</p>
<p>Avant de continuer, assurez-vous que votre script darrêt ou léquivalent a été correctement mis à jour par le processus dinstallation pour contenir la logique dappeler <code class="language-plaintext highlighter-rouge">apcupsd --killpower</code> ou <code class="language-plaintext highlighter-rouge">apccontrol killpower</code> lorsquil détecte une situation de panne de courant (présence dun fichier / etc / powerfail ). Consultez la section <a href="#">Construction et installation dapcupsd</a> de ce manuel ou les fichiers README pour plus de détails sur les modifications darrêt nécessaires.</p>
<p>Lorsque vous êtes prêt à faire le test, soit débranchez simplement la prise et attendez que les batteries soient épuisées, soit définissez la directive de configuration TIMEOUT sur quelque chose comme 60 afin que le système sarrête avant que les batteries ne soient épuisées. Nous vous recommandons de faire larrêt complet sans utiliser TIMEOUT pour simuler correctement une véritable panne de courant, mais le choix vous appartient</p>
<p>Si tout se passe bien, votre système doit être arrêté avant que les batteries ne soient complètement épuisées et londuleur doit être mis hors tension par apcupsd. Veuillez noter que si vous éteignez complètement, vous devez vous assurer que votre onduleur est totalement éteint. Sinon, il a peut-être reçu la commande de mise hors tension, mais en raison dune longue période de grâce, il attend toujours. Si vous deviez redémarrer votre ordinateur pendant la période de grâce, londuleur pourrait alors soudainement couper lalimentation (cela mest arrivé). Pour éviter ce problème, attendez toujours que votre onduleur se mette hors tension ou éteignez-le manuellement avant de redémarrer votre ordinateur. Sur mon système, londuleur est configuré comme en usine pour avoir une période de grâce de 180 secondes avant de couper lalimentation. Au cours de ce type de test, 180 secondes semblent être une éternité, alors prenez soin dattendre ou déteindre manuellement votre onduleur. Pour déterminer quelle période de grâce est programmée dans votre UPS EEPROM, exécutez « apcaccess eprom » et regardez le ““Shutdown grace delay”.</p>
<p>Si vous avez rencontré des problèmes avec les procédures de test ci-dessus, ou si vous portez apcupsd vers un autre système, ou si vous êtes simplement curieux, vous voudrez peut-être savoir exactement ce qui se passe pendant le processus darrêt. Si tel est le cas, veuillez consulter la section <a href="URL">Séquence darrêt</a> de ce manuel.</p>
<h3 id="apctest">apctest</h3>
<p>apctest est un programme qui vous permet de parler directement à votre onduleur et dexécuter certains tests de bas niveau, dajuster divers paramètres tels que la date dinstallation de la batterie et le comportement de lalarme, et deffectuer un étalonnage de lautonomie de la batterie. Nous décrivons ici comment lutiliser pour un SmartUPS utilisant le pilote apcsmart et la connexion série RS232. Les menus et les options pour les onduleurs USB, MODBUS et de signalisation simple sont différents mais pour la plupart explicites.</p>
<p>Arrêtez <em>apcupsd</em> sil est en cours dexécution. Cest important. Un seul programme peut communiquer avec londuleur à la fois et si apcupsd est en cours dexécution, apctest ne parviendra pas à contacter londuleur.</p>
<p>Exécutez <strong>apctest</strong> en linvoquant sans argument.</p>
<p>Il lira votre configuration <strong>apcupsd.conf</strong> installée (afin quil sache où trouver londuleur), puis il vous présentera la sortie suivante:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code> 2003-07-07 11:19:21 apctest 3.10.6 (07 juillet 2003) redhat
Vérification de la configuration ...
Attaché au pilote: apcsmart
sharenet.type = DESACTIVER
cable.type = CUSTOM_SMART
Vous utilisez un type de câble SMART, donc j'entre en mode de test SMART
mode.type = SMART
Configuration du port série ...
Création d'un fichier de verrouillage de port série ...
Bonjour, voici le programme de test de câbles apcupsd.
Cette partie d'apctest sert à tester les onduleurs intelligents.
Veuillez sélectionner la fonction que vous souhaitez exécuter.
1) Interrogez l'onduleur pour toutes les valeurs connues
2) Effectuez un étalonnage de l'autonomie de la batterie
3) Annuler l'étalonnage de la batterie
4) Surveiller la progression de l'étalonnage de la batterie
5) Programme EEPROM
6) Entrer en mode TTY communiquant avec UPS
7) Quittez
Sélectionnez le numéro de fonction: 1
#
2003-07-07 11:19:21 apctest 3.10.6 (07 July 2003) redhat
Checking configuration ...
Attached to driver: apcsmart
sharenet.type = DISABLE
cable.type = CUSTOM_SMART
You are using a SMART cable type, so I'm entering SMART test mode
mode.type = SMART
Setting up serial port ...
Creating serial port lock file ...
Hello, this is the apcupsd Cable Test program.
This part of apctest is for testing Smart UPSes.
Please select the function you want to perform.
1) Query the UPS for all known values
2) Perform a Battery Runtime Calibration
3) Abort Battery Calibration
4) Monitor Battery Calibration progress
5) Program EEPROM
6) Enter TTY mode communicating with UPS
7) Quit
Select function number: 1
</code></pre></div></div>
<ol>
<li>va sonder londuleur pour toutes les valeurs connues de apcupsd et les présenter dans un format plutôt brut. Cette sortie peut être utile pour fournir une assistance technique si vous rencontrez des problèmes avec votre onduleur.</li>
<li>effectuera un étalonnage de lautonomie de la batterie. Ce test ne sera effectué que si votre batterie est chargée à 100%. Lexécution du test entraînera la décharge des batteries à environ 30% de leur capacité. Le nombre exact dépend du modèle dUPS. Dans tous les cas, apctest abandonnera le test sil détecte que la charge de la batterie est de 20% ou moins.<br />
Lavantage de ce test est que londuleur pourra recalibrer le compteur dexécution restant quil conserve dans son micrologiciel. À mesure que vos batteries vieillissent, elles ont tendance à tenir moins en charge, de sorte que le calibrage de la durée de fonctionnement peut ne pas être précis après plusieurs années.<br />
Nous recommandons deffectuer un étalonnage de la batterie environ une fois par an. Vous ne devez pas effectuer cet étalonnage trop souvent car la décharge des batteries a tendance à raccourcir leur durée de vie.</li>
<li>peut être utilisé pour abandonner un étalonnage de la batterie en cours, si vous avez été déconnecté.</li>
<li>peut être utilisé pour redémarrer la surveillance dun étalonnage de batterie si vous deviez vous déconnecter pendant le test.</li>
<li>est utilisé pour programmer lEEPROM. Voir <a href="http://www.apcupsd.org/manual/manual.html#configuration-directives-used-to-set-the-ups-eeprom">Configuration Directives Used to Set the UPS EEPROM</a></li>
<li>initiera une communication directe entre votre terminal et londuleur, auquel cas vous pourrez saisir des commandes brutes de londuleur. Veuillez noter que vous devez faire attention aux commandes que vous entrez car vous pouvez provoquer larrêt soudain de votre onduleur ou vous pouvez modifier lEEPROM de manière à désactiver votre onduleur. Les détails des commandes brutes du mode Smart UPS se trouvent dans le chapitre APC Smart Protocol de ce manuel.</li>
<li>mettra fin à apctest.</li>
</ol>
<h2 id="surveillance-et-réglage-de-votre-ups-monitoring-and-tuning-your-ups">Surveillance et réglage de votre UPS (Monitoring and Tuning your UPS)</h2>
<p>Après avoir vérifié que votre onduleur fonctionne correctement, vous souhaiterez probablement interroger occasionnellement son état de santé. Les outils que apcupsd vous offre pour ce faire incluent un utilitaire de ligne de commande (apcaccess) et une interface graphique que vous pouvez utiliser via un navigateur Web. Vous pouvez également utiliser apctest pour régler certains paramètres de londuleur lui-même.
apcaccess</p>
<p>apcaccess est un programme (normalement présent dans /sbin/apcaccess) qui vous permet dimprimer létat complet de votre onduleur.</p>
<p>apcaccess utilisera le Network Information Server pour obtenir les informations nécessaires. Vous pouvez spécifier un deuxième argument facultatif pour apcaccess sous la forme de host: port où :: port est facultatif. La valeur par défaut est localhost: 3551 . Veuillez noter que dans les versions antérieures à 3.10.6, le port NIS par défaut était 7000, donc si vous mélangez des versions, vous devrez faire très attention pour vous assurer que tous les composants utilisent le même port.</p>
<p>Pour activer le serveur dinformations réseau apcupsd, qui est normalement la valeur par défaut, vous définissez:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>NETSERVER on
NISPORT 3551
</code></pre></div></div>
<p>dans votre fichier apcupsd.conf</p>
<p>La forme complète de la commande apcaccess est:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>apcaccess status localhost:3551
</code></pre></div></div>
<p>où seul le statut apcaccess devrait normalement être nécessaire. localhost peut être remplacé par nimporte quel nom dordinateur, nom de domaine complet ou adresse IP, ce qui signifie quapcaccess peut accéder à nimporte quel onduleur sur le réseau exécutant le Network Information Server.</p>
<p>Loption de ligne de commande d état dapcaccess produira une impression complète de toutes les variables STATUS utilisées par apcupsd. Cela peut être très utile pour vérifier létat de votre onduleur et savoir si apcupsd y est correctement connecté.</p>
<p>Veuillez noter que si vous appelez apcaccess dans les 30 premières secondes suivant le lancement dapcupsd, vous obtiendrez probablement un message derreur tel que:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>APCACCESS FATAL ERROR in apcaccess.c at line 336
tcp_open: cannot connect to server localhost on port 3551.
</code></pre></div></div>
<p>En effet, apcupsd est toujours en cours dinitialisation de londuleur. La solution consiste à attendre au moins 30 secondes après le démarrage dapcupsd avant de lancer apcaccess.</p>
<p>Pour un SmartUPS 1000 apcaccess émettra la sortie suivante:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>DATE : Fri Dec 03 12:34:26 CET 1999
HOSTNAME : matou
RELEASE : 3.7.0-beta-1
CABLE : Custom Cable Smart
MODEL : SMART-UPS 1000
UPSMODE : Stand Alone
UPSNAME : UPS_IDEN
LINEV : 232.7 Volts
MAXLINEV : 236.6 Volts
MINLINEV : 231.4 Volts
LINEFREQ : 50.0 Hz
OUTPUTV : 232.7 Volts
LOADPCT : 11.4 Percent Load Capacity
BATTV : 27.7 Volts
BCHARGE : 100.0 Percent
MBATTCHG : 5 Percent
TIMELEFT : 112.0 Minutes
MINTIMEL : 3 Minutes
SENSE : Low
DWAKE : 060 Seconds
DSHUTD : 180 Seconds
LOTRANS : 204.0 Volts
HITRANS : 253.0 Volts
RETPCT : 050.0 Percent
STATFLAG : 0x08 Status Flag
STATUS : ONLINE
ITEMP : 29.2 C Internal
ALARMDEL : Low Battery
LASTXFER : U command or Self Test
SELFTEST : NO
STESTI : 336
DLOWBATT : 02 Minutes
DIPSW : 0x00 Dip Switch
REG1 : 0x00 Register 1
REG2 : 0x00 Register 2
REG3 : 0x00 Register 3
MANDATE : 01/05/99
SERIALNO : GS9902009459
BATTDATE : 01/05/99
NOMOUTV : 230.0
NOMBATTV : 24.0
HUMIDITY : N/A
AMBTEMP : N/A
EXTBATTS : 0
BADBATTS : N/A
FIRMWARE : 60.11.I
APCMODEL : IWI
END APC : Fri Dec 03 12:34:33 CET 1999
</code></pre></div></div>
<p>Pour les différents onduleurs USB APC plus petits et moins chers, tels que les CS, ES, …, vous obtiendrez la plupart des informations présentées ci-dessus, mais pas toutes. Par exemple, vous nobtiendrez pas MAXLINEV , MINLINEV , LINEFREQ , … et en particulier, le LOADPCT sera nul lorsque vous utilisez le secteur. LOADPCT saffiche lorsque londuleur est sur batteries. Vous devez vous rappeler que les non-SmartUPS sont beaucoup plus simples (et moins chers) et produisent donc moins dinformations.</p>
<h2 id="notification-et-événements-apcupsd-apcupsd-notification-and-events">Notification et événements Apcupsd (Apcupsd Notification and Events)</h2>
<p>Lorsquun événement majeur est généré dans apcupsd, le contrôle est passé au script apccontrol qui se trouve normalement dans /etc/apcupsd/apccontrol. Le nom de lévénement et un certain nombre dautres paramètres importants sont transmis au script.</p>
<p>La fonction principale du script apccontrol est deffectuer un arrêt du système (ainsi que lopération killpower). De plus, une autre tâche majeure de ce script est de vous avertir par e-mail lorsque certains événements tels que PowerFail se produisent.</p>
<p>Comme apccontrol est un script, vous pouvez le personnaliser selon vos besoins en utilisant nimporte quel éditeur de texte. Pour ce faire, vous devez avoir une connaissance minimale de la programmation shell Unix. De plus, une autre fonctionnalité est que vous pouvez écrire vos propres scripts qui seront automatiquement appelés par apccontrol avant lexécution de son propre code. Les détails des événements et la façon de les programmer sont contenus dans la section Rubriques avancées intitulée Personnalisation de la gestion des événements</p>
<h2 id="cgi">CGI</h2>
<h3 id="programmes-de-surveillance-de-réseau-apcupsd-cgi-apcupsd-network-monitoring-cgi-programs">Programmes de surveillance de réseau apcupsd (CGI) (apcupsd Network Monitoring (CGI) Programs)</h3>
<p>Il existe quatre programmes CGI (<strong>multimon.cgi upsstats.cgi upsfstats.cgi upsimage.cgi</strong>). Pour les installer correctement, vous devez exécuter la commande ./configure avec enable-cgi et vous devez spécifier un répertoire dinstallation avec <code class="language-plaintext highlighter-rouge">--with-cgi-bin=</code> ou les charger manuellement. Le répertoire par défaut pour linstallation des programmes CGI est / etc / apcupsd , qui nest pas vraiment là où vous les voulez si vous comptez les utiliser. Normalement, ils devraient aller dans le cgi-bin de votre serveur Web.</p>
<p>Une fois construits et chargés, ils vous donneront le statut de votre ou vos UPS via un navigateur Web.</p>
<p>Normalement, seul <strong>multimon.cgi</strong> est directement invoqué par lutilisateur.<br />
Cependant, il est possible dappeler directement <strong>upsstats.cgi</strong> et <strong>upsfstats.cgi</strong><br />
<u>**upsimage.cgi** ne doit jamais être invoqué directement</u> car il est utilisé par upsstats.cgi pour produire les graphiques à barres.</p>
<h3 id="configuration-et-test-des-programmes-cgi">Configuration et test des programmes CGI</h3>
<p>Avant dutiliser multimon et les autres programmes CGI, assurez-vous dabord que apcupsd est configuré pour exécuter le Network Information Server. Pour ce faire, définissez NETSERVER sur dans /etc/apcupsd/apcupsd.conf. Ce commutateur est activé par défaut.</p>
<p>Ensuite, vous devez modifier le fichier hosts /etc/apcupsd/hosts.conf et à la fin, ajouter le nom des hôtes que vous souhaitez surveiller et une chaîne détiquette pour eux.<br />
Par exemple:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>MONITOR matou "Server"
MONITOR polymatou "Backup server"
MONITOR deuter "Disk server"
</code></pre></div></div>
<p>matou, polymatou et deuter sont les noms de réseau des trois machines exécutant actuellement apcupsd. Veuillez noter que les noms de réseau peuvent être des adresses IP ou des noms de domaine complets. Le nom du réseau (ou ladresse IP) peut éventuellement être suivi de : port , où le port est ladresse du port NIS que vous souhaitez utiliser. Cela est utile si vous exécutez plusieurs copies dapcupsd sur le même système ou si vous exécutez dans un environnement mixte de fournisseurs où les affectations de port NIS diffèrent.<br />
Un exemple pourrait être le suivant:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>MONITOR matou "Server"
MONITOR polymatou "Backup server"
MONITOR deuter "Disk server"
MONITOR polymatou:7001 "APC USB UPS"
</code></pre></div></div>
<p>où la copie USB dapcupsd a été configurée pour utiliser le port 7001 en modifiant apcupsd.conf. Remarque, le port NIS par défaut est 3551 sur la plupart des plates-formes.</p>
<p>Pour tester multimon.cgi, vous pouvez lexécuter en tant que non root directement à partir du répertoire de génération cgi source. Pour ce faire, entrez à linvite du shell:</p>
<p>./multimon.cgi</p>
<p>Si tout est correctement configuré, il imprimera un tas de code HTML avec les valeurs des machines que vous avez placées dans le fichier hosts.conf. Il devrait ressembler à ce qui suit (notez que seule une petite partie de la sortie est reproduite ici):</p>
<p>Type de contenu: texte / html</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>&lt;!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"
"http://www.w3.org/TR/REC-html40/loose.dtd"&gt;
&lt;HTML&gt;
&lt;HEAD&gt;&lt;TITLE&gt;Multimon: UPS Status Page&lt;/TITLE&gt;&lt;/HEAD&gt;
&lt;BODY BGCOLOR="#FFFFFF"&gt;
&lt;TABLE BGCOLOR="#50A0A0" ALIGN=CENTER&gt;
&lt;TR&gt;&lt;TD&gt;
&lt;TABLE CELLPADDING=5&gt;
&lt;TR&gt;
&lt;TH COLSPAN=10 BGCOLOR="#60B0B0"&gt;
&lt;FONT SIZE="+2"&gt;APCUPSD UPS Network Monitor&lt;/FONT&gt;
&lt;BR&gt;Sun Jan 16 12:07:27 CET 2000&lt;/TH&gt;
&lt;/TR&gt;
&lt;TR BGCOLOR="#60B0B0"&gt;
&lt;TH COLSPAN=1&gt;System&lt;/TH&gt;
&lt;TH COLSPAN=1&gt;Model&lt;/TH&gt;
&lt;TH COLSPAN=1&gt;Status&lt;/TH&gt;
...
</code></pre></div></div>
<p>Si vous nobtenez pas de sortie similaire, vérifiez les autorisations du répertoire /etc/apcupsd et celles de /etc/apcupsd/hosts.conf pour vous assurer que votre serveur Web peut y accéder. Sur de nombreux sites, le serveur Apache ne sexécute pas en tant que root, vous devez donc vous assurer que /etc/apcupsd/hosts.conf et /etc/apcupsd/multimon.conf sont lisibles par tous.</p>
<p>Pour appeler multimon dans votre navigateur Web, entrez:</p>
<p>http://your-site/cgi-bin/multimon.cgi</p>
<p>Vous devriez obtenir quelque chose de similaire à la capture décran ci-dessous.</p>
<p>Si vous souhaitez un contrôle supplémentaire sur les couleurs, les visages et les tailles de la sortie multimon, vous pouvez simplement modifier le fichier <strong>apcupsd.css</strong> pour spécifier les styles que vous préférez.</p>
<h3 id="multimoncgi">multimon.cgi</h3>
<p>Ce programme surveille plusieurs onduleurs en même temps. Une sortie typique de multimon.cgi telle quaffichée dans votre navigateur Web peut ressembler à ceci:</p>
<p><img src="/images/multimon.png" alt="multimon.png" /></p>
<p>Les machines surveillées ainsi que les valeurs et leurs en-têtes de colonne sont tous configurables (voir /etc/apcupsd/hosts.conf et /etc/apcupsd/multimon.conf)</p>
<h3 id="upsstatscgi">upsstats.cgi</h3>
<p>En cliquant sur le nom du système dans laffichage multimon.cgi, vous invoquerez upsstats.cgi pour le système spécifié, ce qui produira un affichage à barres de trois des valeurs surveillées. Par exemple,</p>
<p><img src="/images/status.png" alt="status.png" /></p>
<p>Vous pouvez afficher différents graphiques à barres en sélectionnant différentes variables dans les menus déroulants en haut de chacun des trois graphiques à barres.</p>
<p>Comme avec multimon, si votre hôte local est configuré dans le fichier /etc/apcupsd/hosts.conf, vous pouvez lexécuter à partir dun shell Unix depuis le répertoire cgi source comme suit:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>./upsstats.cgi
</code></pre></div></div>
<p>Comme pour multimon, quelques lignes html devraient alors être affichées.</p>
<h3 id="upsfstatuscgi">upsfstatus.cgi</h3>
<p>Si vous souhaitez voir toutes les variables STATUS disponibles sur le réseau, cliquez sur le champ Données du système souhaité et votre navigateur affichera quelque chose comme ceci:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>APC : 001,048,1109
DATE : Thu Dec 02 17:27:21 CET 1999
HOSTNAME : matou.sibbald.com
RELEASE : 3.7.0-beta-1
CABLE : Custom Cable Smart
MODEL : SMART-UPS 1000
UPSMODE : Stand Alone
UPSNAME : UPS_IDEN
LINEV : 223.6 Volts
MAXLINEV : 224.9 Volts
MINLINEV : 222.3 Volts
LINEFREQ : 50.0 Hz
OUTPUTV : 223.6 Volts
LOADPCT : 6.2 Percent Load Capacity
BATTV : 27.9 Volts
BCHARGE : 100.0 Percent
MBATTCHG : 5 Percent
TIMELEFT : 167.0 Minutes
MINTIMEL : 3 Minutes
SENSE : High
DWAKE : 060 Seconds
DSHUTD : 020 Seconds
LOTRANS : 196.0 Volts
HITRANS : 253.0 Volts
RETPCT : 050.0 Percent
STATFLAG : 0x08 Status Flag
STATUS : ONLINE
ITEMP : 35.1 C Internal
ALARMDEL : Low Battery
LASTXFER : U command or Self Test
SELFTEST : NO
STESTI : 336
DLOWBATT : 02 Minutes
DIPSW : 0x00 Dip Switch
REG1 : 0x00 Register 1
REG2 : 0x00 Register 2
REG3 : 0x00 Register 3
MANDATE : 01/11/99
SERIALNO : GS9903001147
BATTDATE : 01/11/99
NOMOUTV : 230.0
NOMBATTV : 24.0
HUMIDITY : N/A
AMBTEMP : N/A
EXTBATTS : 0
BADBATTS : N/A
FIRMWARE : 60.11.I
APCMODEL : IWI
END APC : Thu Dec 02 17:27:25 CET 1999
</code></pre></div></div>
<p>Vous devriez obtenir à peu près la même sortie mélangée avec du html si vous exécutez upsfstats.cgi directement à partir dun shell Unix dans le sous-répertoire cgi comme expliqué ci-dessus pour upsstats.cgi et multimon.cgi.</p>
<h2 id="sécurité">Sécurité</h2>
<h3 id="les-problèmes-de-sécurité">Les problèmes de sécurité:</h3>
<ul>
<li>apcupsd sexécute en tant que root.</li>
<li>
<font color="red">Si **NETSERVER** est **activé** dans votre fichier **apcupsd.conf** (qui est la valeur par défaut), sachez que toute personne sur le réseau peut lire l'état de votre onduleur.</font>
<p>Cela peut ou non poser un problème. Si vous ne considérez pas cette information comme privilégiée, comme cest le cas pour beaucoup, il y a peu de risques. De plus, si vous disposez dun pare-feu de périmètre ou dun routeur NATting avec des paramètres typiques, seuls les utilisateurs de votre réseau local ont accès aux informations de votre onduleur. Vous pouvez également restreindre laccès à laide des paramètres du pare-feu (voir ci-dessous)</p>
</li>
</ul>
<h3 id="paramètres-du-pare-feu">Paramètres du pare-feu</h3>
<p>Si vous exécutez apcupsd en tant que serveur NIS, vous devrez vous assurer que les clients peuvent y accéder en ouvrant NISPORT (par défaut: TCP 3551) sur nimporte quel pare-feu exécuté sur le serveur. Vous souhaiterez peut-être configurer vos <strong>pare-feu pour autoriser uniquement les connexions à partir de votre réseau local</strong> ou spécifiquement à partir des maîtres, des esclaves et des serveurs selon les besoins.</p>
<h2 id="annexe">Annexe</h2>
<h3 id="status">Status</h3>
<p>Pour obtenir le status complet de lUPS, commande suivante</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>apcaccess status
</code></pre></div></div>
<p>Et vous obtiendrez toutes les informations concernant lUPS (exemple ci-dessous) :</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>APC : 001,038,0930
DATE : Thu Jan 26 11:04:36 CET 2006
HOSTNAME : nodearch2
RELEASE : 3.10.17
VERSION : 3.10.17 (18 March 2005) debian
UPSNAME : nodearch2
CABLE : USB Cable
MODEL : Smart-UPS 2200 RM
UPSMODE : Stand Alone
STARTTIME: Thu Jan 26 10:59:31 CET 2006
STATUS : ONLINE
LINEV : 224.6 Volts
LOADPCT : 13.0 Percent Load Capacity
BCHARGE : 100.0 Percent
TIMELEFT : 74.0 Minutes
MBATTCHG : 5 Percent
MINTIMEL : 3 Minutes
MAXTIME : 0 Seconds
OUTPUTV : 224.6 Volts
DWAKE : -01 Seconds
DSHUTD : 090 Seconds
LOTRANS : 208.0 Volts
HITRANS : 253.0 Volts
ITEMP : 27.0 C Internal
ALARMDEL : Always
BATTV : 55.4 Volts
LINEFREQ : 50.0 Hz
NUMXFERS : 0
TONBATT : 0 seconds
CUMONBATT: 0 seconds
XOFFBATT : N/A
SELFTEST : NO
STATFLAG : 0x02000008 Status Flag
SERIALNO : JS0543013779
BATTDATE : 2005-10-19
NOMBATTV : 48.0
FIRMWARE : 65.6.I USB FW:2.4
APCMODEL : Smart-UPS 2200 RM
END APC : Thu Jan 26 11:04:37 CET 2006
</code></pre></div></div>
<p>Voici les informations détat les plus intéressantes :</p>
<ul>
<li><code class="language-plaintext highlighter-rouge">STATUS : ONLINE</code> indique létat de la ligne secteur. <code class="language-plaintext highlighter-rouge">ONLINE</code> signifie que lon fonctionne sur le secteur. <code class="language-plaintext highlighter-rouge">ONBATT</code> signifie que lon fonctionne sur batterie et <code class="language-plaintext highlighter-rouge">CHARGING</code> indique que la batterie se recharge.</li>
<li><code class="language-plaintext highlighter-rouge">LOADPCT : 13.0 Percent Load Capacity</code> indique le pourcentage de charge de lUPS. Dans ce cas, lUPS nous indique quil est à <code class="language-plaintext highlighter-rouge">13%</code> de sa charge. Lorsquon ajoute des serveurs, cette charge augmente (et, fatalement, lautonomie des batteries diminuera).</li>
<li><code class="language-plaintext highlighter-rouge">BCHARGE : 100.0 Percent</code> indique létat de charge de la batterie.</li>
<li><code class="language-plaintext highlighter-rouge">TIMELEFT : 74.0 Minutes</code> indique une estimation du temps restant en considérant la charge de lUPS et létat de la batterie.</li>
<li><code class="language-plaintext highlighter-rouge">BATTDATE : 2005-10-19</code> indique la date de mise en place de la batterie (en général, on conseille de remplacer les batteries tous les 3 ans).</li>
<li><code class="language-plaintext highlighter-rouge">ITEMP : 27.0 C Internal</code> indique la température interne de lUPS. (Noubliez pas que la température a une grande influence sur les capacités de la batterie)</li>
</ul>
<p>Voici les éléments à connaître (et à modifier suivant vos besoins) :</p>
<ul>
<li><code class="language-plaintext highlighter-rouge">MBATTCHG : 5 Percent</code> : si la batterie descend sous ce seuil, le démon <code class="language-plaintext highlighter-rouge">apcupsd</code> demande larrêt du système.</li>
<li><code class="language-plaintext highlighter-rouge">MINTIMEL : 3 Minutes</code> : si lestimation de temps restant descend sous ce seuil, le démon <code class="language-plaintext highlighter-rouge">apcupsd</code> demande larrêt du système.</li>
<li><code class="language-plaintext highlighter-rouge">MAXTIME : 0 Seconds</code> : si le système passe cette durée sur la batterie, le démon <code class="language-plaintext highlighter-rouge">apcupsd</code> demande larrêt du système. Une valeur de <code class="language-plaintext highlighter-rouge">0</code> désactive la fonctionnalité.<br />
<em>Remarque : Cette fonctionnalité est intéressante si vous navez pas de groupe électrogène. Les serveurs le moins critiques peuvent être éteint après 5 minutes sur batterie pour conserver de lénergie afin que les serveurs critiques tiennent le plus longtemps possible sans courant secteur.</em></li>
<li><code class="language-plaintext highlighter-rouge">DWAKE : -01 Seconds</code> : lorsque lUPS est sans courant (secteur ou batterie) et que le courant secteur revient, lUPS attendra cette valeur avant de provoquer lallumage des serveurs.</li>
<li><code class="language-plaintext highlighter-rouge">DSHUTD : 090 Seconds</code> : délais de “grâce” entre le moment où le démon <code class="language-plaintext highlighter-rouge">apcupsd</code> demande larrêt et larrêt effectif.</li>
</ul>
<p>Pour modifier ces éléments, vous devez modifier le fichier de configuration <code class="language-plaintext highlighter-rouge">/etc/apcupsd/apcupsd.conf</code> et ensuite lancer <code class="language-plaintext highlighter-rouge">sudo /sbin/apctest --configure</code> après avoir tué le démon <code class="language-plaintext highlighter-rouge">apcupsd</code> via la commande <code class="language-plaintext highlighter-rouge">sudo systemctl stop apcupsd</code>. Ne pas oublier de relancer le démon par la commande <code class="language-plaintext highlighter-rouge">udo systemctl start apcupsd</code></p>
<h3 id="personnalisation-de-la-gestion-des-événements">Personnalisation de la gestion des événements</h3>
<p>Lorsque apcupsd détecte des anomalies sur votre onduleur, il prend des décisions qui entraînent généralement un ou plusieurs appels au script situé dans <strong>/etc/apcupsd/apccontrol</strong>.<br />
Le fichier <strong>apccontrol</strong> est un script shell qui agit sur le premier argument qui lui est transmis par <em>apcupsd</em>.<br />
Ces actions sont configurées par défaut pour un comportement sain dans toutes les situations que <em>apcupsd</em> est susceptible de détecter depuis londuleur.<br />
Cependant, vous pouvez modifier le comportement dapccontrol pour chaque action.</p>
<p>Pour <strong>personnaliser</strong>, créez donc un fichier avec le même nom que laction, qui est passé comme argument de ligne de commande. Mettez votre script dans le répertoire <strong>/etc/apcupsd</strong></p>
<p>Ces événements sont envoyés au journal système, éventuellement envoyés au fichier dévénements temporaires ( /etc/apcupsd/apcupsd.events), et ils génèrent également un appel à <strong>/etc/apcupsd/apccontrol</strong> qui à son tour appellera tous les scripts que vous avez placés dans le répertoire <strong>/etc/apcupsd</strong></p>
<p>Normalement, <strong>/etc/apcupsd/apccontrol</strong> est appelé uniquement par <em>apcupsd</em>.<br />
Par conséquent, <u>vous ne devez pas l'invoquer directement</u>. <br />
Cependant, il est important de comprendre son fonctionnement et, dans certains cas, vous souhaiterez peut-être modifier les messages quil imprime à laide de <strong>wall</strong><br />
<u>Nous vous recommandons de le faire en écrivant votre propre script à appeler par **apccontrol**</u> plutôt quen modifiant directement apccontrol. Cela vous facilite la mise à niveau vers la prochaine version dapcupsd</p>
<p>Dans dautres cas, vous souhaiterez peut-être <u>écrire vos propres scripts shell qui seront appelés par **apccontrol**</u>.<br />
Par exemple, lorsquune panne de courant se produit, vous pouvez envoyer un e-mail à root.</p>
<p><u>Pour écrire votre propre routine pour l'action **powerout**</u> , vous créez un script shell nommé <strong>powerout</strong> et le placez dans le répertoire lib (normalement <strong>/etc/apcupsd</strong>). Lorsque laction de mise hors tension est invoquée par <em>apcupsd</em>, apccontrol donnera dabord le contrôle de votre script.</p>
<ul>
<li>Si vous souhaitez quapccontrol continue avec laction par défaut, quittez simplement votre script avec un état de sortie de zéro.</li>
<li>Si vous ne souhaitez pas quapccontrol poursuive laction par défaut, votre script doit se terminer avec le <u>code de sortie spécial 99</u>. Cependant, dans ce cas, sachez que vous devez assurer un arrêt correct de votre machine si nécessaire.</li>
</ul>
<p>Certains exemples de scripts (onbattery et mainsback) qui envoient des messages de panne de courant par e-mail peuvent être trouvés dans /etc/apcupsd après une installation ou dans le répertoire platforms/etc du code source.</p>
<p><strong>Options de ligne de commande apccontrol</strong><br />
Quand <em>apcupsd</em> détecte un événement, il appelle le script <strong>apccontrol</strong> avec <u>quatre arguments</u> comme:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>apccontrol event ups-name connected powered
</code></pre></div></div>
<p>où:</p>
<table>
<thead>
<tr>
<th>argument</th>
<th>description</th>
</tr>
</thead>
<tbody>
<tr>
<td>event</td>
<td>est lévénement qui sest produit et il peut sagir de lune des valeurs décrites dans la section suivante.</td>
</tr>
<tr>
<td>ups-name</td>
<td>est le nom de londuleur tel quil est spécifié dans le fichier de configuration (pas le nom dans lEEPROM).</td>
</tr>
<tr>
<td>connected</td>
<td>est 1 si apcupsd est connecté à londuleur via un port série (ou un port USB). Dans la plupart des configurations, ce sera le cas. Dans le cas dune machine esclave où apcupsd nest pas directement connecté à londuleur, cette valeur sera 0.</td>
</tr>
<tr>
<td>powered</td>
<td>est 1 si lordinateur sur lequel apcupsd fonctionne est alimenté par londuleur et 0 sinon. Pour le moment, cette valeur nest pas implémentée et toujours 0.</td>
</tr>
</tbody>
</table>
<p>Les noms d événements suivants sont pris en charge:</p>
<table>
<thead>
<tr>
<th>Evénement</th>
<th>Description</th>
<th>Par défaut</th>
</tr>
</thead>
<tbody>
<tr>
<td>annoyme</td>
<td>Lorsquun arrêt est planifié et que lheure spécifiée dans la directive ANNOYME dans le fichier apcupsd.conf expire, cet événement est généré.</td>
<td>wall un message</td>
</tr>
<tr>
<td>changeme</td>
<td>Lorsque apcupsd détecte que le secteur est sous tension, mais que la batterie ne fonctionne pas correctement, cet événement est généré. Il est répété toutes les x heures.</td>
<td>wall un message</td>
</tr>
<tr>
<td>commfailure</td>
<td>Cet événement est généré chaque fois que la ligne de communication avec lordinateur est coupée. Cet événement nest pas détecté sur les onduleurs de signalisation muets.</td>
<td>wall un message</td>
</tr>
<tr>
<td>commok</td>
<td>Après lémission dun événement de défaillance, lorsque les communications avec lordinateur sont rétablies, cet événement sera généré.</td>
<td>wall un message</td>
</tr>
<tr>
<td>doreboot</td>
<td>Cet événement est amorti et ne doit pas être utilisé.</td>
<td>arrête le système à laide de shutdown -h ou similaire</td>
</tr>
<tr>
<td>doshutdown</td>
<td>Lorsque londuleur fonctionne sur batteries et quune des limites expire (durée, fonctionnement, charge), cet événement est généré pour provoquer larrêt de la machine.</td>
<td>arrête le système à laide de shutdown -h ou similaire</td>
</tr>
<tr>
<td>emergency</td>
<td>Appelé pour un arrêt durgence du système. (Ce qui déclenche un tel arrêt nest pas clair …) Après avoir terminé cet événement, apcupsd lancera immédiatement un événement doshutdown .</td>
<td>wall un message</td>
</tr>
<tr>
<td>failing</td>
<td>Cet événement est généré lorsque londuleur fonctionne sur batteries et que la batterie est épuisée. Lévénement suivant celui-ci sera un arrêt.</td>
<td>wall un message</td>
</tr>
<tr>
<td>loadlimit</td>
<td>Cet événement est généré lorsque la charge de la batterie est inférieure à la limite inférieure spécifiée dans le fichier apcupsd.conf. Après avoir terminé cet événement, apcupsd lancera immédiatement un événement doshutdown .</td>
<td>wall un message</td>
</tr>
<tr>
<td>powerout</td>
<td>Cet événement est généré immédiatement lorsque apcupsd détecte que londuleur est passé aux batteries. Cela peut être dû à une panne de courant courte, à un autotest automatique de londuleur ou à une panne de courant plus longue.</td>
<td>wall un message</td>
</tr>
<tr>
<td>onbattery</td>
<td>Cet événement est généré 5 ou 6 secondes après la détection dun défaut dalimentation initial. Cela signifie que apcupsd considère définitivement londuleur comme étant sur batteries. Le début de cet événement peut être retardé par la directive de configuration ONBATTERYDELAY apcupsd.conf.</td>
<td>wall un message</td>
</tr>
<tr>
<td>offbattery</td>
<td>Cet événement est généré lorsque le réseau revient uniquement si lévénement onbattery a été généré.</td>
<td>wall un message</td>
</tr>
<tr>
<td>mainback</td>
<td>Cet événement est généré lorsque lalimentation secteur revient après une condition de mise hors tension. Lévénement darrêt peut ou non avoir été généré en fonction des paramètres que vous avez définis et de la durée de la panne de courant.</td>
<td>rien</td>
</tr>
<tr>
<td>remotedown</td>
<td>Cet événement est généré sur une machine esclave lorsquil détecte que le maître a été arrêté ou quune situation de batterie existe et que la ligne de communication a été coupée.</td>
<td>wall un message</td>
</tr>
<tr>
<td>runlimit</td>
<td>Cet événement est généré lorsque la valeur MINUTES définie dans le fichier apcupsd.conf expire en cas de panne de courant. Les MINUTES sont le temps dexécution restant, calculé en interne par londuleur et surveillé par apcupsd. Après avoir terminé cet événement, apcupsd lancera immédiatement un événement doshutdown .</td>
<td>wall un message</td>
</tr>
<tr>
<td>timeout</td>
<td>Cet événement est généré lorsque la valeur TIMEOUT définie dans le fichier apcupsd.conf expire en cas de panne de courant. Il indique que la durée totale dune panne de courant a été dépassée et que la machine doit être arrêtée. Après avoir terminé cet événement, apcupsd lancera immédiatement un événement doshutdown .</td>
<td>wall un message</td>
</tr>
<tr>
<td>startselftest</td>
<td>Cet événement est généré lorsque apcupsd détecte un auto-test par londuleur. Normalement, en raison du délai par défaut de 6 secondes du délai de la batterie, les événements dautotest ne sont pas détectés.</td>
<td>rien</td>
</tr>
<tr>
<td>endselftest</td>
<td>Cet événement est généré lorsque la fin dun autotest est détectée.</td>
<td>rien</td>
</tr>
<tr>
<td>battdetach</td>
<td>Cet événement est généré lorsque apcupsd détecte que la batterie de londuleur a été déconnectée.</td>
<td>rien</td>
</tr>
<tr>
<td>battattach</td>
<td>Cet événement est généré lorsque apcupsd détecte que la batterie de londuleur a été reconnectée après un événement battdetach.</td>
<td>rien</td>
</tr>
</tbody>
</table>
<h3 id="hiberner-au-lieu-de-fermer-optionnel">Hiberner au lieu de fermer (Optionnel)</h3>
<p>Vous pouvez mettre votre système en veille prolongée au lieu de larrêter. Tout dabord, assurez-vous que le système hiberne correctement. Pour configurer la mise en veille prolongée, voir Gestion de lalimentation / Suspension et mise en veille prolongée .</p>
<p><strong>Créer le script de mise en veille prolongée</strong></p>
<p>Créez ceci dans <strong>/usr/local/bin/hibernate</strong> tant que root:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>#!/bin/bash
# Hibernate the system - designed to be called via symlink from /etc/apcupsd
# directory in case of apcupsd initiating a shutdown/reboot. Can also be used
# interactively or from any script to cause a hibernate.
# Do the hibernate
/usr/bin/systemctl hibernate
# At this point system should be hibernated - when it comes back, we resume this script here
# On resume, tell controlling script (/etc/apcupsd/apccontrol) NOT to continue with default action (i.e. shutdown).
exit 99
</code></pre></div></div>
<p>Rendez-le exécutable en exécutant:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>chmod +x /usr/local/bin/hibernate
</code></pre></div></div>
<p>Créez un lien symbolique du répertoire /etc/apcupsd vers le script.<br />
Le résultat est que le script apccontrol dapcupd, dans ce répertoire, appellera le script hibernate au lieu de faire laction darrêt par défaut pour ces opérations.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>ln -s /usr/local/bin/hibernate /etc/apcupsd/doshutdown
</code></pre></div></div>
<p><strong>apcupsd en tant que client</strong><br />
Si vous exécutez apcupsd en tant que client sur une autre machine exécutant apcupsd en tant que serveur et que votre machine doit hiberner si le serveur est arrêté ou si la communication avec le serveur est perdue, vous pouvez également ajouter:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>ln -s /usr/local/bin/hibernate /etc/apcupsd/remotedown
</code></pre></div></div>
<p><strong>mettre londuleur hors tension</strong><br />
Une fois que le PC a hiberné avec succès, il est courant de mettre londuleur hors tension afin de conserver la charge de la batterie et dempêcher la décharge complète de la batterie.<br />
Ceci peut être réalisé grâce à un événement de mise hors tension dans systemd.</p>
<p>Créez <strong>/usr/lib/systemd/system-sleep/ups-kill</strong> et mettez-y le contenu suivant:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>#!/bin/bash
case $2 in
# In the event the computer is hibernating.
hibernate)
case $1 in
# Going into a hibernate state.
pre)
# See if this is a powerfail situation.
if [ -f /etc/apcupsd/powerfail ]; then
echo
echo "ACPUPSD will now power off the UPS"
echo
/etc/apcupsd/apccontrol killpower
echo
echo "Please ensure that the UPS has powered off before rebooting"
echo "Otherwise, the UPS may cut the power during the reboot!!!"
echo
fi
;;
# Coming out of a hibernate state.
post)
# If there are remnants from a powerfail situation, remove them.
if [ -f /etc/apcupsd/powerfail ]; then
rm /etc/apcupsd/powerfail
fi
# This may also exist, need to remove it.
if [ -f /etc/nologin ]; then
rm /etc/nologin
fi
# Restart the daemon; otherwise it may be unresponsive in a
# second powerfailure situation.
systemctl restart apcupsd
;;
esac
;;
esac
</code></pre></div></div>
<p>Rendez le script exécutable en faisant:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>chmod +x /usr/lib/systemd/system-sleep/ups-kill
</code></pre></div></div>
<p>Vous pouvez maintenant <a href="#tester">tester</a> votre configuration</p>
<h2 id="dépannage">Dépannage</h2>
<p>Lenvironnement de bureau détectera également londuleur sil est connecté par un câble USB</p>
<p>Par exemple, le paramètre KDE par défaut est de mettre lordinateur en veille sil a été sur batterie UPS pendant plus de 10 minutes et que la souris na pas bougé.<br />
Sur de nombreux ordinateurs, cela provoque un crash.<br />
Cela peut être modifié dans <em>Paramètres système KDE → Gestion de lalimentation → Sur batterie</em> .</p>
<p>hid-generic: file dattente de contrôle pleine (hid-generic : control queue full)</p>
<p>Si vous utilisez un initramfs basé sur systemd (<a href="https://wiki.archlinux.org/index.php/Mkinitcpio#Common_hooks">systemd-based initramfs</a>), vous pouvez rencontrer le message de journal «file dattente de contrôle pleine» qui se produit plusieurs fois par seconde. Vous voudrez ajouter <strong>hid-generic</strong> à vos modules et régénérer vos <strong>initramfs</strong>.</p>
<h2 id="voir-également">Voir également</h2>
<ul>
<li><a href="http://www.apcupsd.org/">Apcupsd</a></li>
<li><a href="https://ubuntuforums.org/showthread.php?p=4302102">Forcing hibernate</a></li>
<li><a href="http://www.apcupsd.com/manual/manual.html">apcupsd manual</a></li>
</ul>
</div>
<div class="d-print-none"><footer class="article__footer"><meta itemprop="dateModified" content="2020-03-30T00:00:00+02:00"><!-- start custom article footer snippet -->
<!-- end custom article footer snippet -->
<!--
<div align="right"><a type="application/rss+xml" href="/feed.xml" title="S'abonner"><i class="fa fa-rss fa-2x"></i></a>
&emsp;</div>
-->
</footer>
<div class="article__section-navigator clearfix"><div class="previous"><span>PRÉCÉDENT</span><a href="/2020/03/29/Utiliser-GPG-pour-chiffrer-dechiffrer-un-mot-de-passe.html">Utiliser GPG pour chiffrer-déchiffrer un mot de passe</a></div><div class="next"><span>SUIVANT</span><a href="/2020/03/31/vps789461-(wgvpn.space)-debian-buster-Icinga.html">vps789461 (wgvpn.space) debian buster - Icinga (INACTIF)</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>