Skip to content

Conversation

@mattreim
Copy link
Contributor

@mattreim mattreim commented Oct 17, 2025

This PR is a follow-up to device request #8333 (Eurotronic SPZB0001), and I hope we can finish it. If @SwoopX, @Smanar, @manup helps, it could happen quickly ;)

Spirit_ZigBee_BAL_web_DE_Okt.-2019.pdf

@Smanar
Copy link
Collaborator

Smanar commented Oct 18, 2025

The typo error is corrected ?
I don't see why the validor is saying there is an error.

@mattreim
Copy link
Contributor Author

I don't understand the error either, but it's actually about the DDF.

@Smanar
Copy link
Collaborator

Smanar commented Oct 18, 2025

Perhaps it's because the PR is on Draft status ? So no new check.

@mattreim mattreim marked this pull request as ready for review October 18, 2025 17:15
@mattreim
Copy link
Contributor Author

I've even deleted everything and the error still exists.

@github-actions
Copy link
Contributor

github-actions bot commented Oct 18, 2025

Hey @mattreim, thanks for your pull request!

Tip

Modified bundles can be downloaded here.
Relative expire date

DDB changes

Modified

  • eurotronic/eurotronic_spzb0001_trv.json : Spirit radiator thermostat ✔️

Validation

Tip

Everything is fine !

🦆 Updated for commit 4f47c45

@mattreim mattreim marked this pull request as draft October 18, 2025 20:13
@mattreim
Copy link
Contributor Author

There are no config/hostflags yet, which I added. The information is from the PDF, but I don't think it's correct yet.

@Smanar
Copy link
Collaborator

Smanar commented Oct 19, 2025

Ha yes, was the missing config_hostflags_item.json.

On the code this flag is hidden, but IDK if it's usefull.

sensor.addItem(DataTypeUInt32, RConfigHostFlags)->setIsPublic(false);

Copy link
Collaborator

@SwoopX SwoopX left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks a lot for the PR. Way better to track changes :)

Please have a look at my comments. Apart from those, it seems that the config/offset item got lost from the issue discussion, so I'd suggest to add

        {
          "name": "config/offset",
          "refresh.interval": 3660,
          "write": {
            "at": "0x0010",
            "cl": "0x0201",
            "dt": "0x28",
            "ep": 1,
            "eval": "Item.val / 10;",
            "fn": "zcl:attr"
          },
          "parse": {
            "at": "0x0010",
            "cl": "0x0201",
            "ep": 1,
            "eval": "Item.val = Attr.val * 10;",
            "fn": "zcl:attr"
          },
          "default": 0
        },

Comment on lines 247 to 262
"name": "state/on",
"refresh.interval": 660,
"read": {
"at": "0x0000",
"cl": "0x0006",
"ep": 1,
"fn": "zcl:attr"
},
"parse": {
"at": "0x0000",
"cl": "0x0006",
"ep": 1,
"eval": "Item.val = Attr.val",
"fn": "zcl:attr"
},
"default": false
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems like the former content got lost. Here, it should be as follows (the attribute is read through state/valve):

          "name": "state/on",
          "parse": {
            "at": "0x0008",
            "cl": "0x0201",
            "ep": 1,
            "eval": "Item.val = Attr.val > 3;",
            "fn": "zcl:attr"
          },
          "read": {
            "fn": "none"
          }

Comment on lines 285 to 287
"read": {
"fn": "none"
},
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there any particular reason not to read the attribute? I would've left the default read function here.

Comment on lines 162 to 168
"read": {
"at": "0x4008",
"cl": "0x0201",
"ep": 1,
"fn": "zcl:attr",
"mf": "0x1037"
},
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd recommend to change the function here to

          "read": {
            "fn": "none"
          },

and let config/hostflags do the read for all other items relying on it. That would save lots of unnecessary reads.

Comment on lines 191 to 197
"read": {
"at": "0x4008",
"cl": "0x0201",
"ep": 1,
"fn": "zcl:attr",
"mf": "0x1037"
},
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd recommend to change the function here to

          "read": {
            "fn": "none"
          },

and let config/hostflags do the read for all other items relying on it. That would save lots of unnecessary reads.

Comment on lines 86 to 92
"read": {
"at": "0x4008",
"cl": "0x0201",
"ep": 1,
"fn": "zcl:attr",
"mf": "0x1037"
},
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd recommend to change the function here to

          "read": {
            "fn": "none"
          },

and let config/hostflags do the read for all other items relying on it. That would save lots of unnecessary reads.

