premier commit

This commit is contained in:
icon 2022-08-30 06:34:34 +04:00
commit 5b620e279f
16 changed files with 9364 additions and 0 deletions

22
autostart Executable file
View File

@ -0,0 +1,22 @@
#/etc/xdg/openbox/
DISPLAY=:0 xdotool getactivewindow key F5
# stop veille/économie dénergie
xset dpms 0 0 0 && xset s noblank && xset s off
#Touches pour sortir du serveur X => CTRL-ATL-Backspace
setxkbmap -option terminate:ctrl_alt_bksp
sed -i 's/"exited_cleanly":false/"exited_cleanly":true/' ~/.config/chromium/Default/Preferences
sed -i 's/"exit_type":"Crashed"/"exit_type":"Normal"/' ~/.config/chromium/Default/Preferences
# vidage du cache chromium
rm -fr /home/sysop/.cache/chromium
rm -fr /home/sysop/.config/chromium/Default/
# orientation de l'écran
xrandr --output DSI-1 --rotate right
# lance chromium avec un user agent spécifique hostname,password,periph,ip (provenant en partie de .chromium_env)
cd /home/sysop/serveurNfcNodeJs/
node serveur_nfc.js

47
node.yml Executable file
View File

@ -0,0 +1,47 @@
---
- hosts: testDsiPi
remote_user: sysop
become: yes
tasks:
- name: install "splash screen"
apt:
name: rpd-plym-splash
state: present
- name: Active SPI
shell:
cmd: echo "dtparam=spi=on" >> /boot/config.txt
- name: Ajout du dépot nodes js
shell: curl -sL https://deb.nodesource.com/setup_16.x | sudo -E bash -
- name: install "nodejs"
apt:
name: nodejs
state: present
- name: Pour nodejs, installation de "gcc" pour la compilation
apt:
name: gcc
state: present
- name: Pour nodejs, installation de "g++" pour la compilation
apt:
name: g++
state: present
- name: Pour nodejs, installation de "make" pour la compilation
apt:
name: make
state: present
- name: Pour nodejs, installation de "apt-transport-https" pour la compilation
apt:
name: apt-transport-https
state: present
- name: Installation des modules node js
shell:
cmd: npm i
chdir: /home/sysop/nodeJsVma405/

80
readme.md Executable file
View File

@ -0,0 +1,80 @@
# VMA 405
côté usb, | 39 | 37 | 35 | 33 | 31 | 29 | 27 | 25 | 23 | 21 | 19 | 17 | 15 | 13 | 11 | 9 | 7 | 5 | 3 | 1 | côté sdcar
reseau | 40 | 38 | 36 | 34 | 32 | 30 | 28 | 26 | 24 | 22 | 20 | 18 | 16 | 14 | 12 | 10 | 8 | 6 | 4 | 2 |
| 39 | 37 | 35 | 33 | 31 | 29 | 27 | 25 | SCK|MISO|MOSI| 17 | 15 | 13 | 11 | GND| 7 | 5 | 3 | vcc|
| 40 | 38 | 36 | 34 | 32 | 30 | 28 | 26 | NSS| RST| 20 | 18 | 16 | 14 | 12 | 10 | 8 | 6 | 4 | 2 |
|VMA405 |PI 3 B+ | |
|VCC | 1 | marron |
|RST 22 rouge
GND 9 orange
MISO 21 jaune
MOSI 19 vert
SCK 23 bleu
NSS 24 violet
IRQ pas utilisé
# splash screen
```
sudo cp splash.png /usr/share/plymouth/themes/pix/splash.png
sudo cp splash.png /usr/share/plymouth/themes/pix/splash.png
```
- sudo nano /boot/config.txt
disable splash=1
- sudo nano /boot/cmdline.txt
consoleblank=0 loglevel=1 quiet logo.nologo
-Pour afficher l'image
sudo apt install fbi
- Créer un service
sudo nano /etc/systemd/system/splashscreen.service
```
[Unit]
Description=Splash screen
DefaultDependencies=no
After=local-fs.target
[Service]
ExecStart=/usr/bin/fbi -d /dev/fb0 --noverbose -a /home/sysop/splash.png
StandardInput=tty
StandardOutput=tty
[Install]
WantedBy=sysinit.target
```
- active le service
sudo systemctl enable splashscreen.service
sudo systemctl start splashscreen.service
# /ext/xdg/openbox/autostart
```
#/etc/xdg/openbox/
DISPLAY=:0 xdotool getactivewindow key F5
# stop veille/économie dénergie
xset dpms 0 0 0 && xset s noblank && xset s off
#Touches pour sortir du serveur X => CTRL-ATL-Backspace
setxkbmap -option terminate:ctrl_alt_bksp
sed -i 's/"exited_cleanly":false/"exited_cleanly":true/' ~/.config/chromium/Default/Preferences
sed -i 's/"exit_type":"Crashed"/"exit_type":"Normal"/' ~/.config/chromium/Default/Preferences
# vidage du cache chromium
rm -fr /home/sysop/.cache/chromium
rm -fr /home/sysop/.config/chromium/Default/
# orientation de l'écran
xrandr --output DSI-1 --rotate right
# lance chromium avec un user agent spécifique hostname,password,periph,ip (provenant en partie de .chromium_env)
cd /home/sysop/serveurNfcNodeJs/
node serveur_nfc.js
```

View File

@ -0,0 +1,16 @@
#cp chromium_env.exemple .chromium_env
#utilisateur
hostname = testDsiPi
#front
front_type = FPI
#url du serveur
url = https://django-local.org:8501/wv/login_hardware
#mode_nfc = NFCMO
mode_nfc = NFCLO
password = xxxxxxxxxxxxxxxxxxxxx
token = xxxxxxxxxxxxxxxxxx

View File

@ -0,0 +1,18 @@
{
"name": "nfc",
"version": "1.5.0",
"description": "",
"main": "serveur_nfc.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "filaos974",
"license": "ISC",
"dependencies": {
"ip": "^1.1.5",
"socket.io": "^3.0.4",
"mfrc522-rpi": "^2.1.3",
"rpi-softspi": "^1.0.5",
"rpio": "^2.4.2"
}
}

View File

