Haverland Radiators Smart Box Integration

Looks like the same error:

Logger: homeassistant.config_entries
Source: config_entries.py:637
First occurred: 16:13:14 (1 occurrences)
Last logged: 16:13:14

Error setting up entry Haverland [email protected] for smartbox
Traceback (most recent call last):
  File "/usr/src/homeassistant/homeassistant/config_entries.py", line 637, in __async_setup_with_context
    result = await component.async_setup_entry(hass, self)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/config/custom_components/smartbox/__init__.py", line 76, in async_setup_entry
    devices = await get_devices(session=session, hass=hass)
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/config/custom_components/smartbox/model.py", line 395, in get_devices
    devices.append(await create_smartbox_device(session_device, session, hass))
                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/config/custom_components/smartbox/model.py", line 407, in create_smartbox_device
    await _device.initialise_nodes()
  File "/config/custom_components/smartbox/model.py", line 56, in initialise_nodes
    session_nodes = await self._session.get_nodes(self.dev_id)
                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.13/site-packages/smartbox/session.py", line 303, in get_nodes
    nodes: Nodes = Nodes.model_validate(response)
                   ~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^
  File "/usr/local/lib/python3.13/site-packages/pydantic/main.py", line 627, in model_validate
    return cls.__pydantic_validator__.validate_python(
           ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^
        obj, strict=strict, from_attributes=from_attributes, context=context
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    )
    ^
