Veolia-idf SEDIF - suivi consommation eau potable

Je n’ai pas encore essayé ce projet - je le surveille.

Je n’ai pas trop le temps pour le tester en ce moment.

Sinon l’autre méthode c’est de mettre à jour la base de données directement.
Voici un script avec lequel j’avais corrigé des erreurs dans la BDD suite à mon développement sous MetersToHA.
Je partage ce script comme éventuelle inspiration. Mais il faut comprendre comment cette table fonctionne!

#!/bin/bash
# 50, 51, 55

# Do update of gas_consumption_kwh
# metadata_id can be found in metadata table
#CREATE TABLE statistics_meta  (
#  id INTEGER NOT NULL,
#  statistic_id VARCHAR(255),
#  source VARCHAR(32),
#  unit_of_measurement VARCHAR(255),
#  has_mean BOOLEAN,
#  has_sum BOOLEAN,
#  name VARCHAR(255),
#  PRIMARY KEY (id)
#)

#mean,min,max,sum
#10727509|2023-01-24 20:30:11.186135|2023-01-24 20:25:00.000000|28657.0|28657.0|28657.0||||50

#28657.0|28657.0|28657.0

#select * from statistics_meta  where id=50 limit 1;
SENSOR="sensor.gas_consumption_kwh"
ID=$(sqlite3 home-assistant_v2.db <<EOSQL
select id from statistics_meta where statistic_id="$SENSOR";
EOSQL
)
echo $ID

if [ "$ID" == "" ] ; then
   echo "Could not find ID for $SENSOR"
fi

#972726|2023-02-09 01:00:10.924994|50|2023-02-09 00:00:00.000000|||||31783.0|36878.0
#11306625|2023-02-08 09:43:12.253890|2023-02-08 09:30:00.000000|||||31106.0|36201.0|50

#11333082|2023-02-09 01:20:10.813158|2023-02-09 01:15:00.000000|||||31783.0|36878.0|50
#12409700|||||||35059.0|40154.0|50|1678206912.48971|1678206600.0|

SHORT_TERM_IDX=12409982
LONG_IDX=1062482
#ID=50
STATE=35059
SUM=40154
ECHO=echo
#ECHO=

#set mean=null,min=null,max=null,state=28657,sum=33752
$ECHO sqlite3 home-assistant_v2.db <<EOSQL
update "statistics_short_term"
set mean=null,min=null,max=null,state=$STATE,sum=$SUM
where metadata_id in ($ID)
AND id>=$SHORT_TERM_IDX
;
EOSQL
#AND state=$STATE


#11250958|2023-02-06 23:25:14.204596|2023-02-06 23:20:00.000000|||||30994.0|36089.0|50
#id|created|start|mean|min|max|last_reset|state|sum|metadata_id
#10694884|2023-01-24 00:50:17.716574|2023-01-24 00:45:00.000000|28657.0|28657.0|28657.0||||50
#10694745|2023-01-24 00:45:31.049645|2023-01-24 00:40:00.000000|||||28657.0|33752.0|50

#10726675|2023-01-24 20:00:11.205636|2023-01-24 19:55:00.000000|||||28657.0|33752.0|50
#922191|2023-01-24 20:00:11.472642|50|2023-01-24 19:00:00.000000|||||28657.0|33752.0

sqlite3 home-assistant_v2.db <<EOSQL
.headers on
SELECT *
FROM "statistics_short_term"
where metadata_id in ($ID)
AND id>=$SHORT_TERM_IDX-500
order by id desc;
EOSQL



#970490|2023-02-08 09:00:10.979432|50|2023-02-08 08:00:00.000000|||||31106.0|36201.0
#965860|2023-02-06 23:00:13.290641|50|2023-02-06 22:00:00.000000|||||30994.0|36089.0
#set mean=null,min=null,max=null,state=28657,sum=33752
$ECHO sqlite3 home-assistant_v2.db <<EOSQL
update "statistics"
set mean=null,min=null,max=null,state=$STATE,sum=$SUM
where metadata_id in ($ID)
AND id>=$LONG_IDX
;
EOSQL
#AND state=$STATE

