Merge pull request #60 from Shabirmean/IoTS-1.0.0-M1

Added complete RaspberryPi Component and Feature
Ruwan 9 years ago
commit 561d46a377

@ -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());
}
}
}

@ -19,5 +19,52 @@
<url-pattern>/*</url-pattern>
</servlet-mapping>
<context-param>
<param-name>isAdminService</param-name>
<param-value>false</param-value>
</context-param>
<context-param>
<param-name>doAuthentication</param-name>
<param-value>false</param-value>
</context-param>
<!--publish to apim-->
<context-param>
<param-name>managed-api-enabled</param-name>
<param-value>true</param-value>
</context-param>
<context-param>
<param-name>managed-api-owner</param-name>
<param-value>admin</param-value>
</context-param>
<context-param>
<param-name>managed-api-name</param-name>
<param-value>arduino</param-value>
</context-param>
<context-param>
<param-name>managed-api-endpoint</param-name>
<param-value>http://localhost:9763/arduino</param-value>
</context-param>
<context-param>
<param-name>managed-api-version</param-name>
<param-value>1.0.0</param-value>
</context-param>
<context-param>
<param-name>managed-api-context</param-name>
<param-value>/arduino</param-value>
</context-param>
<context-param>
<param-name>managed-api-context-template</param-name>
<param-value>/arduino/{version}</param-value>
</context-param>
<context-param>
<param-name>managed-api-application</param-name>
<param-value>arduino</param-value>
</context-param>
<context-param>
<param-name>managed-api-isSecured</param-name>
<param-value>true</param-value>
</context-param>
</web-app>

@ -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";
}

@ -0,0 +1,149 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ 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.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>device-mgt-iot-raspberrypi</artifactId>
<groupId>org.wso2.carbon.devicemgt-plugins</groupId>
<version>1.9.2-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>org.wso2.carbon.device.mgt.iot.raspberrypi.service.impl</artifactId>
<version>1.9.2-SNAPSHOT</version>
<packaging>war</packaging>
<name>WSO2 Carbon - IoT Server RaspberryPi API</name>
<description>WSO2 Carbon - RaspberryPi Service API Implementation</description>
<url>http://wso2.org</url>
<dependencies>
<!-- CDM -->
<dependency>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>org.wso2.carbon.device.mgt.common</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>org.wso2.carbon.device.mgt.core</artifactId>
<scope>provided</scope>
<exclusions>
<exclusion>
<groupId>org.apache.axis2.wso2</groupId>
<artifactId>axis2-client</artifactId>
</exclusion>
</exclusions>
</dependency>
<!--CXF -->
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-frontend-jaxws</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-frontend-jaxrs</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-transports-http</artifactId>
<scope>provided</scope>
</dependency>
<!--MQTT -->
<dependency>
<groupId>org.eclipse.paho</groupId>
<artifactId>mqtt-client</artifactId>
<scope>provided</scope>
</dependency>
<!--IOT -->
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpasyncclient</artifactId>
<version>4.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.wso2.carbon.devicemgt-plugins</groupId>
<artifactId>org.wso2.carbon.device.mgt.iot</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.wso2.carbon.devicemgt-plugins</groupId>
<artifactId>org.wso2.carbon.device.mgt.iot.raspberrypi.plugin.impl</artifactId>
<scope>provided</scope>
</dependency>
<!--JAX-RS -->
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-core-asl</artifactId>
</dependency>
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-jaxrs</artifactId>
</dependency>
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-web-api</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.ws.rs</groupId>
<artifactId>jsr311-api</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>org.wso2.carbon.device.mgt.analytics</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<encoding>UTF-8</encoding>
<source>${wso2.maven.compiler.source}</source>
<target>${wso2.maven.compiler.target}</target>
</configuration>
</plugin>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<configuration>
<warName>raspberrypi</warName>
</configuration>
</plugin>
</plugins>
</build>
</project>

@ -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<String, String> 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<Device> userDevices = deviceManagement.getDeviceManagementService().getDevicesOfUser(username);
ArrayList<Device> 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());
}
}
}

@ -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;
}

@ -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);
}
}

@ -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();
}
}

@ -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<HttpResponse> future = httpclient.execute(
request, new FutureCallback<HttpResponse>() {
@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;
}
}

@ -0,0 +1,33 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<!--
~ Copyright 2005-2013 WSO2, Inc. (http://wso2.com)
~
~ 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.
-->
<!--
This file defines class loading policy of the whole container. But this behaviour can be overridden by individual webapps by putting this file into the META-INF/ directory.
-->
<Classloading xmlns="http://wso2.org/projects/as/classloading">
<!-- Parent-first or child-first. Default behaviour is child-first.-->
<ParentFirst>false</ParentFirst>
<!--
Default environments that contains provides to all the webapps. This can be overridden by individual webapps by specifing required environments
Tomcat environment is the default and every webapps gets it even if they didn't specify it.
e.g. If a webapps requires CXF, they will get both Tomcat and CXF.
-->
<Environments>CXF,Carbon</Environments>
</Classloading>

@ -0,0 +1,48 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ 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.
-->
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jaxrs="http://cxf.apache.org/jaxrs"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://cxf.apache.org/jaxrs http://cxf.apache.org/schemas/jaxrs.xsd">
<jaxrs:server id="RaspberryPi" address="/">
<jaxrs:serviceBeans>
<bean id="RaspberryPiService"
class="org.wso2.carbon.device.mgt.iot.raspberrypi.service.RaspberryPiService">
<property name="raspberryPiMQTTSubscriber" ref="mqttSubscriberBean"/>
</bean>
</jaxrs:serviceBeans>
<jaxrs:providers>
<bean class="org.codehaus.jackson.jaxrs.JacksonJsonProvider"/>
</jaxrs:providers>
</jaxrs:server>
<bean id="mqttSubscriberBean"
class="org.wso2.carbon.device.mgt.iot.raspberrypi.service.transport.RaspberryPiMQTTSubscriber">
</bean>
</beans>

@ -0,0 +1,70 @@
<?xml version="1.0" encoding="utf-8"?>
<web-app version="2.5"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
metadata-complete="true">
<display-name>RaspberryPi</display-name>
<description>RaspberryPi</description>
<servlet>
<servlet-name>CXFServlet</servlet-name>
<servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>CXFServlet</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
<context-param>
<param-name>isAdminService</param-name>
<param-value>false</param-value>
</context-param>
<context-param>
<param-name>doAuthentication</param-name>
<param-value>false</param-value>
</context-param>
<!--publish to apim-->
<context-param>
<param-name>managed-api-enabled</param-name>
<param-value>true</param-value>
</context-param>
<context-param>
<param-name>managed-api-owner</param-name>
<param-value>admin</param-value>
</context-param>
<context-param>
<param-name>managed-api-name</param-name>
<param-value>raspberrypi</param-value>
</context-param>
<context-param>
<param-name>managed-api-endpoint</param-name>
<param-value>http://localhost:9763/raspberrypi</param-value>
</context-param>
<context-param>
<param-name>managed-api-version</param-name>
<param-value>1.0.0</param-value>
</context-param>
<context-param>
<param-name>managed-api-context</param-name>
<param-value>/raspberrypi</param-value>
</context-param>
<context-param>
<param-name>managed-api-context-template</param-name>
<param-value>/raspberrypi/{version}</param-value>
</context-param>
<context-param>
<param-name>managed-api-application</param-name>
<param-value>raspberrypi</param-value>
</context-param>
<context-param>
<param-name>managed-api-isSecured</param-name>
<param-value>true</param-value>
</context-param>
</web-app>

@ -37,7 +37,7 @@
<modules>
<module>org.wso2.carbon.device.mgt.iot.raspberrypi.plugin.impl</module>
<!--<module>org.wso2.carbon.device.mgt.iot.raspberrypi.service.impl</module>-->
<module>org.wso2.carbon.device.mgt.iot.raspberrypi.service.impl</module>
</modules>
<build>

@ -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<String, String> 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,14 +150,26 @@ public class VirtualFireAlarmService {
xmppStarterThread.start();
}
/**
*
* @return
*/
public VerificationManager getVerificationManager() {
return verificationManager;
}
/**
*
* @return
*/
public VirtualFireAlarmXMPPConnector getVirtualFireAlarmXMPPConnector() {
return virtualFireAlarmXMPPConnector;
}
/**
*
* @return
*/
public VirtualFireAlarmMQTTSubscriber getVirtualFireAlarmMQTTSubscriber() {
return virtualFireAlarmMQTTSubscriber;
}
@ -160,6 +178,14 @@ public class VirtualFireAlarmService {
Device management specific 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) {

@ -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();
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) {

@ -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);
}

