diff --git a/components/device-mgt-iot-arduino/org.wso2.carbon.device.mgt.iot.arduino.service.impl/src/main/java/org/wso2/carbon/device/mgt/iot/arduino/service/ArduinoService.java b/components/device-mgt-iot-arduino/org.wso2.carbon.device.mgt.iot.arduino.service.impl/src/main/java/org/wso2/carbon/device/mgt/iot/arduino/service/ArduinoService.java index 03acf76276..a0bc3be694 100644 --- a/components/device-mgt-iot-arduino/org.wso2.carbon.device.mgt.iot.arduino.service.impl/src/main/java/org/wso2/carbon/device/mgt/iot/arduino/service/ArduinoService.java +++ b/components/device-mgt-iot-arduino/org.wso2.carbon.device.mgt.iot.arduino.service.impl/src/main/java/org/wso2/carbon/device/mgt/iot/arduino/service/ArduinoService.java @@ -39,6 +39,7 @@ import org.wso2.carbon.device.mgt.iot.sensormgt.SensorDataManager; import org.wso2.carbon.device.mgt.iot.util.ZipArchive; import org.wso2.carbon.device.mgt.iot.util.ZipUtil; +import javax.jws.WebService; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.ws.rs.Consumes; @@ -459,8 +460,8 @@ public class ArduinoService { String deviceHttpEndpoint = deviceIP + ":" + devicePort; deviceToIpMap.put(deviceId, deviceHttpEndpoint); - result = "Device-IP Registered"; + result = "Device-IP Registered"; response.setStatus(Response.Status.OK.getStatusCode()); if (log.isDebugEnabled()) { @@ -689,7 +690,5 @@ public class ArduinoService { String errorMsg = "Validation attempt for deviceId [" + deviceId + "] of owner [" + owner + "] failed.\n"; log.error(errorMsg + Response.Status.INTERNAL_SERVER_ERROR.getReasonPhrase() + "\n" + e.getErrorMessage()); } - - } } diff --git a/components/device-mgt-iot-arduino/org.wso2.carbon.device.mgt.iot.arduino.service.impl/src/main/webapp/WEB-INF/web.xml b/components/device-mgt-iot-arduino/org.wso2.carbon.device.mgt.iot.arduino.service.impl/src/main/webapp/WEB-INF/web.xml index 2175bbda26..87f9c84601 100644 --- a/components/device-mgt-iot-arduino/org.wso2.carbon.device.mgt.iot.arduino.service.impl/src/main/webapp/WEB-INF/web.xml +++ b/components/device-mgt-iot-arduino/org.wso2.carbon.device.mgt.iot.arduino.service.impl/src/main/webapp/WEB-INF/web.xml @@ -19,5 +19,52 @@ /* + + isAdminService + false + + + doAuthentication + false + + + + + managed-api-enabled + true + + + managed-api-owner + admin + + + managed-api-name + arduino + + + managed-api-endpoint + http://localhost:9763/arduino + + + managed-api-version + 1.0.0 + + + managed-api-context + /arduino + + + managed-api-context-template + /arduino/{version} + + + managed-api-application + arduino + + + managed-api-isSecured + true + + diff --git a/components/device-mgt-iot-raspberrypi/org.wso2.carbon.device.mgt.iot.raspberrypi.plugin.impl/src/main/java/org/wso2/carbon/device/mgt/iot/raspberrypi/plugin/constants/RaspberrypiConstants.java b/components/device-mgt-iot-raspberrypi/org.wso2.carbon.device.mgt.iot.raspberrypi.plugin.impl/src/main/java/org/wso2/carbon/device/mgt/iot/raspberrypi/plugin/constants/RaspberrypiConstants.java index 8a8841d0a1..1c419f0b5c 100644 --- a/components/device-mgt-iot-raspberrypi/org.wso2.carbon.device.mgt.iot.raspberrypi.plugin.impl/src/main/java/org/wso2/carbon/device/mgt/iot/raspberrypi/plugin/constants/RaspberrypiConstants.java +++ b/components/device-mgt-iot-raspberrypi/org.wso2.carbon.device.mgt.iot.raspberrypi.plugin.impl/src/main/java/org/wso2/carbon/device/mgt/iot/raspberrypi/plugin/constants/RaspberrypiConstants.java @@ -23,5 +23,13 @@ public class RaspberrypiConstants { public final static String DEVICE_TYPE = "raspberrypi"; public final static String DEVICE_PLUGIN_DEVICE_NAME = "DEVICE_NAME"; public final static String DEVICE_PLUGIN_DEVICE_ID = "RASPBERRYPI_DEVICE_ID"; + public final static String STATE_ON = "ON"; + public final static String STATE_OFF = "OFF"; + + public static final String URL_PREFIX = "http://"; + public static final String BULB_CONTEXT = "/BULB/"; + public static final String TEMPERATURE_CONTEXT = "/TEMPERATURE/"; + + public static final String SENSOR_TEMPERATURE = "temperature"; } diff --git a/components/device-mgt-iot-raspberrypi/org.wso2.carbon.device.mgt.iot.raspberrypi.service.impl/pom.xml b/components/device-mgt-iot-raspberrypi/org.wso2.carbon.device.mgt.iot.raspberrypi.service.impl/pom.xml new file mode 100644 index 0000000000..146e472712 --- /dev/null +++ b/components/device-mgt-iot-raspberrypi/org.wso2.carbon.device.mgt.iot.raspberrypi.service.impl/pom.xml @@ -0,0 +1,149 @@ + + + + + + device-mgt-iot-raspberrypi + org.wso2.carbon.devicemgt-plugins + 1.9.2-SNAPSHOT + ../pom.xml + + + + 4.0.0 + org.wso2.carbon.device.mgt.iot.raspberrypi.service.impl + 1.9.2-SNAPSHOT + war + WSO2 Carbon - IoT Server RaspberryPi API + WSO2 Carbon - RaspberryPi Service API Implementation + http://wso2.org + + + + + org.wso2.carbon.devicemgt + org.wso2.carbon.device.mgt.common + provided + + + org.wso2.carbon.devicemgt + org.wso2.carbon.device.mgt.core + provided + + + org.apache.axis2.wso2 + axis2-client + + + + + + + org.apache.cxf + cxf-rt-frontend-jaxws + provided + + + org.apache.cxf + cxf-rt-frontend-jaxrs + provided + + + org.apache.cxf + cxf-rt-transports-http + provided + + + + + org.eclipse.paho + mqtt-client + provided + + + + + org.apache.httpcomponents + httpasyncclient + 4.1 + provided + + + org.wso2.carbon.devicemgt-plugins + org.wso2.carbon.device.mgt.iot + provided + + + org.wso2.carbon.devicemgt-plugins + org.wso2.carbon.device.mgt.iot.raspberrypi.plugin.impl + provided + + + + + org.codehaus.jackson + jackson-core-asl + + + org.codehaus.jackson + jackson-jaxrs + + + javax + javaee-web-api + provided + + + javax.ws.rs + jsr311-api + provided + + + + org.wso2.carbon.devicemgt + org.wso2.carbon.device.mgt.analytics + provided + + + + + + + + + + maven-compiler-plugin + + UTF-8 + ${wso2.maven.compiler.source} + ${wso2.maven.compiler.target} + + + + maven-war-plugin + + raspberrypi + + + + + + \ No newline at end of file diff --git a/components/device-mgt-iot-raspberrypi/org.wso2.carbon.device.mgt.iot.raspberrypi.service.impl/src/main/java/org/wso2/carbon/device/mgt/iot/raspberrypi/service/RaspberryPiService.java b/components/device-mgt-iot-raspberrypi/org.wso2.carbon.device.mgt.iot.raspberrypi.service.impl/src/main/java/org/wso2/carbon/device/mgt/iot/raspberrypi/service/RaspberryPiService.java new file mode 100644 index 0000000000..f4805d274a --- /dev/null +++ b/components/device-mgt-iot-raspberrypi/org.wso2.carbon.device.mgt.iot.raspberrypi.service.impl/src/main/java/org/wso2/carbon/device/mgt/iot/raspberrypi/service/RaspberryPiService.java @@ -0,0 +1,624 @@ +/* + * Copyright (c) 2015, 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.wso2.carbon.device.mgt.iot.raspberrypi.service; + +import org.apache.commons.io.FileUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +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.DeviceManagement; +import org.wso2.carbon.device.mgt.iot.DeviceValidator; +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.controlqueue.xmpp.XmppAccount; +import org.wso2.carbon.device.mgt.iot.controlqueue.xmpp.XmppConfig; +import org.wso2.carbon.device.mgt.iot.controlqueue.xmpp.XmppServerClient; +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.raspberrypi.plugin.constants.RaspberrypiConstants; +import org.wso2.carbon.device.mgt.iot.raspberrypi.service.dto.DeviceJSON; +import org.wso2.carbon.device.mgt.iot.raspberrypi.service.transport.RaspberryPiMQTTSubscriber; +import org.wso2.carbon.device.mgt.iot.raspberrypi.service.util.RaspberrypiServiceUtils; +import org.wso2.carbon.device.mgt.iot.sensormgt.SensorDataManager; +import org.wso2.carbon.device.mgt.iot.sensormgt.SensorRecord; +import org.wso2.carbon.device.mgt.iot.util.ZipArchive; +import org.wso2.carbon.device.mgt.iot.util.ZipUtil; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.ws.rs.Consumes; +import javax.ws.rs.DELETE; +import javax.ws.rs.GET; +import javax.ws.rs.HeaderParam; +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.Calendar; +import java.util.Date; +import java.util.List; +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; + +@Path("/RaspberryPiDeviceManager") +public class RaspberryPiService { + + private static Log log = LogFactory.getLog(RaspberryPiService.class); + + //TODO; replace this tenant domain + private static final String SUPER_TENANT = "carbon.super"; + + @Context //injected response proxy supporting multiple thread + private HttpServletResponse response; + + public static final String HTTP_PROTOCOL = "HTTP"; + public static final String MQTT_PROTOCOL = "MQTT"; + + private ConcurrentHashMap deviceToIpMap = new ConcurrentHashMap<>(); + private RaspberryPiMQTTSubscriber raspberryPiMQTTSubscriber; + + /** + * @param raspberryPiMQTTSubscriber + */ + public void setRaspberryPiMQTTSubscriber( + final RaspberryPiMQTTSubscriber raspberryPiMQTTSubscriber) { + this.raspberryPiMQTTSubscriber = raspberryPiMQTTSubscriber; + + Runnable xmppStarter = new Runnable() { + @Override + public void run() { + raspberryPiMQTTSubscriber.initConnector(); + raspberryPiMQTTSubscriber.connectAndSubscribe(); + } + }; + + Thread xmppStarterThread = new Thread(xmppStarter); + xmppStarterThread.setDaemon(true); + xmppStarterThread.start(); + } + + /** + * @return + */ + public RaspberryPiMQTTSubscriber getRaspberryPiMQTTSubscriber() { + return raspberryPiMQTTSubscriber; + } + + /* --------------------------------------------------------------------------------------- + Device management specific APIs + Also contains utility methods required for the execution of these APIs + --------------------------------------------------------------------------------------- */ + @Path("manager/device/register") + @PUT + public boolean register(@QueryParam("deviceId") String deviceId, + @QueryParam("name") String name, @QueryParam("owner") String owner) { + + DeviceManagement deviceManagement = new DeviceManagement(SUPER_TENANT); + + DeviceIdentifier deviceIdentifier = new DeviceIdentifier(); + deviceIdentifier.setId(deviceId); + deviceIdentifier.setType(RaspberrypiConstants.DEVICE_TYPE); + try { + if (deviceManagement.getDeviceManagementService().isEnrolled(deviceIdentifier)) { + response.setStatus(Response.Status.CONFLICT.getStatusCode()); + return false; + } + + 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(RaspberrypiConstants.DEVICE_TYPE); + enrolmentInfo.setOwner(owner); + device.setEnrolmentInfo(enrolmentInfo); + boolean added = deviceManagement.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()); + return false; + } finally { + deviceManagement.endTenantFlow(); + } + } + + @Path("manager/device/remove/{device_id}") + @DELETE + public void removeDevice(@PathParam("device_id") String deviceId, + @Context HttpServletResponse response) { + + DeviceManagement deviceManagement = new DeviceManagement(SUPER_TENANT); + DeviceIdentifier deviceIdentifier = new DeviceIdentifier(); + deviceIdentifier.setId(deviceId); + deviceIdentifier.setType(RaspberrypiConstants.DEVICE_TYPE); + try { + boolean removed = deviceManagement.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()); + } finally { + deviceManagement.endTenantFlow(); + } + + + } + + @Path("manager/device/update/{device_id}") + @POST + public boolean updateDevice(@PathParam("device_id") String deviceId, + @QueryParam("name") String name, + @Context HttpServletResponse response) { + + DeviceManagement deviceManagement = new DeviceManagement(SUPER_TENANT); + + DeviceIdentifier deviceIdentifier = new DeviceIdentifier(); + deviceIdentifier.setId(deviceId); + deviceIdentifier.setType(RaspberrypiConstants.DEVICE_TYPE); + try { + Device device = deviceManagement.getDeviceManagementService().getDevice(deviceIdentifier); + device.setDeviceIdentifier(deviceId); + + // device.setDeviceTypeId(deviceTypeId); + device.getEnrolmentInfo().setDateOfLastUpdate(new Date().getTime()); + + device.setName(name); + device.setType(RaspberrypiConstants.DEVICE_TYPE); + + boolean updated = deviceManagement.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; + } finally { + deviceManagement.endTenantFlow(); + } + + } + + @Path("manager/device/{device_id}") + @GET + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + public Device getDevice(@PathParam("device_id") String deviceId) { + + DeviceManagement deviceManagement = new DeviceManagement(SUPER_TENANT); + DeviceIdentifier deviceIdentifier = new DeviceIdentifier(); + deviceIdentifier.setId(deviceId); + deviceIdentifier.setType(RaspberrypiConstants.DEVICE_TYPE); + + try { + return deviceManagement.getDeviceManagementService().getDevice(deviceIdentifier); + } catch (DeviceManagementException ex) { + log.error("Error occurred while retrieving device with Id " + deviceId + "\n" + ex); + return null; + } finally { + deviceManagement.endTenantFlow(); + } + + } + + @Path("manager/devices/{username}") + @GET + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + public Device[] getRaspberrypiDevices(@PathParam("username") String username) { + + DeviceManagement deviceManagement = new DeviceManagement(SUPER_TENANT); + + try { + List userDevices = deviceManagement.getDeviceManagementService().getDevicesOfUser(username); + ArrayList usersRaspberrypiDevices = new ArrayList<>(); + for (Device device : userDevices) { + if (device.getType().equals(RaspberrypiConstants.DEVICE_TYPE) && + device.getEnrolmentInfo().getStatus().equals(EnrolmentInfo.Status.ACTIVE)) { + usersRaspberrypiDevices.add(device); + } + } + return usersRaspberrypiDevices.toArray(new Device[]{}); + + } catch (DeviceManagementException e) { + response.setStatus(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode()); + return null; + } finally { + deviceManagement.endTenantFlow(); + } + } + + @Path("manager/device/{sketch_type}/download") + @GET + @Produces(MediaType.APPLICATION_JSON) + public Response downloadSketch(@QueryParam("owner") String owner, + @QueryParam("deviceName") String customDeviceName, + @PathParam("sketch_type") String + sketchType) { + + try { + ZipArchive zipFile = createDownloadFile(owner, customDeviceName, 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(); + } + } + + + @Path("manager/device/{sketch_type}/generate_link") + @GET + public Response generateSketchLink(@QueryParam("owner") String owner, + @QueryParam("deviceName") String customDeviceName, + @PathParam("sketch_type") String sketchType) { + + try { + ZipArchive zipFile = createDownloadFile(owner, customDeviceName, sketchType); + Response.ResponseBuilder rb = Response.ok(zipFile.getDeviceId()); + return rb.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(); + } + } + + + private ZipArchive createDownloadFile(String owner, String customDeviceName, 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(); + + TokenClient accessTokenClient = new TokenClient(RaspberrypiConstants.DEVICE_TYPE); + AccessTokenInfo accessTokenInfo = accessTokenClient.getAccessToken(owner, deviceId); + + //create token + String accessToken = accessTokenInfo.getAccess_token(); + String refreshToken = accessTokenInfo.getRefresh_token(); + //adding registering data + + XmppAccount newXmppAccount = new XmppAccount(); + newXmppAccount.setAccountName(owner + "_" + deviceId); + newXmppAccount.setUsername(deviceId); + newXmppAccount.setPassword(accessToken); + newXmppAccount.setEmail(deviceId + "@wso2.com"); + + XmppServerClient xmppServerClient = new XmppServerClient(); + xmppServerClient.initControlQueue(); + boolean status; + + if (XmppConfig.getInstance().isEnabled()) { + status = xmppServerClient.createXMPPAccount(newXmppAccount); + if (!status) { + String msg = + "XMPP Account was not created for device - " + deviceId + " of owner - " + owner + + ".XMPP might have been disabled in org.wso2.carbon.device.mgt.iot.common.config" + + ".server.configs"; + log.warn(msg); + throw new DeviceManagementException(msg); + } + } + + //Register the device with CDMF + String deviceName = customDeviceName + "_" + deviceId; + status = register(deviceId, deviceName, owner); + + 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.downloadSketch(owner, SUPER_TENANT, sketchType, deviceId, deviceName, accessToken, + refreshToken); + zipFile.setDeviceId(deviceId); + return zipFile; + } + + 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); + } + + /* --------------------------------------------------------------------------------------- + Device specific APIs - Control APIs + Data-Publishing APIs + --------------------------------------------------------------------------------------- */ + + @Path("controller/register/{owner}/{deviceId}/{ip}/{port}") + @POST + public String registerDeviceIP(@PathParam("owner") String owner, + @PathParam("deviceId") String deviceId, + @PathParam("ip") String deviceIP, + @PathParam("port") String devicePort, + @Context HttpServletResponse response, + @Context HttpServletRequest request) { + + //TODO:: Need to get IP from the request itself + String result; + + if (log.isDebugEnabled()) { + log.debug("Got register call from IP: " + deviceIP + " for Device ID: " + deviceId + " of owner: " + owner); + } + + String deviceHttpEndpoint = deviceIP + ":" + devicePort; + deviceToIpMap.put(deviceId, deviceHttpEndpoint); + + result = "Device-IP Registered"; + response.setStatus(Response.Status.OK.getStatusCode()); + + if (log.isDebugEnabled()) { + log.debug(result); + } + + return result; + } + + + /** + * @param owner + * @param deviceId + * @param protocol + * @param state + * @param response + */ + @Path("controller/bulb/{state}") + @POST + public void switchBulb(@HeaderParam("owner") String owner, + @HeaderParam("deviceId") String deviceId, + @HeaderParam("protocol") String protocol, + @PathParam("state") String state, + @Context HttpServletResponse response) { + + try { + DeviceValidator deviceValidator = new DeviceValidator(); + if (!deviceValidator.isExist(owner, SUPER_TENANT, new DeviceIdentifier(deviceId, + RaspberrypiConstants.DEVICE_TYPE))) { + response.setStatus(Response.Status.UNAUTHORIZED.getStatusCode()); + return; + } + } catch (DeviceManagementException e) { + log.error("DeviceValidation Failed for deviceId: " + deviceId + " of user: " + owner); + response.setStatus(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode()); + return; + } + + String switchToState = state.toUpperCase(); + + if (!switchToState.equals(RaspberrypiConstants.STATE_ON) && !switchToState.equals( + RaspberrypiConstants.STATE_OFF)) { + log.error("The requested state change shoud be either - 'ON' or 'OFF'"); + response.setStatus(Response.Status.BAD_REQUEST.getStatusCode()); + return; + } + + String protocolString = protocol.toUpperCase(); + String callUrlPattern = RaspberrypiConstants.BULB_CONTEXT + switchToState; + + if (log.isDebugEnabled()) { + log.debug("Sending request to switch-bulb of device [" + deviceId + "] via " + protocolString); + } + + try { + switch (protocolString) { + case HTTP_PROTOCOL: + String deviceHTTPEndpoint = deviceToIpMap.get(deviceId); + if (deviceHTTPEndpoint == null) { + response.setStatus(Response.Status.PRECONDITION_FAILED.getStatusCode()); + return; + } + + RaspberrypiServiceUtils.sendCommandViaHTTP(deviceHTTPEndpoint, callUrlPattern, true); + break; + + case MQTT_PROTOCOL: + String mqttMessage = RaspberrypiConstants.BULB_CONTEXT.replace("/", ""); + RaspberrypiServiceUtils.sendCommandViaMQTT(owner, deviceId, mqttMessage, switchToState); + break; + + default: + response.setStatus(Response.Status.NOT_ACCEPTABLE.getStatusCode()); + return; + } + } catch (DeviceManagementException e) { + log.error("Failed to send switch-bulb request to device [" + deviceId + "] via " + protocolString); + response.setStatus(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode()); + return; + } + + response.setStatus(Response.Status.OK.getStatusCode()); + } + + + /** + * @param owner + * @param deviceId + * @param protocol + * @param response + * @return + */ + @Path("controller/readtemperature") + @GET + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + public SensorRecord requestTemperature(@HeaderParam("owner") String owner, + @HeaderParam("deviceId") String deviceId, + @HeaderParam("protocol") String protocol, + @Context HttpServletResponse response) { + SensorRecord sensorRecord = null; + + DeviceValidator deviceValidator = new DeviceValidator(); + try { + if (!deviceValidator.isExist(owner, SUPER_TENANT, new DeviceIdentifier(deviceId, + RaspberrypiConstants.DEVICE_TYPE))) { + response.setStatus(Response.Status.UNAUTHORIZED.getStatusCode()); + } + } catch (DeviceManagementException e) { + response.setStatus(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode()); + } + + String protocolString = protocol.toUpperCase(); + + if (log.isDebugEnabled()) { + log.debug( + "Sending request to read raspberrypi-temperature of device [" + deviceId + "] via " + + protocolString); + } + + try { + switch (protocolString) { + case HTTP_PROTOCOL: + String deviceHTTPEndpoint = deviceToIpMap.get(deviceId); + if (deviceHTTPEndpoint == null) { + response.setStatus(Response.Status.PRECONDITION_FAILED.getStatusCode()); + } + + String temperatureValue = RaspberrypiServiceUtils.sendCommandViaHTTP(deviceHTTPEndpoint, + RaspberrypiConstants + .TEMPERATURE_CONTEXT, + false); + SensorDataManager.getInstance().setSensorRecord(deviceId, RaspberrypiConstants.SENSOR_TEMPERATURE, + temperatureValue, + Calendar.getInstance().getTimeInMillis()); + break; + + case MQTT_PROTOCOL: + String mqttMessage = RaspberrypiConstants.BULB_CONTEXT.replace("/", ""); + RaspberrypiServiceUtils.sendCommandViaMQTT(owner, deviceId, mqttMessage, ""); + break; + default: + response.setStatus(Response.Status.NOT_ACCEPTABLE.getStatusCode()); + } + sensorRecord = SensorDataManager.getInstance().getSensorRecord(deviceId, + RaspberrypiConstants.SENSOR_TEMPERATURE); + } catch (DeviceManagementException | DeviceControllerException e) { + response.setStatus(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode()); + } + + response.setStatus(Response.Status.OK.getStatusCode()); + return sensorRecord; + } + + /** + * @param dataMsg + * @param response + */ + @Path("controller/push_temperature") + @POST + @Consumes(MediaType.APPLICATION_JSON) + public void pushTemperatureData(final DeviceJSON dataMsg, + @Context HttpServletResponse response, + @Context HttpServletRequest request) { + String owner = dataMsg.owner; + String deviceId = dataMsg.deviceId; + String deviceIp = dataMsg.reply; //TODO:: Get IP from request + float temperature = dataMsg.value; + + try { + DeviceValidator deviceValidator = new DeviceValidator(); + if (!deviceValidator.isExist(owner, SUPER_TENANT, new DeviceIdentifier(deviceId, + RaspberrypiConstants.DEVICE_TYPE))) { + response.setStatus(Response.Status.UNAUTHORIZED.getStatusCode()); + log.warn("Temperature data Received from unregistered raspberrypi device [" + deviceId + + "] for owner [" + owner + "]"); + return; + } + + String registeredIp = deviceToIpMap.get(deviceId); + + if (registeredIp == null) { + log.warn("Unregistered IP: Temperature Data Received from an un-registered IP " + deviceIp + + " for device ID - " + deviceId); + response.setStatus(Response.Status.PRECONDITION_FAILED.getStatusCode()); + return; + } else if (!registeredIp.equals(deviceIp)) { + log.warn("Conflicting IP: Received IP is " + deviceIp + ". Device with ID " + deviceId + + " is already registered under some other IP. Re-registration required"); + response.setStatus(Response.Status.CONFLICT.getStatusCode()); + return; + } + + if (log.isDebugEnabled()) { + log.debug("Received Pin Data Value: " + temperature + " degrees C"); + } + SensorDataManager.getInstance().setSensorRecord(deviceId, RaspberrypiConstants.SENSOR_TEMPERATURE, + String.valueOf(temperature), + Calendar.getInstance().getTimeInMillis()); + + if (!RaspberrypiServiceUtils.publishToDAS(dataMsg.owner, dataMsg.deviceId, dataMsg.value)) { + response.setStatus(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode()); + log.warn("An error occured whilst trying to publish temperature data of raspberrypi with ID [" + + deviceId + "] of owner [" + owner + "]"); + } + + } catch (DeviceManagementException e) { + String errorMsg = "Validation attempt for deviceId [" + deviceId + "] of owner [" + owner + "] failed.\n"; + log.error(errorMsg + Response.Status.INTERNAL_SERVER_ERROR.getReasonPhrase() + "\n" + e.getErrorMessage()); + } + } + +} diff --git a/components/device-mgt-iot-raspberrypi/org.wso2.carbon.device.mgt.iot.raspberrypi.service.impl/src/main/java/org/wso2/carbon/device/mgt/iot/raspberrypi/service/dto/DeviceJSON.java b/components/device-mgt-iot-raspberrypi/org.wso2.carbon.device.mgt.iot.raspberrypi.service.impl/src/main/java/org/wso2/carbon/device/mgt/iot/raspberrypi/service/dto/DeviceJSON.java new file mode 100644 index 0000000000..c8695d707d --- /dev/null +++ b/components/device-mgt-iot-raspberrypi/org.wso2.carbon.device.mgt.iot.raspberrypi.service.impl/src/main/java/org/wso2/carbon/device/mgt/iot/raspberrypi/service/dto/DeviceJSON.java @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2015, 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.wso2.carbon.device.mgt.iot.raspberrypi.service.dto; + +import org.codehaus.jackson.annotate.JsonIgnoreProperties; + +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; + +@XmlRootElement + +@JsonIgnoreProperties(ignoreUnknown = true) +public class DeviceJSON { + @XmlElement(required = true) public String owner; + @XmlElement(required = true) public String deviceId; + @XmlElement(required = true) public String reply; + @XmlElement public Long time; + @XmlElement public String key; + @XmlElement public float value; +} diff --git a/components/device-mgt-iot-raspberrypi/org.wso2.carbon.device.mgt.iot.raspberrypi.service.impl/src/main/java/org/wso2/carbon/device/mgt/iot/raspberrypi/service/exception/RaspberrypiException.java b/components/device-mgt-iot-raspberrypi/org.wso2.carbon.device.mgt.iot.raspberrypi.service.impl/src/main/java/org/wso2/carbon/device/mgt/iot/raspberrypi/service/exception/RaspberrypiException.java new file mode 100644 index 0000000000..d3fd75860b --- /dev/null +++ b/components/device-mgt-iot-raspberrypi/org.wso2.carbon.device.mgt.iot.raspberrypi.service.impl/src/main/java/org/wso2/carbon/device/mgt/iot/raspberrypi/service/exception/RaspberrypiException.java @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2015, 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.wso2.carbon.device.mgt.iot.raspberrypi.service.exception; + +public class RaspberryPiException extends Exception { + private static final long serialVersionUID = 118512086957330189L; + + public RaspberryPiException(String errorMessage) { + super(errorMessage); + } + + public RaspberryPiException(String errorMessage, Throwable throwable) { + super(errorMessage, throwable); + } +} diff --git a/components/device-mgt-iot-raspberrypi/org.wso2.carbon.device.mgt.iot.raspberrypi.service.impl/src/main/java/org/wso2/carbon/device/mgt/iot/raspberrypi/service/transport/RaspberrypiMQTTSubscriber.java b/components/device-mgt-iot-raspberrypi/org.wso2.carbon.device.mgt.iot.raspberrypi.service.impl/src/main/java/org/wso2/carbon/device/mgt/iot/raspberrypi/service/transport/RaspberrypiMQTTSubscriber.java new file mode 100644 index 0000000000..2de9b9a257 --- /dev/null +++ b/components/device-mgt-iot-raspberrypi/org.wso2.carbon.device.mgt.iot.raspberrypi.service.impl/src/main/java/org/wso2/carbon/device/mgt/iot/raspberrypi/service/transport/RaspberrypiMQTTSubscriber.java @@ -0,0 +1,134 @@ +/* + * Copyright (c) 2015, 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.wso2.carbon.device.mgt.iot.raspberrypi.service.transport; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.eclipse.paho.client.mqttv3.MqttMessage; +import org.wso2.carbon.device.mgt.common.DeviceManagementException; +import org.wso2.carbon.device.mgt.iot.config.server.DeviceManagementConfigurationManager; +import org.wso2.carbon.device.mgt.iot.controlqueue.mqtt.MqttConfig; +import org.wso2.carbon.device.mgt.iot.controlqueue.mqtt.MqttSubscriber; +import org.wso2.carbon.device.mgt.iot.raspberrypi.plugin.constants.RaspberrypiConstants; +import org.wso2.carbon.device.mgt.iot.raspberrypi.service.util.RaspberrypiServiceUtils; +import org.wso2.carbon.device.mgt.iot.sensormgt.SensorDataManager; + +import java.io.File; +import java.util.Calendar; +import java.util.UUID; + +public class RaspberryPiMQTTSubscriber extends MqttSubscriber { + private static Log log = LogFactory.getLog(RaspberryPiMQTTSubscriber.class); + + private static final String serverName = + DeviceManagementConfigurationManager.getInstance().getDeviceManagementServerInfo().getName(); + private static final String subscribeTopic = + serverName + File.separator + "+" + File.separator + RaspberrypiConstants.DEVICE_TYPE + + File.separator + "+" + File.separator + "publisher"; + + private static final String iotServerSubscriber = UUID.randomUUID().toString().substring(0, 5); + private String mqttEndpoint; + + private RaspberryPiMQTTSubscriber() { + super(iotServerSubscriber, RaspberrypiConstants.DEVICE_TYPE, + MqttConfig.getInstance().getMqttQueueEndpoint(), subscribeTopic); + } + + public void initConnector() { + mqttEndpoint = MqttConfig.getInstance().getMqttQueueEndpoint(); + } + + public void connectAndSubscribe() { + try { + super.connectAndSubscribe(); + } catch (DeviceManagementException e) { + log.error("Subscription to MQTT Broker at: " + mqttEndpoint + " failed"); + retryMQTTSubscription(); + } + } + + @Override + protected void postMessageArrived(String topic, MqttMessage mqttMessage) { + String ownerAndId = topic.replace("wso2" + File.separator + "iot" + File.separator, ""); + ownerAndId = ownerAndId.replace(File.separator + RaspberrypiConstants.DEVICE_TYPE + File.separator, ":"); + ownerAndId = ownerAndId.replace(File.separator + "publisher", ""); + + String owner = ownerAndId.split(":")[0]; + String deviceId = ownerAndId.split(":")[1]; + String receivedMessage = mqttMessage.toString(); + + if (log.isDebugEnabled()) { + log.debug("Received MQTT message for: {OWNER-" + owner + "} & {DEVICE.ID-" + deviceId + "}"); + log.debug("MQTT: Received Message [" + receivedMessage + "] topic: [" + topic + "]"); + } + + if (receivedMessage.contains("PUBLISHER")) { + float temperature = Float.parseFloat(receivedMessage.split(":")[2]); + + if (!RaspberrypiServiceUtils.publishToDAS(owner, deviceId, temperature)) { + log.error("MQTT Subscriber: Publishing data to DAS failed."); + } + + if (log.isDebugEnabled()) { + log.debug("MQTT Subscriber: Published data to DAS successfully."); + } + + } else if (receivedMessage.contains("TEMPERATURE")) { + String temperatureValue = receivedMessage.split(":")[1]; + SensorDataManager.getInstance().setSensorRecord(deviceId, RaspberrypiConstants.SENSOR_TEMPERATURE, + temperatureValue, + Calendar.getInstance().getTimeInMillis()); + } + } + + private void retryMQTTSubscription() { + Thread retryToSubscribe = new Thread() { + @Override + public void run() { + while (true) { + if (!isConnected()) { + if (log.isDebugEnabled()) { + log.debug("Subscriber re-trying to reach MQTT queue...."); + } + + try { + RaspberryPiMQTTSubscriber.super.connectAndSubscribe(); + } catch (DeviceManagementException e1) { + if (log.isDebugEnabled()) { + log.debug("Attempt to re-connect to MQTT-Queue failed"); + } + } + } else { + break; + } + + try { + Thread.sleep(5000); + } catch (InterruptedException e1) { + log.error("MQTT: Thread S;eep Interrupt Exception"); + } + } + } + }; + + retryToSubscribe.setDaemon(true); + retryToSubscribe.start(); + } +} + diff --git a/components/device-mgt-iot-raspberrypi/org.wso2.carbon.device.mgt.iot.raspberrypi.service.impl/src/main/java/org/wso2/carbon/device/mgt/iot/raspberrypi/service/util/RaspberrypiServiceUtils.java b/components/device-mgt-iot-raspberrypi/org.wso2.carbon.device.mgt.iot.raspberrypi.service.impl/src/main/java/org/wso2/carbon/device/mgt/iot/raspberrypi/service/util/RaspberrypiServiceUtils.java new file mode 100644 index 0000000000..56fe46dabb --- /dev/null +++ b/components/device-mgt-iot-raspberrypi/org.wso2.carbon.device.mgt.iot.raspberrypi.service.impl/src/main/java/org/wso2/carbon/device/mgt/iot/raspberrypi/service/util/RaspberrypiServiceUtils.java @@ -0,0 +1,234 @@ +/* + * Copyright (c) 2015, 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.wso2.carbon.device.mgt.iot.raspberrypi.service.util; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.http.HttpResponse; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.concurrent.FutureCallback; +import org.apache.http.impl.nio.client.CloseableHttpAsyncClient; +import org.apache.http.impl.nio.client.HttpAsyncClients; +import org.wso2.carbon.context.PrivilegedCarbonContext; +import org.wso2.carbon.device.mgt.analytics.exception.DataPublisherConfigurationException; +import org.wso2.carbon.device.mgt.analytics.service.DeviceAnalyticsService; +import org.wso2.carbon.device.mgt.common.DeviceManagementException; +import org.wso2.carbon.device.mgt.iot.DeviceController; +import org.wso2.carbon.device.mgt.iot.exception.DeviceControllerException; +import org.wso2.carbon.device.mgt.iot.raspberrypi.plugin.constants.RaspberrypiConstants; + +import javax.ws.rs.HttpMethod; +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.net.HttpURLConnection; +import java.net.MalformedURLException; +import java.net.ProtocolException; +import java.net.URL; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.Future; + +public class RaspberrypiServiceUtils { + private static final Log log = LogFactory.getLog(RaspberrypiServiceUtils.class); + + //TODO; replace this tenant domain + private static final String SUPER_TENANT = "carbon.super"; + private static final String TEMPERATURE_STREAM_DEFINITION = "org.wso2.iot.devices.temperature"; + + public static String sendCommandViaHTTP(final String deviceHTTPEndpoint, String urlContext, + boolean fireAndForgot) throws DeviceManagementException { + + String responseMsg = ""; + String urlString = RaspberrypiConstants.URL_PREFIX + deviceHTTPEndpoint + urlContext; + + if (log.isDebugEnabled()) { + log.debug(urlString); + } + + if (!fireAndForgot) { + HttpURLConnection httpConnection = getHttpConnection(urlString); + + try { + httpConnection.setRequestMethod(HttpMethod.GET); + } catch (ProtocolException e) { + String errorMsg = + "Protocol specific error occurred when trying to set method to GET" + + " for:" + urlString; + log.error(errorMsg); + throw new DeviceManagementException(errorMsg, e); + } + + responseMsg = readResponseFromGetRequest(httpConnection); + + } else { + CloseableHttpAsyncClient httpclient = null; + try { + + httpclient = HttpAsyncClients.createDefault(); + httpclient.start(); + HttpGet request = new HttpGet(urlString); + final CountDownLatch latch = new CountDownLatch(1); + Future future = httpclient.execute( + request, new FutureCallback() { + @Override + public void completed(HttpResponse httpResponse) { + latch.countDown(); + } + + @Override + public void failed(Exception e) { + latch.countDown(); + } + + @Override + public void cancelled() { + latch.countDown(); + } + }); + + latch.await(); + + } catch (InterruptedException e) { + if (log.isDebugEnabled()) { + log.debug("Sync Interrupted"); + } + } finally { + try { + if (httpclient != null) { + httpclient.close(); + + } + } catch (IOException e) { + if (log.isDebugEnabled()) { + log.debug("Failed on close"); + } + } + } + } + + return responseMsg; + } + + + public static boolean sendCommandViaMQTT(String deviceOwner, String deviceId, String resource, + String state) throws DeviceManagementException { + + boolean result; + DeviceController deviceController = new DeviceController(); + + try { + result = deviceController.publishMqttControl(deviceOwner, RaspberrypiConstants.DEVICE_TYPE, deviceId, resource, state); + } catch (DeviceControllerException e) { + String errorMsg = "Error whilst trying to publish to MQTT Queue"; + log.error(errorMsg); + throw new DeviceManagementException(errorMsg, e); + } + return result; + } + + /* --------------------------------------------------------------------------------------- + Utility methods relevant to creating and sending http requests + --------------------------------------------------------------------------------------- */ + + /* This methods creates and returns a http connection object */ + + public static HttpURLConnection getHttpConnection(String urlString) throws + DeviceManagementException { + + URL connectionUrl = null; + HttpURLConnection httpConnection; + + try { + connectionUrl = new URL(urlString); + httpConnection = (HttpURLConnection) connectionUrl.openConnection(); + } catch (MalformedURLException e) { + String errorMsg = + "Error occured whilst trying to form HTTP-URL from string: " + urlString; + log.error(errorMsg); + throw new DeviceManagementException(errorMsg, e); + } catch (IOException e) { + String errorMsg = "Error occured whilst trying to open a connection to: " + + connectionUrl.toString(); + log.error(errorMsg); + throw new DeviceManagementException(errorMsg, e); + } + + return httpConnection; + } + + /* This methods reads and returns the response from the connection */ + + public static String readResponseFromGetRequest(HttpURLConnection httpConnection) + throws DeviceManagementException { + BufferedReader bufferedReader; + try { + bufferedReader = new BufferedReader(new InputStreamReader( + httpConnection.getInputStream())); + } catch (IOException e) { + String errorMsg = + "There is an issue with connecting the reader to the input stream at: " + + httpConnection.getURL(); + log.error(errorMsg); + throw new DeviceManagementException(errorMsg, e); + } + + String responseLine; + StringBuilder completeResponse = new StringBuilder(); + + try { + while ((responseLine = bufferedReader.readLine()) != null) { + completeResponse.append(responseLine); + } + } catch (IOException e) { + String errorMsg = + "Error occured whilst trying read from the connection stream at: " + + httpConnection.getURL(); + log.error(errorMsg); + throw new DeviceManagementException(errorMsg, e); + } + try { + bufferedReader.close(); + } catch (IOException e) { + log.error( + "Could not succesfully close the bufferedReader to the connection at: " + + httpConnection.getURL()); + } + + return completeResponse.toString(); + } + + public static boolean publishToDAS(String owner, String deviceId, float temperature) { + PrivilegedCarbonContext.startTenantFlow(); + PrivilegedCarbonContext ctx = PrivilegedCarbonContext.getThreadLocalCarbonContext(); + ctx.setTenantDomain(SUPER_TENANT, true); + DeviceAnalyticsService deviceAnalyticsService = (DeviceAnalyticsService) ctx.getOSGiService( + DeviceAnalyticsService.class, null); + Object metdaData[] = {owner, RaspberrypiConstants.DEVICE_TYPE, deviceId, System.currentTimeMillis()}; + Object payloadData[] = {temperature}; + + try { + deviceAnalyticsService.publishEvent(TEMPERATURE_STREAM_DEFINITION, "1.0.0", metdaData, new Object[0], payloadData); + } catch (DataPublisherConfigurationException e) { + return false; + } finally { + PrivilegedCarbonContext.endTenantFlow(); + } + return true; + } +} diff --git a/components/device-mgt-iot-raspberrypi/org.wso2.carbon.device.mgt.iot.raspberrypi.service.impl/src/main/webapp/META-INF/webapp-classloading.xml b/components/device-mgt-iot-raspberrypi/org.wso2.carbon.device.mgt.iot.raspberrypi.service.impl/src/main/webapp/META-INF/webapp-classloading.xml new file mode 100644 index 0000000000..fa44619195 --- /dev/null +++ b/components/device-mgt-iot-raspberrypi/org.wso2.carbon.device.mgt.iot.raspberrypi.service.impl/src/main/webapp/META-INF/webapp-classloading.xml @@ -0,0 +1,33 @@ + + + + + + + + + false + + + CXF,Carbon + diff --git a/components/device-mgt-iot-raspberrypi/org.wso2.carbon.device.mgt.iot.raspberrypi.service.impl/src/main/webapp/WEB-INF/cxf-servlet.xml b/components/device-mgt-iot-raspberrypi/org.wso2.carbon.device.mgt.iot.raspberrypi.service.impl/src/main/webapp/WEB-INF/cxf-servlet.xml new file mode 100644 index 0000000000..78b5061a0b --- /dev/null +++ b/components/device-mgt-iot-raspberrypi/org.wso2.carbon.device.mgt.iot.raspberrypi.service.impl/src/main/webapp/WEB-INF/cxf-servlet.xml @@ -0,0 +1,48 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/components/device-mgt-iot-raspberrypi/org.wso2.carbon.device.mgt.iot.raspberrypi.service.impl/src/main/webapp/WEB-INF/web.xml b/components/device-mgt-iot-raspberrypi/org.wso2.carbon.device.mgt.iot.raspberrypi.service.impl/src/main/webapp/WEB-INF/web.xml new file mode 100644 index 0000000000..6518ec4e2e --- /dev/null +++ b/components/device-mgt-iot-raspberrypi/org.wso2.carbon.device.mgt.iot.raspberrypi.service.impl/src/main/webapp/WEB-INF/web.xml @@ -0,0 +1,70 @@ + + + RaspberryPi + RaspberryPi + + + CXFServlet + org.apache.cxf.transport.servlet.CXFServlet + 1 + + + + + CXFServlet + /* + + + + isAdminService + false + + + doAuthentication + false + + + + + managed-api-enabled + true + + + managed-api-owner + admin + + + managed-api-name + raspberrypi + + + managed-api-endpoint + http://localhost:9763/raspberrypi + + + managed-api-version + 1.0.0 + + + managed-api-context + /raspberrypi + + + managed-api-context-template + /raspberrypi/{version} + + + managed-api-application + raspberrypi + + + managed-api-isSecured + true + + + + diff --git a/components/device-mgt-iot-raspberrypi/pom.xml b/components/device-mgt-iot-raspberrypi/pom.xml index 80de139dd2..b765b22f9c 100644 --- a/components/device-mgt-iot-raspberrypi/pom.xml +++ b/components/device-mgt-iot-raspberrypi/pom.xml @@ -37,7 +37,7 @@ org.wso2.carbon.device.mgt.iot.raspberrypi.plugin.impl - + org.wso2.carbon.device.mgt.iot.raspberrypi.service.impl diff --git a/components/device-mgt-iot-virtualfirealarm/org.wso2.carbon.device.mgt.iot.virtualfirealarm.service.impl/src/main/java/org/wso2/carbon/device/mgt/iot/virtualfirealarm/service/VirtualFireAlarmService.java b/components/device-mgt-iot-virtualfirealarm/org.wso2.carbon.device.mgt.iot.virtualfirealarm.service.impl/src/main/java/org/wso2/carbon/device/mgt/iot/virtualfirealarm/service/VirtualFireAlarmService.java index 6548530823..a0f41b1164 100644 --- a/components/device-mgt-iot-virtualfirealarm/org.wso2.carbon.device.mgt.iot.virtualfirealarm.service.impl/src/main/java/org/wso2/carbon/device/mgt/iot/virtualfirealarm/service/VirtualFireAlarmService.java +++ b/components/device-mgt-iot-virtualfirealarm/org.wso2.carbon.device.mgt.iot.virtualfirealarm.service.impl/src/main/java/org/wso2/carbon/device/mgt/iot/virtualfirealarm/service/VirtualFireAlarmService.java @@ -21,9 +21,6 @@ package org.wso2.carbon.device.mgt.iot.virtualfirealarm.service; import org.apache.commons.io.FileUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.apache.cxf.helpers.IOUtils; -import org.apache.http.Header; -import org.apache.woden.wsdl20.extensions.http.HTTPHeader; import org.wso2.carbon.certificate.mgt.core.dto.SCEPResponse; import org.wso2.carbon.certificate.mgt.core.exception.KeystoreException; import org.wso2.carbon.certificate.mgt.core.service.CertificateManagementService; @@ -69,11 +66,8 @@ 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.File; -import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; -import java.io.OutputStream; import java.nio.ByteBuffer; import java.nio.charset.StandardCharsets; import java.util.ArrayList; @@ -104,12 +98,20 @@ public class VirtualFireAlarmService { private ConcurrentHashMap deviceToIpMap = new ConcurrentHashMap<>(); + /** + * + * @param verificationManager + */ public void setVerificationManager( VerificationManager verificationManager) { this.verificationManager = verificationManager; verificationManager.initVerificationManager(); } + /** + * + * @param virtualFireAlarmXMPPConnector + */ public void setVirtualFireAlarmXMPPConnector( final VirtualFireAlarmXMPPConnector virtualFireAlarmXMPPConnector) { this.virtualFireAlarmXMPPConnector = virtualFireAlarmXMPPConnector; @@ -127,6 +129,10 @@ public class VirtualFireAlarmService { mqttStarterThread.start(); } + /** + * + * @param virtualFireAlarmMQTTSubscriber + */ public void setVirtualFireAlarmMQTTSubscriber( final VirtualFireAlarmMQTTSubscriber virtualFireAlarmMQTTSubscriber) { this.virtualFireAlarmMQTTSubscriber = virtualFireAlarmMQTTSubscriber; @@ -144,22 +150,42 @@ public class VirtualFireAlarmService { xmppStarterThread.start(); } + /** + * + * @return + */ public VerificationManager getVerificationManager() { return verificationManager; } + /** + * + * @return + */ public VirtualFireAlarmXMPPConnector getVirtualFireAlarmXMPPConnector() { return virtualFireAlarmXMPPConnector; } + /** + * + * @return + */ public VirtualFireAlarmMQTTSubscriber getVirtualFireAlarmMQTTSubscriber() { return virtualFireAlarmMQTTSubscriber; } /* --------------------------------------------------------------------------------------- Device management specific APIs - Also contains utility methods required for the execution of these APIs - --------------------------------------------------------------------------------------- */ + Also contains utility methods required for the execution of these APIs + --------------------------------------------------------------------------------------- */ + + /** + * + * @param deviceId + * @param name + * @param owner + * @return + */ @Path("manager/device/register") @PUT public boolean register(@QueryParam("deviceId") String deviceId, @@ -205,6 +231,11 @@ public class VirtualFireAlarmService { } } + /** + * + * @param deviceId + * @param response + */ @Path("manager/device/remove/{device_id}") @DELETE public void removeDevice(@PathParam("device_id") String deviceId, @Context HttpServletResponse response) { @@ -218,10 +249,8 @@ public class VirtualFireAlarmService { 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()); @@ -231,6 +260,13 @@ public class VirtualFireAlarmService { } + /** + * + * @param deviceId + * @param name + * @param response + * @return + */ @Path("manager/device/update/{device_id}") @POST public boolean updateDevice(@PathParam("device_id") String deviceId, @@ -256,10 +292,8 @@ public class VirtualFireAlarmService { if (updated) { response.setStatus(Response.Status.OK.getStatusCode()); - } else { response.setStatus(Response.Status.NOT_ACCEPTABLE.getStatusCode()); - } return updated; } catch (DeviceManagementException e) { @@ -271,6 +305,11 @@ public class VirtualFireAlarmService { } + /** + * + * @param deviceId + * @return + */ @Path("manager/device/{device_id}") @GET @Consumes(MediaType.APPLICATION_JSON) @@ -294,6 +333,11 @@ public class VirtualFireAlarmService { } + /** + * + * @param username + * @return + */ @Path("manager/devices/{username}") @GET @Consumes(MediaType.APPLICATION_JSON) @@ -324,9 +368,15 @@ public class VirtualFireAlarmService { } finally { deviceManagement.endTenantFlow(); } - } + /** + * + * @param owner + * @param customDeviceName + * @param sketchType + * @return + */ @Path("manager/device/{sketch_type}/download") @GET @Produces(MediaType.APPLICATION_JSON) @@ -353,6 +403,13 @@ public class VirtualFireAlarmService { } } + /** + * + * @param owner + * @param customDeviceName + * @param sketchType + * @return + */ @Path("manager/device/{sketch_type}/generate_link") @GET public Response generateSketchLink(@QueryParam("owner") String owner, @@ -372,9 +429,18 @@ public class VirtualFireAlarmService { } catch (DeviceControllerException ex) { return Response.status(500).entity(ex.getMessage()).build(); } - } + /** + * + * @param owner + * @param customDeviceName + * @param sketchType + * @return + * @throws DeviceManagementException + * @throws AccessTokenException + * @throws DeviceControllerException + */ private ZipArchive createDownloadFile(String owner, String customDeviceName, String sketchType) throws DeviceManagementException, AccessTokenException, DeviceControllerException { if (owner == null) { @@ -406,8 +472,7 @@ public class VirtualFireAlarmService { status = xmppServerClient.createXMPPAccount(newXmppAccount); if (!status) { String msg = - "XMPP Account was not created for device - " + deviceId + " of owner - " + - owner + + "XMPP Account was not created for device - " + deviceId + " of owner - " + owner + ".XMPP might have been disabled in org.wso2.carbon.device.mgt.iot" + ".common.config.server.configs"; log.warn(msg); @@ -420,8 +485,7 @@ public class VirtualFireAlarmService { status = register(deviceId, deviceName, owner); if (!status) { - String msg = "Error occurred while registering the device with " + "id: " + deviceId - + " owner:" + owner; + String msg = "Error occurred while registering the device with " + "id: " + deviceId + " owner:" + owner; throw new DeviceManagementException(msg); } @@ -433,6 +497,10 @@ public class VirtualFireAlarmService { return zipFile; } + /** + * + * @return + */ private static String shortUUID() { UUID uuid = UUID.randomUUID(); long l = ByteBuffer.wrap(uuid.toString().getBytes(StandardCharsets.UTF_8)).getLong(); @@ -443,6 +511,17 @@ public class VirtualFireAlarmService { Device specific APIs - Control APIs + Data-Publishing APIs Also contains utility methods required for the execution of these APIs --------------------------------------------------------------------------------------- */ + + /** + * + * @param owner + * @param deviceId + * @param deviceIP + * @param devicePort + * @param response + * @param request + * @return + */ @Path("controller/register/{owner}/{deviceId}/{ip}/{port}") @POST public String registerDeviceIP(@PathParam("owner") String owner, @@ -473,6 +552,15 @@ public class VirtualFireAlarmService { /* Service to switch "ON" and "OFF" the Virtual FireAlarm bulb Called by an external client intended to control the Virtual FireAlarm bulb */ + + /** + * + * @param owner + * @param deviceId + * @param protocol + * @param state + * @param response + */ @Path("controller/bulb/{state}") @POST public void switchBulb(@HeaderParam("owner") String owner, @@ -546,6 +634,14 @@ public class VirtualFireAlarmService { } + /** + * + * @param owner + * @param deviceId + * @param protocol + * @param response + * @return + */ @Path("controller/readsonar") @GET public String requestSonarReading(@HeaderParam("owner") String owner, @@ -619,6 +715,14 @@ public class VirtualFireAlarmService { } + /** + * + * @param owner + * @param deviceId + * @param protocol + * @param response + * @return + */ @Path("controller/readtemperature") @GET @Consumes(MediaType.APPLICATION_JSON) @@ -691,6 +795,11 @@ public class VirtualFireAlarmService { return sensorRecord; } + /** + * + * @param dataMsg + * @param response + */ @Path("controller/push_temperature") @POST @Consumes(MediaType.APPLICATION_JSON) @@ -726,6 +835,12 @@ public class VirtualFireAlarmService { } + /** + * + * @param operation + * @param message + * @return + */ @GET @Path("controller/scep") public Response scepRequest(@QueryParam("operation") String operation, @QueryParam("message") String message) { @@ -803,6 +918,12 @@ public class VirtualFireAlarmService { return Response.serverError().build(); } + /** + * + * @param operation + * @param inputStream + * @return + */ @POST @Path("controller/scep") public Response scepRequestPost(@QueryParam("operation") String operation, InputStream inputStream) { diff --git a/components/device-mgt-iot/org.wso2.carbon.device.mgt.iot/src/main/java/org/wso2/carbon/device/mgt/iot/apimgt/TokenClient.java b/components/device-mgt-iot/org.wso2.carbon.device.mgt.iot/src/main/java/org/wso2/carbon/device/mgt/iot/apimgt/TokenClient.java index 58f4fc0b23..4450707214 100644 --- a/components/device-mgt-iot/org.wso2.carbon.device.mgt.iot/src/main/java/org/wso2/carbon/device/mgt/iot/apimgt/TokenClient.java +++ b/components/device-mgt-iot/org.wso2.carbon.device.mgt.iot/src/main/java/org/wso2/carbon/device/mgt/iot/apimgt/TokenClient.java @@ -116,16 +116,27 @@ public class TokenClient { HttpResponse httpResponse = httpClient.execute(postMethod); String response = IoTUtil.getResponseString(httpResponse); + if(log.isDebugEnabled()) { log.debug(response); } - JSONObject jsonObject = new JSONObject(response); + JSONObject jsonObject = new JSONObject(response); AccessTokenInfo accessTokenInfo = new AccessTokenInfo(); - accessTokenInfo.setAccess_token(jsonObject.getString("access_token")); - accessTokenInfo.setRefresh_token(jsonObject.getString("refresh_token")); - accessTokenInfo.setExpires_in(jsonObject.getInt("expires_in")); - accessTokenInfo.setToken_type(jsonObject.getString("token_type")); + + if (!jsonObject.get("access_token").equals(null)) { + accessTokenInfo.setAccess_token(jsonObject.getString("access_token")); + } + if (!jsonObject.get("refresh_token").equals(null)) { + accessTokenInfo.setRefresh_token(jsonObject.getString("refresh_token")); + } + if (!jsonObject.get("expires_in").equals(null)) { + accessTokenInfo.setExpires_in(jsonObject.getInt("expires_in")); + } + if (!jsonObject.get("token_type").equals(null)) { + accessTokenInfo.setToken_type(jsonObject.getString("token_type")); + } + return accessTokenInfo; } catch ( IOException | JSONException | IoTException e) { diff --git a/components/device-mgt-iot/org.wso2.carbon.device.mgt.iot/src/main/java/org/wso2/carbon/device/mgt/iot/util/ZipUtil.java b/components/device-mgt-iot/org.wso2.carbon.device.mgt.iot/src/main/java/org/wso2/carbon/device/mgt/iot/util/ZipUtil.java index 03ff7d539f..4b18d6e648 100644 --- a/components/device-mgt-iot/org.wso2.carbon.device.mgt.iot/src/main/java/org/wso2/carbon/device/mgt/iot/util/ZipUtil.java +++ b/components/device-mgt-iot/org.wso2.carbon.device.mgt.iot/src/main/java/org/wso2/carbon/device/mgt/iot/util/ZipUtil.java @@ -48,8 +48,7 @@ public class ZipUtil { + sep + deviceId; String templateSketchPath = sketchFolder + sep + deviceType; -// String iotServerIP = System.getProperty("bind.address"); - String iotServerIP = System.getProperty("server.host"); + String iotServerIP = System.getProperty("carbon.local.ip"); // bind.address String httpsServerPort = System.getProperty("httpsPort"); String httpServerPort = System.getProperty("httpPort"); @@ -60,28 +59,13 @@ public class ZipUtil { DeviceManagementConfigurationManager.getInstance().getDeviceCloudMgtConfig().getApiManager() .getServerURL(); -// int indexOfChar = apimIP.lastIndexOf(File.separator); -// if (indexOfChar != -1) { -// apimIP = apimIP.substring((indexOfChar + 1), apimIP.length()); -// } - String apimGatewayPort = DeviceManagementConfigurationManager.getInstance().getDeviceCloudMgtConfig().getApiManager() .getGatewayPort(); String apimEndpoint = apimHost + ":" + apimGatewayPort; - String mqttEndpoint = MqttConfig.getInstance().getMqttQueueEndpoint(); -// indexOfChar = mqttEndpoint.lastIndexOf(File.separator); -// if (indexOfChar != -1) { -// mqttEndpoint = mqttEndpoint.substring((indexOfChar + 1), mqttEndpoint.length()); -// } - String xmppEndpoint = XmppConfig.getInstance().getXmppEndpoint(); -// indexOfChar = xmppEndpoint.lastIndexOf(File.separator); -// if (indexOfChar != -1) { -// xmppEndpoint = xmppEndpoint.substring((indexOfChar + 1), xmppEndpoint.length()); -// } int indexOfChar = xmppEndpoint.lastIndexOf(":"); if (indexOfChar != -1) { @@ -104,8 +88,7 @@ public class ZipUtil { ZipArchive zipFile; try { - zipFile = IotDeviceManagementUtil.getSketchArchive(archivesPath, templateSketchPath, - contextParams); + zipFile = IotDeviceManagementUtil.getSketchArchive(archivesPath, templateSketchPath, contextParams); } catch (IOException e) { throw new DeviceManagementException("Zip File Creation Failed", e); } diff --git a/features/device-mgt-iot-feature/org.wso2.carbon.device.mgt.iot.feature/src/main/resources/conf/devicetype-config.xml b/features/device-mgt-iot-feature/org.wso2.carbon.device.mgt.iot.feature/src/main/resources/conf/devicetype-config.xml index e546b8263e..da47f1a34e 100644 --- a/features/device-mgt-iot-feature/org.wso2.carbon.device.mgt.iot.feature/src/main/resources/conf/devicetype-config.xml +++ b/features/device-mgt-iot-feature/org.wso2.carbon.device.mgt.iot.feature/src/main/resources/conf/devicetype-config.xml @@ -3,18 +3,18 @@ jdbc/AndroidSenseDM_DB - - - + + jdbc/ArduinoDM_DB + jdbc/DigitalDisplayDM_DB jdbc/DroneAnalyzerDM_DB - - - + + jdbc/RaspberryPiDM_DB + jdbc/VirtualFireAlarmDM_DB diff --git a/features/device-mgt-iot-raspberrypi-feature/org.wso2.carbon.device.mgt.iot.raspberrypi.feature/src/main/resources/agent/GuideToPi b/features/device-mgt-iot-raspberrypi-feature/org.wso2.carbon.device.mgt.iot.raspberrypi.feature/src/main/resources/agent/GuideToPi new file mode 100644 index 0000000000..9c23d9eea6 --- /dev/null +++ b/features/device-mgt-iot-raspberrypi-feature/org.wso2.carbon.device.mgt.iot.raspberrypi.feature/src/main/resources/agent/GuideToPi @@ -0,0 +1,17 @@ +Install Rpi.GPIO +Install sh + sudo easy_install pip + sudo pip install sh + + +wget http://67.192.60.197/mikem/bcm2835/bcm2835-1.8.tar.gz +tar xvfz bcm2835-1.8.tar.gz; +cd bcm2835-1.8; +./configure; +make; +sudo make install + +sudo apt-get update +sudo apt-get install python-dev + +nohup command >/dev/null 2>&1 & \ No newline at end of file diff --git a/features/device-mgt-iot-raspberrypi-feature/org.wso2.carbon.device.mgt.iot.raspberrypi.feature/src/main/resources/agent/deviceConfigs.cfg b/features/device-mgt-iot-raspberrypi-feature/org.wso2.carbon.device.mgt.iot.raspberrypi.feature/src/main/resources/agent/deviceConfigs.cfg new file mode 100644 index 0000000000..2638fa9094 --- /dev/null +++ b/features/device-mgt-iot-raspberrypi-feature/org.wso2.carbon.device.mgt.iot.raspberrypi.feature/src/main/resources/agent/deviceConfigs.cfg @@ -0,0 +1,14 @@ +[Device-Configurations] +owner=${DEVICE_OWNER} +deviceId=${DEVICE_ID} +device-name=${DEVICE_NAME} +controller-context=/RaspberryPiDeviceManager/raspberrypi/controller +https-ep=${HTTPS_EP} +http-ep=${HTTP_EP} +apim-ep=${APIM_EP} +mqtt-ep=${MQTT_EP} +xmpp-ep=${XMPP_EP} +auth-method=token +auth-token=${DEVICE_TOKEN} +refresh-token=${DEVICE_REFRESH_TOKEN} +push-interval=15 diff --git a/features/device-mgt-iot-raspberrypi-feature/org.wso2.carbon.device.mgt.iot.raspberrypi.feature/src/main/resources/agent/raspberrypi.deb b/features/device-mgt-iot-raspberrypi-feature/org.wso2.carbon.device.mgt.iot.raspberrypi.feature/src/main/resources/agent/raspberrypi.deb deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/features/device-mgt-iot-raspberrypi-feature/org.wso2.carbon.device.mgt.iot.raspberrypi.feature/src/main/resources/agent/src/Adafruit_Python_DHT.zip b/features/device-mgt-iot-raspberrypi-feature/org.wso2.carbon.device.mgt.iot.raspberrypi.feature/src/main/resources/agent/src/Adafruit_Python_DHT.zip new file mode 100644 index 0000000000..889117c3f7 Binary files /dev/null and b/features/device-mgt-iot-raspberrypi-feature/org.wso2.carbon.device.mgt.iot.raspberrypi.feature/src/main/resources/agent/src/Adafruit_Python_DHT.zip differ diff --git a/features/device-mgt-iot-raspberrypi-feature/org.wso2.carbon.device.mgt.iot.raspberrypi.feature/src/main/resources/agent/src/RaspberryStats.py b/features/device-mgt-iot-raspberrypi-feature/org.wso2.carbon.device.mgt.iot.raspberrypi.feature/src/main/resources/agent/src/RaspberryStats.py new file mode 100755 index 0000000000..34d0a172b0 --- /dev/null +++ b/features/device-mgt-iot-raspberrypi-feature/org.wso2.carbon.device.mgt.iot.raspberrypi.feature/src/main/resources/agent/src/RaspberryStats.py @@ -0,0 +1,332 @@ +#!/usr/bin/env python + +""" +/** +* Copyright (c) 2015, 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. +**/ +""" + + +import logging, logging.handlers +import sys, os, signal, argparse +import httplib, time +import threading +import Adafruit_DHT # Adafruit library required for temperature sensing + +import iotUtils +import httpServer # python script used to start a http-server to listen for operations (includes the TEMPERATURE global variable) +import xmppServer # python script used to communicate with xmpp server +import mqttListener # python script used to accept messages via mqtt + + + +PUSH_INTERVAL = 300 # time interval between successive data pushes in seconds +logging_enabled = False + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# Endpoint specific settings to which the data is pushed +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +DC_IP = '204.232.188.214' #'192.168.57.128' +DC_PORT = 8281 +HOST = DC_IP + ':' + `DC_PORT` + +DC_ENDPOINT = '/firealarm/1.0/controller' #'/firealarm/1.0/' +PUSH_ENDPOINT = DC_ENDPOINT + '/push_temperature' +REGISTER_ENDPOINT = DC_ENDPOINT + '/register' +### ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# Logger defaults +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +LOG_FILENAME = "/usr/local/src/RaspberryAgent/logs/RaspberryStats.log" +LOG_LEVEL = logging.INFO # Could be e.g. "DEBUG" or "WARNING" +### ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# Define and parse command line arguments +# If the log file is specified on the command line then override the default +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +parser = argparse.ArgumentParser(description="Python service to push RPi info to the Device Cloud") +parser.add_argument("-l", "--log", help="file to write log to (default '" + LOG_FILENAME + "')") + +help_string = "time interval between successive data pushes (default '" + str(PUSH_INTERVAL) + "')" +parser.add_argument("-i", "--interval", type=int, help=help_string) + +args = parser.parse_args() +if args.log: + LOG_FILENAME = args.log + +if args.interval: + PUSH_INTERVAL = args.interval +### ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# A class we can use to capture stdout and sterr in the log +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +class IOTLogger(object): + def __init__(self, logger, level): + """Needs a logger and a logger level.""" + self.logger = logger + self.level = level + + def write(self, message): + if message.rstrip() != "": # Only log if there is a message (not just a new line) + self.logger.log(self.level, message.rstrip()) +### ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# Configure logging to log to a file, +# making a new file at midnight and keeping the last 3 day's data +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +def configureLogger(loggerName): + logger = logging.getLogger(loggerName) + logger.setLevel(LOG_LEVEL) # Set the log level to LOG_LEVEL + handler = logging.handlers.TimedRotatingFileHandler(LOG_FILENAME, when="midnight", backupCount=3) # Handler that writes to a file, + # ~~~make new file at midnight and keep 3 backups + formatter = logging.Formatter('%(asctime)s %(levelname)-8s %(message)s') # Format each log message like this + handler.setFormatter(formatter) # Attach the formatter to the handler + logger.addHandler(handler) # Attach the handler to the logger + + if(logging_enabled): + sys.stdout = IOTLogger(logger, logging.INFO) # Replace stdout with logging to file at INFO level + sys.stderr = IOTLogger(logger, logging.ERROR) # Replace stderr with logging to file at ERROR level +### ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# This method registers the DevieIP in the Device-Cloud +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +def registerDeviceIP(): + dcConncection = httplib.HTTPConnection(DC_IP, DC_PORT) + dcConncection.set_debuglevel(1) + dcConncection.connect() + + registerURL = REGISTER_ENDPOINT + '/' + iotUtils.DEVICE_OWNER + '/' + iotUtils.DEVICE_ID + '/' + iotUtils.HOST_NAME + + dcConncection.putrequest('POST', registerURL) + dcConncection.putheader('Authorization', 'Bearer ' + iotUtils.AUTH_TOKEN) + dcConncection.endheaders() + + print '~~~~~~~~~~~~~~~~~~~~~~~~ Device Registration ~~~~~~~~~~~~~~~~~~~~~~~~~' + dcResponse = dcConncection.getresponse() + + print '~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~' + print ('RASPBERRY_STATS: ' + str(registerURL)) + print ('RASPBERRY_STATS: ' + str(dcResponse.status)) + print ('RASPBERRY_STATS: ' + str(dcResponse.reason)) + print ('RASPBERRY_STATS: Response Message') + print str(dcResponse.msg) + + dcConncection.close() + print '~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~' +### ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# This method connects to the Device-Cloud and pushes data +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +def connectAndPushData(): + dcConnection = httplib.HTTPConnection(DC_IP, DC_PORT) + dcConnection.set_debuglevel(1) + + dcConnection.connect() + + request = dcConnection.putrequest('POST', PUSH_ENDPOINT) + + headers = {} + headers['Authorization'] = 'Bearer ' + iotUtils.AUTH_TOKEN + headers['Content-Type'] = 'application/json' + + ### ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + ### Read the Temperature and Load info of RPi and construct payload + ### ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + # rPiTemperature=getCPUTemp() # Can be used if required to push CPU Temperature + # rPiLoad = getCPULoad() # Can be used if required to push CPU Load + + ### ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + rPiTemperature = iotUtils.LAST_TEMP # Push the last read temperature value + PUSH_DATA = iotUtils.DEVICE_INFO + iotUtils.DEVICE_IP.format(ip=iotUtils.HOST_NAME) + iotUtils.DEVICE_DATA.format(temperature=rPiTemperature) + PUSH_DATA += '}' + + # print PUSH_DATA + + headers['Content-Length'] = len(PUSH_DATA) + print '~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~' + + for k in headers: + dcConnection.putheader(k, headers[k]) + dcConnection.endheaders() + + print '~~~~~~~~~~~~~~~~~~~~~~~~ Pushing Device-Data ~~~~~~~~~~~~~~~~~~~~~~~~~' + + dcConnection.send(PUSH_DATA) # Push the data + dcResponse = dcConnection.getresponse() + + print '~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~' + print ('RASPBERRY_STATS: ' + str(dcResponse.status)) + print ('RASPBERRY_STATS: ' + str(dcResponse.reason)) + print ('RASPBERRY_STATS: Response Message') + print str(dcResponse.msg) + print '~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~' + dcConnection.close() + + if (dcResponse.status == 409 or dcResponse.status == 412): + print 'RASPBERRY_STATS: Re-registering Device IP' + registerDeviceIP() + +### ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# This is a Thread object for reading temperature continuously +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +class TemperatureReaderThread(object): + def __init__(self, interval=3): + self.interval = interval + + thread = threading.Thread(target=self.run, args=()) + thread.daemon = True # Daemonize thread + thread.start() # Start the execution + + def run(self): + TEMP_PIN = 4 + TEMP_SENSOR_TYPE = 11 + + # Try to grab a sensor reading. Use the read_retry method which will retry up + # to 15 times to get a sensor reading (waiting 2 seconds between each retry). + while True: + try: + humidity, temperature = Adafruit_DHT.read_retry(TEMP_SENSOR_TYPE, TEMP_PIN) + + if temperature != iotUtils.LAST_TEMP: + iotUtils.LAST_TEMP = temperature + connectAndPushData() + + iotUtils.LAST_TEMP = temperature + print 'RASPBERRY_STATS: Temp={0:0.1f}*C Humidity={1:0.1f}%'.format(temperature, humidity) + + except Exception, e: + print "RASPBERRY_STATS: Exception in TempReaderThread: Could not successfully read Temperature" + print ("RASPBERRY_STATS: " + str(e)) + print '~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~' + pass + + time.sleep(self.interval) +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# This is a Thread object for listening for MQTT Messages +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +class UtilsThread(object): + def __init__(self): + thread = threading.Thread(target=self.run, args=()) + thread.daemon = True # Daemonize thread + thread.start() # Start the execution + + def run(self): + iotUtils.main() +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + + + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# This is a Thread object for HTTP-Server that listens for operations on RPi +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +class ListenHTTPServerThread(object): + def __init__(self): + thread = threading.Thread(target=self.run, args=()) + thread.daemon = True # Daemonize thread + thread.start() # Start the execution + + def run(self): + httpServer.main() +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# This is a Thread object for Server that listens for XMPP Messages +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +class ListenXMPPServerThread(object): + def __init__(self): + thread = threading.Thread(target=self.run, args=()) + thread.daemon = True # Daemonize thread + thread.start() # Start the execution + + def run(self): + xmppServer.main() +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# This is a Thread object for listening for MQTT Messages +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +class ListenMQTTThread(object): + def __init__(self): + thread = threading.Thread(target=self.run, args=()) + thread.daemon = True # Daemonize thread + thread.start() # Start the execution + + def run(self): + mqttListener.main() +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# The Main method of the RPi Agent +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +def main(): + configureLogger("WSO2IOT_RPiStats") +# iotUtils.setUpGPIOPins() + + UtilsThread() + registerDeviceIP() # Call the register endpoint and register Device IP + TemperatureReaderThread() # initiates and runs the thread to continuously read temperature from DHT Sensor + ListenHTTPServerThread() # starts an HTTP Server that listens for operational commands to switch ON/OFF Led + ListenXMPPServerThread() + ListenMQTTThread() + + while True: + try: + if iotUtils.LAST_TEMP > 0: # Push data only if there had been a successful temperature read + connectAndPushData() # Push Sensor (Temperature) data to WSO2 BAM + time.sleep(PUSH_INTERVAL) + except (KeyboardInterrupt, Exception) as e: + print "RASPBERRY_STATS: Exception in RaspberryAgentThread (either KeyboardInterrupt or Other)" + print ("RASPBERRY_STATS: " + str(e)) + print '~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~' + pass +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +if __name__ == "__main__": + main() diff --git a/features/device-mgt-iot-raspberrypi-feature/org.wso2.carbon.device.mgt.iot.raspberrypi.feature/src/main/resources/agent/src/getMac.sh b/features/device-mgt-iot-raspberrypi-feature/org.wso2.carbon.device.mgt.iot.raspberrypi.feature/src/main/resources/agent/src/getMac.sh new file mode 100755 index 0000000000..0b35872df2 --- /dev/null +++ b/features/device-mgt-iot-raspberrypi-feature/org.wso2.carbon.device.mgt.iot.raspberrypi.feature/src/main/resources/agent/src/getMac.sh @@ -0,0 +1,24 @@ +#!/bin/sh + +""" +/** +* Copyright (c) 2015, 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. +**/ +""" + +piMac=`/sbin/ifconfig | grep 'wlan0' | tr -s ' ' | cut -d ' ' -f5 | tr -d ':'` +echo The device ID is $piMac diff --git a/features/device-mgt-iot-raspberrypi-feature/org.wso2.carbon.device.mgt.iot.raspberrypi.feature/src/main/resources/agent/src/httpServer.py b/features/device-mgt-iot-raspberrypi-feature/org.wso2.carbon.device.mgt.iot.raspberrypi.feature/src/main/resources/agent/src/httpServer.py new file mode 100755 index 0000000000..c31a7bb8a0 --- /dev/null +++ b/features/device-mgt-iot-raspberrypi-feature/org.wso2.carbon.device.mgt.iot.raspberrypi.feature/src/main/resources/agent/src/httpServer.py @@ -0,0 +1,134 @@ +#!/usr/bin/env python + +""" +/** +* Copyright (c) 2015, 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. +**/ +""" + +import time +import BaseHTTPServer +import iotUtils + + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# HOST and PORT info of the HTTP Server that gets started +# HOST_NAME is initialised in the main() method +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +#global HOST_NAME +#HOST_NAME = "0.0.0.0" + +SERVER_PORT = 80 # Maybe set this to 9000. +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# Class that handles HTTP GET requests for operations on the RPi +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +class MyHandler(BaseHTTPServer.BaseHTTPRequestHandler): + def do_GET(request): + # """Respond to a GET request.""" + + if not processURLPath(request.path): + return + + resource = request.path.split("/")[1].upper() + state = request.path.split("/")[2].upper() + print "HTTP_SERVER: Resource - " + resource + + if resource == "TEMP": + request.send_response(200) + request.send_header("Content-type", "text/plain") + request.end_headers() + request.wfile.write(iotUtils.LAST_TEMP) + + elif resource == "BULB": + iotUtils.switchBulb(state) + print "HTTP_SERVER: Requested Switch State - " + state + + elif resource == "SONAR": + request.send_response(200) + request.send_header("Content-type", "text/plain") + request.end_headers() + request.wfile.write(iotUtils.LAST_DISTANCE) + + print '~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~' +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# Check the URL string of the request and validate +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +def processURLPath(path): + if path.count("/") != 2 and not "favicon" in path: + print "HTTP_SERVER: Invalid URL String: " + path + return False + + resource = path.split("/")[1] + + if not iequal("BULB", resource) and not iequal("TEMP", resource) and not iequal("FAN", resource) and not iequal("SONAR", resource): + if not "favicon" in resource: + print "HTTP_SERVER: Invalid resource - " + resource + " to execute operation" + return False + + return True +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# Case-Insensitive check on whether two string are similar +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +def iequal(a, b): + try: + return a.upper() == b.upper() + except AttributeError: + return a == b +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# The Main method of the server script +# This method is invoked from RaspberryStats.py on a new thread +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +def main(): + HOST_NAME = iotUtils.getDeviceIP() + server_class = BaseHTTPServer.HTTPServer + + while True: + try: + httpd = server_class((HOST_NAME, SERVER_PORT), MyHandler) + print "HTTP_SERVER: " + time.asctime(), "Server Starts - %s:%s" % (HOST_NAME, SERVER_PORT) + + httpd.serve_forever() + except (KeyboardInterrupt, Exception) as e: + print "HTTP_SERVER: Exception in HttpServerThread (either KeyboardInterrupt or Other)" + print ("HTTP_SERVER: " + str(e)) + + iotUtils.switchBulb("OFF") + httpd.server_close() + print "HTTP_SERVER: " + time.asctime(), "Server Stops - %s:%s" % (HOST_NAME, SERVER_PORT) + print '~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~' + pass + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + + +if __name__ == '__main__': + main() + diff --git a/features/device-mgt-iot-raspberrypi-feature/org.wso2.carbon.device.mgt.iot.raspberrypi.feature/src/main/resources/agent/src/iotUtils.py b/features/device-mgt-iot-raspberrypi-feature/org.wso2.carbon.device.mgt.iot.raspberrypi.feature/src/main/resources/agent/src/iotUtils.py new file mode 100755 index 0000000000..bd9faea404 --- /dev/null +++ b/features/device-mgt-iot-raspberrypi-feature/org.wso2.carbon.device.mgt.iot.raspberrypi.feature/src/main/resources/agent/src/iotUtils.py @@ -0,0 +1,200 @@ +#!/usr/bin/env python + +""" +/** +* Copyright (c) 2015, 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. +**/ +""" + +import time, commands +import RPi.GPIO as GPIO +import ConfigParser + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# HOST_NAME(IP) of the Device +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +global HOST_NAME +HOST_NAME = "0.0.0.0" +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +global LAST_TEMP +LAST_TEMP = 25 # The Last read temperature value from the DHT sensor. Kept globally + # Updated by the temperature reading thread + +global LAST_DISTANCE +LAST_DISTANCE = 100 + +SONAR_TRIG_PIN = 16 #Associate pin 23 to TRIG +SONAR_ECHO_PIN = 18 +BULB_PIN = 11 # The GPIO Pin# in RPi to which the LED is connected + + + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# Device specific info when pushing data to server +# Read from a file "deviceConfigs.cfg" in the same folder level +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +configParser = ConfigParser.RawConfigParser() +configFilePath = r'./deviceConfigs.cfg' +configParser.read(configFilePath) + +DEVICE_OWNER = configParser.get('Device-Configurations', 'owner') +DEVICE_ID = configParser.get('Device-Configurations', 'deviceId') +MQTT_EP = configParser.get('Device-Configurations', 'mqtt-ep') +XMPP_EP = configParser.get('Device-Configurations', 'xmpp-ep') +AUTH_TOKEN = configParser.get('Device-Configurations', 'auth-token') + +DEVICE_INFO = '{"owner":"'+ DEVICE_OWNER + '","deviceId":"' + DEVICE_ID + '","reply":' +DEVICE_IP = '"{ip}","value":' +DEVICE_DATA = '"{temperature}"' # '"{temperature}:{load}:OFF"' +### ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# Method used to switch ON/OFF the LED attached to RPi +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +def switchBulb(state): + print "Requested Switch State: " + state + + if state == "ON": + GPIO.output(BULB_PIN, True) + print "BULB Switched ON" + elif state == "OFF": + GPIO.output(BULB_PIN, False) + print "BULB Switched OFF" + + print '~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~' +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# Get the wlan0 interface via which the RPi is connected +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +def getDeviceIP(): + rPi_IP = commands.getoutput("ip route list | grep 'src '").split() + rPi_IP = rPi_IP[rPi_IP.index('src') + 1] + + if len(rPi_IP)<=16: + print "------------------------------------------------------------------------------------" + print "IOT_UTILS: IP Address of RaspberryPi: " + rPi_IP + print "------------------------------------------------------------------------------------" + return rPi_IP +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# Set the GPIO pin modes for the ones to be read +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +def setUpGPIOPins(): + try: + GPIO.setwarnings(False) + GPIO.setmode(GPIO.BOARD) + except Exception as e: + print "IOT_UTILS: Exception at 'GPIO.setmode'" + print '~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~' + pass + + GPIO.setup(SONAR_TRIG_PIN,GPIO.OUT) #Set pin as GPIO out + GPIO.setup(SONAR_ECHO_PIN,GPIO.IN) #Set pin as GPIO in + GPIO.setup(BULB_PIN, GPIO.OUT) + GPIO.output(BULB_PIN, False) +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# This method get the CPU Temperature of the Raspberry Pi +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +def getCPUTemp(): + CPU_TEMP_LOC = "/sys/class/thermal/thermal_zone0/temp" # RaspberryPi file location to get CPU TEMP info + tempFile = open(CPU_TEMP_LOC) + cpuTemp = tempFile.read() + cpuTemp = long(float(cpuTemp)) + cpuTemp = cpuTemp * 1.0 / 1000.0 + print "The CPU temperature is: %.2f" % cpuTemp + return cpuTemp +### ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# This method get the CPU Load of the Raspberry Pi +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +def getCPULoad(): + CPU_LOAD_LOC = "/proc/loadavg" # RaspberryPi file location to get CPU LOAD info + loadFile = open(CPU_LOAD_LOC) + cpuLoad = loadFile.read() + cpuLoad = cpuLoad.split()[0] + cpuLoad = long(float(cpuLoad)) + print "The CPU temperature is: %.2f" % cpuLoad + return cpuLoad +### ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +def readSonarDistance(): + global LAST_DISTANCE + try: + GPIO.output(SONAR_TRIG_PIN, False) #Set TRIG as LOW + print "IOT_UTILS: Waitng For Sonar Sensor To Settle" + time.sleep(0.5) #Delay of 2 seconds + + GPIO.output(SONAR_TRIG_PIN, True) #Set TRIG as HIGH + time.sleep(0.00001) #Delay of 0.00001 seconds + GPIO.output(SONAR_TRIG_PIN, False) #Set TRIG as LOW + + while GPIO.input(SONAR_ECHO_PIN)==0: #Check whether the ECHO is LOW + pulse_start = time.time() #Saves the last known time of LOW pulse + + while GPIO.input(SONAR_ECHO_PIN)==1: #Check whether the ECHO is HIGH + pulse_end = time.time() #Saves the last known time of HIGH pulse + + pulse_duration = pulse_end - pulse_start #Get pulse duration to a variable + + distance = pulse_duration * 17150 #Multiply pulse duration by 17150 to get distance + distance = round(distance, 2) #Round to two decimal points + + if distance > 2 and distance < 400: #Check whether the distance is within range + print "IOT_UTILS: Distance: ", distance - 0.5,"cm" #Print distance with 0.5 cm calibration + LAST_DISTANCE = distance + else: + print "IOT_UTILS: Out Of Range" #display out of range + + except Exception, e: + print "IOT_UTILS: Exception in SonarReaderThread: Could not successfully read Sonar" + print ("IOT_UTILS: " + str(e)) + print '~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~' + + + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# The Main method of the server script +# This method is invoked from RaspberryStats.py on a new thread +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +def main(): + global HOST_NAME + HOST_NAME = getDeviceIP() + setUpGPIOPins() + + while True: + readSonarDistance() + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +if __name__ == '__main__': + main() + diff --git a/features/device-mgt-iot-raspberrypi-feature/org.wso2.carbon.device.mgt.iot.raspberrypi.feature/src/main/resources/agent/src/mqttListener.py b/features/device-mgt-iot-raspberrypi-feature/org.wso2.carbon.device.mgt.iot.raspberrypi.feature/src/main/resources/agent/src/mqttListener.py new file mode 100755 index 0000000000..e36d0eee79 --- /dev/null +++ b/features/device-mgt-iot-raspberrypi-feature/org.wso2.carbon.device.mgt.iot.raspberrypi.feature/src/main/resources/agent/src/mqttListener.py @@ -0,0 +1,109 @@ +#!/usr/bin/env python + +""" +/** +* Copyright (c) 2015, 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. +**/ +""" + +import time +import iotUtils +#import RPi.GPIO as GPIO +import paho.mqtt.client as mqtt + + +# The callback for when the client receives a CONNACK response from the server. +def on_connect(client, userdata, flags, rc): + print("MQTT_LISTENER: Connected with result code " + str(rc)) + + # Subscribing in on_connect() means that if we lose the connection and + # reconnect then subscriptions will be renewed. + print ("MQTT_LISTENER: Subscribing with topic " + TOPIC) + client.subscribe(TOPIC) + + + +# The callback for when a PUBLISH message is received from the server. +def on_message(client, userdata, msg): + print( "MQTT_LISTENER: " + msg.topic + " " + str(msg.payload) ) + + request = str(msg.payload) + + resource = request.split(":")[0].upper() + state = request.split(":")[1].upper() + + print "MQTT_LISTENER: Resource- " + resource + + if resource == "TEMP": + pass + #request.send_response(200) + #request.send_header("Content-type", "text/plain") + #request.end_headers() + #request.wfile.write(LAST_TEMP) + # return + + elif resource == "BULB": + iotUtils.switchBulb(state) + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# The Main method of the server script +# This method is invoked from RaspberryStats.py on a new thread +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +def main(): + + MQTT_ENDPOINT = iotUtils.MQTT_EP.split(":") + MQTT_IP = MQTT_ENDPOINT[0] + MQTT_PORT = MQTT_ENDPOINT[1] + + DEV_OWNER = iotUtils.DEVICE_OWNER + DEV_ID = iotUtils.DEVICE_ID + + global TOPIC + TOPIC = "wso2/iot/" + DEV_OWNER + "/firealarm/" + DEV_ID + + print ("MQTT_LISTENER: MQTT_ENDPOINT is " + str(MQTT_ENDPOINT)) + print ("MQTT_LISTENER: MQTT_TOPIC is " + TOPIC) + + mqttClient = mqtt.Client() + mqttClient.on_connect = on_connect + mqttClient.on_message = on_message + + while True: + try: + mqttClient.connect(MQTT_IP, MQTT_PORT, 60) + print "MQTT_LISTENER: " + time.asctime(), "Connected to MQTT Broker - %s:%s" % (MQTT_IP, MQTT_PORT) + + # Blocking call that processes network traffic, dispatches callbacks and + # handles reconnecting. + # Other loop*() functions are available that give a threaded interface and a + # manual interface. + mqttClient.loop_forever() + + except (KeyboardInterrupt, Exception) as e: + print "MQTT_LISTENER: Exception in MQTTServerThread (either KeyboardInterrupt or Other)" + print ("MQTT_LISTENER: " + str(e)) + + mqttClient.disconnect() + print "MQTT_LISTENER: " + time.asctime(), "Connection to Broker closed - %s:%s" % (MQTT_IP, MQTT_PORT) + print '~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~' + pass + + +if __name__ == '__main__': + iotUtils.setUpGPIOPins() + main() + diff --git a/features/device-mgt-iot-raspberrypi-feature/org.wso2.carbon.device.mgt.iot.raspberrypi.feature/src/main/resources/agent/src/org.eclipse.paho.mqtt.python.tar b/features/device-mgt-iot-raspberrypi-feature/org.wso2.carbon.device.mgt.iot.raspberrypi.feature/src/main/resources/agent/src/org.eclipse.paho.mqtt.python.tar new file mode 100644 index 0000000000..5f65105b8f Binary files /dev/null and b/features/device-mgt-iot-raspberrypi-feature/org.wso2.carbon.device.mgt.iot.raspberrypi.feature/src/main/resources/agent/src/org.eclipse.paho.mqtt.python.tar differ diff --git a/features/device-mgt-iot-raspberrypi-feature/org.wso2.carbon.device.mgt.iot.raspberrypi.feature/src/main/resources/agent/src/xmppServer.py b/features/device-mgt-iot-raspberrypi-feature/org.wso2.carbon.device.mgt.iot.raspberrypi.feature/src/main/resources/agent/src/xmppServer.py new file mode 100755 index 0000000000..199d145734 --- /dev/null +++ b/features/device-mgt-iot-raspberrypi-feature/org.wso2.carbon.device.mgt.iot.raspberrypi.feature/src/main/resources/agent/src/xmppServer.py @@ -0,0 +1,145 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +""" +/* + * Copyright (c) 2014, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * Licensed 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. + */ +""" + +import sleekxmpp +import getpass +import sys +import ssl, pyasn1 + +from urllib import urlopen +import iotUtils + +# Python versions before 3.0 do not use UTF-8 encoding +# by default. To ensure that Unicode is handled properly +# throughout SleekXMPP, we will set the default encoding +# ourselves to UTF-8. +if sys.version_info < (3, 0): + from sleekxmpp.util.misc_ops import setdefaultencoding + setdefaultencoding('utf8') +else: + raw_input = input + +from sleekxmpp.plugins.xep_0323.device import Device + +class IoT_TestDevice(sleekxmpp.ClientXMPP): + """ + A simple IoT device that can act as server or client + """ + def __init__(self, jid, password): + sleekxmpp.ClientXMPP.__init__(self, jid, password) + self.add_event_handler("session_start", self.session_start) + self.add_event_handler("message", self.message) + self.device=None + self.releaseMe=False + self.beServer=True + + def beClientOrServer(self,server=True,clientJID=None ): + self.beServer=True + + def testForRelease(self): + # todo thread safe + return self.releaseMe + + def doReleaseMe(self): + # todo thread safe + self.releaseMe=True + + def addDevice(self, device): + self.device=device + + def session_start(self, event): + self.send_presence() + self.get_roster() + # tell your preffered friend that you are alive + #self.send_message(mto='jocke@jabber.sust.se', mbody=self.boundjid.bare +' is now online use xep_323 stanza to talk to me') + + def message(self, msg): + if msg['type'] in ('chat', 'normal'): + print ("XMPP_SERVER: Got normal chat message" + str(msg)) + ip = urlopen('http://icanhazip.com').read() + msg.reply("XMPP_SERVER: Hi I am " + self.boundjid.full + " and I am on IP " + ip).send() + else: + print ("XMPP_SERVER: Got unknown message type %s", str(msg['type'])) + +class TheDevice(Device): + """ + This is the actual device object that you will use to get information from your real hardware + You will be called in the refresh method when someone is requesting information from you + """ + def __init__(self,nodeId): + Device.__init__(self,nodeId) + + def refresh(self,fields): + """ + the implementation of the refresh method + """ +# global LAST_TEMP + #self._set_momentary_timestamp(self._get_timestamp()) + #self._add_field_momentary_data(self, "Temperature", self.counter) + + self._add_field(name="Temperature", typename="numeric", unit="C") + self._set_momentary_timestamp(self._get_timestamp()) + self._add_field_momentary_data("Temperature", str(iotUtils.LAST_TEMP), flags={"automaticReadout": "true"}) + +def main(): + XMPP_ENDP = iotUtils.XMPP_EP.split(":")[0] + + XMPP_OWN = iotUtils.DEVICE_OWNER + XMPP_JID = iotUtils.DEVICE_ID + "@" + XMPP_ENDP + "/raspi" + XMPP_PWD = iotUtils.AUTH_TOKEN + + print "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" + print "XMPP_SERVER: Owner - " + XMPP_OWN + print "XMPP_SERVER: AccountID - " + XMPP_JID + print "XMPP_SERVER: AccountPass - " + XMPP_PWD + print "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" + + xmpp = IoT_TestDevice(XMPP_JID,XMPP_PWD) + xmpp.ssl_version = ssl.PROTOCOL_SSLv3 + + xmpp.register_plugin('xep_0030') + xmpp.register_plugin('xep_0323') + xmpp.register_plugin('xep_0325') + + if XMPP_OWN: + # xmpp['xep_0030'].add_feature(feature='urn:xmpp:sn', + # node=opts.nodeid, + # jid=xmpp.boundjid.full) + + myDevice = TheDevice(XMPP_OWN) + # myDevice._add_field(name="Relay", typename="numeric", unit="Bool"); + myDevice._add_field(name="Temperature", typename="numeric", unit="C") + myDevice._set_momentary_timestamp("2013-03-07T16:24:30") + myDevice._add_field_momentary_data("Temperature", "23.4", flags={"automaticReadout": "true"}) + + xmpp['xep_0323'].register_node(nodeId=XMPP_OWN, device=myDevice, commTimeout=10) + xmpp.beClientOrServer(server=True) + + while not(xmpp.testForRelease()): + try: + xmpp.connect() + xmpp.process(block=True) + print ("XMPP_SERVER: Lost Connection") + except Exception as e: + print "XMPP_SERVER: Exception in XMPPServerThread (either KeyboardInterrupt or Other)" + print ("XMPP_SERVER: " + str(e)) + +if __name__ == '__main__': + main() diff --git a/features/device-mgt-iot-raspberrypi-feature/org.wso2.carbon.device.mgt.iot.raspberrypi.feature/src/main/resources/agent/startservice.sh b/features/device-mgt-iot-raspberrypi-feature/org.wso2.carbon.device.mgt.iot.raspberrypi.feature/src/main/resources/agent/startservice.sh new file mode 100755 index 0000000000..321e973c9f --- /dev/null +++ b/features/device-mgt-iot-raspberrypi-feature/org.wso2.carbon.device.mgt.iot.raspberrypi.feature/src/main/resources/agent/startservice.sh @@ -0,0 +1,94 @@ +#!/bin/bash + +echo "----------------------------------------------------------------" +echo "| WSO2 IOT Sample " +echo "| RaspiAlarm " +echo "| ---------------- " +echo "| ....initializing startup-script " +echo "----------------------------------------------------------------" + +currentDir=$PWD + +cd /var/lib/dpkg/info +sudo rm -rf wso2-raspi-alarm* +dpkg --remove --force-remove-reinstreq wso2-raspi-alarm + +while true; do + read -p "Do you wish to run 'apt-get update' and continue? [Yes/No] " yn + case $yn in + [Yy]* ) sudo apt-get update; + break;; + [Nn]* ) echo "Continuing without apt-get update..."; + break;; + * ) echo "Please answer yes or no."; + esac +done + +if [ $? -ne 0 ]; then + echo "apt-get update failed.... Some dependencies may not get installed" + echo "If an already installed version of the package exists, try running:" + echo "----------------------------------------------------------------" + echo "sudo -i" + echo "cd /var/lib/dpkg/info" + echo "rm -rf wso2-raspi-alarm*" + echo "dpkg --remove --force-remove-reinstreq wso2-raspi-alarm" + echo "exit" + echo "----------------------------------------------------------------" + echo "Retry Installation...." + break; +fi + + +for f in ./deviceConfigs.cfg; do + ## Check if the glob gets expanded to existing files. + ## If not, f here will be exactly the pattern above + ## and the exists test will evaluate to false. + # [ -e "$f" ] && echo "'wso2-raspi-alarm_1.0_armhf.deb' file found and installing" || echo "'wso2-raspi-alarm_1.0_armhf.deb' file does not exist in current path"; exit; + if [ -e "$f" ]; then + echo "Configuration file found......" + else + echo "'deviceConfigs.cfg' file does not exist in current path. \nExiting installation..."; + exit; + fi + ## This is all we needed to know, so we can break after the first iteration + break +done + +cd $currentDir +git clone git://git.eclipse.org/gitroot/paho/org.eclipse.paho.mqtt.python.git +cd org.eclipse.paho.mqtt.python +sudo python setup.py install + +cd $currentDir + +#sudo apt-get install python-pip +sudo pip install sleekxmpp +sudo pip install pyasn1 pyasn1-modules + + +echo "Running the RaspberryAgent service...." +# sudo service RaspberryService.sh start + +while true; do + read -p "Whats the time-interval (in seconds) between successive Data-Pushes to the WSO2-DC (ex: '60' indicates 1 minute) > " input + + if [ $input -eq $input 2>/dev/null ] + then + echo "Setting data-push interval to $input seconds." + break; + else + echo "Input needs to be an integer indicating the number seconds between successive data-pushes." + fi +done + +sudo nohup ./RaspberryStats.py -i $input > /dev/null 2>&1 & + +if [ $? -ne 0 ]; then + echo "Could not start the service..." + exit; +fi + + +echo "--------------------------------------------------------------------------" +echo "| Successfully Started " +echo "---------------------------------------------------------------------------" diff --git a/features/device-mgt-iot-raspberrypi-feature/org.wso2.carbon.device.mgt.iot.raspberrypi.feature/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.device.type.raspberrypi.type-view/private/conf/device-type.json b/features/device-mgt-iot-raspberrypi-feature/org.wso2.carbon.device.mgt.iot.raspberrypi.feature/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.device.type.raspberrypi.type-view/private/conf/device-type.json index d7662e6a6d..5811e89ef5 100644 --- a/features/device-mgt-iot-raspberrypi-feature/org.wso2.carbon.device.mgt.iot.raspberrypi.feature/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.device.type.raspberrypi.type-view/private/conf/device-type.json +++ b/features/device-mgt-iot-raspberrypi-feature/org.wso2.carbon.device.mgt.iot.raspberrypi.feature/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.device.type.raspberrypi.type-view/private/conf/device-type.json @@ -2,7 +2,7 @@ "deviceType": { "label": "RaspberryPi", "category": "iot", - "downloadAgentUri": "https://localhost:9443/raspberrypi/RaspberryPiDeviceManager/manager/device/raspberrypi/download", - "downloadAgentLinkGenUri" : "https://localhost:9443/raspberrypi/RaspberryPiDeviceManager/manager/device/raspberrypi/generate_link" + "downloadAgentUri": "RaspberryPiDeviceManager/manager/device/raspberrypi/download", + "downloadAgentLinkGenUri" : "RaspberryPiDeviceManager/manager/device/raspberrypi/generate_link" } } \ No newline at end of file diff --git a/features/device-mgt-iot-virtualfirealarm-feature/org.wso2.carbon.device.mgt.iot.virtualfirealarm.feature/src/main/resources/advanced_agent/deviceConfig.properties b/features/device-mgt-iot-virtualfirealarm-feature/org.wso2.carbon.device.mgt.iot.virtualfirealarm.feature/src/main/resources/advanced_agent/deviceConfig.properties index 0e2be4403e..f76a969f72 100644 --- a/features/device-mgt-iot-virtualfirealarm-feature/org.wso2.carbon.device.mgt.iot.virtualfirealarm.feature/src/main/resources/advanced_agent/deviceConfig.properties +++ b/features/device-mgt-iot-virtualfirealarm-feature/org.wso2.carbon.device.mgt.iot.virtualfirealarm.feature/src/main/resources/advanced_agent/deviceConfig.properties @@ -19,7 +19,7 @@ owner=${DEVICE_OWNER} deviceId=${DEVICE_ID} device-name=${DEVICE_NAME} -controller-context=/virtual_firealarm/controller +controller-context=/virtual_firealarm/VirtualFireAlarmDeviceManager/controller https-ep=${HTTPS_EP} http-ep=${HTTP_EP} apim-ep=${APIM_EP} diff --git a/features/device-mgt-iot-virtualfirealarm-feature/org.wso2.carbon.device.mgt.iot.virtualfirealarm.feature/src/main/resources/agent/deviceConfig.properties b/features/device-mgt-iot-virtualfirealarm-feature/org.wso2.carbon.device.mgt.iot.virtualfirealarm.feature/src/main/resources/agent/deviceConfig.properties index 0e2be4403e..f76a969f72 100644 --- a/features/device-mgt-iot-virtualfirealarm-feature/org.wso2.carbon.device.mgt.iot.virtualfirealarm.feature/src/main/resources/agent/deviceConfig.properties +++ b/features/device-mgt-iot-virtualfirealarm-feature/org.wso2.carbon.device.mgt.iot.virtualfirealarm.feature/src/main/resources/agent/deviceConfig.properties @@ -19,7 +19,7 @@ owner=${DEVICE_OWNER} deviceId=${DEVICE_ID} device-name=${DEVICE_NAME} -controller-context=/virtual_firealarm/controller +controller-context=/virtual_firealarm/VirtualFireAlarmDeviceManager/controller https-ep=${HTTPS_EP} http-ep=${HTTP_EP} apim-ep=${APIM_EP} diff --git a/pom.xml b/pom.xml index a4cbec451a..f3dbe262a3 100644 --- a/pom.xml +++ b/pom.xml @@ -48,10 +48,10 @@ components/device-mgt-iot-androidsense - + components/device-mgt-iot-arduino components/device-mgt-iot-digitaldisplay components/device-mgt-iot-droneanalyzer - + components/device-mgt-iot-raspberrypi components/device-mgt-iot-virtualfirealarm @@ -64,10 +64,10 @@ features/device-mgt-iot-androidsense-feature - + features/device-mgt-iot-arduino-feature features/device-mgt-iot-digitaldisplay-feature features/device-mgt-iot-droneanalyzer-feature - + features/device-mgt-iot-raspberrypi-feature features/device-mgt-iot-virtualfirealarm-feature