sqlite3 home-assistant_v2.db <<EOSQL
.headers on
SELECT *
FROM "statistics"
where metadata_id in ($ID)
AND id>=$LONG_IDX-5000
order by id desc;
EOSQL

Merci je vais regarder cela. Je suis sous MariaDB et il y a bien une fonction import CSV. cependant comme tu le dis il faut vérifier le fonctionnement de la table statistics et potentiellement des dépendances qu’il peut y avoir avec les autres tables.

La seule dépendence c’est d’utiliser le bon id - que l’on trouve dans statistics_meta (voir requête dans l’exemple).

Sinon, le tout c’est de bien construire date, le min/max (à priori null), la valeur de la periode et l’accumulation. On peut prendre comme exemple l’historique récente.
C’est scriptable et pourrait être indépendant du type de base de données et généralisé si on le fait sous Python (avec SQLAlchemy je crois).

Ok ca marche je ferais quelques test :sunglasses::+1:t4:

Bonjour,

J’ai légèrement adapté MetersToHA pour récuperer la consomation d’eau pour service.eau.veolia
Merci pour les différentes solutions déjà en place :slight_smile:

Simple question:
Le sensor récupere la dernière valeur dispo

                data = {
                    "state": meter_total,
                    "attributes": {
                        "date_time": date_time,
                        "unit_of_measurement": "L",
                        "device_class": "water",
                        "state_class": "total_increasing",
                    },
                }
                self.open_url(
                    HA_API_SENSOR_FORMAT
                    % (
                        "sensor.veolia_%s_total"
                        % (self.configuration[PARAM_VEOLIA_CONTRACT],),
                    ),
                    data,
                )

Est-il possible de charger les données historiques dans un sensor et si oui comment ?

Merci par avance

J’anticipe qu’un PR pour les changements arrives :wink: ? Merci!

Pour l’historique: j’en ai parlé ici: Veolia-idf SEDIF - suivi consommation eau potable - #143 par le_top .

Et récemment j’ai vu Add-on pour compteurs Linky qui semble avoir fait qqchse pour récupérer l’historique - ce qui peut aussi être une source d’idées.

Top, je vais regarder ! Merci encore !

Hello,

Il y a une autre solution en activant spook
Le service « recorder.import_statistics » sera disponible et pourra être appelé par webservice
reste a lire le fichier de veolia et créer des données en cumulées

Pour moi c’est la solution la plus simple

Pour plus d’info ici

Exemple de données à envoyer

service: recorder.import_statistics
data:
  has_mean: false
  has_sum: true
  statistic_id: sensor.veolia_XXX_total
  unit_of_measurement: m3
  source: recorder
  stats:
    - start: "2023-01-01T00:00:00+06:00"
      state: 10
      sum: 10

Intéressant.

A partir de cela j’ai trouvé:

et un test qui me semble intéressant:

Donc pas besoin de spooky à priori.

Puis, cela suggère que l’on peut ajouter une statistique pour un moment précis.

Et d’après d’autres indicateurs, cet api permettrai d’importer une historique.
A vérifier comment cela fonctionne, ensuite ajouter un sensor supplémentaire ou l’on ajoute ces éléments à l’heure de la consommation.
Il faudrait une option pour indiquer une date de début pour l’importation + un autre pour le forcer. A utiliser pour récupérer l’historique depuis cette date s’il n’y a pas encore de données ou si le forçage est actif…

Hello,

Oui effectivement il y a une dépendance ce qui n’est pas le plus optimale,

Je ne savais pas comment invoquer la websocket depuis le script python et je ne voulais pas passer plus de temps dessus.