Comment on lines 112 to 137
{
"name": "config/heatsetpoint",
"refresh.interval": 660,
"read": {
"at": "0x0012",
"cl": "0x0201",
"ep": 1,
"fn": "zcl:attr"
},
"write": {
"at": "0x0012",
"cl": "0x0201",
"dt": "0x29",
"ep": 1,
"eval": "Item.val",
"fn": "zcl:attr"
},
"parse": {
"at": "0x0012",
"cl": "0x0201",
"ep": 1,
"eval": "Item.val = Attr.val",
"fn": "zcl:attr"
},
"default": 0
},
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This one here is very delicate, as the screwed firmware version does not allow for any differentiation which attribute must be written. For the Spirit, the legacy code uses mf attribute 0x4003, so I'd vouch for continuing using it in the read and parse functions.

As for the write function, I guess we can leave it as is, since it doesn't matter anyway. The legacy code has an ugly, but required workaround and sends a write request to any relevant attribute (so in total 2). As said, this must remain as you have no chance to know which attribute the hardware really accepts.

Please, this must be tested in strict mode!

"id": "config/hostflags",
"datatype": "Int32",
"access": "RW",
"public": true,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess the item should not be public.

"dt": "0x29",
"mf": "0x1037",
"min": 1,
"max": 600
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Legacy code has a reportable change of 50 (int value). Do we want to adapt that?

@mattreim
Copy link
Contributor Author

mattreim commented Oct 22, 2025

@SwoopX Thank you for your help and I hope I understood the changes correctly but please take another look.

@mattreim mattreim requested a review from SwoopX October 24, 2025 16:11
Copy link
Collaborator

@SwoopX SwoopX left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems as if the force push screwed the proper tracking of the changes...

From what I can see, quite some write functions have been deleted, presumably accidentally? Also, the question regarding the reportable change is still pending and if the DDF has been tested in strict mode.

@mattreim
Copy link
Contributor Author

Now I'm completely confused, too. Probably something about ("read" => "fn": "none"), right? I haven't been able to test it yet because I'm using HA and am currently testing it on Windows. But I'd like to start with a somewhat finished DDF.

@mattreim mattreim requested a review from SwoopX October 24, 2025 21:25
@mattreim
Copy link
Contributor Author

mattreim commented Oct 25, 2025

@SwoopX I just tested everything in strict mode, and the device works exactly as expected. The valve shows values ​​between 0 and 100, and the error code appears immediately, even if I remove the thermostat. The only thing I haven't been able to test is "windowopen", as it's apparently still too warm outside. So, for me, the DDF is now ready for use, but only in strict mode; otherwise, it doesn't work.

{
    "capabilities": {
        "sleeper": false
    },
    "config": {
        "battery": 60,
        "displayflipped": false,
        "heatsetpoint": 2100,
        "locked": false,
        "mode": "auto",
        "offset": 0,
        "on": true,
        "reachable": true
    },
    "ep": 1,
    "etag": "6088eb7dd4abf9d3f826e8ed75b7bdfe",
    "lastannounced": "2025-10-25T13:47:57Z",
    "lastseen": "2025-10-25T13:56Z",
    "manufacturername": "Eurotronic",
    "modelid": "SPZB0001",
    "name": "Thermostat - Diele",
    "nwkaddress": "0x9EB5",
    "state": {
        "errorcode": "none",
        "lastupdated": "2025-10-25T13:57:03.876",
        "on": false,
        "temperature": 2158,
        "valve": 0,
        "windowopen": "0"
    },
    "swversion": "18181120",
    "type": "ZHAThermostat",
    "uniqueid": "00:15:8d:00:07:74:34:93-01-0201"
}

Events:

    "16:15:42:46": {
        "e": "changed",
        "id": "36",
        "r": "sensors",
        "state": {
            "errorcode": "none",
            "lastupdated": "2025-10-25T14:15:42.045",
            "on": false,
            "temperature": 2087,
            "valve": 0,
            "windowopen": "0"
        },
        "t": "event",
        "uniqueid": "00:15:8d:00:07:74:34:93-01-0201"
    }
}

@SwoopX
Copy link
Collaborator

SwoopX commented Oct 25, 2025

Awesome, I guess this one should be ready to go then. However, I'd need to prepare another PR to have the legacy code removed completely, otherwise the DDF is not used.

One last remark though: the legacy code sets the bits for the hostflags a little different. No clue if that has any (noticable) impact or not.

@mattreim
Copy link
Contributor Author

Thanks for taking over the follow-up PR, and this old device is a bit slower than the new ones anyway, but that's not a big deal. So the legacy code is getting smaller and smaller. I'll now make it "Ready for review".

@mattreim mattreim marked this pull request as ready for review October 25, 2025 22:11
@manup
Copy link
Member

manup commented Oct 29, 2025

Nice work guys, much appreciated when the legacy code can be removed too later on 👍

@manup manup added this to the v2.32.1-beta milestone Oct 29, 2025
@SwoopX
Copy link
Collaborator

SwoopX commented Oct 29, 2025

I fear it needs to go with the legacy code simultaneously. Will prepare the accompanying PR on the weekend at the latest.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants