Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[siemenshvac] Initial contribution - interface (OZW672) #14263

Open
wants to merge 173 commits into
base: main
Choose a base branch
from

Conversation

lo92fr
Copy link

@lo92fr lo92fr commented Jan 22, 2023

Title

Add a binding for siemens Hvac interface (OZW672)

Description

This pull request is about adding a binding for siemens Hvac interface OZW672 (https://hit.sbt.siemens.com/RWD/app.aspx?rc=FR&lang=fr&module=Catalog&action=ShowProduct&key=BPZ:OZW672.01)

The OZW672 is a ethernet bridge for the LSB bus of Hvac device.
It implements a web interface that enable reading and setting of differents hvac parameters.
OZW672 also support a REST api.

This binding use this REST api to integrate OZW672 into openhab.

Testing

The binding support autodiscovery of the OZW672 interface using upnp.
After a few minutes, you should see the OZW672 bridge into your Inbox.
If not, power off and up OZW672.
You can also add the bridge manually.

After adding the bridge, you will have to go to bridge parameters, setting the password for the OZW672, and then restart openhab.
On restart, OZW672 will do autodiscovery phase from you installation during initialization.
This can be a little long : ~2 to 5 minutes depending of your installation.

After OZW672 bridge come up again, go back again to the "things" page of openhab.
Click on the add button, then click on the "siemensHvac" binding, and on the next page click on the "scan" button.
After a few second, openhab should list all you devices connect to the LSB bus.
If you have a simple home Hvac installation, it will generally find only one device.
Most common name for this device are something like "RVS41xxx.yyy".
This device represents the main controler inside your Hvac device.

After you add this RVS to your system, you can go into it, and Channels tabs will expose all your hvac settings.
Structure of the Channels should be the same as the one on the LCD screen of your Hvac device.
You may have a lot more of items that on your LCD screen because the device exposte all items, even the one for "specialist" guys.

@lo92fr lo92fr requested a review from a team as a code owner January 22, 2023 19:28
@lo92fr lo92fr force-pushed the 14262-siemensHvac branch 2 times, most recently from dc1076f to 737f2f3 Compare January 22, 2023 19:41
@lo92fr
Copy link
Author

lo92fr commented Jan 22, 2023

Hello,

Not sure to understand the error message on the build.
The compilation is working on my side, if you can give me some advice about this error.

@lsiepel lsiepel changed the title Add a binding for siemens Hvac interface (OZW672) [siemenshvac] Initial contribution - interface (OZW672) Jan 22, 2023
@lsiepel lsiepel added new binding If someone has started to work on a binding. For a new binding PR. rebuild Triggers Jenkins PR build and removed rebuild Triggers Jenkins PR build labels Jan 22, 2023
@lsiepel
Copy link
Contributor

lsiepel commented Jan 23, 2023

Hope the rebuild helps, don't see anything obvious wrong with the POM etc. You might want to look at the readme.md and the i18n files as they seem to be just the placeholders.

@lsiepel lsiepel linked an issue Jan 24, 2023 that may be closed by this pull request
Copy link
Contributor

@clinique clinique left a comment

Choose a reason for hiding this comment

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

Partial review

Copy link
Contributor

@clinique clinique left a comment

Choose a reason for hiding this comment

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

Partial review.

@lo92fr
Copy link
Author

lo92fr commented Jan 24, 2023

Hello Gael,

Thanks for your review.
I've just updated the pull request with the requested modifications.

Laurent.

@lo92fr lo92fr force-pushed the 14262-siemensHvac branch 2 times, most recently from bc727ff to 66445a4 Compare January 24, 2023 18:50
@lo92fr
Copy link
Author

lo92fr commented Jan 24, 2023

I also manage to fix the build.
Was missing a reference in bom/openhab-addons/pom.xml.

Laurent.

Copy link
Contributor

@clinique clinique left a comment

Choose a reason for hiding this comment

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

Second review

@freichen
Copy link

freichen commented Apr 4, 2023

@lo92fr Amazing binding - thank you ! I tested it with an OZW672.01 connected to a RVP350 and the only issue I found was that Enumeration channels are auto-discovered as Number - for example:

image

@lo92fr
Copy link
Author

lo92fr commented Apr 16, 2023

hannels are auto-discovered as Number - for example:

Hello Freichen,

Not sure what are the good way to fix this.
Do you have some guidlines, or some other example binding I can look to fix this.

@lo92fr
Copy link
Author

lo92fr commented Apr 16, 2023

Hello Gaël,

@clinique : I'm not sure what are the current state of this pull request.
Do you wait more change from my side ?

@larnalcegid
Copy link

Hello,

Can some one can give an update about the integration of this pull request in main stream.

Thanks,
Laurent.

@larnalcegid
Copy link

@lo92fr Amazing binding - thank you ! I tested it with an OZW672.01 connected to a RVP350 and the only issue I found was that Enumeration channels are auto-discovered as Number - for example:

image

I've commit a fix for this, should be working as excepted now.

@larnalcegid
Copy link

Hello Gaël, Hello Freichen,

Any update on this ?
Let me know if any more changed is need.

Laurent.

@lo92fr
Copy link
Author

lo92fr commented May 7, 2024

@lo92fr - I see a few commits here and there, but I haven't seen you respond to any of my comments for months. I'm starting to wonder if you somehow got into a state where your own responses by GitHub are considered as a review comments not yet submitted? See https://github.com/orgs/community/discussions/10369

Hello Jacob,

Yes, sorry for this. I have miss the step of submiting the review, so you don't see my comment.
It explains why you ask me many time to complete the review !

I do it this morning, so you shoudl see them now (please confirm if it's ok now).
I will also do a pass this morning to verify if there is some unresolved comment.

Thks,
Laurent.

lo92fr added 6 commits May 7, 2024 11:36
Signed-off-by: Laurent ARNAL <laurent@clae.net>
Signed-off-by: Laurent ARNAL <laurent@clae.net>
Signed-off-by: Laurent ARNAL <laurent@clae.net>
Signed-off-by: Laurent ARNAL <laurent@clae.net>
Signed-off-by: Laurent ARNAL <laurent@clae.net>
Signed-off-by: Laurent ARNAL <laurent@clae.net>
Copy link
Author

@lo92fr lo92fr left a comment

Choose a reason for hiding this comment

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

I finish the review on my side

Signed-off-by: Laurent ARNAL <laurent@clae.net>
Copy link
Contributor

@jlaur jlaur left a comment

Choose a reason for hiding this comment

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

I have checked most comment resolutions with some follow-ups on some of them, and a few new comments.


return new DateTimeType(zdt);
} catch (ParseException ex) {
}
Copy link
Contributor

@jlaur jlaur May 7, 2024

Choose a reason for hiding this comment

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

If you throw the exception after the for loop, you will know that parsing failed for all formats.

result = result.replaceAll("\\p{M}", "");
}

