Skip to content
This repository has been archived by the owner on May 7, 2020. It is now read-only.

[OpenWeatherMap] Initial contribution of OpenWeatherMap binding #5694

Merged
merged 1 commit into from
Nov 14, 2018
Merged

[OpenWeatherMap] Initial contribution of OpenWeatherMap binding #5694

merged 1 commit into from
Nov 14, 2018

Conversation

cweitkamp
Copy link
Contributor

@cweitkamp cweitkamp commented Jun 7, 2018

Initial contribution of OpenWeatherMap binding. See https://openweathermap.org/api. Valid candidate for #5659.

TODOs after merging:

Any kind of feedback will be very much appreciated.

Beta version:

Signed-off-by: Christoph Weitkamp github@christophweitkamp.de

@openhab-bot
Copy link
Contributor

This pull request has been mentioned on openHAB Community. There might be relevant details there:

https://community.openhab.org/t/announcing-openweathermap-binding-for-eclipse-smarthome-openhab/46420/1

@cweitkamp cweitkamp changed the title [WIP][OpenWeatherMap] Initial contribution of OpenWeatherMap binding [OpenWeatherMap] Initial contribution of OpenWeatherMap binding Jun 21, 2018
@9037568
Copy link
Contributor

9037568 commented Jun 23, 2018

A question, if I may.

What's the advantage in declaring an item like this:

<item-type>Number:Dimensionless</item-type>

instead of like this?

<item-type>Number</item-type>

@jaywiseman1971
Copy link

I'm using your OpenWeatherMap API on a Synology NAS OH2.3 and it works SO much better than the Weather binding that comes with OH2.3, thank you for your work!

The only issue I'm having is when I clear my cache and tmp directories; you binding isn't installed anymore and I have re-install it from the market place.

Any suggestions?

Best, Jay

@cweitkamp
Copy link
Contributor Author

@jaywiseman1971 Thank you very much for your feedback.

Did you see this post in the community forum? It maybe helps with your issue.

@jaywiseman1971
Copy link

jaywiseman1971 commented Jul 13, 2018

Hi Christoph,

That didn't work; here's the lines of code I added to /services/addon.cfg which worked for others in the file just not yours.

Is it possible for you to post the JAR so I can manually add it to ADDON directory instead so I don't have to manually add it when I clear the CACHE and TMP directories?

Access Remote Add-on Repository

Defines whether the remote openHAB add-on repository should be used for browsing and installing add-ons.

This not only makes latest snapshots of add-ons available, it is also required for the installation of

any legacy 1.x add-on. (default is true)

remote = true

A comma-separated list of bindings to install (e.g. "binding = sonos,knx,zwave")

binding = sonos,zwave,mail,airquality,caldav-command1,caldav-personal1,nest,network,ntp,onkyo,plex1.samsungtv,weather1,wemo

A comma-separated list of UIs to install (e.g. "ui = basic,paper")

ui = basic,paper,habpanel

A comma-separated list of persistence services to install (e.g. "persistence = rrd4j,jpa")

persistence = rrd4j

A comma-separated list of actions to install (e.g. "action = mail,pushover")

action = mail

A comma-separated list of transformation services to install (e.g. "transformation = map,jsonpath")

transformation = javascript,jsonpath,map

A comma-separated list of miscellaneous services to install (e.g. "misc = myopenhab")

misc = market,openhabcloud