Le code suivant met à jour le sensor avec la dernière valeur mesuré et charge toute les données historique du csv. Celà est utile dans mon cas car le relevé du compteur d’eau n’est pas journalier.

Il est adapté pour le site de veolia_service_eau_veolia_fr
Pour veolia IDF uniquement la date et le dernier paramètre (estimé/mesuré) sont formaté différament

    def update_veolia_service_eau_veolia_fr(self, csv_file):
        
        self.mylog("Parsing csv file")
        stats_array = []
        with open(csv_file, encoding="utf_8") as f:
            rows = list(csv.reader(f, delimiter=";"))

            # Remove the first row (header) from the list that is not useful
            rows = rows[1:]

             # Iterate through each row in reverse order, skipping the csv header line
            for row in reversed(rows): 

                method = row[3]  # "Mesuré" or "Estimé"
                #skip if estimated
                if method in ("E",):
                    self.mylog(f"File contains estimated data we skip it ")
                else:
                    # Assuming the original date format is "%d/%m/%Y"
                    date_obj = datetime.strptime(row[0], "%d/%m/%Y")
                    # Convert to ISO 8601 format with timezone and add 6h
                    date_with_timezone = date_obj.replace(tzinfo=timezone.utc).astimezone(timezone(timedelta(hours=6)))
                    # Format the date as a string
                    date_formated =  date_with_timezone.strftime("%Y-%m-%dT%H:%M:%S%z")

                    stat = {
                        "start": date_formated,  #formated date
                        "state": int(row[2]),
                        "sum": int(row[1])
                    }
                    # Add the stat to the array
                    stats_array.append(stat)
        
        # DEBUG - Print the data array
        #for item in stats_array:
        #    self.mylog("Date:" + str(item['start']) + ", state:" + str(item['state'])  + "sum:" + str(item['sum']))
        
        # Publish the last up to date statistics to the sensor
        self.mylog("Update the sensor with the most up to date info")
        sensor_data = {
                    "state": stats_array[0]["state"],
                    "attributes": {
                        "date_time": stats_array[0]["start"],
                        "unit_of_measurement": "L",
                        "device_class": "water",
                        "state_class": "total_increasing",
                    },
        }
        self.open_url(
            HA_API_SENSOR_FORMAT
            % (
                "sensor.veolia_%s_total"
                % (self.configuration[PARAM_VEOLIA_CONTRACT],),
            ),
            sensor_data,
        )
        self.mylog(st="OK")
        # Prepare the statistics that need to be sent
        data = {
                    "has_mean": False,
                    "has_sum": True,
                    "statistic_id":("sensor.veolia_%s_total" % self.configuration[PARAM_VEOLIA_CONTRACT]),
                    "unit_of_measurement": "L",
                    "source": "recorder",
                    "stats": stats_array
                }
        self.mylog("Publish all the historical data in the statistics")
        self.open_url(
            "/api/services/recorder/import_statistics",
            data
        )
        self.mylog(st="OK")
1 « J'aime »

Tres intéressant.
Tu l’utilises comment?

J’ai installé MetersToHA et Spook
Dans MetersToHA tu as toute la logique pour te connecter à Veolia et récuperer le CSV des consommations

J’ai ajouté cette fonction dans le fichier meters_to_ha.py
Reste ensuite à l’instancier au bon moment, simple si tu es sur veolia IDF (remplace la fonction update_veolia_device)

Dans mon cas je ne suis pas sur ce portail, j’ai ajouté un nouveau connecteur pour me connecter à veolia_service_eau_veolia_fr. Là c’est plus complexe car il faut scraper un autre site web (logique à re-developper). Là ou j’ai perdu du temps, le site me reconnaissais comme un bot, j’ai du changé le userAgent du browser, il faut integrer une logique pour renommer le dernier fichier téléchargé

