diff --git a/modules/samples/firealarm/component/analytics/build.xml b/modules/samples/firealarm/component/analytics/build.xml new file mode 100644 index 00000000..2f3be332 --- /dev/null +++ b/modules/samples/firealarm/component/analytics/build.xml @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/modules/samples/firealarm/component/analytics/pom.xml b/modules/samples/firealarm/component/analytics/pom.xml new file mode 100644 index 00000000..d587c1ae --- /dev/null +++ b/modules/samples/firealarm/component/analytics/pom.xml @@ -0,0 +1,90 @@ + + + + + + + org.homeautomation + firealarm-component + 1.0.0-SNAPSHOT + ../pom.xml + + 4.0.0 + ${groupId}.firealarm.analytics + 1.0.0-SNAPSHOT + pom + ${groupId}.firealarm.analytics + http://wso2.org + + + + maven-clean-plugin + ${maven-clean-plugin.version} + + + auto-clean + initialize + + clean + + + + + + maven-antrun-plugin + ${wso2.maven.compiler.source} + + + process-resources + + + + + + + run + + + + + + maven-assembly-plugin + ${maven-assembly-plugin.version} + + ${project.artifactId}-1.0.0-SNAPSHOT + false + + src/assembly/src.xml + + + + + create-archive + package + + single + + + + + + + \ No newline at end of file diff --git a/modules/samples/firealarm/component/analytics/src/assembly/src.xml b/modules/samples/firealarm/component/analytics/src/assembly/src.xml new file mode 100644 index 00000000..b7735b0b --- /dev/null +++ b/modules/samples/firealarm/component/analytics/src/assembly/src.xml @@ -0,0 +1,36 @@ + + + + src + + zip + + false + ${basedir}/src + + + ${basedir}/target/carbonapps + / + true + + + \ No newline at end of file diff --git a/modules/samples/firealarm/component/analytics/src/main/resources/carbonapps/Humidity_Sensor/Eventreceiver_humidity_1.0.0/EventReceiver_humidity.xml b/modules/samples/firealarm/component/analytics/src/main/resources/carbonapps/Humidity_Sensor/Eventreceiver_humidity_1.0.0/EventReceiver_humidity.xml new file mode 100644 index 00000000..8f117bdb --- /dev/null +++ b/modules/samples/firealarm/component/analytics/src/main/resources/carbonapps/Humidity_Sensor/Eventreceiver_humidity_1.0.0/EventReceiver_humidity.xml @@ -0,0 +1,27 @@ + + + + + + false + + + + diff --git a/modules/samples/firealarm/component/analytics/src/main/resources/carbonapps/Humidity_Sensor/Eventreceiver_humidity_1.0.0/artifact.xml b/modules/samples/firealarm/component/analytics/src/main/resources/carbonapps/Humidity_Sensor/Eventreceiver_humidity_1.0.0/artifact.xml new file mode 100644 index 00000000..59756609 --- /dev/null +++ b/modules/samples/firealarm/component/analytics/src/main/resources/carbonapps/Humidity_Sensor/Eventreceiver_humidity_1.0.0/artifact.xml @@ -0,0 +1,23 @@ + + + + + EventReceiver_humidity.xml + diff --git a/modules/samples/firealarm/component/analytics/src/main/resources/carbonapps/Humidity_Sensor/Eventstore_humidity_1.0.0/artifact.xml b/modules/samples/firealarm/component/analytics/src/main/resources/carbonapps/Humidity_Sensor/Eventstore_humidity_1.0.0/artifact.xml new file mode 100644 index 00000000..484978bb --- /dev/null +++ b/modules/samples/firealarm/component/analytics/src/main/resources/carbonapps/Humidity_Sensor/Eventstore_humidity_1.0.0/artifact.xml @@ -0,0 +1,23 @@ + + + + + org_wso2_iot_devices_humidity.xml + diff --git a/modules/samples/firealarm/component/analytics/src/main/resources/carbonapps/Humidity_Sensor/Eventstore_humidity_1.0.0/org_wso2_iot_devices_humidity.xml b/modules/samples/firealarm/component/analytics/src/main/resources/carbonapps/Humidity_Sensor/Eventstore_humidity_1.0.0/org_wso2_iot_devices_humidity.xml new file mode 100644 index 00000000..5d490868 --- /dev/null +++ b/modules/samples/firealarm/component/analytics/src/main/resources/carbonapps/Humidity_Sensor/Eventstore_humidity_1.0.0/org_wso2_iot_devices_humidity.xml @@ -0,0 +1,62 @@ + + + + + + org.wso2.iot.devices.humidity:1.0.0 + + EVENT_STORE + + + meta_owner + true + true + false + STRING + + + meta_deviceType + true + true + false + STRING + + + meta_deviceId + true + true + false + STRING + + + meta_time + true + true + false + LONG + + + humidity + false + false + false + FLOAT + + + \ No newline at end of file diff --git a/modules/samples/firealarm/component/analytics/src/main/resources/carbonapps/Humidity_Sensor/Eventstream_humidity_1.0.0/artifact.xml b/modules/samples/firealarm/component/analytics/src/main/resources/carbonapps/Humidity_Sensor/Eventstream_humidity_1.0.0/artifact.xml new file mode 100644 index 00000000..84836c69 --- /dev/null +++ b/modules/samples/firealarm/component/analytics/src/main/resources/carbonapps/Humidity_Sensor/Eventstream_humidity_1.0.0/artifact.xml @@ -0,0 +1,24 @@ + + + + + org.wso2.iot.devices.humidity_1.0.0.json + + diff --git a/modules/samples/firealarm/component/analytics/src/main/resources/carbonapps/Humidity_Sensor/Eventstream_humidity_1.0.0/org.wso2.iot.devices.humidity_1.0.0.json b/modules/samples/firealarm/component/analytics/src/main/resources/carbonapps/Humidity_Sensor/Eventstream_humidity_1.0.0/org.wso2.iot.devices.humidity_1.0.0.json new file mode 100644 index 00000000..fd9ea41b --- /dev/null +++ b/modules/samples/firealarm/component/analytics/src/main/resources/carbonapps/Humidity_Sensor/Eventstream_humidity_1.0.0/org.wso2.iot.devices.humidity_1.0.0.json @@ -0,0 +1,33 @@ +{ + "name": "org.wso2.iot.devices.humidity", + "version": "1.0.0", + "nickName": "Humidity Data", + "description": "Humidity data received from the Device", + "metaData": [ + { + "name": "owner", + "type": "STRING" + }, + { + "name": "deviceType", + "type": "STRING" + }, + { + "name": "deviceId", + "type": "STRING" + }, + { + "name": "time", + "type": "LONG" + } + ], + "payloadData": [ + { + "name": "humidity", + "type": "FLOAT" + } + ] +} + + + diff --git a/modules/samples/firealarm/component/analytics/src/main/resources/carbonapps/Humidity_Sensor/Sparkscripts_1.0.0/Humidity_Sensor_Script.xml b/modules/samples/firealarm/component/analytics/src/main/resources/carbonapps/Humidity_Sensor/Sparkscripts_1.0.0/Humidity_Sensor_Script.xml new file mode 100644 index 00000000..ed215baa --- /dev/null +++ b/modules/samples/firealarm/component/analytics/src/main/resources/carbonapps/Humidity_Sensor/Sparkscripts_1.0.0/Humidity_Sensor_Script.xml @@ -0,0 +1,37 @@ + + + + + IoTServer_Sensor_Script + + 0 * * * * ? + diff --git a/modules/samples/firealarm/component/analytics/src/main/resources/carbonapps/Humidity_Sensor/Sparkscripts_1.0.0/artifact.xml b/modules/samples/firealarm/component/analytics/src/main/resources/carbonapps/Humidity_Sensor/Sparkscripts_1.0.0/artifact.xml new file mode 100644 index 00000000..1d92c387 --- /dev/null +++ b/modules/samples/firealarm/component/analytics/src/main/resources/carbonapps/Humidity_Sensor/Sparkscripts_1.0.0/artifact.xml @@ -0,0 +1,23 @@ + + + + + Humidity_Sensor_Script.xml + diff --git a/modules/samples/firealarm/component/analytics/src/main/resources/carbonapps/Humidity_Sensor/artifacts.xml b/modules/samples/firealarm/component/analytics/src/main/resources/carbonapps/Humidity_Sensor/artifacts.xml new file mode 100644 index 00000000..d89620e4 --- /dev/null +++ b/modules/samples/firealarm/component/analytics/src/main/resources/carbonapps/Humidity_Sensor/artifacts.xml @@ -0,0 +1,33 @@ + + + + + + + + + + + + + diff --git a/modules/samples/firealarm/component/analytics/src/main/resources/carbonapps/Temperature_Sensor/Eventreceiver_temperature_1.0.0/EventReceiver_temperature.xml b/modules/samples/firealarm/component/analytics/src/main/resources/carbonapps/Temperature_Sensor/Eventreceiver_temperature_1.0.0/EventReceiver_temperature.xml new file mode 100644 index 00000000..b4026b4e --- /dev/null +++ b/modules/samples/firealarm/component/analytics/src/main/resources/carbonapps/Temperature_Sensor/Eventreceiver_temperature_1.0.0/EventReceiver_temperature.xml @@ -0,0 +1,27 @@ + + + + + + false + + + + diff --git a/modules/samples/firealarm/component/analytics/src/main/resources/carbonapps/Temperature_Sensor/Eventreceiver_temperature_1.0.0/artifact.xml b/modules/samples/firealarm/component/analytics/src/main/resources/carbonapps/Temperature_Sensor/Eventreceiver_temperature_1.0.0/artifact.xml new file mode 100644 index 00000000..7cac6e0b --- /dev/null +++ b/modules/samples/firealarm/component/analytics/src/main/resources/carbonapps/Temperature_Sensor/Eventreceiver_temperature_1.0.0/artifact.xml @@ -0,0 +1,23 @@ + + + + + EventReceiver_temperature.xml + diff --git a/modules/samples/firealarm/component/analytics/src/main/resources/carbonapps/Temperature_Sensor/Eventstore_temperature_1.0.0/artifact.xml b/modules/samples/firealarm/component/analytics/src/main/resources/carbonapps/Temperature_Sensor/Eventstore_temperature_1.0.0/artifact.xml new file mode 100644 index 00000000..02990e3c --- /dev/null +++ b/modules/samples/firealarm/component/analytics/src/main/resources/carbonapps/Temperature_Sensor/Eventstore_temperature_1.0.0/artifact.xml @@ -0,0 +1,23 @@ + + + + + org_wso2_iot_devices_temperature.xml + diff --git a/modules/samples/firealarm/component/analytics/src/main/resources/carbonapps/Temperature_Sensor/Eventstore_temperature_1.0.0/org_wso2_iot_devices_temperature.xml b/modules/samples/firealarm/component/analytics/src/main/resources/carbonapps/Temperature_Sensor/Eventstore_temperature_1.0.0/org_wso2_iot_devices_temperature.xml new file mode 100644 index 00000000..9e41647b --- /dev/null +++ b/modules/samples/firealarm/component/analytics/src/main/resources/carbonapps/Temperature_Sensor/Eventstore_temperature_1.0.0/org_wso2_iot_devices_temperature.xml @@ -0,0 +1,62 @@ + + + + + + org.wso2.iot.devices.temperature:1.0.0 + + EVENT_STORE + + + meta_owner + true + true + false + STRING + + + meta_deviceType + true + true + false + STRING + + + meta_deviceId + true + true + false + STRING + + + meta_time + true + true + false + LONG + + + temperature + false + false + false + FLOAT + + + \ No newline at end of file diff --git a/modules/samples/firealarm/component/analytics/src/main/resources/carbonapps/Temperature_Sensor/Eventstream_temperature_1.0.0/artifact.xml b/modules/samples/firealarm/component/analytics/src/main/resources/carbonapps/Temperature_Sensor/Eventstream_temperature_1.0.0/artifact.xml new file mode 100644 index 00000000..6f41292b --- /dev/null +++ b/modules/samples/firealarm/component/analytics/src/main/resources/carbonapps/Temperature_Sensor/Eventstream_temperature_1.0.0/artifact.xml @@ -0,0 +1,24 @@ + + + + + org.wso2.iot.devices.temperature_1.0.0.json + + diff --git a/modules/samples/firealarm/component/analytics/src/main/resources/carbonapps/Temperature_Sensor/Eventstream_temperature_1.0.0/org.wso2.iot.devices.temperature_1.0.0.json b/modules/samples/firealarm/component/analytics/src/main/resources/carbonapps/Temperature_Sensor/Eventstream_temperature_1.0.0/org.wso2.iot.devices.temperature_1.0.0.json new file mode 100644 index 00000000..b851e5bb --- /dev/null +++ b/modules/samples/firealarm/component/analytics/src/main/resources/carbonapps/Temperature_Sensor/Eventstream_temperature_1.0.0/org.wso2.iot.devices.temperature_1.0.0.json @@ -0,0 +1,33 @@ +{ + "name": "org.wso2.iot.devices.temperature", + "version": "1.0.0", + "nickName": "Temperature Data", + "description": "Temperature data received from the Device", + "metaData": [ + { + "name": "owner", + "type": "STRING" + }, + { + "name": "deviceType", + "type": "STRING" + }, + { + "name": "deviceId", + "type": "STRING" + }, + { + "name": "time", + "type": "LONG" + } + ], + "payloadData": [ + { + "name": "temperature", + "type": "FLOAT" + } + ] +} + + + diff --git a/modules/samples/firealarm/component/analytics/src/main/resources/carbonapps/Temperature_Sensor/Sparkscripts_1.0.0/Temperature_Sensor_Script.xml b/modules/samples/firealarm/component/analytics/src/main/resources/carbonapps/Temperature_Sensor/Sparkscripts_1.0.0/Temperature_Sensor_Script.xml new file mode 100644 index 00000000..d184528c --- /dev/null +++ b/modules/samples/firealarm/component/analytics/src/main/resources/carbonapps/Temperature_Sensor/Sparkscripts_1.0.0/Temperature_Sensor_Script.xml @@ -0,0 +1,37 @@ + + + + + IoTServer_Sensor_Script + + 0 * * * * ? + diff --git a/modules/samples/firealarm/component/analytics/src/main/resources/carbonapps/Temperature_Sensor/Sparkscripts_1.0.0/artifact.xml b/modules/samples/firealarm/component/analytics/src/main/resources/carbonapps/Temperature_Sensor/Sparkscripts_1.0.0/artifact.xml new file mode 100644 index 00000000..fa653516 --- /dev/null +++ b/modules/samples/firealarm/component/analytics/src/main/resources/carbonapps/Temperature_Sensor/Sparkscripts_1.0.0/artifact.xml @@ -0,0 +1,23 @@ + + + + + Temperature_Sensor_Script.xml + diff --git a/modules/samples/firealarm/component/analytics/src/main/resources/carbonapps/Temperature_Sensor/artifacts.xml b/modules/samples/firealarm/component/analytics/src/main/resources/carbonapps/Temperature_Sensor/artifacts.xml new file mode 100644 index 00000000..4fa4b796 --- /dev/null +++ b/modules/samples/firealarm/component/analytics/src/main/resources/carbonapps/Temperature_Sensor/artifacts.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + diff --git a/modules/samples/firealarm/component/controller/pom.xml b/modules/samples/firealarm/component/controller/pom.xml new file mode 100644 index 00000000..0ffa899e --- /dev/null +++ b/modules/samples/firealarm/component/controller/pom.xml @@ -0,0 +1,226 @@ + + + + + + + org.homeautomation + firealarm-component + 1.0.0-SNAPSHOT + ../pom.xml + + 4.0.0 + ${groupId}.firealarm.controller + 1.0.0-SNAPSHOT + war + ${groupId}.firealarm.controller + http://wso2.com + + + + org.apache.maven.plugins + maven-compiler-plugin + ${maven-compiler-plugin.version} + + UTF-8 + ${wso2.maven.compiler.source} + ${wso2.maven.compiler.target} + + + + maven-war-plugin + ${maven-war-plugin.version} + + ${groupId}.firealarm.controller + + + + + + + org.homeautomation + ${project-base-package}.plugin + + + + org.wso2.carbon.devicemgt + org.wso2.carbon.device.mgt.common + + + org.wso2.carbon.devicemgt + org.wso2.carbon.device.mgt.core + + + org.apache.axis2.wso2 + axis2-client + + + + + + org.wso2.carbon.devicemgt + org.wso2.carbon.device.mgt.analytics + + + org.apache.axis2.wso2 + axis2-client + + + + + + org.wso2.carbon.devicemgt + org.wso2.carbon.certificate.mgt.core + + + + + org.apache.cxf + cxf-rt-frontend-jaxws + + + org.apache.cxf + cxf-rt-frontend-jaxrs + + + org.apache.cxf + cxf-rt-transports-http + + + + + org.apache.httpcomponents + httpasyncclient + 4.1 + + + org.wso2.carbon.devicemgt-plugins + org.wso2.carbon.device.mgt.iot + + + + + org.eclipse.paho + org.eclipse.paho.client.mqttv3 + + + + + org.codehaus.jackson + jackson-core-asl + + + org.codehaus.jackson + jackson-jaxrs + + + javax + javaee-web-api + + + javax.ws.rs + jsr311-api + + + commons-httpclient.wso2 + commons-httpclient + + + + org.wso2.carbon + org.wso2.carbon.utils + + + org.bouncycastle.wso2 + bcprov-jdk15on + + + org.wso2.carbon + org.wso2.carbon.user.api + + + org.wso2.carbon + org.wso2.carbon.queuing + + + org.wso2.carbon + org.wso2.carbon.base + + + org.apache.axis2.wso2 + axis2 + + + org.igniterealtime.smack.wso2 + smack + + + org.igniterealtime.smack.wso2 + smackx + + + jaxen + jaxen + + + commons-fileupload.wso2 + commons-fileupload + + + org.apache.ant.wso2 + ant + + + org.apache.ant.wso2 + ant + + + commons-httpclient.wso2 + commons-httpclient + + + org.eclipse.equinox + javax.servlet + + + org.wso2.carbon + org.wso2.carbon.registry.api + + + + + org.igniterealtime.smack.wso2 + smack + + + org.igniterealtime.smack.wso2 + smackx + + + org.wso2.carbon.devicemgt + org.wso2.carbon.apimgt.annotations + + + org.json.wso2 + json + + + \ No newline at end of file diff --git a/modules/samples/firealarm/component/controller/src/main/java/org.homeautomation/firealarm/controller/api/ControllerService.java b/modules/samples/firealarm/component/controller/src/main/java/org.homeautomation/firealarm/controller/api/ControllerService.java new file mode 100644 index 00000000..20fdcd86 --- /dev/null +++ b/modules/samples/firealarm/component/controller/src/main/java/org.homeautomation/firealarm/controller/api/ControllerService.java @@ -0,0 +1,220 @@ +/* +* Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. +* +* WSO2 Inc. licenses this file to you under the Apache License, +* Version 2.0 (the "License"); you may not use this file except +* in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +package org.homeautomation.firealarm.controller.api; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.homeautomation.firealarm.controller.api.dto.DeviceJSON; +import org.homeautomation.firealarm.controller.api.exception.DeviceTypeException; +import org.homeautomation.firealarm.controller.api.transport.MQTTConnector; +import org.homeautomation.firealarm.plugin.constants.DeviceTypeConstants; +import org.wso2.carbon.apimgt.annotations.api.API; +import org.wso2.carbon.apimgt.annotations.device.DeviceType; +import org.wso2.carbon.apimgt.annotations.device.feature.Feature; +import org.wso2.carbon.context.CarbonContext; +import org.wso2.carbon.device.mgt.common.DeviceIdentifier; +import org.wso2.carbon.device.mgt.common.DeviceManagementException; +import org.wso2.carbon.device.mgt.iot.DeviceManagement; +import org.wso2.carbon.device.mgt.iot.DeviceValidator; +import org.wso2.carbon.device.mgt.iot.controlqueue.mqtt.MqttConfig; +import org.wso2.carbon.device.mgt.iot.exception.DeviceControllerException; +import org.wso2.carbon.device.mgt.iot.sensormgt.SensorDataManager; +import org.wso2.carbon.device.mgt.iot.sensormgt.SensorRecord; + +import javax.servlet.http.HttpServletResponse; +import javax.ws.rs.Consumes; +import javax.ws.rs.FormParam; +import javax.ws.rs.GET; +import javax.ws.rs.HeaderParam; +import javax.ws.rs.POST; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; + +/** + * This is the controller API which is used to control agent side functionality + */ +@SuppressWarnings("NonJaxWsWebServices") +@API(name = "firealarm", version = "1.0.0", context = "/firealarm") +@DeviceType(value = "firealarm") +public class ControllerService { + + private static Log log = LogFactory.getLog(ControllerService.class); + private MQTTConnector mqttConnector; + + private boolean waitForServerStartup() { + while (!DeviceManagement.isServerReady()) { + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + return true; + } + } + return false; + } + + @SuppressWarnings("unused") + public MQTTConnector getMQTTConnector() { + return mqttConnector; + } + + @SuppressWarnings("unused") + public void setMQTTConnector(final MQTTConnector MQTTConnector) { + Runnable connector = new Runnable() { + public void run() { + if (waitForServerStartup()) { + return; + } + ControllerService.this.mqttConnector = MQTTConnector; + if (MqttConfig.getInstance().isEnabled()) { + mqttConnector.connect(); + } else { + log.warn("MQTT disabled in 'devicemgt-config.xml'. Hence, MQTTConnector" + + " not started."); + } + } + }; + Thread connectorThread = new Thread(connector); + connectorThread.setDaemon(true); + connectorThread.start(); + } + + /** + * @param agentInfo device owner,id and sensor value + * @return device registration status + */ + @Path("controller/register") + @POST + @Consumes(MediaType.APPLICATION_JSON) + public Response registerDevice(final DeviceJSON agentInfo) { + if ((agentInfo.deviceId != null) && (agentInfo.owner != null)) { + return Response.status(Response.Status.OK).entity("Device has been registered successfully").build(); + } + return Response.status(Response.Status.NOT_ACCEPTABLE).entity("Message body not " + + "well-formed and still invalid").build(); + } + + /** + * @param owner device owner + * @param deviceId unique identifier for given device type + * @param protocol name of supported protocol. here MQTT is used + * @param response to request + * @return sensor record + */ + @Path("controller/read-temperature") + @GET + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + @Feature(code = "read-temperature", name = "Temperature", type = "monitor", + description = "Request temperature reading from device") + public SensorRecord readTemperature(@HeaderParam("owner") String owner, + @HeaderParam("deviceId") String deviceId, + @HeaderParam("protocol") String protocol, + @Context HttpServletResponse response) { + SensorRecord sensorRecord = null; + if (isPermitted(owner, deviceId, response)) { + try { + sensorRecord = SensorDataManager.getInstance().getSensorRecord(deviceId, + DeviceTypeConstants.SENSOR_TEMPERATURE); + } catch (DeviceControllerException e) { + response.setStatus(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode()); + } + response.setStatus(Response.Status.OK.getStatusCode()); + } + return sensorRecord; + } + + /** + * @param owner device owner + * @param deviceId unique identifier for given device type + * @param protocol name of supported protocol. here MQTT is used + * @param response to request + * @return sensor record + */ + @Path("controller/read-humidity") + @GET + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + @Feature(code = "read-humidity", name = "Humidity", type = "monitor", + description = "Request humidity reading from device") + public SensorRecord readHumidity(@HeaderParam("owner") String owner, + @HeaderParam("deviceId") String deviceId, + @HeaderParam("protocol") String protocol, + @Context HttpServletResponse response) { + SensorRecord sensorRecord = null; + if (isPermitted(owner, deviceId, response)) { + try { + sensorRecord = SensorDataManager.getInstance().getSensorRecord(deviceId, + DeviceTypeConstants.SENSOR_HUMIDITY); + } catch (DeviceControllerException e) { + response.setStatus(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode()); + } + response.setStatus(Response.Status.OK.getStatusCode()); + } + return sensorRecord; + } + + /** + * @param owner device owner + * @param deviceId unique identifier for given device type + * @param protocol name of supported protocol. Here MQTT is used + * @param state change status of buzzer: on/off + * @param response to request + */ + @Path("controller/change-status") + @POST + @Feature(code = "change-status", name = "Buzzer: on/off", type = "operation", + description = "Switch on/off Fire Alarm Buzzer. (On / Off)") + public void changeBuzzerState(@HeaderParam("owner") String owner, + @HeaderParam("deviceId") String deviceId, + @HeaderParam("protocol") String protocol, + @FormParam("state") String state, + @Context HttpServletResponse response) { + if (isPermitted(owner, deviceId, response)) { + try { + mqttConnector.sendCommandViaMQTT(owner, deviceId, "buzzer:", state.toUpperCase()); + response.setStatus(Response.Status.OK.getStatusCode()); + } catch (DeviceManagementException e) { + log.error(e); + response.setStatus(Response.Status.UNAUTHORIZED.getStatusCode()); + } catch (DeviceTypeException e) { + log.error(e); + response.setStatus(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode()); + } + } + } + + private boolean isPermitted(String owner, String deviceId, HttpServletResponse response) { + DeviceValidator deviceValidator = new DeviceValidator(); + try { + String tenantDomain = CarbonContext.getThreadLocalCarbonContext().getTenantDomain(); + if (!deviceValidator.isExist(owner, tenantDomain, new DeviceIdentifier( + deviceId, DeviceTypeConstants.DEVICE_TYPE))) { + response.setStatus(Response.Status.UNAUTHORIZED.getStatusCode()); + } else { + return true; + } + } catch (DeviceManagementException e) { + response.setStatus(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode()); + } + return false; + } +} \ No newline at end of file diff --git a/modules/samples/firealarm/component/controller/src/main/java/org.homeautomation/firealarm/controller/api/dto/DeviceJSON.java b/modules/samples/firealarm/component/controller/src/main/java/org.homeautomation/firealarm/controller/api/dto/DeviceJSON.java new file mode 100644 index 00000000..db95b8ea --- /dev/null +++ b/modules/samples/firealarm/component/controller/src/main/java/org.homeautomation/firealarm/controller/api/dto/DeviceJSON.java @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.homeautomation.firealarm.controller.api.dto; + +import org.codehaus.jackson.annotate.JsonIgnoreProperties; + +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; + +/** + * These information are sent by agent in each request to server + */ +@XmlRootElement +@JsonIgnoreProperties(ignoreUnknown = true) +public class DeviceJSON { + @XmlElement(required = true) + public String owner; + @XmlElement(required = true) + public String deviceId; + @XmlElement(required = true) + public Float sensorValue; +} diff --git a/modules/samples/firealarm/component/controller/src/main/java/org.homeautomation/firealarm/controller/api/exception/DeviceTypeException.java b/modules/samples/firealarm/component/controller/src/main/java/org.homeautomation/firealarm/controller/api/exception/DeviceTypeException.java new file mode 100644 index 00000000..e790a4fc --- /dev/null +++ b/modules/samples/firealarm/component/controller/src/main/java/org.homeautomation/firealarm/controller/api/exception/DeviceTypeException.java @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.homeautomation.firealarm.controller.api.exception; + +public class DeviceTypeException extends Exception { + + private static final long serialVersionUID = 2736466230451105441L; + + private String errorMessage; + + public DeviceTypeException(String msg, DeviceTypeException nestedEx) { + super(msg, nestedEx); + setErrorMessage(msg); + } + + public DeviceTypeException(String message, Throwable cause) { + super(message, cause); + setErrorMessage(message); + } + + public DeviceTypeException(String msg) { + super(msg); + setErrorMessage(msg); + } + + public DeviceTypeException() { + super(); + } + + public DeviceTypeException(Throwable cause) { + super(cause); + } + + public String getErrorMessage() { + return errorMessage; + } + + public void setErrorMessage(String errorMessage) { + this.errorMessage = errorMessage; + } +} diff --git a/modules/samples/firealarm/component/controller/src/main/java/org.homeautomation/firealarm/controller/api/transport/MQTTConnector.java b/modules/samples/firealarm/component/controller/src/main/java/org.homeautomation/firealarm/controller/api/transport/MQTTConnector.java new file mode 100644 index 00000000..803e4a97 --- /dev/null +++ b/modules/samples/firealarm/component/controller/src/main/java/org.homeautomation/firealarm/controller/api/transport/MQTTConnector.java @@ -0,0 +1,229 @@ +/* + * Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.homeautomation.firealarm.controller.api.transport; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.eclipse.paho.client.mqttv3.MqttException; +import org.eclipse.paho.client.mqttv3.MqttMessage; +import org.homeautomation.firealarm.controller.api.exception.DeviceTypeException; +import org.homeautomation.firealarm.controller.api.util.ServiceUtils; +import org.homeautomation.firealarm.plugin.constants.DeviceTypeConstants; +import org.wso2.carbon.device.mgt.common.DeviceManagementException; +import org.wso2.carbon.device.mgt.iot.controlqueue.mqtt.MqttConfig; +import org.wso2.carbon.device.mgt.iot.sensormgt.SensorDataManager; +import org.wso2.carbon.device.mgt.iot.transport.TransportHandlerException; +import org.wso2.carbon.device.mgt.iot.transport.mqtt.MQTTTransportHandler; + +import java.io.File; +import java.util.Calendar; +import java.util.UUID; + +/** + * MQTT is used as transport protocol. So this will provide basic functional requirement in order to communicate over + * MQTT + */ +@SuppressWarnings("no JAX-WS annotation") +public class MQTTConnector extends MQTTTransportHandler { + + private static final String publisherContext = "publisher"; + private static final String subscriberContext = "subscriber"; + private static final String subscribeTopic = + "wso2" + File.separator + "iot" + File.separator + "+" + File.separator + + DeviceTypeConstants.DEVICE_TYPE + File.separator + "+" + File.separator + + publisherContext; + private static Log log = LogFactory.getLog(MQTTConnector.class); + private static String iotServerSubscriber = UUID.randomUUID().toString().substring(0, 5); + String publisher = "wso2/iot/%s/firealarm/%s/" + subscriberContext; + + private MQTTConnector() { + super(iotServerSubscriber, DeviceTypeConstants.DEVICE_TYPE, + MqttConfig.getInstance().getMqttQueueEndpoint(), subscribeTopic); + } + + /** + * This method will initialize connection with message broker + */ + @Override + public void connect() { + Runnable connector = new Runnable() { + public void run() { + while (!isConnected()) { + try { + String brokerUsername = MqttConfig.getInstance().getMqttQueueUsername(); + String brokerPassword = MqttConfig.getInstance().getMqttQueuePassword(); + setUsernameAndPassword(brokerUsername, brokerPassword); + connectToQueue(); + } catch (TransportHandlerException e) { + log.error("Connection to MQTT Broker at: " + mqttBrokerEndPoint + " failed", e); + try { + Thread.sleep(timeoutInterval); + } catch (InterruptedException ex) { + log.error("MQTT-Connector: Thread Sleep Interrupt Exception.", ex); + } + } + try { + subscribeToQueue(); + } catch (TransportHandlerException e) { + log.warn("Subscription to MQTT Broker at: " + mqttBrokerEndPoint + " failed", e); + } + } + } + }; + Thread connectorThread = new Thread(connector); + connectorThread.setDaemon(true); + connectorThread.start(); + } + + /** + * This callback function will be called by message broker when some messages available to subscribed topic + * + * @param message mqtt message which is coming form agent side + * @param messageParams metadata of mqtt message + */ + @Override + public void processIncomingMessage(MqttMessage message, String... messageParams) { + String topic = messageParams[0]; + String ownerAndId = topic.replace("wso2" + File.separator + "iot" + File.separator, ""); + ownerAndId = ownerAndId.replace(File.separator + DeviceTypeConstants.DEVICE_TYPE + + File.separator, ":"); + ownerAndId = ownerAndId.replace(File.separator + publisherContext, ""); + String owner = ownerAndId.split(":")[0]; + String deviceId = ownerAndId.split(":")[1]; + String[] messageData = message.toString().split(":"); + if (log.isDebugEnabled()) { + log.debug("Received MQTT message for: [OWNER-" + owner + "] & [DEVICE.ID-" + deviceId + "]"); + } + if (messageData.length == 4) { + SensorDataManager.getInstance().setSensorRecord(deviceId, DeviceTypeConstants.SENSOR_TEMPERATURE, + messageData[1], Calendar.getInstance().getTimeInMillis()); + SensorDataManager.getInstance().setSensorRecord(deviceId, DeviceTypeConstants.SENSOR_HUMIDITY, + messageData[3], Calendar.getInstance().getTimeInMillis()); + + + if (!ServiceUtils.publishTemperatureToDAS(owner, deviceId, messageData[1])) { + log.error("MQTT Subscriber: Publishing data to DAS failed."); + } + + if (!ServiceUtils.publishHumidityToDAS(owner, deviceId, messageData[3])) { + log.error("MQTT Subscriber: Publishing data to DAS failed."); + } + + if (log.isDebugEnabled()) { + log.debug("Temperature: " + messageData[1]); + log.debug("Humidity: " + messageData[3]); + } + } + } + + /** + * Publish a MQTT message to device through message broker + * + * @param topic mqtt topic which will be used to uniquely identify who are the subscribers to this topic + * @param payLoad message is to be published + * @param qos level of qos(quality of service):1,2,3 + * @param retained life status + * @throws TransportHandlerException + */ + private void publishToAgent(String topic, String payLoad, int qos, boolean retained) + throws TransportHandlerException { + if (log.isDebugEnabled()) { + log.debug("Publishing message [" + payLoad + "to topic [" + topic + "]."); + } + publishToQueue(topic, payLoad, qos, retained); + } + + /** + * Publish a MQTT message to device through message broker + * + * @param deviceOwner person who own the device + * @param deviceId unique identifier for each device + * @param operation command is to executed at agent side e.g: off, on + * @param param additional payload + * @throws DeviceManagementException + * @throws DeviceTypeException + */ + public void sendCommandViaMQTT(String deviceOwner, String deviceId, String operation, + String param) + throws DeviceManagementException, DeviceTypeException { + String topic = String.format(publisher, deviceOwner, deviceId); + String payload = operation + param; + try { + publishToAgent(topic, payload, 2, false); + } catch (TransportHandlerException e) { + String errorMessage = "Error publishing data to device with ID " + deviceId; + throw new DeviceTypeException(errorMessage, e); + } + } + + /** + * connection with message broker can be terminated + */ + @Override + public void disconnect() { + Runnable stopConnection = new Runnable() { + public void run() { + while (isConnected()) { + try { + closeConnection(); + } catch (MqttException e) { + if (log.isDebugEnabled()) { + log.warn("Unable to 'STOP' MQTT connection at broker at: " + mqttBrokerEndPoint); + } + try { + Thread.sleep(timeoutInterval); + } catch (InterruptedException e1) { + log.error("MQTT-Terminator: Thread Sleep Interrupt Exception"); + } + } + } + } + }; + Thread terminatorThread = new Thread(stopConnection); + terminatorThread.setDaemon(true); + terminatorThread.start(); + } + + + @Override + public void publishDeviceData() throws TransportHandlerException { + + } + + @Override + public void publishDeviceData(MqttMessage publishData) throws TransportHandlerException { + + } + + @Override + public void publishDeviceData(String... publishData) throws TransportHandlerException { + + } + + @Override + public void processIncomingMessage() { + + } + + @Override + public void processIncomingMessage(MqttMessage message) throws TransportHandlerException { + + } + +} diff --git a/modules/samples/firealarm/component/controller/src/main/java/org.homeautomation/firealarm/controller/api/util/ServiceUtils.java b/modules/samples/firealarm/component/controller/src/main/java/org.homeautomation/firealarm/controller/api/util/ServiceUtils.java new file mode 100644 index 00000000..98ad99c2 --- /dev/null +++ b/modules/samples/firealarm/component/controller/src/main/java/org.homeautomation/firealarm/controller/api/util/ServiceUtils.java @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.homeautomation.firealarm.controller.api.util; + +import org.homeautomation.firealarm.plugin.constants.DeviceTypeConstants; +import org.wso2.carbon.context.PrivilegedCarbonContext; +import org.wso2.carbon.device.mgt.analytics.exception.DataPublisherConfigurationException; +import org.wso2.carbon.device.mgt.analytics.service.DeviceAnalyticsService; + +public class ServiceUtils { + + private static final String ORG_WSO2_IOT_DEVICES_TEMPERATURE = "org.wso2.iot.devices.temperature"; + private static final String ORG_WSO2_IOT_DEVICES_HUMIDITY = "org.wso2.iot.devices.humidity"; + private static final String SENSOR_STREAM_VERSION = "1.0.0"; + + /** + * sensor data are published to DAS + * + * @param owner name of device owner + * @param deviceId unique identifier of the device + * @param sensorValue current value of sensor which is set at agent side + * @return status + */ + public static boolean publishTemperatureToDAS(String owner, String deviceId, + String sensorValue) { + float temperature = Float.parseFloat(sensorValue); + Object payloadCurrent[] = {temperature}; + return publishToDAS(owner, deviceId, payloadCurrent, ORG_WSO2_IOT_DEVICES_TEMPERATURE); + } + + /** + * sensor data are published to DAS + * + * @param owner name of device owner + * @param deviceId unique identifier of the device + * @param sensorValue current value of sensor which is set at agent side + * @return status + */ + public static boolean publishHumidityToDAS(String owner, String deviceId, + String sensorValue) { + float humidity = Float.parseFloat(sensorValue); + Object payloadCurrent[] = {humidity}; + return publishToDAS(owner, deviceId, payloadCurrent, ORG_WSO2_IOT_DEVICES_HUMIDITY); + } + + private static boolean publishToDAS(String owner, String deviceId, Object[] payloadCurrent, + String definition) { + PrivilegedCarbonContext.startTenantFlow(); + PrivilegedCarbonContext ctx = PrivilegedCarbonContext.getThreadLocalCarbonContext(); + ctx.setUsername(owner); + if (ctx.getTenantDomain(true) == null) { + ctx.setTenantDomain("carbon.super", true); + } + DeviceAnalyticsService deviceAnalyticsService = (DeviceAnalyticsService) ctx.getOSGiService( + DeviceAnalyticsService.class, null); + Object metaData[] = {owner, DeviceTypeConstants.DEVICE_TYPE, deviceId, System.currentTimeMillis()}; + try { + deviceAnalyticsService.publishEvent(definition, SENSOR_STREAM_VERSION, metaData, + new Object[0], payloadCurrent); + } catch (DataPublisherConfigurationException e) { + return false; + } finally { + PrivilegedCarbonContext.endTenantFlow(); + } + return true; + } +} diff --git a/modules/samples/firealarm/component/controller/src/main/webapp/META-INF/webapp-classloading.xml b/modules/samples/firealarm/component/controller/src/main/webapp/META-INF/webapp-classloading.xml new file mode 100644 index 00000000..b410b426 --- /dev/null +++ b/modules/samples/firealarm/component/controller/src/main/webapp/META-INF/webapp-classloading.xml @@ -0,0 +1,35 @@ + + + + + + + + + false + + + CXF,Carbon + diff --git a/modules/samples/firealarm/component/controller/src/main/webapp/WEB-INF/cxf-servlet.xml b/modules/samples/firealarm/component/controller/src/main/webapp/WEB-INF/cxf-servlet.xml new file mode 100644 index 00000000..46a71e29 --- /dev/null +++ b/modules/samples/firealarm/component/controller/src/main/webapp/WEB-INF/cxf-servlet.xml @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + diff --git a/modules/samples/firealarm/component/controller/src/main/webapp/WEB-INF/web.xml b/modules/samples/firealarm/component/controller/src/main/webapp/WEB-INF/web.xml new file mode 100644 index 00000000..7f6126d2 --- /dev/null +++ b/modules/samples/firealarm/component/controller/src/main/webapp/WEB-INF/web.xml @@ -0,0 +1,68 @@ + + + + + + Sample-Webapp-Controller + + JAX-WS/JAX-RS Endpoint + JAX-WS/JAX-RS Servlet + CXFServlet + + org.apache.cxf.transport.servlet.CXFServlet + + 1 + + + CXFServlet + /* + + + isAdminService + false + + + doAuthentication + false + + + + managed-api-enabled + true + + + managed-api-owner + admin + + + managed-api-context-template + /firealarm/{version} + + + managed-api-application + firealarm + + + managed-api-isSecured + true + + diff --git a/modules/samples/firealarm/component/manager/pom.xml b/modules/samples/firealarm/component/manager/pom.xml new file mode 100644 index 00000000..fd549767 --- /dev/null +++ b/modules/samples/firealarm/component/manager/pom.xml @@ -0,0 +1,231 @@ + + + + + + + org.homeautomation + firealarm-component + 1.0.0-SNAPSHOT + ../pom.xml + + 4.0.0 + ${groupId}.firealarm.manager + war + 1.0.0-SNAPSHOT + ${groupId}.firealarm.manager + http://wso2.org + + ${basedir}/src/main/java + + + org.apache.maven.plugins + maven-compiler-plugin + ${maven-compiler-plugin.version} + + UTF-8 + ${wso2.maven.compiler.source} + ${wso2.maven.compiler.target} + + + + maven-war-plugin + ${maven-war-plugin.version} + + ${groupId}.firealarm.manager_mgt + + + + + + + org.homeautomation + ${project-base-package}.plugin + + + org.wso2.carbon.devicemgt + org.wso2.carbon.device.mgt.common + + + org.wso2.carbon.devicemgt + org.wso2.carbon.device.mgt.core + + + org.apache.axis2.wso2 + axis2-client + + + + + + org.wso2.carbon.devicemgt + org.wso2.carbon.device.mgt.analytics + + + org.apache.axis2.wso2 + axis2-client + + + + + + org.wso2.carbon.devicemgt + org.wso2.carbon.certificate.mgt.core + + + commons-codec.wso2 + commons-codec + + + + + + + org.apache.cxf + cxf-rt-frontend-jaxws + + + org.apache.cxf + cxf-rt-frontend-jaxrs + + + org.apache.cxf + cxf-rt-transports-http + + + + org.apache.httpcomponents + httpasyncclient + + + org.wso2.carbon.devicemgt-plugins + org.wso2.carbon.device.mgt.iot + + + + org.codehaus.jackson + jackson-core-asl + + + org.codehaus.jackson + jackson-jaxrs + + + javax + javaee-web-api + + + javax.ws.rs + jsr311-api + + + commons-httpclient.wso2 + commons-httpclient + + + org.wso2.carbon + org.wso2.carbon.utils + + + org.bouncycastle.wso2 + bcprov-jdk15on + + + org.wso2.carbon + org.wso2.carbon.user.api + + + org.wso2.carbon + org.wso2.carbon.queuing + + + org.wso2.carbon + org.wso2.carbon.base + + + org.apache.axis2.wso2 + axis2 + + + org.igniterealtime.smack.wso2 + smack + + + org.igniterealtime.smack.wso2 + smackx + + + jaxen + jaxen + + + commons-fileupload.wso2 + commons-fileupload + + + org.apache.ant.wso2 + ant + + + org.apache.ant.wso2 + ant + + + commons-httpclient.wso2 + commons-httpclient + + + org.eclipse.equinox + javax.servlet + + + org.wso2.carbon + org.wso2.carbon.registry.api + + + + + commons-codec + commons-codec + + + commons-io + commons-io + + + + org.igniterealtime.smack.wso2 + smack + + + org.igniterealtime.smack.wso2 + smackx + + + org.wso2.carbon.devicemgt + org.wso2.carbon.apimgt.annotations + + + org.wso2.carbon.devicemgt + org.wso2.carbon.apimgt.webapp.publisher + + + \ No newline at end of file diff --git a/modules/samples/firealarm/component/manager/src/main/java/org/homeautomation/firealarm/manager/api/ManagerService.java b/modules/samples/firealarm/component/manager/src/main/java/org/homeautomation/firealarm/manager/api/ManagerService.java new file mode 100644 index 00000000..9c4cc572 --- /dev/null +++ b/modules/samples/firealarm/component/manager/src/main/java/org/homeautomation/firealarm/manager/api/ManagerService.java @@ -0,0 +1,337 @@ +/* + * Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.homeautomation.firealarm.manager.api; + +import org.apache.commons.httpclient.HttpStatus; +import org.apache.commons.io.FileUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.homeautomation.firealarm.manager.api.util.APIUtil; +import org.homeautomation.firealarm.manager.api.util.ResponsePayload; +import org.homeautomation.firealarm.plugin.constants.DeviceTypeConstants; +import org.wso2.carbon.apimgt.annotations.device.DeviceType; +import org.wso2.carbon.apimgt.webapp.publisher.KeyGenerationUtil; +import org.wso2.carbon.device.mgt.common.Device; +import org.wso2.carbon.device.mgt.common.DeviceIdentifier; +import org.wso2.carbon.device.mgt.common.DeviceManagementException; +import org.wso2.carbon.device.mgt.common.EnrolmentInfo; +import org.wso2.carbon.device.mgt.iot.apimgt.AccessTokenInfo; +import org.wso2.carbon.device.mgt.iot.apimgt.TokenClient; +import org.wso2.carbon.device.mgt.iot.exception.AccessTokenException; +import org.wso2.carbon.device.mgt.iot.exception.DeviceControllerException; +import org.wso2.carbon.device.mgt.iot.util.ZipArchive; +import org.wso2.carbon.device.mgt.iot.util.ZipUtil; + +import javax.servlet.http.HttpServletResponse; +import javax.ws.rs.Consumes; +import javax.ws.rs.DELETE; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.QueryParam; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import java.io.IOException; +import java.nio.ByteBuffer; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.util.UUID; + +@SuppressWarnings("NonJaxWsWebServices") +@DeviceType(value = "firealarm") +public class ManagerService { + + private static Log log = LogFactory.getLog(ManagerService.class); + + @Context //injected response proxy supporting multiple thread + private HttpServletResponse response; + + /** + * Generate UUID + * + * @return generated UUID + */ + private static String shortUUID() { + UUID uuid = UUID.randomUUID(); + long l = ByteBuffer.wrap(uuid.toString().getBytes(StandardCharsets.UTF_8)).getLong(); + return Long.toString(l, Character.MAX_RADIX); + } + + /** + * Register new device into IoT Server + * + * @param deviceId unique identifier for device + * @param name name of new device + * @return registration status + */ + @Path("manager/device/register") + @PUT + public boolean register(@QueryParam("deviceId") String deviceId, + @QueryParam("name") String name) { + DeviceIdentifier deviceIdentifier = new DeviceIdentifier(); + deviceIdentifier.setId(deviceId); + deviceIdentifier.setType(DeviceTypeConstants.DEVICE_TYPE); + try { + if (APIUtil.getDeviceManagementService().isEnrolled(deviceIdentifier)) { + response.setStatus(Response.Status.CONFLICT.getStatusCode()); + return false; + } + + String owner = APIUtil.getAuthenticatedUser(); + Device device = new Device(); + device.setDeviceIdentifier(deviceId); + EnrolmentInfo enrolmentInfo = new EnrolmentInfo(); + enrolmentInfo.setDateOfEnrolment(new Date().getTime()); + enrolmentInfo.setDateOfLastUpdate(new Date().getTime()); + enrolmentInfo.setStatus(EnrolmentInfo.Status.ACTIVE); + enrolmentInfo.setOwnership(EnrolmentInfo.OwnerShip.BYOD); + device.setName(name); + device.setType(DeviceTypeConstants.DEVICE_TYPE); + enrolmentInfo.setOwner(owner); + device.setEnrolmentInfo(enrolmentInfo); + KeyGenerationUtil.createApplicationKeys(DeviceTypeConstants.DEVICE_TYPE); + TokenClient accessTokenClient = new TokenClient(DeviceTypeConstants.DEVICE_TYPE); + AccessTokenInfo accessTokenInfo = accessTokenClient.getAccessToken(owner, deviceId); + + //create token + String accessToken = accessTokenInfo.getAccess_token(); + String refreshToken = accessTokenInfo.getRefresh_token(); + List properties = new ArrayList<>(); + Device.Property accessTokenProperty = new Device.Property(); + accessTokenProperty.setName("accessToken"); + accessTokenProperty.setValue(accessToken); + Device.Property refreshTokenProperty = new Device.Property(); + refreshTokenProperty.setName("refreshToken"); + refreshTokenProperty.setValue(refreshToken); + properties.add(accessTokenProperty); + properties.add(refreshTokenProperty); + device.setProperties(properties); + + boolean added = APIUtil.getDeviceManagementService().enrollDevice(device); + if (added) { + response.setStatus(Response.Status.OK.getStatusCode()); + } else { + response.setStatus(Response.Status.NOT_ACCEPTABLE.getStatusCode()); + } + return added; + } catch (DeviceManagementException e) { + response.setStatus(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode()); + log.error(e.getErrorMessage(), e); + return false; + } catch (AccessTokenException e) { + response.setStatus(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode()); + log.error("Unable to obtain access token", e); + return false; + } + } + + /** + * Remove installed device + * + * @param deviceId unique identifier for device + * @param response to request + */ + @Path("manager/device/remove/{device_id}") + @DELETE + public void removeDevice(@PathParam("device_id") String deviceId, + @Context HttpServletResponse response) { + DeviceIdentifier deviceIdentifier = new DeviceIdentifier(); + deviceIdentifier.setId(deviceId); + deviceIdentifier.setType(DeviceTypeConstants.DEVICE_TYPE); + try { + boolean removed = APIUtil.getDeviceManagementService().disenrollDevice( + deviceIdentifier); + if (removed) { + response.setStatus(Response.Status.OK.getStatusCode()); + } else { + response.setStatus(Response.Status.NOT_ACCEPTABLE.getStatusCode()); + } + } catch (DeviceManagementException e) { + response.setStatus(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode()); + } + } + + /** + * Update device name + * + * @param deviceId unique identifier for device + * @param name new name of the device + * @param response to request + * @return update status + */ + @Path("manager/device/update/{device_id}") + @POST + public boolean updateDevice(@PathParam("device_id") String deviceId, + @QueryParam("name") String name, + @Context HttpServletResponse response) { + DeviceIdentifier deviceIdentifier = new DeviceIdentifier(); + deviceIdentifier.setId(deviceId); + deviceIdentifier.setType(DeviceTypeConstants.DEVICE_TYPE); + try { + Device device = APIUtil.getDeviceManagementService().getDevice(deviceIdentifier); + device.setDeviceIdentifier(deviceId); + device.getEnrolmentInfo().setDateOfLastUpdate(new Date().getTime()); + device.setName(name); + device.setType(DeviceTypeConstants.DEVICE_TYPE); + boolean updated = APIUtil.getDeviceManagementService().modifyEnrollment(device); + if (updated) { + response.setStatus(Response.Status.OK.getStatusCode()); + } else { + response.setStatus(Response.Status.NOT_ACCEPTABLE.getStatusCode()); + } + return updated; + } catch (DeviceManagementException e) { + log.error(e.getErrorMessage()); + return false; + } + } + + /** + * Get device information + * + * @param deviceId unique identifier for device + * @return device + */ + @Path("manager/device/{device_id}") + @GET + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + public Device getDevice(@PathParam("device_id") String deviceId) { + DeviceIdentifier deviceIdentifier = new DeviceIdentifier(); + deviceIdentifier.setId(deviceId); + deviceIdentifier.setType(DeviceTypeConstants.DEVICE_TYPE); + try { + return APIUtil.getDeviceManagementService().getDevice(deviceIdentifier); + } catch (DeviceManagementException ex) { + log.error("Error occurred while retrieving device with Id " + deviceId + "\n" + ex); + return null; + } + } + + /** + * This will download the agent for given device type + * + * @param deviceName name of the device which is to be created + * @param sketchType name of sketch type + * @return agent archive + */ + @Path("manager/device/{sketch_type}/download") + @GET + @Produces(MediaType.APPLICATION_JSON) + public Response downloadSketch(@QueryParam("deviceName") String deviceName, + @PathParam("sketch_type") String sketchType) { + try { + ZipArchive zipFile = createDownloadFile(APIUtil.getAuthenticatedUser(), deviceName, sketchType); + Response.ResponseBuilder response = Response.ok(FileUtils.readFileToByteArray(zipFile.getZipFile())); + response.type("application/zip"); + response.header("Content-Disposition", "attachment; filename=\"" + zipFile.getFileName() + "\""); + return response.build(); + } catch (IllegalArgumentException ex) { + return Response.status(400).entity(ex.getMessage()).build();//bad request + } catch (DeviceManagementException ex) { + return Response.status(500).entity(ex.getMessage()).build(); + } catch (AccessTokenException ex) { + return Response.status(500).entity(ex.getMessage()).build(); + } catch (DeviceControllerException ex) { + return Response.status(500).entity(ex.getMessage()).build(); + } catch (IOException ex) { + return Response.status(500).entity(ex.getMessage()).build(); + } + } + + /** + * This will give link to generated agent + * + * @param deviceName name of the device which is to be created + * @param sketchType name of sketch type + * @return link to generated agent + */ + @Path("manager/device/{sketch_type}/generate_link") + @GET + public Response generateSketchLink(@QueryParam("deviceName") String deviceName, + @PathParam("sketch_type") String sketchType) { + + try { + ZipArchive zipFile = createDownloadFile(APIUtil.getAuthenticatedUser(), deviceName, sketchType); + ResponsePayload responsePayload = new ResponsePayload(); + responsePayload.setStatusCode(HttpStatus.SC_OK); + responsePayload.setMessageFromServer("Sending Requested sketch by type: " + sketchType + + " and id: " + zipFile.getDeviceId() + "."); + responsePayload.setResponseContent(zipFile.getDeviceId()); + return Response.status(HttpStatus.SC_OK).entity(responsePayload).build(); + } catch (IllegalArgumentException ex) { + return Response.status(HttpStatus.SC_BAD_REQUEST).entity(ex.getMessage()).build(); + } catch (DeviceManagementException ex) { + log.error("Error occurred while creating device with name " + deviceName + "\n", ex); + return Response.status(HttpStatus.SC_INTERNAL_SERVER_ERROR).entity(ex.getMessage()).build(); + } catch (AccessTokenException ex) { + log.error(ex.getMessage(), ex); + return Response.status(HttpStatus.SC_INTERNAL_SERVER_ERROR).entity(ex.getMessage()).build(); + } catch (DeviceControllerException ex) { + log.error(ex.getMessage(), ex); + return Response.status(HttpStatus.SC_INTERNAL_SERVER_ERROR).entity(ex.getMessage()).build(); + } + } + + /** + * Make zip file which include all the agent source codes and configuration file + * + * @param owner owner of the device + * @param deviceName name of device + * @param sketchType name of sketch type + * @return zip archive file + * @throws DeviceManagementException + * @throws AccessTokenException + * @throws DeviceControllerException + */ + private ZipArchive createDownloadFile(String owner, String deviceName, String sketchType) + throws DeviceManagementException, AccessTokenException, DeviceControllerException { + if (owner == null) { + throw new IllegalArgumentException("Error on createDownloadFile() Owner is null!"); + } + //create new device id + String deviceId = shortUUID(); + KeyGenerationUtil.createApplicationKeys(DeviceTypeConstants.DEVICE_TYPE); + TokenClient accessTokenClient = new TokenClient(DeviceTypeConstants.DEVICE_TYPE); + AccessTokenInfo accessTokenInfo = accessTokenClient.getAccessToken(owner, deviceId); + //create token + String accessToken = accessTokenInfo.getAccess_token(); + String refreshToken = accessTokenInfo.getRefresh_token(); + //adding registering data + boolean status; + //Register the device with CDMF + status = register(deviceId, deviceName); + if (!status) { + String msg = "Error occurred while registering the device with " + "id: " + deviceId + " owner:" + owner; + throw new DeviceManagementException(msg); + } + ZipUtil ziputil = new ZipUtil(); + ZipArchive zipFile = ziputil.createZipFile(owner, APIUtil.getTenantDomainOfUser(), sketchType, deviceId, deviceName, accessToken, + refreshToken); + zipFile.setDeviceId(deviceId); + return zipFile; + } + +} diff --git a/modules/samples/firealarm/component/manager/src/main/java/org/homeautomation/firealarm/manager/api/util/APIUtil.java b/modules/samples/firealarm/component/manager/src/main/java/org/homeautomation/firealarm/manager/api/util/APIUtil.java new file mode 100644 index 00000000..c3699691 --- /dev/null +++ b/modules/samples/firealarm/component/manager/src/main/java/org/homeautomation/firealarm/manager/api/util/APIUtil.java @@ -0,0 +1,54 @@ +/* +* Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. +* +* WSO2 Inc. licenses this file to you under the Apache License, +* Version 2.0 (the "License"); you may not use this file except +* in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +package org.homeautomation.firealarm.manager.api.util; + +import org.wso2.carbon.context.PrivilegedCarbonContext; +import org.wso2.carbon.device.mgt.core.service.DeviceManagementProviderService; + +/** + * This class provides utility functions used by REST-API. + */ +public class APIUtil { + + public static String getAuthenticatedUser() { + PrivilegedCarbonContext threadLocalCarbonContext = PrivilegedCarbonContext.getThreadLocalCarbonContext(); + String username = threadLocalCarbonContext.getUsername(); + String tenantDomain = threadLocalCarbonContext.getTenantDomain(); + if (username.endsWith(tenantDomain)) { + return username.substring(0, username.lastIndexOf("@")); + } + return username; + } + + public static String getTenantDomainOfUser() { + PrivilegedCarbonContext threadLocalCarbonContext = PrivilegedCarbonContext.getThreadLocalCarbonContext(); + return threadLocalCarbonContext.getTenantDomain(); + } + + public static DeviceManagementProviderService getDeviceManagementService() { + PrivilegedCarbonContext ctx = PrivilegedCarbonContext.getThreadLocalCarbonContext(); + DeviceManagementProviderService deviceManagementProviderService = + (DeviceManagementProviderService) ctx.getOSGiService(DeviceManagementProviderService.class, null); + if (deviceManagementProviderService == null) { + String msg = "Device Management service has not initialized."; + throw new IllegalStateException(msg); + } + return deviceManagementProviderService; + } +} diff --git a/modules/samples/firealarm/component/manager/src/main/java/org/homeautomation/firealarm/manager/api/util/ResponsePayload.java b/modules/samples/firealarm/component/manager/src/main/java/org/homeautomation/firealarm/manager/api/util/ResponsePayload.java new file mode 100644 index 00000000..684e9374 --- /dev/null +++ b/modules/samples/firealarm/component/manager/src/main/java/org/homeautomation/firealarm/manager/api/util/ResponsePayload.java @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.homeautomation.firealarm.manager.api.util; + +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; + +@XmlRootElement +public class ResponsePayload { + + private int statusCode; + private String messageFromServer; + private Object responseContent; + + public static ResponsePayload.ResponsePayloadBuilder statusCode(int statusCode) { + ResponsePayload message = new ResponsePayload(); + return message.getBuilder().statusCode(statusCode); + } + + public static ResponsePayload.ResponsePayloadBuilder messageFromServer( + String messageFromServer) { + ResponsePayload message = new ResponsePayload(); + return message.getBuilder().messageFromServer(messageFromServer); + } + + public static ResponsePayload.ResponsePayloadBuilder responseContent(String responseContent) { + ResponsePayload message = new ResponsePayload(); + return message.getBuilder().responseContent(responseContent); + } + + @XmlElement + public int getStatusCode() { + return statusCode; + } + + public void setStatusCode(int statusCode) { + this.statusCode = statusCode; + } + + @XmlElement + public String getMessageFromServer() { + return messageFromServer; + } + + public void setMessageFromServer(String messageFromServer) { + this.messageFromServer = messageFromServer; + } + + @XmlElement + public Object getResponseContent() { + return responseContent; + } + + public void setResponseContent(Object responseContent) { + this.responseContent = responseContent; + } + + private ResponsePayload.ResponsePayloadBuilder getBuilder() { + return new ResponsePayload.ResponsePayloadBuilder(); + } + + public class ResponsePayloadBuilder { + + private int statusCode; + private String messageFromServer; + private Object responseContent; + + public ResponsePayloadBuilder statusCode(int statusCode) { + this.statusCode = statusCode; + return this; + } + + public ResponsePayloadBuilder messageFromServer(String messageFromServer) { + this.messageFromServer = messageFromServer; + return this; + } + + public ResponsePayloadBuilder responseContent(String responseContent) { + this.responseContent = responseContent; + return this; + } + + public ResponsePayload build() { + ResponsePayload payload = new ResponsePayload(); + payload.setStatusCode(statusCode); + payload.setMessageFromServer(messageFromServer); + payload.setResponseContent(responseContent); + return payload; + } + } + +} diff --git a/modules/samples/firealarm/component/manager/src/main/webapp/META-INF/permissions.xml b/modules/samples/firealarm/component/manager/src/main/webapp/META-INF/permissions.xml new file mode 100644 index 00000000..a98f6a8e --- /dev/null +++ b/modules/samples/firealarm/component/manager/src/main/webapp/META-INF/permissions.xml @@ -0,0 +1,73 @@ + + + + + + + + + + Get device + /device-mgt/user/devices/list + /manager/device/* + GET + emm_admin,emm_user + + + Add device + /device-mgt/user/devices/add + /manager/device/register + PUT + emm_admin,emm_user + + + Download device + /device-mgt/user/devices/add + /manager/device/firealarm/download + GET + emm_admin,emm_user + + + Generate link to download + /device-mgt/user/devices/add + /manager/device/firealarm/generate_link + GET + emm_admin,emm_user + + + Update device + /device-mgt/user/devices/update + /manager/device/update/* + POST + emm_admin,emm_user + + + Remove device + /device-mgt/user/devices/remove + /manager/device/remove/* + DELETE + emm_admin,emm_user + + \ No newline at end of file diff --git a/modules/samples/firealarm/component/manager/src/main/webapp/META-INF/webapp-classloading.xml b/modules/samples/firealarm/component/manager/src/main/webapp/META-INF/webapp-classloading.xml new file mode 100644 index 00000000..b410b426 --- /dev/null +++ b/modules/samples/firealarm/component/manager/src/main/webapp/META-INF/webapp-classloading.xml @@ -0,0 +1,35 @@ + + + + + + + + + false + + + CXF,Carbon + diff --git a/modules/samples/firealarm/component/manager/src/main/webapp/WEB-INF/cxf-servlet.xml b/modules/samples/firealarm/component/manager/src/main/webapp/WEB-INF/cxf-servlet.xml new file mode 100644 index 00000000..854b0248 --- /dev/null +++ b/modules/samples/firealarm/component/manager/src/main/webapp/WEB-INF/cxf-servlet.xml @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + diff --git a/modules/samples/firealarm/component/manager/src/main/webapp/WEB-INF/web.xml b/modules/samples/firealarm/component/manager/src/main/webapp/WEB-INF/web.xml new file mode 100644 index 00000000..a5f0c0c6 --- /dev/null +++ b/modules/samples/firealarm/component/manager/src/main/webapp/WEB-INF/web.xml @@ -0,0 +1,68 @@ + + + + + + Firealarm-Webapp-Manager + + JAX-WS/JAX-RS Endpoint + JAX-WS/JAX-RS Servlet + CXFServlet + + org.apache.cxf.transport.servlet.CXFServlet + + 1 + + + CXFServlet + /* + + + isAdminService + false + + + doAuthentication + true + + + + managed-api-enabled + false + + + managed-api-owner + admin + + + managed-api-context-template + /firealarm/{version} + + + managed-api-application + firealarm + + + managed-api-isSecured + true + + diff --git a/modules/samples/firealarm/component/plugin/pom.xml b/modules/samples/firealarm/component/plugin/pom.xml new file mode 100644 index 00000000..492d5a4e --- /dev/null +++ b/modules/samples/firealarm/component/plugin/pom.xml @@ -0,0 +1,114 @@ + + + + + + + org.homeautomation + firealarm-component + 1.0.0-SNAPSHOT + ../pom.xml + + 4.0.0 + 1.0.0-SNAPSHOT + ${groupId}.firealarm.plugin + bundle + ${groupId}.firealarm.plugin + http://wso2.org + + + + org.apache.felix + maven-scr-plugin + + + org.apache.maven.plugins + maven-compiler-plugin + ${maven-compiler-plugin.version} + + UTF-8 + ${wso2.maven.compiler.source} + ${wso2.maven.compiler.target} + + + + org.apache.felix + maven-bundle-plugin + ${org.apache.felix.version} + true + + + ${groupId}.firealarm.plugin + ${groupId}.firealarm.plugin + 1.0.0-SNAPSHOT + IoT Server Impl Bundle + ${project-base-package}.plugin.internal + + org.osgi.framework, + org.osgi.service.component, + org.apache.commons.logging, + javax.naming, + javax.sql, + javax.xml.parsers, + javax.net, + javax.net.ssl, + org.w3c.dom, + org.wso2.carbon.device.mgt.common.*, + org.wso2.carbon.context.*, + org.wso2.carbon.ndatasource.core, + org.wso2.carbon.device.mgt.iot.*, + + + !${project-base-package}.plugin.internal, + ${project-base-package}.plugin.* + + + + + + + + + org.eclipse.osgi + org.eclipse.osgi + + + org.eclipse.osgi + org.eclipse.osgi.services + + + org.wso2.carbon + org.wso2.carbon.logging + + + org.wso2.carbon.devicemgt + org.wso2.carbon.device.mgt.common + + + org.wso2.carbon + org.wso2.carbon.ndatasource.core + + + org.wso2.carbon.devicemgt-plugins + org.wso2.carbon.device.mgt.iot + + + \ No newline at end of file diff --git a/modules/samples/firealarm/component/plugin/src/main/java/org/homeautomation/firealarm/plugin/constants/DeviceTypeConstants.java b/modules/samples/firealarm/component/plugin/src/main/java/org/homeautomation/firealarm/plugin/constants/DeviceTypeConstants.java new file mode 100644 index 00000000..48db43cf --- /dev/null +++ b/modules/samples/firealarm/component/plugin/src/main/java/org/homeautomation/firealarm/plugin/constants/DeviceTypeConstants.java @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.homeautomation.firealarm.plugin.constants; + +public class DeviceTypeConstants { + + public final static String DEVICE_TYPE = "firealarm"; + public final static String DEVICE_PLUGIN_DEVICE_NAME = "DEVICE_NAME"; + public final static String DEVICE_PLUGIN_DEVICE_ID = "firealarm_DEVICE_ID"; + public final static String SENSOR_TEMPERATURE = "temperature"; + public final static String SENSOR_HUMIDITY = "humidity"; + public static final String DATA_SOURCE_NAME = "jdbc/firealarmDM_DB"; + + public final static String DEVICE_PLUGIN_PROPERTY_ACCESS_TOKEN = "accessToken"; + public final static String DEVICE_PLUGIN_PROPERTY_REFRESH_TOKEN = "refreshToken"; + +} diff --git a/modules/samples/firealarm/component/plugin/src/main/java/org/homeautomation/firealarm/plugin/exception/FirealarmPluginException.java b/modules/samples/firealarm/component/plugin/src/main/java/org/homeautomation/firealarm/plugin/exception/FirealarmPluginException.java new file mode 100644 index 00000000..60b41c98 --- /dev/null +++ b/modules/samples/firealarm/component/plugin/src/main/java/org/homeautomation/firealarm/plugin/exception/FirealarmPluginException.java @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.homeautomation.firealarm.plugin.exception; + +public class FirealarmPluginException extends Exception { + + private String errorMessage; + + public FirealarmPluginException(String msg, Exception nestedEx) { + super(msg, nestedEx); + setErrorMessage(msg); + } + + public FirealarmPluginException(String message, Throwable cause) { + super(message, cause); + setErrorMessage(message); + } + + public FirealarmPluginException(String msg) { + super(msg); + setErrorMessage(msg); + } + + public FirealarmPluginException() { + super(); + } + + public FirealarmPluginException(Throwable cause) { + super(cause); + } + + public String getErrorMessage() { + return errorMessage; + } + + public void setErrorMessage(String errorMessage) { + this.errorMessage = errorMessage; + } + +} diff --git a/modules/samples/firealarm/component/plugin/src/main/java/org/homeautomation/firealarm/plugin/impl/DeviceTypeManager.java b/modules/samples/firealarm/component/plugin/src/main/java/org/homeautomation/firealarm/plugin/impl/DeviceTypeManager.java new file mode 100644 index 00000000..63063cc6 --- /dev/null +++ b/modules/samples/firealarm/component/plugin/src/main/java/org/homeautomation/firealarm/plugin/impl/DeviceTypeManager.java @@ -0,0 +1,259 @@ +/* + * Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.homeautomation.firealarm.plugin.impl; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.homeautomation.firealarm.plugin.exception.FirealarmPluginException; +import org.homeautomation.firealarm.plugin.impl.dao.DeviceTypeDAO; +import org.wso2.carbon.device.mgt.common.Device; +import org.wso2.carbon.device.mgt.common.DeviceIdentifier; +import org.wso2.carbon.device.mgt.common.DeviceManagementException; +import org.wso2.carbon.device.mgt.common.DeviceManager; +import org.wso2.carbon.device.mgt.common.EnrolmentInfo; +import org.wso2.carbon.device.mgt.common.FeatureManager; +import org.wso2.carbon.device.mgt.common.configuration.mgt.TenantConfiguration; +import org.wso2.carbon.device.mgt.common.license.mgt.License; +import org.wso2.carbon.device.mgt.common.license.mgt.LicenseManagementException; + +import java.util.List; + +/** + * + */ +public class DeviceTypeManager implements DeviceManager { + + private static final Log log = LogFactory.getLog(DeviceTypeManager.class); + + private static final DeviceTypeDAO connectedCupDAO = new DeviceTypeDAO(); + + @Override + public FeatureManager getFeatureManager() { + return null; + } + + @Override + public boolean saveConfiguration(TenantConfiguration tenantConfiguration) + throws DeviceManagementException { + //TODO implement this + return false; + } + + @Override + public TenantConfiguration getConfiguration() throws DeviceManagementException { + //TODO implement this + return null; + } + + @Override + public boolean enrollDevice(Device device) throws DeviceManagementException { + boolean status; + try { + if (log.isDebugEnabled()) { + log.debug("Enrolling a new Connected Cup device : " + device.getDeviceIdentifier()); + } + DeviceTypeDAO.beginTransaction(); + status = connectedCupDAO.getConnectedCupDeviceDAO().addDevice(device); + DeviceTypeDAO.commitTransaction(); + } catch (FirealarmPluginException e) { + try { + DeviceTypeDAO.rollbackTransaction(); + } catch (FirealarmPluginException iotDAOEx) { + String msg = "Error occurred while roll back the device enrol transaction :" + device.toString(); + log.warn(msg, iotDAOEx); + } + String msg = "Error while enrolling the Connected Cup device : " + device.getDeviceIdentifier(); + log.error(msg, e); + throw new DeviceManagementException(msg, e); + } + return status; + } + + @Override + public boolean modifyEnrollment(Device device) throws DeviceManagementException { + boolean status; + try { + if (log.isDebugEnabled()) { + log.debug("Modifying the Connected Cup device enrollment data"); + } + DeviceTypeDAO.beginTransaction(); + status = connectedCupDAO.getConnectedCupDeviceDAO().updateDevice(device); + DeviceTypeDAO.commitTransaction(); + } catch (FirealarmPluginException e) { + try { + DeviceTypeDAO.rollbackTransaction(); + } catch (FirealarmPluginException iotDAOEx) { + String msg = "Error occurred while roll back the update device transaction :" + device.toString(); + log.warn(msg, iotDAOEx); + } + String msg = "Error while updating the enrollment of the Connected Cup device : " + + device.getDeviceIdentifier(); + log.error(msg, e); + throw new DeviceManagementException(msg, e); + } + return status; + } + + @Override + public boolean disenrollDevice(DeviceIdentifier deviceId) throws DeviceManagementException { + boolean status; + try { + if (log.isDebugEnabled()) { + log.debug("Dis-enrolling Connected Cup device : " + deviceId); + } + DeviceTypeDAO.beginTransaction(); + status = connectedCupDAO.getConnectedCupDeviceDAO().deleteDevice(deviceId.getId()); + DeviceTypeDAO.commitTransaction(); + } catch (FirealarmPluginException e) { + try { + DeviceTypeDAO.rollbackTransaction(); + } catch (FirealarmPluginException iotDAOEx) { + String msg = "Error occurred while roll back the device dis enrol transaction :" + deviceId.toString(); + log.warn(msg, iotDAOEx); + } + String msg = "Error while removing the Connected Cup device : " + deviceId.getId(); + log.error(msg, e); + throw new DeviceManagementException(msg, e); + } + return status; + } + + @Override + public boolean isEnrolled(DeviceIdentifier deviceId) throws DeviceManagementException { + boolean isEnrolled = false; + try { + if (log.isDebugEnabled()) { + log.debug("Checking the enrollment of Connected Cup device : " + deviceId.getId()); + } + Device iotDevice = connectedCupDAO.getConnectedCupDeviceDAO().getDevice(deviceId.getId()); + if (iotDevice != null) { + isEnrolled = true; + } + } catch (FirealarmPluginException e) { + String msg = "Error while checking the enrollment status of Connected Cup device : " + + deviceId.getId(); + log.error(msg, e); + throw new DeviceManagementException(msg, e); + } + return isEnrolled; + } + + @Override + public boolean isActive(DeviceIdentifier deviceId) throws DeviceManagementException { + return true; + } + + @Override + public boolean setActive(DeviceIdentifier deviceId, boolean status) + throws DeviceManagementException { + return true; + } + + @Override + public Device getDevice(DeviceIdentifier deviceId) throws DeviceManagementException { + Device device; + try { + if (log.isDebugEnabled()) { + log.debug("Getting the details of Connected Cup device : " + deviceId.getId()); + } + device = connectedCupDAO.getConnectedCupDeviceDAO().getDevice(deviceId.getId()); + + } catch (FirealarmPluginException e) { + String msg = "Error while fetching the Connected Cup device : " + deviceId.getId(); + log.error(msg, e); + throw new DeviceManagementException(msg, e); + } + return device; + } + + @Override + public boolean setOwnership(DeviceIdentifier deviceId, String ownershipType) + throws DeviceManagementException { + return true; + } + + public boolean isClaimable(DeviceIdentifier deviceIdentifier) throws DeviceManagementException { + return false; + } + + @Override + public boolean setStatus(DeviceIdentifier deviceId, String currentOwner, + EnrolmentInfo.Status status) throws DeviceManagementException { + return false; + } + + @Override + public License getLicense(String s) throws LicenseManagementException { + return null; + } + + @Override + public void addLicense(License license) throws LicenseManagementException { + + } + + @Override + public boolean requireDeviceAuthorization() { + return false; + } + + @Override + public boolean updateDeviceInfo(DeviceIdentifier deviceIdentifier, Device device) + throws DeviceManagementException { + boolean status; + try { + if (log.isDebugEnabled()) { + log.debug( + "updating the details of Connected Cup device : " + deviceIdentifier); + } + DeviceTypeDAO.beginTransaction(); + status = connectedCupDAO.getConnectedCupDeviceDAO().updateDevice(device); + DeviceTypeDAO.commitTransaction(); + } catch (FirealarmPluginException e) { + try { + DeviceTypeDAO.rollbackTransaction(); + } catch (FirealarmPluginException iotDAOEx) { + String msg = "Error occurred while roll back the update device info transaction :" + device.toString(); + log.warn(msg, iotDAOEx); + } + String msg = + "Error while updating the Connected Cup device : " + deviceIdentifier; + log.error(msg, e); + throw new DeviceManagementException(msg, e); + } + return status; + } + + @Override + public List getAllDevices() throws DeviceManagementException { + List devices; + try { + if (log.isDebugEnabled()) { + log.debug("Fetching the details of all Connected Cup devices"); + } + devices = connectedCupDAO.getConnectedCupDeviceDAO().getAllDevices(); + } catch (FirealarmPluginException e) { + String msg = "Error while fetching all Connected Cup devices."; + log.error(msg, e); + throw new DeviceManagementException(msg, e); + } + return devices; + } + +} \ No newline at end of file diff --git a/modules/samples/firealarm/component/plugin/src/main/java/org/homeautomation/firealarm/plugin/impl/DeviceTypeManagerService.java b/modules/samples/firealarm/component/plugin/src/main/java/org/homeautomation/firealarm/plugin/impl/DeviceTypeManagerService.java new file mode 100644 index 00000000..86d7351b --- /dev/null +++ b/modules/samples/firealarm/component/plugin/src/main/java/org/homeautomation/firealarm/plugin/impl/DeviceTypeManagerService.java @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.homeautomation.firealarm.plugin.impl; + +import org.homeautomation.firealarm.plugin.constants.DeviceTypeConstants; +import org.wso2.carbon.device.mgt.common.DeviceIdentifier; +import org.wso2.carbon.device.mgt.common.DeviceManagementException; +import org.wso2.carbon.device.mgt.common.DeviceManager; +import org.wso2.carbon.device.mgt.common.app.mgt.Application; +import org.wso2.carbon.device.mgt.common.app.mgt.ApplicationManagementException; +import org.wso2.carbon.device.mgt.common.app.mgt.ApplicationManager; +import org.wso2.carbon.device.mgt.common.operation.mgt.Operation; +import org.wso2.carbon.device.mgt.common.spi.DeviceManagementService; + +import java.util.List; + +public class DeviceTypeManagerService implements DeviceManagementService { + private DeviceManager deviceManager; + + @Override + public String getType() { + return DeviceTypeConstants.DEVICE_TYPE; + } + + + @Override + public String getProviderTenantDomain() { + return "carbon.super"; + } + + @Override + public boolean isSharedWithAllTenants() { + return true; + } + + @Override + public String[] getSharedTenantsDomain() { + return new String[0]; + } + + @Override + public void init() throws DeviceManagementException { + this.deviceManager = new DeviceTypeManager(); + } + + @Override + public DeviceManager getDeviceManager() { + return deviceManager; + } + + @Override + public ApplicationManager getApplicationManager() { + return null; + } + + @Override + public void notifyOperationToDevices(Operation operation, List deviceIds) + throws DeviceManagementException { + + } + + @Override + public Application[] getApplications(String domain, int pageNumber, int size) + throws ApplicationManagementException { + return new Application[0]; + } + + @Override + public void updateApplicationStatus(DeviceIdentifier deviceId, Application application, + String status) throws ApplicationManagementException { + + } + + @Override + public String getApplicationStatus(DeviceIdentifier deviceId, Application application) + throws ApplicationManagementException { + return null; + } + + @Override + public void installApplicationForDevices(Operation operation, + List deviceIdentifiers) + throws ApplicationManagementException { + + } + + @Override + public void installApplicationForUsers(Operation operation, List userNameList) + throws ApplicationManagementException { + + } + + @Override + public void installApplicationForUserRoles(Operation operation, List userRoleList) + throws ApplicationManagementException { + + } +} diff --git a/modules/samples/firealarm/component/plugin/src/main/java/org/homeautomation/firealarm/plugin/impl/dao/DeviceTypeDAO.java b/modules/samples/firealarm/component/plugin/src/main/java/org/homeautomation/firealarm/plugin/impl/dao/DeviceTypeDAO.java new file mode 100644 index 00000000..e78b3ab0 --- /dev/null +++ b/modules/samples/firealarm/component/plugin/src/main/java/org/homeautomation/firealarm/plugin/impl/dao/DeviceTypeDAO.java @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.homeautomation.firealarm.plugin.impl.dao; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.homeautomation.firealarm.plugin.constants.DeviceTypeConstants; +import org.homeautomation.firealarm.plugin.exception.FirealarmPluginException; +import org.homeautomation.firealarm.plugin.impl.dao.impl.DeviceTypeDAOImpl; + +import javax.naming.Context; +import javax.naming.InitialContext; +import javax.naming.NamingException; +import javax.sql.DataSource; +import java.sql.Connection; +import java.sql.SQLException; + +public class DeviceTypeDAO { + + private static final Log log = LogFactory.getLog(DeviceTypeDAO.class); + private static DataSource dataSource; + private static ThreadLocal currentConnection = new ThreadLocal<>(); + + public DeviceTypeDAO() { + initConnectedCupDAO(); + } + + public static void initConnectedCupDAO() { + try { + Context ctx = new InitialContext(); + dataSource = (DataSource) ctx.lookup(DeviceTypeConstants.DATA_SOURCE_NAME); + } catch (NamingException e) { + log.error("Error while looking up the data source: " + + DeviceTypeConstants.DATA_SOURCE_NAME); + } + + } + + public static void beginTransaction() throws FirealarmPluginException { + try { + Connection conn = dataSource.getConnection(); + conn.setAutoCommit(false); + currentConnection.set(conn); + } catch (SQLException e) { + throw new FirealarmPluginException( + "Error occurred while retrieving datasource connection", e); + } + } + + public static Connection getConnection() throws FirealarmPluginException { + if (currentConnection.get() == null) { + try { + currentConnection.set(dataSource.getConnection()); + } catch (SQLException e) { + throw new FirealarmPluginException( + "Error occurred while retrieving data source connection", e); + } + } + return currentConnection.get(); + } + + public static void commitTransaction() throws FirealarmPluginException { + try { + Connection conn = currentConnection.get(); + if (conn != null) { + conn.commit(); + } else { + if (log.isDebugEnabled()) { + log.debug("Datasource connection associated with the current thread is null, " + + "hence commit has not been attempted"); + } + } + } catch (SQLException e) { + throw new FirealarmPluginException( + "Error occurred while committing the transaction", e); + } finally { + closeConnection(); + } + } + + public static void closeConnection() throws FirealarmPluginException { + + Connection con = currentConnection.get(); + if (con != null) { + try { + con.close(); + } catch (SQLException e) { + log.error("Error occurred while close the connection"); + } + } + currentConnection.remove(); + } + + public static void rollbackTransaction() throws FirealarmPluginException { + try { + Connection conn = currentConnection.get(); + if (conn != null) { + conn.rollback(); + } else { + if (log.isDebugEnabled()) { + log.debug( + "Datasource connection associated with the current thread is null, " + + "hence rollback has not been attempted"); + } + } + } catch (SQLException e) { + throw new FirealarmPluginException("Error occurred while rollback the transaction", e); + } finally { + closeConnection(); + } + } + + public DeviceTypeDAOImpl getConnectedCupDeviceDAO() { + return new DeviceTypeDAOImpl(); + } +} diff --git a/modules/samples/firealarm/component/plugin/src/main/java/org/homeautomation/firealarm/plugin/impl/dao/impl/DeviceTypeDAOImpl.java b/modules/samples/firealarm/component/plugin/src/main/java/org/homeautomation/firealarm/plugin/impl/dao/impl/DeviceTypeDAOImpl.java new file mode 100644 index 00000000..e9b09baa --- /dev/null +++ b/modules/samples/firealarm/component/plugin/src/main/java/org/homeautomation/firealarm/plugin/impl/dao/impl/DeviceTypeDAOImpl.java @@ -0,0 +1,239 @@ +/* + * Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.homeautomation.firealarm.plugin.impl.dao.impl; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.homeautomation.firealarm.plugin.constants.DeviceTypeConstants; +import org.homeautomation.firealarm.plugin.exception.FirealarmPluginException; +import org.homeautomation.firealarm.plugin.impl.dao.DeviceTypeDAO; +import org.homeautomation.firealarm.plugin.impl.dao.util.DeviceTypeUtils; +import org.wso2.carbon.device.mgt.common.Device; + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.List; + +/** + * Device Dao for Firealarm Devices. + */ +public class DeviceTypeDAOImpl { + + private static final Log log = LogFactory.getLog(DeviceTypeDAOImpl.class); + + public Device getDevice(String deviceId) throws FirealarmPluginException { + Connection conn; + PreparedStatement stmt = null; + Device connectedCupDevice = null; + ResultSet resultSet = null; + try { + conn = DeviceTypeDAO.getConnection(); + String selectDBQuery = + "SELECT firealarm_DEVICE_ID, DEVICE_NAME, ACCESS_TOKEN, REFRESH_TOKEN" + + " FROM firealarm_DEVICE WHERE firealarm_DEVICE_ID = ?"; + stmt = conn.prepareStatement(selectDBQuery); + stmt.setString(1, deviceId); + resultSet = stmt.executeQuery(); + + if (resultSet.next()) { + connectedCupDevice = new Device(); + connectedCupDevice.setName(resultSet.getString( + DeviceTypeConstants.DEVICE_PLUGIN_DEVICE_NAME)); + List propertyList = new ArrayList<>(); + propertyList.add(DeviceTypeUtils.getProperty( + DeviceTypeConstants.DEVICE_PLUGIN_PROPERTY_ACCESS_TOKEN, + resultSet.getString("ACCESS_TOKEN"))); + propertyList.add(DeviceTypeUtils.getProperty( + DeviceTypeConstants.DEVICE_PLUGIN_PROPERTY_REFRESH_TOKEN, + resultSet.getString("REFRESH_TOKEN"))); + connectedCupDevice.setProperties(propertyList); + + if (log.isDebugEnabled()) { + log.debug("Firealarm service " + deviceId + " data has been fetched from" + + "Firealarm database."); + } + } + } catch (SQLException e) { + String msg = "Error occurred while fetching Firealarm device : '" + deviceId + "'"; + log.error(msg, e); + throw new FirealarmPluginException(msg, e); + } finally { + DeviceTypeUtils.cleanupResources(stmt, resultSet); + DeviceTypeDAO.closeConnection(); + } + return connectedCupDevice; + } + + public boolean addDevice(Device connectedCupDevice) throws FirealarmPluginException { + boolean status = false; + Connection conn; + PreparedStatement stmt = null; + try { + conn = DeviceTypeDAO.getConnection(); + String createDBQuery = + "INSERT INTO firealarm_DEVICE(firealarm_DEVICE_ID, DEVICE_NAME, " + + "ACCESS_TOKEN, REFRESH_TOKEN) VALUES (?, ?, ?, ?)"; + + stmt = conn.prepareStatement(createDBQuery); + stmt.setString(1, connectedCupDevice.getDeviceIdentifier()); + stmt.setString(2, connectedCupDevice.getName()); + stmt.setString(3, DeviceTypeUtils.getDeviceProperty( + connectedCupDevice.getProperties(), + DeviceTypeConstants.DEVICE_PLUGIN_PROPERTY_ACCESS_TOKEN)); + stmt.setString(4, DeviceTypeUtils.getDeviceProperty( + connectedCupDevice.getProperties(), + DeviceTypeConstants.DEVICE_PLUGIN_PROPERTY_REFRESH_TOKEN)); + + int rows = stmt.executeUpdate(); + if (rows > 0) { + status = true; + if (log.isDebugEnabled()) { + log.debug("Connected Cup device " + connectedCupDevice.getDeviceIdentifier() + + " data has been added to the Connected Cup database."); + } + } + } catch (SQLException e) { + String msg = "Error occurred while adding the Connected Cup device '" + + connectedCupDevice.getDeviceIdentifier() + "' to the Connected Cup db."; + throw new FirealarmPluginException(msg, e); + } finally { + DeviceTypeUtils.cleanupResources(stmt, null); + } + return status; + } + + public boolean updateDevice(Device connectedCupDevice) throws FirealarmPluginException { + boolean status = false; + Connection conn; + PreparedStatement stmt = null; + try { + conn = DeviceTypeDAO.getConnection(); + String updateDBQuery = + "UPDATE firealarm_DEVICE SET DEVICE_NAME = ?, ACCESS_TOKEN=?, " + + "REFRESH_TOKEN=? WHERE firealarm_DEVICE_ID = ?"; + + stmt = conn.prepareStatement(updateDBQuery); + + if (connectedCupDevice.getProperties() == null) { + connectedCupDevice.setProperties(new ArrayList()); + } + stmt.setString(1, connectedCupDevice.getName()); + stmt.setString(2, DeviceTypeUtils.getDeviceProperty( + connectedCupDevice.getProperties(), + DeviceTypeConstants.DEVICE_PLUGIN_PROPERTY_ACCESS_TOKEN)); + stmt.setString(3, DeviceTypeUtils.getDeviceProperty( + connectedCupDevice.getProperties(), + DeviceTypeConstants.DEVICE_PLUGIN_PROPERTY_REFRESH_TOKEN)); + stmt.setString(4, connectedCupDevice.getDeviceIdentifier()); + int rows = stmt.executeUpdate(); + if (rows > 0) { + status = true; + if (log.isDebugEnabled()) { + log.debug("Connected Cup device " + connectedCupDevice.getDeviceIdentifier() + + " data has been modified."); + } + } + } catch (SQLException e) { + String msg = "Error occurred while modifying the Connected Cup device '" + + connectedCupDevice.getDeviceIdentifier() + "' data."; + log.error(msg, e); + throw new FirealarmPluginException(msg, e); + } finally { + DeviceTypeUtils.cleanupResources(stmt, null); + } + return status; + } + + public boolean deleteDevice(String deviceId) throws FirealarmPluginException { + boolean status = false; + Connection conn; + PreparedStatement stmt = null; + try { + conn = DeviceTypeDAO.getConnection(); + String deleteDBQuery = + "DELETE FROM firealarm_DEVICE WHERE firealarm_DEVICE_ID = ?"; + stmt = conn.prepareStatement(deleteDBQuery); + stmt.setString(1, deviceId); + int rows = stmt.executeUpdate(); + if (rows > 0) { + status = true; + if (log.isDebugEnabled()) { + log.debug("Connected Cup device " + deviceId + " data has deleted" + + " from the Connected Cup database."); + } + } + } catch (SQLException e) { + String msg = "Error occurred while deleting Connected Cup device " + deviceId; + log.error(msg, e); + throw new FirealarmPluginException(msg, e); + } finally { + DeviceTypeUtils.cleanupResources(stmt, null); + } + return status; + } + + public List getAllDevices() throws FirealarmPluginException { + Connection conn; + PreparedStatement stmt = null; + ResultSet resultSet = null; + Device connectedCupDevice; + List iotDevices = new ArrayList<>(); + + try { + conn = DeviceTypeDAO.getConnection(); + String selectDBQuery = + "SELECT firealarm_DEVICE_ID, DEVICE_NAME, ACCESS_TOKEN, REFRESH_TOKEN" + + "FROM firealarm_DEVICE"; + stmt = conn.prepareStatement(selectDBQuery); + resultSet = stmt.executeQuery(); + while (resultSet.next()) { + connectedCupDevice = new Device(); + connectedCupDevice.setDeviceIdentifier(resultSet.getString( + DeviceTypeConstants.DEVICE_PLUGIN_DEVICE_ID)); + connectedCupDevice.setName(resultSet.getString( + DeviceTypeConstants.DEVICE_PLUGIN_DEVICE_NAME)); + + List propertyList = new ArrayList<>(); + propertyList.add(DeviceTypeUtils.getProperty( + DeviceTypeConstants.DEVICE_PLUGIN_PROPERTY_ACCESS_TOKEN, + resultSet.getString("ACCESS_TOKEN"))); + propertyList.add(DeviceTypeUtils.getProperty( + DeviceTypeConstants.DEVICE_PLUGIN_PROPERTY_REFRESH_TOKEN, + resultSet.getString("REFRESH_TOKEN"))); + connectedCupDevice.setProperties(propertyList); + } + if (log.isDebugEnabled()) { + log.debug("All Connected Cup device details have fetched from Connected Cup database" + + "."); + } + return iotDevices; + } catch (SQLException e) { + String msg = "Error occurred while fetching all Connected Cup device data'"; + log.error(msg, e); + throw new FirealarmPluginException(msg, e); + } finally { + DeviceTypeUtils.cleanupResources(stmt, resultSet); + DeviceTypeDAO.closeConnection(); + } + } + +} diff --git a/modules/samples/firealarm/component/plugin/src/main/java/org/homeautomation/firealarm/plugin/impl/dao/util/DeviceTypeUtils.java b/modules/samples/firealarm/component/plugin/src/main/java/org/homeautomation/firealarm/plugin/impl/dao/util/DeviceTypeUtils.java new file mode 100644 index 00000000..e8c5c6c9 --- /dev/null +++ b/modules/samples/firealarm/component/plugin/src/main/java/org/homeautomation/firealarm/plugin/impl/dao/util/DeviceTypeUtils.java @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.homeautomation.firealarm.plugin.impl.dao.util; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.wso2.carbon.device.mgt.common.Device; + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.List; + +/** + * Contains utility methods used by FireAlarm plugin. + */ +public class DeviceTypeUtils { + + private static Log log = LogFactory.getLog(DeviceTypeUtils.class); + + public static String getDeviceProperty(List deviceProperties, + String propertyKey) { + String deviceProperty = ""; + for (Device.Property property : deviceProperties) { + if (propertyKey.equals(property.getName())) { + deviceProperty = property.getValue(); + } + } + return deviceProperty; + } + + public static Device.Property getProperty(String property, String value) { + if (property != null) { + Device.Property prop = new Device.Property(); + prop.setName(property); + prop.setValue(value); + return prop; + } + return null; + } + + public static void cleanupResources(Connection conn, PreparedStatement stmt, ResultSet rs) { + if (rs != null) { + try { + rs.close(); + } catch (SQLException e) { + log.warn("Error occurred while closing result set", e); + } + } + if (stmt != null) { + try { + stmt.close(); + } catch (SQLException e) { + log.warn("Error occurred while closing prepared statement", e); + } + } + if (conn != null) { + try { + conn.close(); + } catch (SQLException e) { + log.warn("Error occurred while closing database connection", e); + } + } + } + + public static void cleanupResources(PreparedStatement stmt, ResultSet rs) { + cleanupResources(null, stmt, rs); + } + +} diff --git a/modules/samples/firealarm/component/plugin/src/main/java/org/homeautomation/firealarm/plugin/internal/ServiceComponent.java b/modules/samples/firealarm/component/plugin/src/main/java/org/homeautomation/firealarm/plugin/internal/ServiceComponent.java new file mode 100644 index 00000000..d949e6a8 --- /dev/null +++ b/modules/samples/firealarm/component/plugin/src/main/java/org/homeautomation/firealarm/plugin/internal/ServiceComponent.java @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.homeautomation.firealarm.plugin.internal; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.homeautomation.firealarm.plugin.impl.DeviceTypeManagerService; +import org.osgi.framework.BundleContext; +import org.osgi.framework.ServiceRegistration; +import org.osgi.service.component.ComponentContext; +import org.wso2.carbon.device.mgt.common.spi.DeviceManagementService; + +/** + * @scr.component name="org.homeautomation.firealarm.plugin.internal.ServiceComponent" + * immediate="true" + */ + +public class ServiceComponent { + + private static final Log log = LogFactory.getLog(ServiceComponent.class); + private ServiceRegistration serviceRegistration; + + protected void activate(ComponentContext ctx) { + if (log.isDebugEnabled()) { + log.debug("Activating firealarm Management Service Component"); + } + try { + BundleContext bundleContext = ctx.getBundleContext(); + serviceRegistration = + bundleContext.registerService(DeviceManagementService.class.getName(), new + DeviceTypeManagerService(), null); + if (log.isDebugEnabled()) { + log.debug("firealarm Management Service Component has been successfully activated"); + } + } catch (Throwable e) { + log.error("Error occurred while activating Current Sensor Management Service Component", e); + } + } + + protected void deactivate(ComponentContext ctx) { + if (log.isDebugEnabled()) { + log.debug("De-activating firealarm Management Service Component"); + } + try { + if (serviceRegistration != null) { + serviceRegistration.unregister(); + } + if (log.isDebugEnabled()) { + log.debug("Current Sensor Management Service Component has been successfully de-activated"); + } + } catch (Throwable e) { + log.error("Error occurred while de-activating Iot Device Management bundle", e); + } + } + +} diff --git a/modules/samples/firealarm/component/pom.xml b/modules/samples/firealarm/component/pom.xml new file mode 100644 index 00000000..45d5e76c --- /dev/null +++ b/modules/samples/firealarm/component/pom.xml @@ -0,0 +1,268 @@ + + + + + + + org.homeautomation + firealarm + 1.0.0-SNAPSHOT + ../pom.xml + + 4.0.0 + 1.0.0-SNAPSHOT + firealarm-component + pom + + + + + org.apache.felix + maven-scr-plugin + ${maven-scr-plugin.version} + + + generate-scr-scrdescriptor + + scr + + + + + + + + + + + org.homeautomation + ${project-base-package}.plugin + 1.0.0-SNAPSHOT + provided + + + org.wso2.carbon.devicemgt + org.wso2.carbon.apimgt.webapp.publisher + ${carbon.device.mgt.version} + system + + ${basedir}/../../../../repository/components/plugins/org.wso2.carbon.apimgt.webapp.publisher_${carbon.device.mgt.jar.version}.jar + + + + org.wso2.carbon + org.wso2.carbon.ndatasource.core + ${carbon.kernel.version} + system + + ${basedir}/../../../../repository/components/plugins/org.wso2.carbon.ndatasource.core_${carbon.kernel.version}.jar + + + + org.wso2.carbon.devicemgt-plugins + org.wso2.carbon.device.mgt.iot + ${carbon.iot.device.mgt.version} + system + + ${basedir}/../../../../repository/components/plugins/org.wso2.carbon.device.mgt.iot_${carbon.iot.device.mgt.jar.version}.jar + + + + org.wso2.carbon.devicemgt + org.wso2.carbon.device.mgt.core + ${carbon.device.mgt.version} + system + + ${basedir}/../../../../repository/components/plugins/org.wso2.carbon.device.mgt.core_${carbon.device.mgt.jar.version}.jar + + + + org.wso2.carbon.devicemgt + org.wso2.carbon.device.mgt.common + ${carbon.device.mgt.version} + system + + ${basedir}/../../../../repository/components/plugins/org.wso2.carbon.device.mgt.common_${carbon.device.mgt.jar.version}.jar + + + + org.wso2.carbon.devicemgt + org.wso2.carbon.certificate.mgt.core + ${carbon.device.mgt.version} + system + + ${basedir}/../../../../repository/components/plugins/org.wso2.carbon.certificate.mgt.core_${carbon.device.mgt.jar.version}.jar + + + + org.wso2.carbon.devicemgt + org.wso2.carbon.apimgt.annotations + ${carbon.device.mgt.version} + system + + ${basedir}/../../../../repository/components/plugins/org.wso2.carbon.apimgt.annotations_${carbon.device.mgt.jar.version}.jar + + + + org.wso2.carbon.devicemgt + org.wso2.carbon.device.mgt.analytics + ${carbon.device.mgt.version} + system + + ${basedir}/../../../../repository/components/plugins/org.wso2.carbon.device.mgt.analytics_${carbon.device.mgt.jar.version}.jar + + + + commons-httpclient.wso2 + commons-httpclient + ${commons-httpclient.orbit.version} + system + + ${basedir}/../../../../repository/components/plugins/commons-httpclient_3.1.0.wso2v2.jar + + + + commons-httpclient.wso2 + commons-httpclient + ${commons-httpclient.orbit.version} + system + + ${basedir}/../../../../repository/components/plugins/commons-httpclient_3.1.0.wso2v2.jar + + + + org.wso2.carbon + org.wso2.carbon.utils + ${carbon.kernel.version} + + + org.bouncycastle.wso2 + bcprov-jdk15on + + + org.wso2.carbon + org.wso2.carbon.user.api + + + org.wso2.carbon + org.wso2.carbon.queuing + + + org.wso2.carbon + org.wso2.carbon.base + + + org.apache.axis2.wso2 + axis2 + + + org.igniterealtime.smack.wso2 + smack + + + org.igniterealtime.smack.wso2 + smackx + + + jaxen + jaxen + + + commons-fileupload.wso2 + commons-fileupload + + + org.apache.ant.wso2 + ant + + + org.apache.ant.wso2 + ant + + + commons-httpclient.wso2 + commons-httpclient + + + org.eclipse.equinox + javax.servlet + + + org.wso2.carbon + org.wso2.carbon.registry.api + + + system + + ${basedir}/../../../../repository/components/plugins/org.wso2.carbon.utils_${carbon.kernel.version}.jar + + + + org.igniterealtime.smack.wso2 + smack + ${smack.wso2.version} + system + + ${basedir}/../../../../repository/components/plugins/smack_3.0.4.wso2v1.jar + + + + org.igniterealtime.smack.wso2 + smackx + ${smackx.wso2.version} + system + + ${basedir}/../../../../repository/components/plugins/smackx_3.0.4.wso2v1.jar + + + + org.json.wso2 + json + ${commons-json.version} + system + + ${basedir}/../../../../repository/components/plugins/json_2.0.0.wso2v1.jar + + + + commons-codec + commons-codec + 1.4.0.wso2v1 + system + + ${basedir}/../../../../repository/components/plugins/commons-codec_1.4.0.wso2v1.jar + + + + commons-io + commons-io + ${commons-io.version} + + + + + plugin + controller + manager + analytics + ui + + \ No newline at end of file diff --git a/modules/samples/firealarm/component/ui/pom.xml b/modules/samples/firealarm/component/ui/pom.xml new file mode 100644 index 00000000..3e6076d1 --- /dev/null +++ b/modules/samples/firealarm/component/ui/pom.xml @@ -0,0 +1,58 @@ + + + + + + + org.homeautomation + firealarm-component + 1.0.0-SNAPSHOT + ../pom.xml + + 4.0.0 + ${groupId}.firealarm.ui + ${groupId}.firealarm.ui + pom + + + + maven-assembly-plugin + ${maven-assembly-plugin.version} + + ${project.artifactId}-1.0.0-SNAPSHOT + false + + src/assembly/src.xml + + + + + create-archive + package + + single + + + + + + + \ No newline at end of file diff --git a/modules/samples/firealarm/component/ui/src/assembly/src.xml b/modules/samples/firealarm/component/ui/src/assembly/src.xml new file mode 100644 index 00000000..3f381cbe --- /dev/null +++ b/modules/samples/firealarm/component/ui/src/assembly/src.xml @@ -0,0 +1,38 @@ + + + + + + src + + zip + + false + ${basedir}/src + + + ${basedir}/src/main/resources/jaggeryapps/ + / + true + + + \ No newline at end of file diff --git a/modules/samples/firealarm/component/ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.device.type.firealarm.device-view/device-view.hbs b/modules/samples/firealarm/component/ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.device.type.firealarm.device-view/device-view.hbs new file mode 100644 index 00000000..429c632a --- /dev/null +++ b/modules/samples/firealarm/component/ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.device.type.firealarm.device-view/device-view.hbs @@ -0,0 +1,130 @@ + +{{#zone "topCss"}} + +{{/zone}} + +{{#zone "device-thumbnail"}} + +{{/zone}} + +{{#zone "operation-status"}} + +{{/zone}} + +{{#zone "device-opetations"}} +
+ Operations +
+
+ {{unit "iot.unit.device.operation-bar" device=device}} +
+{{/zone}} + +{{#zone "device-detail-properties"}} +
+ +
+
+
+
Device Statistics
+ {{unit "iot.unit.device.stats" device=device}} +
+
+
Policy Compliance +
+
+
Policies
+
+ +
+
+ No policies found +
+
+
+
+
+ + + + + Add device specific policy +
+
+
Operations Log
+
+ +
+
+ Not available yet +
+
+
+
+
+
+
+
+{{/zone}} + + + diff --git a/modules/samples/firealarm/component/ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.device.type.firealarm.device-view/device-view.js b/modules/samples/firealarm/component/ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.device.type.firealarm.device-view/device-view.js new file mode 100644 index 00000000..9cf48f5e --- /dev/null +++ b/modules/samples/firealarm/component/ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.device.type.firealarm.device-view/device-view.js @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + + +/* + * Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +function onRequest(context) { + + var log = new Log("device-view.js"); + var deviceType = context.uriParams.deviceType; + var deviceId = request.getParameter("id"); + + var getProperty = require("process").getProperty; + var port = getProperty("carbon.https.port"); + var host = getProperty("carbon.local.ip"); + var sessionId = session.getId(); + if (deviceType != null && deviceType != undefined && deviceId != null && deviceId != undefined) { + var deviceModule = require("/app/modules/device.js").deviceModule; + var device = deviceModule.viewDevice(deviceType, deviceId); + + if (device && device.status != "error") { + log.info(device); + return {"device": device, "port": port, "host": host, "sessionId": sessionId}; + } + } +} \ No newline at end of file diff --git a/modules/samples/firealarm/component/ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.device.type.firealarm.device-view/device-view.json b/modules/samples/firealarm/component/ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.device.type.firealarm.device-view/device-view.json new file mode 100644 index 00000000..688e9398 --- /dev/null +++ b/modules/samples/firealarm/component/ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.device.type.firealarm.device-view/device-view.json @@ -0,0 +1,3 @@ +{ + "version": "1.0.0" +} \ No newline at end of file diff --git a/modules/samples/firealarm/component/ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.device.type.firealarm.device-view/public/images/current-sensor.png b/modules/samples/firealarm/component/ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.device.type.firealarm.device-view/public/images/current-sensor.png new file mode 100644 index 00000000..b1ce4901 Binary files /dev/null and b/modules/samples/firealarm/component/ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.device.type.firealarm.device-view/public/images/current-sensor.png differ diff --git a/modules/samples/firealarm/component/ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.device.type.firealarm.policy-edit/policy-edit.hbs b/modules/samples/firealarm/component/ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.device.type.firealarm.policy-edit/policy-edit.hbs new file mode 100644 index 00000000..cf80b006 --- /dev/null +++ b/modules/samples/firealarm/component/ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.device.type.firealarm.policy-edit/policy-edit.hbs @@ -0,0 +1,18 @@ + +{{unit "iot.unit.policy.edit"}} \ No newline at end of file diff --git a/modules/samples/firealarm/component/ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.device.type.firealarm.policy-edit/policy-edit.json b/modules/samples/firealarm/component/ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.device.type.firealarm.policy-edit/policy-edit.json new file mode 100644 index 00000000..688e9398 --- /dev/null +++ b/modules/samples/firealarm/component/ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.device.type.firealarm.policy-edit/policy-edit.json @@ -0,0 +1,3 @@ +{ + "version": "1.0.0" +} \ No newline at end of file diff --git a/modules/samples/firealarm/component/ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.device.type.firealarm.policy-view/policy-view.hbs b/modules/samples/firealarm/component/ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.device.type.firealarm.policy-view/policy-view.hbs new file mode 100644 index 00000000..c2a4706b --- /dev/null +++ b/modules/samples/firealarm/component/ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.device.type.firealarm.policy-view/policy-view.hbs @@ -0,0 +1,18 @@ + +{{unit "iot.unit.policy.view"}} \ No newline at end of file diff --git a/modules/samples/firealarm/component/ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.device.type.firealarm.policy-view/policy-view.json b/modules/samples/firealarm/component/ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.device.type.firealarm.policy-view/policy-view.json new file mode 100644 index 00000000..688e9398 --- /dev/null +++ b/modules/samples/firealarm/component/ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.device.type.firealarm.policy-view/policy-view.json @@ -0,0 +1,3 @@ +{ + "version": "1.0.0" +} \ No newline at end of file diff --git a/modules/samples/firealarm/component/ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.device.type.firealarm.policy-wizard/policy-wizard.hbs b/modules/samples/firealarm/component/ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.device.type.firealarm.policy-wizard/policy-wizard.hbs new file mode 100644 index 00000000..7b94f953 --- /dev/null +++ b/modules/samples/firealarm/component/ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.device.type.firealarm.policy-wizard/policy-wizard.hbs @@ -0,0 +1,18 @@ + +{{unit "iot.unit.policy.wizard"}} \ No newline at end of file diff --git a/modules/samples/firealarm/component/ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.device.type.firealarm.policy-wizard/policy-wizard.json b/modules/samples/firealarm/component/ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.device.type.firealarm.policy-wizard/policy-wizard.json new file mode 100644 index 00000000..688e9398 --- /dev/null +++ b/modules/samples/firealarm/component/ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.device.type.firealarm.policy-wizard/policy-wizard.json @@ -0,0 +1,3 @@ +{ + "version": "1.0.0" +} \ No newline at end of file diff --git a/modules/samples/firealarm/component/ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.device.type.firealarm.type-view/public/images/deviceType.png b/modules/samples/firealarm/component/ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.device.type.firealarm.type-view/public/images/deviceType.png new file mode 100644 index 00000000..7c580869 Binary files /dev/null and b/modules/samples/firealarm/component/ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.device.type.firealarm.type-view/public/images/deviceType.png differ diff --git a/modules/samples/firealarm/component/ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.device.type.firealarm.type-view/public/images/myDevices_analytics.png b/modules/samples/firealarm/component/ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.device.type.firealarm.type-view/public/images/myDevices_analytics.png new file mode 100644 index 00000000..0aafe6e7 Binary files /dev/null and b/modules/samples/firealarm/component/ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.device.type.firealarm.type-view/public/images/myDevices_analytics.png differ diff --git a/modules/samples/firealarm/component/ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.device.type.firealarm.type-view/public/images/schematicsGuide.png b/modules/samples/firealarm/component/ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.device.type.firealarm.type-view/public/images/schematicsGuide.png new file mode 100644 index 00000000..db4d0adb Binary files /dev/null and b/modules/samples/firealarm/component/ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.device.type.firealarm.type-view/public/images/schematicsGuide.png differ diff --git a/modules/samples/firealarm/component/ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.device.type.firealarm.type-view/public/images/thumb.png b/modules/samples/firealarm/component/ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.device.type.firealarm.type-view/public/images/thumb.png new file mode 100644 index 00000000..80696049 Binary files /dev/null and b/modules/samples/firealarm/component/ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.device.type.firealarm.type-view/public/images/thumb.png differ diff --git a/modules/samples/firealarm/component/ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.device.type.firealarm.type-view/public/js/download.js b/modules/samples/firealarm/component/ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.device.type.firealarm.type-view/public/js/download.js new file mode 100644 index 00000000..21251e2f --- /dev/null +++ b/modules/samples/firealarm/component/ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.device.type.firealarm.type-view/public/js/download.js @@ -0,0 +1,195 @@ +/* + * Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +var modalPopup = ".wr-modalpopup"; +var modalPopupContainer = modalPopup + " .modalpopup-container"; +var modalPopupContent = modalPopup + " .modalpopup-content"; +var body = "body"; + +/* + * set popup maximum height function. + */ +function setPopupMaxHeight() { + $(modalPopupContent).css('max-height', ($(body).height() - ($(body).height() / 100 * 30))); + $(modalPopupContainer).css('margin-top', (-($(modalPopupContainer).height() / 2))); +} + +/* + * show popup function. + */ +function showPopup() { + $(modalPopup).show(); + setPopupMaxHeight(); + $('#downloadForm').validate({ + rules: { + deviceName: { + minlength: 4, + required: true + } + }, + highlight: function (element) { + $(element).closest('.control-group').removeClass('success').addClass('error'); + }, + success: function (element) { + $(element).closest('.control-group').removeClass('error').addClass('success'); + $('label[for=deviceName]').remove(); + } + }); + var deviceType = ""; + $('.deviceType').each(function () { + if (this.value != "") { + deviceType = this.value; + } + }); +} + +/* + * hide popup function. + */ +function hidePopup() { + $('label[for=deviceName]').remove(); + $('.control-group').removeClass('success').removeClass('error'); + $(modalPopupContent).html(''); + $(modalPopup).hide(); +} + +/* + * DOM ready functions. + */ +$(document).ready(function () { + attachEvents(); +}); + +function attachEvents() { + /** + * Following click function would execute + * when a user clicks on "Download" link + * on Device Management page in WSO2 DC Console. + */ + $("a.download-link").click(function () { + var sketchType = $(this).data("sketchtype"); + var deviceType = $(this).data("devicetype"); + var downloadDeviceAPI = "/devicemgt/api/devices/sketch/generate_link"; + var payload = {"sketchType": sketchType, "deviceType": deviceType}; + $(modalPopupContent).html($('#download-device-modal-content').html()); + showPopup(); + var deviceName; + $("a#download-device-download-link").click(function () { + $('.new-device-name').each(function () { + if (this.value != "") { + deviceName = this.value; + } + }); + $('label[for=deviceName]').remove(); + if (deviceName && deviceName.length >= 4) { + payload.deviceName = deviceName; + invokerUtil.post( + downloadDeviceAPI, + payload, + function (data, textStatus, jqxhr) { + doAction(data); + }, + function (data) { + doAction(data); + } + ); + } else if (deviceName) { + $('.controls').append(''); + $('.control-group').removeClass('success').addClass('error'); + } else { + $('.controls').append(''); + $('.control-group').removeClass('success').addClass('error'); + } + }); + + $("a#download-device-cancel-link").click(function () { + hidePopup(); + }); + + }); +} + +function downloadAgent() { + var deviceName = ""; + $('.new-device-name').each(function () { + if (this.value != "") { + deviceName = this.value; + } + }); + var deviceType = ""; + $('.deviceType').each(function () { + if (this.value != "") { + deviceType = this.value; + } + }); + var sketchType = ""; + $('.sketchType').each(function () { + if (this.value != "") { + sketchType = this.value; + } + }); + var deviceNameFormat = /^[^~?!#$:;%^*`+={}\[\]\\()|<>,'"]{1,30}$/; + if (deviceName && deviceNameFormat.test(deviceName)) { + $(modalPopupContent).html($('#device-agent-downloading-content').html()); + var successCallback = function (data) { + data = JSON.parse(data); + hidePopup(); + window.location = "/devicemgt/api/devices/sketch/download/" + data.responseContent; + }; + var generateLink = "/" + deviceType + "_mgt/manager/device/" + sketchType + + "/generate_link?deviceName=" + deviceName; + invokerUtil.get(generateLink, successCallback, function (message) { + console.log(message.content); + hidePopup(); + doAction(data); + }); + } else { + $("#invalid-username-error-msg span").text("Invalid device name"); + $("#invalid-username-error-msg").removeClass("hidden"); + } +} + +function doAction(data) { + //if it is saml redirection response + if (data.status == null) { + document.write(data); + } + + if (data.status == "401") { + $(modalPopupContent).html($('#device-401-content').html()); + $("#device-401-link").click(function () { + window.location = "/devicemgt/login"; + }); + showPopup(); + } else if (data == "403") { + $(modalPopupContent).html($('#device-403-content').html()); + $("#device-403-link").click(function () { + window.location = "/devicemgt/login"; + }); + showPopup(); + } else { + $(modalPopupContent).html($('#device-unexpected-error-content').html()); + $("a#device-unexpected-error-link").click(function () { + hidePopup(); + }); + } +} \ No newline at end of file diff --git a/modules/samples/firealarm/component/ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.device.type.firealarm.type-view/public/js/jquery.validate.js b/modules/samples/firealarm/component/ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.device.type.firealarm.type-view/public/js/jquery.validate.js new file mode 100644 index 00000000..ae92b49e --- /dev/null +++ b/modules/samples/firealarm/component/ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.device.type.firealarm.type-view/public/js/jquery.validate.js @@ -0,0 +1,1234 @@ +/* + * Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +(function ($) { + + $.extend($.fn, { + // http://docs.jquery.com/Plugins/Validation/validate + validate: function (options) { + + // if nothing is selected, return nothing; can't chain anyway + if (!this.length) { + if (options && options.debug && window.console) { + console.warn("Nothing selected, can't validate, returning nothing."); + } + return; + } + + // check if a validator for this form was already created + var validator = $.data(this[0], "validator"); + if (validator) { + return validator; + } + + // Add novalidate tag if HTML5. + this.attr("novalidate", "novalidate"); + + validator = new $.validator(options, this[0]); + $.data(this[0], "validator", validator); + + if (validator.settings.onsubmit) { + + this.validateDelegate(":submit", "click", function (event) { + if (validator.settings.submitHandler) { + validator.submitButton = event.target; + } + // allow suppressing validation by adding a cancel class to the submit button + if ($(event.target).hasClass("cancel")) { + validator.cancelSubmit = true; + } + }); + + // validate the form on submit + this.submit(function (event) { + if (validator.settings.debug) { + // prevent form submit to be able to see console output + event.preventDefault(); + } + function handle() { + var hidden; + if (validator.settings.submitHandler) { + if (validator.submitButton) { + // insert a hidden input as a replacement for the missing submit button + hidden = $("").attr("name", validator.submitButton.name).val(validator.submitButton.value).appendTo(validator.currentForm); + } + validator.settings.submitHandler.call(validator, validator.currentForm, event); + if (validator.submitButton) { + // and clean up afterwards; thanks to no-block-scope, hidden can be referenced + hidden.remove(); + } + return false; + } + return true; + } + + // prevent submit for invalid forms or custom submit handlers + if (validator.cancelSubmit) { + validator.cancelSubmit = false; + return handle(); + } + if (validator.form()) { + if (validator.pendingRequest) { + validator.formSubmitted = true; + return false; + } + return handle(); + } else { + validator.focusInvalid(); + return false; + } + }); + } + + return validator; + }, + // http://docs.jquery.com/Plugins/Validation/valid + valid: function () { + if ($(this[0]).is("form")) { + return this.validate().form(); + } else { + var valid = true; + var validator = $(this[0].form).validate(); + this.each(function () { + valid &= validator.element(this); + }); + return valid; + } + }, + // attributes: space seperated list of attributes to retrieve and remove + removeAttrs: function (attributes) { + var result = {}, + $element = this; + $.each(attributes.split(/\s/), function (index, value) { + result[value] = $element.attr(value); + $element.removeAttr(value); + }); + return result; + }, + // http://docs.jquery.com/Plugins/Validation/rules + rules: function (command, argument) { + var element = this[0]; + + if (command) { + var settings = $.data(element.form, "validator").settings; + var staticRules = settings.rules; + var existingRules = $.validator.staticRules(element); + switch (command) { + case "add": + $.extend(existingRules, $.validator.normalizeRule(argument)); + staticRules[element.name] = existingRules; + if (argument.messages) { + settings.messages[element.name] = $.extend(settings.messages[element.name], argument.messages); + } + break; + case "remove": + if (!argument) { + delete staticRules[element.name]; + return existingRules; + } + var filtered = {}; + $.each(argument.split(/\s/), function (index, method) { + filtered[method] = existingRules[method]; + delete existingRules[method]; + }); + return filtered; + } + } + + var data = $.validator.normalizeRules( + $.extend( + {}, + $.validator.classRules(element), + $.validator.attributeRules(element), + $.validator.dataRules(element), + $.validator.staticRules(element) + ), element); + + // make sure required is at front + if (data.required) { + var param = data.required; + delete data.required; + data = $.extend({required: param}, data); + } + + return data; + } + }); + +// Custom selectors + $.extend($.expr[":"], { + // http://docs.jquery.com/Plugins/Validation/blank + blank: function (a) { + return !$.trim("" + a.value); + }, + // http://docs.jquery.com/Plugins/Validation/filled + filled: function (a) { + return !!$.trim("" + a.value); + }, + // http://docs.jquery.com/Plugins/Validation/unchecked + unchecked: function (a) { + return !a.checked; + } + }); + +// constructor for validator + $.validator = function (options, form) { + this.settings = $.extend(true, {}, $.validator.defaults, options); + this.currentForm = form; + this.init(); + }; + + $.validator.format = function (source, params) { + if (arguments.length === 1) { + return function () { + var args = $.makeArray(arguments); + args.unshift(source); + return $.validator.format.apply(this, args); + }; + } + if (arguments.length > 2 && params.constructor !== Array) { + params = $.makeArray(arguments).slice(1); + } + if (params.constructor !== Array) { + params = [params]; + } + $.each(params, function (i, n) { + source = source.replace(new RegExp("\\{" + i + "\\}", "g"), function () { + return n; + }); + }); + return source; + }; + + $.extend($.validator, { + + defaults: { + messages: {}, + groups: {}, + rules: {}, + errorClass: "error", + validClass: "valid", + errorElement: "label", + focusInvalid: true, + errorContainer: $([]), + errorLabelContainer: $([]), + onsubmit: true, + ignore: ":hidden", + ignoreTitle: false, + onfocusin: function (element, event) { + this.lastActive = element; + + // hide error label and remove error class on focus if enabled + if (this.settings.focusCleanup && !this.blockFocusCleanup) { + if (this.settings.unhighlight) { + this.settings.unhighlight.call(this, element, this.settings.errorClass, this.settings.validClass); + } + this.addWrapper(this.errorsFor(element)).hide(); + } + }, + onfocusout: function (element, event) { + if (!this.checkable(element) && (element.name in this.submitted || !this.optional(element))) { + this.element(element); + } + }, + onkeyup: function (element, event) { + if (event.which === 9 && this.elementValue(element) === "") { + return; + } else if (element.name in this.submitted || element === this.lastElement) { + this.element(element); + } + }, + onclick: function (element, event) { + // click on selects, radiobuttons and checkboxes + if (element.name in this.submitted) { + this.element(element); + } + // or option elements, check parent select in that case + else if (element.parentNode.name in this.submitted) { + this.element(element.parentNode); + } + }, + highlight: function (element, errorClass, validClass) { + if (element.type === "radio") { + this.findByName(element.name).addClass(errorClass).removeClass(validClass); + } else { + $(element).addClass(errorClass).removeClass(validClass); + } + }, + unhighlight: function (element, errorClass, validClass) { + if (element.type === "radio") { + this.findByName(element.name).removeClass(errorClass).addClass(validClass); + } else { + $(element).removeClass(errorClass).addClass(validClass); + } + } + }, + + // http://docs.jquery.com/Plugins/Validation/Validator/setDefaults + setDefaults: function (settings) { + $.extend($.validator.defaults, settings); + }, + + messages: { + required: "This field is required.", + remote: "Please fix this field.", + email: "Please enter a valid email address.", + url: "Please enter a valid URL.", + date: "Please enter a valid date.", + dateISO: "Please enter a valid date (ISO).", + number: "Please enter a valid number.", + digits: "Please enter only digits.", + creditcard: "Please enter a valid credit card number.", + equalTo: "Please enter the same value again.", + maxlength: $.validator.format("Please enter no more than {0} characters."), + minlength: $.validator.format("Please enter at least {0} characters."), + rangelength: $.validator.format("Please enter a value between {0} and {1} characters long."), + range: $.validator.format("Please enter a value between {0} and {1}."), + max: $.validator.format("Please enter a value less than or equal to {0}."), + min: $.validator.format("Please enter a value greater than or equal to {0}.") + }, + + autoCreateRanges: false, + + prototype: { + + init: function () { + this.labelContainer = $(this.settings.errorLabelContainer); + this.errorContext = this.labelContainer.length && this.labelContainer || $(this.currentForm); + this.containers = $(this.settings.errorContainer).add(this.settings.errorLabelContainer); + this.submitted = {}; + this.valueCache = {}; + this.pendingRequest = 0; + this.pending = {}; + this.invalid = {}; + this.reset(); + + var groups = (this.groups = {}); + $.each(this.settings.groups, function (key, value) { + if (typeof value === "string") { + value = value.split(/\s/); + } + $.each(value, function (index, name) { + groups[name] = key; + }); + }); + var rules = this.settings.rules; + $.each(rules, function (key, value) { + rules[key] = $.validator.normalizeRule(value); + }); + + function delegate(event) { + var validator = $.data(this[0].form, "validator"), + eventType = "on" + event.type.replace(/^validate/, ""); + if (validator.settings[eventType]) { + validator.settings[eventType].call(validator, this[0], event); + } + } + + $(this.currentForm) + .validateDelegate( ":text, [type='password'], [type='file'], select, textarea, " + + "[type='number'], [type='search'] ,[type='tel'], [type='url'], " + + "[type='email'], [type='datetime'], [type='date'], [type='month'], " + + "[type='week'], [type='time'], [type='datetime-local'], " + + "[type='range'], [type='color'] ", + "focusin focusout keyup", delegate) + .validateDelegate("[type='radio'], [type='checkbox'], select, option", "click", delegate); + + if (this.settings.invalidHandler) { + $(this.currentForm).bind("invalid-form.validate", this.settings.invalidHandler); + } + }, + + // http://docs.jquery.com/Plugins/Validation/Validator/form + form: function () { + this.checkForm(); + $.extend(this.submitted, this.errorMap); + this.invalid = $.extend({}, this.errorMap); + if (!this.valid()) { + $(this.currentForm).triggerHandler("invalid-form", [this]); + } + this.showErrors(); + return this.valid(); + }, + + checkForm: function () { + this.prepareForm(); + for (var i = 0, elements = (this.currentElements = this.elements()); elements[i]; i++) { + this.check(elements[i]); + } + return this.valid(); + }, + + // http://docs.jquery.com/Plugins/Validation/Validator/element + element: function (element) { + element = this.validationTargetFor(this.clean(element)); + this.lastElement = element; + this.prepareElement(element); + this.currentElements = $(element); + var result = this.check(element) !== false; + if (result) { + delete this.invalid[element.name]; + } else { + this.invalid[element.name] = true; + } + if (!this.numberOfInvalids()) { + // Hide error containers on last error + this.toHide = this.toHide.add(this.containers); + } + this.showErrors(); + return result; + }, + + // http://docs.jquery.com/Plugins/Validation/Validator/showErrors + showErrors: function (errors) { + if (errors) { + // add items to error list and map + $.extend(this.errorMap, errors); + this.errorList = []; + for (var name in errors) { + this.errorList.push({ + message: errors[name], + element: this.findByName(name)[0] + }); + } + // remove items from success list + this.successList = $.grep(this.successList, function (element) { + return !(element.name in errors); + }); + } + if (this.settings.showErrors) { + this.settings.showErrors.call(this, this.errorMap, this.errorList); + } else { + this.defaultShowErrors(); + } + }, + + // http://docs.jquery.com/Plugins/Validation/Validator/resetForm + resetForm: function () { + if ($.fn.resetForm) { + $(this.currentForm).resetForm(); + } + this.submitted = {}; + this.lastElement = null; + this.prepareForm(); + this.hideErrors(); + this.elements().removeClass(this.settings.errorClass).removeData("previousValue"); + }, + + numberOfInvalids: function () { + return this.objectLength(this.invalid); + }, + + objectLength: function (obj) { + var count = 0; + for (var i in obj) { + count++; + } + return count; + }, + + hideErrors: function () { + this.addWrapper(this.toHide).hide(); + }, + + valid: function () { + return this.size() === 0; + }, + + size: function () { + return this.errorList.length; + }, + + focusInvalid: function () { + if (this.settings.focusInvalid) { + try { + $(this.findLastActive() || this.errorList.length && this.errorList[0].element || []) + .filter(":visible") + .focus() + // manually trigger focusin event; without it, focusin handler isn't called, findLastActive won't have anything to find + .trigger("focusin"); + } catch (e) { + // ignore IE throwing errors when focusing hidden elements + } + } + }, + + findLastActive: function () { + var lastActive = this.lastActive; + return lastActive && $.grep(this.errorList, function (n) { + return n.element.name === lastActive.name; + }).length === 1 && lastActive; + }, + + elements: function () { + var validator = this, + rulesCache = {}; + + // select all valid inputs inside the form (no submit or reset buttons) + return $(this.currentForm) + .find("input, select, textarea") + .not(":submit, :reset, :image, [disabled]") + .not(this.settings.ignore) + .filter(function () { + if (!this.name) { + if (window.console) { + console.error("%o has no name assigned", this); + } + throw new Error("Failed to validate, found an element with no name assigned. See console for element reference."); + } + + // select only the first element for each name, and only those with rules specified + if (this.name in rulesCache || !validator.objectLength($(this).rules())) { + return false; + } + + rulesCache[this.name] = true; + return true; + }); + }, + + clean: function (selector) { + return $(selector)[0]; + }, + + errors: function () { + var errorClass = this.settings.errorClass.replace(" ", "."); + return $(this.settings.errorElement + "." + errorClass, this.errorContext); + }, + + reset: function () { + this.successList = []; + this.errorList = []; + this.errorMap = {}; + this.toShow = $([]); + this.toHide = $([]); + this.currentElements = $([]); + }, + + prepareForm: function () { + this.reset(); + this.toHide = this.errors().add(this.containers); + }, + + prepareElement: function (element) { + this.reset(); + this.toHide = this.errorsFor(element); + }, + + elementValue: function (element) { + var type = $(element).attr("type"), + val = $(element).val(); + + if (type === "radio" || type === "checkbox") { + return $("input[name='" + $(element).attr("name") + "']:checked").val(); + } + + if (typeof val === "string") { + return val.replace(/\r/g, ""); + } + return val; + }, + + check: function (element) { + element = this.validationTargetFor(this.clean(element)); + + var rules = $(element).rules(); + var dependencyMismatch = false; + var val = this.elementValue(element); + var result; + + for (var method in rules) { + var rule = {method: method, parameters: rules[method]}; + try { + + result = $.validator.methods[method].call(this, val, element, rule.parameters); + + // if a method indicates that the field is optional and therefore valid, + // don't mark it as valid when there are no other rules + if (result === "dependency-mismatch") { + dependencyMismatch = true; + continue; + } + dependencyMismatch = false; + + if (result === "pending") { + this.toHide = this.toHide.not(this.errorsFor(element)); + return; + } + + if (!result) { + this.formatAndAdd(element, rule); + return false; + } + } catch (e) { + if (this.settings.debug && window.console) { + console.log("Exception occured when checking element " + element.id + ", check the '" + rule.method + "' method.", e); + } + throw e; + } + } + if (dependencyMismatch) { + return; + } + if (this.objectLength(rules)) { + this.successList.push(element); + } + return true; + }, + + // return the custom message for the given element and validation method + // specified in the element's HTML5 data attribute + customDataMessage: function (element, method) { + return $(element).data("msg-" + method.toLowerCase()) || (element.attributes && $(element).attr("data-msg-" + method.toLowerCase())); + }, + + // return the custom message for the given element name and validation method + customMessage: function (name, method) { + var m = this.settings.messages[name]; + return m && (m.constructor === String ? m : m[method]); + }, + + // return the first defined argument, allowing empty strings + findDefined: function () { + for (var i = 0; i < arguments.length; i++) { + if (arguments[i] !== undefined) { + return arguments[i]; + } + } + return undefined; + }, + + defaultMessage: function (element, method) { + return this.findDefined( + this.customMessage(element.name, method), + this.customDataMessage(element, method), + // title is never undefined, so handle empty string as undefined + !this.settings.ignoreTitle && element.title || undefined, + $.validator.messages[method], + "Warning: No message defined for " + element.name + "" + ); + }, + + formatAndAdd: function (element, rule) { + var message = this.defaultMessage(element, rule.method), + theregex = /\$?\{(\d+)\}/g; + if (typeof message === "function") { + message = message.call(this, rule.parameters, element); + } else if (theregex.test(message)) { + message = $.validator.format(message.replace(theregex, "{$1}"), rule.parameters); + } + this.errorList.push({ + message: message, + element: element + }); + + this.errorMap[element.name] = message; + this.submitted[element.name] = message; + }, + + addWrapper: function (toToggle) { + if (this.settings.wrapper) { + toToggle = toToggle.add(toToggle.parent(this.settings.wrapper)); + } + return toToggle; + }, + + defaultShowErrors: function () { + var i, elements; + for (i = 0; this.errorList[i]; i++) { + var error = this.errorList[i]; + if (this.settings.highlight) { + this.settings.highlight.call(this, error.element, this.settings.errorClass, this.settings.validClass); + } + this.showLabel(error.element, error.message); + } + if (this.errorList.length) { + this.toShow = this.toShow.add(this.containers); + } + if (this.settings.success) { + for (i = 0; this.successList[i]; i++) { + this.showLabel(this.successList[i]); + } + } + if (this.settings.unhighlight) { + for (i = 0, elements = this.validElements(); elements[i]; i++) { + this.settings.unhighlight.call(this, elements[i], this.settings.errorClass, this.settings.validClass); + } + } + this.toHide = this.toHide.not(this.toShow); + this.hideErrors(); + this.addWrapper(this.toShow).show(); + }, + + validElements: function () { + return this.currentElements.not(this.invalidElements()); + }, + + invalidElements: function () { + return $(this.errorList).map(function () { + return this.element; + }); + }, + + showLabel: function (element, message) { + var label = this.errorsFor(element); + if (label.length) { + // refresh error/success class + label.removeClass(this.settings.validClass).addClass(this.settings.errorClass); + + // check if we have a generated label, replace the message then + if (label.attr("generated")) { + label.html(message); + } + } else { + // create label + label = $("<" + this.settings.errorElement + "/>") + .attr({"for": this.idOrName(element), generated: true}) + .addClass(this.settings.errorClass) + .html(message || ""); + if (this.settings.wrapper) { + // make sure the element is visible, even in IE + // actually showing the wrapped element is handled elsewhere + label = label.hide().show().wrap("<" + this.settings.wrapper + "/>").parent(); + } + if (!this.labelContainer.append(label).length) { + if (this.settings.errorPlacement) { + this.settings.errorPlacement(label, $(element)); + } else { + label.insertAfter(element); + } + } + } + if (!message && this.settings.success) { + label.text(""); + if (typeof this.settings.success === "string") { + label.addClass(this.settings.success); + } else { + this.settings.success(label, element); + } + } + this.toShow = this.toShow.add(label); + }, + + errorsFor: function (element) { + var name = this.idOrName(element); + return this.errors().filter(function () { + return $(this).attr("for") === name; + }); + }, + + idOrName: function (element) { + return this.groups[element.name] || (this.checkable(element) ? element.name : element.id || element.name); + }, + + validationTargetFor: function (element) { + // if radio/checkbox, validate first element in group instead + if (this.checkable(element)) { + element = this.findByName(element.name).not(this.settings.ignore)[0]; + } + return element; + }, + + checkable: function (element) { + return (/radio|checkbox/i).test(element.type); + }, + + findByName: function (name) { + return $(this.currentForm).find("[name='" + name + "']"); + }, + + getLength: function (value, element) { + switch (element.nodeName.toLowerCase()) { + case "select": + return $("option:selected", element).length; + case "input": + if (this.checkable(element)) { + return this.findByName(element.name).filter(":checked").length; + } + } + return value.length; + }, + + depend: function (param, element) { + return this.dependTypes[typeof param] ? this.dependTypes[typeof param](param, element) : true; + }, + + dependTypes: { + "boolean": function (param, element) { + return param; + }, + "string": function (param, element) { + return !!$(param, element.form).length; + }, + "function": function (param, element) { + return param(element); + } + }, + + optional: function (element) { + var val = this.elementValue(element); + return !$.validator.methods.required.call(this, val, element) && "dependency-mismatch"; + }, + + startRequest: function (element) { + if (!this.pending[element.name]) { + this.pendingRequest++; + this.pending[element.name] = true; + } + }, + + stopRequest: function (element, valid) { + this.pendingRequest--; + // sometimes synchronization fails, make sure pendingRequest is never < 0 + if (this.pendingRequest < 0) { + this.pendingRequest = 0; + } + delete this.pending[element.name]; + if (valid && this.pendingRequest === 0 && this.formSubmitted && this.form()) { + $(this.currentForm).submit(); + this.formSubmitted = false; + } else if (!valid && this.pendingRequest === 0 && this.formSubmitted) { + $(this.currentForm).triggerHandler("invalid-form", [this]); + this.formSubmitted = false; + } + }, + + previousValue: function (element) { + return $.data(element, "previousValue") || $.data(element, "previousValue", { + old: null, + valid: true, + message: this.defaultMessage(element, "remote") + }); + } + + }, + + classRuleSettings: { + required: {required: true}, + email: {email: true}, + url: {url: true}, + date: {date: true}, + dateISO: {dateISO: true}, + number: {number: true}, + digits: {digits: true}, + creditcard: {creditcard: true} + }, + + addClassRules: function (className, rules) { + if (className.constructor === String) { + this.classRuleSettings[className] = rules; + } else { + $.extend(this.classRuleSettings, className); + } + }, + + classRules: function (element) { + var rules = {}; + var classes = $(element).attr("class"); + if (classes) { + $.each(classes.split(" "), function () { + if (this in $.validator.classRuleSettings) { + $.extend(rules, $.validator.classRuleSettings[this]); + } + }); + } + return rules; + }, + + attributeRules: function (element) { + var rules = {}; + var $element = $(element); + + for (var method in $.validator.methods) { + var value; + + // support for in both html5 and older browsers + if (method === "required") { + value = $element.get(0).getAttribute(method); + // Some browsers return an empty string for the required attribute + // and non-HTML5 browsers might have required="" markup + if (value === "") { + value = true; + } + // force non-HTML5 browsers to return bool + value = !!value; + } else { + value = $element.attr(method); + } + + if (value) { + rules[method] = value; + } else if ($element[0].getAttribute("type") === method) { + rules[method] = true; + } + } + + // maxlength may be returned as -1, 2147483647 (IE) and 524288 (safari) for text inputs + if (rules.maxlength && /-1|2147483647|524288/.test(rules.maxlength)) { + delete rules.maxlength; + } + + return rules; + }, + + dataRules: function (element) { + var method, value, + rules = {}, $element = $(element); + for (method in $.validator.methods) { + value = $element.data("rule-" + method.toLowerCase()); + if (value !== undefined) { + rules[method] = value; + } + } + return rules; + }, + + staticRules: function (element) { + var rules = {}; + var validator = $.data(element.form, "validator"); + if (validator.settings.rules) { + rules = $.validator.normalizeRule(validator.settings.rules[element.name]) || {}; + } + return rules; + }, + + normalizeRules: function (rules, element) { + // handle dependency check + $.each(rules, function (prop, val) { + // ignore rule when param is explicitly false, eg. required:false + if (val === false) { + delete rules[prop]; + return; + } + if (val.param || val.depends) { + var keepRule = true; + switch (typeof val.depends) { + case "string": + keepRule = !!$(val.depends, element.form).length; + break; + case "function": + keepRule = val.depends.call(element, element); + break; + } + if (keepRule) { + rules[prop] = val.param !== undefined ? val.param : true; + } else { + delete rules[prop]; + } + } + }); + + // evaluate parameters + $.each(rules, function (rule, parameter) { + rules[rule] = $.isFunction(parameter) ? parameter(element) : parameter; + }); + + // clean number parameters + $.each(["minlength", "maxlength", "min", "max"], function () { + if (rules[this]) { + rules[this] = Number(rules[this]); + } + }); + $.each(["rangelength", "range"], function () { + var parts; + if (rules[this]) { + if ($.isArray(rules[this])) { + rules[this] = [Number(rules[this][0]), Number(rules[this][1])]; + } else if (typeof rules[this] === "string") { + parts = rules[this].split(/[\s,]+/); + rules[this] = [Number(parts[0]), Number(parts[1])]; + } + } + }); + + if ($.validator.autoCreateRanges) { + // auto-create ranges + if (rules.min && rules.max) { + rules.range = [rules.min, rules.max]; + delete rules.min; + delete rules.max; + } + if (rules.minlength && rules.maxlength) { + rules.rangelength = [rules.minlength, rules.maxlength]; + delete rules.minlength; + delete rules.maxlength; + } + } + + return rules; + }, + + // Converts a simple string to a {string: true} rule, e.g., "required" to {required:true} + normalizeRule: function (data) { + if (typeof data === "string") { + var transformed = {}; + $.each(data.split(/\s/), function () { + transformed[this] = true; + }); + data = transformed; + } + return data; + }, + + // http://docs.jquery.com/Plugins/Validation/Validator/addMethod + addMethod: function (name, method, message) { + $.validator.methods[name] = method; + $.validator.messages[name] = message !== undefined ? message : $.validator.messages[name]; + if (method.length < 3) { + $.validator.addClassRules(name, $.validator.normalizeRule(name)); + } + }, + + methods: { + + // http://docs.jquery.com/Plugins/Validation/Methods/required + required: function (value, element, param) { + // check if dependency is met + if (!this.depend(param, element)) { + return "dependency-mismatch"; + } + if (element.nodeName.toLowerCase() === "select") { + // could be an array for select-multiple or a string, both are fine this way + var val = $(element).val(); + return val && val.length > 0; + } + if (this.checkable(element)) { + return this.getLength(value, element) > 0; + } + return $.trim(value).length > 0; + }, + + // http://docs.jquery.com/Plugins/Validation/Methods/remote + remote: function (value, element, param) { + if (this.optional(element)) { + return "dependency-mismatch"; + } + + var previous = this.previousValue(element); + if (!this.settings.messages[element.name]) { + this.settings.messages[element.name] = {}; + } + previous.originalMessage = this.settings.messages[element.name].remote; + this.settings.messages[element.name].remote = previous.message; + + param = typeof param === "string" && {url: param} || param; + + if (previous.old === value) { + return previous.valid; + } + + previous.old = value; + var validator = this; + this.startRequest(element); + var data = {}; + data[element.name] = value; + $.ajax($.extend(true, { + url: param, + mode: "abort", + port: "validate" + element.name, + dataType: "json", + data: data, + success: function (response) { + validator.settings.messages[element.name].remote = previous.originalMessage; + var valid = response === true || response === "true"; + if (valid) { + var submitted = validator.formSubmitted; + validator.prepareElement(element); + validator.formSubmitted = submitted; + validator.successList.push(element); + delete validator.invalid[element.name]; + validator.showErrors(); + } else { + var errors = {}; + var message = response || validator.defaultMessage(element, "remote"); + errors[element.name] = previous.message = $.isFunction(message) ? message(value) : message; + validator.invalid[element.name] = true; + validator.showErrors(errors); + } + previous.valid = valid; + validator.stopRequest(element, valid); + } + }, param)); + return "pending"; + }, + + // http://docs.jquery.com/Plugins/Validation/Methods/minlength + minlength: function (value, element, param) { + var length = $.isArray(value) ? value.length : this.getLength($.trim(value), element); + return this.optional(element) || length >= param; + }, + + // http://docs.jquery.com/Plugins/Validation/Methods/maxlength + maxlength: function (value, element, param) { + var length = $.isArray(value) ? value.length : this.getLength($.trim(value), element); + return this.optional(element) || length <= param; + }, + + // http://docs.jquery.com/Plugins/Validation/Methods/rangelength + rangelength: function (value, element, param) { + var length = $.isArray(value) ? value.length : this.getLength($.trim(value), element); + return this.optional(element) || ( length >= param[0] && length <= param[1] ); + }, + + // http://docs.jquery.com/Plugins/Validation/Methods/min + min: function (value, element, param) { + return this.optional(element) || value >= param; + }, + + // http://docs.jquery.com/Plugins/Validation/Methods/max + max: function (value, element, param) { + return this.optional(element) || value <= param; + }, + + // http://docs.jquery.com/Plugins/Validation/Methods/range + range: function (value, element, param) { + return this.optional(element) || ( value >= param[0] && value <= param[1] ); + }, + + // http://docs.jquery.com/Plugins/Validation/Methods/email + email: function (value, element) { + // contributed by Scott Gonzalez: http://projects.scottsplayground.com/email_address_validation/ + return this.optional(element) || /^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))$/i.test(value); + }, + + // http://docs.jquery.com/Plugins/Validation/Methods/url + url: function (value, element) { + // contributed by Scott Gonzalez: http://projects.scottsplayground.com/iri/ + return this.optional(element) || /^(https?|s?ftp):\/\/(((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?(((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?)(:\d*)?)(\/((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)?(\?((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(#((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/i.test(value); + }, + + // http://docs.jquery.com/Plugins/Validation/Methods/date + date: function (value, element) { + return this.optional(element) || !/Invalid|NaN/.test(new Date(value).toString()); + }, + + // http://docs.jquery.com/Plugins/Validation/Methods/dateISO + dateISO: function (value, element) { + return this.optional(element) || /^\d{4}[\/\-]\d{1,2}[\/\-]\d{1,2}$/.test(value); + }, + + // http://docs.jquery.com/Plugins/Validation/Methods/number + number: function (value, element) { + return this.optional(element) || /^-?(?:\d+|\d{1,3}(?:,\d{3})+)?(?:\.\d+)?$/.test(value); + }, + + // http://docs.jquery.com/Plugins/Validation/Methods/digits + digits: function (value, element) { + return this.optional(element) || /^\d+$/.test(value); + }, + + // http://docs.jquery.com/Plugins/Validation/Methods/creditcard + // based on http://en.wikipedia.org/wiki/Luhn + creditcard: function (value, element) { + if (this.optional(element)) { + return "dependency-mismatch"; + } + // accept only spaces, digits and dashes + if (/[^0-9 \-]+/.test(value)) { + return false; + } + var nCheck = 0, + nDigit = 0, + bEven = false; + + value = value.replace(/\D/g, ""); + + for (var n = value.length - 1; n >= 0; n--) { + var cDigit = value.charAt(n); + nDigit = parseInt(cDigit, 10); + if (bEven) { + if ((nDigit *= 2) > 9) { + nDigit -= 9; + } + } + nCheck += nDigit; + bEven = !bEven; + } + + return (nCheck % 10) === 0; + }, + + // http://docs.jquery.com/Plugins/Validation/Methods/equalTo + equalTo: function (value, element, param) { + // bind to the blur event of the target in order to revalidate whenever the target field is updated + // TODO find a way to bind the event just once, avoiding the unbind-rebind overhead + var target = $(param); + if (this.settings.onfocusout) { + target.unbind(".validate-equalTo").bind("blur.validate-equalTo", function () { + $(element).valid(); + }); + } + return value === target.val(); + } + + } + + }); + +// deprecated, use $.validator.format instead + $.format = $.validator.format; + +}(jQuery)); + +// ajax mode: abort +// usage: $.ajax({ mode: "abort"[, port: "uniqueport"]}); +// if mode:"abort" is used, the previous request on that port (port can be undefined) is aborted via XMLHttpRequest.abort() +(function ($) { + var pendingRequests = {}; + // Use a prefilter if available (1.5+) + if ($.ajaxPrefilter) { + $.ajaxPrefilter(function (settings, _, xhr) { + var port = settings.port; + if (settings.mode === "abort") { + if (pendingRequests[port]) { + pendingRequests[port].abort(); + } + pendingRequests[port] = xhr; + } + }); + } else { + // Proxy ajax + var ajax = $.ajax; + $.ajax = function (settings) { + var mode = ( "mode" in settings ? settings : $.ajaxSettings ).mode, + port = ( "port" in settings ? settings : $.ajaxSettings ).port; + if (mode === "abort") { + if (pendingRequests[port]) { + pendingRequests[port].abort(); + } + return (pendingRequests[port] = ajax.apply(this, arguments)); + } + return ajax.apply(this, arguments); + }; + } +}(jQuery)); + +// provides delegate(type: String, delegate: Selector, handler: Callback) plugin for easier event delegation +// handler is only called when $(event.target).is(delegate), in the scope of the jquery-object for event.target +(function ($) { + $.extend($.fn, { + validateDelegate: function (delegate, type, handler) { + return this.bind(type, function (event) { + var target = $(event.target); + if (target.is(delegate)) { + return handler.apply(target, arguments); + } + }); + } + }); +}(jQuery)); diff --git a/modules/samples/firealarm/component/ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.device.type.firealarm.type-view/type-view.hbs b/modules/samples/firealarm/component/ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.device.type.firealarm.type-view/type-view.hbs new file mode 100644 index 00000000..8299b21e --- /dev/null +++ b/modules/samples/firealarm/component/ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.device.type.firealarm.type-view/type-view.hbs @@ -0,0 +1,378 @@ +
+

Fire Alarm

+
+
+ +
+ +
+ +
+ +

What it Does

+
+

Connect your Fire Alarm to WSO2 IoT Server.

+
+

An ESP8266 based fire alarm device. Once run, the Fire alarm will connect to WSO2 IoTServer + and push Temperature and Humidity readings via MQTT. You can also on/off fire alarm buzzer + remotely with IoTServer. +

+
+

What You Need

+
+
    +
  • + STEP 01 +    NodeMCU loaded ESP8266 201 Module. +
  • +
  • + STEP 02 +    DHT11 Temperature & Humidity Sensor. +
  • +
  • + STEP 03 +    Buzzer. +
  • +
  • + STEP 04 +    USB to TTL converter. +
  • +
  • + STEP 05 +    ESPlorer software. If you don't have please click + [here] + to download. +
  • +
+
+ View API   + Download + Agent + +
+ +
+ +
+ +
+ + + +
+ +
+ +
+ +
+ +
+ +
+ +
+ +
+ +
+ +
+ +

+
+ +
+

Prepare

+
+
    +
  • + 01 +    Connect USB to TTL converter and other component with ESP8266 201 + module + as schematic in FIRE ALARM SETUP. +
  • +
  • + 02 +    Download Agent files from [Download Agent] link above. +
  • +
  • + 03 +    Unzip the downloaded Fire Alarm Agent +
  • +
  • + 04 +    Open wifi-connect.lua and provide appropriate values for + [SSID] and + [Password] + variables according to your network. +
  • +
  • + 05 +    Upload all .lua files to ESP8266 using ESPlorer in following order. + Then restart the ESP8266. +
    +                + + + + +    dht_lib.lua +
    +                + + + + +    wifi-connect.lua +
    +                + + + + +    read-sensor.lua +
    +                + + + + +    init.lua +

    +
  • +
  • + 06 +    Now you can remove USB to TTL module and fix fire alarm device in any + place you want. +

    +                + + + + +    ESP8266 will publish temperature and humidity from DHT11 to + WSO2-IoT-Server +

    +                + + + + +    Buzzer can be controlled from Device Management page. +
  • +
+
+
+ +
+

Fire alarm Setup

+
+

Click on the image to zoom

+
+ + + +
+
+
+ +
+

Try Out

+
+
    +
  • 01   You can view + all your connected + devices at [Device + Management] + page. +
  • +
  • 02   Select one of + connected devices and check for + available control operations. +
  • +
+
+ +
+ + + +{{#zone "bottomJs"}} + {{js "/js/download.js"}} + {{js "/js/jquery.validate.js"}} +{{/zone}} + diff --git a/modules/samples/firealarm/component/ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.device.type.firealarm.type-view/type-view.json b/modules/samples/firealarm/component/ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.device.type.firealarm.type-view/type-view.json new file mode 100644 index 00000000..688e9398 --- /dev/null +++ b/modules/samples/firealarm/component/ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.device.type.firealarm.type-view/type-view.json @@ -0,0 +1,3 @@ +{ + "version": "1.0.0" +} \ No newline at end of file diff --git a/modules/samples/firealarm/feature/feature/pom.xml b/modules/samples/firealarm/feature/feature/pom.xml new file mode 100644 index 00000000..aa60607d --- /dev/null +++ b/modules/samples/firealarm/feature/feature/pom.xml @@ -0,0 +1,244 @@ + + + + + + + org.homeautomation + firealarm-feature + 1.0.0-SNAPSHOT + ../pom.xml + + 4.0.0 + 1.0.0-SNAPSHOT + ${groupId}.firealarm.feature + pom + ${project.artifactId} + http://wso2.org + + + org.homeautomation + ${project-base-package}.plugin + 1.0.0-SNAPSHOT + + + org.homeautomation + ${project-base-package}.manager + 1.0.0-SNAPSHOT + war + + + org.homeautomation + ${project-base-package}.controller + 1.0.0-SNAPSHOT + war + + + com.h2database.wso2 + h2-database-engine + 1.2.140.wso2v3 + + + + + + maven-resources-plugin + + + copy-resources + generate-resources + + copy-resources + + + src/main/resources + + + resources + + build.properties + p2.inf + + + + + + + + + org.apache.maven.plugins + maven-dependency-plugin + + + unpack + package + + unpack + + + + + org.homeautomation + ${project-base-package}.analytics + 1.0.0-SNAPSHOT + zip + true + + ${project.build.directory}/maven-shared-archive-resources/carbonapps + + **/* + + + org.homeautomation + ${project-base-package}.ui + + ${project.version} + zip + true + + ${project.build.directory}/maven-shared-archive-resources/jaggeryapps + + **/* + + + + + + copy-jaxrs-manager-war + package + + copy + + + + + org.homeautomation + ${project-base-package}.manager + war + true + + + ${project.build.directory}/maven-shared-archive-resources/webapps/ + + firealarm_mgt.war + + + + + + copy-jaxrs-controller-war + package + + copy + + + + + org.homeautomation + ${project-base-package}.controller + war + true + + + ${project.build.directory}/maven-shared-archive-resources/webapps/ + + firealarm.war + + + + + + + + org.apache.maven.plugins + maven-antrun-plugin + ${maven-antrun-plugin.version} + + + create-firealarm-plugin-mgt-schema + package + + run + + + + + + + + + + + + + + + + + + + + + org.wso2.maven + carbon-p2-plugin + + + p2-feature-generation + package + + p2-feature-gen + + + ${project-base-package} + ../../../features/etc/feature.properties + + + + org.wso2.carbon.p2.category.type:server + + org.eclipse.equinox.p2.type.group:false + + + + + + org.homeautomation:${project-base-package}.plugin:1.0.0-SNAPSHOT + + + + + org.wso2.carbon.core.server:${carbon.kernel.version} + + + org.wso2.carbon.device.mgt.server:${carbon.device.mgt.version} + + + + + + + + + diff --git a/modules/samples/firealarm/feature/feature/src/main/resources/agent/dht_lib.lua b/modules/samples/firealarm/feature/feature/src/main/resources/agent/dht_lib.lua new file mode 100644 index 00000000..643cd05d --- /dev/null +++ b/modules/samples/firealarm/feature/feature/src/main/resources/agent/dht_lib.lua @@ -0,0 +1,65 @@ +local dht_lib = {} + +local humidity +local temperature + +local bitStream = {} + +function dht_lib.read(pin) + for j = 1, 40, 1 do + bitStream[j]=0 + end + bitlength=0 + + gpio.mode(pin, gpio.OUTPUT) + gpio.write(pin, gpio.LOW) + tmr.delay(20000) + + gpio_read=gpio.read + gpio_write=gpio.write + + gpio.mode(pin, gpio.INPUT) + + while (gpio_read(pin)==0 ) do end + + c=0 + while (gpio_read(pin)==1 and c<100) do c=c+1 end + + while (gpio_read(pin)==0 ) do end + + c=0 + while (gpio_read(pin)==1 and c<100) do c=c+1 end + + for j = 1, 40, 1 do + while (gpio_read(pin)==1 and bitlength<10 ) do + bitlength=bitlength+1 + end + bitStream[j]=bitlength + bitlength=0 + while (gpio_read(pin)==0) do end + end + + humidity = 0 + temperature = 0 + + for i = 1, 8, 1 do + if (bitStream[i+0] > 2) then + humidity = humidity+2^(8-i) + end + end + for i = 1, 8, 1 do + if (bitStream[i+16] > 2) then + temperature = temperature+2^(8-i) + end + end +end + +function dht_lib.getTemperature() + return temperature +end + +function dht_lib.getHumidity() + return humidity +end + +return dht_lib diff --git a/modules/samples/firealarm/feature/feature/src/main/resources/agent/init.lua b/modules/samples/firealarm/feature/feature/src/main/resources/agent/init.lua new file mode 100644 index 00000000..31ece4ba --- /dev/null +++ b/modules/samples/firealarm/feature/feature/src/main/resources/agent/init.lua @@ -0,0 +1,4 @@ +tmr.alarm(0,1000,0,function() + dofile("wifi-connect.lua"); + dofile("read-sensor.lua"); +end) diff --git a/modules/samples/firealarm/feature/feature/src/main/resources/agent/read-sensor.lua b/modules/samples/firealarm/feature/feature/src/main/resources/agent/read-sensor.lua new file mode 100644 index 00000000..99727b9e --- /dev/null +++ b/modules/samples/firealarm/feature/feature/src/main/resources/agent/read-sensor.lua @@ -0,0 +1,74 @@ +DHT= require("dht_lib") + +dht_data = 2 +buzzer = 1 +gpio.mode(buzzer, gpio.OUTPUT) +client_connected = false +m = mqtt.Client("ESP8266-"..node.chipid(), 120, "", "") + +tmr.alarm(0,10000,1,function() + DHT.read(dht_data) + + t = DHT.getTemperature() + h = DHT.getHumidity() + + if t == nil then + print("Error reading from DHTxx") + else + if (client_connected) then + m:publish("wso2/iot/${DEVICE_OWNER}/firealarm/${DEVICE_ID}/publisher", "Temperature:"..t..":Humidity:"..h, 0, 0, function(client) + print("Published> Temperature: "..t.."C Humidity: "..h.."%") + end) + else + connectMQTTClient() + end + end +end) + +function connectMQTTClient() + ip = wifi.sta.getip() + if ip == nil then + print("Waiting for network") + else + print("Client IP: "..ip) + print("Trying to connect MQTT client") + m:connect("${SERVER_IP}", 1883, 0, function(client) + client_connected = true + print("MQTT client connected") + subscribeToMQTTQueue() + end) + end +end + +function subscribeToMQTTQueue() + m:subscribe("wso2/iot/${DEVICE_OWNER}/firealarm/${DEVICE_ID}/subscriber", 0, function(client, topic, message) + print("Subscribed to MQTT Queue") + end) + m:on("message", function(client, topic, message) + print("MQTT message received") + print(message) + buzz(message == "buzzer:ON") + end) + m:on("offline", function(client) + print("Disconnected") + client_connected = false + end) +end + +function buzz(status) + buzzerOn=true + if (status) then + tmr.alarm(1,500,1,function() + if buzzerOn then + buzzerOn=false + gpio.write(buzzer, gpio.HIGH) + else + buzzerOn=true + gpio.write(buzzer, gpio.LOW) + end + end) + else + tmr.stop(1) + gpio.write(buzzer, gpio.LOW) + end +end \ No newline at end of file diff --git a/modules/samples/firealarm/feature/feature/src/main/resources/agent/sketch.properties b/modules/samples/firealarm/feature/feature/src/main/resources/agent/sketch.properties new file mode 100644 index 00000000..5485808b --- /dev/null +++ b/modules/samples/firealarm/feature/feature/src/main/resources/agent/sketch.properties @@ -0,0 +1,16 @@ +#/* +# * Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. +# * WSO2 Inc. licenses this file to you under the Apache License, +# * Version 2.0 (the "License"); you may not use this file except +# * in compliance with the License. +# * You may obtain a copy of the License at +# * http://www.apache.org/licenses/LICENSE-2.0 +# * Unless required by applicable law or agreed to in writing, +# * software distributed under the License is distributed on an +# * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# * KIND, either express or implied. See the License for the +# * specific language governing permissions and limitations +# * under the License. +# */ +templates=read-sensor.lua +zipfilename=firealarm.zip diff --git a/modules/samples/firealarm/feature/feature/src/main/resources/agent/wifi-connect.lua b/modules/samples/firealarm/feature/feature/src/main/resources/agent/wifi-connect.lua new file mode 100644 index 00000000..1c4498b9 --- /dev/null +++ b/modules/samples/firealarm/feature/feature/src/main/resources/agent/wifi-connect.lua @@ -0,0 +1,2 @@ +wifi.setmode(wifi.STATION) +wifi.sta.config("SSID","Password") \ No newline at end of file diff --git a/modules/samples/firealarm/feature/feature/src/main/resources/build.properties b/modules/samples/firealarm/feature/feature/src/main/resources/build.properties new file mode 100644 index 00000000..a7e289bc --- /dev/null +++ b/modules/samples/firealarm/feature/feature/src/main/resources/build.properties @@ -0,0 +1,18 @@ +# +custom = true diff --git a/modules/samples/firealarm/feature/feature/src/main/resources/configs/firealarm.json b/modules/samples/firealarm/feature/feature/src/main/resources/configs/firealarm.json new file mode 100644 index 00000000..b627d223 --- /dev/null +++ b/modules/samples/firealarm/feature/feature/src/main/resources/configs/firealarm.json @@ -0,0 +1,54 @@ +{ + "deviceType": { + "label": "Fire Alarm", + "category": "iot" + }, + "analyticStreams": [ + { + "name": "Temperature", + "table": "DEVICE_TEMPERATURE_SUMMARY", + "ui_unit": { + "name": "cdmf.unit.analytics.line-chart", + "data": [ + { + "column": { + "name": "TIME", + "label": "time", + "ui-mapping": "x-axis" + } + }, + { + "column": { + "name": "TEMPERATURE", + "label": "Temperature", + "ui-mapping": "y-axis" + } + } + ] + } + }, + { + "name": "Humidity", + "table": "DEVICE_HUMIDITY_SUMMARY", + "ui_unit": { + "name": "cdmf.unit.analytics.line-chart", + "data": [ + { + "column": { + "name": "TIME", + "label": "time", + "ui-mapping": "x-axis" + } + }, + { + "column": { + "name": "HUMIDITY", + "label": "Humidity", + "ui-mapping": "y-axis" + } + } + ] + } + } + ] +} \ No newline at end of file diff --git a/modules/samples/firealarm/feature/feature/src/main/resources/configs/firealarm.xml b/modules/samples/firealarm/feature/feature/src/main/resources/configs/firealarm.xml new file mode 100644 index 00000000..b505b3ff --- /dev/null +++ b/modules/samples/firealarm/feature/feature/src/main/resources/configs/firealarm.xml @@ -0,0 +1,25 @@ + + + + + + + jdbc/firealarmDM_DB + + diff --git a/modules/samples/firealarm/feature/feature/src/main/resources/datasources/firealarm-datasources.xml b/modules/samples/firealarm/feature/feature/src/main/resources/datasources/firealarm-datasources.xml new file mode 100644 index 00000000..7d219601 --- /dev/null +++ b/modules/samples/firealarm/feature/feature/src/main/resources/datasources/firealarm-datasources.xml @@ -0,0 +1,48 @@ + + + + + + + org.wso2.carbon.ndatasource.rdbms.RDBMSDataSourceReader + + + + firealarmDM_DB + The datasource used for the this device type + + jdbc/firealarmDM_DB + + + + jdbc:h2:repository/database/firealarmDM_DB;DB_CLOSE_ON_EXIT=FALSE + + wso2carbon + wso2carbon + org.h2.Driver + 50 + 60000 + true + SELECT 1 + 30000 + + + + + diff --git a/modules/samples/firealarm/feature/feature/src/main/resources/dbscripts/h2.sql b/modules/samples/firealarm/feature/feature/src/main/resources/dbscripts/h2.sql new file mode 100644 index 00000000..df4b2214 --- /dev/null +++ b/modules/samples/firealarm/feature/feature/src/main/resources/dbscripts/h2.sql @@ -0,0 +1,13 @@ + +-- ----------------------------------------------------- +-- Agent Database +-- ----------------------------------------------------- +CREATE TABLE IF NOT EXISTS `firealarm_DEVICE` ( + `firealarm_DEVICE_ID` VARCHAR(45) NOT NULL , + `DEVICE_NAME` VARCHAR(100) NULL DEFAULT NULL, + `ACCESS_TOKEN` VARCHAR(50) NOT NULL, + `REFRESH_TOKEN` VARCHAR(50) NOT NULL, + PRIMARY KEY (`firealarm_DEVICE_ID`) ); + + + diff --git a/modules/samples/firealarm/feature/feature/src/main/resources/dbscripts/mysql.sql b/modules/samples/firealarm/feature/feature/src/main/resources/dbscripts/mysql.sql new file mode 100644 index 00000000..344812ba --- /dev/null +++ b/modules/samples/firealarm/feature/feature/src/main/resources/dbscripts/mysql.sql @@ -0,0 +1,12 @@ + +CREATE TABLE IF NOT EXISTS `firealarm_DEVICE` ( + `firealarm_DEVICE_ID` VARCHAR(45) NOT NULL , + `DEVICE_NAME` VARCHAR(100) NULL DEFAULT NULL, + `ACCESS_TOKEN` VARCHAR(50) NOT NULL, + `REFRESH_TOKEN` VARCHAR(50) NOT NULL, + PRIMARY KEY (`firealarm_DEVICE_ID`) ) +ENGINE = InnoDB; + + + + diff --git a/modules/samples/firealarm/feature/feature/src/main/resources/p2.inf b/modules/samples/firealarm/feature/feature/src/main/resources/p2.inf new file mode 100644 index 00000000..f747e63a --- /dev/null +++ b/modules/samples/firealarm/feature/feature/src/main/resources/p2.inf @@ -0,0 +1,16 @@ +instructions.configure = \ +org.eclipse.equinox.p2.touchpoint.natives.mkdir(path:${installFolder}/../../conf/device-types/);\ +org.eclipse.equinox.p2.touchpoint.natives.copy(source:${installFolder}/../features/org.homeautomation.firealarm_${feature.version}/configs/,target:${installFolder}/../../conf/device-types/,overwrite:true);\ +org.eclipse.equinox.p2.touchpoint.natives.mkdir(path:${installFolder}/../../deployment/server/webapps/);\ +org.eclipse.equinox.p2.touchpoint.natives.copy(source:${installFolder}/../features/org.homeautomation.firealarm_${feature.version}/webapps/,target:${installFolder}/../../deployment/server/webapps/,overwrite:true);\ +org.eclipse.equinox.p2.touchpoint.natives.mkdir(path:${installFolder}/../../resources/sketches/);\ +org.eclipse.equinox.p2.touchpoint.natives.mkdir(path:${installFolder}/../../resources/sketches/firealarm/);\ +org.eclipse.equinox.p2.touchpoint.natives.copy(source:${installFolder}/../features/org.homeautomation.firealarm_${feature.version}/agent/,target:${installFolder}/../../resources/sketches/firealarm/,overwrite:true);\ +org.eclipse.equinox.p2.touchpoint.natives.copy(source:${installFolder}/../features/org.homeautomation.firealarm_${feature.version}/dbscripts/,target:${installFolder}/../../../dbscripts/cdm/plugins/firealarm,overwrite:true);\ +org.eclipse.equinox.p2.touchpoint.natives.copy(source:${installFolder}/../features/org.homeautomation.firealarm_${feature.version}/datasources/,target:${installFolder}/../../conf/datasources/,overwrite:true);\ +org.eclipse.equinox.p2.touchpoint.natives.mkdir(path:${installFolder}/../../deployment/server/jaggeryapps/);\ +org.eclipse.equinox.p2.touchpoint.natives.copy(source:${installFolder}/../features/org.homeautomation.firealarm_${feature.version}/jaggeryapps/,target:${installFolder}/../../deployment/server/jaggeryapps/,overwrite:true);\ +org.eclipse.equinox.p2.touchpoint.natives.mkdir(path:${installFolder}/../../database/);\ +org.eclipse.equinox.p2.touchpoint.natives.copy(source:${installFolder}/../features/org.homeautomation.firealarm_${feature.version}/database/,target:${installFolder}/../../database/,overwrite:true);\ +org.eclipse.equinox.p2.touchpoint.natives.mkdir(path:${installFolder}/../../deployment/server/carbonapps/);\ +org.eclipse.equinox.p2.touchpoint.natives.copy(source:${installFolder}/../features/org.homeautomation.firealarm_${feature.version}/carbonapps/,target:${installFolder}/../../deployment/server/carbonapps/,overwrite:true);\ diff --git a/modules/samples/firealarm/feature/pom.xml b/modules/samples/firealarm/feature/pom.xml new file mode 100644 index 00000000..86265530 --- /dev/null +++ b/modules/samples/firealarm/feature/pom.xml @@ -0,0 +1,37 @@ + + + + + + + org.homeautomation + firealarm + 1.0.0-SNAPSHOT + ../pom.xml + + firealarm-feature + 4.0.0 + pom + 1.0.0-SNAPSHOT + + feature + + \ No newline at end of file diff --git a/modules/samples/firealarm/pom.xml b/modules/samples/firealarm/pom.xml new file mode 100644 index 00000000..4d5c36dd --- /dev/null +++ b/modules/samples/firealarm/pom.xml @@ -0,0 +1,257 @@ + + + + + + + org.wso2 + wso2 + 1 + + org.homeautomation + firealarm + 1.0.0-SNAPSHOT + pom + 4.0.0 + http://wso2.com + + component + feature + + + + + org.eclipse.osgi + org.eclipse.osgi + ${eclipse.osgi.version} + provided + + + org.eclipse.equinox + org.eclipse.equinox.common + ${eclipse.equinox.common.version} + provided + + + org.testng + testng + ${testng.version} + + + junit + junit + + + org.beanshell + bsh + + + org.yaml + snakeyaml + + + provided + + + org.eclipse.osgi + org.eclipse.osgi.services + 3.3.100.v20120522-1822 + provided + + + org.wso2.carbon + org.wso2.carbon.logging + ${carbon.kernel.version} + + + org.apache.log4j.wso2 + log4j + + + commons-logging + commons-logging + + + org.wso2.carbon + org.wso2.carbon.bootstrap + + + provided + + + + org.apache.cxf + cxf-rt-frontend-jaxws + ${cxf.version} + provided + + + org.apache.cxf + cxf-rt-frontend-jaxrs + ${cxf.version} + provided + + + org.apache.cxf + cxf-rt-transports-http + ${cxf.version} + provided + + + org.eclipse.paho + org.eclipse.paho.client.mqttv3 + ${paho.mqtt.version} + provided + + + org.codehaus.jackson + jackson-core-asl + ${jackson.version} + + + org.codehaus.jackson + jackson-jaxrs + ${jackson.version} + + + javax + javaee-web-api + 6.0 + provided + + + javax.ws.rs + jsr311-api + ${javax.ws.rs.version} + provided + + + org.apache.httpcomponents + httpasyncclient + 4.1 + provided + + + + + + wso2.releases + WSO2 internal Repository + http://maven.wso2.org/nexus/content/repositories/releases/ + + true + daily + ignore + + + + wso2.snapshots + Apache Snapshot Repository + http://maven.wso2.org/nexus/content/repositories/snapshots/ + + true + daily + + + false + + + + wso2-nexus + WSO2 internal Repository + http://maven.wso2.org/nexus/content/groups/wso2-public/ + + true + daily + ignore + + + + + + wso2-nexus + WSO2 internal Repository + http://maven.wso2.org/nexus/content/groups/wso2-public/ + + true + daily + ignore + + + + wso2.releases + WSO2 internal Repository + http://maven.wso2.org/nexus/content/repositories/releases/ + + true + daily + ignore + + + + wso2.snapshots + WSO2 Snapshot Repository + http://maven.wso2.org/nexus/content/repositories/snapshots/ + + true + daily + + + false + + + + gcm-server-repository + GCM Server repository - GitHub + https://github.com/slorber/gcm-server-repository/raw/master/releases/ + + + + 4.4.3 + 1.1.0-SNAPSHOT + 1.1.0.SNAPSHOT + 1.0.2 + 3.0.0.wso2v1 + 3.8.1.v20120830-144521 + 2.0.4-SNAPSHOT + 2.0.4.SNAPSHOT + 1.1.1 + 2.4 + + 3.0.4.wso2v1 + 3.0.4.wso2v1 + 2.6.1 + 1.9.0 + 3.1.0.wso2v2 + 3.6.100.v20120522-1841 + 1.7 + 1.7 + org.homeautomation.firealarm + 3.8.1 + 1.4.0 + 2.4.1 + 2.3.2 + 2.6 + 1.8 + 1.7.2 + 2.5.5 + + \ No newline at end of file diff --git a/modules/samples/installer/device-deployer.xml b/modules/samples/installer/device-deployer.xml index efb3575e..4a437faa 100644 --- a/modules/samples/installer/device-deployer.xml +++ b/modules/samples/installer/device-deployer.xml @@ -35,6 +35,7 @@ samples/connectedcup samples/currentsensor + samples/firealarm @@ -64,6 +65,9 @@ org.homeautomation:org.homeautomation.currentsensor.feature:2.0.4-SNAPSHOT + + org.homeautomation:org.homeautomation.firealarm.feature:1.0.0-SNAPSHOT + @@ -97,6 +101,10 @@ org.homeautomation.currentsensor.feature.group 2.0.4-SNAPSHOT + + org.homeautomation.firealarm.feature.group + 1.0.0-SNAPSHOT +