@ -0,0 +1,659 @@
// pour "configurer" le lecteur nfc
// ouvrir le fichier: sudo nano /usr/lib/pcsc/drivers/ifd-ccid.bundle/Contents/Info.plist (pour pi)
// localiser la ligne <key>ifdDriverOptions</key>,
// la ligne suivante vaux <string>0x0000</string>,
// modifier la <string>0x0001</string>,
// sauvegarder le fichier et redémarer pcscd(sudo service pcscd restart)
// même action pour le fichier sudo nano /usr/lib/pcsc/drivers/ifd-acsccid.bundle/Contents/Info.plist (pour desktop)
let script, ip, memSudoMdp = '', etatUrl = 0
let TAB = ['A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z','a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '!', '#', '$', '%', '&', '?','0','1','2','3','4','5','6','7','8','9'];
let max_TAB = TAB.length - 1
let donneesFichierConfiguration = {}
// type de lecteur nfc
const typeLecteurNfc = 'vma405'
// dev = 1 = mode développement
let dev = 1
// nfc
const vma405Emitter = require('./vma405.js')
const os = require('os')
const hostname= os.hostname()
const { spawn, exec } = require('child_process')
const IP = require('ip')
const path = require('path')
const fs = require('fs')
// serveur http
const http = require('http')
// const ADR = '192.168.1.32'
const ADR = '127.0.0.1'
const PORT = 3000
const TOKEN = '$a;b2yuM5454@4!cd'
// retour = null = aucune demande de lecture de carte nfc
let retour = null
let client_globale = null
let fichier = '', contentType = ''
/**
* retourne l'ip
* @param {string|'public'|'private'} typeReseau
* @param {String|'ipv4'|'ipv6'} famille
* @returns {string}
*/
function obtenirIp(typeReseau, famille){
ip = IP.address(typeReseau, famille)
let retour = "erreur"
if (ip !== "127.0.0.1" && ip !== "0.0.0.0") {
retour = ip
}
return retour
}
// --- nfc ---
vma405Emitter.on('tagId', (tagId) => {
if (retour !== null){
retour['tagId'] = tagId.toUpperCase()
client_globale.emit('envoieTagId',retour)
console.log('--> demande carte, envoi tag id = ' + tagId.toUpperCase())
retour = null
} else {
// console.log('-> Aucune demande, carte :' + card.uid.toString().toUpperCase())
console.log('-> Aucune demande, carte :' + tagId.toUpperCase())
if (client_globale !== null) {
client_globale.emit('infosTagId', tagId.toUpperCase())
}
}
})
vma405Emitter.on('msgVma405', (msg) => {
console.log('msgVma405 =', msg)
})
// --- commandes système ---
/** @function
* Obtenir ip extérieur (wan/box)
*/
function obtenirIpWan() {
const prog = spawn('curl', ['ifconfig.me'])
prog.stdout.on('data', (data) => {
prog.resultatRequete = data.toString()
})
prog.on('close', (code) => {
if (code === 0 ){
// ok: ip = prog.resultatRequete
} else {
// erreur
}
})
}
/**
* Obtenir des données de configuration d'un fichier (.chromium_env)
* @param {Array} rechercher - liste des varaibles à rechercher ddans le fichier
* @param {String} fichier - nom du fichier à lire
* @returns {{msg, erreur: number}|{valeurs: {}, erreur: number}}
*/
function obtenirConfigurationDunFichier(rechercher,fichier) {
try {
const fic = fs.readFileSync(fichier, {encoding:'utf8', flag:'r'}).split('\n')
let obj = {}
for (let index = 0; index < fic.length; index++) {
let ligne = fic[index].toString()
if (ligne.length > 0 && ligne[0] !== '#' && ligne.indexOf('=') !== -1) {
let tab = ligne.split('=')
for ( let im in rechercher) {
mot = rechercher[im]
if (mot === (tab[0].trim())) {
obj[tab[0].trim()] = tab[1].trim()
}
}
}
}
return {erreur: 0, valeurs: obj}
} catch (error) {
return {erreur:1 , msg: error}
}
}
function afficherInfoServeur(donnees){
// console.log('-> fonction afficherInfoServeur !')
// console.log('donnees = ', donnees)
if (donnees.erreur === 0) {
let bruteUrl = donnees.valeurs.url
let posDeuxSlashs = bruteUrl.indexOf('//') + 2
let posFinDomaine = bruteUrl.indexOf('/wv/login_hardware')
let domaine = bruteUrl.substring(posDeuxSlashs,posFinDomaine)
let onclique = ''
if (donnees.valeurs.front_type === "FPI") {
onclique = `onclick="clavierVirtuel.obtPosition('serveur');clavierVirtuel.afficher('serveur', 'alpahMin')"`
}
let fronts = ['FPI', 'FOR']
let options = ''
for (let i = 0; i < fronts.length; i++) {
let sel = ''
console.log(`${ i} -> ${ fronts[i] } -- ${ donnees.valeurs.front_type }`)
if (fronts[i] === donnees.valeurs.front_type) {
sel = 'selected'
}
options += `<option value="${ fronts[i]}" ${ sel }>${ fronts[i]}</option>`
}
return `
<div id="info-serveur" class="BF-ligne-deb l100p item-info" data-url-serveur="${ bruteUrl }" data-serveur="${ domaine }">Serveur: ${ domaine }</div>
<div class="BF-ligne-deb l100p">
<div id="bt-tester-serveur" class="bt bt-250px fond-ok curseur-action">
<div class="md4px">Tester Serveur</div>
</div>
</div>
<div class="BF-ligne-deb item-info l100p">
<div id="bt-modifier-serveur" class="bt bt-250px fond-alerte curseur-action">
<div class="md4px">Modifier Serveur</div>
<div id="etat-modifier-serveur" class="mod-serveur-ok"></div>
</div>
</div>
<div id="modifier-serveur" class="contenu-form eff p4px fond-header l100p">
<div class="BF-ligne-deb mb8px">
<label for="serveur" class="serveur-label">Serveur</label>
<input type="text" id="serveur" class="input-pour-pi" name="serveur" value="${ domaine }" ${ onclique } required>
</div>
<div class="BF-ligne-deb mb8px">
<label for="nom-appareil" class="mod-wifi-label">APPAREIL</label>
<input type="text" id="nom-appareil" class="input-pour-pi" name="nom-appareil" value="${ os.hostname() }" disabled>
</div>
<div class="BF-ligne-deb mb8px">
<label for="passe" class="mod-wifi-label">GENERER MOT DE PASSE</label>
<input type="checkbox" id="passe" name="passe" >
</div>
<div class="BF-ligne-deb mb8px">
<label for="type-front" class="mod-wifi-label">FRONT</label>
<select id="type-front" class="input-pour-pi">${ options }</select>
</div>
<div class="BF-ligne">
<div id="bt-valider-modifier-serveur" class="bt bt-valider fond-ok coulBlanc curseur-action">Valider</div>
</div>
</div>
`
} else {
return `
<div class="BF-ligne-deb item-info l100p">Erreur</div>
<div class="item-info">donnees.msg</div>
`
}
}
/** @function
* Teste l'url avec curl
* @param {Sring} url - url à tester
* @param {Number} nbMaxStderr - nombre maxi d'évènement Stderr avant de sortir de la fonction
*/
function testUrl(url, nbMaxStderr) {
console.log(`-> fonction testUrl, url = ->${ url }<-`)
const prog = spawn('curl', ['-I', url])
prog.nbMaxStderr = nbMaxStderr
prog.nbStderr = 0
prog.resultatRequete = "404"
etatUrl = 0
prog.stdout.on('data', (data) => {
let premiereLigne = data.toString().split('\n')[0]
prog.resultatRequete = premiereLigne.split(' ')[1]
})
prog.stderr.on('data', (data) => {
prog.nbStderr ++
if(prog.nbStderr === prog.nbMaxStderr) {
prog.kill()
}
})
prog.on('close', (code) => {
// header 307 = redirection temporaire
// header 308 = redirection permanente
console.log('réponse test serveur = ', prog.resultatRequete)
if(prog.resultatRequete === '200' || prog.resultatRequete === '307' || prog.resultatRequete === '308') {
etatUrl = 1
}
client_globale.emit('etatUrlServeur', prog.resultatRequete)
})
}
function modifierConfigurationWifi(data) {
console.log('-> fonction modifierConfigurationWifi !')
console.log('data = ', data)
let template = `country=FR
ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
update_config=1
network={
ssid="${ data.essid }"
psk="${ data.passePhrase }"
scan_ssid=1
}
`
try {
fs.writeFileSync("/etc/wpa_supplicant/wpa_supplicant.conf", template, {flag: "w"})
client_globale.emit('modificationWifi', {
erreur: 0,
msg: `
<div class="l100p h100p BF-col">
<h1>Modification wifi effectuée,</h1>
<h1>réseau = ${ data.essid }</h1>
<h1>Redémmarer l'appareil ! </h1>
</div>
`
})
} catch (erreur) {
client_globale.emit('modificationWifi', {
erreur: 1,
msg: `
<h1>Erreur configuration wifi</h1>
<h2>${ erreur }</h2>
`
})
}
}
function afficherInfosWifi() {
// console.log('-> fonction afficherInfosWifi !')
const prog = spawn('iwconfig', [])
prog.stdout.on('data', (data) => {
let lignes = data.toString().split('\n')
for (let i = 0; i < lignes.length; i++) {
let ligne = lignes[i]
if (ligne.indexOf('ESSID') !== -1) {
let tmpData = ligne.split(':')
let etatWifi = 'on'
let essid = ''
if (tmpData[1].includes('off')){
etatWifi = 'off'
} else {
essid = tmpData[1].trim().replace(/"/g, '')
}
let tmpData2 = ligne.split(' ')
prog.resultat = {interface: tmpData2[0], etat: etatWifi, essid: essid}
break
}
}
})
prog.on('close', (code) => {
if (code === 0) {
// wifi actif
// if (prog.resultat.etat === 'on' && donneesFichierConfiguration.erreur === 0) {
// uniquement sur pi
if (donneesFichierConfiguration.valeurs.front_type === "FPI") {
let onclique = ''
// if (donneesFichierConfiguration.valeurs.front_type === "FPI") {
oncliqueEssid = `onclick="clavierVirtuel.obtPosition('essid');clavierVirtuel.afficher('essid', 'alpahMin')"`
oncliquePasse = `onclick="clavierVirtuel.obtPosition('pp');clavierVirtuel.afficher('pp', 'alpahMin')"`
// }
let fragHtml = `
<div id="info-essid" class="BF-ligne-deb item-info l100p">Ssid: ${ prog.resultat.essid }</div>
<div class="BF-ligne-deb item-info l100p">
<div id="bt-modifier-wifi" class="bt bt-250px fond-alerte curseur-action">
<div class="md4px">Modifier Wifi</div>
<div id="etat-modifier-wifi" class="mod-wifi-ok"></div>
</div>
</div>
<div id="modifier-wifi" class="contenu-form eff p4px fond-header l100p">
<div class="BF-ligne-deb mb8px">
<label for="essid" class="mod-wifi-label">RESEAU:</label>
<input type="text" id="essid" class="input-pour-pi" name="essid" ${ oncliqueEssid } required>
</div>
<div class="BF-ligne-deb mb8px">
<label for="pp" class="mod-wifi-label">MOT DE PASSE:</label>
<input type="password" id="pp" class="input-pour-pi" name="pp" ${ oncliquePasse } required>
</div>
<div class="BF-ligne">
<div id="bt-valider-modifier-wifi" class="bt bt-valider fond-ok coulBlanc curseur-action">Valider</div>
</div>
</div>
`
client_globale.emit('retourInfosWifi', fragHtml)
}
// }
}
})
}
/**
* Lancer chromium
* @param {Number|1|2} - etape
*/
function lancerChromium(etape, dataFichier) {
console.log('-> fonction lancerChromium !')
let optionsChromium = [], msgErreur = ''
console.log('dataFichier = ', dataFichier)
if (dataFichier.erreur === 0) {
data = dataFichier.valeurs
} else {
msgErreur = dataFichier.msg
}
if (msgErreur === '') {
if (etape === 1) {
// dev
if (dev === 1) {
optionsChromium = ['--disable-features=Translate', '--disable-pinch', '--remote-debugging-port=9222', '--noerrdialogs', '--disable-infobars', '--check-for-update-interval=31536000', 'http://127.0.0.1:3000']
} else {
// prod
optionsChromium = ['--disable-features=Translate', '--disable-pinch', '--noerrdialogs', '--disable-infobars', '--check-for-update-interval=31536000', 'http://127.0.0.1:3000']
}
} else {
// dev
console.log('-> etape 2, url = ', data.url)
if (dev === 1) {
optionsChromium = ['--disable-features=Translate', '--disable-pinch', '--remote-debugging-port=9222', '--noerrdialogs', '--disable-infobars', '--check-for-update-interval=31536000', data.url]
} else {
// prod
optionsChromium = ['--disable-features=Translate', '--disable-pinch', '--noerrdialogs', '--disable-infobars', '--check-for-update-interval=31536000', data.url]
}
}
// mode kiosk uniquement pi
if (data.front_type === "FPI") {
optionsChromium.push('--kiosk')
}
if (msgErreur === '') {
const userAgent = `{"hostname":"${data.hostname}", "token": "${data.token}", "password":"${data.password}","modeNfc":"${data.mode_nfc}","front":"${data.front_type}","ip":"${obtenirIp('public', 'ipv4')}"}`
console.log('userAgent = ', userAgent)
optionsChromium.push(`--user-agent=${userAgent}`)
console.log('optionsChromium = ', optionsChromium)
// Lance chromium
const demChromium = spawn('chromium-browser', optionsChromium)
demChromium.stdout.on('data', (data) => {
console.log(`demChromium - stdout: ${data}`)
});
demChromium.stderr.on('data', (data) => {
console.error(`demChromium - stderr: ${data}`)
})
demChromium.on('close', (code) => {
console.log(`demChromium - child process exited with code ${code}`)
if (code === 0) {
console.log('--> Chromium démarrer !')
}
})
}
} else {
console.log('Erreur: ', msgErreur)
}
}
function lancerApplication(){
console.log('-> fonction lancerApplication !')
const dataConf = obtenirConfigurationDunFichier(['hostname', 'token', 'password', 'front_type', 'url', 'mode_nfc'], './.chromium_env')
if (dataConf.erreur === 0) {
let prog
if (dataConf.valeurs.front_type === "FPI") {
prog = spawn('pkill', ['chromium'])
} else {
prog = spawn('pkill', ['chrome'])
}
prog.stdout.on('data', (data) => {
console.log('stdout: ', data.toString())
})
prog.stderr.on('data', (data) => {
console.log('stderr: ', data.toString())
})
prog.on('close', (code) => {
if (code === 0) {
console.log('--> Chromium arrêter !')
const dataFichier = obtenirConfigurationDunFichier(['hostname', 'token', 'password', 'front_type', 'url', 'mode_nfc'], './.chromium_env')
lancerChromium(2, dataFichier)
}
})
} else {
console.log('Erreur: ', dataConf.msg)
}
}
function afficherFrontType() {
console.log('-> fonction afficherFrontType !')
console.log('donneesFichierConfiguration = ', donneesFichierConfiguration)
if (donneesFichierConfiguration.erreur === 0) {
return donneesFichierConfiguration.valeurs.front_type
} else {
return 'inconnu'
}
}
function rnd(min, max) {
return Math.round(Math.random() * ((max+1) - min) + min,0);
}
function generer_mot_de_passe(longueur) {
let mot = '';
let lettre = TAB[rnd(0,max_TAB)];
for(let i=0;i<(longueur);i++){
while (mot.indexOf(lettre)!=-1) {
lettre = TAB[rnd(0,59)];
}
mot += lettre;
}
return mot
}
function modifierConfigurationServeur(data) {
// console.log('-> fonction modifierConfigurationServeur !')
let proto = 'https'
// Développement serveur = "#serveur.com#", donne un protocol http et serveur = "serveur.com"
let serveur = data.serveurDomaine.toString()
// console.log('0 = ',serveur[0], ' -- dernier = ',serveur[(serveur.length-1)])
if (serveur[0] === '#' && serveur[(serveur.length-1)] === '#') {
proto = 'http'
serveur = data.serveurDomaine.toString().substring(1,(serveur.length-1))
}
donnees = obtenirConfigurationDunFichier(['hostname', 'token', 'password', 'front_type', 'url', 'mode_nfc'], './.chromium_env')
if (donnees.erreur === 0) {
let motDePasse = generer_mot_de_passe(16)
if (data.genererMotDePasse === false) {
motDePasse = donnees.valeurs.password
}
let template = `#utilisateur
hostname = ${data.user}
#front
front_type = ${data.typeFront}
#url du serveur
#url = http://django-local.org:8001/wv/login_hardware
url = ${proto}://${serveur}/wv/login_hardware
#mode_nfc = NFCMO
mode_nfc = ${ donnees.valeurs.mode_nfc }
password = ${ motDePasse }
token = ${ donnees.valeurs.token }
`
try {
fs.writeFileSync(".chromium_env", template)
client_globale.emit('modificationServeur', {erreur: 0, serveurDomaine: serveur})
testUrl(serveur, 14)
redemarrerChromium()
} catch (error) {
client_globale.emit('modificationServeur', {erreur: 1})
}
} else {
client_globale.emit('modificationServeur', {erreur: 1})
}
}
// --- serveur http ---
let typeMime = {
"aac":"audio/aac","abw":"application/x-abiword","arc":"application/octet-stream","avi":"video/x-msvideo","azw":"application/vnd.amazon.ebook",
"bin":"application/octet-stream","bz":"application/x-bzip","bz2":"application/x-bzip2","csh":"application/x-csh","css":"text/css","csv":"text/csv",
"doc":"application/msword","docx":"application/vnd.openxmlformats-officedocument.wordprocessingml.document","eot":"application/vnd.ms-fontobject",
"epub":"application/epub+zip","gif":"image/gif","htm":"text/html","html":"text/html","ico":"image/x-icon","ics":"text/calendar","jar":"application/java-archive",
"jpeg":"image/jpeg","jpeg":"image/jpeg","js":"application/javascript","json":"application/json","mid":"audio/midi","midi":"audio/midi","mpeg":"video/mpeg",
"mpkg":"application/vnd.apple.installer+xml","odp":"application/vnd.oasis.opendocument.presentation","ods":"application/vnd.oasis.opendocument.spreadsheet",
"odt":"application/vnd.oasis.opendocument.text","oga":"audio/ogg","ogv":"video/ogg","ogx":"application/ogg","otf":"font/otf","png":"image/png","pdf":"application/pdf",
"ppt":"application/vnd.ms-powerpoint","pptx":"application/vnd.openxmlformats-officedocument.presentationml.presentation","rar":"application/x-rar-compressed",
"rtf":"application/rtf","sh":"application/x-sh","svg":"image/svg+xml","swf":"application/x-shockwave-flash","tar":"application/x-tar","tif":"image/tiff",
"tiff":"image/tiff","ts":"application/typescript","ttf":"font/ttf","vsd":"application/vnd.visio","wav":"audio/x-wav","weba":"audio/webm","webm":"video/webm",
"webp":"image/webp","woff":"font/woff","woff2":"font/woff2","xhtml":"application/xhtml+xml","xls":"application/vnd.ms-excel",
"xlsx":"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet","xml":"application/xml","xul":"application/vnd.mozilla.xul+xml","zip":"application/zip",
"3gp":"video/3gpp audio/3gpp","3g2":"video/3gpp2 audio/3gpp2",
"7z":"application/x-7z-compressed"
}
let www = process.cwd() + '/www/'
console.log('www = ', www)
function retour404(res){
res.writeHead(404, {'Content-Type': 'text/html'});
res.write('Page inconnue !');
res.end();
}
function renderHtml(contenu, ctx) {
// let contenuTp1, contenuTp2, contenuTp3, contenuTp4
contenu = contenu.toString()
let rendu = contenu.toString().replace(/{{\s*[\w\.]+\s*}}/g, function(match, token) {
let clef = match.replace(/ /g,'').replace('{{','').replace('}}','')
console.log('-> match = ', match, ' -- clef = ', clef)
return ctx[clef]
})
contenu = {}
return rendu
}
// lire la conf. dans le fichier .chromium_env
donneesFichierConfiguration = obtenirConfigurationDunFichier(['hostname', 'token', 'password', 'front_type', 'url', 'mode_nfc'], './.chromium_env')
const serveur = http.createServer(function(req, res){
let url = req.url;
// routes
let ctx = {}
if(url=='/') {
url = 'index.html'
ctx = {
fontType: afficherFrontType(),
nomAppareil: os.hostname(),
afficherInfoServeur: afficherInfoServeur(donneesFichierConfiguration),
urlServeur: donneesFichierConfiguration.url,
ip: obtenirIp('public','ipv4'),
typeLecteurNfc: typeLecteurNfc,
typeserveurNfc: 'nodejs'
}
}
if(url=='/favicon.ico') url = 'img/favicon2.ico'
fichier = www + url.substring(0,url.length);
//assets
let posDerPoint = url.lastIndexOf('.')
let extention = ''
if(posDerPoint != -1){
extention = url.substring(posDerPoint+1,url.length);
if(extention.toLowerCase() == 'css') contentType = 'text/css';
contentType = typeMime[extention.toLowerCase()];
}
try {
let contenuFichier = fs.readFileSync(fichier)
// rendre du html
if (extention === 'html') {
contenuFichier = renderHtml(contenuFichier, ctx)
}
res.writeHead(200, {"Content-Type": contentType})
res.write(contenuFichier)
res.end();
console.log('-> url = '+url+' -- fichier :'+fichier+' -- contentType = '+contentType+' -> chargé !');
} catch (err) {
console.log('-> url = ' + url + ' -- Erreur: ' + err)
retour404(res);
}
})
// --- socket.io ---
const options = {
// allowEIO3: true,
cors: {
origin: "*",
methods: ["PUT", "GET", "POST"]
}
}
const IO = require('socket.io')(serveur,options)
// middleware
IO.use(function(socket, next){
let token = socket.handshake.query.token
// console.log('token reçu = '+token+' -- TOKEN = '+TOKEN)
if (token === TOKEN){
return next()
} else {
next(new Error("ERREUR d'autentification !"))
}
})
IO.on('connection', client => {
client_globale = client;
client_globale.on('demandeTagId', (data) => {
retour = data;
console.log('-> demandeTagIdg = '+JSON.stringify(retour))
})
client_globale.on('AnnuleDemandeTagId', () => {
retour = null
})
client_globale.on('disconnect', () => {
console.log('Client déconnecté !!')
})
client_globale.on('validerModifierWifi', (data) => {
modifierConfigurationWifi(data)
})
client_globale.on('validerModifierServeur', (data) => {
modifierConfigurationServeur(data)
})
client_globale.on('testerUrlServeur', (urlATester) => {
console.log('-> test url serveur = ',urlATester)
testUrl(urlATester, 12)
})
client_globale.on('donnerInfosWifi', () => {
afficherInfosWifi()
})
client_globale.on('lancerApplication', () => {
lancerApplication()
})
})
// lancement serveur http
serveur.listen(PORT, ADR, () => {
console.log(`le serveur écoute http://localhost:${PORT}`)
})
const dataConf = obtenirConfigurationDunFichier(['hostname', 'token', 'password', 'front_type', 'url', 'mode_nfc'], './.chromium_env')
lancerChromium(1,dataConf)

View File

@ -0,0 +1,65 @@
// si problême de droit
// sudo chown root:gpio /dev/gpiomem
// sudo chmod g+rw /dev/gpiomem
// sudo chmod g+rw /dev/gpiomem
// sudo usermod -a -G gpio $USER
// sudo usermod -a -G spi $USER
// sudo usermod -a -G netdev $USER
"use strict"
// const event = require('events')
const EventEmitter = require('node:events')
const Mfrc522 = require("mfrc522-rpi")
const SoftSPI = require("rpi-softspi")
const vma405Emitter = new EventEmitter()
vma405Emitter.emit('msgVma405', 'scanning...')
const softSPI = new SoftSPI({
clock: 23, // pin number of SCLK
mosi: 19, // pin number of MOSI
miso: 21, // pin number of MISO
client: 24 // pin number of CS
});
// GPIO 24 can be used for buzzer bin (PIN 18), Reset pin is (PIN 22).
// const mfrc522 = new Mfrc522(softSPI).setResetPin(22).setBuzzerPin(18);
const mfrc522 = new Mfrc522(softSPI).setResetPin(22)
setInterval(function() {
//# reset card
mfrc522.reset();
// Scan for cards
let response = mfrc522.findCard();
if (!response.status) {
// console.log("No Card");
return;
}
// Get the UID of the card
response = mfrc522.getUid();
if (!response.status) {
vma405Emitter.emit('msgVma405', 'UID Scan Erro')
return;
}
// If we have the UID, continue
const uid = response.data;
let resultat = ''
for(let i=0; i < 4; i++){
let lettre = uid[i].toString(16).toUpperCase()
if(uid[i].toString(16).length === 1) {
resultat += '0' + lettre
} else {
resultat += lettre
}
}
// resultat
vma405Emitter.emit('tagId',resultat)
// Stop
mfrc522.stopCrypto();
}, 500);
module.exports = vma405Emitter

View File

@ -0,0 +1,43 @@
/* clavier virtuel */
#clavier-virtuel-conteneur {
position: absolute;
left: 0;
top: 0;
width: auto;
display: flex;
flex-direction: column;
overflow: hidden;
background-color: #d6dbdf;
}
.clavier-virtuel-ligne {
width: 100%;
height: 50px;
margin: 3px 0 3px 0;
display: flex;
flex-direction: row;
justify-content: flex-start;
align-items: center;
}
.clavier-virtuel-touche {
height: 50px;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
margin: 0 4px 0 4px;
/*border: 1px solid #000;*/
border-radius: 2px;
cursor: pointer;
box-shadow: inset 0 0 8px #bbb, 0 1px 0 #aaa, 0 4px 0 #bbb, 0 10px 30px #ddd;
}
.clavier-virtuel-text {
font-size: 16px;
font-weight: bold;
display: flex;
flex-direction: row;
justify-content: center;
color: #000000;
}

View File

@ -0,0 +1,280 @@
body {
font-size: 14px;
color: #000000;
width: 100%;
height: 100%;
overflow: hidden;
position: relative;
background: #18252f;
color: #fff;
height: 100vh;
width: 100vw;
margin: 0;
padding: 0;
}
.BF-ligne {
display: flex;
flex-direction: row;
/* axe ligne - x */
justify-content: center;
/* axe colonne - y */
align-items: center;
}
.BF-ligne-deb {
display: flex;
flex-direction: row;
justify-content: flex-start;
align-items: center;
}
.BF-col {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
.BF-col-deb {
display: flex;
flex-direction: column;
justify-content: center;
}
.BF-col-haut {
display: flex;
flex-direction: column;
justify-content: flex-start;
align-items: center;
}
/* padding x/y px */
.p4px {padding: 4px;}
.p8px {padding: 8px;}
.p12px {padding: 12px;}
.p16px {padding: 16px;}
/* marges x/y px */
.m4px {margin: 4px;}
.m8px {margin: 8px;}
.m12px {margin: 12px;}
.m16px {margin: 16px;}
/* marges gauche px */
.mg4px {margin-left: 4px;}
.mg8px {margin-left: 8px;}
.mg12px {margin-left: 12px;}
.mg16px {margin-left: 16px;}
/* marges droite px */
.md4px {margin-right: 4px;}
.md8px {margin-right: 8px;}
.md12px {margin-right: 12px;}
.md16px {margin-right: 16px;}
/* marges basse px */
.mb4px {margin-bottom: 4px;}
.mb8px {margin-bottom: 8px;}
.mb12px {margin-bottom: 12px;}
.mb16px {margin-bottom: 16px;}
/* largeur % */
.l50p { width: 50%;}
.l60p { width: 60%;}
.l99p { width: 99%; }
.l100p { width: 100%;}
/* hauteur % */
.h100p { height: 100%; }
/* fonte */
.ft-gras { font-weight: bold;}
.ft-1r { font-size: 1rem;}
.ft-1-5r { font-size: 1.5rem;}
.ft-2r { font-size: 2rem;}
/* fonds */
.fond-alerte {
background-color: #aa3a3a;
}
.fond-retour {
background-color: #3b567f;
}
.fond-header {
background-color: #1a1e25;
}
.fond-ok {
background-color: #339448;
}
.fond-info {
background-color: #17a2b8;
}
.fond-pasbon {
background-color: #a6adad;
}
.fond-dev1 {
background-color: #040426;
}
.fond-dev2 {
background-color: #0335b8;
}
.fond-dev3 {
background-color: #012584;
}
.fond-dev4 {
background-color: #011549;
}
.fond-dev5 {
background-color: #492601;
}
.fond-menu-cashless {
/*background-color: #b35c22;*/
background-color: #af6c7a;
}
.fond-coul1 {
background-color: #dc6575; /* #8d1737; */
}
/* couleurs */
.coulBlanc {
color: #ffffff;
}
.coul-alerte {
color: #aa3a3a;
}
.eff {
display: none!important;
}
.curseur-action {
cursor: pointer;
}
/* Header - Menu haut */
.navbar-horizontal {
display: flex;
flex-direction: row;
width: 100%;
border-bottom: 1px solid #303b44;
height: 60px;
}
.navbar-img {
width: 120px;
height: 100%;
}
.navbar-nom {
width: calc(100% - 120px);
height: 100%;
}
#contenu {
width: 100%;
height: calc(100% - 140px);
}
.item-info {
font-size: 18px;
font-weight: bold;
margin: 4px 0;
}
.bt {
height: 60px;
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
margin: 4px;
padding: 0 16px;
font-size: 16px;
font-weight: bold;
border: 2px solid #000000;
border-radius: 4px;
}
.bt-250px {
width: 250px;
}
.mod-wifi-label, .serveur-label {
width: 150px;
font-size: 16px;
font-weight: bold;
}
.input-pour-pi {
width: calc(100% - 170px);
font-size: 24px;
font-weight: bold;
height: 60px;
}
#modifier-wifi, #modifier-serveur{
width: 100%;
border-radius: 4px;
border: 2px solid #000000;
padding: 4px;
}
.mod-wifi-erreur, .mod-serveur-erreur {
width: 20px;
height: 20px;
border-radius: 10px;
background-color: #8A2400;
}
.mod-wifi-ok, .mod-serveur-ok {
width: 20px;
height: 20px;
border-radius: 10px;
background-color: #47e005;
}
.bt-valider {
width: 150px;
}
#infos-plus {
background-color: #4caf50;
width: 100%;
overflow: auto;
}
footer {
height: 80px;
}
/* popup */
#popup{
position: absolute;
left: 0;
top: 0;
height: 100vh;
}
#popup-contenu {
width: 100%;
height: calc(100% - 80px);
}
#popup-footer {
width: 100%;
height: 80px;
font-size: 18px;
font-weight: bold;
}

