Files
shipheart-qt/config_reseau_wifi_ap.qml
T

556 lines
24 KiB
QML

//========================================================================================================================================================================
// CONFIG_RESEAU_WIFI_AP.QML
// Ce fichier traite la configuration du Wifi en mode AP
// La page est appelée depuis la page parametres_avances.qml
//========================================================================================================================================================================
import QtQuick 2.12
import QtQml.Models
import qt.koriolan.shipheart 1.0
Shipheart_page {
id: page_config_reseau_wifi_ap
// Mis en forme :
readonly property double pourcentage_largeur_colonne_gauche: 0.75
readonly property double espace_colonnes_principales: 20
readonly property double espace_lignes_principales: 20
readonly property double affichage_hauteur_utile: shipheart_hauteur_page - shipheart_hauteur_bandeau_haut - shipheart_hauteur_bandeau_bas
readonly property int hauteur_ligne_formulaire: 60
readonly property double pourcentage_largeur_labels_formulaire: 0.4
readonly property int hauteur_bouton_droit: 80
readonly property double pourcentage_bandeau_bas_largeur_zone_retour: 1
readonly property int periode_init_raffraichissement_parametres: 1 // En ms
readonly property int periode_raffraichissement_parametres: 1000 // En ms
// Affichage :
property int protection_mode: 0
property bool flag_init: true // Permet de bloquer certains affichage tant que l'init n'est pas terminée
// Données :
property string ip_ap: ""
// Modèles :
// Note : les modèles chargés dans 'main.qml' n'ont pas à être rechargés dans les pages suivantes
//===========================================================
// Timer periode raffraichissement parametres :
//===========================================================
Timer {
id: timer_raffraichissement_parametres
interval: periode_init_raffraichissement_parametres
triggeredOnStart: false
running: true
repeat: true
onTriggered: {
if (interval == periode_init_raffraichissement_parametres) { // Premier passage, 1ms après le premier chargement
interval = periode_raffraichissement_parametres;
init_page();
}
else
{
mise_a_jour();
}
}
}
// Titre de la page :
Shipheart_titre_1 {titre:qsTr("Configuration Wifi en mode AP"); hauteur: shipheart_hauteur_bandeau_haut}
//-------------------------------------------------------
// Ecran Haut - Gauche :
//-------------------------------------------------------
Rectangle {
id: zone_affichage_haut_gauche
x: 0
y: shipheart_hauteur_bandeau_haut;
width: (shipheart_largeur_page * pourcentage_largeur_colonne_gauche) - (espace_colonnes_principales / 2)
height: affichage_hauteur_utile - espace_lignes_principales;
color: "transparent"
ListView {
id: grille_principale
width: parent.width
height: parent.height
snapMode: GridView.SnapToRow // L'arret de l'affichage se fera sur une rangée entière
clip: true // Nécessaire pour que les Delegates s'arretent à l'intérieur de la GridView
model: modele_grille_principale
footer: Rectangle { // Permet de dégager la place suffisante en fin de GridView pour accéder même au dernier élément lorsque que clavier est déplié
height: shipheart_hauteur_clavier
color: "transparent"
}
ObjectModel {
id: modele_grille_principale
//-------------------------------------------------------------------------------
// Ligne de formulaire : Ap_Commande
Rectangle {
width: parent.width
height: visible ? hauteur_ligne_formulaire : 0
color: "transparent"
//visible: false
Shipheart_formulaire_label {
text: qsTr("Etat")
width: parent.width * pourcentage_largeur_labels_formulaire
}
Shipheart_formulaire_combobox {
id: champ_formulaire_Ap_commande
model: ListModel { }
width: parent.width * (1 - pourcentage_largeur_labels_formulaire)
onActivated: {
shipheart_clic();
}
}
Shipheart_formulaire_ligne_separation {
haut_bas_hautbas: shipheart_formulaire_ligne_separation_basse
}
}
//-------------------------------------------------------------------------------
// Ligne de formulaire : AP_SSID
Rectangle {
width: (shipheart_largeur_page * pourcentage_largeur_colonne_gauche) - (espace_colonnes_principales / 2)
height: visible ? hauteur_ligne_formulaire : 0
color: "transparent"
visible: !flag_init && (champ_formulaire_Ap_commande.model.get(champ_formulaire_Ap_commande.currentIndex).valeur === 1)
Shipheart_formulaire_label {
text: qsTr("Nom du réseau (SSID)")
width: parent.width * pourcentage_largeur_labels_formulaire
}
Shipheart_formulaire_textfield {
id: champ_formulaire_Ap_ssid
width: parent.width * (1 - pourcentage_largeur_labels_formulaire)
x: parent.width * pourcentage_largeur_labels_formulaire
}
Shipheart_formulaire_ligne_separation {
haut_bas_hautbas: shipheart_formulaire_ligne_separation_basse
}
}
//-------------------------------------------------------------------------------
// Ligne de formulaire : AP_PWD
Rectangle {
width: (shipheart_largeur_page * pourcentage_largeur_colonne_gauche) - (espace_colonnes_principales / 2)
height: visible ? hauteur_ligne_formulaire : 0
color: "transparent"
visible: !flag_init && (champ_formulaire_Ap_commande.model.get(champ_formulaire_Ap_commande.currentIndex).valeur === 1)
Shipheart_formulaire_label {
text: qsTr("Mot de passe d'accès au réseau")
width: parent.width * pourcentage_largeur_labels_formulaire
}
Shipheart_formulaire_textfield {
id: champ_formulaire_Ap_pwd
width: parent.width * (1 - pourcentage_largeur_labels_formulaire)
x: parent.width * pourcentage_largeur_labels_formulaire
}
Shipheart_formulaire_ligne_separation {
haut_bas_hautbas: shipheart_formulaire_ligne_separation_basse
}
}
//-------------------------------------------------------------------------------
// Ligne de formulaire : AP_Canal
Rectangle {
width: parent.width
height: visible ? hauteur_ligne_formulaire : 0
color: "transparent"
visible: !flag_init && (champ_formulaire_Ap_commande.model.get(champ_formulaire_Ap_commande.currentIndex).valeur === 1)
//visible: false
Shipheart_formulaire_label {
text: qsTr("Canal")
width: parent.width * pourcentage_largeur_labels_formulaire
}
Shipheart_formulaire_combobox {
id: champ_formulaire_Ap_canal
model: ListModel { }
width: parent.width * (1 - pourcentage_largeur_labels_formulaire)
onActivated: {
shipheart_clic();
}
}
Shipheart_formulaire_ligne_separation {
haut_bas_hautbas: shipheart_formulaire_ligne_separation_basse
}
}
//-------------------------------------------------------------------------------
// Ligne de formulaire : Ip_AP
Rectangle {
width: (shipheart_largeur_page * pourcentage_largeur_colonne_gauche) - (espace_colonnes_principales / 2)
height: visible ? hauteur_ligne_formulaire : 0
color: "transparent"
visible: !flag_init && (champ_formulaire_Ap_commande.model.get(champ_formulaire_Ap_commande.currentIndex).valeur === 1)
//visible: false
Shipheart_formulaire_label {
text: qsTr("Adresse IP")
width: parent.width * pourcentage_largeur_labels_formulaire
}
Shipheart_formulaire_valeur_fixe {
text: (ip_ap === shipheart_adresse_ip_inconnue) ? qsTr("Non connecté") : ip_ap
width: parent.width * (1 - pourcentage_largeur_labels_formulaire)
x: parent.width * pourcentage_largeur_labels_formulaire
padding: 10
}
Shipheart_formulaire_ligne_separation {
haut_bas_hautbas: shipheart_formulaire_ligne_separation_basse
}
}
}
}
}
//-------------------------------------------------------
// Ecran Droite :
//-------------------------------------------------------
Rectangle {
id: zone_affichage_droite
x: zone_affichage_haut_gauche.width + espace_colonnes_principales
y: shipheart_hauteur_bandeau_haut;
width: (shipheart_largeur_page * (1 - pourcentage_largeur_colonne_gauche)) - (espace_colonnes_principales / 2)
height: affichage_hauteur_utile - (espace_lignes_principales / 2);
color: "transparent"
Column {
anchors.fill: parent
spacing: 10
// Bouton Enregistrer :
Rectangle {
width: parent.width
height: hauteur_bouton_droit
color: shipheart_couleur_fond_bouton
radius: shipheart_rayon_bouton
// visible: !clavier.active // SDIR #255
Text {
anchors {
verticalCenter: parent.verticalCenter
horizontalCenter: parent.horizontalCenter
}
font.pixelSize: 20
text: qsTr("Enregistrer")
color: couleur_blanc_casse
}
MouseArea {
anchors.fill: parent
onClicked: {
shipheart_clic();
var texte_erreur = check_saisie();
if (texte_erreur === "")
{
enregistrement(); // Mise à jour des données saisies dans la BDD et reconfiguration par l'application pour prise en compte.
stackView.pop(); // Retour aux Paramètres Avancés
}
else
{
boite_validation.niveau = 2
boite_validation.imageTitreSource = "/images/attention.png"
boite_validation.message = texte_erreur;
boite_validation.open();
}
}
}
}
}
}
//-------------------------------------------------------
// Bandeau bas :
//-------------------------------------------------------
Row {
x: 0
y: shipheart_hauteur_page - shipheart_hauteur_bandeau_bas;
width: shipheart_largeur_page;
height: shipheart_hauteur_bandeau_bas;
spacing: 5
padding: 5
//.................................................
// Bouton retour
//.................................................
Rectangle {
id: bandeau_bas_zone_retour
width: (parent.width * pourcentage_bandeau_bas_largeur_zone_retour) - (2 * parent.padding)
height: shipheart_hauteur_bandeau_bas - parent.topPadding - parent.bottomPadding;
radius: shipheart_rayon_bouton
color: shipheart_couleur_fond_bouton
Image {
source: "/images/icone_retour.png"
sourceSize.height: 30
anchors {
verticalCenter: parent.verticalCenter
horizontalCenter: parent.horizontalCenter
}
}
MouseArea { // Zone d'interaction. On est obligé de la mettre dans la grille pour que Rectangle et MouseArea soient frères ou parent/enfant ET qu'on n'occupe qu'un espace dans la grille.
id: mouse_area_bandeau_bas_zone_retour
anchors.fill: parent
onClicked: {
shipheart_clic();
stackView.pop()
}
}
}
}
//-------------------------------------------------------
// Boite de validation :
// NB : il est important que ce composant soit directement
// rattaché à la page pour qu'elle s'affiche en plein écran.
//-------------------------------------------------------
Shipheart_boite_dialogue {
id: boite_validation
boutonAnnuler: true
onClicked: {
switch(bouton)
{
case shipheart_boite_dialogue_bouton_1:
break;
case shipheart_boite_dialogue_bouton_2:
break;
default:
}
}
}
// Note : il est inutile de prévoir un Mousearea pour sortir de l'économiseur sur cette page puisqu'il
// est systématiquement bloqué pour toutes les pages lancées depuis 'Paramètres Avancés'.
//=============================================================================================================
// Init de la page
//=============================================================================================================
function init_page()
{
var req, res;
var nb;
var i;
var nom_champ, valeur_champ;
var commande_ap;
var mode;
var ap_canal;
//---------------------------------------------------------------------------------------
// Commande AP :
req = 'SELECT Valeur FROM TB_Configuration WHERE Nom="Wifi_ap_cde" ';
res = bdd.requete_unique(req);
commande_ap = Number(res[0]);
champ_formulaire_Ap_commande.model.clear();
champ_formulaire_Ap_commande.model.append({"valeur": 0, "texte": qsTr("Off") });
champ_formulaire_Ap_commande.model.append({"valeur": 1, "texte": qsTr("On") });
// Positionnement de l'index sur la valeur en cours :
i = recherche_index_valeur_modele(commande_ap, champ_formulaire_Ap_commande.model, "commande_ap");
if (i === -1) champ_formulaire_Ap_commande.currentIndex = recherche_index_valeur_modele(1, champ_formulaire_Ap_commande.model, "commande_ap");
else champ_formulaire_Ap_commande.currentIndex = i;
//---------------------------------------------------------------------------------------
// SSid_AP :
req = 'SELECT Valeur FROM TB_Configuration WHERE Nom="Wifi_ap_ssid" ';
res = bdd.requete_unique(req);
champ_formulaire_Ap_ssid.text = res[0];
//---------------------------------------------------------------------------------------
// Pwd_AP :
req = 'SELECT Valeur FROM TB_Configuration WHERE Nom="Wifi_ap_pwd" ';
res = bdd.requete_unique(req);
champ_formulaire_Ap_pwd.text = res[0];
//---------------------------------------------------------------------------------------
// Canal :
req = 'SELECT Valeur FROM TB_Configuration WHERE Nom="Wifi_ap_canal" ';
res = bdd.requete_unique(req);
ap_canal = Number(res[0]);
champ_formulaire_Ap_canal.model.clear();
var canaux = [];
if (shipheart_generation_shipbase === shipheart_generation_shipbase_v1)
{
for (i=1; i <= 11; i ++) canaux.push(i); // Canaux accessibles en 2.4GHz
}
else if (shipheart_generation_shipbase === shipheart_generation_shipbase_v2)
{
for (i=1; i <= 13; i ++) canaux.push(i); // Canaux accessibles en 2.4GHz
canaux.push(36); // Canaux accessibles en 5GHz (sans "logique" permettant d'éviter l'enregistrement manuel...)
canaux.push(40);
canaux.push(44);
canaux.push(48);
// Les canaux > 48 déclenchent une erreur... Ils apparaissent effectivement avec la mention '(no IR, radar detection)' dans le retour de 'iw list'.
/* canaux.push(52);
canaux.push(56);
canaux.push(60);
canaux.push(64);
canaux.push(100);
canaux.push(104);
canaux.push(108);
canaux.push(112);
canaux.push(116);
canaux.push(120);
canaux.push(124);
canaux.push(128);
canaux.push(132);
canaux.push(136);
canaux.push(140);
*/
}
// Remplissage du modèle :
var freq;
for (const canal of canaux)
{
if (canal < 36) freq = "2.4";
else freq = "5";
champ_formulaire_Ap_canal.model.append({"valeur": canal, "texte": qsTr("Canal %1 - [%2GHz]").arg(canal).arg(freq) });
}
// Positionnement de l'index sur la valeur en cours :
i = recherche_index_valeur_modele(ap_canal, champ_formulaire_Ap_canal.model, "Canal");
if (i === -1) champ_formulaire_Ap_canal.currentIndex = recherche_index_valeur_modele(11, champ_formulaire_Ap_canal.model, "Canal");
else champ_formulaire_Ap_canal.currentIndex = i;
//---------------------------------------------------------------------------------------
// Ip_AP :
req = 'SELECT Valeur FROM TB_Systeme WHERE Nom="Adresse_ip_wifi_ap" ';
res = bdd.requete_unique(req);
ip_ap = res[0];
flag_init = false; // Indique que l'init est terminée
}
//=============================================================================================================
// Mise à jour
//=============================================================================================================
function mise_a_jour()
{
var req, res;
//-------------------------------------------------------------------------------
// Mode AP
//-------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------
// Ip_AP :
req = 'SELECT Valeur FROM TB_Systeme WHERE Nom="Adresse_ip_wifi_ap" ';
res = bdd.requete_unique(req);
ip_ap = res[0];
}
//=============================================================================================================
// Check des valeurs saisies
// Retourne une chaine vide si Ok, le message d'erreur si NOK
//=============================================================================================================
function check_saisie()
{
if (champ_formulaire_Ap_commande.model.get(champ_formulaire_Ap_commande.currentIndex).valeur > 0)
{
var liste_caracteres_autorisés_ssid_ap = "-."; // En plus des chiffres et des lettres majuscules et minuscules
var regex_ssid_ap = new RegExp("(^[0-9A-Za-z]+$)");
var liste_caracteres_autorisés_pwd_ap = "-_./="; // En plus des chiffres et des lettres majuscules et minuscules
var regex_pwd_ap = new RegExp("(^[0-9A-Za-z" + liste_caracteres_autorisés_pwd_ap + "]+$)");
if ((champ_formulaire_Ap_ssid.text.length < 1) || (champ_formulaire_Ap_ssid.text.length > 32)) return(qsTr("Le nom du réseau (SSID) doit comprendre entre 1 et 32 caractères. <br />Merci d'entrer un nom valide."));
if ((champ_formulaire_Ap_pwd.text.length < 8) || (champ_formulaire_Ap_pwd.text.length > 63)) return(qsTr("Le mot de passe d'accès au réseau doit comprendre entre 8 et 63 caractères. <br />Merci d'entrer un mot de passe valide."));
if (! regex_ssid_ap.test(champ_formulaire_Ap_ssid.text)) // S'il y a autre chose que le regex
{
return(qsTr("Le nom du réseau (SSID) doit comprendre uniquement :<br />- des lettres majuscules [A - Z],<br />- des lettres minuscules [a - z],<br />- des chiffres [0 - 9]<br />- les caractères spéciaux [%1].<br /><br />Merci d'entrer un nom valide.").arg(liste_caracteres_autorisés_ssid_ap));
}
if (! regex_pwd_ap.test(champ_formulaire_Ap_pwd.text)) // S'il y a autre chose que le regex
{
return(qsTr("Le mot de passe d'accès au réseau doit comprendre uniquement :<br />- des lettres majuscules [A - Z],<br />- des lettres minuscules [a - z],<br />- des chiffres [0 - 9]<br />- les caractères spéciaux [%1].<br /><br />Merci d'entrer un nom valide.").arg(liste_caracteres_autorisés_pwd_ap));
}
}
return("");
}
//=============================================================================================================
// Mise à jour des valeurs saisies
//=============================================================================================================
function enregistrement()
{
var req;
// Mise à jour des nouvelles valeurs dans la BDD :
req = 'UPDATE TB_Configuration SET Valeur="' + champ_formulaire_Ap_commande.model.get(champ_formulaire_Ap_commande.currentIndex).valeur + '" WHERE Nom="Wifi_ap_cde" ';
bdd.requete_unique(req);
req = 'UPDATE TB_Configuration SET Valeur="' + champ_formulaire_Ap_ssid.text + '" WHERE Nom="Wifi_ap_ssid" ';
bdd.requete_unique(req);
req = 'UPDATE TB_Configuration SET Valeur="' + champ_formulaire_Ap_pwd.text + '" WHERE Nom="Wifi_ap_pwd" ';
bdd.requete_unique(req);
req = 'UPDATE TB_Configuration SET Valeur="' + champ_formulaire_Ap_canal.model.get(champ_formulaire_Ap_canal.currentIndex).valeur + '" WHERE Nom="Wifi_ap_canal" ';
bdd.requete_unique(req);
// Demande de rechargement de la config du Wifi :
req = 'UPDATE TB_Configuration SET Valeur=1 WHERE Nom="Wifi_new_config" ';
bdd.requete_unique(req);
}
//=============================================================================================================
// Recherche de l'index d'une certaine valeur dans un modele
//=============================================================================================================
function recherche_index_valeur_modele(cible, modele, nom_modele)
{
var i;
for (i=0; i<modele.count; i ++)
{
if (modele.get(i).valeur === cible) break; // Cas où la valeur cible a été trouvée parmi les valeurs du modèle
}
if (i === modele.count)
{
console.log("Aucune valeur trouvée pour cible = [" + cible + "] du modèle = " + nom_modele);
i = -1; // Cas où la valeur n'a pas été trouvée parmi les valeurs du modèle
}
//else console.log("Valeur trouvée : [" + i + "] pour cible = [" + cible + "] soit texte = [" + modele.get(i).texte + "]");
return(i);
}
}