Files
shipheart-qt/config_reseau_one_wire.qml
T

491 lines
26 KiB
QML

//========================================================================================================================================================================
// CONFIG_RESEAU_ONE_WIRE.QML
// Ce fichier traite la configuration des devices One Wire. La page permet notamment de :
// - Afficher tous les capteurs déjà configurés (présents ou absent mais utilisés sur un capteur)
// - Déclencher la recherche de nouveaux capteurs OW
// La page est appelée depuis la page PARAMETRES_AVANCES.
//========================================================================================================================================================================
import QtQuick 2.12
import QtQuick.Controls 2.12
import qt.koriolan.shipheart 1.0
Shipheart_page {
id: page_config_reseau_one_wire
// Mis en forme :
readonly property double affichage_hauteur_utile: shipheart_hauteur_page - shipheart_hauteur_bandeau_haut - shipheart_hauteur_bandeau_bas
readonly property double pourcentage_largeur_labels_formulaire: 0.5
readonly property int nombre_capteurs_affiches_sur_une_colonne: 8
readonly property int nombre_sondes_affichees_sur_une_colonne: 8
readonly property double pourcentage_largeur_colonne_gauche: 0.75
readonly property int espace_colonnes_principales: 20
readonly property double pourcentage_bandeau_bas_largeur_zone_retour: 1.0
readonly property int periode_init_raffraichissement_parametres: 1 // En ms
readonly property int periode_raffraichissement_parametres: 1000 // En ms /!\ Laisser à 1s afin que le compteur secondes fonctionne correctement...
readonly property int periode_decouverte_reseau_ow: 10 // En secondes
// Affichage :
property int niveau_page: 0
property int defaut_bus_ow: 0
property int compteur_secondes: periode_decouverte_reseau_ow // Cette init permet de débuter par une découverte réseau
// 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();
}
if (stackView.depth === (niveau_page + 1)) // Désactive le raffraichissement quand la page n'est pas activée dans la pile
{
compteur_secondes ++;
if (compteur_secondes >= periode_decouverte_reseau_ow)
{
compteur_secondes = 0;
demande_decouverte_ow(); // On fait une découverte OW toutes les 10 secondes tant qu'on est sur cette page (et uniquement quand on est sur cette page !)
}
else
{
if (compteur_secondes >= 2) mise_a_jour_donnees(); // La mise à jour des données se fait toutes les secondes, sauf entre 0 et 2s (pour laisser le temps à la découverte réseau de se terminer et ainsi éviter les affichages tronqués)
}
}
}
}
// Titre de la page :
Shipheart_titre_1 {titre:qsTr("Réseau One Wire"); hauteur: shipheart_hauteur_bandeau_haut}
//-------------------------------------------------------
// Ecran de gauche (liste des capteurs) :
//-------------------------------------------------------
Rectangle {
id: zone_affichage_gauche
x: 0
y: shipheart_hauteur_bandeau_haut;
width: (shipheart_largeur_page * pourcentage_largeur_colonne_gauche) - (espace_colonnes_principales / 2)
height: affichage_hauteur_utile
color: "transparent"
//-------------------------------------------------------------------
// Grille pour afficher les devices :
GridView {
id: grille_principale
width: parent.width
height: affichage_hauteur_utile - (affichage_hauteur_utile / nombre_sondes_affichees_sur_une_colonne)
cellWidth: parent.width;
cellHeight: affichage_hauteur_utile / nombre_sondes_affichees_sur_une_colonne
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
visible: (defaut_bus_ow === 0)
delegate: Rectangle {
width: grille_principale.cellWidth
height: grille_principale.cellHeight
color: "transparent"
Rectangle {
width: parent.width - 10
height: parent.height - 10
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
radius: shipheart_rayon_bouton
color: (erreur === 0) ? shipheart_couleur_fond_bouton : couleur_rouge_transparent
border.color: couleur_blanc_casse
border.width: ((affecte === 0) && (erreur === 0)) ? 1 : 0
Text {
anchors.fill: parent
horizontalAlignment: Qt.AlignLeft
verticalAlignment: Qt.AlignTop
topPadding: 10
leftPadding: 20
text: "ID : " + rom_code
color: ((affecte === 1) && (erreur === 0)) ? couleur_gris_moyen : couleur_blanc_casse
font.pixelSize: 14
wrapMode: Label.Wrap
}
Text {
anchors.fill: parent
horizontalAlignment: Qt.AlignLeft
verticalAlignment: Qt.AlignTop
topPadding: 10
leftPadding: parent.width / 2
text: device_family + " [" + device_family_description + "]"
color: ((affecte === 1) && (erreur === 0)) ? couleur_gris_moyen : couleur_blanc_casse
font.pixelSize: 14
wrapMode: Label.Wrap
}
Text {
anchors.fill: parent
horizontalAlignment: Qt.AlignLeft
verticalAlignment: Qt.AlignBottom
bottomPadding: 10
leftPadding: 20
text: nom
color: ((affecte === 1) && (erreur === 0)) ? couleur_gris_moyen : couleur_blanc_casse
font.pixelSize: 18
font.weight: Font.Bold
wrapMode: Label.Wrap
}
Text {
anchors.fill: parent
horizontalAlignment: Qt.AlignLeft
verticalAlignment: Qt.AlignBottom
bottomPadding: 10
leftPadding: parent.width / 2
text: emplacement
color: ((affecte === 1) && (erreur === 0)) ? couleur_gris_moyen : couleur_blanc_casse
font.pixelSize: 14
wrapMode: Label.Wrap
}
Text {
anchors.fill: parent
horizontalAlignment: Qt.AlignRight
verticalAlignment: Qt.AlignVCenter
rightPadding: 20
text: valeur
color: ((affecte === 1) && (erreur === 0)) ? couleur_gris_moyen : couleur_blanc_casse
font.pixelSize: 18
font.bold: true
// wrapMode: Label.Wrap
}
}
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.
anchors.fill: parent
onPressAndHold: {
shipheart_clic();
stackView.push("config_reseau_one_wire_modification.qml", {"rom_code": rom_code});
}
onClicked: {
shipheart_clic();
if (affecte === 0) stackView.push("config_capteur.qml", {"type_entrees": shipheart_capteur_type_entrees_ow, "entrees": rom_code});
}
}
}
ListModel {
id: modele_grille_principale
}
Label {
anchors.fill: parent
horizontalAlignment: Qt.AlignHCenter
verticalAlignment: Qt.AlignVCenter
visible: parent.count === 0
text: qsTr("Aucune sonde n'est encore installée...")
color: couleur_rouge_transparent
font.pixelSize: 15
font.bold: true
wrapMode: Label.Wrap
}
}
Rectangle {
id: message_defaut_bus_ow
anchors.fill: parent
color: "transparent"
border.width: 3
border.color: couleur_orange
radius: shipheart_rayon_bouton
visible: (defaut_bus_ow !== 0)
Text { // Affiche parfaitement 1, 2 ou 3 lignes de texte. A partir de 4 et 5, ça mort sur le contour du rectangle mais c'est encore lisible.
id: etat_circuit
width: parent.width - anchors.leftMargin;
wrapMode: Text.Wrap
horizontalAlignment: Text.AlignHCenter
text: qsTr("Le bus One Wire est actuellement détecté en court-circuit. <br />Cet état ne présente aucun danger mais l'empêche de fonctionner. <br /><br />Vérifier le câblage correspondant jusqu'à ce que ce message disparaisse.");
anchors {
horizontalCenter: parent.horizontalCenter
verticalCenter: parent.verticalCenter
}
font.pixelSize: 18
color: couleur_blanc_casse
}
}
}
//-------------------------------------------------------
// Ecran de droite (liste des sondes de température) :
//-------------------------------------------------------
Rectangle {
id: zone_affichage_droite
x: (shipheart_largeur_page * pourcentage_largeur_colonne_gauche) + (espace_colonnes_principales / 2)
y: shipheart_hauteur_bandeau_haut;
width: (shipheart_largeur_page * (1 - pourcentage_largeur_colonne_gauche)) - (espace_colonnes_principales / 2)
height: affichage_hauteur_utile
color: "transparent"
}
//-------------------------------------------------------
// Bandeau bas :
//-------------------------------------------------------
Row {
x: 0
y: shipheart_hauteur_page - shipheart_hauteur_bandeau_bas;
width: shipheart_largeur_page;
height: shipheart_hauteur_bandeau_bas;
padding: 5
spacing: 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()
}
}
}
}
// 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'.
// Principes :
// L'état de chaque device est caractérisé par 3 indicateurs :
// - Affectation : indique si le device est utilisé par un capteur (ou un équipement en général).
// - si 0 : le device n'est PAS utilisé
// - si 1 : le device est utilisé
// - Présence : indique si le device est physiquement présent (et donc qu'il a communiqué correctement lors de la dernière communication de la part du Compagnon)
// - si 0 : le device est absent
// - si 1 : le device est présent
// - Etat : indique l'état du device lui-même ou, par extension, l'état du réseau.
// - si 0 : le device fonctionne correctement
// - si -1 : le device comporte une erreur interne
// - si -2 : l'ensemble du bus est en erreur (cf alors également 'Defaut_bus_ow' dans TB_Système)
//
// Dans TB_One_wire, il n'y a JAMAIS d'entrée avec Présence=0 et Affectation=0. En effet, dans ce cas, l'entrée est supprimée.
//
// L'indicateur d'erreur est calculé comme la synthèse entre 'Etat<0' OU 'Affecté=1 ET Présence=0'. Si l'une de ces condition est vraie, l'indicateur d'erreur est vrai.
// Au-delà de 'erreur' qui prévaut pour l'affichage, on utilise 'Affectation' pour indiquer si le device est occupé ou pas.
//
// En synthèse, on gère 3 états distincts pour un device :
// 1. Erreur=0 et Affecté=1 : cas normal d'un device utilisé
// 2. Erreur=0 et Affecté=0 : cas normal d'un device non utilisé
// 3. Erreur=1 : cas d'un device en erreur (et a priori, utilisé car sinon, il est peu probabe qu'il soit dans la liste)
// A noter qu'un 4ème état existe mais il est global : si TB_Systeme.defaut_bus_ow=1, une page dédiée est affichée sur tout l'écran pour indiquer un défaut bus global.
//=============================================================================================================
// Init de la page
//=============================================================================================================
function init_page()
{
niveau_page = stackView.depth - 1; // Permet de stocker le niveau de la page dans la Stackview
mise_a_jour_donnees();
}
//=============================================================================================================
// Mise à jour des données
//=============================================================================================================
function mise_a_jour_donnees()
{
var req, res;
var i;
var nb_sondes;
var device_family;
var device_family_description;
var erreur;
//=======================================================================
// Grille principale (liste des sondes de température configurées) :
modele_grille_principale.clear(); // RAZ des valeurs existantes
req = 'SELECT Valeur FROM TB_Systeme WHERE Nom="Defaut_bus_ow" ';
res = bdd.requete_unique(req);
defaut_bus_ow = Number(res[0]);
if (defaut_bus_ow === 0) // Si un défaut de bus OW est en cours, il est inutile d'afficher quoi que ce soit...
{
req = 'SELECT ';
req += ' Rom_code, ';
req += ' CONV(substring_index(Rom_code,":",1), 16, 10) AS Type, ' // Extrait le premier octet du Rom_Code qui contient le Device-Family puis le convertit de Hexa en Décimal
req += ' Affecte, ';
req += ' Presence, ';
req += ' Etat, ';
req += ' Valeur, ';
req += ' Emplacement ';
req += ' FROM TB_One_wire ';
req += ' ORDER BY Rom_code';
nb_sondes = bdd.requete(req);
//console.log("Requête =" + req + " et nb réponses = " + nb_sondes);
for (i = 0; i < nb_sondes; i ++)
{
res = bdd.lecture_ligne();
if (!res.isEmpty)
{
// Recherche du type de device en fonction de ROM_CODE_0 :
switch(Number(res[1]))
{
case 0x01: device_family = "DS1990A, DS1990R, DS2401, DS2411"; device_family_description= "Serial number"; break;
case 0x02: device_family = "DS1991"; device_family_description= "Secure memory"; break;
case 0x04: device_family = "DS2404"; device_family_description= "EconoRAM time chip"; break;
case 0x05: device_family = "DS2405"; device_family_description= "Addressable switch"; break;
case 0x06: device_family = "DS1993"; device_family_description= "4Kb Memory button"; break;
case 0x08: device_family = "DS1992"; device_family_description= "1kb memory button"; break;
case 0x0A: device_family = "DS1995"; device_family_description= "16kb memory button"; break;
case 0x0B: device_family = "DS1985, DS2505"; device_family_description= "16kb add-only memory"; break;
case 0x0C: device_family = "DS1996"; device_family_description= "64kb memory button"; break;
case 0x0F: device_family = "DS1986, DS2506"; device_family_description= "64kb add-only memory"; break;
case 0x10: device_family = "DS18S20"; device_family_description= "Temperature sensor"; break;
case 0x12: device_family = "DS2406, DS2407"; device_family_description= "Dual addressable switch"; break;
case 0x14: device_family = "DS1971, DS2430A"; device_family_description= "256b EEPROM"; break;
case 0x16: device_family = "DS1954, DS1957"; device_family_description= "Coprocessor ibutton"; break;
case 0x18: device_family = "DS1962, DS1963S"; device_family_description= "4kb monetary device with SHA"; break;
case 0x1A: device_family = "DS1963L"; device_family_description= "4kb monetary device"; break;
case 0x1B: device_family = "DS2436"; device_family_description= "Battery ID/monitor"; break;
case 0x1C: device_family = "DS28E04-100"; device_family_description= "4kb EEPROM with PIO"; break;
case 0x1D: device_family = "DS2423"; device_family_description= "4kb 1Wire RAM with counter"; break;
case 0x1E: device_family = "DS2437"; device_family_description= "Smart battery monitor IC"; break;
case 0x1F: device_family = "DS2409"; device_family_description= "Microlan coupler"; break;
case 0x20: device_family = "DS2450"; device_family_description= "Quad ADC"; break;
case 0x21: device_family = "DS1921G, DS1921H, DS1921Z"; device_family_description= "Thermochron loggers"; break;
case 0x22: device_family = "DS1822"; device_family_description= "Econo digital thermometer"; break;
case 0x23: device_family = "DS1973, DS2433"; device_family_description= "4kb EEPROM"; break;
case 0x24: device_family = "DS2415"; device_family_description= "Time chip"; break;
case 0x26: device_family = "DS2438"; device_family_description= "Smart battery monitor"; break;
case 0x27: device_family = "DS2417"; device_family_description= "Time chip"; break;
case 0x28: device_family = "DS18B20"; device_family_description= "Temperature sensor"; break; // Cas des DS18B20
case 0x29: device_family = "DS2408"; device_family_description= "8-channel switch"; break;
case 0x2C: device_family = "DS2890"; device_family_description= "Digital potentiometer"; break;
case 0x2D: device_family = "DS1972, DS2431"; device_family_description= "1024b memory"; break;
case 0x2E: device_family = "DS2770"; device_family_description= "Battery monitor/charge controller"; break;
case 0x30: device_family = "DS2760"; device_family_description= "Precision li+ battery monitor"; break;
case 0x31: device_family = "DS2720"; device_family_description= "Single cell li+ protection IC"; break;
case 0x32: device_family = "DS2780"; device_family_description= "Fuel gauge IC"; break;
case 0x33: device_family = "DS1961S, DS2432"; device_family_description= "1kb memory with SHA"; break;
case 0x34: device_family = "DS2703"; device_family_description= "Sha battery authentication"; break;
case 0x35: device_family = "DS2755"; device_family_description= "Fuel gauge"; break;
case 0x36: device_family = "DS2740"; device_family_description= "Coulomb counter"; break;
case 0x37: device_family = "DS1977"; device_family_description= "32kb memory"; break;
case 0x3D: device_family = "DS2781"; device_family_description= "Fuel gauge IC"; break;
case 0x3A: device_family = "DS2413"; device_family_description= "Two-channel switch"; break;
case 0x3B: device_family = "DS1825, MAX31826, MAX31850"; device_family_description= "Temperature sensor, TC reader"; break;
case 0x41: device_family = "DS1923, DS1922E, DS1922L, DS1922T"; device_family_description= "Hygrochrons"; break;
case 0x42: device_family = "DS28EA00"; device_family_description= "Digital thermometer with sequence detect"; break;
case 0x43: device_family = "DS28EC20"; device_family_description= "20kb memory"; break;
case 0x44: device_family = "DS28E10"; device_family_description= "Sha1 authenticator"; break;
case 0x51: device_family = "DS2751"; device_family_description= "Battery fuel gauge"; break;
case 0x7E: device_family = "EDS00xx"; device_family_description= "EDS sensor adapter"; break;
case 0x81: device_family = "USBID, DS1420"; device_family_description= "ID"; break;
case 0x82: device_family = "DS1425"; device_family_description= "ID and pw protected RAM"; break;
default: device_family = "<i>" + qsTr("Type inconnu") + "</i>"; break;
}
erreur = 0;
if (Number(res[4]) < 0) erreur = 1;
else
{
if ((Number(res[2]) === 1) && (Number(res[3]) === 0)) erreur = 1;
}
//console.log("Sonde OW trouvée : ROM_Code = [" + res[0] + "] donc Device_type = " + device_family_description);
modele_grille_principale.append({
"rom_code": res[0],
"nom": qsTr("Sonde non affectée"),
"device_family": device_family,
"device_family_description": device_family_description,
"affecte": Number(res[2]),
"presence": Number(res[3]),
"erreur": erreur,
"valeur": Number(res[5]).toFixed(2) + " °C",
"emplacement": res[6] });
console.log("ID:" + res[0] + " est " + Number(res[2]));
}
}
// Mise à jour du nom des capteurs utilisant ces sondes :
for (i = 0; i < modele_grille_principale.count; i ++)
{
if (modele_grille_principale.get(i).affecte > 0)
{
req = 'SELECT Nom FROM TB_Capteurs WHERE Adresse_module=0 AND Type_entrees=' + shipheart_capteur_type_entrees_ow + ' AND Entrees="' + modele_grille_principale.get(i).rom_code + '" ';
//console.log("Requête = [ " + req + "; ]");
var nb = bdd.requete(req);
if (nb > 0)
{
res = bdd.lecture_ligne();
modele_grille_principale.setProperty(i, "nom", res[0]);
}
}
}
}
}
//=============================================================================================================
// Demande de découverte OW
//=============================================================================================================
function demande_decouverte_ow()
{
var req, res;
var i;
var nb;
req = 'UPDATE TB_Systeme SET Valeur=1 WHERE Nom="Demande_decouverte_ow" ';
//console.log("req =" + req);
bdd.requete_unique(req);
}
}