Weiter zum Inhalt
  • Home
  • Aktuell
  • 0 Ungelesen 0
  • Kategorien
  • Unreplied
  • Beliebt
  • GitHub
  • Docu
  • Hilfe
Skins
  • Hell
  • Brite
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dunkel
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Standard: (Kein Skin)
  • Kein Skin
Einklappen
ioBroker Logo

Community Forum

donate donate
  1. ioBroker Community Home
  2. English
  3. Projects (Showcase)
  4. Wolf boilers on ebusd: solved — read and write

NEWS

  • Node.js 24 ist jetzt offiziell empfohlen!
    apollon77A
    apollon77
    6
    1
    150

  • NEWS Räume und Funktionen in einem Durchlauf: der Assistent in Admin 8 (mit Video)
    BluefoxB
    Bluefox
    6
    1
    225

  • NEWS: Neu im Admin, zentrale Verwaltung für Passwörter und Schlüssel
    BluefoxB
    Bluefox
    19
    1
    425

Wolf boilers on ebusd: solved — read and write

Geplant Angeheftet Gesperrt Verschoben Projects (Showcase)
ebusdwolf
1 Beiträge 1 Kommentatoren 33 Aufrufe 1 Beobachtet
  • Älteste zuerst
  • Neuste zuerst
  • Meiste Stimmen
Antworten
  • In einem neuen Thema antworten