A comma-separated list of market extension to install (see https://marketplace.eclipse.org/)

market = binding-4126092 <-- this is your entry

Best, Jay

@cweitkamp
Copy link
Contributor Author

@jaywiseman1971 I am afraid I cannot help you very much regarding to the marketplace / addon.cfg topic. Please continue this discussion in the community forum.

You can find the link to the current *.jar file behind the "download" button next to the "question mark" button in the marketplace.

@jaywiseman1971
Copy link

Thank you; got the JAR and all is good now!

Best, Jay

@cweitkamp
Copy link
Contributor Author

From my side the code is ready for an initial review. One open item left: Optimize README.

@cweitkamp
Copy link
Contributor Author

I rebased to resolve merge conflicts.

Copy link
Contributor

@htreu htreu left a comment

Choose a reason for hiding this comment

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

Thanks @cweitkamp for this nicely done binding. I left some comments/remarks inline.

@@ -107,7 +107,7 @@ public boolean isReadOnly() {
/**
* Returns a list of predefined states with their label.
*
* @return a list of predefined states with their label
* @return ist of predefined states with their label
Copy link
Contributor

Choose a reason for hiding this comment

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

this actually looked better before

Bundle-Vendor: Eclipse.org/SmartHome
Bundle-Version: 0.10.0.qualifier
Export-Package:
org.eclipse.smarthome.binding.openweathermap,
Copy link
Contributor

Choose a reason for hiding this comment

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

In the latest bindings we decided not to export any packages if the binding is not meant to be extended by further bundles. This implies all packages/classes to be internal.

| apikey | API key to access the OpenWeatherMap API: https://home.openweathermap.org/users/sign_up. **Mandatory**. |
| refreshInterval | Specifies the refresh interval (in minutes). Optional, the default value is 60, the minimum value is 10. |
| language | Language to be used by the OpenWeatherMap API. Optional, valid values are: `ar`, `bg`, `ca`, `zh_cn`, `zh_tw`, `hr`, `cz`, `nl`, `en`, `fi`, `fr`, `gl`, `de`, `el`, `hu`, `it`, `ja`, `kr`, `la`, `lt`, `mk`, `fa`, `pl`, `pt`, `ro`, `ru`, `sk`, `sl`, `es`, `sw`, `tr`, `ua`, `vi`. |
| hourlyForecast | Read 3 hour forecast weather data from the OpenWeatherMap API. Optional, default value is `true`. |
Copy link
Contributor

Choose a reason for hiding this comment

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

what are hourlyForecast and dailyForecast parameters good for? Should the existing things for this bridge be considered when deciding which data to fetch?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

State state = UnDefType.UNDEF;
switch (channelId) {
case CHANNEL_TIME_STAMP:
state = getDateTimeTypeState(dailyForecastData.getList().get(count).getDt());
Copy link
Contributor

Choose a reason for hiding this comment

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

personal style: factoring out dailyForecastData.getList().get(count) may enhance readability.

State state = UnDefType.UNDEF;
switch (channelId) {
case CHANNEL_TIME_STAMP:
state = getDateTimeTypeState(hourlyForecastData.getList().get(count).getDt());
Copy link
Contributor

Choose a reason for hiding this comment

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

same with hourlyForecastData.getList().get(count)

OpenWeatherMapLocationDiscoveryService discoveryService = (OpenWeatherMapLocationDiscoveryService) bundleContext
.getService(serviceReg.getReference());
discoveryService.deactivate();
serviceReg.unregister();
Copy link
Contributor

Choose a reason for hiding this comment

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

also in the Hue binding I switched those two lines, so the service gets unregistered first, then deactivated. Although we had no real problems with the order it feels a bit more stable.

activate(null);
}

@Activate
Copy link
Contributor

Choose a reason for hiding this comment

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

Since this service is only created from the handler factory the annotation is not necessary.

super.modified(configProperties);
}

@Deactivate
Copy link
Contributor

Choose a reason for hiding this comment

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

Since this service is only created from the handler factory the annotation is not necessary.


@Modified
@Override
protected void modified(@Nullable Map<String, @Nullable Object> configProperties) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Since this method will not be called its obsolete.

ThingUID bridgeUID = bridgeHandler.getThing().getUID();
createWeatherResult(locationString, bridgeUID);
OpenWeatherMapAPIConfiguration config = bridgeHandler.getOpenWeatherMapAPIConfig();
if (config.getHourlyForecast() == Boolean.TRUE) {
Copy link
Contributor

Choose a reason for hiding this comment

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

maybe I understand now how those config params work: in the bridge config the user can decide if hourly and/or daily forecasts things should be discovered. In case one option is false auto discovery and data fetching get disabled.
But: when the daily forecast thing gets discovered, isn't it an option to just ignore the discovery result and decide data fetching by the existing things on the bridge?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@htreu Thank you for taking time to review the binding. Yes, I agree. It makes more sense. I cannot remember why I did it this was. Maybe I should rename those parameters to discoverHourlyForecast and discoverDailyForecast. The purpose should be clearer then.

Copy link
Contributor

Choose a reason for hiding this comment

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

See my comment on the description for both config parameters.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done.

Copy link
Contributor

@wborn wborn left a comment

Choose a reason for hiding this comment

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

Thanks for the binding! I'll probably also migrate to it from the WU Binding. I've added some minor comments below.

Can you also add null annotations to the remaining classes (where it is missing from) as much as possible? Partially annotated code can cause errors when people trust the compiler will always be there to save them from NPEs. 😉

this.apikey = apikey;
}

public Integer getRefreshIntervall() {
Copy link
Contributor

Choose a reason for hiding this comment

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

getRefreshIntervall -> getRefreshInterval

return refreshInterval;
}

public void setRefreshIntervall(Integer refreshInterval) {
Copy link
Contributor

Choose a reason for hiding this comment

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

setRefreshIntervall -> setRefreshInterval

}

@Nullable
public synchronized OpenWeatherMapJsonHourlyForecastData getHourlyForecastData(
Copy link
Contributor

Choose a reason for hiding this comment

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

Please annotate the result type with @Nullable instead (see Null Annotations Conventions).

}

@Nullable
public synchronized OpenWeatherMapJsonDailyForecastData getDailyForecastData(
Copy link
Contributor

Choose a reason for hiding this comment

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

Please annotate the result type with @Nullable instead (see Null Annotations Conventions).

# thing status
offline.conf-error-missing-apikey = The 'apikey' parameter must be configured.
offline.conf-error-invalid-apikey = Invalid API key. Please see https://openweathermap.org/faq#error401 for more info.
offline.conf-error-not-supported-refreshIntervall = The 'refreshIntervall' parameter must be at least 10 minutes.
Copy link
Contributor

Choose a reason for hiding this comment

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

offline.conf-error-not-supported-refreshIntervall -> offline.conf-error-not-supported-refreshInterval
refreshIntervall - > refreshInterval

# thing status
offline.conf-error-missing-apikey = Der Parameter 'API Schl�ssel' muss konfiguriert werden.
offline.conf-error-invalid-apikey = Ung�ltiger 'API Schl�ssel'. Mehr Infos unter https://openweathermap.org/faq#error401.
offline.conf-error-not-supported-refreshIntervall = Der Parameter 'Abfrageintervall' muss mindestens 10 min betragen.
Copy link
Contributor

Choose a reason for hiding this comment

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

offline.conf-error-not-supported-refreshIntervall -> offline.conf-error-not-supported-refreshInterval

}
if (config.getRefreshIntervall() != null && config.getRefreshIntervall() < 10) {
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
"@text/offline.conf-error-not-supported-refreshIntervall");
Copy link
Contributor

Choose a reason for hiding this comment

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

@text/offline.conf-error-not-supported-refreshIntervall -> @text/offline.conf-error-not-supported-refreshInterval

connection = new OpenWeatherMapConnection(this, httpClient);

if (refreshJob == null || refreshJob.isCancelled()) {
logger.debug("Start refresh job at intervall {} min.", config.getRefreshIntervall());
Copy link
Contributor

Choose a reason for hiding this comment

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

intervall -> interval

}

@Nullable
public synchronized OpenWeatherMapJsonWeatherData getWeatherData(OpenWeatherMapLocationConfiguration locationConfig)
Copy link
Contributor

Choose a reason for hiding this comment

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

Please annotate the result type with @Nullable instead (see Null Annotations Conventions).

@jaywiseman1971
Copy link

Hi Christoph,

Can I get the updated JAR for your new work?

Best, Jay

@cweitkamp
Copy link
Contributor Author

@jaywiseman1971 I uploaded the latest version in #5694 (comment).

@lolodomo
Copy link
Contributor

This merge will become urgent as the WU binding is apparently no more working.

Copy link
Contributor

@htreu htreu left a comment

Choose a reason for hiding this comment

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

I comment again on both of the discovery result parameter descriptions. I think it should be clearly stated that the "daily" thing is only available for paid subscriptions.

During testing I experienced the following: Despite my subscription being a free one, I added a "daily" thing to my bridge. This results in the "daily" thing to have status "OFFLINE, CONFIG_ERROR" but will also bring down the bridge and with it all other things.
Is it possible to only put the "daily" thing offline due to the invalid API key?


| Parameter | Description |
|-----------|-------------------------------------------------------------------------------------------------------------|
| location | Multiple syntaxes are supported. Please read the binding documentation for more information. **Mandatory**. |
Copy link
Contributor

Choose a reason for hiding this comment

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

Please read the binding documentation for more information.

while doing so I was invited to read the binding documentation for more information. I got caught in an infinite loop.

</parameter>
<parameter name="hourlyForecast" type="boolean">
<label>Access 3 Hour Forecast</label>
<description>Read 3 hour forecast weather data from the OpenWeatherMap API.</description>
Copy link
Contributor

Choose a reason for hiding this comment

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

The description sounds as if this will affect which information is retrieved from the API. But this does only toggle the discovery, and should prevent to discover "daily forecast" for a free account I guess?
Please update the description for both parameters to make this more clear.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done. Yes, it toggles discovery. I changed the description and clarified the documentation. I - hopefully - clearly stated in the section for the daily-forecast that it is only available for payed accounts.

ThingUID bridgeUID = bridgeHandler.getThing().getUID();
createWeatherResult(locationString, bridgeUID);
OpenWeatherMapAPIConfiguration config = bridgeHandler.getOpenWeatherMapAPIConfig();
if (config.getHourlyForecast() == Boolean.TRUE) {
Copy link
Contributor

Choose a reason for hiding this comment

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

See my comment on the description for both config parameters.

@cweitkamp
Copy link
Contributor Author

@htreu Thanks again for your review.

I looked into the bridge status handling and have optimized it.

@openhab-bot
Copy link
Contributor

This pull request has been mentioned on openHAB Community. There might be relevant details there:

https://community.openhab.org/t/announcing-openweathermap-binding-for-eclipse-smarthome-openhab/46420/101

Copy link
Contributor

@htreu htreu left a comment

Choose a reason for hiding this comment

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

The online/offline handling works nicely now, thanks. Have another look at the config description params, you accidentally changed the thing-type description. btw: are those even used anyway?

@@ -60,14 +60,14 @@ thing-type.openweathermap.weather.label = Wetterinformationen
thing-type.openweathermap.weather.description = Erm�glicht die Anzeige der aktuellen Wetterinformationen.

thing-type.openweathermap.hourly-forecast.label = 3 Stunden Wettervorhersage
thing-type.openweathermap.hourly-forecast.description = Erm�glicht die Anzeige einer 3 Stunden Wettervorhersage.
thing-type.openweathermap.hourly-forecast.description = Aktiviert / Deaktiviert die automatische Erstellung einer 3 Stunden Wettervorhersage.
Copy link
Contributor

Choose a reason for hiding this comment

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

I think in the heat of action you accidentally changed the wrong lines:

The

bridge-type.config.openweathermap.weather-api.hourlyForecast.description
...
bridge-type.config.openweathermap.weather-api.dailyForecast.description

are the ones describing the config parameter of the bridge.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

😓 Ups, in the lunch break between two meetings ... I am eager to get this finally merged ...

@cweitkamp
Copy link
Contributor Author

btw: are those even used anyway?

@htreu What do you mean? The thing-type description?

@htreu
Copy link
Contributor

htreu commented Sep 24, 2018

Yes. I didn't have a closer look. But the two parameters are only used on the bridge. So the description on the bridge-type should be sufficient.

@htreu
Copy link
Contributor

htreu commented Sep 25, 2018

Sorry, its just the label & description of the 3 hours forecast. Forget my last comment.

Copy link
Contributor

@htreu htreu left a comment

Choose a reason for hiding this comment

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

Thanks @cweitkamp, nice work!

Copy link
Contributor

@kaikreuzer kaikreuzer left a comment

Choose a reason for hiding this comment

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

I didn't look through the code, but had a short glance at the modelling side - so please allow me some comments/questions.

<parameter name="apikey" type="text" required="true">
<context>password</context>
<label>API Key</label>
<description>API key to access the OpenWeatherMap API: https://home.openweathermap.org/users/sign_up.</description>
Copy link
Contributor

Choose a reason for hiding this comment

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

do not add urls here

</parameter>
<parameter name="hourlyForecast" type="boolean">
<label>3 Hour Forecast</label>
<description>Enable / Disable discovery of the 3 hour forecast thing.</description>
Copy link
Contributor

Choose a reason for hiding this comment

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

"3 hour forecast thing" - sounds pretty weird (especially as a user facing text) and it feels as if there's something not ideal. You might have discussed the modelling with others already, so forgive me if you have to repeat it here. But imho it would make much more sense to have the forecasts being a part of the "weather" thing, but not a separate one for which you have to configure the location individually.

Copy link
Contributor Author

@cweitkamp cweitkamp Sep 25, 2018

Choose a reason for hiding this comment

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

I second your opinion on the description. I will think about it.

The way how I modeled bridges and things has not been discussed in detail with others yet. The idea behind my model is mainly based in the different forecast options provided by OWM and the underlying accounting / price model (The hourly forecast is free for everyone and the daily forecast restricted to payed accounts).
Additionally I am planning to do some extensions once this will have been merged. OWM provides UV Index, Air pollution and weather alerts too. I want to add them as new things too because I do not think that everyone needs them or is allowed to access them. Why overload one thing with channels / data which are not necessary?

Copy link
Contributor

Choose a reason for hiding this comment

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

Why overload one thing with channels / data which are not necessary?

Because Things are not a means to express a functional structure, but are the entities that can physically be added to a system and which can potentially provide many functionalities in one.

Certainly you should only add the channels to the Thing that really ARE available. So if it is a free account, the daily forecast channels would not be added. Btw, can this be determined automatically?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Btw, can this be determined automatically?

OWM does not expose any information about the account. I can try to ping the daily forecast API and evaluate the result to determine the details of the account. But we cannot say it for 100% sure.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

My current approach tries to request daily forecast data from the OWM API. If the request fails, all channel groups are removed from the thing and further request are omitted.

<label>Weather Station</label>
<description>This is a weather station.</description>
<channels>
<channel id="id" typeId="station-id" />
Copy link
Contributor

Choose a reason for hiding this comment

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

Can the id ever change dynamically? If not, this should be a property, not a channel.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Copy link
Contributor

Choose a reason for hiding this comment

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

Still, the id is a pretty technical information. Is there really a valid use case for it?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, you can call the weather / forecast data for one location either by geographic coordinates or by city id (which I am planning to implement in the future).


## Discovery

At first the auto-discovery will add an "OpenWeatherMap API" `weather-api` bridge.
Copy link
Contributor

Choose a reason for hiding this comment

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

This must not be discovered as you do not know whether the user has an account at all.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

That is something I do not understand. Why? We did the same in #5501.

Copy link
Contributor

Choose a reason for hiding this comment

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

That is something I do not understand. Why?

Because discovery should only discover what really exists. Imagine you and your spouse each have an OWM account. Which one do you discover? Imagine myself having no account? Which one did you discover? Discovery must not be misused as a shortcut to prompt users to manually create a thing of a certain type.

We did the same in #5501.

Did we? I can only see that it discovers the weather for the system location, once a bridge (=account) has been (manually) created.

If a system location is set, a "Local Weather" (`weather`) thing and a "Local 3 Hour Forecast" (`hourly-forecast`) thing will be automatically discovered for this location.
The thing for "Local Daily Forecast" will not be added by default (see `dailyForecast` parameter to enable it).

Auto-discovery is enabled by default.
Copy link
Contributor

Choose a reason for hiding this comment

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

This is not binding specific, hence it should not be specifically mentioned here. (see #6224)
Especially, there must not be any reference to openHAB here.

public class OpenWeatherMapLocationConfiguration {

private String location;
private Double altitude;
Copy link
Contributor

Choose a reason for hiding this comment

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

Double is not a good choice for precise values.

return altitude;
}

public OpenWeatherMapLocationConfiguration parseLocation() {
Copy link
Contributor

Choose a reason for hiding this comment

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

You should use PointType, which already provides everything you need.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I switched this logic to use existing features in f2eaef7. Thanks for the hint.

A question from my side which has not be solved in this PR: Is it possible to convert a config param with context location to PointType by the framework automatically? It seems to be a little overhead to parse the location String every time before doing a request.

Copy link
Contributor

Choose a reason for hiding this comment

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

No, this is not possible, because configurations only have the text, boolean of decimal values by definition. But filling the string into a PointType should not be much overhead. It only needs to be done once and not every time "before doing a request".

}
} catch (ExecutionException e) {
String errorMessage = e.getLocalizedMessage();
if (errorMessage.startsWith("org.eclipse.jetty.client.HttpResponseException")) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Does this have to be a string matching here? What is different about the 401 handling that you have in line 199 already?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is one of the most ugliest part I discovered during the implementation of the binding. Funny thing is once I try to request the OMW API with an invalid a API key I do not get a 401 Unauthorized status code but Jetty internally fails with an org.eclipse.jetty.client.HttpResponseException -> ExecutionException. The same request in a browser fails in the normal way returning a 401 Unauthorized status code. If you have any idea why or how to solve it in a better way your help is very much appreciated. Try it yourself:

https://api.openweathermap.org/data/2.5/forecast/daily?appid=12345&cnt=6&lon=25.782403&units=metric&lang=de&lat=-80.264563

Copy link
Contributor

Choose a reason for hiding this comment

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

What is the cause of the ExecutionException?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Here is a stack trace for the failing request:

2018-09-25 13:54:30.494 [TRACE] [.connection.OpenWeatherMapConnection] - Exception occurred during execution: org.eclipse.jetty.client.HttpResponseException: HTTP protocol violation: Authentication challenge without WWW-Authenticate header
java.util.concurrent.ExecutionException: org.eclipse.jetty.client.HttpResponseException: HTTP protocol violation: Authentication challenge without WWW-Authenticate header
	at org.eclipse.jetty.client.util.FutureResponseListener.getResult(FutureResponseListener.java:118) ~[?:?]
	at org.eclipse.jetty.client.util.FutureResponseListener.get(FutureResponseListener.java:101) ~[?:?]
	at org.eclipse.jetty.client.HttpRequest.send(HttpRequest.java:684) ~[?:?]
	at org.eclipse.smarthome.binding.openweathermap.internal.connection.OpenWeatherMapConnection.getResponse(OpenWeatherMapConnection.java:190) ~[?:?]
	at org.eclipse.smarthome.binding.openweathermap.internal.connection.OpenWeatherMapConnection.lambda$2(OpenWeatherMapConnection.java:182) ~[?:?]
	at org.eclipse.smarthome.core.cache.ExpiringCache.refreshValue(ExpiringCache.java:91) ~[?:?]
	at org.eclipse.smarthome.core.cache.ExpiringCache.getValue(ExpiringCache.java:61) ~[?:?]
	at org.eclipse.smarthome.core.cache.ExpiringCacheMap.get(ExpiringCacheMap.java:202) ~[?:?]
	at org.eclipse.smarthome.core.cache.ExpiringCacheMap.putIfAbsentAndGet(ExpiringCacheMap.java:133) ~[?:?]
	at org.eclipse.smarthome.core.cache.ExpiringCacheMap.putIfAbsentAndGet(ExpiringCacheMap.java:118) ~[?:?]
	at org.eclipse.smarthome.binding.openweathermap.internal.connection.OpenWeatherMapConnection.getResponseFromCache(OpenWeatherMapConnection.java:182) ~[?:?]
	at org.eclipse.smarthome.binding.openweathermap.internal.connection.OpenWeatherMapConnection.getDailyForecastData(OpenWeatherMapConnection.java:124) ~[?:?]
	at org.eclipse.smarthome.binding.openweathermap.internal.handler.OpenWeatherMapDailyForecastHandler.requestData(OpenWeatherMapDailyForecastHandler.java:56) ~[?:?]
	at org.eclipse.smarthome.binding.openweathermap.internal.handler.AbstractOpenWeatherMapHandler.updateData(AbstractOpenWeatherMapHandler.java:125) ~[?:?]
	at org.eclipse.smarthome.binding.openweathermap.internal.handler.OpenWeatherMapAPIHandler.updateThing(OpenWeatherMapAPIHandler.java:154) ~[?:?]
	at org.eclipse.smarthome.binding.openweathermap.internal.handler.OpenWeatherMapAPIHandler.lambda$2(OpenWeatherMapAPIHandler.java:121) ~[?:?]
	at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) [?:?]
	at java.util.concurrent.FutureTask.run(FutureTask.java:266) [?:?]
	at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:180) [?:?]
	at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293) [?:?]
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [?:?]
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [?:?]
	at java.lang.Thread.run(Thread.java:748) [?:?]
Caused by: org.eclipse.jetty.client.HttpResponseException: HTTP protocol violation: Authentication challenge without WWW-Authenticate header
	at org.eclipse.jetty.client.AuthenticationProtocolHandler$AuthenticationListener.onComplete(AuthenticationProtocolHandler.java:197) ~[?:?]
	at org.eclipse.jetty.client.ResponseNotifier.notifyComplete(ResponseNotifier.java:216) ~[?:?]
	at org.eclipse.jetty.client.ResponseNotifier.notifyComplete(ResponseNotifier.java:208) ~[?:?]
	at org.eclipse.jetty.client.HttpReceiver.terminateResponse(HttpReceiver.java:470) ~[?:?]
	at org.eclipse.jetty.client.HttpReceiver.responseSuccess(HttpReceiver.java:416) ~[?:?]
	at org.eclipse.jetty.client.http.HttpReceiverOverHTTP.messageComplete(HttpReceiverOverHTTP.java:316) ~[?:?]
	at org.eclipse.jetty.http.HttpParser.handleContentMessage(HttpParser.java:605) ~[?:?]
	at org.eclipse.jetty.http.HttpParser.parseContent(HttpParser.java:1675) ~[?:?]
	at org.eclipse.jetty.http.HttpParser.parseNext(HttpParser.java:1523) ~[?:?]
	at org.eclipse.jetty.client.http.HttpReceiverOverHTTP.parse(HttpReceiverOverHTTP.java:172) ~[?:?]
	at org.eclipse.jetty.client.http.HttpReceiverOverHTTP.process(HttpReceiverOverHTTP.java:135) ~[?:?]
	at org.eclipse.jetty.client.http.HttpReceiverOverHTTP.receive(HttpReceiverOverHTTP.java:73) ~[?:?]
	at org.eclipse.jetty.client.http.HttpChannelOverHTTP.receive(HttpChannelOverHTTP.java:133) ~[?:?]
	at org.eclipse.jetty.client.http.HttpConnectionOverHTTP.onFillable(HttpConnectionOverHTTP.java:155) ~[?:?]
	at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:281) ~[?:?]
	at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:102) ~[?:?]
	at org.eclipse.jetty.io.ssl.SslConnection.onFillable(SslConnection.java:291) ~[?:?]
	at org.eclipse.jetty.io.ssl.SslConnection$3.succeeded(SslConnection.java:151) ~[?:?]
	at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:102) ~[?:?]
	at org.eclipse.jetty.io.ChannelEndPoint$2.run(ChannelEndPoint.java:118) ~[?:?]
	at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.runTask(EatWhatYouKill.java:333) ~[?:?]
	at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.doProduce(EatWhatYouKill.java:310) ~[?:?]
	at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.tryProduce(EatWhatYouKill.java:168) ~[?:?]
	at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.run(EatWhatYouKill.java:126) ~[?:?]
	at org.eclipse.jetty.util.thread.ReservedThreadExecutor$ReservedThread.run(ReservedThreadExecutor.java:366) ~[?:?]
	at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:762) ~[?:?]
	at org.eclipse.jetty.util.thread.QueuedThreadPool$2.run(QueuedThreadPool.java:680) ~[?:?]
	... 1 more

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Just to make clear: The same request with a valid API key works like a charm.

Copy link
Contributor

Choose a reason for hiding this comment

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

My point has been: Shouldn't we check the e.g. the cause using instanceof instead of check the message string?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I get it. You mean we should replace

if (errorMessage.startsWith("org.eclipse.jetty.client.HttpResponseException")) {
...

with

if (e.getCause() instanceof HttpResponseException) {
...

That is nice and should work too.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

@kaikreuzer
Copy link
Contributor

@cweitkamp Thanks for your updates - are you done with everything and the PR is ready for a final review round?

@cweitkamp
Copy link
Contributor Author

cweitkamp commented Oct 15, 2018

@kaikreuzer No, unfortunately not. The main part - redesign of things for current weather and forecast - is still in progress.

@cweitkamp
Copy link
Contributor Author

@kaikreuzer @htreu I finalized my work. I hope I have catched everything. The binding is back in a stable mode and ready for a follow-up review. Thanks in advance.

Copy link
Contributor

@htreu htreu left a comment

Choose a reason for hiding this comment

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

Just a quick 2nd round with the new architecture. The code looks pretty good, just minor text stuff and one conceptual question so far.

Thanks @cweitkamp.

channel-type.openweathermap.forecasted-rain.description = Zeigt den vorhergesagten, kumulierten Regen der n�chsten drei Stunden an.

channel-type.openweathermap.snow.label = Schnee
channel-type.openweathermap.snow.description = Zeigt den kumulierten Schnee der n�chsten drei Stunden an.
Copy link
Contributor

Choose a reason for hiding this comment

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

"der nächsten drei Stunden" oder hier "der letzten drei Stunden"?

<channel-type id="forecasted-snow">
<item-type>Number:Length</item-type>
<label>Forecasted Snow</label>
<description>Forecasted snow volume for the last 3 hours.</description>
Copy link
Contributor

Choose a reason for hiding this comment

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

this one should be "for the next 3 hours."

| forecastHours03, forecastHours06, ... forecastHours120 | wind-direction | Number:Angle | Forecasted wind direction. |
| forecastHours03, forecastHours06, ... forecastHours120 | gust-speed | Number:Speed | Forecasted gust speed. **Advanced** |
| forecastHours03, forecastHours06, ... forecastHours120 | cloudiness | Number:Dimensionless | Forecasted cloudiness. |
| forecastHours03, forecastHours06, ... forecastHours120 | rain | Number:Length | Expected rain volume of a day. |
Copy link
Contributor

Choose a reason for hiding this comment

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

expected volume for the next 3 hours

| forecastHours03, forecastHours06, ... forecastHours120 | gust-speed | Number:Speed | Forecasted gust speed. **Advanced** |
| forecastHours03, forecastHours06, ... forecastHours120 | cloudiness | Number:Dimensionless | Forecasted cloudiness. |
| forecastHours03, forecastHours06, ... forecastHours120 | rain | Number:Length | Expected rain volume of a day. |
| forecastHours03, forecastHours06, ... forecastHours120 | snow | Number:Length | Expected snow volume of a day. |
Copy link
Contributor

Choose a reason for hiding this comment

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

expected volume for the next 3 hours

configValid = false;
}

if (configValid) {
Copy link
Contributor

Choose a reason for hiding this comment

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

In initialization you dynamically create the channel groups for hourly and daily forecasts as defined in the config. Why are hourly forecast channels 03 - 24 predefined in the thing-type xml? Same for daily forecast channels 2 - 6?

Copy link
Contributor Author

@cweitkamp cweitkamp Oct 31, 2018

Choose a reason for hiding this comment

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

My initial idea was to have those channel groups by default and only change them dynamically if the user changes the thing configuration. Thus I had implemented a logic inside the handleConfigurationUpdate() method. But that did not work because when I tried to configure the things via textual configuration with different numbers of forecasted hours / days the method never had been triggered - which leads to a wrong count of channel groups. Afterwards I moved the logic to the initialization of the thing.

To be honest I do not think that it is the best way how to solve it. But for now I have no better solution in my mind. Maybe you have an idea how to do it?

So in general we now can remove them from the thing type definition.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Like every time - once you start talking about it the idea starts to develop inside your mind.

I reworked the dynamically handling. Now only new channels will be added or superflous will be removed. This way the predefined ones in the thing-type xml as default makes sense again.

@cweitkamp
Copy link
Contributor Author

Done. Thanks.

@lolodomo
Copy link
Contributor

lolodomo commented Nov 2, 2018

The WU binding will become useless first of January 2019. So we need this binding available in snapshots before the end of the year.

@kaikreuzer
Copy link
Contributor

The WU binding will become useless first of January 2019.

This is not said - the notification from WU told a lot about "stay tuned" and "apis for non-commercial developers"...

But I think if you have a look at the progress of this PR, there is no doubt that it'll be finished soon, even without pushing anybody ;-)

Copy link
Contributor

@kaikreuzer kaikreuzer left a comment

Choose a reason for hiding this comment

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

lgtm, thanks!
@htreu I leave the final feedback to you - if everything is fine, @cweitkamp should squash the commits and we can create a CQ for it.

Copy link
Contributor

@htreu htreu 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 this contribution @cweitkamp, nice work!

Please squash your commits so we can issue the CQ for IP check.

Signed-off-by: Christoph Weitkamp <github@christophweitkamp.de>
@cweitkamp
Copy link
Contributor Author

I am finished. Thanks everyone.

@htreu htreu added the CQ label Nov 7, 2018
@htreu
Copy link
Contributor

htreu commented Nov 7, 2018

FTR: CQ18113 created.

@kaikreuzer
Copy link
Contributor

CQ has been approved!

@kaikreuzer kaikreuzer merged commit 75305c1 into eclipse-archived:master Nov 14, 2018
@cweitkamp cweitkamp deleted the feature-openweathermap-binding branch November 14, 2018 18:01
@cweitkamp
Copy link
Contributor Author

Great! Thank you very much. 👍

@kaikreuzer
Copy link
Contributor

@cweitkamp I just tried to release a new ESH stable, but the build failed due to this binding - could you please have a look at https://ci.eclipse.org/smarthome/job/SmartHomeDistribution-Stable/312/console?

@cweitkamp
Copy link
Contributor Author

@kaikreuzer will be fixed with #6521.

@woanne67
Copy link

First thank you for your development work. I've been trying to make the openweather binding work for a few days now. The integration of the org.eclipse.smarthome.binding.openweathermap-0.10.0-SNAPSHOT.jar worked so far. I had a free OWM API generated and could receive data with the account binding. Unfortunately this only worked once. Afterwards the data was not updated anymore. The status of the OWM account changed to Unknown. Now I can't receive any more data.
Also the test on a Raspi with openHAB 2.4.0#1427 and the 2.4.0 OWM-Binding does not work.
Do you have an idea how I can bring the account setting back to life?

The events.log

2018-11-15 21:11:48.058 [hingStatusInfoChangedEvent] - 'openweathermap:weather-and-forecast:6b382647:local' changed from UNINITIALIZED (BRIDGE_UNINITIALIZED) to INITIALIZING
2018-11-15 21:11:48.060 [hingStatusInfoChangedEvent] - 'openweathermap:weather-and-forecast:6b382647:local' changed from INITIALIZING to UNKNOWN
2018-11-15 21:11:48.099 [hingStatusInfoChangedEvent] - 'openweathermap:weather-and-forecast:6b382647:local' changed from UNKNOWN to UNINITIALIZED (HANDLER_INITIALIZING_ERROR): org.eclipse.smarthome.core.thing.Thing.getChannelsOfGroup(Ljava/lang/String;)Ljava/util/List;
2018-11-15 21:12:03.650 [me.event.ThingUpdatedEvent] - Thing 'openweathermap:weather-and-forecast:6b382647:local' has been updated.
2018-11-15 21:12:03.750 [me.event.ThingUpdatedEvent] - Thing 'openweathermap:weather-and-forecast:6b382647:local' has been updated.

@cweitkamp
Copy link
Contributor Author

@woanne67 May I ask you to use code fences for your log abstract (three backticks before and after the data)? Thanks.

If I understood correctly you did two tests on different OH2 versions. Which test/version belongs to this log? Can you please clarify?

@woanne67
Copy link

@cweitkamp Yes, after I read here that it also works under OH2.3 on a Synology I installed the OWM binding there and it ran exactly once. For test purposes I installed OH2.4 on a Raspi.
I checked the Thing "Weather and Forecast" again this morning, checked the Bridge settings again, then changed the status of both installations to Online. A 5 days forecast configuration on the OH2.3 ended with an Error 500 - reqest failed.
Now the status of the Thing "weather and forecast" is unknown again.It seems that the system doesn't like a forecast longer than 24 hours (maybe it depends on the Free API of OWM).
I have one more question. How can I embed the icons as a background image in a widget (HABPanel)? I could also need help with that. Thank you.

@cweitkamp
Copy link
Contributor Author

A 5 days forecast configuration on the OH2.3 ended with an Error 500 - reqest failed.

@woanne67 Is it possible to append a log extract for that situation? That would be nice.

For the rest of your issue I do not see a technical reason. May I ask you to continue our discussion in the community forum. Thanks.

@woanne67
Copy link

Changed the OH2.3 OWM-Config from 0 to 3 days forecast:

image

After saving the settings:

image

The status changed from online to unknown:

image

event.log

2018-11-17 12:04:11.660 [me.event.ThingUpdatedEvent] - Thing 'openweathermap:weather-and-forecast:6b382647:local' has been updated. 2018-11-17 12:04:11.685 [hingStatusInfoChangedEvent] - 'openweathermap:weather-and-forecast:6b382647:local' changed from ONLINE to UNKNOWN
openhab.log

2018-11-17 12:04:11.658 [WARN ] [eclipse.jetty.servlet.ServletHandler] - javax.servlet.ServletException: org.glassfish.jersey.server.ContainerException: java.lang.NoSuchMethodError: org.eclipse.smarthome.core.thing.Thing.getChannelsOfGroup(Ljava/lang/String;)Ljava/util/List; at org.glassfish.jersey.servlet.WebComponent.serviceImpl(WebComponent.java:489) [167:org.glassfish.jersey.containers.jersey-container-servlet-core:2.22.2] at org.glassfish.jersey.servlet.WebComponent.service(WebComponent.java:427) [167:org.glassfish.jersey.containers.jersey-container-servlet-core:2.22.2] at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:388) [167:org.glassfish.jersey.containers.jersey-container-servlet-core:2.22.2] at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:341) [167:org.glassfish.jersey.containers.jersey-container-servlet-core:2.22.2] at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:228) [167:org.glassfish.jersey.containers.jersey-container-servlet-core:2.22.2] at com.eclipsesource.jaxrs.publisher.internal.ServletContainerBridge.service(ServletContainerBridge.java:76) [15:com.eclipsesource.jaxrs.publisher:5.3.1.201602281253] at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:848) [85:org.eclipse.jetty.servlet:9.3.21.v20170918] at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:584) [85:org.eclipse.jetty.servlet:9.3.21.v20170918] at org.ops4j.pax.web.service.jetty.internal.HttpServiceServletHandler.doHandle(HttpServiceServletHandler.java:71) [183:org.ops4j.pax.web.pax-web-jetty:6.0.9] at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:143) [84:org.eclipse.jetty.server:9.3.21.v20170918] at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:548) [82:org.eclipse.jetty.security:9.3.21.v20170918] at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:226) [84:org.eclipse.jetty.server:9.3.21.v20170918] at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1180) [84:org.eclipse.jetty.server:9.3.21.v20170918] at org.ops4j.pax.web.service.jetty.internal.HttpServiceContext.doHandle(HttpServiceContext.java:284) [183:org.ops4j.pax.web.pax-web-jetty:6.0.9] at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:512) [85:org.eclipse.jetty.servlet:9.3.21.v20170918] at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:185) [84:org.eclipse.jetty.server:9.3.21.v20170918] at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1112) [84:org.eclipse.jetty.server:9.3.21.v20170918] at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:141) [84:org.eclipse.jetty.server:9.3.21.v20170918] at org.ops4j.pax.web.service.jetty.internal.JettyServerHandlerCollection.handle(JettyServerHandlerCollection.java:80) [183:org.ops4j.pax.web.pax-web-jetty:6.0.9] at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:134) [84:org.eclipse.jetty.server:9.3.21.v20170918] at org.eclipse.jetty.server.Server.handle(Server.java:534) [84:org.eclipse.jetty.server:9.3.21.v20170918] at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:333) [84:org.eclipse.jetty.server:9.3.21.v20170918] at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:251) [84:org.eclipse.jetty.server:9.3.21.v20170918] at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:283) [76:org.eclipse.jetty.io:9.3.21.v20170918] at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:108) [76:org.eclipse.jetty.io:9.3.21.v20170918] at org.eclipse.jetty.io.SelectChannelEndPoint$2.run(SelectChannelEndPoint.java:93) [76:org.eclipse.jetty.io:9.3.21.v20170918] at org.eclipse.jetty.util.thread.strategy.ExecuteProduceConsume.executeProduceConsume(ExecuteProduceConsume.java:303) [87:org.eclipse.jetty.util:9.3.21.v20170918] at org.eclipse.jetty.util.thread.strategy.ExecuteProduceConsume.produceConsume(ExecuteProduceConsume.java:148) [87:org.eclipse.jetty.util:9.3.21.v20170918] at org.eclipse.jetty.util.thread.strategy.ExecuteProduceConsume.run(ExecuteProduceConsume.java:136) [87:org.eclipse.jetty.util:9.3.21.v20170918] at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:671) [87:org.eclipse.jetty.util:9.3.21.v20170918] at org.eclipse.jetty.util.thread.QueuedThreadPool$2.run(QueuedThreadPool.java:589) [87:org.eclipse.jetty.util:9.3.21.v20170918] at java.lang.Thread.run(Thread.java:748) [?:?] Caused by: org.glassfish.jersey.server.ContainerException: java.lang.NoSuchMethodError: org.eclipse.smarthome.core.thing.Thing.getChannelsOfGroup(Ljava/lang/String;)Ljava/util/List; at org.glassfish.jersey.servlet.internal.ResponseWriter.rethrow(ResponseWriter.java:278) ~[?:?] at org.glassfish.jersey.servlet.internal.ResponseWriter.failure(ResponseWriter.java:260) ~[?:?] at org.glassfish.jersey.server.ServerRuntime$Responder.process(ServerRuntime.java:509) ~[170:org.glassfish.jersey.core.jersey-server:2.22.2] at org.glassfish.jersey.server.ServerRuntime$2.run(ServerRuntime.java:334) ~[170:org.glassfish.jersey.core.jersey-server:2.22.2] at org.glassfish.jersey.internal.Errors$1.call(Errors.java:271) ~[169:org.glassfish.jersey.core.jersey-common:2.22.2] at org.glassfish.jersey.internal.Errors$1.call(Errors.java:267) ~[169:org.glassfish.jersey.core.jersey-common:2.22.2] at org.glassfish.jersey.internal.Errors.process(Errors.java:315) ~[169:org.glassfish.jersey.core.jersey-common:2.22.2] at org.glassfish.jersey.internal.Errors.process(Errors.java:297) ~[169:org.glassfish.jersey.core.jersey-common:2.22.2] at org.glassfish.jersey.internal.Errors.process(Errors.java:267) ~[169:org.glassfish.jersey.core.jersey-common:2.22.2] at org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:317) ~[169:org.glassfish.jersey.core.jersey-common:2.22.2] at org.glassfish.jersey.server.ServerRuntime.process(ServerRuntime.java:305) ~[170:org.glassfish.jersey.core.jersey-server:2.22.2] at org.glassfish.jersey.server.ApplicationHandler.handle(ApplicationHandler.java:1154) ~[170:org.glassfish.jersey.core.jersey-server:2.22.2] at org.glassfish.jersey.servlet.WebComponent.serviceImpl(WebComponent.java:473) ~[167:org.glassfish.jersey.containers.jersey-container-servlet-core:2.22.2] ... 31 more Caused by: java.lang.NoSuchMethodError: org.eclipse.smarthome.core.thing.Thing.getChannelsOfGroup(Ljava/lang/String;)Ljava/util/List; at org.eclipse.smarthome.binding.openweathermap.internal.handler.OpenWeatherMapWeatherAndForecastHandler.initialize(OpenWeatherMapWeatherAndForecastHandler.java:108) ~[?:?] at org.eclipse.smarthome.core.thing.binding.BaseThingHandler.handleConfigurationUpdate(BaseThingHandler.java:198) ~[?:?] at org.eclipse.smarthome.core.thing.internal.ThingRegistryImpl.updateConfiguration(ThingRegistryImpl.java:92) ~[?:?] at org.eclipse.smarthome.io.rest.core.internal.thing.ThingResource.updateConfiguration(ThingResource.java:425) ~[?:?] at sun.reflect.GeneratedMethodAccessor91.invoke(Unknown Source) ~[?:?] at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:?] at java.lang.reflect.Method.invoke(Method.java:498) ~[?:?] at org.glassfish.jersey.server.model.internal.ResourceMethodInvocationHandlerFactory$1.invoke(ResourceMethodInvocationHandlerFactory.java:81) ~[170:org.glassfish.jersey.core.jersey-server:2.22.2] at org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher$1.run(AbstractJavaResourceMethodDispatcher.java:144) ~[170:org.glassfish.jersey.core.jersey-server:2.22.2] at org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher.invoke(AbstractJavaResourceMethodDispatcher.java:161) ~[170:org.glassfish.jersey.core.jersey-server:2.22.2] at org.glassfish.jersey.server.model.internal.JavaResourceMethodDispatcherProvider$ResponseOutInvoker.doDispatch(JavaResourceMethodDispatcherProvider.java:160) ~[170:org.glassfish.jersey.core.jersey-server:2.22.2] at org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher.dispatch(AbstractJavaResourceMethodDispatcher.java:99) ~[170:org.glassfish.jersey.core.jersey-server:2.22.2] at org.glassfish.jersey.server.model.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:389) ~[170:org.glassfish.jersey.core.jersey-server:2.22.2] at org.glassfish.jersey.server.model.ResourceMethodInvoker.apply(ResourceMethodInvoker.java:347) ~[170:org.glassfish.jersey.core.jersey-server:2.22.2] at org.glassfish.jersey.server.model.ResourceMethodInvoker.apply(ResourceMethodInvoker.java:102) ~[170:org.glassfish.jersey.core.jersey-server:2.22.2] at org.glassfish.jersey.server.ServerRuntime$2.run(ServerRuntime.java:326) ~[170:org.glassfish.jersey.core.jersey-server:2.22.2] at org.glassfish.jersey.internal.Errors$1.call(Errors.java:271) ~[169:org.glassfish.jersey.core.jersey-common:2.22.2] at org.glassfish.jersey.internal.Errors$1.call(Errors.java:267) ~[169:org.glassfish.jersey.core.jersey-common:2.22.2] at org.glassfish.jersey.internal.Errors.process(Errors.java:315) ~[169:org.glassfish.jersey.core.jersey-common:2.22.2] at org.glassfish.jersey.internal.Errors.process(Errors.java:297) ~[169:org.glassfish.jersey.core.jersey-common:2.22.2] at org.glassfish.jersey.internal.Errors.process(Errors.java:267) ~[169:org.glassfish.jersey.core.jersey-common:2.22.2] at org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:317) ~[169:org.glassfish.jersey.core.jersey-common:2.22.2] at org.glassfish.jersey.server.ServerRuntime.process(ServerRuntime.java:305) ~[170:org.glassfish.jersey.core.jersey-server:2.22.2] at org.glassfish.jersey.server.ApplicationHandler.handle(ApplicationHandler.java:1154) ~[170:org.glassfish.jersey.core.jersey-server:2.22.2] at org.glassfish.jersey.servlet.WebComponent.serviceImpl(WebComponent.java:473) ~[167:org.glassfish.jersey.containers.jersey-container-servlet-core:2.22.2] ... 31 more 2018-11-17 12:04:11.686 [WARN ] [org.eclipse.jetty.server.HttpChannel] - //fritzlconnect.synology.me:8181/rest/things/openweathermap:weather-and-forecast:6b382647:local/config javax.servlet.ServletException: javax.servlet.ServletException: org.glassfish.jersey.server.ContainerException: java.lang.NoSuchMethodError: org.eclipse.smarthome.core.thing.Thing.getChannelsOfGroup(Ljava/lang/String;)Ljava/util/List; at org.ops4j.pax.web.service.jetty.internal.JettyServerHandlerCollection.handle(JettyServerHandlerCollection.java:88) [183:org.ops4j.pax.web.pax-web-jetty:6.0.9] at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:134) [84:org.eclipse.jetty.server:9.3.21.v20170918] at org.eclipse.jetty.server.Server.handle(Server.java:534) [84:org.eclipse.jetty.server:9.3.21.v20170918] at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:333) [84:org.eclipse.jetty.server:9.3.21.v20170918] at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:251) [84:org.eclipse.jetty.server:9.3.21.v20170918] at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:283) [76:org.eclipse.jetty.io:9.3.21.v20170918] at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:108) [76:org.eclipse.jetty.io:9.3.21.v20170918] at org.eclipse.jetty.io.SelectChannelEndPoint$2.run(SelectChannelEndPoint.java:93) [76:org.eclipse.jetty.io:9.3.21.v20170918] at org.eclipse.jetty.util.thread.strategy.ExecuteProduceConsume.executeProduceConsume(ExecuteProduceConsume.java:303) [87:org.eclipse.jetty.util:9.3.21.v20170918] at org.eclipse.jetty.util.thread.strategy.ExecuteProduceConsume.produceConsume(ExecuteProduceConsume.java:148) [87:org.eclipse.jetty.util:9.3.21.v20170918] at org.eclipse.jetty.util.thread.strategy.ExecuteProduceConsume.run(ExecuteProduceConsume.java:136) [87:org.eclipse.jetty.util:9.3.21.v20170918] at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:671) [87:org.eclipse.jetty.util:9.3.21.v20170918] at org.eclipse.jetty.util.thread.QueuedThreadPool$2.run(QueuedThreadPool.java:589) [87:org.eclipse.jetty.util:9.3.21.v20170918] at java.lang.Thread.run(Thread.java:748) [?:?] Caused by: javax.servlet.ServletException: org.glassfish.jersey.server.ContainerException: java.lang.NoSuchMethodError: org.eclipse.smarthome.core.thing.Thing.getChannelsOfGroup(Ljava/lang/String;)Ljava/util/List; at org.glassfish.jersey.servlet.WebComponent.serviceImpl(WebComponent.java:489) ~[?:?] at org.glassfish.jersey.servlet.WebComponent.service(WebComponent.java:427) ~[?:?] at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:388) ~[?:?] at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:341) ~[?:?] at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:228) ~[?:?] at com.eclipsesource.jaxrs.publisher.internal.ServletContainerBridge.service(ServletContainerBridge.java:76) ~[?:?] at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:848) ~[?:?] at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:584) ~[?:?] at org.ops4j.pax.web.service.jetty.internal.HttpServiceServletHandler.doHandle(HttpServiceServletHandler.java:71) ~[?:?] at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:143) ~[?:?] at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:548) ~[?:?] at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:226) ~[?:?] at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1180) ~[?:?] at org.ops4j.pax.web.service.jetty.internal.HttpServiceContext.doHandle(HttpServiceContext.java:284) ~[?:?] at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:512) ~[?:?] at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:185) ~[?:?] at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1112) ~[?:?] at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:141) ~[?:?] at org.ops4j.pax.web.service.jetty.internal.JettyServerHandlerCollection.handle(JettyServerHandlerCollection.java:80) ~[?:?] ... 13 more Caused by: org.glassfish.jersey.server.ContainerException: java.lang.NoSuchMethodError: org.eclipse.smarthome.core.thing.Thing.getChannelsOfGroup(Ljava/lang/String;)Ljava/util/List; at org.glassfish.jersey.servlet.internal.ResponseWriter.rethrow(ResponseWriter.java:278) ~[?:?] at org.glassfish.jersey.servlet.internal.ResponseWriter.failure(ResponseWriter.java:260) ~[?:?] at org.glassfish.jersey.server.ServerRuntime$Responder.process(ServerRuntime.java:509) ~[?:?] at org.glassfish.jersey.server.ServerRuntime$2.run(ServerRuntime.java:334) ~[?:?] at org.glassfish.jersey.internal.Errors$1.call(Errors.java:271) ~[?:?] at org.glassfish.jersey.internal.Errors$1.call(Errors.java:267) ~[?:?] at org.glassfish.jersey.internal.Errors.process(Errors.java:315) ~[?:?] at org.glassfish.jersey.internal.Errors.process(Errors.java:297) ~[?:?] at org.glassfish.jersey.internal.Errors.process(Errors.java:267) ~[?:?] at org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:317) ~[?:?] at org.glassfish.jersey.server.ServerRuntime.process(ServerRuntime.java:305) ~[?:?] at org.glassfish.jersey.server.ApplicationHandler.handle(ApplicationHandler.java:1154) ~[?:?] at org.glassfish.jersey.servlet.WebComponent.serviceImpl(WebComponent.java:473) ~[?:?] at org.glassfish.jersey.servlet.WebComponent.service(WebComponent.java:427) ~[?:?] at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:388) ~[?:?] at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:341) ~[?:?] at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:228) ~[?:?] at com.eclipsesource.jaxrs.publisher.internal.ServletContainerBridge.service(ServletContainerBridge.java:76) ~[?:?] at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:848) ~[?:?] at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:584) ~[?:?] at org.ops4j.pax.web.service.jetty.internal.HttpServiceServletHandler.doHandle(HttpServiceServletHandler.java:71) ~[?:?] at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:143) ~[?:?] at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:548) ~[?:?] at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:226) ~[?:?] at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1180) ~[?:?] at org.ops4j.pax.web.service.jetty.internal.HttpServiceContext.doHandle(HttpServiceContext.java:284) ~[?:?] at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:512) ~[?:?] at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:185) ~[?:?] at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1112) ~[?:?] at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:141) ~[?:?] at org.ops4j.pax.web.service.jetty.internal.JettyServerHandlerCollection.handle(JettyServerHandlerCollection.java:80) ~[?:?] ... 13 more Caused by: java.lang.NoSuchMethodError: org.eclipse.smarthome.core.thing.Thing.getChannelsOfGroup(Ljava/lang/String;)Ljava/util/List; at org.eclipse.smarthome.binding.openweathermap.internal.handler.OpenWeatherMapWeatherAndForecastHandler.initialize(OpenWeatherMapWeatherAndForecastHandler.java:108) ~[?:?] at org.eclipse.smarthome.core.thing.binding.BaseThingHandler.handleConfigurationUpdate(BaseThingHandler.java:198) ~[?:?] at org.eclipse.smarthome.core.thing.internal.ThingRegistryImpl.updateConfiguration(ThingRegistryImpl.java:92) ~[?:?] at org.eclipse.smarthome.io.rest.core.internal.thing.ThingResource.updateConfiguration(ThingResource.java:425) ~[?:?] at sun.reflect.GeneratedMethodAccessor91.invoke(Unknown Source) ~[?:?] at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:?] at java.lang.reflect.Method.invoke(Method.java:498) ~[?:?] at org.glassfish.jersey.server.model.internal.ResourceMethodInvocationHandlerFactory$1.invoke(ResourceMethodInvocationHandlerFactory.java:81) ~[?:?] at org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher$1.run(AbstractJavaResourceMethodDispatcher.java:144) ~[?:?] at org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher.invoke(AbstractJavaResourceMethodDispatcher.java:161) ~[?:?] at org.glassfish.jersey.server.model.internal.JavaResourceMethodDispatcherProvider$ResponseOutInvoker.doDispatch(JavaResourceMethodDispatcherProvider.java:160) ~[?:?] at org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher.dispatch(AbstractJavaResourceMethodDispatcher.java:99) ~[?:?] at org.glassfish.jersey.server.model.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:389) ~[?:?] at org.glassfish.jersey.server.model.ResourceMethodInvoker.apply(ResourceMethodInvoker.java:347) ~[?:?] at org.glassfish.jersey.server.model.ResourceMethodInvoker.apply(ResourceMethodInvoker.java:102) ~[?:?] at org.glassfish.jersey.server.ServerRuntime$2.run(ServerRuntime.java:326) ~[?:?] at org.glassfish.jersey.internal.Errors$1.call(Errors.java:271) ~[?:?] at org.glassfish.jersey.internal.Errors$1.call(Errors.java:267) ~[?:?] at org.glassfish.jersey.internal.Errors.process(Errors.java:315) ~[?:?] at org.glassfish.jersey.internal.Errors.process(Errors.java:297) ~[?:?] at org.glassfish.jersey.internal.Errors.process(Errors.java:267) ~[?:?] at org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:317) ~[?:?] at org.glassfish.jersey.server.ServerRuntime.process(ServerRuntime.java:305) ~[?:?] at org.glassfish.jersey.server.ApplicationHandler.handle(ApplicationHandler.java:1154) ~[?:?] at org.glassfish.jersey.servlet.WebComponent.serviceImpl(WebComponent.java:473) ~[?:?] at org.glassfish.jersey.servlet.WebComponent.service(WebComponent.java:427) ~[?:?] at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:388) ~[?:?] at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:341) ~[?:?] at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:228) ~[?:?] at com.eclipsesource.jaxrs.publisher.internal.ServletContainerBridge.service(ServletContainerBridge.java:76) ~[?:?] at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:848) ~[?:?] at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:584) ~[?:?] at org.ops4j.pax.web.service.jetty.internal.HttpServiceServletHandler.doHandle(HttpServiceServletHandler.java:71) ~[?:?] at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:143) ~[?:?] at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:548) ~[?:?] at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:226) ~[?:?] at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1180) ~[?:?] at org.ops4j.pax.web.service.jetty.internal.HttpServiceContext.doHandle(HttpServiceContext.java:284) ~[?:?] at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:512) ~[?:?] at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:185) ~[?:?] at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1112) ~[?:?] at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:141) ~[?:?] at org.ops4j.pax.web.service.jetty.internal.JettyServerHandlerCollection.handle(JettyServerHandlerCollection.java:80) ~[?:?] ... 13 more

current status

image

@maggu2810
Copy link
Contributor

Your core ESH bundles are not up to date.

java.lang.NoSuchMethodError: org.eclipse.smarthome.core.thing.Thing.getChannelsOfGroup(Ljava/lang/String;)Ljava/util/List;

At least this error is not caused by the binding but by your runtime.
OH 2.3 is AFAIK rather old and I am not aware that the OWM is compatible with such an old runtime.

You should use an up to date runtime.
For me this sounds like an OH product related problem and should perhaps be moved to their community forum.

@woanne67
Copy link

@maggu2810 @cweitkamp Thanks. Before installing OH2.3 on the synology I make a runtime update to Java 1.8.0_191. What else can I do?

@cweitkamp
Copy link
Contributor Author

@woanne67 You can switch your installation to the testing or snapshot release.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.