City heating (stadsverwarming) Kamstrup values into Energy Dashboard

Some places in the Netherlands have city heating (stadsverwarming). It’s a closed system that is hard to get values.

I wanted to get the values and from City heating and visualize the usage of heating in the amazing Home Assistant Energy Dashboard. The Energy dashboard can track your heating by gas. Unfortunately city heating is not measures with M3 gas but it’s measured measurement called GigaJoule (GJ).

I wrote (a bit lengthy) article that explains step by step how you can read out your city heating and get the values in the Energy Dashboard.

Make your city heating (stadsverwarming) smart and connect it Home Assistant energy dashboard -

Very happy with the final results, finally some insights in my heating consumption.
Stadsverwarming in Home Assistant

Hope it helps!


thanks @pbrink !
I’ll be sure to check this one out. It’s one of the biggest annoyances I still have left. Not being able to measure my heating solution.

Got it working on my side as well with a Landis Gyr LG2WR5. From what I see on the internet, it could work with LG UH50 (Ultra Heat) as well.

Used the following script as basis and running it inside appdaemon on my HA

Hi gents,

@pbrink very nice solution im also using your water measure solution.
I’ve read your blog and I was wondering if there would be a way to use ESPhome and maybe then use one ESP32 for both measurements .

Disclaimer: I can like prutsing with this stuff but I’m not really a wiz in the material.


Hi @330chauf,

I fully agree with your comment. I have moved most of my projects from RPI to ESP. I always have corrupt SD carts or other stability issues with RPIs in the long term.

It should be doable to port this solution, but it’s going to include a lot of tinkering and trial and error. I just thought that it was not worth the hassle.

Funny thing is that I’ve added a GJ meter reading. Since then I’ve not been able to add a m3 reading. I’ve added a GJ-to-m3 sensor, device_class: gas/state_class: total_increasing/unit_of_measurement: GJ, but also with UOM in M3, the latter not being able to be selected for the dashboard.
What I did notice is that my straight from the P1 reader measurement of GJ is in the dashboard but shown as kwh, but with a factor of 100 of the actual. So some additional research is needed.

@Sandmman I added the following to configuration.yaml

  - sensor:
      - name: "GJ to m³ gas"
        unit_of_measurement: "m³"
        device_class: gas
        state_class: total_increasing
        state: "{{ states('sensor.stadsverwarming_energy')|float(0) * 32 }}"

@frenck I would be sooooo delighted when heat (GJ) is available in the energy dashboard. District-heating is a common utility service here in NL and I do not have gas supplied to my home. The above solution does make the way city-heating is billed not more accurate or give more insight (which it isn’t anyway but that’s another discussion).


