use of org.openhab.binding.shelly.internal.api.ShellyApiException in project openhab-addons by openhab.
the class ShellyManagerActionPage method generateContent.
@Override
public ShellyMgrResponse generateContent(String path, Map<String, String[]> parameters) throws ShellyApiException {
String action = getUrlParm(parameters, URLPARM_ACTION);
String uid = getUrlParm(parameters, URLPARM_UID);
String update = getUrlParm(parameters, URLPARM_UPDATE);
if (uid.isEmpty() || action.isEmpty()) {
return new ShellyMgrResponse("Invalid URL parameters: " + parameters.toString(), HttpStatus.BAD_REQUEST_400);
}
Map<String, String> properties = new HashMap<>();
properties.put(ATTRIBUTE_METATAG, "");
properties.put(ATTRIBUTE_CSS_HEADER, "");
properties.put(ATTRIBUTE_CSS_FOOTER, "");
String html = loadHTML(HEADER_HTML, properties);
ShellyManagerInterface th = getThingHandler(uid);
if (th != null) {
fillProperties(properties, uid, th);
Map<String, String> actions = getActions(th.getProfile());
String actionUrl = SHELLY_MGR_OVERVIEW_URI;
// Default
String actionButtonLabel = "OK";
String serviceName = getValue(properties, PROPERTY_SERVICE_NAME);
String message = "";
ShellyThingConfiguration config = getThingConfig(th, properties);
ShellyDeviceProfile profile = th.getProfile();
ShellyHttpApi api = th.getApi();
new ShellyHttpApi(uid, config, httpClient);
int refreshTimer = 0;
switch(action) {
case ACTION_RES_STATS:
th.resetStats();
message = getMessageP("action.resstats.confirm", MCINFO);
refreshTimer = 3;
break;
case ACTION_RESTART:
if ("yes".equalsIgnoreCase(update)) {
message = getMessageP("action.restart.info", MCINFO);
actionButtonLabel = "Ok";
new Thread(() -> {
// schedule asynchronous reboot
try {
api.deviceReboot();
} catch (ShellyApiException e) {
// maybe the device restarts before returning the http response
}
// refresh after reboot
setRestarted(th, uid);
}).start();
refreshTimer = profile.isMotion ? 60 : 30;
} else {
message = getMessageS("action.restart.confirm", MCINFO);
actionUrl = buildActionUrl(uid, action);
}
break;
case ACTION_PROTECT:
// Get device settings
if (config.userId.isEmpty() || config.password.isEmpty()) {
message = getMessageP("action.protect.id-missing", MCWARNING);
break;
}
if (!"yes".equalsIgnoreCase(update)) {
ShellySettingsLogin status = api.getLoginSettings();
message = getMessage("action.protect.status", getBool(status.enabled) ? "enabled" : "disabled", status.username) + getMessageP("action.protect.new", MCINFO, config.userId, config.password);
actionUrl = buildActionUrl(uid, action);
} else {
api.setLoginCredentials(config.userId, config.password);
message = getMessageP("action.protect.confirm", MCINFO, config.userId, config.password);
refreshTimer = 3;
}
break;
case ACTION_SETCOIOT_MCAST:
case ACTION_SETCOIOT_PEER:
if ((profile.settings.coiot == null) || (profile.settings.coiot.peer == null)) {
// feature not available
message = getMessage("coiot.mode-not-suppored", MCWARNING, action);
break;
}
String peer = getString(profile.settings.coiot.peer);
boolean mcast = peer.isEmpty() || SHELLY_COIOT_MCAST.equalsIgnoreCase(peer);
String newPeer = mcast ? localIp + ":" + ShellyCoapJSonDTO.COIOT_PORT : SHELLY_COIOT_MCAST;
String displayPeer = mcast ? newPeer : "Multicast";
if (profile.isMotion && action.equalsIgnoreCase(ACTION_SETCOIOT_MCAST)) {
// feature not available
message = getMessageP("coiot.multicast-not-supported", "warning", displayPeer);
break;
}
if (!"yes".equalsIgnoreCase(update)) {
message = getMessageP("coiot.current-peer", MCMESSAGE, mcast ? "Multicast" : peer) + getMessageP("coiot.new-peer", MCINFO, displayPeer) + getMessageP(mcast ? "coiot.mode-peer" : "coiot.mode-mcast", MCMESSAGE);
actionUrl = buildActionUrl(uid, action);
} else {
new Thread(() -> {
// schedule asynchronous reboot
try {
api.setCoIoTPeer(newPeer);
api.deviceReboot();
} catch (ShellyApiException e) {
// maybe the device restarts before returning the http response
}
// refresh after reboot
setRestarted(th, uid);
}).start();
// The device needs a restart after changing the peer mode
message = getMessageP("action.restart.info", MCINFO);
refreshTimer = 30;
}
break;
case ACTION_ENCLOUD:
case ACTION_DISCLOUD:
boolean enabled = action.equals(ACTION_ENCLOUD);
api.setCloud(enabled);
message = getMessageP("action.setcloud.config", MCINFO, enabled ? "enabled" : "disabled");
refreshTimer = 20;
break;
case ACTION_RESET:
if (!"yes".equalsIgnoreCase(update)) {
message = getMessageP("action.reset.warning", MCWARNING, serviceName);
actionUrl = buildActionUrl(uid, action);
} else {
new Thread(() -> {
// schedule asynchronous reboot
try {
api.factoryReset();
setRestarted(th, uid);
} catch (ShellyApiException e) {
// maybe the device restarts before returning the http response
}
}).start();
message = getMessageP("action.reset.confirm", MCINFO, serviceName);
refreshTimer = 5;
}
break;
case ACTION_OTACHECK:
try {
ShellyOtaCheckResult result = api.checkForUpdate();
message = getMessage("action.checkupd." + result.status);
} catch (ShellyApiException e) {
// maybe the device restarts before returning the http response
message = getMessageP("action.checkupd.failed", e.toString());
}
refreshTimer = 3;
break;
case ACTION_ENDEBUG:
case ACTION_DISDEBUG:
boolean enable = ACTION_ENDEBUG.equalsIgnoreCase(action);
if (!"yes".equalsIgnoreCase(update)) {
message = getMessage(enable ? "action.debug-enable" : "action.debug-disable");
actionUrl = buildActionUrl(uid, action);
} else {
new Thread(() -> {
// schedule asynchronous reboot
try {
api.setDebug(enable);
} catch (ShellyApiException e) {
// maybe the device restarts before returning the http response
}
}).start();
message = getMessage("action.debug-confirm", enable ? "enabled" : "disabled");
refreshTimer = 3;
}
break;
case ACTION_RESSTA:
if (!"yes".equalsIgnoreCase(update)) {
message = getMessage("action.resetsta-info");
actionUrl = buildActionUrl(uid, action);
} else {
try {
api.resetStaCache();
message = getMessage("action.resetsta-confirm");
} catch (ShellyApiException e) {
message = getMessageP("action.resetsta-failed", e.toString());
}
refreshTimer = 10;
}
break;
case ACTION_ENWIFIREC:
case ACTION_DISWIFIREC:
enable = ACTION_ENWIFIREC.equalsIgnoreCase(action);
if (!"yes".equalsIgnoreCase(update)) {
message = getMessage(enable ? "action.setwifirec-enable" : "action.setwifirec-disable");
actionUrl = buildActionUrl(uid, action);
} else {
try {
api.setWiFiRecovery(enable);
message = getMessage("action.setwifirec-confirm", enable ? "enabled" : "disabled");
} catch (ShellyApiException e) {
message = getMessage("action.setwifirec-failed", e.toString());
}
refreshTimer = 3;
}
break;
case ACTION_ENAPROAMING:
case ACTION_DISAPROAMING:
enable = ACTION_ENAPROAMING.equalsIgnoreCase(action);
if (!"yes".equalsIgnoreCase(update)) {
message = getMessage(enable ? "action.aproaming-enable" : "action.aproaming-disable");
actionUrl = buildActionUrl(uid, action);
} else {
try {
api.setApRoaming(enable);
message = getMessage("action.aproaming-confirm", enable ? "enabled" : "disabled");
} catch (ShellyApiException e) {
message = getMessage("action.aproaming-failed", e.toString());
}
refreshTimer = 3;
}
break;
case ACTION_GETDEB:
case ACTION_GETDEB1:
try {
message = api.getDebugLog(ACTION_GETDEB.equalsIgnoreCase(action) ? "log" : "log1");
message = message.replaceAll("[\r]", "").replaceAll("[\r\n]", "<br>");
} catch (ShellyApiException e) {
message = getMessage("action.getdebug-failed", e.toString());
}
break;
case ACTION_NONE:
break;
default:
logger.warn("{}: {}", LOG_PREFIX, getMessage("action.unknown", action));
}
// get description for command
properties.put(ATTRIBUTE_ACTION, getString(actions.get(action)));
properties.put(ATTRIBUTE_ACTION_BUTTON, actionButtonLabel);
properties.put(ATTRIBUTE_ACTION_URL, actionUrl);
message = fillAttributes(message, properties);
properties.put(ATTRIBUTE_MESSAGE, message);
properties.put(ATTRIBUTE_REFRESH, String.valueOf(refreshTimer));
html += loadHTML(ACTION_HTML, properties);
// trigger background update
th.requestUpdates(1, refreshTimer > 0);
}
properties.clear();
html += loadHTML(FOOTER_HTML, properties);
return new ShellyMgrResponse(html, HttpStatus.OK_200);
}
use of org.openhab.binding.shelly.internal.api.ShellyApiException in project openhab-addons by openhab.
the class ShellyManagerPage method httpRequest.
protected String httpRequest(HttpMethod method, String url) throws ShellyApiException {
ShellyApiResult apiResult = new ShellyApiResult();
try {
Request request = httpClient.newRequest(url).method(method).timeout(SHELLY_API_TIMEOUT_MS, TimeUnit.MILLISECONDS);
request.header(HttpHeader.ACCEPT, ShellyHttpApi.CONTENT_TYPE_JSON);
logger.trace("{}: HTTP {} {}", LOG_PREFIX, method, url);
ContentResponse contentResponse = request.send();
apiResult = new ShellyApiResult(contentResponse);
String response = contentResponse.getContentAsString().replace("\t", "").replace("\r\n", "").trim();
logger.trace("{}: HTTP Response {}: {}", LOG_PREFIX, contentResponse.getStatus(), response);
// validate response, API errors are reported as Json
if (contentResponse.getStatus() != HttpStatus.OK_200) {
throw new ShellyApiException(apiResult);
}
return response;
} catch (ExecutionException | TimeoutException | InterruptedException | IllegalArgumentException e) {
throw new ShellyApiException("HTTP GET failed", e);
}
}
use of org.openhab.binding.shelly.internal.api.ShellyApiException in project openhab-addons by openhab.
the class ShellyLightHandler method handleDeviceCommand.
@Override
public boolean handleDeviceCommand(ChannelUID channelUID, Command command) throws IllegalArgumentException {
String groupName = getString(channelUID.getGroupId());
if (groupName.isEmpty()) {
throw new IllegalArgumentException("Empty groupName");
}
int lightId = getLightIdFromGroup(groupName);
logger.trace("{}: Execute command {} on channel {}, lightId={}", thingName, command, channelUID.getAsString(), lightId);
try {
ShellyColorUtils oldCol = getCurrentColors(lightId);
oldCol.mode = profile.mode;
ShellyColorUtils col = new ShellyColorUtils(oldCol);
boolean update = true;
switch(channelUID.getIdWithoutGroup()) {
default:
// non-bulb commands will be handled by the generic handler
return false;
case CHANNEL_LIGHT_POWER:
logger.debug("{}: Switch light {}", thingName, command);
api.setLightParm(lightId, SHELLY_LIGHT_TURN, command == OnOffType.ON ? SHELLY_API_ON : SHELLY_API_OFF);
col.power = (OnOffType) command;
requestUpdates(1, false);
update = false;
break;
case CHANNEL_LIGHT_COLOR_MODE:
logger.debug("{}: Select color mode {}", thingName, command);
col.setMode((OnOffType) command == OnOffType.ON ? SHELLY_MODE_COLOR : SHELLY_MODE_WHITE);
break;
case CHANNEL_COLOR_PICKER:
logger.debug("{}: Update colors from color picker", thingName);
update = handleColorPicker(profile, lightId, col, command);
break;
case CHANNEL_COLOR_FULL:
logger.debug("{}: Set colors to {}", thingName, command);
handleFullColor(col, command);
break;
case CHANNEL_COLOR_RED:
col.setRed(setColor(lightId, SHELLY_COLOR_RED, command, SHELLY_MAX_COLOR));
break;
case CHANNEL_COLOR_GREEN:
col.setGreen(setColor(lightId, SHELLY_COLOR_GREEN, command, SHELLY_MAX_COLOR));
break;
case CHANNEL_COLOR_BLUE:
col.setBlue(setColor(lightId, SHELLY_COLOR_BLUE, command, SHELLY_MAX_COLOR));
break;
case CHANNEL_COLOR_WHITE:
col.setWhite(setColor(lightId, SHELLY_COLOR_WHITE, command, SHELLY_MAX_COLOR));
break;
case CHANNEL_COLOR_GAIN:
col.setGain(setColor(lightId, SHELLY_COLOR_GAIN, command, SHELLY_MIN_GAIN, SHELLY_MAX_GAIN));
break;
case // only in white mode
CHANNEL_BRIGHTNESS:
if (profile.inColor && !profile.isBulb) {
logger.debug("{}: Not in white mode, brightness not available", thingName);
break;
}
int value = -1;
if (command instanceof OnOffType) {
// Switch
logger.debug("{}: Switch light {}", thingName, command);
ShellyShortLightStatus light = api.setRelayTurn(lightId, command == OnOffType.ON ? SHELLY_API_ON : SHELLY_API_OFF);
col.power = getOnOff(light.ison);
col.setBrightness(light.brightness);
updateChannel(CHANNEL_COLOR_WHITE, CHANNEL_BRIGHTNESS + "$Switch", col.power);
updateChannel(CHANNEL_COLOR_WHITE, CHANNEL_BRIGHTNESS + "$Value", toQuantityType((double) (col.power == OnOffType.ON ? col.brightness : 0), DIGITS_NONE, Units.PERCENT));
update = false;
break;
}
if (command instanceof PercentType) {
Float percent = ((PercentType) command).floatValue();
// 0..100% = 0..100
value = percent.intValue();
logger.debug("{}: Set brightness to {}%/{}", thingName, percent, value);
} else if (command instanceof DecimalType) {
value = ((DecimalType) command).intValue();
logger.debug("{}: Set brightness to {} (Integer)", thingName, value);
}
if (value == 0) {
logger.debug("{}: Brightness=0 -> switch light OFF", thingName);
api.setRelayTurn(lightId, SHELLY_API_OFF);
update = false;
} else {
if (command instanceof IncreaseDecreaseType) {
ShellyShortLightStatus light = api.getLightStatus(lightId);
if (((IncreaseDecreaseType) command).equals(IncreaseDecreaseType.INCREASE)) {
value = Math.min(light.brightness + DIM_STEPSIZE, 100);
} else {
value = Math.max(light.brightness - DIM_STEPSIZE, 0);
}
logger.trace("{}: Change brightness from {} to {}", thingName, light.brightness, value);
}
validateRange("brightness", value, 0, 100);
logger.debug("{}: Changing brightness from {} to {}", thingName, oldCol.brightness, value);
col.setBrightness(value);
}
updateChannel(CHANNEL_GROUP_LIGHT_CONTROL, CHANNEL_LIGHT_POWER, value > 0 ? OnOffType.ON : OnOffType.OFF);
break;
case CHANNEL_COLOR_TEMP:
Integer temp = -1;
if (command instanceof PercentType) {
logger.debug("{}: Set color temp to {}%", thingName, ((PercentType) command).floatValue());
Float percent = ((PercentType) command).floatValue() / 100;
temp = new DecimalType(col.minTemp + ((col.maxTemp - col.minTemp)) * percent).intValue();
logger.debug("{}: Converted color-temp {}% to {}K (from Percent to Integer)", thingName, percent, temp);
} else if (command instanceof DecimalType) {
temp = ((DecimalType) command).intValue();
logger.debug("{}: Set color temp to {}K (Integer)", thingName, temp);
}
validateRange(CHANNEL_COLOR_TEMP, temp, col.minTemp, col.maxTemp);
col.setTemp(temp);
col.brightness = -1;
break;
case CHANNEL_COLOR_EFFECT:
Integer effect = ((DecimalType) command).intValue();
logger.debug("{}: Set color effect to {}", thingName, effect);
validateRange("effect", effect, SHELLY_MIN_EFFECT, SHELLY_MAX_EFFECT);
col.setEffect(effect.intValue());
}
if (update) {
// check for switching color mode
if (profile.isBulb && !col.mode.isEmpty() && !col.mode.equals(oldCol.mode)) {
logger.debug("{}: Color mode changed from {} to {}, set new mode", thingName, oldCol.mode, col.mode);
api.setLightMode(col.mode);
}
// send changed colors to the device
sendColors(profile, lightId, oldCol, col, config.brightnessAutoOn);
}
return true;
} catch (ShellyApiException e) {
logger.debug("{}: Unable to handle command: {}", thingName, e.toString());
return false;
} catch (IllegalArgumentException e) {
logger.debug("{}: Unable to handle command", thingName, e);
return false;
}
}
use of org.openhab.binding.shelly.internal.api.ShellyApiException in project openhab-addons by openhab.
the class ShellyManagerOverviewPage method generateContent.
@Override
public ShellyMgrResponse generateContent(String path, Map<String, String[]> parameters) throws ShellyApiException {
String filter = getUrlParm(parameters, URLPARM_FILTER).toLowerCase();
String action = getUrlParm(parameters, URLPARM_ACTION).toLowerCase();
String uidParm = getUrlParm(parameters, URLPARM_UID).toLowerCase();
logger.debug("Generating overview for {} devices", getThingHandlers().size());
String html = "";
Map<String, String> properties = new HashMap<>();
properties.put(ATTRIBUTE_METATAG, "<meta http-equiv=\"refresh\" content=\"60\" />");
properties.put(ATTRIBUTE_CSS_HEADER, loadHTML(OVERVIEW_HEADER, properties));
String deviceHtml = "";
TreeMap<String, ShellyManagerInterface> sortedMap = new TreeMap<>();
for (Map.Entry<String, ShellyManagerInterface> th : getThingHandlers().entrySet()) {
// sort by Device Name
ShellyManagerInterface handler = th.getValue();
sortedMap.put(getDisplayName(handler.getThing().getProperties()), handler);
}
html = loadHTML(HEADER_HTML, properties);
html += loadHTML(OVERVIEW_HTML, properties);
int filteredDevices = 0;
for (Map.Entry<String, ShellyManagerInterface> handler : sortedMap.entrySet()) {
try {
ShellyManagerInterface th = handler.getValue();
ThingStatus status = th.getThing().getStatus();
ShellyDeviceProfile profile = th.getProfile();
// handler.getKey();
String uid = getString(th.getThing().getUID().getAsString());
if (action.equals(ACTION_REFRESH) && (uidParm.isEmpty() || uidParm.equals(uid))) {
// Refresh thing status, this is asynchronosly and takes 0-3sec
th.requestUpdates(1, true);
} else if (action.equals(ACTION_RES_STATS) && (uidParm.isEmpty() || uidParm.equals(uid))) {
th.resetStats();
} else if (action.equals(ACTION_OTACHECK) && (uidParm.isEmpty() || uidParm.equals(uid))) {
th.resetStats();
}
Map<String, String> warnings = getStatusWarnings(th);
if (applyFilter(th, filter) || (filter.equals(FILTER_ATTENTION) && !warnings.isEmpty())) {
filteredDevices++;
properties.clear();
fillProperties(properties, uid, handler.getValue());
String deviceType = getDeviceType(properties);
properties.put(ATTRIBUTE_DISPLAY_NAME, getDisplayName(properties));
properties.put(ATTRIBUTE_DEV_STATUS, fillDeviceStatus(warnings));
if (!warnings.isEmpty() && (status != ThingStatus.UNKNOWN)) {
properties.put(ATTRIBUTE_STATUS_ICON, ICON_ATTENTION);
}
if (!"unknown".equalsIgnoreCase(deviceType) && (status == ThingStatus.ONLINE)) {
properties.put(ATTRIBUTE_FIRMWARE_SEL, fillFirmwareHtml(uid, deviceType, profile.mode));
properties.put(ATTRIBUTE_ACTION_LIST, fillActionHtml(th, uid));
} else {
properties.put(ATTRIBUTE_FIRMWARE_SEL, "");
properties.put(ATTRIBUTE_ACTION_LIST, "");
}
html += loadHTML(OVERVIEW_DEVICE, properties);
}
} catch (ShellyApiException e) {
logger.debug("{}: Exception", LOG_PREFIX, e);
}
}
properties.clear();
properties.put("numberDevices", "<span class=\"footerDevices\">" + "Number of devices: " + filteredDevices + " of " + String.valueOf(getThingHandlers().size()) + " </span>");
properties.put(ATTRIBUTE_CSS_FOOTER, loadHTML(OVERVIEW_FOOTER, properties));
html += deviceHtml + loadHTML(FOOTER_HTML, properties);
return new ShellyMgrResponse(fillAttributes(html, properties), HttpStatus.OK_200);
}
use of org.openhab.binding.shelly.internal.api.ShellyApiException in project openhab-addons by openhab.
the class ShellyManagerOverviewPage method fillFirmwareHtml.
private String fillFirmwareHtml(String uid, String deviceType, String mode) throws ShellyApiException {
String html = "\n\t\t\t\t<select name=\"fwList\" id=\"fwList\" onchange=\"location = this.options[this.selectedIndex].value;\">\n";
html += "\t\t\t\t\t<option value=\"\" selected disabled hidden>update to</option>\n";
String pVersion = "";
String bVersion = "";
String updateUrl = SHELLY_MGR_FWUPDATE_URI + "?" + URLPARM_UID + "=" + urlEncode(uid);
try {
// Get current prod + beta version from original firmware repo
logger.debug("{}: Load firmware version list for device type {}", LOG_PREFIX, deviceType);
FwRepoEntry fw = getFirmwareRepoEntry(deviceType, mode);
pVersion = extractFwVersion(fw.version);
if (!pVersion.isEmpty()) {
html += "\t\t\t\t\t<option value=\"" + updateUrl + "&" + URLPARM_VERSION + "=" + FWPROD + "\">Release " + pVersion + "</option>\n";
}
bVersion = extractFwVersion(fw.betaVer);
if (!bVersion.isEmpty()) {
html += "\t\t\t\t\t<option value=\"" + updateUrl + "&" + URLPARM_VERSION + "=" + FWBETA + "\">Beta " + bVersion + "</option>\n";
}
// Add those from Shelly Firmware Archive
String json = httpGet(FWREPO_ARCH_URL + "?" + URLPARM_TYPE + "=" + deviceType);
if (json.startsWith("[]")) {
// no files available for this device type
logger.debug("{}: No firmware files found for device type {}", LOG_PREFIX, deviceType);
} else {
// Create selection list
// make it an named array
json = "{" + json.replace("[{", "\"versions\":[{") + "}";
FwArchList list = getFirmwareArchiveList(deviceType);
ArrayList<FwArchEntry> versions = list.versions;
if (versions != null) {
html += "\t\t\t\t\t<option value=\"\" disabled>-- Archive:</option>\n";
for (int i = versions.size() - 1; i >= 0; i--) {
FwArchEntry e = versions.get(i);
String version = getString(e.version);
ShellyVersionDTO v = new ShellyVersionDTO();
if (!version.equalsIgnoreCase(pVersion) && !version.equalsIgnoreCase(bVersion) && (v.compare(version, SHELLY_API_MIN_FWCOIOT) >= 0) || version.contains("master")) {
html += "\t\t\t\t\t<option value=\"" + updateUrl + "&" + URLPARM_VERSION + "=" + version + "\">" + version + "</option>\n";
}
}
}
}
} catch (ShellyApiException e) {
logger.debug("{}: Unable to retrieve firmware list: {}", LOG_PREFIX, e.toString());
}
html += "\t\t\t\t\t<option class=\"select-hr\" value=\"" + SHELLY_MGR_FWUPDATE_URI + "?uid=" + uid + "&connection=custom\">Custom URL</option>\n";
html += "\t\t\t\t</select>\n\t\t\t";
return html;
}
Aggregations