C’est la que ce n’est pas evident car quand il telecharge les data dans le csv il y a une dizaine de jours avant. Moi j’ai tout récupéré au prealable. J’ai donc un csv que je veux traiter. Il faudrait peut etre que j’appel cette fonction avec le lien vers mon csv. J’essayerai commr ca. J’te dirai.

@Regis_Balmes J’ai intégré la fonction sans l’appeler dans https://github.com/mdeweerd/MetersToHA/blob/service_eau_veolia_fr/apps/meters_to_ha/meters_to_ha.py#L2319 sans l’appeler . De toute façon il y a aussi la fonction pour aller chercher les données sur le site.

@Anas92600 L’outil a une option « –skip-download » pour utiliser le fichier local sans téléchargement, et une option « –keep-output » ou « -k » pour garder le fichier après traitement. Donc idealement MetersToHA aurait la fonctionnalité pour enregistrer l’historique et cela pourrait se faire avec ces options. En plus, MetersToHA ne récupère qu’une petite historique alors que cela pourrait évoluer pour récupérer toute l’historique au tout début et plus tard depuis la dernière date connue.

Aussi: cela mériterait d’être refactorisé, mais l’essentiel c’est déjà que cela fonctionne.

Le code pour intégrer l’historique pourrait être plus générique dans une fonction à part et être appelé pour les divers types de mesures.

1 « J'aime »

J’vais tenter cette solution :sunglasses::+1:t4:

Je précise qu’actuellement le code pour appliquer l’historique n’est pas fonctionnelle dans MeterToHA.

je croyais qu’il fallait juste l’instance « au bon moment » chose pas évidente mais je l’ai fait juste après :
injector.update_veolia_device(veolia_idf_file)
j’espère qu’on pourra bientôt le faire :slight_smile:

Hello,

J’ai fait un PR sur le github pour ajouter la prise en compte de www.service.eau.veolia.fr et l’historique.
Si c’est approuvé il faudra tester avec IDF (Le formatage du fichier est légèrement différent)

Je suis toujours en phase de test, ca à l’air de fonctionner.
Je vais prochainement traiter les lignes « Estimés » pour éviter ces gaps 28 et 29 septembre

Avez vous un fichier IDF avec des lignes mesurés/estimés à partager pour tester ? J’aimerai voir 5/6 lignes consecutives avec du « Estimé » au milieu ? Je veux juste m’assurer que l’on a le même comportement.

1 « J'aime »

Hello, voici un exemple:
Date de relevé;Index relevé (litres);Consommation du jour (litres);Index Mesuré/Estimé
2019-10-01 18:03:39;584524;342;Mesuré
2019-10-02 18:00:32;584773;250;Mesuré
2019-10-03 18:03:25;584917;144;Mesuré
2019-10-04 18:03:43;585181;264;Estimé
2019-10-05 18:03:09;585497;316;Mesuré
2019-10-06 18:03:50;585884;387;Mesuré

Merci pour le relevé,

Les donnée pour la consommation du jour ne fonctionne pas exactement pareil entre IDF et service eau veolia

IDF
Date de relevé;Index relevé (litres);Consommation du jour (litres);Index Mesuré/Estimé
2019-10-01 18:03:39;584524;342;Mesuré
2019-10-02 18:00:32;584773;250;Mesuré
==> pour 2019-10-02 c’est bien 250 = l’index du jour - l’index hier (584773 - 584524)

service eau veolia
Date de relevé;Index relevé (litres);Consommation du jour (litres);Index Mesuré/Estimé
25/09/2023;32947;397;M
26/09/2023;33344;385;M
27/09/2023;33729;506;M
28/09/2023;34235;581;E
29/09/2023;34235;582;E
30/09/2023;35398;823;M
==> pour 26/09/2023 c’est 385 = l’index du jour suivant - l’index aujourd’hui (33729 - 33344)

Ca fonctionne pas pareil, le parseur doit être ajusté
Ca doit s’en doute dépendre à quel moment il prenne la mesure.