Small addition, I’ve switched from the HA Energy dash to a TimeScaleDB/Graphana option, I have as yet not deprecated the Energy DB itself as it is fun for a “quick and dirty”.
However, the calculation GJ to M3 is not really right. The conversion (in your use case 1:32) is low (for the dutch market, but maybe right where you’re from. In the Dutch market a value of about 35.5/35.8 would be better.
The following might be TL:DR (the see above)
Even though we as end-user are billed in GJ, the supplier calculates in M3 due to how the market is set up. The market pricing is in MWh (Mega Watt Hours), which is of course 1000 kWh, this to “facilitate” buying energy whether fossil or green origins.
Now we the consumer are billed in either m³ (Gas), kWh (electricity) or GJ (City-heating or Block-heating (which differ BTW!!)
So in order for us to get the right numbers we need some conversion. Now for MWh to kWh it’s easy (1:1000), GJ and m³ a bit more difficult, also because today’s conversion will be (slightly) different from any other day.
The conversion is done with the calorific factor, a representation of how much energy actual is in the gas.
This data can be gotten from GTS for instance.
There we find that 1m³ of gas relates to about 34 to 38 MJ. Once again MJ to GJ is easy (1000:1) for MJ to kWh its 1:0.2778. So GJ to kWH is 1:277.7778, but GJ to M3 always depends on the calorific value

Getting that just a little wrong can result in quite big delta’s (I know… I’ve had to fix this issue once at a Dutch utility where the calorific values hadn’t been updated for 6 months…averaged out to €50-250 per customer)

I also wanted to do this with ESPHome and have created the component for this. A pull request is pending on GitHub. Hopefully the guys at ESPHome can find some time to review and merge.

In the meantime you can import the kamstrup_mc40x component using the external_components option in your config file. An example and the documentation of the Kamstrup component can be found here.

Hope this helps.

Neat! What kind of sensor did you buy to make it work on an ESP?

I too have a Kamstrup meter for our city grid (Fjärrvärme). Got a wire connected to the meter by our provider, stating that is act’s just like the optical reader. Now looking for anyone that has an idea how to proceed with an esp with wired reading rather than optical reading.


Nice & neat solution. How did you get this connected. My Kamstrup is sealed with an official seal by Eneco and I’m not allowed to use the P1 port. They have remote transmitters connected to them nowadays to report directly back to Eneco as well.

Do let me know if you have a solution. Using a P1 port with ESP is better than the optical reader and some docker container. :stuck_out_tongue_winking_eye:

OK, so what I did is create a PCB with the optical interface. The details of the housing and the PCB can be found at my Github.

I did order a bunch of these PCBs (because the cost barely increased for higher number of PCBs :wink:). So I have around 25 spare ones. They contain all the transistors, but do need the photo diode, IR LED and ESP board still. If you are happy to order and solder those yourself, I can send one PCB over or you can pick one up (Dordrecht area). Details on the required components are listed at the above mentioned Github.

A wire connection would be ideal of course, but here in NL the provider (Eneco) already uses that connection for their remote metering system. Also Eneco is not helpful at all when it comes to these kind of things.
The P1 port on the Eneco remote transmission box is an input as far as I understand from them. So you cannot use it with a P1 reader.

The optical connection is basically an RS485 connection. So I can imagine using the wires would be similar to the optical interface protocol wise. If this is indeed the case, the ESP integration I created will also work with the wire interface, however, you will need some electronics to wire it up to the ESP.

There are different add-on boards for Kamstrup meters that use two wires; ModBus, Mbus, S0-pulse, BacNet etc etc. You can’t tell from the outside which interface is installed… Give them a call and find out first.

I have two Kamstrup meters, model M403, owned by Eneco and model M303, owned by me. I used to read the M403 via optical interface too. Very successfully too. However, when I acquired the M303, the optical interface does not keep the meter awake. It sleeps after a few minutes and only wakes up after physically pressing the button on the front (also confirmed by Kamstrup Customer Service).
So I pieced together a different approach to reading these meters from tinkerers at using the M-Bus that both meters have. I bought an Mbus-USB interface at AliExpress (€32 + shipping) and within a few hours of its arrival I had my setup up and running.
It employs:

  • A separate raspberry pi 3B which I had still lying around (I did not want to mess up my HA pi during testing this new approach)
  • NodeRed installed on the separate pi, auto starting when it boots, headless
  • The module “node-red-contrib-m-bus” installed via the Palette manager
  • An imported NodeRed flow from here
  • I used the primary addresses, 1 and 89, of the two meters (that are both connected to the same MBus-USB), on the same two wires; it takes a while until the scan is finished, but then boom it reads data from both meters.
  • The M303 and M403 both employ slightly different data formats, so these needed to be sorted out, which is not too difficult if you have some experience with NodeRed.
  • I send the tweaked dataset via MQTT to Home Assistant, where NodeRed sorts out the data and sends them to the Home Assistant entities that I have defined for them.
  • Since I had something running for the M403, it took careful migration not to mess up the historic data from the previous approach
  • When the setup works, you can run the two wires directly to the pi that runs Home Assistant, up to a few hundred meters of cable. Then the whole setup becomes even easier, because most tinkerers will have NodeRed already running and you only need to sort out fixed USB port naming of you have one or more USB ports already in use.
  • Advantage of this approach: you can do multiple heat meters on a single MBus_USB, I believe up to 10, before you need to add a separate powersupply; plus it takes very little energy to send a telegram via Mbus, less then the IR head approach. So the battery life will not be affected, also allowing to increase the output frequency (I read both meters every five minutes, but every two minutes is feasible too). And finally, there is no fiddling with the IR head, which is finicky to position exactly on the right spot, with paper filter to reduce glare etc.
    Drop me a note if you would like to find out more about this simplified approach.
    All the credit goes to the folks who published their findings on It is in dutch!!!

Fact that the meter goes to sleep is a displacement of the magnets when the optical head is placed on the meter. Consult the manual for this to confirm, not sure if this applies to your M303 meter but it does matter for the M403 so I suppose it does. There is a reed-relay build in the meter to preserve battery usage. The IR-circuit is disabled when contact is open.

Can anyone help with my setup?
I am unable to get the reading from kamstrup multical 401. I bought the optical reader from AliExpress.

Same problem no sensor readout

@sjofel @mohit0749 have you allready tried turning the sensor 180 so that the wire is at the top?

Yes, makes no difference for me. Also removed the pcb from te enclosure for testing.