package com.francetelecom.m2m.gateway.bundle.application; import java.io.IOException; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.json.simple.JSONArray; import org.json.simple.JSONObject; import org.osgi.service.http.HttpService; import org.osgi.service.http.NamespaceException; import org.osgi.service.log.LogService; import com.francetelecom.m2m.gateway.service.machine.zcl.element.EndPointService; import com.orange.openthebox.hab.HueLightDevice; import com.st.greennet.service.Actuator; import com.st.greennet.service.Device; /** * This servlet exposes as a REST API the Fire Application. This servlet is * available at /FireApplication/rest. It provides the following commands : * <ul> * <li>GET /status returns as a json string the status of the Fire application. * See</li> * </ul> * * * @author mpcy8647 * */ public class FireApplicationServlet extends HttpServlet { /** * Rest servlet alias */ private static final String REST_SERVLET_ALIAS = "/FireApplication/rest"; /** * IHM */ private static final String IHM_ALIAS = "/FireApplication"; /** * log prefix */ private static final String LOG_PREFIX = "[FIRE_APPLICATION_REST_SERVLET] "; /** * status path */ private static final String STATUS_PATH = "/status"; /** * enable path */ private static final String ENABLE_PATH = "/enable"; /** * disable path */ private static final String DISABLE_PATH = "/disable"; /** * init demo path. */ private static final String INIT_DEMO_PATH = "/initDemo"; /** * devices path */ private static final String DEVICES = "/devices"; /** * Zigbee techno */ private static final String ZIGBEE_TECHNO = "ZigBee"; /** * Hue techno */ private static final String HUE_TECHNO = "Hue"; /** * X3D techno */ private static final String X3D_TECHNO = "X3D"; /** * GreenNet techno */ private static final String GREENNET_TECHNO = "GreenNet"; /** * PUMP img. */ private static final String PUMP_IMG = "img/zigbeePump.png"; /** * SMOKE DETECTOR IMG */ private static final String SMOKE_DETECTOR_IMG = "img/zigbeeSmokeDetector.png"; /** * WARNING IMG */ private static final String WARNING_IMG = "img/zigbeeWarning.png"; /** * HUE LIGHT IMG */ private static final String HUE_LIGHT_IMG = "img/hueLight.png"; /** * X3D DIMMER IMG */ private static final String X3D_DIMMER_IMG = "img/x3dDimmer.png"; /** * GREENNET AIR EJECTOR IMG */ private static final String GREENNET_AIR_EJECTOR_IMG = "img/greennetAirEjector.png"; /** * PUMPS property name for device. */ private static final String PUMPS_PROP = "pumps"; /** * IAS ZONES property name for device. */ private static final String IAS_ZONES_PROP = "iasZones"; /** * IAS WARNING property name for device. */ private static final String IAS_WARNING_PROP = "iasWarnings"; /** * PUMP prefix id */ private static final String PUMP_PREFIX_ID = "pump_"; /** * IAS ZONES prefix id */ private static final String IAS_ZONES_PREFIX_ID = "iasZone_"; /** * IAS WARNING prefix id */ private static final String IAS_WARNING_PREFIX_ID = "iasWarning_"; /** * HUE PREFIX id */ private static final String HUE_PREFIX_ID = "hueLight_"; /** * x3d dimmer prefix id */ private static final String X3D_DIMMER_PREFIX_ID = "x3dDimmer_"; /** * NAME property name for device */ private static final String NAME_PROP = "name"; /** * ID property name for device */ private static final String ID_PROP = "id"; /** * TECHNO property name for device */ private static final String TECHNO_PROP = "techno"; /** * IMG property name for device */ private static final String IMG_PROP = "img"; /** * http service (mandatory) */ private final HttpService httpService; /** * logService (mandatory) */ private LogService logService; /** * fire application service */ private final FireApplicationService_Impl fireApplication; public FireApplicationServlet(final HttpService pHttpService, final FireApplicationService_Impl pFireApplication) { httpService = pHttpService; fireApplication = pFireApplication; } /** * This method is called when an HTTP get is received by the servlet */ protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String path = req.getPathInfo(); if (STATUS_PATH.equals(path)) { executeDoGetStatus(req, resp); } else if (DEVICES.equals(path)) { executeDoGetDevices(req, resp); } else { // invalid path // returns 404 resp.setStatus(HttpServletResponse.SC_NOT_FOUND); } } protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String path = req.getPathInfo(); if (ENABLE_PATH.equals(path)) { executeDoPostEnable(req, resp); } else if (DISABLE_PATH.equals(path)) { executeDoPostDisable(req, resp); } else if (INIT_DEMO_PATH.equals(path)) { } else { // invalid path // returns 404 resp.setStatus(HttpServletResponse.SC_NOT_FOUND); } } /** * Register the rest servlet. */ protected void registerRestServlet() { try { httpService.registerServlet(REST_SERVLET_ALIAS, this, null, null); } catch (ServletException e) { log(LogService.LOG_ERROR, "unable to register the REST servlet " + e.getMessage(), e); } catch (NamespaceException e) { log(LogService.LOG_ERROR, "unable to register the REST servlet " + e.getMessage(), e); } } /** * Unregister this rest servlet. */ protected void unregisterRestServlet() { httpService.unregister(REST_SERVLET_ALIAS); } /** * Register IHM resource (html, js) servlet. */ protected void registerResourceServlet() { try { httpService.registerResources(IHM_ALIAS, "WEB-INF", null); } catch (NamespaceException e) { log(LogService.LOG_ERROR, "unable to register the IHM servlet " + e.getMessage(), e); } } /** * Unregister IHM resource servlet. */ protected void unregisterResourceServlet() { httpService.unregister(IHM_ALIAS); } /** * Set the log service. * * @param pLogService * log service */ protected void setLogService(LogService pLogService) { logService = pLogService; } protected void unsetLogService(LogService pLogService) { logService = null; } /** * Retrieves the status as a Json list. this list contains the status * boolean parameter. * * @param request * request * @param response * response */ private void executeDoGetStatus(final HttpServletRequest request, final HttpServletResponse response) { ApplicationStatus as = fireApplication.getStatus(); JSONObject jsonObject = new JSONObject(); jsonObject.put("status", new Integer(as.getCurrentState())); JSONArray errorCodeJson = new JSONArray(); errorCodeJson.addAll(as.getErrorCodes()); jsonObject.put("errorCodes", errorCodeJson); response.setStatus(HttpServletResponse.SC_OK); try { response.getWriter().println(jsonObject.toString()); } catch (IOException e) { response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); log(LogService.LOG_ERROR, "unable to write response about application status", e); } } private void executeDoGetDevices(HttpServletRequest req, HttpServletResponse resp) { JSONObject devices = new JSONObject(); // pumps List pumps = fireApplication.getPumps(); JSONArray pumpsArray = new JSONArray(); for (Iterator it = pumps.iterator(); it.hasNext();) { EndPointService es = (EndPointService) it.next(); String name = es.getName(); String friendlyName = getDeviceFriendlyNameId(es); name = name + " " + friendlyName; // remove first # from friendlyname friendlyName = friendlyName.replaceAll("#", ""); String id = PUMP_PREFIX_ID + friendlyName; Map properties = new HashMap(); properties.put(ID_PROP, id); properties.put(NAME_PROP, name); properties.put(TECHNO_PROP, ZIGBEE_TECHNO); properties.put(IMG_PROP, PUMP_IMG); JSONObject pumpJs = new JSONObject(properties); pumpsArray.add(pumpJs); } // GreenNet switches is also viewed as a pump (i.e. actuator) List greenNetSwitches = fireApplication.getGreenNetSwitches(); for(Iterator it = greenNetSwitches.iterator(); it.hasNext();) { Device greenNetSwitch = (Device) it.next(); String id = ((Actuator)greenNetSwitch).getNode().getIdentifier(); String name = "Air extractor"; Map properties = new HashMap(); properties.put(ID_PROP, id); properties.put(NAME_PROP, name); properties.put(TECHNO_PROP, GREENNET_TECHNO); properties.put(IMG_PROP, GREENNET_AIR_EJECTOR_IMG); JSONObject pumpJs = new JSONObject(properties); pumpsArray.add(pumpJs); } devices.put(PUMPS_PROP, pumpsArray); // ias zones List zones = fireApplication.getZoneDevices(); JSONArray zonesArray = new JSONArray(); for (Iterator it = zones.iterator(); it.hasNext();) { EndPointService es = (EndPointService) it.next(); String name = es.getName(); String friendlyName = getDeviceFriendlyNameId(es); name = name + " " + friendlyName; // remove first # from friendlyname friendlyName = friendlyName.replaceAll("#", ""); String id = IAS_ZONES_PREFIX_ID + friendlyName; Map properties = new HashMap(); properties.put(ID_PROP, id); properties.put(NAME_PROP, name); properties.put(TECHNO_PROP, ZIGBEE_TECHNO); properties.put(IMG_PROP, SMOKE_DETECTOR_IMG); JSONObject zoneJs = new JSONObject(properties); zonesArray.add(zoneJs); } devices.put(IAS_ZONES_PROP, zonesArray); // warning devices List warnings = fireApplication.getWarningDevices(); JSONArray warningArray = new JSONArray(); for (Iterator it = warnings.iterator(); it.hasNext();) { EndPointService es = (EndPointService) it.next(); String name = es.getName(); String friendlyName = getDeviceFriendlyNameId(es); name = name + " " + friendlyName; // remove first # from friendlyname friendlyName = friendlyName.replaceAll("#", ""); String id = IAS_WARNING_PREFIX_ID + friendlyName; Map properties = new HashMap(); properties.put(ID_PROP, id); properties.put(NAME_PROP, name); properties.put(TECHNO_PROP, ZIGBEE_TECHNO); properties.put(IMG_PROP, WARNING_IMG); JSONObject warningJs = new JSONObject(properties); warningArray.add(warningJs); } // x3d dimmers are also considered as warning devices List x3dDimmers = fireApplication.getX3DDimmers(); int index = 1; for(Iterator it = x3dDimmers.iterator(); it.hasNext();) { X3DLightDimmer dimmer = (X3DLightDimmer) it.next(); String id = X3D_DIMMER_PREFIX_ID + dimmer.getX3DDevice().getDeviceUri(); id = id.replaceAll(" ", ""); id = id.replaceAll("/", ""); id = id.replaceAll(":", ""); String name = "X3D Dimmer #" + index; index++; Map properties = new HashMap(); properties.put(ID_PROP, id); properties.put(NAME_PROP, name); properties.put(TECHNO_PROP, X3D_TECHNO); properties.put(IMG_PROP, X3D_DIMMER_IMG); JSONObject warningJs = new JSONObject(properties); warningArray.add(warningJs); } // hue light are also considered as warning devices List hueLights = fireApplication.getHueLights(); for(Iterator it = hueLights.iterator(); it.hasNext();) { HueLightDevice hld = (HueLightDevice) it.next(); String name = hld.getName(); String id = HUE_PREFIX_ID + hld.getId(); Map properties = new HashMap(); properties.put(ID_PROP, id); properties.put(NAME_PROP, name); properties.put(TECHNO_PROP, HUE_TECHNO); properties.put(IMG_PROP, HUE_LIGHT_IMG); JSONObject warningJs = new JSONObject(properties); warningArray.add(warningJs); } devices.put(IAS_WARNING_PROP, warningArray); try { resp.getWriter().print(devices.toJSONString()); resp.setStatus(HttpServletResponse.SC_OK); } catch (IOException e) { resp.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); } } /** * Enable the application. * * @param request * request * @param response * response (200 OK) */ private void executeDoPostEnable(final HttpServletRequest request, final HttpServletResponse response) { fireApplication.enable(); response.setStatus(HttpServletResponse.SC_OK); } /** * Disable the application. * * @param request * request * @param response * response (200 OK) */ private void executeDoPostDisable(final HttpServletRequest request, final HttpServletResponse response) { fireApplication.disable(); response.setStatus(HttpServletResponse.SC_NO_CONTENT); } /** * Init the demo, i.e. open all pumps. * * @param request * @param response */ private void executeDoPostInitDemo(final HttpServletRequest request, final HttpServletResponse response) { fireApplication.initService(); response.setStatus(HttpServletResponse.SC_NO_CONTENT); } /** * Log message using the log service if available * * @param logLevel * Http service log level * @param msg * message * @param e * exception. May be null */ private void log(int logLevel, String msg, Throwable e) { if (logService != null) { logService.log(logLevel, LOG_PREFIX + msg, e); } } private static String getDeviceFriendlyNameId(EndPointService es) { String fnId = "#"; String technoId = es.getCapillaryElementService().getTechnoId(); // get the four last character of the technoId field fnId = fnId + technoId.substring(technoId.length() - 4, technoId.length()); return fnId; } }