org.openhab.binding.imperihab.internal.imperiHabBinding.java Source code

Java tutorial

Introduction

Here is the source code for org.openhab.binding.imperihab.internal.imperiHabBinding.java

Source

/**
 * Copyright (c) 2010-2015, openHAB.org and others.
 *
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 */
package org.openhab.binding.imperihab.internal;

import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.URL;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.sql.Date;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Map;
import java.util.zip.GZIPOutputStream;

import org.apache.commons.lang.StringUtils;
import org.joda.time.DateTime;
import org.openhab.binding.imperihab.imperiHabBindingProvider;
import org.openhab.core.items.Item;
import org.openhab.core.items.ItemNotFoundException;
import org.openhab.core.library.types.IncreaseDecreaseType;
import org.openhab.core.library.types.OnOffType;
import org.openhab.core.library.types.StopMoveType;
import org.openhab.core.library.types.StringType;
import org.openhab.core.library.types.PercentType;
import org.openhab.core.persistence.HistoricItem;
import org.openhab.core.persistence.extensions.PersistenceExtensions;
//import org.openhab.core.persistence.extensions.PersistenceExtensions;
import org.openhab.core.types.Command;
import org.openhab.core.types.State;
import org.osgi.framework.BundleContext;
import org.osgi.service.http.NamespaceException;

//import com.sun.jmx.snmp.Timestamp;

/**
 * Implement this class if you are going create an actively polling service
 * like querying a Website/Device.
 * 
 * @author reven
 * @since 1.7.0
 */
public class imperiHabBinding extends imperiHabBindingBase {

    public imperiHabBinding() {

    }

    /**
     * Called by the SCR to activate the component with its configuration read from CAS
     * 
     * @param bundleContext BundleContext of the Bundle that defines this component
     * @param configuration Configuration properties for this component obtained from the ConfigAdmin service
     */
    public void activate(final BundleContext bundleContext, final Map<String, Object> configuration) {
        logger.debug("imperihab activate called!");
        this.bundleContext = bundleContext;

        this.openHabDirectory = System.getProperty("user.dir");
        configGo(configuration);

        Hashtable<String, String> props = new Hashtable<String, String>();
        try {
            httpService.registerServlet(SERVLET_NAME, this, props, createHttpContext());
        } catch (ServletException e) {
            // TODO Auto-generated catch block
            logger.error("ImperiHab, error registering servlet: " + e.getMessage());
            e.printStackTrace();
        } catch (NamespaceException e) {
            // TODO Auto-generated catch block
            logger.error("ImperiHab, error registering servlet: " + e.getMessage());
            e.printStackTrace();
        }

        setProperlyConfigured(true);
    }

    /**
     * @{inheritDoc}
     */
    @Override
    protected void execute() {
        // the frequently executed code (polling) goes here ...
        logger.debug("execute() method is called!");
    }

    /**
     * @{inheritDoc}
     */
    @Override
    protected void internalReceiveCommand(String itemName, Command command) {
        // the code being executed when a command was sent on the openHAB
        // event bus goes here. This method is only called if one of the 
        // BindingProviders provide a binding for the given 'itemName'.
        logger.debug("imperiHab: internalReceiveCommand({},{}) is called!", itemName, command);
        imperiHabAlarmController.internalReceiveCommand(itemName, command);
    }

    /**
     * @{inheritDoc}
     */
    @Override
    protected void internalReceiveUpdate(String itemName, State newState) {
        // the code being executed when a state was sent on the openHAB
        // event bus goes here. This method is only called if one of the 
        // BindingProviders provide a binding for the given 'itemName'.
        logger.debug("imperiHab: internalReceiveUpdate({},{}) is called!", itemName, newState);
        imperiHabAlarmController.internalReceiveUpdate(itemName, newState);
    }

