NOTE AND DISCLAIMER
Please be aware that this blog post will not provide you with code that you should use productively. It actually is focusing on getting an app up-and-running for demo purposes.
So take this whole blog post series and its sample code AS IS and with the purpose it was build: to inspire you to think about other IoT (Internet of Things) scenarios you could run on the SAP HANA Cloud Platform and NOT as a best practice for productive environments.
package org.persistence;
import static javax.persistence.GenerationType.AUTO;
import java.io.Serializable;
import java.sql.Timestamp;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
@Entity
@NamedQueries({
@NamedQuery(name = "AllMeasurements", query = "select m from Measurement m"),
@NamedQuery(name = "LastSensorReading", query = "select m from Measurement m where m.sensorId = :paramSensorId and m.storedAt = (SELECT MAX(r.storedAt) from Measurement r where r.sensorId = :paramSensorId)"),
@NamedQuery(name = "LastReadingsFromSensor", query = "select p from Measurement p where p.sensorId = :paramSensorId order by p.storedAt DESC") })
public class Measurement implements Serializable {
private static final long serialVersionUID = 1L;
public Measurement() {}
@Id
@GeneratedValue(strategy = AUTO)
private Long id;
private String unit;
private Timestamp storedAt;
private Double value;
private long sensorId;
public Long getId() {return id;}
public void setId(Long id) {this.id = id;}
public String getUnit() {return unit;}
public void setUnit(String unit) {this.unit = unit;}
public Timestamp getStoredAt() {return storedAt;}
public void setStoredAt(Timestamp dateStored) {this.storedAt = dateStored;}
public Double getValue() {return value;}
public void setValue(Double sensorValue) {this.value = sensorValue;}
public static long getSerialversionuid() {return serialVersionUID;}
public long getSensorId() {return sensorId;}
public void setSensorId(long param) {this.sensorId = param;}
}
package org.persistence;
import java.io.Serializable;
import javax.persistence.*;
import org.persistence.Measurement;
import java.util.Collection;
import static javax.persistence.GenerationType.AUTO;
@Entity
@NamedQueries({ @NamedQuery(name = "GetListOfSensors", query = "select s from Sensor s") })
public class Sensor implements Serializable {
private static final long serialVersionUID = 1L;
public Sensor() { }
@Id
@GeneratedValue(strategy = AUTO)
private long id;
private String device;
private String type;
private String description;
private Measurement lastMeasurement;
@OneToMany
private Collection<Measurement> measurements;
public Measurement getLastMeasurement() {return lastMeasurement;}
public void setLastMeasurement(Measurement lastMeasurement) {this.lastMeasurement = lastMeasurement;}
public long getId() {return id;}
public void setId(long id) {this.id = id;}
public String getDevice() {return device;}
public void setDevice(String param) {this.device = param;}
public String getType() {return type;}
public void setType(String param) {this.type = param;}
public String getDescription() {return description;}
public void setDescription(String param) {this.description = param;}
public Collection<Measurement> getMeasurement() {return measurements;}
public void setMeasurement(Collection<Measurement> param) {this.measurements = param;}
}
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
<persistence-unit name="iotscenario">
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
<class>org.persistence.Measurement</class>
<class>org.persistence.Sensor</class>
<properties>
<property name="eclipselink.ddl-generation" value="create-tables"/>
</properties>
</persistence-unit>
</persistence>
emf = Persistence.createEntityManagerFactory("iotscenario", properties);
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">
<display-name>iotscenario</display-name>
<resource-ref>
<res-ref-name>jdbc/DefaultDB</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
</resource-ref>
<servlet>
<description></description>
<display-name>SensorsServlet</display-name>
<servlet-name>SensorsServlet</servlet-name>
<servlet-class>com.sap.iot.sensors.SensorsServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>SensorsServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
<resource-ref>
<res-ref-name>jdbc/DefaultDB</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
</resource-ref>
<servlet>
<description></description>
<display-name>SensorsServlet</display-name>
<servlet-name>SensorsServlet</servlet-name>
<servlet-class>com.sap.iot.sensors.SensorsServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>SensorsServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
https://<name of your application><your account name>.hanatrial.ondemand.com/<name of your project>/?action=addsensor&type=temperature&device=Truck 1- RaspPi&description=RaspberryPi CPU
https://fishimportp1234567890trial.hanatrial.ondemand.com/iotscenario/?action=addsensor&type=temperature&device=Truck 1- RaspPi&description=RaspberryPi CPU
{
"sensor0":
{"id":1,"device":"Truck 1 - RaspPi","type":"temperature","description":"RaspberryPi CPU","measurements":[]}
}
https://fishimportp1234567890trial.hanatrial.ondemand.com/iotscenario/?action=addsensorvalue&sensorid=1&unit=Celsius&sensorvalue=16&sensorvaluemultiplier=0.1&sensorvaluecalibration=0
{
"id":1,"device":"Truck 1 - RaspPi","type":"temperature","description":"RaspberryPi CPU",
"lastMeasurement":
{"id":1,"unit":"Celsius","storedAt":"Nov 10, 2014 9:53:13 AM","value":-1.6,"sensorId":1},
"measurements":
[
{"id":1,"unit":"Celsius","storedAt":"Nov 10, 2014 9:53:13 AM","value":-1.1,"sensorId":1}
]
}
package com.sap.iot.sensors;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Query;
import org.persistence.Measurement;
import org.persistence.Sensor;
public class DataHelper {
private EntityManagerFactory emf;
public DataHelper(EntityManagerFactory emf) {
this.emf = emf;
}
/*
* Persists a measured sensor value (measurement)
*
* @param measurement The measured sensor value
*/
public boolean addMeasurement(Measurement measurement) {
boolean result = false;
EntityManager em = emf.createEntityManager();
// System.out.println("Trying to commit sensor data for sensor " +
// measurement.getSensorDescription());
try {
if (measurement != null && measurement.getValue() != null) {
em.getTransaction().begin();
em.persist(measurement);
em.getTransaction().commit();
}
} catch (Exception e) {
System.out.println("ERROR: persisting measurement didn't work " + e.getMessage());
} finally {
em.close();
}
return result;
}
/*
* Persists a new sensor
*
* @param sensor The sensor object to be added
*/
public boolean addSensor(Sensor sensor) {
boolean result = false;
if (sensor != null) {
EntityManager em = emf.createEntityManager();
try {
em.getTransaction().begin();
em.persist(sensor);
em.getTransaction().commit();
result = true;
} catch (Exception e) {
System.out.println("ERROR: persisting sensor didn't work " + e.getMessage());
result = false;
}
em.close();
}
return result;
}
/*
* Provides a list of a defined number of sensor readings for a specific
* sensor. The method will provide the newest sensor readings (measurements)
* first
*
* @param sensorId The sensor id of the sensor that you wish to get the
* measured values from
*
* @param numberOfReadings The maximum number of readings you'll get back
*/
@SuppressWarnings("unchecked")
public List<Measurement> getLastSensorReadings(long sensorId, int numberOfReadings) {
List<Measurement> result = null;
EntityManager em = emf.createEntityManager();
try {
Query q = em.createNamedQuery("LastReadingsFromSensor");
q.setParameter("paramSensorId", sensorId);
// To not affect performance we just retrieve the first 20 result
// sets
q.setMaxResults(numberOfReadings);
result = q.getResultList();
Collections.sort(result, new Comparator<Measurement>() {
public int compare(Measurement m1, Measurement m2) {
return m1.getStoredAt().compareTo(m2.getStoredAt());
}
});
} catch (Exception e) {
}
em.close();
return result;
}
/*
* Provides a list of ALL sensor readings. To avoid too many data the output
* is restricted to a maximum of 500 entries
*/
@SuppressWarnings("unchecked")
public List<Measurement> getAllSensorReadings() {
List<Measurement> result = null;
EntityManager em = emf.createEntityManager();
try {
Query q = em.createNamedQuery("AllMeasurements");
q.setMaxResults(500);
result = q.getResultList();
} catch (Exception e) {
}
em.close();
return result;
}
/*
* Provides the last measured sensor value for a sensor
*
* @param sensorId The sensor id of the sensor that you wish to get the
* measured value from
*/
public Measurement getLastSensorReading(long sensorId) {
Measurement result = null;
EntityManager em = emf.createEntityManager();
try {
Query q = em.createNamedQuery("LastSensorReading");
q.setParameter("paramSensorId", sensorId);
result = (Measurement) q.getSingleResult();
} catch (Exception e) {
}
em.close();
return result;
}
/*
* Provides a list of all sensors
*/
@SuppressWarnings("unchecked")
public List<Sensor> getListOfSensors() {
List<Sensor> result = null;
EntityManager em = emf.createEntityManager();
try {
Query q = em.createNamedQuery("GetListOfSensors");
result = q.getResultList();
} catch (Exception e) {
}
em.close();
return result;
}
}
package com.sap.iot.sensors;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.sql.Timestamp;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.sql.DataSource;
import org.eclipse.persistence.config.PersistenceUnitProperties;
import org.persistence.Measurement;
import org.persistence.Sensor;
import com.google.gson.Gson;
import com.sap.security.core.server.csi.IXSSEncoder;
import com.sap.security.core.server.csi.XSSEncoder;
/**
* Servlet implementation class SensorsServlet
*/
public class SensorsServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
private DataSource ds;
private EntityManagerFactory emf;
// Number of sensor readings that should be sent as response
private static final int MAX_NUMBER_SENSOR_READINGS = 10;
/**
* @see HttpServlet#HttpServlet()
*/
public SensorsServlet() {
super();
}
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse
* response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String action = encodeText(request.getParameter("action"));
DataHelper dataHelper = new DataHelper(emf);
// Add a sensor
if (action != null && action.equalsIgnoreCase("addsensor")) {
Sensor sensor = extractSensorData(request);
dataHelper.addSensor(sensor);
}
// Add a sensor value
if (action != null && action.equalsIgnoreCase("addsensorvalue")) {
Measurement measurement = extractMeasurementData(request);
dataHelper.addMeasurement(measurement);
}
// Provide a JSON output of all sensor values (measurements)
if (action != null && action.equalsIgnoreCase("showallmeasurements")) {
List<Measurement> sensorMeasurements = dataHelper.getAllSensorReadings();
outputJsonForAllMeasurements(response, sensorMeasurements);
}
// If no action parameter is provided simply print out the sensor data
// as JSON
if (action == null) {
List<Sensor> sensors = dataHelper.getListOfSensors();
// Step into each sensor and add the related measurements to it
for (int i = 0; i < sensors.size(); i++) {
Sensor sensor = sensors.get(i);
List<Measurement> sensorMeasurements = dataHelper.getLastSensorReadings(sensor.getId(), MAX_NUMBER_SENSOR_READINGS);
sensor.setMeasurement(sensorMeasurements);
Measurement sensorLastMeasurement = dataHelper.getLastSensorReading(sensor.getId());
sensor.setLastMeasurement(sensorLastMeasurement);
sensors.set(i, sensor);
}
outputJsonAllData(response, sensors);
}
}
/*
* Creates a JSON output of all sensor values (measurements)
*
* @param response The HTTP-response object
*
* @param sensorMeasurements The list of sensors values (measurements)
*/
private void outputJsonForAllMeasurements(HttpServletResponse response, List<Measurement> sensorMeasurements) {
Gson gson = new Gson();
try {
response.getWriter().println("{");
for (int i = 0; i < sensorMeasurements.size(); i++) {
response.getWriter().println(gson.toJson(sensorMeasurements.get(i)));
if (i != sensorMeasurements.size() - 1) {
response.getWriter().println(",");
}
}
response.getWriter().println("}");
} catch (IOException e) {
e.printStackTrace();
}
}
/*
* Creates a JSON output out of the provided list of sensors with their
* corresponding sensor values (measurements)
*
* @param response The HTTP-response object
*
* @param sensors The list of sensors with their respective measurements
*/
private void outputJsonAllData(HttpServletResponse response, List<Sensor> sensors) {
Gson gson = new Gson();
try {
response.getWriter().println("{");
for (int i = 0; i < sensors.size(); i++) {
response.getWriter().println('"' + "sensor" + i + '"' + ":");
response.getWriter().print(gson.toJson(sensors.get(i)));
if (i != sensors.size() - 1) {
response.getWriter().println(",");
}
}
response.getWriter().println("}");
} catch (IOException e) {
e.printStackTrace();
}
}
/*
* Extracts a Sensor object out of the parameters provided in the
* HTTP-request
*
* @param request The HTTP-request object
*
* @return The derived Sensor object
*/
private Sensor extractSensorData(HttpServletRequest request) {
Sensor sensor = new Sensor();
String idString = encodeText(request.getParameter("id"));
if (idString != null && idString.length() > 0) {
sensor.setId(Long.parseLong(idString));
}
sensor.setType(encodeText(request.getParameter("type")));
sensor.setDevice(encodeText(request.getParameter("device")));
sensor.setDescription(encodeText(request.getParameter("description")));
return sensor;
}
/*
* Extracts a Measurement object (sensor values) out of the parameters
* provided in the HTTP-request
*
* @param request The HTTP-request object
*
* @return The derived Measurement object
*/
private Measurement extractMeasurementData(HttpServletRequest request) {
Measurement measurement = new Measurement();
// Get sensorId
String sensorIdString = encodeText(request.getParameter("sensorid"));
if (sensorIdString != null && sensorIdString.length() > 0) {
measurement.setSensorId(Long.parseLong(sensorIdString));
}
// Get unit of measured value
measurement.setUnit(encodeText(request.getParameter("unit")));
// Get measured value and calculate the value to be stored
String sensorValue = encodeText(request.getParameter("sensorvalue"));
String sensorValueMultiplier = encodeText(request.getParameter("sensorvaluemultiplier"));
String sensorValueCalibration = encodeText(request.getParameter("sensorvaluecalibration"));
if (sensorValueCalibration != null && sensorValueCalibration.length() > 0 && sensorValue != null && sensorValueMultiplier != null && sensorValueMultiplier.length() > 0
&& sensorValue.length() > 0) {
measurement.setStoredAt(new Timestamp(new Date().getTime()));
Double valueDouble = Double.parseDouble(sensorValue);
Double multiplierDouble = Double.parseDouble(sensorValueMultiplier);
Double valueGap = Double.parseDouble(sensorValueCalibration);
Double value = (valueDouble * multiplierDouble) + valueGap;
measurement.setValue(value);
}
return measurement;
}
/*
* Encodes a text to avoid cross-site-scripting vulnerability
*
* @param request The text to be encoded
*
* @return The encoded String
*/
private String encodeText(String text) {
String result = null;
IXSSEncoder xssEncoder = XSSEncoder.getInstance();
try {
result = (String) xssEncoder.encodeURL(text);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return result;
}
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse
* response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doGet(request, response);
}
/** {@inheritDoc} */
@SuppressWarnings({ "rawtypes", "unchecked" })
@Override
public void init() throws ServletException {
try {
InitialContext ctx = new InitialContext();
ds = (DataSource) ctx.lookup("java:comp/env/jdbc/DefaultDB");
Map properties = new HashMap();
properties.put(PersistenceUnitProperties.NON_JTA_DATASOURCE, ds);
emf = Persistence.createEntityManagerFactory("practice", properties);
} catch (NamingException e) {
throw new ServletException(e);
}
}
/** {@inheritDoc} */
@Override
public void destroy() {
emf.close();
}
}
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
User | Count |
---|---|
40 | |
25 | |
17 | |
13 | |
7 | |
7 | |
7 | |
6 | |
6 | |
6 |