use of org.openhab.binding.shelly.internal.api.ShellyApiException in project openhab-addons by openhab.
the class ShellyManagerPage method loadHTML.
protected String loadHTML(String template) throws ShellyApiException {
if (htmlTemplates.containsKey(template)) {
return getString(htmlTemplates.get(template));
}
String html = "";
String file = TEMPLATE_PATH + template;
logger.debug("Read HTML from {}", file);
ClassLoader cl = ShellyManagerInterface.class.getClassLoader();
if (cl != null) {
try (InputStream inputStream = cl.getResourceAsStream(file)) {
if (inputStream != null) {
html = new BufferedReader(new InputStreamReader(inputStream)).lines().collect(Collectors.joining("\n"));
htmlTemplates.put(template, html);
}
} catch (IOException e) {
throw new ShellyApiException("Unable to read " + file + " from bundle resources!", e);
}
}
return html;
}
use of org.openhab.binding.shelly.internal.api.ShellyApiException in project openhab-addons by openhab.
the class ShellyManagerServlet method service.
@Override
protected void service(@Nullable HttpServletRequest request, @Nullable HttpServletResponse response) throws ServletException, IOException, IllegalArgumentException {
if ((request == null) || (response == null)) {
logger.debug("request or resp must not be null!");
return;
}
String path = getString(request.getRequestURI()).toLowerCase();
String ipAddress = request.getHeader("HTTP_X_FORWARDED_FOR");
ShellyMgrResponse output = new ShellyMgrResponse();
PrintWriter print = null;
OutputStream bin = null;
try {
if (ipAddress == null) {
ipAddress = request.getRemoteAddr();
}
Map<String, String[]> parameters = request.getParameterMap();
logger.debug("{}: {} Request from {}:{}{}?{}", className, request.getProtocol(), ipAddress, request.getRemotePort(), path, parameters.toString());
if (!path.toLowerCase().startsWith(SERVLET_URI)) {
logger.warn("{} received unknown request: path = {}", className, path);
return;
}
output = manager.generateContent(path, parameters);
response.setContentType(output.mimeType);
if (output.mimeType.equals("text/html")) {
// Make sure it's UTF-8 encoded
response.setCharacterEncoding(UTF_8);
print = response.getWriter();
print.write((String) output.data);
} else {
// binary data
byte[] data = (byte[]) output.data;
if (data != null) {
response.setContentLength(data.length);
bin = response.getOutputStream();
bin.write(data, 0, data.length);
}
}
} catch (ShellyApiException | RuntimeException e) {
logger.debug("{}: Exception uri={}, parameters={}", className, path, request.getParameterMap().toString(), e);
response.setContentType("text/html");
print = response.getWriter();
print.write("Exception:" + e.toString() + "<br/>Check openHAB.log for details." + "<p/><a href=\"/shelly/manager\">Return to Overview</a>");
logger.debug("{}: {}", className, output);
response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
} finally {
if (print != null) {
print.close();
}
if (bin != null) {
bin.close();
}
}
}
use of org.openhab.binding.shelly.internal.api.ShellyApiException in project openhab-addons by openhab.
the class ShellyCoapHandler method start.
/**
* Initialize CoAP access, send discovery packet and start Status server
*
* @parm thingName Thing name derived from Thing Type/hostname
* @parm config ShellyThingConfiguration
* @thows ShellyApiException
*/
public synchronized void start(String thingName, ShellyThingConfiguration config) throws ShellyApiException {
try {
this.thingName = thingName;
this.config = config;
this.profile = thingHandler.getProfile();
if (isStarted()) {
logger.trace("{}: CoAP Listener was already started", thingName);
stop();
}
logger.debug("{}: Starting CoAP Listener", thingName);
if (!profile.coiotEndpoint.isEmpty() && profile.coiotEndpoint.contains(":")) {
String ps = substringAfter(profile.coiotEndpoint, ":");
coiotPort = Integer.parseInt(ps);
}
coapServer.start(config.localIp, coiotPort, this);
statusClient = new CoapClient(completeUrl(config.deviceIp, coiotPort, COLOIT_URI_DEVSTATUS)).setTimeout((long) SHELLY_API_TIMEOUT_MS).useNONs().setEndpoint(coapServer.getEndpoint());
@Nullable Endpoint endpoint = null;
CoapClient client = statusClient;
if (client != null) {
endpoint = client.getEndpoint();
}
if ((endpoint == null) || !endpoint.isStarted()) {
logger.warn("{}: Unable to initialize CoAP access (network error)", thingName);
throw new ShellyApiException("Network initialization failed");
}
discover();
} catch (SocketException e) {
logger.warn("{}: Unable to initialize CoAP access (socket exception) - {}", thingName, e.getMessage());
throw new ShellyApiException("Network error", e);
} catch (UnknownHostException e) {
logger.info("{}: CoAP Exception (Unknown Host)", thingName, e);
throw new ShellyApiException("Unknown Host: " + config.deviceIp, e);
}
}
use of org.openhab.binding.shelly.internal.api.ShellyApiException in project openhab-addons by openhab.
the class ShellyCoapHandler method processResponse.
/**
* Process an inbound Response (or mapped Request): decode CoAP options. handle discovery result or status updates
*
* @param response The Response packet
*/
@Override
public void processResponse(@Nullable Response response) {
if (response == null) {
coiotErrors++;
// other device instance
return;
}
ResponseCode code = response.getCode();
if (code != ResponseCode.CONTENT) {
// error handling
logger.debug("{}: Unknown Response Code {} received, payload={}", thingName, code, response.getPayloadString());
coiotErrors++;
return;
}
List<Option> options = response.getOptions().asSortedList();
String ip = response.getSourceContext().getPeerAddress().toString();
boolean match = ip.contains(config.deviceIp);
if (!match) {
// We can't identify device by IP, so we need to check the CoAP header's Global Device ID
for (Option opt : options) {
if (opt.getNumber() == COIOT_OPTION_GLOBAL_DEVID) {
String devid = opt.getStringValue();
if (devid.contains("#")) {
// Format: <device type>#<mac address>#<coap version>
String macid = substringBetween(devid, "#", "#");
if (profile.mac.toUpperCase().contains(macid.toUpperCase())) {
match = true;
break;
}
}
}
}
}
if (!match) {
// other instance
return;
}
String payload = "";
String devId = "";
String uri = "";
int serial = -1;
try {
coiotMessages++;
if (logger.isDebugEnabled()) {
logger.debug("{}: CoIoT Message from {} (MID={}): {}", thingName, response.getSourceContext().getPeerAddress(), response.getMID(), response.getPayloadString());
}
if (response.isCanceled() || response.isDuplicate() || response.isRejected()) {
logger.debug("{} ({}): Packet was canceled, rejected or is a duplicate -> discard", thingName, devId);
coiotErrors++;
return;
}
payload = response.getPayloadString();
for (Option opt : options) {
switch(opt.getNumber()) {
case OptionNumberRegistry.URI_PATH:
uri = COLOIT_URI_BASE + opt.getStringValue();
break;
case // ignore
OptionNumberRegistry.URI_HOST:
break;
case // ignore
OptionNumberRegistry.CONTENT_FORMAT:
break;
case COIOT_OPTION_GLOBAL_DEVID:
devId = opt.getStringValue();
String sVersion = substringAfterLast(devId, "#");
int iVersion = Integer.parseInt(sVersion);
if (coiotBound && (coiotVers != iVersion)) {
logger.debug("{}: CoIoT versopm has changed from {} to {}, maybe the firmware was upgraded", thingName, coiotVers, iVersion);
thingHandler.reinitializeThing();
coiotBound = false;
}
if (!coiotBound) {
thingHandler.updateProperties(PROPERTY_COAP_VERSION, sVersion);
logger.debug("{}: CoIoT Version {} detected", thingName, iVersion);
if (iVersion == COIOT_VERSION_1) {
coiot = new ShellyCoIoTVersion1(thingName, thingHandler, blkMap, sensorMap);
} else if (iVersion == COIOT_VERSION_2) {
coiot = new ShellyCoIoTVersion2(thingName, thingHandler, blkMap, sensorMap);
} else {
logger.warn("{}: Unsupported CoAP version detected: {}", thingName, sVersion);
return;
}
coiotVers = iVersion;
coiotBound = true;
}
break;
case COIOT_OPTION_STATUS_VALIDITY:
break;
case COIOT_OPTION_STATUS_SERIAL:
serial = opt.getIntegerValue();
break;
default:
logger.debug("{} ({}): COAP option {} with value {} skipped", thingName, devId, opt.getNumber(), opt.getValue());
}
}
// If we received a CoAP message successful the thing must be online
thingHandler.setThingOnline();
// duplicate, excep for battery devices! Those reset the serial every time when they wake-up
if ((serial == lastSerial) && payload.equals(lastPayload) && (!profile.hasBattery || coiot.getLastWakeup().equalsIgnoreCase("ext_power") || ((serial & 0xFF) != 0))) {
logger.debug("{}: Serial {} was already processed, ignore update", thingName, serial);
return;
}
// fixed malformed JSON :-(
payload = fixJSON(payload);
try {
if (uri.equalsIgnoreCase(COLOIT_URI_DEVDESC) || (uri.isEmpty() && payload.contains(COIOT_TAG_BLK))) {
handleDeviceDescription(devId, payload);
} else if (uri.equalsIgnoreCase(COLOIT_URI_DEVSTATUS) || (uri.isEmpty() && payload.contains(COIOT_TAG_GENERIC))) {
handleStatusUpdate(devId, payload, serial);
}
} catch (ShellyApiException e) {
logger.debug("{}: Unable to process CoIoT message: {}", thingName, e.toString());
coiotErrors++;
}
if (!updatesRequested) {
// Observe Status Updates
reqStatus = sendRequest(reqStatus, config.deviceIp, COLOIT_URI_DEVSTATUS, Type.NON);
updatesRequested = true;
}
} catch (JsonSyntaxException | IllegalArgumentException | NullPointerException e) {
logger.debug("{}: Unable to process CoIoT Message for payload={}", thingName, payload, e);
resetSerial();
coiotErrors++;
}
}
use of org.openhab.binding.shelly.internal.api.ShellyApiException in project openhab-addons by openhab.
the class ShellyBaseHandler method handleCommand.
/**
* Handle Channel Commands
*/
@Override
public void handleCommand(ChannelUID channelUID, Command command) {
try {
if (command instanceof RefreshType) {
String channelId = channelUID.getId();
State value = cache.getValue(channelId);
if (value != UnDefType.NULL) {
updateState(channelId, value);
}
return;
}
if (!profile.isInitialized()) {
logger.debug("{}: {}", thingName, messages.get("command.init", command));
initializeThing();
} else {
profile = getProfile(false);
}
boolean update = false;
switch(channelUID.getIdWithoutGroup()) {
case // Shelly Sense: Send Key
CHANNEL_SENSE_KEY:
logger.debug("{}: Send key {}", thingName, command);
api.sendIRKey(command.toString());
update = true;
break;
case CHANNEL_LED_STATUS_DISABLE:
logger.debug("{}: Set STATUS LED disabled to {}", thingName, command);
api.setLedStatus(SHELLY_LED_STATUS_DISABLE, command == OnOffType.ON);
break;
case CHANNEL_LED_POWER_DISABLE:
logger.debug("{}: Set POWER LED disabled to {}", thingName, command);
api.setLedStatus(SHELLY_LED_POWER_DISABLE, command == OnOffType.ON);
break;
case CHANNEL_SENSOR_SLEEPTIME:
logger.debug("{}: Set sensor sleep time to {}", thingName, command);
int value = ((DecimalType) command).intValue();
value = value > 0 ? Math.max(SHELLY_MOTION_SLEEPTIME_OFFSET, value - SHELLY_MOTION_SLEEPTIME_OFFSET) : 0;
api.setSleepTime(value);
break;
default:
update = handleDeviceCommand(channelUID, command);
break;
}
restartWatchdog();
if (update && !autoCoIoT) {
requestUpdates(1, false);
}
} catch (ShellyApiException e) {
ShellyApiResult res = e.getApiResult();
if (isAuthorizationFailed(res)) {
return;
}
if (res.isNotCalibrtated()) {
logger.warn("{}: {}", thingName, messages.get("roller.calibrating"));
} else {
logger.warn("{}: {} - {}", thingName, messages.get("command.failed", command, channelUID), e.toString());
}
} catch (IllegalArgumentException e) {
logger.debug("{}: {}", thingName, messages.get("command.failed", command, channelUID));
}
}
Aggregations