Rechercher sur ce site...

Catégorie : Non classé

Suivre les données télé-info de EDF dans Grafana

Hello,

Je vous propose de suivre votre consommation grâce aux données télé-info d'EDF recueilli. Je ne vais pas vous expliquer comment récupérer les données, mais plutôt vous aidez à les afficher dans Grafana dont voici un aperçu.

 

 

Prérequis :

  • La récupération des données fonctionne, voir tuto http://www.magdiblog.fr/gpio/teleinfo-edf-suivi-conso-de-votre-compteur-electrique/
  • Avoir monté une solution de supervision Grafana/Prometheus.

C'est partie pour l'intégration :

Installer le package xinetd qui va permettre d'afficher la page web :

apt update
apt install xinetd

On place le fichier de conf xinetd dans le repertoire /etc/xinetd.d/

cd /etc/xinetd.d/
curl -k -O https://raw.githubusercontent.com/jbsky/jbsky/master/script/edf/etc/edf

Le fichier de config xinetd téléchargé :

service edf-expose-metric
{
  type = unlisted
  port = 10111
  socket_type = stream
  wait = no
  user = root
  server = /usr/local/bin/httpwrapper
  server_args = /usr/local/bin/edf-expose-metric
  disable = no
  only_from = 0.0.0.0
  log_type = FILE /dev/null
  protocol = TCP
}

Ensuite, on place les 3 scripts suivants dans le répertoire /usr/local/bin/

cd /usr/local/bin/
curl -k -O https://raw.githubusercontent.com/jbsky/jbsky/master/script/edf/bin/edf-teleinfo
curl -k -O https://raw.githubusercontent.com/jbsky/jbsky/master/script/edf/bin/edf-expose-metric
curl -k -O https://raw.githubusercontent.com/jbsky/jbsky/master/script/edf/bin/httpwrapper
chmod +x /usr/local/bin/{httpwrapper,edf-teleinfo,edf-expose-metric}

Le 1er qui est lancé par /etc/init.d/edf est en écoute sur le dev, ici à configurer par le votre, alimente au fur et à mesure que des infos sont lues dans un fichier /tmp.

#!/bin/bash
TMPFILE=/tmp/edf
DEV=/dev/ttyUSB0
stty -F ${DEV} 1200 sane evenp parenb cs7 -crtscts

cat > ${TMPFILE} <<EOF
HCHP
HCHC
MOTDETAT
ISOUSC
OPTARIF
ADCO
PAPP
HHPHC
PTEC
IINST
IMAX
EOF
function readdev(){
while read TYPE VALUE CHECKSUM;do

	case "$TYPE" in

HCHP)sed -i  "s/HCHP.*/HCHP=$VALUE/g" ${TMPFILE} ;;
HCHC)sed -i  "s/HCHC.*/HCHC=$VALUE/g" ${TMPFILE} ;;
MOTDETAT)sed -i  "s/MOTDETAT.*/MOTDETAT=$VALUE/g" ${TMPFILE} ;;
ISOUSC)sed -i  "s/ISOUSC.*/ISOUSC=$VALUE/g" ${TMPFILE} ;;
OPTARIF)sed -i  "s/OPTARIF.*/OPTARIF=$VALUE/g" ${TMPFILE} ;;
ADCO)sed -i  "s/ADCO.*/ADCO=$VALUE/g" ${TMPFILE} ;;
PAPP)sed -i  "s/PAPP.*/PAPP=$VALUE/g" ${TMPFILE} ;;
HHPHC)sed -i  "s/HHPHC.*/HHPHC=$VALUE/g" ${TMPFILE} ;;
PTEC)sed -i  "s/PTEC.*/PTEC=$VALUE/g" ${TMPFILE} ;;
IINST)sed -i  "s/IINST.*/IINST=$VALUE/g" ${TMPFILE} ;;
IMAX)sed -i  "s/IMAX.*/IMAX=$VALUE/g" ${TMPFILE} ;;
	esac

done < ${DEV}
}
readdev

Le 2e script va afficher les métriques, si vous avez lancé le 1er script, celui-ci devrait afficher les données recueillies.

#!/bin/bash
# printMetric name description type value
function printMetric {
    echo "# HELP $1 $2"
    echo "# TYPE $1 $3"
    echo "$1 $4"
}
. /tmp/edf

