syberalexis / linky-exporter

Prometheus exporter to French Eletrical Remote Information (TeleInfo Linky)
https://grafana.com/grafana/dashboards/17649-fr-linky-exporter/
Apache License 2.0
25 stars 7 forks source link

Add support to standard TIC output #7

Closed hugocollignon closed 1 year ago

hugocollignon commented 3 years ago

Hello

First, thanks to you for this project!

I added a support to the standard mode of the TIC, you could be interested : https://github.com/hugocollignon/linky-exporter. I didn't create a pull request because code is not perfectly finalised (have to see how to integrate both modes).

syberalexis commented 2 years ago

Hello,

I will update the code in a few days with your standard mode proposition.

diminou91 commented 2 years ago

Hello,

First, thank you for the work you've put in :)

Tried to compile @hugocollignon's code (on arm64; my pi3b) but I can't launch the executable afterward. Then I tried to do the same with @syberalexis's code from this repo and I got the same issue. (I obviously changed the GOARCH for arm64).

Any idea of how to try this on my pi ? (or if I just have to wait a few days for your own release, I don't mind :) )

Thanks!

hugocollignon commented 2 years ago

Hello

I had to rebuild my (mostly syberalexis's one) code few weeks ago and I didn't encounter any issue.

What was your problem? I check my launch command on my side.

hugocollignon commented 2 years ago

To begin, are you able to read your serial bus (without this executable, with minicom for example)?

My launch options: ./linky-exporter --baud 9600 --device /dev/ttyAMA0 --parity ParityEven

/boot/config.txt on the Pi (last lines): enable_uart=1 dtoverlay=disable-bt

diminou91 commented 2 years ago

To begin, are you able to read your serial bus (without this executable, with minicom for example)?

My launch options: ./linky-exporter --baud 9600 --device /dev/ttyAMA0 --parity ParityEven

/boot/config.txt on the Pi (last lines): enable_uart=1 dtoverlay=disable-bt

I'm using https://www.tindie.com/products/hallard/micro-teleinfo-v20/ so it's USB and not AMA, and a lightweight Ubuntu Server as an OS so I don't have to modify config.txt (as far as I understand it).

Yes, I am able to read my bus using picocom (picocom -b 9600 -d 7 -p e -f n /dev/ttyUSB0). I asked Enedis to switch from Historical to Standard without realizing this tool did not support it (yet!).

Hello

I had to rebuild my (mostly syberalexis's one) code few weeks ago and I didn't encounter any issue.

What was your problem? I check my launch command on my side.

Just built it again (from your repo) and it is currently working! No idea what happened last night. Could not get it to launch at all! Anyway, thanks for your time :)

PS: Is the pricing (HP/HC) automagically detected ?

EDIT : All linky related metrics are at 0 :(

hugocollignon commented 2 years ago

I'm using https://www.tindie.com/products/hallard/micro-teleinfo-v20/ so it's USB and not AMA, and a lightweight Ubuntu Server as an OS so I don't have to modify config.txt (as far as I understand it).

Ok you right.

Yes, I am able to read my bus using picocom (picocom -b 9600 -d 7 -p e -f n /dev/ttyUSB0). I asked Enedis to switch from Historical to Standard without realizing this tool did not support it (yet!).

On your Linky, has the mode been changed? -> Ok I got my answer.

it is currently working

Well nice!

PS: Is the pricing (HP/HC) automagically detected ?

In fact no, the exporter is really less smart. It takes each line of the linky and expose each one "as is". Exporter are supposed to be as simple as possible, then you should create your smart requests on Prometheus.

See https://github.com/hugocollignon/linky-exporter/blob/master/pkg/collectors/linky-standard-collector.go#L165 to L201 to see which Linky TIC line goes to which metric, and related to counters, L166 to L185.

I suppose you use a Grafana at the end, you can query each counters.

EDIT : All linky related metrics are at 0 :(

Is it on your Prom/Grafana or directly on the exporter (http://host:9901/metrics by default)?

diminou91 commented 2 years ago

PS: Is the pricing (HP/HC) automagically detected ?

In fact no, the exporter is really less smart. It takes each line of the linky and expose each one "as is". Exporter are supposed to be as simple as possible, then you should create your smart requests on Prometheus.

See https://github.com/hugocollignon/linky-exporter/blob/master/pkg/collectors/linky-standard-collector.go#L165 to L201 to see which Linky TIC line goes to which metric, and related to counters, L166 to L185.

I suppose you use a Grafana at the end, you can query each counters.

Great, thanks!

EDIT : All linky related metrics are at 0 :(

Is it on your Prom/Grafana or directly on the exporter (http://host:9901/metrics by default)?

Both :

HELP linky_index_watthours_total Index en Wh

TYPE linky_index_watthours_total counter

linky_index_watthours_total{index="eait",prm=""} 0 linky_index_watthours_total{index="easd01",prm=""} 0 linky_index_watthours_total{index="easd02",prm=""} 0 linky_index_watthours_total{index="easd03",prm=""} 0 linky_index_watthours_total{index="easd04",prm=""} 0 linky_index_watthours_total{index="easf01",prm=""} 0 linky_index_watthours_total{index="easf02",prm=""} 0 linky_index_watthours_total{index="easf03",prm=""} 0 linky_index_watthours_total{index="easf04",prm=""} 0 linky_index_watthours_total{index="easf05",prm=""} 0 linky_index_watthours_total{index="easf06",prm=""} 0 linky_index_watthours_total{index="easf07",prm=""} 0 linky_index_watthours_total{index="easf08",prm=""} 0 linky_index_watthours_total{index="easf09",prm=""} 0 linky_index_watthours_total{index="easf10",prm=""} 0 linky_index_watthours_total{index="east",prm=""} 0 linky_index_watthours_total{index="erq1",prm=""} 0 linky_index_watthours_total{index="erq2",prm=""} 0

graflinky0

hugocollignon commented 2 years ago

Before trying to see anything on Prom/Grafana, you will save time by refreshing directly the exporter. :)

So, do you have any logs on your host (where the exporter is running)? What if you launch it not daemonized?

Yes, I am able to read my bus using picocom (picocom -b 9600 -d 7 -p e -f n /dev/ttyUSB0)

Ok so the physical layer should be good. Have you closed all your serial connections with the same device before launching the exporter?

When you launched the exporter, is it with same options as me (--baud 9600 --device /dev/ttyAMA0 --parity ParityEven)? (Found in an interesting Enedis documentation https://www.enedis.fr/media/2035/download §5.3.5)

diminou91 commented 2 years ago

Before trying to see anything on Prom/Grafana, you will save time by refreshing directly the exporter. :)

I know, I was already on it as soon as I saw that /metrics was actually populated :D

So, do you have any logs on your host (where the exporter is running)? What if you launch it not daemonized?

It is not daemonized yet, and beside the "INFO[0000] Beginning to serve on port :9901" there is no log.

Yes, I am able to read my bus using picocom (picocom -b 9600 -d 7 -p e -f n /dev/ttyUSB0)

Ok so the physical layer should be good. Have you closed all your serial connections with the same device before launching the exporter?

Yup!

When you launched the exporter, is it with same options as me (--baud 9600 --device /dev/ttyAMA0 --parity ParityEven)? (Found in an interesting Enedis documentation)

I'm curious about that documentation, because from my understanding the parity is by default at Even on the code, yet it is working when manually adding it as an option... Working now, thank you for your help :)

hugocollignon commented 2 years ago

By default it is none: https://github.com/hugocollignon/linky-exporter/blob/master/cmd/linky-exporter/main.go#L21

But you right, after a manual merge of syberalexis's code and mine, we should add a toggle to select Historical vs Standard mode, then adapt all the serial parameters (except the device /dev/something) accordingly. Even better, try one mode first, with serial parameters of one and if we are not able to read something, try the other one.

I think we both lack of time to do better for now, this is why I did the fix with a simple .disabled of the historical mode.

If someone is interested to improve that.. ;D

diminou91 commented 2 years ago

By default it is none: https://github.com/hugocollignon/linky-exporter/blob/master/cmd/linky-exporter/main.go#L21

But you right, after a manual merge of syberalexis's code and mine, we should add a toggle to select Historical vs Standard mode, then adapt all the serial parameters (except the device /dev/something) accordingly. Even better, try one mode first, with serial parameters of one and if we are not able to read something, try the other one.

I think we both lack of time to do better for now, this is why I did the fix with a simple .disabled of the historical mode.

If someone is interested to improve that.. ;D

Ha, I see! Thank you for your help, I'll now try to set up a dashboard even though metrology is not my forte :D Once merged if I can find time I'll see if I can improve the project a bit :)

hugocollignon commented 2 years ago

What we use, same it could be improved.

{
  "annotations": {
    "list": [
      {
        "builtIn": 1,
        "datasource": {
          "type": "grafana",
          "uid": "-- Grafana --"
        },
        "enable": true,
        "hide": true,
        "iconColor": "rgba(0, 211, 255, 1)",
        "name": "Annotations & Alerts",
        "target": {
          "limit": 100,
          "matchAny": false,
          "tags": [],
          "type": "dashboard"
        },
        "type": "dashboard"
      }
    ]
  },
  "editable": true,
  "fiscalYearStartMonth": 0,
  "graphTooltip": 0,
  "id": 19,
  "links": [],
  "liveNow": false,
  "panels": [
    {
      "datasource": {
        "type": "prometheus",
        "uid": "something"
      },
      "fieldConfig": {
        "defaults": {
          "color": {
            "mode": "palette-classic"
          },
          "custom": {
            "axisLabel": "",
            "axisPlacement": "auto",
            "barAlignment": 0,
            "drawStyle": "line",
            "fillOpacity": 0,
            "gradientMode": "none",
            "hideFrom": {
              "legend": false,
              "tooltip": false,
              "viz": false
            },
            "lineInterpolation": "smooth",
            "lineWidth": 1,
            "pointSize": 5,
            "scaleDistribution": {
              "type": "linear"
            },
            "showPoints": "never",
            "spanNulls": true,
            "stacking": {
              "group": "A",
              "mode": "none"
            },
            "thresholdsStyle": {
              "mode": "off"
            }
          },
          "mappings": [],
          "thresholds": {
            "mode": "absolute",
            "steps": [
              {
                "color": "green",
                "value": null
              },
              {
                "color": "red",
                "value": 80
              }
            ]
          },
          "unit": "volt"
        },
        "overrides": []
      },
      "gridPos": {
        "h": 8,
        "w": 12,
        "x": 0,
        "y": 0
      },
      "id": 12,
      "options": {
        "legend": {
          "calcs": [],
          "displayMode": "hidden",
          "placement": "bottom"
        },
        "tooltip": {
          "mode": "single",
          "sort": "none"
        }
      },
      "targets": [
        {
          "datasource": {
            "type": "prometheus",
            "uid": "something"
          },
          "expr": "linky_voltage_volts{phase=\"1\",prm=\"prm_number\"}",
          "refId": "A"
        }
      ],
      "title": "Tension efficace",
      "type": "timeseries"
    },
    {
      "datasource": {
        "type": "prometheus",
        "uid": "something"
      },
      "fieldConfig": {
        "defaults": {
          "color": {
            "mode": "palette-classic"
          },
          "custom": {
            "axisLabel": "",
            "axisPlacement": "auto",
            "barAlignment": 0,
            "drawStyle": "line",
            "fillOpacity": 0,
            "gradientMode": "none",
            "hideFrom": {
              "legend": false,
              "tooltip": false,
              "viz": false
            },
            "lineInterpolation": "smooth",
            "lineWidth": 1,
            "pointSize": 5,
            "scaleDistribution": {
              "type": "linear"
            },
            "showPoints": "never",
            "spanNulls": true,
            "stacking": {
              "group": "A",
              "mode": "none"
            },
            "thresholdsStyle": {
              "mode": "off"
            }
          },
          "mappings": [],
          "min": 0,
          "thresholds": {
            "mode": "absolute",
            "steps": [
              {
                "color": "green",
                "value": null
              }
            ]
          },
          "unit": "amp"
        },
        "overrides": []
      },
      "gridPos": {
        "h": 8,
        "w": 12,
        "x": 12,
        "y": 0
      },
      "id": 2,
      "options": {
        "legend": {
          "calcs": [],
          "displayMode": "hidden",
          "placement": "bottom"
        },
        "tooltip": {
          "mode": "single",
          "sort": "none"
        }
      },
      "targets": [
        {
          "datasource": {
            "type": "prometheus",
            "uid": "something"
          },
          "expr": "linky_current_amperes{phase=\"1\",prm=\"prm_number\"}",
          "refId": "A"
        }
      ],
      "title": "Courant efficace",
      "type": "timeseries"
    },
    {
      "datasource": {
        "type": "prometheus",
        "uid": "something"
      },
      "description": "",
      "fieldConfig": {
        "defaults": {
          "color": {
            "mode": "palette-classic"
          },
          "custom": {
            "axisLabel": "",
            "axisPlacement": "auto",
            "barAlignment": 0,
            "drawStyle": "line",
            "fillOpacity": 0,
            "gradientMode": "none",
            "hideFrom": {
              "legend": false,
              "tooltip": false,
              "viz": false
            },
            "lineInterpolation": "smooth",
            "lineWidth": 1,
            "pointSize": 5,
            "scaleDistribution": {
              "type": "linear"
            },
            "showPoints": "never",
            "spanNulls": true,
            "stacking": {
              "group": "A",
              "mode": "none"
            },
            "thresholdsStyle": {
              "mode": "line"
            }
          },
          "mappings": [],
          "min": 0,
          "thresholds": {
            "mode": "absolute",
            "steps": [
              {
                "color": "green",
                "value": null
              },
              {
                "color": "orange",
                "value": 7200
              },
              {
                "color": "red",
                "value": 8100
              }
            ]
          },
          "unit": "voltamp"
        },
        "overrides": []
      },
      "gridPos": {
        "h": 8,
        "w": 12,
        "x": 0,
        "y": 8
      },
      "id": 10,
      "options": {
        "legend": {
          "calcs": [],
          "displayMode": "hidden",
          "placement": "bottom"
        },
        "tooltip": {
          "mode": "single",
          "sort": "none"
        }
      },
      "targets": [
        {
          "datasource": {
            "type": "prometheus",
            "uid": "something"
          },
          "expr": "linky_power_voltamperes{direction=\"drawn\",phase=\"sum\",prm=\"prm_number\"}",
          "refId": "A"
        }
      ],
      "title": "Puissance apparente",
      "type": "timeseries"
    },
    {
      "datasource": {
        "type": "prometheus",
        "uid": "something"
      },
      "fieldConfig": {
        "defaults": {
          "color": {
            "mode": "thresholds"
          },
          "custom": {
            "align": "auto",
            "displayMode": "auto",
            "inspect": false
          },
          "mappings": [],
          "thresholds": {
            "mode": "absolute",
            "steps": [
              {
                "color": "green",
                "value": null
              },
              {
                "color": "red",
                "value": 80
              }
            ]
          }
        },
        "overrides": []
      },
      "gridPos": {
        "h": 8,
        "w": 12,
        "x": 12,
        "y": 8
      },
      "id": 6,
      "options": {
        "footer": {
          "fields": "",
          "reducer": [
            "sum"
          ],
          "show": false
        },
        "showHeader": true
      },
      "pluginVersion": "8.5.0",
      "targets": [
        {
          "datasource": {
            "type": "prometheus",
            "uid": "something"
          },
          "editorMode": "code",
          "exemplar": false,
          "expr": "linky_info{prm=\"prm_number\"}",
          "format": "table",
          "instant": false,
          "range": true,
          "refId": "A"
        }
      ],
      "title": "Infos",
      "type": "table"
    },
    {
      "datasource": {
        "type": "prometheus",
        "uid": "something"
      },
      "description": "",
      "fieldConfig": {
        "defaults": {
          "color": {
            "mode": "thresholds"
          },
          "decimals": 6,
          "mappings": [],
          "thresholds": {
            "mode": "absolute",
            "steps": [
              {
                "color": "green",
                "value": null
              }
            ]
          },
          "unit": "watth"
        },
        "overrides": []
      },
      "gridPos": {
        "h": 8,
        "w": 12,
        "x": 0,
        "y": 16
      },
      "id": 4,
      "options": {
        "colorMode": "value",
        "graphMode": "none",
        "justifyMode": "auto",
        "orientation": "auto",
        "reduceOptions": {
          "calcs": [
            "lastNotNull"
          ],
          "fields": "",
          "values": false
        },
        "textMode": "auto"
      },
      "pluginVersion": "8.5.0",
      "targets": [
        {
          "datasource": {
            "type": "prometheus",
            "uid": "something"
          },
          "expr": "linky_index_watthours_total{index=\"east\",prm=\"prm_number\"}",
          "refId": "A"
        }
      ],
      "title": "Energie consommée",
      "type": "stat"
    },
    {
      "datasource": {
        "type": "prometheus",
        "uid": "something"
      },
      "description": "",
      "fieldConfig": {
        "defaults": {
          "color": {
            "mode": "thresholds"
          },
          "decimals": 6,
          "mappings": [],
          "thresholds": {
            "mode": "absolute",
            "steps": [
              {
                "color": "green",
                "value": null
              }
            ]
          },
          "unit": "watt"
        },
        "overrides": []
      },
      "gridPos": {
        "h": 8,
        "w": 12,
        "x": 12,
        "y": 16
      },
      "id": 14,
      "options": {
        "colorMode": "value",
        "graphMode": "none",
        "justifyMode": "auto",
        "orientation": "auto",
        "reduceOptions": {
          "calcs": [
            "lastNotNull"
          ],
          "fields": "",
          "values": false
        },
        "textMode": "auto"
      },
      "pluginVersion": "8.5.0",
      "targets": [
        {
          "datasource": {
            "type": "prometheus",
            "uid": "something"
          },
          "expr": "linky_power_voltamperes{direction=\"drawn\",phase=\"sum\",prm=\"prm_number\"}",
          "refId": "A"
        }
      ],
      "title": "Conso instantanée",
      "type": "stat"
    }
  ],
  "refresh": "5s",
  "schemaVersion": 36,
  "style": "dark",
  "tags": [],
  "templating": {
    "list": []
  },
  "time": {
    "from": "now-1h",
    "to": "now"
  },
  "timepicker": {},
  "timezone": "",
  "title": "Linky",
  "uid": "B7tba9M4k",
  "version": 5,
  "weekStart": ""
}
syberalexis commented 2 years ago

Hello guys,

Thank you to use this project and be active to help each other and to improve it :)

I am working now on a new version that will support all modes of linky (two at now ^^), add new feature like auto detect, support more os and rework exposed metrics to normalized them between the modes :)

In bonus : a better documentation, with more explanation and details, links to the hardware documentation, grafana dashboards and if I have more time, an integration with the project Home Assistant :)

I hope to finish the new version the next week, if life don’t eat my time 😅

hugocollignon commented 2 years ago

Such a good news!

Regarding "rework exposed metrics to normalized them between the modes", available to help if needed, since this is the part on which I worked for the standard mode.

syberalexis commented 1 year ago

Hello,

The new released version of Linky exporter is ready : https://github.com/syberalexis/linky-exporter/releases/tag/v3.0.0 ;)

A dashboard is available with id 17649. The link https://grafana.com/grafana/dashboards/17649-fr-linky-exporter/ is buggy. I opened a ticket in GrafanaLabs.

Have a nice day. Best regards,