View File

@ -0,0 +1,39 @@
<!DOCTYPE html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="css/clavier_virtuel.css">
<link rel="stylesheet" href="css/index.css">
<title>Tibillet</title>
</head>
<body>
<header class="l100p fond-header">
<nav class="navbar-horizontal">
<div class="navbar-img BF-col curseur-action" onclick="window.location.reload();">
<img alt="TiBillet" src="images/logo_115x46.png"/>
</div>
<div class="navbar-nom BF-ligne">
<h1>{{ nomAppareil }}</h1>
</div>
</nav>
</header>
<div id="contenu" class="BF-col-haut m4px" data-front-type="{{ fontType }}">
<div id="info-resolution-ecran" class="BF-ligne-deb item-info l100p"> Résolution: ?</div>
{{ afficherInfoServeur }}
<div class="BF-ligne-deb item-info l100p">Ip: {{ ip }}</div>
<div id="rep-info-reseau"></div>
<div class="BF-ligne-deb item-info l100p">Type serveur nfc: {{ typeserveurNfc }}</div>
<div class="BF-ligne-deb item-info l100p">Type lecteur nfc: {{ typeLecteurNfc }}</div>
<div class="BF-ligne-deb item-info l100p">tag Id:<span id="nfc"></span></div>
</div>
<footer class="l100p BF-ligne">
<div id="bt-lancer-application" class="fond-pasbon BF-col l100p h100p ft-1-5r ft-gras curseur-action" disabled>
<div>LANCER</div>
<div>L'APPLICATION</div>
</div>
</footer>
<script src="js/socket.io.js"></script>
<script type="module" src="js/index.js"></script>
</body>
</html>