Anmelden zum Antworten
Dieses Thema wurde gelöscht. Nur Nutzer mit entsprechenden Rechten können es sehen.
  • D
    D
    DragoGT
    schrieb zuletzt editiert von
    #1

    Wolf boilers on ebusd: the checksum is solved — read and write every register

    TL;DR — The mystery byte in a Wolf read telegram is a CRC8 with polynomial 0x5c over the
    low byte of the TelegramNr, XORed with the high byte. That was the last thing standing between
    Wolf's own published parameter database and a complete ebusd config. You no longer need to
    copy magic bytes out of somebody else's 08.csv. There is a script below that generates a
    config for any of 48 Wolf device templates. Writes work too, and the write format is
    different from the read format in a way that explains why so many people's w rows do nothing.

    Tested on a Wolf FGB-K-28 (ebusd 25.1, eBUS shield, ioBroker). 22 of 22 generated IDs are
    byte-identical to a hand-made config that has worked for years, plus 30 new registers that were
    never readable before. Please try it on your CGB / CGB-2 / CGG-2 / COB / CHA / BM-2 and report
    back — the derivation is device-independent but I can only prove it on the hardware I own.


    1. Why this has been hard

    Wolf publishes no eBUS documentation. Every Wolf config in the wild is hand-made, partial, and
    propagated by copy-paste. --scanconfig can never help: a Wolf boiler answers the scan with
    MF=65; ID=" &", ebusd does not know manufacturer 0x65, and the ID looks like line noise.

    Reads are ZZ=08, PBSB=5022, three ID bytes:

    r,heating,dhw_temp,,,08,5022,cc0e00,...
                                ^^^^^^
                                ?? 0e 00      0x000e = 14 = TelegramNr
    

    The last two bytes are obviously the TelegramNr little-endian. The first byte is the problem.
    It is different for every register, the forums call it "the CRC", and the accepted workaround has
    been: if nobody has published the byte for the register you want, you cannot read that register.

    2. The checksum

    It is linear over GF(2), which is what makes it recoverable. Take known-good (byte, TelegramNr)
    pairs out of any working Wolf 08.csv, treat each output bit as a linear equation over the 16
    index bits plus a constant, and solve. On 22 verified pairs that is heavily over-determined and
    gives a unique answer, whose bit-effects are exactly:

    function wolfCrc(telegramNr) {
        let c = telegramNr & 0xff;
        for (let i = 0; i < 8; i++)
            c = (c & 0x80) ? (((c << 1) & 0xff) ^ 0x5c) : ((c << 1) & 0xff);
        return (c ^ (telegramNr >> 8)) & 0xff;
    }
    
    const hx = n => n.toString(16).padStart(2, '0');
    const readId = tn => hx(wolfCrc(tn)) + hx(tn & 0xff) + hx((tn >> 8) & 0xff);
    

    A CRC8 chain with polynomial 0x5c, init 0, over the LOW byte only — then the HIGH byte is
    XORed in and never shifted.
    That last part is why it is not any textbook CRC8 and why
    table-driven guesses fail.

    Checks that matter:

    • It reproduces 22 of 22 IDs in a config that has worked for years.
    • The linear solve leaves index bits 10–15 unconstrained (no training sample used them, since
      all known registers were < 1024). The poly-0x5c form pins them as identity on the high byte.
      That extrapolation is confirmed on real hardware: TelegramNr 10010 (high byte 0x27, far
      outside the training set) generates 771a27 and reads 1.80 bar of system pressure on my
      boiler. Same for 10013, 10067, 10068, 65019.
    • TelegramNr 554 and 644 both produce de — a genuine collision, because 0x2a and 0x84 shift
      to the same value. The high byte disambiguates them. If you have been confused by two registers
      sharing a first byte, that is why.

    Bonus: running this over an existing config is a good way to find typos. It flagged one in
    mine — hg74 had d5 where the algorithm says 91. It had never worked and nobody knew why.

    3. Writes — and why yours probably do nothing

    Writes use a different address and a different ID format:

    Read Write
    Destination ZZ=08 (slave) ZZ=03 (master)
    PB SB 5022 5023
    First ID byte the checksum 00 — writes are not checksummed
    Payload — value, then a 4-byte suffix 9d010000
    w,heating,dhw_target_set,Warmwassersolltemperatur eingestellt,,03,5023,001300,dhw_target_set,,SIN,10,°C,,suffix,,HEX:4,=9d010000,,
    

    Two things people get wrong:

    1. The destination is the master address 03, not 08. I had this recorded as "the write
      rows are mis-addressed" — that was wrong, and it had simply never been tested. Sending the same
      write to ZZ=08 gives ERR: read timeout.
    2. ebusctl write printing empty is SUCCESS, not an error. A Wolf write is a master-master
      telegram with no data response. empty is what a successful one looks like.

    Proof, on a deliberately harmless register (hg07, heating pump run-on, valid range 0–30 min):

    $ ebusctl read -m 0 -c heating hg07
    2
    $ ebusctl write -c heating hg07 3
    empty
    $ ebusctl read -m 0 -c heating hg07
    3
    

    And the one that matters — the DHW setpoint, TelegramNr 19, write ID 001300:

    before: 45.0
    empty
    after:  50.0
    live:   50.0      <- TelegramNr 3, the derived setpoint, followed
    

    Test writes on something harmless first. hg07 or hg09 are ideal: in-range values change
    nothing you will notice, and they read straight back.

    4. Getting the register list for your Wolf device

    You do not have to guess which TelegramNrs exist. Wolf's own SmartSet/ISM7 metadata is public
    inside zivillian/ism7mqtt — parameter.xml,
    converter.xml and device.xml under src/ism7mqtt/Resources/. Between them they give, for
    every Wolf device: TelegramNr, data type, unit, min/max, and the value labels for enums.

    wolf-registers.js (attached) downloads them and does the join:

    $ node wolf-registers.js --list
      DTID    WRSDeviceIds  params  Name
      30000   0x18          80      BM
      220000  0x20          139     BM-2
      80000   0x6           45      CGB
      180000  0x21          97      CGB-2
      100000  0x1D          53      CGG-2
      110000  0x1C          53      CGU-2
      270000  0x29          178     CHA
      90000   0x1A          49      COB
      250000  0x26          64      FGB
      ...48 templates
    

    Which one are you? Look at your ebusd scan string. Mine says MF=65; ID=" &". Those ID bytes
    are 0x20 0x26 — and & is 0x26, which is exactly the WRSDeviceIds of the FGB
    template. The "garbage" ID is not garbage; it contains your device id. Match it against the list.

    $ node wolf-registers.js --device FGB
    TelegramNr  readID   writeID  Type    Unit   Range        Name
    13          280d00   000d00   SS10    °C                  Kesseltemperatur
    14          cc0e00   000e00   SS10    °C                  Warmwassertemperatur
    19          541300   001300   SS10    °C     30..80       Warmwassersolltemperatur eingestellt
    270         cd0e01   000e01   SS100          0..30        Heizkurve
    10010       771a27   001a27   SS100   bar                 Anlagendruck
    ...
    
    $ node wolf-registers.js --device FGB --csv --write > 08-generated.csv
    

    Type mapping: SS10→SIN divider 10, SS100→SIN divider 100, US10→UIN divider 10,
    US→UIN, SS→SIN.

    5. Things that cost me hours

    ebusctl read -h only works for messages ebusd ALREADY KNOWS. It is not a raw frame sender.
    An unknown ID returns ERR: element not found without touching the bus. So you cannot use it to
    probe for new registers, and "a wrong checksum is rejected" proves nothing about your boiler — it
    only proves ebusd's message table did not match.

    ebusctl hex and read -def need --enablehex / --enabledefine. Off by default.

    Validate a config offline, as a normal user, before installing it:

    ebusd --checkconfig --configpath=/home/you/ebustest/ --device=ens:127.0.0.1:59999
    

    Copy your config tree somewhere writable, edit, check. It prints found messages: N (... M poll)
    and exits 0 without touching the running daemon or the bus.

    Do not force-read many registers back to back. I ran 32 sequential read -m 0 calls and
    roughly every other one came back empty, with the symbol rate spiking to 102. It looks exactly
    like "this register is unsupported" and it is not. Read the poll cache instead —
    ebusctl find -a -c heating — giving it a couple of minutes after ebusctl reload to refill.

    Adding a write row whose name matches an existing read row does NOT increase messages:.
    ebusd merges them into one message with two directions. Check with ebusctl find -w -c heating,
    not the count. I briefly misread this as a rejected row.

    Polling more costs nothing. I went from 28 to 60 polled messages and the bus symbol rate
    stayed at 12, exactly as before. Poll priority (r1…r9) controls how often each is polled,
    not how much traffic there is in total.

    Values reading 32768 or 3276.8 are the eBUS null sentinel — "this register does not exist
    on this device". Six of mine had been dead for years. Their TelegramNrs (39, 321, 362, 365, 368)
    simply are not in the FGB parameter list; they had been copied from a different Wolf model. No
    config change will ever fix those, and now you can tell the difference between "wrong byte" and
    "not present" by checking the generated list.

    6. ioBroker integration

    MQTT. ebusd's own MQTT integration publishes reads fine:

    --mqttint=/etc/ebusd/mqtt-integration.cfg --mqtthost=127.0.0.1 --mqttport 1883 ...
    

    Note it ships filter-direction = r|u, i.e. read-only — it will not accept writes. To write
    from a script, shell out:

    exec('ebusctl write -c heating dhw_target_set 50', () => {
        exec('ebusctl read -m 0 -c heating dhw_target_set', (e, out) => log('now ' + out));
    });
    

    Always read back and verify. A write that silently does nothing is the failure mode here.

    Poll priority gotcha. If you use the Home Assistant MQTT profile, filter-seen = 5 silently
    promotes matched messages to poll priority 5. Remove it and everything goes to no data stored
    because nothing is polled any more. Declare priority in the CSV instead (r5,heating,...).

    Two scripts are attached:

    • boiler_status_en.js — turns the raw enum numbers into readable states under
      0_userdata.0.heating.boiler.*: status, mode, burner_status, firing, fault, alive,
      plus a one-line summary like Firing at 28% — Heating mode. fault is the one worth
      alarming on: true when burner_status is 12 (Störung) or the safety limiter has tripped.
      alive watches staleness across several polled registers, because the boiler powers the eBUS —
      so a dead bus means a dead boiler.
    • boiler_aliases.js — a stable alias.0.boiler.* layer so renaming an ebusd message does not
      break every widget and chart. It refuses to create an alias whose source does not exist and
      tells you which ones to fix.

    Useful enum decodings (from Wolf's own KeyValueList, FGB — check yours with the tool):

    burner_status  0 Aus · 1 Ruhekontakt · 2 Vorspülen · 3 Zünden · 4 Stabilisierung · 5 Ein ·
                   6 Ventilprüfung · 7 Nachspülen · 8 Softstart · 9 Taktsperre ·
                   10 Betrieb ohne Brenner · 11 Abgasklappe · 12 Störung · 13 Gradienten Überwachung ·
                   14 Gasdruck · 15 Spreizung hoch · 16 Spreizung KF
    operating_mode 0 Test · 1 Start · 2 Frost Heizkreis · 3 Frost Warmwasser · 4 Schornsteinfeger ·
                   5 Kombibetrieb · 6 Parallelbetrieb · 7 Warmwasser · 8 Warmwassernachlauf ·
                   9 Mindest-Kombizeit · 10 Heizbetrieb · 11 Nachlauf Heizkreispumpe ·
                   12 Frostschutz · 13 Standby · 14 Kaskadenbetrieb · 15 GLT-Betrieb ·
                   16-19 Kalibration · 20 WW Schnellstart · 21 Externe Deaktivierung
    program (10100) 1 Aus · 3 Winterbetrieb · 5 Sommerbetrieb
    TelegramNr 370 bit 3          = Brenner
    TelegramNr 371 bits 0,1,2,4,5 = Zündung, Ventil 1, Ventil 2, Kesselkreispumpe, 3-Wege-Ventil
    

    7. Safety

    This is a gas appliance. A few things I would not do:

    • Do not write to a register you have not looked up. The generated table gives the valid
      range; stay inside it. Writing outside a documented range is not something I have tested and
      not something I would.
    • Prove writes on a harmless parameter first (hg07, hg09), read back, restore.
    • Do not try to make ebusd the heating controller. Emulating the controller broadcast means
      repeating it forever, and if your automation dies in winter so does your frost protection. For
      simple on/off demand a relay across the room-thermostat contact fails safe; this does not.
    • Back up 08.csv boiler_aliases.js boiler_status_en.js wolf-registers.js before every change and keep ebusd --checkconfig in the loop.
    • Writes change settings in the boiler, persistently. They survive a reboot of everything
      else. Write down what you changed.

    8. What it got me

    A Wolf FGB-K-28 that exposed 28 registers, six of them permanently dead, now exposes 60 — at
    identical bus load. New and working:

    Anlagendruck (system pressure, bar) · Abgastemperatur (flue gas) · Modulationsgrad ·
    Brennerstatus (17 states) · Betriebsart (20 modes) · Brenner, Zündung,
    Ventil 1/2, Kesselkreispumpe, 3-Wege-Ventil (six real digital signals) ·
    Drehzahl Kesselkreispumpe / ZHP WW · Heizkurve · Firmware · Anlagendruck ·
    Auslauftemperatur Warmwasser · Sicherheitstemperaturbegrenzer · Anzahl Netz-Starts ·
    and roughly fifteen more.

    Plus working writes, which turned into an automated weekly DHW disinfection cycle and a
    vacation setback.

    Three errors found in a config that had been running for years: a wrong checksum on hg74,
    hg75 typed as minutes when TelegramNr 364 is litres per minute (it is the DHW flow rate),
    and six registers that do not exist on this device at all.


    Files

    wolf-registers.js generates the register table / ebusd CSV for any Wolf device
    boiler_status_en.js ioBroker: decoded status states + fault/alive flags
    boiler_aliases.js ioBroker: stable alias.0.boiler.* layer

    Credit

    The parameter database is zivillian/ism7mqtt's extraction
    of Wolf's SmartSet metadata — without it none of this is possible. ebusd is
    john30/ebusd. The forum threads that got me oriented are
    ebusd discussion #779 and #721.

    Corrections welcome, especially from anyone who can confirm or refute the checksum on a non-FGB
    Wolf device.

    1 Antwort Letzte Antwort
    0

    Hey! Du scheinst an dieser Unterhaltung interessiert zu sein, hast aber noch kein Konto.

    Hast du es satt, bei jedem Besuch durch die gleichen Beiträge zu scrollen? Wenn du dich für ein Konto anmeldest, kommst du immer genau dorthin zurück, wo du zuvor warst, und kannst dich über neue Antworten benachrichtigen lassen (entweder per E-Mail oder Push-Benachrichtigung). Du kannst auch Lesezeichen speichern und Beiträge positiv bewerten, um anderen Community-Mitgliedern deine Wertschätzung zu zeigen.

    Mit deinem Input könnte dieser Beitrag noch besser werden 💗

    Registrieren Anmelden
    Antworten
    • In einem neuen Thema antworten
    Anmelden zum Antworten
    • Älteste zuerst
    • Neuste zuerst
    • Meiste Stimmen


    Support us

    ioBroker
    Community Adapters
    Donate

    438

    Online

    33.1k

    Benutzende

    83.9k

    Themen

    1.4m

    Beiträge
    Community
    Impressum | Datenschutz-Bestimmungen | Nutzungsbedingungen | Einwilligungseinstellungen
    ioBroker Community 2014-2026
    logo
    • Anmelden

    • Du hast noch kein Konto? Registrieren

    • Anmelden oder registrieren, um zu suchen
    • Erster Beitrag
      Letzter Beitrag
    0
    • Home
    • Aktuell
    • Ungelesen 0
    • Kategorien
    • Unreplied
    • Beliebt
    • GitHub
    • Docu
    • Hilfe