printMetric "Heures_pleines" "HCHP" "COUNTER" "$HCHP"
printMetric "Heures_creuses" "HCHC" "COUNTER" "$HCHC"
printMetric "Mot_d_etat" "MOTDETAT" "GAUGE" "$MOTDETAT"
printMetric "Intensite_souscrite_I" "ISOUSC" "GAUGE" "$ISOUSC"
#printMetric "Option_tarifaire" "OPTARIF" "GAUGE" "$OPTARIF"
printMetric "Identifiant_du_compteur" "ADCO" "GAUGE" "$ADCO"

printMetric "Puissance_apparente_VA" "PPAP" "GAUGE" "$PAPP"
#printMetric "Groupe_horaire_si_option" "HHPHC" "GAUGE" "$HHPHC"
#printMetric "Periode_tarifaire_en_cours" "PTEC" "GAUGE" "$PTEC"

if [[ "${PTEC}" == "HP.." ]];then
	printMetric "Periode_tarifaire_en_cours_HP" "PTEC" "GAUGE" "1"
	printMetric "Periode_tarifaire_en_cours_HC" "PTEC" "GAUGE" "0"
else
	printMetric "Periode_tarifaire_en_cours_HP" "PTEC" "GAUGE" "0"
	printMetric "Periode_tarifaire_en_cours_HC" "PTEC" "GAUGE" "1"
fi
printMetric "Intensite_instantanee_A" "IINST" "GAUGE" "$IINST"
printMetric "Intensite_maximale_A" "IMAX" "GAUGE" "$IMAX"

HCHP=005594895
HCHC=005702480
MOTDETAT=000000
ISOUSC=30
OPTARIF=HC..
ADCO=000000000000
PAPP=00460
HHPHC=C
PTEC=HP..
IINST=002
IMAX=034

Le dernier est le httpwrapper, en gros, ça va rajouter un header afin que n'importe quel navigateur considère les données du 2e script comme une page web.

#!/bin/bash
# small http wrapper for bash scripts via xinetd

ulimit -n 20480
ulimit -l 512

#root='/opt/metrics.d/'
file="$1"
mime='text/plain'

#cd $root

if [ -f "$file" ]; then
  #$root
  $file > /tmp/.$$.output

  size=$(stat -c "%s" "/tmp/.$$.output")

  printf 'HTTP/1.1 200 OK\r\nDate: %s\r\nContent-Length: %s\r\nContent-Type: %s\r\nConnection: close\r\n\r\n' "$(date)" "$size" "$mime"

  cat /tmp/.$$.output

  sleep 1
  rm -f /tmp/.$$.output
  exit 0
fi

exit 1

Pour la partie lancement de service de la collecte des infos dans le fichier tmp, il faut encore un script à placer dans /etc/init.d/

Malheureusement, même si j'ai un fichier systemd dans le dépot, je n'ai pas réussit à démarrer le service sans qu'il me ramène un code erreur à 2, si quelqu'un à la solution, je suis preneur, bien entendu.

cd /etc/init.d/
curl -k -O https://raw.githubusercontent.com/jbsky/jbsky/master/script/edf/init.d/edf-teleinfo
chmod +x /etc/init.d/edf-teleinfo
#! /bin/sh
### BEGIN INIT INFO
# Provides:          skeleton
# Required-Start:    $remote_fs $syslog
# Required-Stop:     $remote_fs $syslog
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: Example initscript
# Description:       This file should be used to construct scripts to be
#                    placed in /etc/init.d.
### END INIT INFO

# Author: Foo Bar <foobar@baz.org>
#
# Please remove the "Author" lines above and replace them
# with your own name if you copy and modify this script.

# Do NOT "set -e"

# PATH should only include /usr/* if it runs after the mountnfs.sh script
PATH=/sbin:/usr/sbin:/bin:/usr/bin
DESC="Teleinfo edf capture"
NAME=edf-teleinfo
DAEMON=/usr/local/bin/$NAME
DAEMON_ARGS=""
PIDFILE=/var/run/$NAME.pid
SCRIPTNAME=/etc/init.d/$NAME

# Exit if the package is not installed
[ -x "$DAEMON" ] || exit 0

# Read configuration variable file if it is present
[ -r /etc/default/$NAME ] && . /etc/default/$NAME

# Load the VERBOSE setting and other rcS variables
. /lib/init/vars.sh

# Define LSB log_* functions.
# Depend on lsb-base (>= 3.2-14) to ensure that this file is present
# and status_of_proc is working.
. /lib/lsb/init-functions