result = result.replace(' ', '_');
Copy link
Contributor

Choose a reason for hiding this comment

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

My suggestion was specifically for the line where it was put, i.e. line 51 just after the normalization. It was meant to replace the lines below.

Copy link
Contributor

@jlaur jlaur left a comment

Choose a reason for hiding this comment

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

I'm working my way through all the files, only a few left. I have posted many minor comments, but also a few crucial ones about the model.

At this point I think it would help me if you could post screenshots of a few Things and corresponding channels to gain more understanding of the results of the dynamic creation of everything.

controlBoilerApproval | Set Boiler Approval (`AUTO`, `OFF`, `ON`) | String | | | R/W | true
controlProgram | Set Program (`OFF`, `NORMAL`, `WARMWATER`, `MANUAL`) | String | | | R/W | true
Copy link
Contributor

Choose a reason for hiding this comment

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

These documented channels do not comply to the naming convention - are they auto-generated like that?

Comment on lines +43 to +44
Number num = (quantityType);
valUpdate = num.doubleValue();
Copy link
Contributor

Choose a reason for hiding this comment

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

Is this the converter used for temperatures? It seems that units are stripped here, is that intentional? I suspect that temperatures are supported based on the README examples and this SiemensHvacMetadataRegistryImpl.getCategory:

        } else if (dptUnit.contains("°C")) {

Copy link
Author

Choose a reason for hiding this comment

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

Yes, it is used for temperature.
I'm just handling it as a number as we already attach the unit to the meta data description of the ChannelType (see screenshoot below).

So i'm not sure we need to handle it one more time at this place, even if the API returns the unit as a separate field when reading the value.

image

image

image

Copy link
Contributor

@jlaur jlaur May 14, 2024

Choose a reason for hiding this comment

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

For UoM support you would need to add dimension, i.e. Number:Temperature. This will allow the framework to convert to any temperature measurement unit. If you link a Number:Temperature item with unit °F to the Number channel without dimension, the result will be 14 °F for the example above, which is not expected. The binding needs to inform the framework about the unit.

For a Number:Temperature channel, you can update with QuantityType rather than DecimalType. Since the API actually carries the unit, you can even supply this directly when creating the QuantityType. Then the API could even start serving °F, and your item above would still be updated with °C (with correct conversion).

Comment on lines 73 to 61
public static final String CATEGORY_CHANNEL_PROPS_TEMP = "Temperature";
public static final String CATEGORY_CHANNEL_PROPS_TIME = "Time";

public static final String CATEGORY_CHANNEL_CONTROL_HEATING = "Heating";
Copy link
Contributor

Choose a reason for hiding this comment

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

Why are these named differently than the ones above ("WIDGETS" vs. "PROPS")?

Copy link
Author

Choose a reason for hiding this comment

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

no good reason, i changed them

Copy link
Contributor

Choose a reason for hiding this comment

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

CATEGORY_CHANNEL_CONTROL_HEATING is still without "WIDGETS", but perhaps it is better to drop that from all names?

Signed-off-by: Laurent ARNAL <laurent@clae.net>
Signed-off-by: Laurent ARNAL <laurent@clae.net>
Signed-off-by: Laurent ARNAL <laurent@clae.net>
Signed-off-by: Laurent ARNAL <laurent@clae.net>
@lo92fr
Copy link
Author

lo92fr commented May 14, 2024

Hello Jacob (@jlaur ),

I commit a bunch of fixes this morning about your last review.
I also see your question about screenshoot f the discovered things.
So I've put some screenshoot and explanation on your comment.
Tell me if it's sufficient, or if you're need more explanation.

Laurent.

Signed-off-by: Laurent ARNAL <laurent@clae.net>
Signed-off-by: Laurent ARNAL <laurent@clae.net>
@lo92fr
Copy link
Author

lo92fr commented May 14, 2024

Freichen

Hello @freichen,

I don't know if you see my last message (#14263 (comment)).
Do you have the time to verify if removing the json fix the issue ?

Thanks,
Laurent.

Signed-off-by: Laurent ARNAL <laurent@clae.net>
result = result.replaceAll("\\p{M}", "");
}

