Skip to content

Commit 96def56

Browse files
authored
[haassohnpelletstove] Improve connection handling (openhab#18212)
* Adding a Reconnect Rate to improve connectivity for the thing in case of weak wifi signal and automatically reconnect the thing. Signed-off-by: chingon007 <[email protected]>
1 parent c3fa943 commit 96def56

File tree

6 files changed

+99
-195
lines changed

6 files changed

+99
-195
lines changed

bundles/org.openhab.binding.haassohnpelletstove/README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ WIFI module. More information about the WIFI module can be found here: <https://
1212
## Thing Configuration
1313

1414
In general two parameters are required. The IP-Address of the WIFI-Modul of the Stove in the local Network and the Access PIN of the Stove.
15-
The PIN can be found directly at the stove under the Menue/Network/WLAN-PIN
15+
The PIN can be found directly at the stove under the Menue/Network/WLAN-PIN.
1616

1717
```java
1818
Thing haassohnpelletstove:oven:myOven "Pelletstove" [ hostIP="192.168.0.23", hostPIN="1234"]

bundles/org.openhab.binding.haassohnpelletstove/src/main/java/org/openhab/binding/haassohnpelletstove/internal/HaasSohnpelletstoveConfiguration.java

+2-3
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@
1313
package org.openhab.binding.haassohnpelletstove.internal;
1414

1515
import org.eclipse.jdt.annotation.NonNullByDefault;
16-
import org.eclipse.jdt.annotation.Nullable;
1716

1817
/**
1918
* The {@link HaasSohnpelletstoveConfiguration} class contains fields mapping thing configuration parameters.
@@ -23,7 +22,7 @@
2322
@NonNullByDefault
2423
public class HaasSohnpelletstoveConfiguration {
2524

26-
public @Nullable String hostIP = null;
27-
public @Nullable String hostPIN = null;
25+
public String hostIP = "";
26+
public String hostPIN = "";
2827
public int refreshRate = 30;
2928
}

bundles/org.openhab.binding.haassohnpelletstove/src/main/java/org/openhab/binding/haassohnpelletstove/internal/HaasSohnpelletstoveHandler.java

+61-69
Original file line numberDiff line numberDiff line change
@@ -108,82 +108,63 @@ public void handleCommand(ChannelUID channelUID, Command command) {
108108
}
109109
}
110110

111-
/**
112-
* Calls the service to update the oven data
113-
*
114-
* @param postdata
115-
*/
116-
private boolean updateOvenData(@Nullable String postdata) {
117-
Helper message = new Helper();
118-
if (serviceCommunication.updateOvenData(postdata, message, this.getThing().getUID().toString())) {
119-
updateStatus(ThingStatus.ONLINE);
120-
return true;
121-
} else {
122-
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.OFFLINE.COMMUNICATION_ERROR,
123-
message.getStatusDesription());
124-
return false;
125-
}
126-
}
127-
128111
@Override
129112
public void initialize() {
130113
logger.debug("Initializing haassohnpelletstove handler for thing {}", getThing().getUID());
131114
config = getConfigAs(HaasSohnpelletstoveConfiguration.class);
132-
boolean validConfig = true;
133-
String errors = "";
134-
String statusDescr = null;
135-
if (config.refreshRate < 0 && config.refreshRate > 999) {
136-
errors += " Parameter 'refresh Rate' greater then 0 and less then 1000.";
137-
statusDescr = "Parameter 'refresh Rate' greater then 0 and less then 1000.";
138-
validConfig = false;
115+
if (config.refreshRate < 1 || config.refreshRate > 1000) {
116+
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
117+
"Parameter 'refresh Rate' must be in the range 1-1000!");
118+
return;
139119
}
140-
if (config.hostIP == null) {
141-
errors += " Parameter 'hostIP' must be configured.";
142-
statusDescr = "IP Address must be configured!";
143-
validConfig = false;
120+
if (config.hostIP.isBlank()) {
121+
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, "IP Address must be configured!");
122+
return;
144123
}
145-
if (config.hostPIN == null) {
146-
errors += " Parameter 'hostPin' must be configured.";
147-
statusDescr = "PIN must be configured!";
148-
validConfig = false;
124+
125+
if (config.hostPIN.isBlank()) {
126+
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
127+
"Parameter 'hostPin' must be configured!");
128+
return;
149129
}
150-
errors = errors.trim();
151-
Helper message = new Helper();
152-
message.setStatusDescription(statusDescr);
153-
if (validConfig) {
154-
serviceCommunication.setConfig(config);
155-
if (serviceCommunication.refreshOvenConnection(message, this.getThing().getUID().toString())) {
156-
if (updateOvenData(null)) {
157-
updateStatus(ThingStatus.ONLINE);
158-
updateLinkedChannels();
130+
131+
serviceCommunication.setConfig(config);
132+
updateStatus(ThingStatus.UNKNOWN);
133+
scheduler.submit(() -> {
134+
if (updateOvenData(null)) {
135+
for (Channel channel : getThing().getChannels()) {
136+
if (isLinked(channel.getUID().getId())) {
137+
channelLinked(channel.getUID());
138+
}
159139
}
160-
} else {
161-
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, message.getStatusDesription());
162140
}
163-
} else {
164-
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, message.getStatusDesription());
165-
}
141+
});
166142
}
167143

168-
private void updateLinkedChannels() {
169-
verifyLinkedChannel(CHANNELISTEMP);
170-
verifyLinkedChannel(CHANNELMODE);
171-
verifyLinkedChannel(CHANNELPOWER);
172-
verifyLinkedChannel(CHANNELSPTEMP);
173-
verifyLinkedChannel(CHANNELECOMODE);
174-
verifyLinkedChannel(CHANNELIGNITIONS);
175-
verifyLinkedChannel(CHANNELMAINTENANCEIN);
176-
verifyLinkedChannel(CHANNELCLEANINGIN);
177-
verifyLinkedChannel(CHANNELCONSUMPTION);
178-
verifyLinkedChannel(CHANNELONTIME);
179-
if (!linkedChannels.isEmpty()) {
180-
updateOvenData(null);
181-
for (Channel channel : getThing().getChannels()) {
182-
updateChannel(channel.getUID().getId());
144+
/**
145+
* Calls the service to update the oven data
146+
*
147+
* @return true if the update succeeded, false otherwise
148+
*/
149+
private boolean updateOvenData(@Nullable String postdata) {
150+
String error = "";
151+
if (postdata != null) {
152+
error = serviceCommunication.updateOvenData(postdata);
153+
} else {
154+
error = serviceCommunication.refreshOvenConnection();
155+
}
156+
if (error.isEmpty()) {
157+
if (ThingStatus.OFFLINE.equals(getThing().getStatus())) {
158+
updateStatus(ThingStatus.UNKNOWN);
183159
}
184-
startAutomaticRefresh();
185-
automaticRefreshing = true;
160+
if (!ThingStatus.ONLINE.equals(getThing().getStatus())) {
161+
updateStatus(ThingStatus.ONLINE);
162+
}
163+
} else {
164+
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, error);
165+
return false;
186166
}
167+
return error.isEmpty();
187168
}
188169

189170
private void verifyLinkedChannel(String channelID) {
@@ -195,14 +176,24 @@ private void verifyLinkedChannel(String channelID) {
195176
@Override
196177
public void dispose() {
197178
stopScheduler();
179+
linkedChannels.clear();
180+
automaticRefreshing = false;
198181
}
199182

200183
private void stopScheduler() {
201184
ScheduledFuture<?> job = refreshJob;
202-
if (job != null) {
203-
job.cancel(true);
185+
if (job == null || job.isCancelled()) {
186+
refreshJob = scheduler.scheduleWithFixedDelay(this::refreshChannels, 0, config.refreshRate,
187+
TimeUnit.SECONDS);
188+
}
189+
}
190+
191+
private void refreshChannels() {
192+
if (updateOvenData(null)) {
193+
for (Channel channel : getThing().getChannels()) {
194+
updateChannel(channel.getUID().getId());
195+
}
204196
}
205-
refreshJob = null;
206197
}
207198

208199
/**
@@ -217,9 +208,10 @@ private void startAutomaticRefresh() {
217208
}
218209

219210
private void run() {
220-
updateOvenData(null);
221-
for (Channel channel : getThing().getChannels()) {
222-
updateChannel(channel.getUID().getId());
211+
if (updateOvenData(null)) {
212+
for (Channel channel : getThing().getChannels()) {
213+
updateChannel(channel.getUID().getId());
214+
}
223215
}
224216
}
225217

bundles/org.openhab.binding.haassohnpelletstove/src/main/java/org/openhab/binding/haassohnpelletstove/internal/HaasSohnpelletstoveJSONCommunication.java

+34-73
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
import org.slf4j.LoggerFactory;
2727

2828
import com.google.gson.Gson;
29+
import com.google.gson.JsonSyntaxException;
2930

3031
/**
3132
* This class handles the JSON communication with the Wifi Modul of the Stove
@@ -52,105 +53,65 @@ public HaasSohnpelletstoveJSONCommunication() {
5253
/**
5354
* Refreshes the oven Connection with the internal oven token.
5455
*
55-
* @param message Message object to pass errors to the calling method.
56-
* @param thingUID Thing UID for logging purposes
57-
* @return true if no error occurred, false otherwise.
56+
* @return an empty string if no error occurred, the error message otherwise.
5857
*/
59-
public boolean refreshOvenConnection(Helper message, String thingUID) {
60-
if (config.hostIP == null || config.hostPIN == null) {
61-
message.setStatusDescription("Error in configuration. Please recreate Thing.");
62-
return false;
63-
}
64-
HaasSohnpelletstoveJsonDataDTO result = null;
65-
boolean resultOk = false;
66-
String error = "", errorDetail = "", statusDescr = "";
58+
public String refreshOvenConnection() {
59+
String result = "";
60+
HaasSohnpelletstoveJsonDataDTO responseObject = null;
6761
String urlStr = "http://" + config.hostIP + "/status.cgi";
6862

6963
String response = null;
7064
try {
7165
response = HttpUtil.executeUrl("GET", urlStr, 10000);
7266
logger.debug("OvenData = {}", response);
73-
result = gson.fromJson(response, HaasSohnpelletstoveJsonDataDTO.class);
74-
resultOk = true;
75-
} catch (IOException e) {
67+
responseObject = gson.fromJson(response, HaasSohnpelletstoveJsonDataDTO.class);
68+
ovenData = responseObject;
69+
xhspin = getValidXHSPIN(ovenData);
70+
} catch (IOException | JsonSyntaxException e) {
7671
logger.debug("Error processiong Get request {}", urlStr);
77-
statusDescr = "Timeout error with" + config.hostIP
78-
+ ". Cannot find service on give IP. Please verify the IP-Address!";
79-
errorDetail = e.getMessage();
80-
resultOk = false;
72+
result = "Timeout error with " + config.hostIP
73+
+ ". Cannot find service on given IP. Please verify the IP-Address!";
74+
logger.debug("Error in establishing connection: {}", e.getMessage());
8175
} catch (Exception e) {
8276
logger.debug("Unknwon Error: {}", e.getMessage());
83-
errorDetail = e.getMessage();
84-
resultOk = false;
85-
}
86-
if (resultOk) {
87-
ovenData = result;
88-
xhspin = getValidXHSPIN(ovenData);
89-
} else {
90-
logger.debug("Setting thing '{}' to OFFLINE: Error '{}': {}", thingUID, error, errorDetail);
9177
ovenData = new HaasSohnpelletstoveJsonDataDTO();
9278
}
93-
message.setStatusDescription(statusDescr);
94-
return resultOk;
79+
return result;
9580
}
9681

9782
/**
9883
* Gets the status of the oven
9984
*
100-
* @return true if success or false in case of error
85+
* @return an empty string if no error occurred, the error message otherwise.
10186
*/
102-
public boolean updateOvenData(@Nullable String postData, Helper helper, String thingUID) {
103-
String statusDescr = "";
104-
boolean resultOk = false;
105-
String error = "", errorDetail = "";
106-
if (config.hostIP == null || config.hostPIN == null) {
107-
return false;
108-
}
87+
public String updateOvenData(@Nullable String postData) {
88+
String error = "";
10989
String urlStr = "http://" + config.hostIP + "/status.cgi";
110-
11190
// Run the HTTP POST request and get the JSON response from Oven
11291
String response = null;
113-
11492
Properties httpHeader = new Properties();
11593

116-
if (postData != null) {
117-
try {
118-
InputStream targetStream = new ByteArrayInputStream(postData.getBytes(StandardCharsets.UTF_8));
119-
refreshOvenConnection(helper, thingUID);
120-
httpHeader = createHeader(postData);
121-
response = HttpUtil.executeUrl("POST", urlStr, httpHeader, targetStream, "application/json", 10000);
122-
resultOk = true;
123-
logger.debug("Execute POST request with content to {} with header: {}", urlStr, httpHeader.toString());
124-
} catch (IOException e) {
125-
logger.debug("Error processiong POST request {}", urlStr);
126-
statusDescr = "Cannot execute command on Stove. Please verify connection and Thing Status";
127-
resultOk = false;
128-
}
129-
} else {
130-
try {
131-
refreshOvenConnection(helper, thingUID);
132-
httpHeader = createHeader(null);
133-
response = HttpUtil.executeUrl("POST", urlStr, httpHeader, null, "", 10000);
134-
resultOk = true;
135-
logger.debug("Execute POST request to {} with header: {}", urlStr, httpHeader.toString());
136-
} catch (IOException e) {
137-
logger.debug("Error processiong POST request {}", e.getMessage());
138-
String message = e.getMessage();
139-
if (message != null && message.contains("Authentication challenge without WWW-Authenticate ")) {
140-
statusDescr = "Cannot connect to stove. Given PIN: " + config.hostPIN + " is incorrect!";
141-
}
142-
resultOk = false;
94+
try {
95+
InputStream targetStream = null;
96+
if (postData != null) {
97+
targetStream = new ByteArrayInputStream(postData.getBytes(StandardCharsets.UTF_8));
14398
}
144-
}
145-
if (resultOk) {
146-
logger.debug("OvenData = {}", response);
99+
refreshOvenConnection();
100+
httpHeader = createHeader(postData != null ? postData : null);
101+
response = HttpUtil.executeUrl("POST", urlStr, httpHeader, targetStream != null ? targetStream : null,
102+
"application/json", 10000);
103+
logger.debug("Execute POST request with content to {} with header: {}", urlStr, httpHeader.toString());
147104
ovenData = gson.fromJson(response, HaasSohnpelletstoveJsonDataDTO.class);
148-
} else {
149-
logger.debug("Setting thing '{}' to OFFLINE: Error '{}': {}", thingUID, error, errorDetail);
150-
ovenData = new HaasSohnpelletstoveJsonDataDTO();
105+
logger.debug("OvenData = {}", response);
106+
} catch (IOException e) {
107+
logger.debug("Error processiong POST request {}", urlStr);
108+
error = "Cannot execute command on Stove. Please verify connection or PIN";
109+
110+
} catch (JsonSyntaxException e) {
111+
logger.debug("Error in establishing connection: {}", e.getMessage());
112+
error = "Cannot find service on given IP " + config.hostIP + ". Please verify the IP address!";
151113
}
152-
helper.setStatusDescription(statusDescr);
153-
return resultOk;
114+
return error;
154115
}
155116

156117
/**

bundles/org.openhab.binding.haassohnpelletstove/src/main/java/org/openhab/binding/haassohnpelletstove/internal/Helper.java

-48
This file was deleted.

0 commit comments

Comments
 (0)