More about the Remeha protocol

This evening i spent some time on trying to figure out the meaning of all the bytes that make up the response. I already knew where to locate the information inside a packet by a brief analysis of the packets a few days ago, but to make things a bit more stable, I knew I had to dig a bit deeper to find out as much as possible. Cause the more you know, the more checks you can build into the software which results in less chance that invalid packets slip through that could possibly crash the system.

When I started analyzing the responses from the boiler, I started with the Sample command. Here’s an example:


I already found out that the part marked in blue contains the payload e.g. the ‘interesting stuff’ some days ago, so let’s focus on the remaining bytes:

0201FE06480201 and 2C4303

The 02 at the beginning and 03 at the end are common values for start- and end bytes, so let’s assume this is the case here also, so now the unknown bytes left are:

01FE06480201 and 2C43

The size (2 bytes) and the position inside the packet (at the end) made me think that the 2C43 could very well be a checksum, and it is: it’s the CRC16 (Modbus variant) of the complete packet without the start- and end byte (and of course the checksum value itself); so based on the packet above the bytes of which the CRC is calculated are:


The Modbus variant of CRC16 calculation differs from a “standard” CRC16 calculation in that the initial value isn’t 0 (zero), but $FFFF. Being able to validate the checksum is very valuable and adds a lot to the robustness of this interface.

So now all that’s left are these leading bytes:


To understand the 01FE part, I looked at some outgoing packets, these look like this:


Again, after removing the start- and stop byte and the checksum we see this:


Compare thisΒ  with what is still unknown from the response:

Incoming: 01FE06480201
Outgoing: FE0105080201

The first two bytes seem to be the addresses of the source and destination device; this is not that strange as it seems; although this is a 1:1 communication, since there seems to be some Modbus inheritance in this protocol (the CRC16) and knowing that Modbus allows for more devices to be on the same bus, it ain’t that strange at all. Looking at other packet types (blockings, lockings, counters) I always see these 2 bytes coming back, so it’s fair to assume these are used for addressing. Now we’re down to 4 bytes:


$48 = 72 decimal. Packet size! Another important item to validate the incoming data stream.

Believe me, (I won’t bore you with examples of all the other packet types) 0201 is the function code or command code or whatever you like to name it. It identifies what the payload is about. 1 byte left, the 06. Protocol version? I don’t know yet. Maybe some day I will…

Tagged . Bookmark the permalink.

14 Responses to More about the Remeha protocol

  1. Leo says:

    Trying to build an similar interface on Linux (domoticz) for my Calenta (in France it is distributed under the de dietrich Brand)
    Would you like to share some more info and possibly piece of code that I could use?
    Many thanks,

  2. Patrick says:

    Would you please send me the script for using the protocol as well?

    • Robert Hekkers says:

      Do you have a Remeha Calenta or some other Remeha model?
      The files I’ll need to send depend on your answer.

  3. Peter says:

    Hi Robert,

    I also have a Calenta. Thereby I’m retrieving a Homey in a couple of weeks.
    What I want is to use an arduino as interface between Homey and my Calenta. Is it possible for you to send the information you have about the Calenta so that I don’t have to bit-it-out myself?

    Kind regards!

    • Robert Hekkers says:

      Hi Peter,
      Homey, me too!
      I’ll send you my NodeJS code, some XML files, that will do I guess.
      Remind me if you don’t hear from me because I get a lot of, ehm, fanmail πŸ˜‰

  4. Peter says:


    With a little help I’m now able to read-out the Calenta with my Arduino :).

    I’ve just have a question left, do you also have a difference between what Recom says and what the output says? If you look here, on the left you see the Recom values and on the right my read-outs with the arduino. For example, the roomtemperature in Recom is 18,94 degrees but the arduino says 19,8. Do you know where this difference is coming from?

    Also, what value (HEX) do you send to the Calenta? I tried 02 FE 00 05 08 01 0B D4 9C 03 but this isn’t working. I also found your char sentence but I’m not able to convert that into HEX values.

    Kind regards.

    • Robert Hekkers says:

      No, with my Calenta I got exactly the same numbers as Recom.
      But your model is different from mine, so you should check the xml files for differences between PCU-02 (P1) and your model.

  5. Peter says:


    I fixed the request part. Is also works if I send the Char as decimals :-).

  6. nik600 says:

    Dear all
    i’m trying too to decode responses from a PCU-04_P1.xml model.

    Looking at messages sent by recom, i’ve noticed that this is the request to get the values:


    Now, i have to decode the response wich obviously vari

    Do you have a more updated reference / documentation of the reverse-engeenering of the protocol?

    BTW…. thanks for all the work you have done!

    • nik600 says:

      Guys, i’ve implemented a small nodejs script that dump all the bytes received and looping on it i’ve decoded the values:

      Here my code (nothing clean or optimized, only a mix of try&fix reverse-eng):


      var sleep = require(‘sleep’);
      var SerialPort = require(“serialport”).SerialPort

      var serialPort = new SerialPort(“/dev/ttyUSB0”, {
      baudrate: 9600,
      databits: 8,
      stopbits: 1,
      parity: ‘none’

      var comando_recv=new Buffer(200);
      var comando_recv_i=0;

      serialPort.on(“open”, function () {


      serialPort.on(‘data’, function (data) {

      console.log("RX["+comando_recv_i+"]: " + data.readUInt8(i));
      console.log("RX["+comando_recv_i+"]: " + data.readUInt8(0));

      console.log("TOT: comando_recv="+comando_recv_i);


      // console.log("VAL readUInt16LE["+i+"]: " + comando_recv.readUInt16LE(i));
      // console.log("VAL readUInt16BE["+i+"]: " + comando_recv.readUInt16BE(i));
      console.log("VAL readInt16LE["+i+"]: " + comando_recv.readInt16LE(i));
      // console.log("VAL readInt16BE["+i+"]: " + comando_recv.readInt16BE(i));
      console.log("T. mandata = "+comando_recv.readInt16LE(7)/100);
      console.log("T. ritorno = "+comando_recv.readInt16LE(9)/100);
      console.log("val. nom. T. RISC = "+comando_recv.readInt16LE(23)/100);
      console.log("val. nom. T. ACS = = "+comando_recv.readInt16LE(25)/100);



      var comando_read = new Buffer([0x02, 0xFE, 0x01, 0x05, 0x08, 0x02, 0x01, 0x69, 0xAB, 0x03]);

      console.log("attendo 2 secondi…");

      console.log("TX: Mex");

      for (i = 0; i < comando_read.length; i++) {
      console.log("TX: " + comando_read.readUInt8(i));

      serialPort.write(comando_read, function (err, results) {
      if (err) {
      console.log('TX: err ' + err);
      } else {
      console.log('TX: results ' + results);



    • Robert Hekkers says:

      The documentation is in the Recom XML files. Do you have those?
      I could send you my NodeJS code if you like.

  7. HansN says:

    Bedankt. Ik heb het inmiddels ook aan de praat. Althans, een pc progje geschreven. Binnenkort wil ik het porten naar de Arduino.

    PS, ik zag op je website een plaatje van die Philips Experimenteerdoos. Daar is het bij mij destijds ook allemaal mee begonnen. πŸ™‚

    • Robert Hekkers says:

      Leuk dat je even laat weten dat het je gelukt is, succes verder!
      En ja die Philips Experimenteerdoos, daar heb ik vroeger heel wat uurtjes mee doorgebracht πŸ™‚

Leave a Reply

Your email address will not be published. Required fields are marked *