View File

@ -0,0 +1,379 @@
export let pos = { debSel: 0, finSel: 0}
export let ancienEtatAlpha = 'alpahMin'
let etatsClavier = {
"alpahMin": [
[
{"type": "nombre", "taille": 1, "val": 97},
{"type": "nombre", "taille": 1, "val": 122},
{"type": "nombre", "taille": 1, "val": 101},
{"type": "nombre", "taille": 1, "val": 114},
{"type": "nombre", "taille": 1, "val": 116},
{"type": "nombre", "taille": 1, "val": 121},
{"type": "nombre", "taille": 1, "val": 117},
{"type": "nombre", "taille": 1, "val": 105},
{"type": "nombre", "taille": 1, "val": 111},
{"type": "nombre", "taille": 1, "val": 112}
],
[
{"type": "caractere", "taille": 1, "val": 'q'},
{"type": "caractere", "taille": 1, "val": 's'},
{"type": "caractere", "taille": 1, "val": 'd'},
{"type": "caractere", "taille": 1, "val": 'f'},
{"type": "caractere", "taille": 1, "val": 'g'},
{"type": "caractere", "taille": 1, "val": 'h'},
{"type": "caractere", "taille": 1, "val": 'j'},
{"type": "caractere", "taille": 1, "val": 'k'},
{"type": "caractere", "taille": 1, "val": 'l'},
{"type": "caractere", "taille": 1, "val": 'm'}
],
[
{"type": "mot", "taille": 1, "val": 'MAJ'},
{"type": "caractere", "taille": 1, "val": 'w'},
{"type": "caractere", "taille": 1, "val": 'x'},
{"type": "caractere", "taille": 1, "val": 'c'},
{"type": "caractere", "taille": 1, "val": 'v'},
{"type": "caractere", "taille": 1, "val": 'b'},
{"type": "caractere", "taille": 1, "val": 'n'},
{"type": "caractere", "taille": 1, "val": '?'},
{"type": "mot", "taille": 1, "val": "simpleGuillemet"},
{"type": "mot", "taille": 1, "val": 'SUP'}
],
[
{"type": "mot", "taille": 1, "val": 'ALT'},
{"type": "mot", "taille": 1, "val": 'NUM'},
{"type": "caractere", "taille": 1, "val": ','},
{"type": "mot", "taille": 2, "val": 'ESPACE'},
{"type": "caractere", "taille": 1, "val": '.'},
{"type": "mot", "taille": 2, "val": 'VALIDER'},
{"type": "mot", "taille": 2, "val": 'RETOUR LIGNE'}
],
],
"alpahMaj": [
[
{"type": "caractere", "taille": 1, "val": 'A'},
{"type": "caractere", "taille": 1, "val": 'Z'},
{"type": "caractere", "taille": 1, "val": 'E'},
{"type": "caractere", "taille": 1, "val": 'R'},
{"type": "caractere", "taille": 1, "val": 'T'},
{"type": "caractere", "taille": 1, "val": 'Y'},
{"type": "caractere", "taille": 1, "val": 'U'},
{"type": "caractere", "taille": 1, "val": 'I'},
{"type": "caractere", "taille": 1, "val": 'O'},
{"type": "caractere", "taille": 1, "val": 'P'}
],
[
{"type": "caractere", "taille": 1, "val": 'Q'},
{"type": "caractere", "taille": 1, "val": 'S'},
{"type": "caractere", "taille": 1, "val": 'D'},
{"type": "caractere", "taille": 1, "val": 'F'},
{"type": "caractere", "taille": 1, "val": 'G'},
{"type": "caractere", "taille": 1, "val": 'H'},
{"type": "caractere", "taille": 1, "val": 'J'},
{"type": "caractere", "taille": 1, "val": 'K'},
{"type": "caractere", "taille": 1, "val": 'L'},
{"type": "caractere", "taille": 1, "val": 'M'}
],
[
{"type": "mot", "taille": 1, "val": 'MAJ'},
{"type": "caractere", "taille": 1, "val": 'W'},
{"type": "caractere", "taille": 1, "val": 'X'},
{"type": "caractere", "taille": 1, "val": 'C'},
{"type": "caractere", "taille": 1, "val": 'V'},
{"type": "caractere", "taille": 1, "val": 'B'},
{"type": "caractere", "taille": 1, "val": 'N'},
{"type": "mot", "taille": 1, "val": "simpleGuillemet"},
{"type": "mot", "taille": 2, "val": 'SUP'},
],
[
{"type": "mot", "taille": 2, "val": 'NUM'},
{"type": "caractere", "taille": 1, "val": ','},
{"type": "mot", "taille": 4, "val": 'ESPACE'},
{"type": "caractere", "taille": 1, "val": '.'},
{"type": "mot", "taille": 2, "val": 'RETOUR LIGNE'}
],
],
"num": [
[
{"type": "caractere", "taille": 1, "val": '1'},
{"type": "caractere", "taille": 1, "val": '2'},
{"type": "caractere", "taille": 1, "val": '3'},
{"type": "caractere", "taille": 1, "val": '4'},
{"type": "caractere", "taille": 1, "val": '5'},
{"type": "caractere", "taille": 1, "val": '6'},
{"type": "caractere", "taille": 1, "val": '7'},
{"type": "caractere", "taille": 1, "val": '8'},
{"type": "caractere", "taille": 1, "val": '9'},
{"type": "caractere", "taille": 1, "val": '0'}
],
[
{"type": "caractere", "taille": 1, "val": '@'},
{"type": "caractere", "taille": 1, "val": '#'},
{"type": "caractere", "taille": 1, "val": '$'},
{"type": "caractere", "taille": 1, "val": '%'},
{"type": "caractere", "taille": 1, "val": '&'},
{"type": "caractere", "taille": 1, "val": '*'},
{"type": "caractere", "taille": 1, "val": '_'},
{"type": "caractere", "taille": 1, "val": '+'},
{"type": "caractere", "taille": 1, "val": '('},
{"type": "caractere", "taille": 1, "val": ')'},
],
[
{"type": "caractere", "taille": 1, "val": '-'},
{"type": "caractere", "taille": 1, "val": '['},
{"type": "caractere", "taille": 1, "val": ']'},
{"type": "caractere", "taille": 1, "val": '!'},
{"type": "caractere", "taille": 1, "val": '"'},
{"type": "mot", "taille": 1, "val": "simpleGuillemet"},
{"type": "caractere", "taille": 1, "val": ':'},
{"type": "caractere", "taille": 1, "val": ';'},
{"type": "caractere", "taille": 1, "val": '/'},
{"type": "caractere", "taille": 1, "val": '?'}
],
[
{"type": "mot", "taille": 2, "val": 'ABC'},
{"type": "mot", "taille": 1, "val": 'ALT'},
{"type": "mot", "taille": 4, "val": 'ESPACE'},
{"type": "caractere", "taille": 1, "val": '.'},
{"type": "mot", "taille": 2, "val": 'RETOUR LIGNE'}
],
],
"alt": [
[
{"type": "caractere", "taille": 1, "val": '~'},
{"type": "caractere", "taille": 1, "val": '`'},
{"type": "caractere", "taille": 1, "val": '|'},
{"type": "caractere", "taille": 1, "val": '.'},
{"type": "caractere", "taille": 1, "val": 'x'},
{"type": "caractere", "taille": 1, "val": '{'},
{"type": "caractere", "taille": 1, "val": '}'},
{"type": "caractere", "taille": 1, "val": '€'},
{"type": "caractere", "taille": 1, "val": '°'},
{"type": "caractere", "taille": 1, "val": '^'},
],
[
{"type": "mot", "taille": 2, "val": 'NUM'},
{"type": "caractere", "taille": 1, "val": '_'},
{"type": "caractere", "taille": 1, "val": '='},
{"type": "caractere", "taille": 1, "val": '['},
{"type": "caractere", "taille": 1, "val": ']'},
{"type": "caractere", "taille": 1, "val": '<'},
{"type": "caractere", "taille": 1, "val": '>'},
{"type": "mot", "taille": 1, "val": 'antiSlash'},
{"type": "caractere", "taille": 1, "val": '"'}
],
[
{"type": "mot", "taille": 2, "val": 'ABC'},
{"type": "mot", "taille": 4, "val": 'ESPACE'},
{"type": "mot", "taille": 2, "val": 'VALIDER'},
{"type": "mot", "taille": 2, "val": 'RETOUR LIGNE'}
],
],
"numSolo": [
[
{"type": "caractere", "taille": 1, "val": '1'},
{"type": "caractere", "taille": 1, "val": '2'},
{"type": "caractere", "taille": 1, "val": '3'},
{"type": "caractere", "taille": 1, "val": '4'}
],
[
{"type": "caractere", "taille": 1, "val": '5'},
{"type": "caractere", "taille": 1, "val": '6'},
{"type": "caractere", "taille": 1, "val": '7'},
{"type": "caractere", "taille": 1, "val": '8'}
],
[
{"type": "caractere", "taille": 1, "val": '9'},
{"type": "caractere", "taille": 1, "val": '0'},
{"type": "caractere", "taille": 1, "val": '.'},
{"type": "mot", "taille": 1, "val": 'C'}
],
[
{"type": "mot", "taille": 2, "val": 'SUP'},
{"type": "mot", "taille": 2, "val": 'VALIDER'}
]
]
}
function obtEtatSelection (cible){
let element = document.getElementById(cible)
// plage de sélection
let debSel = element.selectionStart
let finSel = element.selectionEnd
return { debSel: debSel, finSel: finSel }
}
export function simule(touche, typeTouche, cible) {
let etat
let element = document.getElementById(cible)
// ajout de cartères qui induisent des erreurs de d'interprétation du code html/javascript
if (touche === 'simpleGuillemet') {
touche = "'"
typeTouche = 'caractere'
}
if (touche === 'antiSlash') {
touche = "\\"
typeTouche = 'caractere'
}
if (touche === 'ESPACE') {
touche = ' '
typeTouche = 'caractere'
}
if (touche === 'RETOUR LIGNE') {
touche = '\n'
typeTouche = 'caractere'
}
// entrée clavier
if (typeTouche !== 'mot') {
let texte = element.value
// tout le texte avant le début de sélection
let texteAvant = texte.substring(0, pos.debSel)
// tout le texte après la fin de sélection
let texteApres = texte.substring(pos.finSel, texte.length)
// nouveau texte
element.value = texteAvant + touche + texteApres
// maj position curseur
pos.debSel += 1
pos.finSel = pos.debSel
}
// état du clavier
if (touche === 'MAJ') {
if (etat === 'alpahMaj' ){
etat = 'alpahMin'
ancienEtatAlpha = 'alpahMin'
} else {
etat = 'alpahMaj'
ancienEtatAlpha = 'alpahMaj'
}
afficher(cible, etat)
}
if (touche === 'NUM') {
etat = 'num'
afficher(cible, etat)
}
if (touche === 'ABC') {
etat = ancienEtatAlpha
afficher(cible, etat)
}
if (touche === 'ALT') {
etat = 'alt'
afficher(cible, etat)
}
// touche supprimer
if (touche === 'SUP') {
let texteAvant, texteApres
let texte = element.value
// selection ?
let sel = obtEtatSelection(cible)
if (sel.debSel !== sel.finSel) {
pos.debSel = sel.debSel
pos.finSel = sel.finSel
}
if (sel.debSel === sel.finSel) { // pas de sélection
texteAvant = texte.substring(0, pos.debSel-1)
pos.debSel -= 1
} else { // sélection
texteAvant = texte.substring(0, pos.debSel)
}
texteApres = texte.substring(pos.finSel, texte.length)
pos.finSel = pos.debSel
element.value = texteAvant + texteApres
}
//Vider l'entréé
if (touche === 'C') {
document.querySelector('#' + cible).value = ''
}
// validation
if (touche === 'VALIDER') {
let eleSup = document.querySelector('#clavier-virtuel-conteneur')
eleSup.parentNode.removeChild(eleSup)
}
}
export function obtPosition(cible){
let element = document.getElementById(cible)
pos = { debSel: element.selectionStart, finSel: element.selectionEnd}
}
export function afficher(cible, etat) {
let largeurTouche = 50
try {
// supprime un ancien clavier virtuel et son évènement
let eleSup = document.querySelector('#clavier-virtuel-conteneur')
eleSup.parentNode.removeChild(eleSup)
} catch (error) {
console.log("info: l'élément clavier n'existait pas !")
}
let touches = etatsClavier[etat]
let clavierFrag = `
<div id="clavier-virtuel-conteneur">
`
for (let i = 0; i < touches.length; i++) {
let ligne = touches[i]
clavierFrag += `
<div class="clavier-virtuel-ligne">
`
for (let j = 0; j < ligne.length; j++) {
let typeData = ligne[j].type
let taille = ligne[j].taille
let val = ligne[j].val
let retour, goutiere = 0
if (typeData === 'nombre') {
retour = String.fromCharCode(val)
} else {
retour = val
}
if (taille > 1) {
goutiere = (taille-1) * 8
}
// console.log('-> typeData = ' + typeData + ' -- taille = ' + taille + ' -- val = ' + val + ' -- retour = ' + retour)
clavierFrag += `
<div class="clavier-virtuel-touche" onclick="clavierVirtuel.simule('${ retour }', '${ typeData }', '${ cible }')"
style="width: ${ (goutiere + taille * largeurTouche) }px">
`
if (typeData === 'nombre' || typeData === 'caractere' || typeData === 'caractereSpecial') {
clavierFrag += `<div class="clavier-virtuel-text">${ retour }</div>`
}
if (typeData === 'mot') {
if (val === 'simpleGuillemet') {
clavierFrag += `<div class="clavier-virtuel-text">'</div>`
}
if (val === 'antiSlash') {
clavierFrag += `<div class="clavier-virtuel-text">\\</div>`
}
if (val !== 'simpleGuillemet' && val !== 'antiSlash') {
let text = val.split(' ')
for (let k = 0; k < text.length; k++) {
clavierFrag += `<div class="clavier-virtuel-text">${text[k]}</div>`
}
}
}
clavierFrag += `</div>`
}
clavierFrag += `</div>`
}
clavierFrag += '</div>'
document.querySelector('body').insertAdjacentHTML('beforeend', clavierFrag)
}