#
# Function that starts the daemon/service
#
do_start()
{
        # Return
        #   0 if daemon has been started
        #   1 if daemon was already running
        #   2 if daemon could not be started
        start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON --test > /dev/null \
                || return 1
        start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON -- \
                $DAEMON_ARGS \
                || return 2
        # Add code here, if necessary, that waits for the process to be ready
        # to handle requests from services started subsequently which depend
                # on this one.  As a last resort, sleep for some time.
}

#
# Function that stops the daemon/service
#
do_stop()
{
        # Return
        #   0 if daemon has been stopped
        #   1 if daemon was already stopped
        #   2 if daemon could not be stopped
        #   other if a failure occurred
        start-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 --pidfile $PIDFILE --name $NAME
        RETVAL="$?"
        [ "$RETVAL" = 2 ] && return 2
        # Wait for children to finish too if this is a daemon that forks
        # and if the daemon is only ever run from this initscript.
        # If the above conditions are not satisfied then add some other code
        # that waits for the process to drop all resources that could be
        # needed by services started subsequently.  A last resort is to
        # sleep for some time.
        start-stop-daemon --stop --quiet --oknodo --retry=0/30/KILL/5 --exec $DAEMON
        [ "$?" = 2 ] && return 2
        # Many daemons don't delete their pidfiles when they exit.
        rm -f $PIDFILE
        return "$RETVAL"
}

#
# Function that sends a SIGHUP to the daemon/service
#
do_reload() {
        #
        # If the daemon can reload its configuration without
        # restarting (for example, when it is sent a SIGHUP),
        # then implement that here.
        #
        start-stop-daemon --stop --signal 1 --quiet --pidfile $PIDFILE --name $NAME
        return 0
}

case "$1" in
  start)
        [ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC" "$NAME"
        do_start
        case "$?" in
                0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
                2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
        esac
        ;;
  stop)
        [ "$VERBOSE" != no ] && log_daemon_msg "Stopping $DESC" "$NAME"
        do_stop
        case "$?" in
                0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
                2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
        esac
        ;;
  status)
       status_of_proc "$DAEMON" "$NAME" && exit 0 || exit $?
       ;;
  #reload|force-reload)
        #
        # If do_reload() is not implemented then leave this commented out
        # and leave 'force-reload' as an alias for 'restart'.
        #
        #log_daemon_msg "Reloading $DESC" "$NAME"
        #do_reload
        #log_end_msg $?
        #;;
  restart|force-reload)
        #
        # If the "reload" option is implemented then remove the
        # 'force-reload' alias
        #
        log_daemon_msg "Restarting $DESC" "$NAME"
        do_stop
        case "$?" in
          0|1)
                do_start
                case "$?" in
                        0) log_end_msg 0 ;;
                        1) log_end_msg 1 ;; # Old process is still running
                        *) log_end_msg 1 ;; # Failed to start
                esac
                ;;
          *)
                # Failed to stop
                log_end_msg 1
                ;;
        esac
        ;;
  *)
        echo "Usage: $SCRIPTNAME {start|stop|status|restart|force-reload}" >&2
        exit 3
        ;;
esac

Reste à démarrer l'histoire!

systemctl restart xinetd
systemctl enable edf-teleinfo
systemctl start edf-teleinfo

Logiquement, le port 10111 doit être en écoute :

lsof -i -n -P |grep 10111

doit ramener une ligne.

=> http://192.168.X.Y:10111

Attention, un test avec le navigateur est aussi nécessaire.

Si vos données s'affiche, y a plus qu'à configurer dans Prometheus, pas de difficulté apparente, ajouter ce qui suit dans le fichier prometheus.yml.

 - job_name: 'edf'
static_configs:
- targets: ['192.168.X.Y:10111']

Étape finale, le board grafana est disponible à l'URL suivante :

https://grafana.com/grafana/dashboards/11675

Sources :

Exporting Prometheus Metrics with Bash Scripts

Note sur git

Supprimer un fichier de l'historique :

 git filter-branch --index-filter 'git rm --cached --ignore-unmatch install ${FICHIER}' -f

Changer l'historique des commits

 git rebase -i HEAD~15
  • on tombe sur un menu avec une liste du plus ancien au plus nouveau commit, par exemple 15, remonte jusqu'à 15 commit. Il est possible de changer l'ordre, de fusionner (squash) des commits.
# p, pick = use commit
# r, reword = use commit, but edit the commit message
# e, edit = use commit, but stop for amending
# s, squash = use commit, but meld into previous commit
# f, fixup = like "squash", but discard this commit's log message
# x, exec = run command (the rest of the line) using shell
# d, drop = remove commit
  • Enfin, on push :
git push origin +master
Page suivante »