result = result.replaceAll("[^a-zA-Z0-9_]", "_").toLowerCase();
Copy link
Contributor

@jlaur jlaur May 14, 2024

Choose a reason for hiding this comment

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

I might have made a mistake in a previous suggestion based on the logic being replaced rather than the naming convention:

Suggested change
result = result.replaceAll("[^a-zA-Z0-9_]", "_").toLowerCase();
result = result.replaceAll("[^a-zA-Z0-9-]", "-").toLowerCase();

(not sure if "-" needs to be escaped, i.e. "[^a-zA-Z0-9\-]")

xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd">

<!-- Bridge Thing Type -->
<bridge-type id="ozw672">
Copy link
Contributor

Choose a reason for hiding this comment

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

I was thinking about #14263 (comment) on my way to work and to provide some additional context. I then came also to think about the bridge type id. If the binding also works with OZW772.x, or might be brought to work with that as well, probably this id is too specialized. I'm thinking about two possible scenarios:

  • OZW772.x is very different code-wise and a new bridge type would have to be introduced.
  • OZW772.x is very similar code-wise, and it can be tweaked to work with the same bridge type, perhaps with some different configuration.

If actually it is expected to be similar, it would be strange to create a bridge type ozw672 for a OZW772.

My proposal in this case would be to rename to a more generic name, perhaps the common denominator "ozw"?

try {
c.add(new URI(baseUri), cookie);
} catch (URISyntaxException ex) {
throw new SiemensHvacException(String.format("URI is not correctly formated: %s", baseUri), ex);
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
throw new SiemensHvacException(String.format("URI is not correctly formated: %s", baseUri), ex);
throw new SiemensHvacException(String.format("URI is not correctly formatted: %s", baseUri), ex);

updateStatus(ThingStatus.ONLINE);
} catch (SiemensHvacException ex) {
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
String.format("@text/offline.error-gateway-init", ex.getMessage()));
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
String.format("@text/offline.error-gateway-init", ex.getMessage()));
"@text/offline.error-gateway-init[\"" + ex.getMessage() + "\"]");

See corresponding comment for the I18N text.

offline.waiting-bridge-initialization = Waiting bridge initialization, reading metadata in background

offline.baseurl-mandatory = baseUrl is mandatory on configuration !
offline.error-gateway-init = Error occurs during gateway initialization: %s
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
offline.error-gateway-init = Error occurs during gateway initialization: %s
offline.error-gateway-init = Error occurred during gateway initialization: {0}


offline.waiting-bridge-initialization = Waiting bridge initialization, reading metadata in background

offline.baseurl-mandatory = baseUrl is mandatory on configuration !
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
offline.baseurl-mandatory = baseUrl is mandatory on configuration !
offline.baseurl-mandatory = baseUrl is mandatory on configuration.

public interface SiemensHvacConnector {

@Nullable
String doBasicRequest(String uri) throws Exception;
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
String doBasicRequest(String uri) throws Exception;
String doBasicRequest(String uri) throws SiemensHvacException;

}
}
}
} catch (Exception e) {
Copy link
Contributor

Choose a reason for hiding this comment

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

You can either wrap the exception from doBasicRequest:

Suggested change
} catch (Exception e) {
} catch (SiemensHvacException e) {

Or not catch it at all, letting the original exception be thrown to the caller of this method.

I don't think there are any other exceptions to handle here?

}

LocalDateTime parsedDate = LocalDateTime.parse(value.getAsString(),
formatterBuilder.toFormatter(Locale.FRENCH));
Copy link
Contributor

Choose a reason for hiding this comment

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

Is this product only for the French market, or why do you need hardcoded French Locale here? Can you configure the OZW webserver language - if yes, how will such a change affect this method?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
new binding If someone has started to work on a binding. For a new binding PR.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add a binding for siemens Hvac interface (OZW672)
8 participants