View File

@ -0,0 +1,234 @@
// initialisation
window.store = {}
const TOKEN = '$a;b2yuM5454@4!cd'
let socket = io('http://localhost:3000',{ query: { token: TOKEN} })
let etatServeur = 0
import * as ClavierVirtuel from "./clavier_virtuel.js"
window.clavierVirtuel = ClavierVirtuel
function popup(data) {
let fondPopup = 'fond-header'
if (data.typeMessage === 'alerte') {
fondPopup = 'fond-alerte'
}
if (data.typeMessage === 'succes') {
fondPopup = 'fond-ok'
}
let frag = `
<div id="popup" class="${ fondPopup } l100p">
<div id="popup-contenu" class="BF-col-haut" >
${ data.contenu }
</div>
<div id="popup-footer" class="BF-ligne fond-retour" onclick="let elePopup = document.querySelector('#popup');elePopup.parentNode.removeChild(elePopup)">RETOUR</div>
</div>
`
let elePopup = document.querySelector('#popup')
if (elePopup !== null) {
elePopup.parentNode.removeChild(elePopup)
document.body.insertAdjacentHTML('afterbegin', frag)
} else {
document.body.insertAdjacentHTML('afterbegin', frag)
}
}
// messages divers
socket.on('afficherMsg', (retour) => {
// exemple, retour = { contenu: retour, typeMessage: 'succes' }
popup(retour)
})
// Réception tagId
socket.on('afficherMsgErreur', (retour) => {
let data = {
contenu: retour,
typeMessage: 'alerte'
}
popup(data)
})
// Retour infos wifi
socket.on('retourInfosWifi', (fragmentHtml) => {
// console.log('-> retourInfosWifi !!!')
document.querySelector('#rep-info-reseau').insertAdjacentHTML('afterend', fragmentHtml)
document.querySelector('#bt-modifier-wifi').addEventListener('click', function () {
let contenuClass = document.querySelector('#modifier-wifi').classList.value
if (contenuClass.indexOf('eff') !== -1 ) {
cacherContenuFormSauf('modifier-wifi')
} else {
document.querySelector('#modifier-wifi').classList.add('eff')
}
})
document.querySelector('#bt-valider-modifier-wifi').addEventListener('click', function () {
let essid = document.querySelector('#essid').value
let passePhrase = document.querySelector('#pp').value
// console.log('essid = ',essid, ' -- passePhrase = ', passePhrase)
socket.emit('validerModifierWifi', {essid: essid, passePhrase: passePhrase})
effacerClavierVirtuel()
})
})
socket.on('etatUrlServeur', (retourTestUrl) => {
// header 307 = redirection temporaire
// header 308 = redirection permanente
if(retourTestUrl === '200' || retourTestUrl === '307' || retourTestUrl === '308') {
document.querySelector('#info-serveur').style.color = "#00FF00"
// bt lancer l'application
etatServeur = 1
document.querySelector('#bt-lancer-application').classList.remove('fond-pasbon')
document.querySelector('#bt-lancer-application').classList.add('fond-ok')
} else {
document.querySelector('#info-serveur').style.color = "#FF0000"
// bt lancer l'application
etatServeur = 0
document.querySelector('#bt-lancer-application').classList.remove('fond-ok')
document.querySelector('#bt-lancer-application').classList.add('fond-pasbon')
}
})
socket.on('infosTagId', (retour) => {
document.querySelector('#nfc').innerHTML = retour
})
// message modification wifi
socket.on('modificationWifi', (retour) => {
console.log('wifi: ',retour)
let data = {}
if (retour.erreur === 0) {
document.querySelector('#etat-modifier-wifi').classList.remove('mod-wifi-erreur')
document.querySelector('#etat-modifier-wifi').classList.add('mod-wifi-ok')
data = { contenu: retour.msg, typeMessage: 'succes' }
} else {
document.querySelector('#etat-modifier-wifi').classList.remove('mod-wifi-ok')
document.querySelector('#etat-modifier-wifi').classList.add('mod-wifi-erreur')
document.querySelector('#modifier-wifi').classList.toggle('eff')
data = { contenu: retour.msg, typeMessage: 'alerte' }
}
popup(data)
cacherContenuFormTous()
})
// modification serveur
socket.on('modificationServeur', (retour) => {
console.log('serveur: ',retour)
let data = {}
if (retour.erreur === 0) {
document.querySelector('#etat-modifier-serveur').classList.remove('mod-serveur-erreur')
document.querySelector('#etat-modifier-serveur').classList.add('mod-serveur-ok')
data = {
contenu: `
<div class="l100p h100p BF-col">
<h1>Modification du serveur effectuée :</h1>
<h2>serveur = ${ retour.serveurDomaine} .</h2>
<h2 class="coul-alerte">Vous devez redémmarer l'appareil</h2>
<h2 class="coul-alerte">pour prendre en compte le nouveau serveur .</h2>
</div>
`,
typeMessage: 'succes'
}
document.querySelector('#info-serveur').innerHTML = `Serveur: ${ retour.serveurDomaine }`
} else {
document.querySelector('#etat-modifier-serveur').classList.remove('mod-serveur-ok')
document.querySelector('#etat-modifier-serveur').classList.add('mod-serveur-erreur')
document.querySelector('#modifier-serveur').classList.toggle('eff')
data = {
contenu: `
<h1>Erreur modification serveur !</h1>
`,
typeMessage: 'alerte'
}
}
popup(data)
cacherContenuFormTous()
})
function cacherContenuFormSauf(id) {
// console.log('-> fonction cacherContenuFormSauf, id = ', id)
let eles = document.querySelectorAll('.contenu-form')
for (let i = 0; i < eles.length; i++) {
let ele = eles[i]
let idEle = ele.id
// console.log('idEle = ', idEle)
ele.classList.add('eff')
if (id === idEle) {
ele.classList.remove('eff')
}
}
}
function cacherContenuFormTous() {
cacherContenuFormSauf('nimportequoi')
}
function effacerClavierVirtuel() {
let clavier = document.querySelector('#clavier-virtuel-conteneur')
if (clavier !== null) {
clavier.parentNode.removeChild(clavier)
}
}
window.addEventListener('load',function() {
let resolution = 'Résolution: ' + document.body.clientWidth + 'x' + document.body.clientHeight
document.querySelector('#info-resolution-ecran').innerHTML = resolution
let urlATester = document.querySelector('#info-serveur').getAttribute('data-serveur')
if (urlATester !== '' && urlATester !== undefined) {
socket.emit('testerUrlServeur', urlATester)
}
let emplacementInfosReseau = document.querySelector('#rep-info-reseau')
socket.emit('donnerInfosWifi', '')
})
if (document.querySelector('#bt-modifier-serveur')) {
document.querySelector('#bt-modifier-serveur').addEventListener('click', function () {
let contenuClass = document.querySelector('#modifier-serveur').classList.value
if (contenuClass.indexOf('eff') !== -1 ) {
cacherContenuFormSauf('modifier-serveur')
effacerClavierVirtuel()
} else {
document.querySelector('#modifier-serveur').classList.add('eff')
}
})
}
if (document.querySelector('#bt-valider-modifier-serveur')) {
document.querySelector('#bt-valider-modifier-serveur').addEventListener('click', function () {
let serveurDomaine = document.querySelector('#serveur').value
let user = document.querySelector('#nom-appareil').value
let typeFront = document.querySelector('#type-front').value
let genererMotDePasse = document.querySelector('#passe').checked
// console.log('genererMotDePasse = ', genererMotDePasse)
socket.emit('validerModifierServeur', {serveurDomaine: serveurDomaine, user: user, typeFront: typeFront, genererMotDePasse: genererMotDePasse})
effacerClavierVirtuel()
})
}
if (document.querySelector('#bt-tester-serveur')) {
document.querySelector('#bt-tester-serveur').addEventListener('click', function () {
let urlATester = document.querySelector('#info-serveur').getAttribute('data-serveur')
if (urlATester !== '' && urlATester !== undefined) {
socket.emit('testerUrlServeur', urlATester)
}
effacerClavierVirtuel()
})
}
document.querySelector('#bt-lancer-application').addEventListener('click',function() {
if (etatServeur === 1) {
// let urlRedirection = document.querySelector('#info-serveur').getAttribute('data-url-serveur')
// console.log(`${ new Date() } -> lancer l'application à l'url: ${ urlRedirection }`)
// console.log('agent = ', JSON.stringify(navigator.userAgent, null, '\t'))
//window.location = urlRedirection
socket.emit('lancerApplication')
}
effacerClavierVirtuel()
})