@ -3,18 +3,18 @@
<IotDeviceTypeConfig type="android_sense">
<DatasourceName>jdbc/AndroidSenseDM_DB</DatasourceName>
</IotDeviceTypeConfig>
<!--<IotDeviceTypeConfig type="arduino">-->
<!--<DatasourceName>jdbc/ArduinoDM_DB</DatasourceName>-->
<!--</IotDeviceTypeConfig>-->
<IotDeviceTypeConfig type="arduino">
<DatasourceName>jdbc/ArduinoDM_DB</DatasourceName>
</IotDeviceTypeConfig>
<IotDeviceTypeConfig type="digital_display">
<DatasourceName>jdbc/DigitalDisplayDM_DB</DatasourceName>
</IotDeviceTypeConfig>
<IotDeviceTypeConfig type="drone_analyzer">
<DatasourceName>jdbc/DroneAnalyzerDM_DB</DatasourceName>
</IotDeviceTypeConfig>
<!--<IotDeviceTypeConfig type="raspberrypi">-->
<!--<DatasourceName>jdbc/RaspberryPiDM_DB</DatasourceName>-->
<!--</IotDeviceTypeConfig>-->
<IotDeviceTypeConfig type="raspberrypi">
<DatasourceName>jdbc/RaspberryPiDM_DB</DatasourceName>
</IotDeviceTypeConfig>
<IotDeviceTypeConfig type="virtual_firealarm">
<DatasourceName>jdbc/VirtualFireAlarmDM_DB</DatasourceName>
<!--TODO: Uncomment this to work with apim @ 192.168.67.21 -->

