fgtoul
1
Bonjour Ă tous,
avec la sortie de l’extension X-Wiegand, je vous propose un nouvel article.
Mise en œuvre du module et exemples de programmations.
X-WIEGAND et X-DISPLAY V2 : La sûreté avec IPX800 V5 — GCE Electronics
J’ai également écrit un second article permettant d’étudier l’utilisation du clavier virtuel sur X-Display V2 au travers de la mise en place d’un petit système d’alarme.
X-Display V2 : conception d’un système d’alarme simple — GCE Electronics
Bonne lecture
9 « J'aime »
Bonjour Ă tous,
Astuce 1
après la conception d’un système d’alarme sur V5, je souhaitais mettre un dashboard sur une tablette murale.
Celle-ci étant toujours connectée avec un user sans durée limitée de session, il était nécessaire de sécuriser le dashboard.
Sur IPX V5, j’ai donc créé une tempo, le dashboard sera activé pendant le décompte seulement.
Cette tempo est démarrée par la sortie d’un objet Access Control lui-même piloté via un widget clavier virtuel (voir tuto ici).
exemple avec une tempo de 3s

Tous les widgets restent pleinement fonctionnels.
Exemple avec tempo 30s

un petit widget HTML récupère l’IO output de la tempo et bascule la visibilité des widgets par leur id. (pour connaître l’id d’un widget, voir plus bas)
Exemple de code pour les widget avec id ‹ 3 › et ‹ 6 ›:
<script>
var idUnlock=66298; //id de la sortie de la tempo
var dashboardEnabled;
function g(elm){return document.getElementById(elm);}
function toggleWidgets(){ //masquage/démasquage des widget avec id=3 et 6
if (dashboardEnabled) {
g('3').style.display = "block";
g('6').style.display = "block";
} else {
g('3').style.display = "none";
g('6').style.display = "none";
}
}
window.GCE_Refresh.push(function(data) {
switch (data['_id']) {
case idUnlock: //id tempo output
dashboardEnabled=data.on;
toggleWidgets();
break;
}
});
function init() {
dashboardEnabled=false;
GCE_API.getIO(idUnlock).then((ret) => { // ask for the actual value
dashboardEnabled=ret.on;
toggleWidgets();
});
setTimeout(init,150);
</script>
Pour retrouver l’id d’un widget, faites un clic dessus avec le bouton droit de la souris puis sélectionnez l’option « inspecter ». Dans le code qui s’affiche alors, remontez progressivement en survolant le code puis sélectionnez la balise qui met en surbrillance le widget en totalité. Vous repèrerez l’élément avec la classe grid-stack-item widget. La valeur à relever est l’attribut id. (3 dans notre exemple ci-dessous)
voici la méthode en vidéo (avec le navigateur Edge):

bonne journée
3 « J'aime »
ASTUCE 2
Il est également possible de sécuriser un Liveview.
La méthode la plus simple consiste à masquer tout ou partie du Liveview par des widgets Image On/Off.
Exemple avec le Liveview du système d’alarme. Certains widgets sont masqués par une image on/off dépendant d’une temporisation activée par la saisie d’un code administrateur. Dans le cas ci-dessous c’est un objet Control d’accès dont la sortie est liée à la commande de la tempo.
Un panneau « Entrez le code administrateur » masque les informations confidentielles comme le dernier numéro de badge reçu par le contrôleur Wiegand.
1 « J'aime »
En partage, voici un nouveau widget HTML pour visualiser l’état d’une centrale d’alarme.
Sur IPX V5, un compteur prend 3 valeurs possibles :
0 : désarmée
1: armement partiel
2: armement total

Voici le code :
<script>
var valueCentrale = 0;
var positions = ["80px", "-20px", "180px"]; // Centre, Gauche, Droite
var colors = ["#1fdb49", "yellow", "red"];
function updateSlider() {
var thumb = document.getElementById("thumb");
thumb.style.left = positions[valueCentrale];
thumb.style.borderColor = colors[valueCentrale];
}
window.GCE_Refresh.push(function(data) {
switch (data['_id'])
{
case 327806:
valueCentrale=data.value;
updateSlider();
break;
}
})
function init4() {
GCE_API.get('/api/core/ana/327806').then((ret) => { // ask for the actual value
valueCentrale=ret.value;
updateSlider();
})
}
setTimeout(init4,50);
</script>
<style>
.slider-container {
width: 200px;
height: 1px;
background-color: #fff;
position: relative;
margin: 40px auto 0;
}
.slider-thumb {
width: 40px;
height: 20px;
position: absolute;
top: -13px;
left: 80px;
background-color: #ccc;
border-radius: 10px;
border: 3px solid #1fdb49;
transition: all 0.3s ease-in-out;
display: flex;
justify-content: center;
align-items: center;
}
.slider-thumb::before {
content: "|";
color: #fff;
font-size: 14px;
}
.marker {
width: 4px;
height: 10px;
background-color: #fff;
position: absolute;
top: -5px;
}
.slider-icon {
position: absolute;
top: -70px;
font-size: 2em;
}
.slider-label {
position: absolute;
top: -40px;
font-size: 0.8em;
}
</style>
<div class="slider-container">
<!-- IcĂ´nes -->
<i class="gce-glyph icon-home_room slider-icon" style="left: -10px; color: yellow;"></i>
<i class="gce-glyph icon-home_room slider-icon" style="left: 90px; color: #1fdb49;"></i>
<i class="gce-glyph icon-home_room slider-icon" style="left: 190px; color: #f00;"></i>
<!-- Labels -->
<span class="slider-label" style="left: -15px; color: yellow;">PARTIEL</span>
<span class="slider-label" style="left: 85px; color: #1fdb49;">DESARME</span>
<span class="slider-label" style="left: 185px; color: #f00;">ARME</span>
<!-- Marqueurs -->
<div class="marker" style="left: 0;"></div>
<div class="marker" style="left: 100px;"></div>
<div class="marker" style="left: 200px;"></div>
<!-- Curseur -->
<div id="thumb" class="slider-thumb"></div>
</div>
vous devez renseigner l’ID de la sortie Valeur du compteur
voici un exemple d’utilisation :

Le même widget pourrait superviser l’état d’une partition. En cas d’inhibition de capteurs, la partition serait armée partiellement, en cas de non inhibition, l’armement serait total.
bonne journée
1 « J'aime »
le même Widget avec possibilité de contrôle par déplacement du curseur, à la souris (mousemove) ou sur écran tactile (touchmove)
Le compteur est mis à jour à chaque déplacement, il suffit de scénariser l’armement et désarmement en fonction de sa valeur.
Lors d’un clic sur la ligne du slider, le script évalue la position la plus proche pour y déplacer le curseur. Si vous cliquez pile au milieu, le curseur n’est pas déplacé.
Pour éviter cela, les icônes labels et repères sont également cliquables, ce qui garantit une utilisation plus fluide.

Voici le code :
<style>
.slider-container {
width: 200px;
height: 1px;
background-color: #fff;
position: relative;
margin: 40px auto 0;
cursor:pointer;
}
.slider-thumb {
width: 40px;
height: 20px;
position: absolute;
top: -13px;
left: 80px;
background-color: #ccc;
border-radius: 10px;
border: 3px solid #1fdb49;
transition: all 0.3s ease-in-out;
display: flex;
justify-content: center;
align-items: center;
cursor:grab;
}
.slider-thumb::before {
content: "|";
color: #fff;
font-size: 14px;
}
.marker {
width: 4px;
height: 10px;
background-color: #fff;
position: absolute;
top: -5px;
cursor:pointer;
}
.slider-icon {
position: absolute;
top: -70px;
font-size: 2em;
}
.slider-label {
position: absolute;
top: -40px;
font-size: 0.8em;
}
</style>
<script>
var valueCentrale = 0;
var positions = [80, -20, 180]; // Centre, Gauche, Droite
var colors = ["#1fdb49", "yellow", "red"];
function updateSlider() {
var thumb = document.getElementById("thumb");
thumb.style.left = positions[valueCentrale] + "px";
thumb.style.borderColor = colors[valueCentrale];
GCE_API.put('/api/core/ana/327806',{value : valueCentrale}).then((ret) => {
});
}
window.GCE_Refresh.push(function(data) {
if (data['_id'] === 327806) {
valueCentrale = data.value;
updateSlider();
}
});
function moveThumb(event) {
let xPos = event.clientX || event.touches[0].clientX;
let sliderRect = document.querySelector(".slider-container").getBoundingClientRect();
let relativeX = xPos - sliderRect.left;
let closestIndex = positions.reduce((prev, curr, index) =>
Math.abs(curr - relativeX) < Math.abs(positions[prev] - relativeX) ? index : prev, 0);
valueCentrale = closestIndex;
updateSlider();
}
function init4() {
GCE_API.get('/api/core/ana/327806').then((ret) => {
valueCentrale = ret.value;
updateSlider();
});
document.querySelector(".slider-container").addEventListener("mousedown", (event) => moveThumb(event));
document.querySelector(".slider-container").addEventListener("touchmove", (event) => {
event.preventDefault();
moveThumb(event);
});
}
setTimeout(init4, 50);
</script>
<div class="slider-container">
<!-- IcĂ´nes -->
<i class="gce-glyph icon-home_room slider-icon" style="left: -10px; color: yellow;"></i>
<i class="gce-glyph icon-home_room slider-icon" style="left: 90px; color: #1fdb49;"></i>
<i class="gce-glyph icon-home_room slider-icon" style="left: 190px; color: #f00;"></i>
<!-- Labels -->
<span class="slider-label" style="left: -15px; color: yellow;">PARTIEL</span>
<span class="slider-label" style="left: 85px; color: #1fdb49;">DESARME</span>
<span class="slider-label" style="left: 185px; color: #f00;">ARME</span>
<!-- Marqueurs -->
<div class="marker" style="left: 0;"></div>
<div class="marker" style="left: 100px;"></div>
<div class="marker" style="left: 200px;"></div>
<!-- Curseur -->
<div id="thumb" class="slider-thumb"></div>
</div>
```
1 « J'aime »
Merci @fgtoul pour le partage
En prenant l’exemple des casiers dans le WIKI on peut gérer un code sous contrainte ?
Code qui désarme mais fait autre chose aussi alarme silencieuse ou autre
Bonne journée
oui, il faut créer un objet Control Access dédié
Super merci (le reste c’est pour les 20 caractères :-))
Voici une autre manière de protéger un affichage sur un liveview avec un champ de saisie :

Le champ de saisie est dans un widget HTML qui vérifie à intervalle régulier la sortie d’une temporisation. Cette temporisation est démarrée par un objet Access Control qui permet la gestion d’un code administrateur. Si le code saisi est correct, la sortie de la tempo (id 65602) s’active pour le temps déterminé (9s dans l’exemple), ce qui autorise l’affichage des informations confidentielles.
Dans mon exemple, c’est un autre widget HTML qui affiche le numéro du dernier badge lu.
Dans mon exemple, le widget HTML récupère le numéro du dernier badge lu. Cette information est contenue dans le paramètre StrCurrentCode d’un autre objet Access Control.,
Voici le code:
<style>
#admInput {
font-size: 1.2em;
padding: 10px;
border: 2px solid #333;
border-radius: 5px;
width: 250px;
color:white;
background-color:#333;
}
#admButton {
font-size: 1.2em;
padding: 10px 20px;
background-color: #007BFF;
color: white;
border: none;
border-radius: 25px;
cursor: pointer;
margin-top: 10px;
}
#admButton:hover {
background-color: #0056b3;
}
</style>
<script type="text/javascript">
var server="",//vide pour local, sinon format http://ip
api="wlAbCG6FZm2UH5w", //renseigner clé API
uriStr="/api/core/str/",
uriIO="/api/core/io/",
idA="524310", // Administrator code
idT="65602"; //Tempo Admin output
idW="524289";//dernier code reçu
var IOadmin;
IOadmin=false;
var mStr="";
function validateCode() {
var inputValue = document.getElementById("admInput").value;
document.getElementById("admInput").value="";
fetch(uriStr + idA + '?ApiKey=' + api, {
method: "PUT", //envoie valeur saisie au Access Control
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify({ "value": inputValue.toString() })
})
.then(response => response.json())
//document.getElementById("admInput").value="";
}
/* Get data from API */
function getIPX1(cb) {// get sortie tempo ADM
fetch(uriIO+idT+"?ApiKey="+api, {method: "GET"}).then((ret) => { // Get IPX object
ret.json().then((ipx) => {
cb(ipx); // Return IPX state from API
});
});
}
function getIPX2(cb) {// get dernier code reçu
fetch(uriStr+idW+"?ApiKey="+api, {method: "GET"}).then((ret) => { // Get IPX object
ret.json().then((ipx) => {
cb(ipx); // Return IPX state from API
});
});
}
function init2(){
/* recup tempo administrateur */
getIPX1((ipx) => {IOadmin = ipx.on;});
/* recup string */
getIPX2((ipx) => {mStr = ipx.value;});
cADM=document.getElementById("cADM");
if (IOadmin){
cADM.innerHTML=mStr;
}else{
cADM.innerHTML="Affichage verrouillé!";
}
}
function autoRefresh() {
setInterval(() => {
init2();
}, 1000); // 1 sec
}
setTimeout(init2, 500);
autoRefresh();
</script>
<input width=100 type="text" id="admInput" placeholder="Entrez votre code Admin" autocomplete="off">
<button id="admButton" onclick="validateCode()">OK</button>
Voici le code du widget qui se charge d’afficher l’info
<div id="cADM" style="background-color:#222;font-size:1.5em">...</div>
1 « J'aime »
Voici comme discuté plus haut le widget pour le statut de 2 partitions.
Les compteurs 327806 et 327808 devront être gérés par ailleurs.

<style>
.slider-container {
width: 200px;
height: 1px;
background-color: #fff;
position: relative;
margin: 40px auto 0;
}
.slider-thumb {
width: 40px;
height: 20px;
position: absolute;
top: -13px;
left: 80px;
background-color: #ccc;
border-radius: 10px;
border: 3px solid #1fdb49;
transition: all 0.3s ease-in-out;
display: flex;
justify-content: center;
align-items: center;
}
.slider-thumb::before {
content: "|||";
color: #fff;
font-size: 14px;
}
.marker {
width: 4px;
height: 10px;
background-color: #fff;
position: absolute;
top: -5px;
}
.slider-icon {
position: absolute;
top: -60px;
font-size: 2em;
}
.slider-label {
position: absolute;
top: -30px;
font-size: 0.8em;
}
</style>
<script>
var valueP1 = 0;var valueP2 = 0;
var positions = ["80px", "-20px", "180px"]; // Centre, Gauche, Droite
var colors = ["#1fdb49", "yellow", "red"];
function updateSlider1() {
var thumb = document.getElementById("thumb1");
thumb.style.left = positions[valueP1];
thumb.style.borderColor = colors[valueP1];
}
function updateSlider2() {
var thumb = document.getElementById("thumb2");
thumb.style.left = positions[valueP2];
thumb.style.borderColor = colors[valueP2];
}
window.GCE_Refresh.push(function(data) {
switch (data['_id'])
{
case 327806:
valueP1=data.value;
updateSlider1();
break;
case 327808:
valueP2=data.value;
updateSlider2();
break;
}
})
function init4() {
GCE_API.get('/api/core/ana/327806').then((ret) => { // ask for the actual value
valueP1=ret.value;
updateSlider1();
})
GCE_API.get('/api/core/ana/327808').then((ret) => { // ask for the actual value
valueP2=ret.value;
updateSlider2();
})
}
setTimeout(init4,50);
</script>
<div class="slider-container">
<!-- IcĂ´nes -->
<i class="gce-glyph icon-home_room slider-icon" style="left: -10px; color: yellow;"></i>
<i class="gce-glyph icon-home_room slider-icon" style="left: 90px; color: #1fdb49;"></i>
<i class="gce-glyph icon-home_room slider-icon" style="left: 190px; color: #ff0013;"></i>
<!-- Labels -->
<span class="slider-label" style="left: -15px; color: yellow;">PARTIEL</span>
<span class="slider-label" style="left: 85px; color: #1fdb49;">DESARME</span>
<span class="slider-label" style="left: 185px; color: #ff0013;">ARME</span>
<!-- Marqueurs -->
<div class="marker" style="left: 0;"></div>
<div class="marker" style="left: 100px;"></div>
<div class="marker" style="left: 200px;"></div>
<!-- Curseur -->
<div id="thumb1" class="slider-thumb"></div>
</div>
<div class="slider-container">
<!-- Marqueurs -->
<div class="marker" style="left: 0;"></div>
<div class="marker" style="left: 100px;"></div>
<div class="marker" style="left: 200px;"></div>
<!-- Curseur -->
<div id="thumb2" class="slider-thumb"></div>
</div>
1 « J'aime »