Search in sources :

Example 6 with ShellyApiException

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;
}
Also used : InputStreamReader(java.io.InputStreamReader) InputStream(java.io.InputStream) BufferedReader(java.io.BufferedReader) IOException(java.io.IOException) ShellyApiException(org.openhab.binding.shelly.internal.api.ShellyApiException)

Example 7 with ShellyApiException

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();
        }
    }
}
Also used : ShellyMgrResponse(org.openhab.binding.shelly.internal.manager.ShellyManagerPage.ShellyMgrResponse) OutputStream(java.io.OutputStream) ShellyApiException(org.openhab.binding.shelly.internal.api.ShellyApiException) PrintWriter(java.io.PrintWriter)

Example 8 with ShellyApiException

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);
    }
}
Also used : SocketException(java.net.SocketException) Endpoint(org.eclipse.californium.core.network.Endpoint) UnknownHostException(java.net.UnknownHostException) ShellyApiException(org.openhab.binding.shelly.internal.api.ShellyApiException) CoapClient(org.eclipse.californium.core.CoapClient) Nullable(org.eclipse.jdt.annotation.Nullable)

Example 9 with ShellyApiException

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++;
    }
}
Also used : ResponseCode(org.eclipse.californium.core.coap.CoAP.ResponseCode) ShellyApiException(org.openhab.binding.shelly.internal.api.ShellyApiException) Endpoint(org.eclipse.californium.core.network.Endpoint) JsonSyntaxException(com.google.gson.JsonSyntaxException) Option(org.eclipse.californium.core.coap.Option)

Example 10 with ShellyApiException

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));
    }
}
Also used : ShellyInputState(org.openhab.binding.shelly.internal.api.ShellyApiJsonDTO.ShellyInputState) State(org.openhab.core.types.State) DecimalType(org.openhab.core.library.types.DecimalType) ShellyApiResult(org.openhab.binding.shelly.internal.api.ShellyApiResult) ShellyApiException(org.openhab.binding.shelly.internal.api.ShellyApiException) RefreshType(org.openhab.core.types.RefreshType)

Aggregations

ShellyApiException (org.openhab.binding.shelly.internal.api.ShellyApiException)14 ShellyDeviceProfile (org.openhab.binding.shelly.internal.api.ShellyDeviceProfile)5 ShellyApiResult (org.openhab.binding.shelly.internal.api.ShellyApiResult)4 HashMap (java.util.HashMap)3 ShellyHttpApi (org.openhab.binding.shelly.internal.api.ShellyHttpApi)3 ShellyThingConfiguration (org.openhab.binding.shelly.internal.config.ShellyThingConfiguration)3 ShellyManagerInterface (org.openhab.binding.shelly.internal.handler.ShellyManagerInterface)3 IOException (java.io.IOException)2 TreeMap (java.util.TreeMap)2 Endpoint (org.eclipse.californium.core.network.Endpoint)2 Nullable (org.eclipse.jdt.annotation.Nullable)2 DecimalType (org.openhab.core.library.types.DecimalType)2 ThingStatus (org.openhab.core.thing.ThingStatus)2 JsonSyntaxException (com.google.gson.JsonSyntaxException)1 BufferedReader (java.io.BufferedReader)1 InputStream (java.io.InputStream)1 InputStreamReader (java.io.InputStreamReader)1 OutputStream (java.io.OutputStream)1 PrintWriter (java.io.PrintWriter)1 SocketException (java.net.SocketException)1