File diff suppressed because it is too large Load Diff

BIN
splash.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 112 KiB

BIN
vma405.jpg Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 592 KiB

65
vma405.js Executable file
View File

@ -0,0 +1,65 @@
// si problême de droit
// sudo chown root:gpio /dev/gpiomem
// sudo chmod g+rw /dev/gpiomem
// sudo chmod g+rw /dev/gpiomem
// sudo usermod -a -G gpio $USER
// sudo usermod -a -G spi $USER
// sudo usermod -a -G netdev $USER
"use strict"
// const event = require('events')
const EventEmitter = require('node:events')
const Mfrc522 = require("mfrc522-rpi")
const SoftSPI = require("rpi-softspi")
const vma405Emitter = new EventEmitter()
vma405Emitter.emit('msgVma405', 'scanning...')
const softSPI = new SoftSPI({
clock: 23, // pin number of SCLK
mosi: 19, // pin number of MOSI
miso: 21, // pin number of MISO
client: 24 // pin number of CS
});
// GPIO 24 can be used for buzzer bin (PIN 18), Reset pin is (PIN 22).
// const mfrc522 = new Mfrc522(softSPI).setResetPin(22).setBuzzerPin(18);
const mfrc522 = new Mfrc522(softSPI).setResetPin(22)
setInterval(function() {
//# reset card
mfrc522.reset();
// Scan for cards
let response = mfrc522.findCard();
if (!response.status) {
// console.log("No Card");
return;
}
// Get the UID of the card
response = mfrc522.getUid();
if (!response.status) {
vma405Emitter.emit('msgVma405', 'UID Scan Erro')
return;
}
// If we have the UID, continue
const uid = response.data;
let resultat = ''
for(let i=0; i < 4; i++){
let lettre = uid[i].toString(16).toUpperCase()
if(uid[i].toString(16).length === 1) {
resultat += '0' + lettre
} else {
resultat += lettre
}
}
// resultat
vma405Emitter.emit('tagId',resultat)
// Stop
mfrc522.stopCrypto();
}, 500);
module.exports = vma405Emitter