pydantic_core._pydantic_core.ValidationError: 12 validation errors for Nodes
nodes.0.lost
  Field required [type=missing, input_value={'name': 'KITCHEN', 'addr...'level': 0, 'parent': 0}, input_type=dict]
    For further information visit https://errors.pydantic.dev/2.10/v/missing
nodes.1.lost
  Field required [type=missing, input_value={'name': 'LIVING ROOM 2',...'level': 0, 'parent': 0}, input_type=dict]
    For further information visit https://errors.pydantic.dev/2.10/v/missing
nodes.2.lost
  Field required [type=missing, input_value={'name': 'SITTING ROOM 2'...'level': 0, 'parent': 0}, input_type=dict]
    For further information visit https://errors.pydantic.dev/2.10/v/missing
nodes.3.lost
  Field required [type=missing, input_value={'name': 'SITTING ROOM 1'...'level': 0, 'parent': 0}, input_type=dict]
    For further information visit https://errors.pydantic.dev/2.10/v/missing
nodes.4.lost
  Field required [type=missing, input_value={'name': 'LIVING ROOM 1',...'level': 0, 'parent': 0}, input_type=dict]
    For further information visit https://errors.pydantic.dev/2.10/v/missing
nodes.5.lost
  Field required [type=missing, input_value={'name': 'ALISS BEDROOM',...'level': 0, 'parent': 0}, input_type=dict]
    For further information visit https://errors.pydantic.dev/2.10/v/missing
nodes.6.lost
  Field required [type=missing, input_value={'name': 'LANDING', 'addr...'level': 0, 'parent': 0}, input_type=dict]
    For further information visit https://errors.pydantic.dev/2.10/v/missing
nodes.7.lost
  Field required [type=missing, input_value={'name': 'ROBS BEDROOM', ...'level': 0, 'parent': 0}, input_type=dict]
    For further information visit https://errors.pydantic.dev/2.10/v/missing
nodes.8.lost
  Field required [type=missing, input_value={'name': 'UTILITY', 'addr...'level': 0, 'parent': 0}, input_type=dict]
    For further information visit https://errors.pydantic.dev/2.10/v/missing
nodes.9.lost
  Field required [type=missing, input_value={'name': 'OFFICE', 'addr'...'level': 0, 'parent': 0}, input_type=dict]
    For further information visit https://errors.pydantic.dev/2.10/v/missing
nodes.10.lost
  Field required [type=missing, input_value={'name': 'STUDIO', 'addr'...'level': 0, 'parent': 0}, input_type=dict]
    For further information visit https://errors.pydantic.dev/2.10/v/missing
nodes.11.lost
  Field required [type=missing, input_value={'name': 'End Bedroom', '...'level': 0, 'parent': 0}, input_type=dict]
    For further information visit https://errors.pydantic.dev/2.10/v/missing

Okay, the patch has been push
Could you redownload the integration throw HACS, restart home assistant and try again please ?

1 Like

Success!! It worked, thank you. The only issue is that it shows several radiators that I don’t have (see images). I have 4 radiators but the list shows 16! The 12 that I don’t have are not connected (which is just as well) so I will just disable them. I wonder if Haverland includes these as defaults/tests. They don’t appear in the Haverland app. Anyway, thank you so much for getting this working - great work.

perfect… just an ideia… please edit the first post, (or just TAG something) or create a new “post” with instructions… to avoid multiple questions on this thread… about “situations” solved on “new” update… so we keep this “clean”
or a new post… without the possibility to reply… any issues we continue discussing here, on this post…

Thanks for the hard job, in my HA send this error:

Registrador: homeassistant.config_entries
Fuente: config_entries.py:637
Ocurrió por primera vez: 10:49:38 (3 ocurrencias)
Última vez registrado: 10:52:57

Error setting up entry Elnur [email protected] for smartbox
Traceback (most recent call last):
File “/usr/src/homeassistant/homeassistant/config_entries.py”, line 637, in __async_setup_with_context
result = await component.async_setup_entry(hass, self)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File “/config/custom_components/smartbox/init.py”, line 76, in async_setup_entry
devices = await get_devices(session=session, hass=hass)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File “/config/custom_components/smartbox/model.py”, line 395, in get_devices
devices.append(await create_smartbox_device(session_device, session, hass))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File “/config/custom_components/smartbox/model.py”, line 407, in create_smartbox_device
await _device.initialise_nodes()
File “/config/custom_components/smartbox/model.py”, line 65, in initialise_nodes
samples: SamplesDict = await self._session.get_node_samples(
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
…<4 lines>…
)
^
File “/usr/local/lib/python3.13/site-packages/smartbox/session.py”, line 383, in get_node_samples
samples = Samples.model_validate(
await self._api_request(
f"devs/{device_id}/{_node.type}/{_node.addr}/samples?start={start_time}&end={end_time}",
),
)
File “/usr/local/lib/python3.13/site-packages/pydantic/main.py”, line 627, in model_validate
return cls.pydantic_validator.validate_python(
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^
obj, strict=strict, from_attributes=from_attributes, context=context
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
)
^
pydantic_core._pydantic_core.ValidationError: 3 validation errors for Samples
samples.0.counter
Field required [type=missing, input_value={‘t’: 1739602800, ‘temp’:…019763], ‘valley’: True}, input_type=dict]
For further information visit Redirecting...
samples.1.counter
Field required [type=missing, input_value={‘t’: 1739606400, ‘temp’:…019763], ‘valley’: True}, input_type=dict]
For further information visit Redirecting...
samples.2.counter
Field required [type=missing, input_value={‘t’: 1739610000, ‘temp’:…019763], ‘valley’: True}, input_type=dict]
For further information visit Redirecting...

1 Like

Hi there.

I reinstalled everything, and I have the account connected, but I still get some errors:

2025-02-15 16:55:11.446 DEBUG (MainThread) [smartbox.resailer] Resailer api_url (api-hjm), name=HJM,  web_url https://api.calorhjm.com/
2025-02-15 16:55:11.863 DEBUG (MainThread) [smartbox.session] Authenticated session (password), access_token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOiI1ZmVkZDU2YjYxNmE5ZjM3OWM2NDYwMmQiLCJzZXJpYWxJZCI6IjEwIiwiY2xpZW50SWQiOiI1NGJjY2JmYjQxYTlhNTExM2YwNDg4ZDAiLCJlbWFpbCI6ImZyYW5jaXNjb2hvcnRhQGdtYWlsLmNvbSIsImV4cCI6MTczOTY1MjkxMSwic2NvcGUiOiIvdXNlcjpXIC9kZXZzLyo6VyIsImlhdCI6MTczOTYzODUxMSwiaXNzIjoiaGVsa2kifQ.2f-fsY9Qn8b1L3wtPT-H1uCOwc-WWfbBpXmD1gYi7AE, expires at 2025-02-15 20:55:11.863112+00:00
2025-02-15 16:55:11.863 DEBUG (MainThread) [smartbox.session] Getting https://api-hjm.helki.com/api/v2/grouped_devs.
2025-02-15 16:55:11.993 DEBUG (MainThread) [smartbox.session] Getting https://api-hjm.helki.com/api/v2/devs/c44fea5ec15048c7e8/mgr/nodes.
2025-02-15 16:55:12.107 DEBUG (MainThread) [smartbox.session] Get nodes {'nodes': [{'name': 'Consumos', 'addr': 3, 'type': 'pmo', 'setup': {'counter_offset': '679.33'}, 'installed': True, 'lost': False, 'uid': '003E003F0D47373436363733', 'level': 1, 'parent': 1}, {'name': 'Bedroom', 'addr': 2, 'type': 'htr', 'setup': {'counter_offset': 2375}, 'installed': True, 'lost': False, 'uid': '0032002F0647373033363637', 'level': 1, 'parent': 1}, {'name': 'Office', 'addr': 4, 'type': 'htr', 'setup': {'counter_offset': 293}, 'installed': True, 'lost': True, 'uid': '0033006F0647373033363637', 'level': 1, 'parent': 1}, {'name': 'Living room', 'addr': 5, 'type': 'htr', 'setup': {'counter_offset': 584}, 'installed': True, 'lost': False, 'uid': '0029002D0647373033363637', 'level': 1, 'parent': 1}]}
2025-02-15 16:55:12.108 DEBUG (MainThread) [smartbox.session] Getting https://api-hjm.helki.com/api/v2/devs/c44fea5ec15048c7e8/pmo/3/status.
2025-02-15 16:55:12.159 DEBUG (MainThread) [smartbox.session] (pmo) Status config data {'statusCode': 404, 'message': 'Not Found'}
2025-02-15 16:55:12.159 DEBUG (MainThread) [smartbox.session] Getting https://api-hjm.helki.com/api/v2/devs/c44fea5ec15048c7e8/pmo/3/setup.
2025-02-15 16:55:12.217 DEBUG (MainThread) [smartbox.session] (pmo) Setup config data {'power_limit': 0, 'reverse': False, 'circuit_type': 0}
2025-02-15 16:55:12.217 DEBUG (MainThread) [smartbox.session] Get_Device_Samples_Node: from 2025-02-15 13:55:12+00:00 to 2025-02-15 16:55:12+00:00
2025-02-15 16:55:12.217 DEBUG (MainThread) [smartbox.session] Getting https://api-hjm.helki.com/api/v2/devs/c44fea5ec15048c7e8/pmo/3/samples?start=1739627712&end=1739638512.
2025-02-15 16:55:12.280 ERROR (MainThread) [homeassistant.config_entries] Error setting up entry HJM [email protected] for smartbox
Traceback (most recent call last):
  File "/usr/src/homeassistant/homeassistant/config_entries.py", line 637, in __async_setup_with_context
    result = await component.async_setup_entry(hass, self)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/config/custom_components/smartbox/__init__.py", line 76, in async_setup_entry
    devices = await get_devices(session=session, hass=hass)
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/config/custom_components/smartbox/model.py", line 395, in get_devices
    devices.append(await create_smartbox_device(session_device, session, hass))
                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/config/custom_components/smartbox/model.py", line 407, in create_smartbox_device
    await _device.initialise_nodes()
  File "/config/custom_components/smartbox/model.py", line 65, in initialise_nodes
    samples: SamplesDict = await self._session.get_node_samples(
                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    ...<4 lines>...
    )
    ^
  File "/usr/local/lib/python3.13/site-packages/smartbox/session.py", line 383, in get_node_samples
    samples = Samples.model_validate(
        await self._api_request(
            f"devs/{device_id}/{_node.type}/{_node.addr}/samples?start={start_time}&end={end_time}",
        ),
    )
  File "/usr/local/lib/python3.13/site-packages/pydantic/main.py", line 627, in model_validate
    return cls.__pydantic_validator__.validate_python(
           ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^
        obj, strict=strict, from_attributes=from_attributes, context=context
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    )
    ^
pydantic_core._pydantic_core.ValidationError: 22 validation errors for Samples
samples.0.temp
  Field required [type=missing, input_value={'t': 1739628000, 'counte...': '3490', 'min': '210'}, input_type=dict]
    For further information visit https://errors.pydantic.dev/2.10/v/missing
samples.0.counter
  Input should be a valid integer, unable to parse string as an integer [type=int_parsing, input_value='16820127.64', input_type=str]
    For further information visit https://errors.pydantic.dev/2.10/v/int_parsing
samples.1.temp
  Field required [type=missing, input_value={'t': 1739628900, 'counte...': '3865', 'min': '279'}, input_type=dict]
    For further information visit https://errors.pydantic.dev/2.10/v/missing
samples.1.counter
  Input should be a valid integer, unable to parse string as an integer [type=int_parsing, input_value='16820589.77', input_type=str]
    For further information visit https://errors.pydantic.dev/2.10/v/int_parsing
samples.2.temp
  Field required [type=missing, input_value={'t': 1739629800, 'counte...': '2288', 'min': '281'}, input_type=dict]
    For further information visit https://errors.pydantic.dev/2.10/v/missing
samples.2.counter
  Input should be a valid integer, unable to parse string as an integer [type=int_parsing, input_value='16820740.40', input_type=str]
    For further information visit https://errors.pydantic.dev/2.10/v/int_parsing
samples.3.temp
  Field required [type=missing, input_value={'t': 1739630700, 'counte...x': '642', 'min': '244'}, input_type=dict]
    For further information visit https://errors.pydantic.dev/2.10/v/missing
samples.3.counter
  Input should be a valid integer, unable to parse string as an integer [type=int_parsing, input_value='16820837.87', input_type=str]
    For further information visit https://errors.pydantic.dev/2.10/v/int_parsing
samples.4.temp
  Field required [type=missing, input_value={'t': 1739631600, 'counte...x': '472', 'min': '221'}, input_type=dict]
    For further information visit https://errors.pydantic.dev/2.10/v/missing
samples.4.counter
  Input should be a valid integer, unable to parse string as an integer [type=int_parsing, input_value='16820922.26', input_type=str]
    For further information visit https://errors.pydantic.dev/2.10/v/int_parsing
samples.5.temp
  Field required [type=missing, input_value={'t': 1739632500, 'counte...': '2332', 'min': '252'}, input_type=dict]
    For further information visit https://errors.pydantic.dev/2.10/v/missing
samples.5.counter
  Input should be a valid integer, unable to parse string as an integer [type=int_parsing, input_value='16821375.83', input_type=str]
    For further information visit https://errors.pydantic.dev/2.10/v/int_parsing
samples.6.temp
  Field required [type=missing, input_value={'t': 1739633400, 'counte...': '3565', 'min': '237'}, input_type=dict]
    For further information visit https://errors.pydantic.dev/2.10/v/missing
samples.6.counter
  Input should be a valid integer, unable to parse string as an integer [type=int_parsing, input_value='16821805.30', input_type=str]
    For further information visit https://errors.pydantic.dev/2.10/v/int_parsing
samples.7.temp
  Field required [type=missing, input_value={'t': 1739634300, 'counte...': '5482', 'min': '237'}, input_type=dict]
    For further information visit https://errors.pydantic.dev/2.10/v/missing
samples.7.counter
  Input should be a valid integer, unable to parse string as an integer [type=int_parsing, input_value='16822153.53', input_type=str]
    For further information visit https://errors.pydantic.dev/2.10/v/int_parsing
samples.8.temp
  Field required [type=missing, input_value={'t': 1739635200, 'counte...': '1704', 'min': '237'}, input_type=dict]
    For further information visit https://errors.pydantic.dev/2.10/v/missing
samples.8.counter
  Input should be a valid integer, unable to parse string as an integer [type=int_parsing, input_value='16822363.55', input_type=str]
    For further information visit https://errors.pydantic.dev/2.10/v/int_parsing
samples.9.temp
  Field required [type=missing, input_value={'t': 1739636100, 'counte...': '1911', 'min': '236'}, input_type=dict]
    For further information visit https://errors.pydantic.dev/2.10/v/missing
samples.9.counter
  Input should be a valid integer, unable to parse string as an integer [type=int_parsing, input_value='16822519.38', input_type=str]
    For further information visit https://errors.pydantic.dev/2.10/v/int_parsing
samples.10.temp
  Field required [type=missing, input_value={'t': 1739637000, 'counte...x': '572', 'min': '224'}, input_type=dict]
    For further information visit https://errors.pydantic.dev/2.10/v/missing
samples.10.counter
  Input should be a valid integer, unable to parse string as an integer [type=int_parsing, input_value='16822604.74', input_type=str]
    For further information visit https://errors.pydantic.dev/2.10/v/int_parsing)

From What I can tell it finds the devices, but then It can’t connect them with HA.

Thanks for the help

PS Im running 2.1.0

@franciscohorta and @elgrajo could you please raise an issue at GitHub · Where software is built , it will be easier to discuss :slight_smile:

Hi there. Thank you. Already sent the info there.

1 Like

Hello everyone
I’ve made a new release of the integration.
You can see here the full changes : Release v2.1.1 · ajtudela/hass-smartbox · GitHub
If you have any issue do not hesitate to create one in github
Cheers :raised_hands:

2 Likes

Hi Delmael

Thanks for your work on this

Can you tell if this custom integration works with climastar heaters, which are similar to Haverland, just another server?
The old version by graham used to work…

I also have some difficulty setting it up, missing what is needed in config.yaml…

Or my tired brain must have missed that…

TIA
Diego

Hi @Alien8
Yes this integration work with climastar and you do not need anymore to add some line in config.yaml
Everything go through the config UI.
Do not forget to set this link in HACS GitHub - ajtudela/hass-smartbox: Home Assistant integration for Haverland heating smartboxes instead of the one from graham :smile:

1 Like

It works correctly with Elnur, and even detects the energy meters I have in the electrical panel.

The current power of the meters gives me negative. I would like to know if there is any way to change the sign without changing the clamp in the electrical panel. The problem is that the total and historical consumption of each meter also gives me negative because of that. On the manufacturer’s web/app, in my case Elnur, there is the option to change the sign of the current direction and all the current power values ​​and the historical consumption are positioned. Because although I change the direction of the meter clamp in the electrical panel the historical consumption will remain negative in integration. The solution I think would be inplementing the change of sign in integration as in the manufacturer’s app.

Hi Delmael, this looks fantastic!

Unfortunately, when I try to set it up I see my reseller is not listed and none of the others work with my log in details.

Is there any possibility of getting the company Lucht-LHZ added to the integration?

As far as I can tell it’s just another version of the same smartbox and app.

Happy to log a request or provide more info on Github if you can point me in the right direction.

Thank you!

Hello @Errecatro
There is an existing issue about the negative consumption : Energy card · Issue #28 · ajtudela/hass-smartbox · GitHub
The updates are here :slight_smile:

1 Like

Hello @Magick_Hattus
Did you tried the Technotherm resailer ?
You can see here the process to ask to add a new resailer
See you there :wink:

Hello everyone
I’ve juste release a new version which should fix the negative consumption.
If you still have the bug, report it here
Thanks