    @Override
    public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
        if (req instanceof HttpServletRequest) {
            HttpServletRequest request = (HttpServletRequest) req;
            HttpServletResponse response = (HttpServletResponse) res;
            String url = request.getRequestURL().toString();
            url = url.substring(url.indexOf(SERVLET_NAME) + SERVLET_NAME.length());
            //String queryString = ((HttpServletRequest)req).getQueryString();      
            if (url.toLowerCase().startsWith("/ss-image")) {
                response.setHeader("Cache-Control", "max-age=604800,private");
                imperiHabAlarmPanel.returnImage(res, url.substring("/ss-image/".length()));
                return;
            } else if (url.toLowerCase().startsWith("/camera/")) {
                String cameraName = url.substring("/camera/".length());
                cameraImage(res, cameraName);
                return;
            }
            PrintWriter writer = null;
            GZIPOutputStream gz = null;
            if (request.getHeader("Accept-Encoding") != null
                    && request.getHeader("Accept-Encoding").contains("gzip")) {
                gz = new GZIPOutputStream(res.getOutputStream());
                writer = new PrintWriter(new OutputStreamWriter(gz, "UTF-8"));
            } else {
                writer = res.getWriter();
            }
            response.setHeader("Content-Encoding", "gzip");
            if (url.toLowerCase().equals("/alarm")) {
                response.setHeader("Cache-Control", "max-age=600,private");
            } else {
                response.setHeader("Cache-Control", "no-cache, no-store, must-revalidate"); // HTTP 1.1.
                response.setHeader("Pragma", "no-cache"); // HTTP 1.0.
                response.setDateHeader("Expires", 0); // Proxies.
            }
            if (url.toLowerCase().equals("/alarm")) {
                imperiHabAlarmPanel.writeHtml(writer);
            } else if (url.toLowerCase().equals("/alarm-status")) {
                writer.write(imperiHabAlarmController.alarmStatus());
            } else if (url.toLowerCase().equals("/alarm-arm-away")) {
                writer.write("{\"success\":" + (imperiHabAlarmController.arm(true) ? "true" : "false") + "}");
            } else if (url.toLowerCase().equals("/alarm-arm-home")) {
                writer.write("{\"success\":" + (imperiHabAlarmController.arm(false) ? "true" : "false") + "}");
            } else if (url.toLowerCase().equals("/alarm-disarm")) {
                String code = req.getParameter("code");
                if (imperiHabAlarmController.disarm(code))
                    writer.write("{\"success\":true}");
                else
                    writer.write("{\"success\":false, \"error\":\"INVALID CODE\"}");
            } else {
                //res.setCharacterEncoding("UTF-8");
                response.setHeader("Content-type", "application/json; charset=utf-8");
                if (url.toLowerCase().equals("/rooms"))
                    writer.write(generateRoomsJson());
                else if (url.toLowerCase().startsWith("/devices/") && url.toLowerCase().contains("/histo"))
                    writer.write(generateHistoryData(url));
                else if (url.toLowerCase().equals("/devices")) {
                    String host = ((HttpServletRequest) req).getRequestURL().toString();
                    host = host.substring(0, host.indexOf(("/devices")));
                    writer.write(generateDevicesJson(host));
                } else if (url.toLowerCase().equals("/system"))
                    writer.write("{\"id\":\"" + openHabInstanceName + "\", \"apiversion\":\"1\"}");
                else if (url.toLowerCase().startsWith("/devices/"))
                    writer.write(performAction(url));
            }
            writer.flush();
            writer.close();
            if (gz != null) {
                gz.flush();
                gz.close();
            }
        }
    }

    private String generateHistoryData(String requestUrl) {
        String[] parts = requestUrl.substring(1).split("/");
        String deviceId = parts[1];
        String paramKey = parts[2];
        Date start = new Date(Long.parseLong(parts[4]));
        Date end = new Date(Long.parseLong(parts[5]));
        log("deviceId: " + deviceId + ", paramKey: " + paramKey + ", start: " + start + ", end:" + end);
        Item item = null;
        try {
            item = itemRegistry.getItem(deviceId);
        } catch (ItemNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        String persistService = getPersistService(item.getName());

        ArrayList<String> data = new ArrayList<String>();
        if (item != null) {
            DateTime date = new DateTime(start.getTime());
            while (date.isAfter(end.getTime()) == false) {
                HistoricItem histItem;
                if (persistService == null)
                    histItem = PersistenceExtensions.historicState(item, date);
                else
                    histItem = PersistenceExtensions.historicState(item, date, persistService);
                if (histItem != null)
                    data.add(
                            "{\"value\":" + histItem.getState().toString() + ",\"date\":" + date.getMillis() + "}");
                date = date.plusMinutes(30);
            }
        }

        return "{\"values\":[" + imperiHabUtils.join(data, ",") + "]}";
    }

    String performAction(String requestUrl) {
        String[] parts = requestUrl.substring(1).split("/");
        String deviceId = parts[1];
        String actionName = parts[3];
        String actionParam = parts.length == 5 ? parts[4] : "";
        log("deviceId: " + deviceId + ", actionName: " + actionName + ", actionParam: " + actionParam);
        try {
            if (actionName.equalsIgnoreCase("setStatus")) {
                eventPublisher.postCommand(deviceId, actionParam.equals("1") ? OnOffType.ON : OnOffType.OFF);
                return "ok";
            } else if (actionName.equalsIgnoreCase("setLevel")) {
                eventPublisher.postCommand(deviceId, PercentType.valueOf(actionParam));
                return "ok";
            } else if (actionName.equalsIgnoreCase("setSetPoint")) {
                eventPublisher.postCommand(deviceId, PercentType.valueOf(actionParam));
                return "ok";
            } else if (actionName.equalsIgnoreCase("stopShutter")) {
                eventPublisher.postCommand(deviceId, StopMoveType.STOP);
                return "ok";
            } else if (actionName.equalsIgnoreCase("pulseShutter")) {
                if (actionParam.equalsIgnoreCase("up"))
                    eventPublisher.postCommand(deviceId, IncreaseDecreaseType.INCREASE);
                else if (actionParam.equalsIgnoreCase("down"))
                    eventPublisher.postCommand(deviceId, IncreaseDecreaseType.DECREASE);

                return "ok";
            } else if (actionName.equalsIgnoreCase("setColor")) {
                int alpha = (int) (Integer.parseInt(actionParam.substring(0, 2), 16) / 255f * 100);
                int red = Integer.parseInt(actionParam.substring(2, 4), 16);
                int green = Integer.parseInt(actionParam.substring(4, 6), 16);
                int blue = Integer.parseInt(actionParam.substring(6, 8), 16);
                // colour command is redvalue +"," + greenValue + ","+ blueValue
                String colourCommand = red + "," + green + "," + blue;
                log("#### setting RGB colour to: " + colourCommand);
                eventPublisher.postCommand(deviceId, new StringType(colourCommand));
                eventPublisher.postCommand(deviceId, PercentType.valueOf(String.valueOf(alpha)));
                return "ok";
            } else if (actionName.equalsIgnoreCase("setChoice") || actionName.equalsIgnoreCase("setMode")) {
                String targetItemId = imperiHabGenericBindingProvider.ItemLookups.get(deviceId);
                if (StringUtils.isBlank(targetItemId)) {
                    log("Failed to find targetItemId for device: " + deviceId);
                    return "No item id found.";
                }
                Item item = findItem(targetItemId);
                if (item == null) {
                    log("Failed to find targetItem from Id: " + targetItemId);
                    return "not found";
                }
                eventPublisher.postCommand(targetItemId, new StringType(actionParam));
                return "ok";
            }
        } catch (Exception ex) {
            log("Error: " + ex.getMessage());
        }
        return "bad action";
    }

    String generateRoomsJson() {
        StringBuilder sBuilder = new StringBuilder();
        sBuilder.append("{\"rooms\":[");
        ArrayList<String> rooms = new ArrayList<String>();
        for (imperiHabBindingProvider provider : this.providers) {
            for (String room : provider.getRooms()) {
                if (!rooms.contains(room)) {
                    rooms.add(room);
                    sBuilder.append("{\"id\":\"" + room + "\",\"name\":\"" + room + "\"},");
                }
            }
        }
        if (rooms.size() > 0) {
            sBuilder = sBuilder.replace(sBuilder.length() - 1, sBuilder.length(), "");
        }
        sBuilder.append("]}");

        return sBuilder.toString();
    }

    String generateDevicesJson(String hostUrl) {
        ArrayList<String> devices = new ArrayList<String>();
        HashMap<String, Item> items = new HashMap<String, Item>();
        for (Item item : itemRegistry.getItems())
            items.put(item.getName(), item);
        for (imperiHabBindingProvider provider : this.providers) {
            devices.addAll(provider.getDevices(hostUrl, items));
        }
        return "{\"devices\":[\n\t" + imperiHabUtils.join(devices, ",\n\t") + "\n]}";
    }

    Item findItem(String name) {
        for (Item item : itemRegistry.getItems())
            if (name.equals(item.getName()))
                return item;
        return null;
    }

    String getPersistService(String name) {
        for (imperiHabBindingProvider provider : this.providers) {
            String persistService = provider.getPersistService(name);
            if (persistService != null)
                return persistService;
        }
        return null;
    }

    public static void cameraImage(ServletResponse response, String cameraName) {
        String cameraUrl = imperiHabGenericBindingProvider.ItemLookups.get(cameraName);

        logger.debug("imerpihab2: returning image: " + cameraUrl);
        try {
            response.setContentType("image/jpeg");

            URL url = new URL(cameraUrl);
            InputStream is = url.openStream();
            OutputStream out = response.getOutputStream();

            byte[] b = new byte[2048];
            int length;

            while ((length = is.read(b)) != -1) {
                out.write(b, 0, length);
            }

            is.close();
            out.close();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            logger.debug("imperihab2: error: " + e.getMessage());
            e.printStackTrace();

        }
    }
}