@ -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 &

@ -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

@ -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()

@ -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

@ -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()

@ -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()

@ -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()

@ -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()

@ -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 "---------------------------------------------------------------------------"

@ -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"
}
}

@ -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}

@ -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}

@ -48,10 +48,10 @@
<!--Device Specific IoT Components-->
<module>components/device-mgt-iot-androidsense</module>
<!--<module>components/device-mgt-iot-arduino</module>-->
<module>components/device-mgt-iot-arduino</module>
<module>components/device-mgt-iot-digitaldisplay</module>
<module>components/device-mgt-iot-droneanalyzer</module>
<!--<module>components/device-mgt-iot-raspberrypi</module>-->
<module>components/device-mgt-iot-raspberrypi</module>
<module>components/device-mgt-iot-virtualfirealarm</module>
<!--Core MDM and IoT Features-->
@ -64,10 +64,10 @@
<!--Device specific IoT Features-->
<module>features/device-mgt-iot-androidsense-feature</module>
<!--<module>features/device-mgt-iot-arduino-feature</module>-->
<module>features/device-mgt-iot-arduino-feature</module>
<module>features/device-mgt-iot-digitaldisplay-feature</module>
<module>features/device-mgt-iot-droneanalyzer-feature</module>
<!--<module>features/device-mgt-iot-raspberrypi-feature</module>-->
<module>features/device-mgt-iot-raspberrypi-feature</module>
<module>features/device-mgt-iot-virtualfirealarm-feature</module>
</modules>

Loading…
Cancel
Save