diff --git a/.classpath b/.classpath
index 6561552..210b896 100644
--- a/.classpath
+++ b/.classpath
@@ -14,7 +14,7 @@
-
+
diff --git a/bin/.gitignore b/bin/.gitignore
new file mode 100644
index 0000000..519d5f8
--- /dev/null
+++ b/bin/.gitignore
@@ -0,0 +1,3 @@
+/com/
+/maps/
+/devices/
diff --git a/bin/admin.properties b/bin/admin.properties
index 601b2b8..cfdf0bc 100644
--- a/bin/admin.properties
+++ b/bin/admin.properties
@@ -1,3 +1,3 @@
group.name = simulator
-nr.of.cars = 5
-nr.of.ambulances = 3
\ No newline at end of file
+nr.of.cars = 4
+nr.of.ambulances = 4
\ No newline at end of file
diff --git a/bin/application.properties b/bin/application.properties
index 14dd591..0a060dd 100644
--- a/bin/application.properties
+++ b/bin/application.properties
@@ -1,4 +1,4 @@
-api-key = a-0yngjl-qd4wocrack
-api-token = eA5HT)4ccFU2dULL7A
-orga-id = 0yngjl
+api-key = a-5rcpia-hxwn2ipopc
+api-token = tSzH3*7wou5pLfZd4e
+orga-id = 5rcpia
devices = devices/test-devices.json
diff --git a/bin/com/capgemini/hackathon/device/simulation/bo/Ambulance$EmergencyCommandHandler.class b/bin/com/capgemini/hackathon/device/simulation/bo/Ambulance$EmergencyCommandHandler.class
index 3a6fbc4..62d20cd 100644
Binary files a/bin/com/capgemini/hackathon/device/simulation/bo/Ambulance$EmergencyCommandHandler.class and b/bin/com/capgemini/hackathon/device/simulation/bo/Ambulance$EmergencyCommandHandler.class differ
diff --git a/bin/com/capgemini/hackathon/device/simulation/bo/Ambulance.class b/bin/com/capgemini/hackathon/device/simulation/bo/Ambulance.class
index 294217d..1b8f22e 100644
Binary files a/bin/com/capgemini/hackathon/device/simulation/bo/Ambulance.class and b/bin/com/capgemini/hackathon/device/simulation/bo/Ambulance.class differ
diff --git a/bin/com/capgemini/hackathon/device/simulation/bo/Car.class b/bin/com/capgemini/hackathon/device/simulation/bo/Car.class
index a3daf50..6dce01d 100644
Binary files a/bin/com/capgemini/hackathon/device/simulation/bo/Car.class and b/bin/com/capgemini/hackathon/device/simulation/bo/Car.class differ
diff --git a/bin/com/capgemini/hackathon/device/simulation/bo/Hospital$EmergencyDeviceCommand.class b/bin/com/capgemini/hackathon/device/simulation/bo/Hospital$EmergencyDeviceCommand.class
index 66c1b1d..2397dfe 100644
Binary files a/bin/com/capgemini/hackathon/device/simulation/bo/Hospital$EmergencyDeviceCommand.class and b/bin/com/capgemini/hackathon/device/simulation/bo/Hospital$EmergencyDeviceCommand.class differ
diff --git a/bin/com/capgemini/hackathon/device/simulation/bo/Hospital.class b/bin/com/capgemini/hackathon/device/simulation/bo/Hospital.class
index 67ea732..f7b6798 100644
Binary files a/bin/com/capgemini/hackathon/device/simulation/bo/Hospital.class and b/bin/com/capgemini/hackathon/device/simulation/bo/Hospital.class differ
diff --git a/bin/com/capgemini/hackathon/device/simulation/bo/Simulation.class b/bin/com/capgemini/hackathon/device/simulation/bo/Simulation.class
index 7e845ae..5e57e38 100644
Binary files a/bin/com/capgemini/hackathon/device/simulation/bo/Simulation.class and b/bin/com/capgemini/hackathon/device/simulation/bo/Simulation.class differ
diff --git a/bin/com/capgemini/hackathon/device/simulation/bo/Vehicle.class b/bin/com/capgemini/hackathon/device/simulation/bo/Vehicle.class
index 2dd3280..6873f85 100644
Binary files a/bin/com/capgemini/hackathon/device/simulation/bo/Vehicle.class and b/bin/com/capgemini/hackathon/device/simulation/bo/Vehicle.class differ
diff --git a/bin/devices/test-devices.json b/bin/devices/test-devices.json
index 091cef9..95302a7 100644
--- a/bin/devices/test-devices.json
+++ b/bin/devices/test-devices.json
@@ -1,73 +1,73 @@
-[{
- "simulatorClazz": "com.capgemini.hackathon.device.simulation.bo.Car",
- "id": "car0",
- "orgId": "0yngjl",
- "clientId": "d:0yngjl:car-simulator:car0",
- "typeId": "car-simulator",
- "deviceId": "car0",
- "apiToken": "E3BF69B9-C5B6-41AE-A5AB-70A35F583E64"
-},{
- "simulatorClazz": "com.capgemini.hackathon.device.simulation.bo.Car",
- "id": "car1",
- "orgId": "0yngjl",
- "clientId": "d:0yngjl:car-simulator:car1",
- "typeId": "car-simulator",
- "deviceId": "car1",
- "apiToken": "6CFA16A6-210F-4CDD-95FA-7C3158ED9C91"
-},{
- "simulatorClazz": "com.capgemini.hackathon.device.simulation.bo.Car",
- "id": "car2",
- "orgId": "0yngjl",
- "clientId": "d:0yngjl:car-simulator:car2",
- "typeId": "car-simulator",
- "deviceId": "car2",
- "apiToken": "F36A8081-11BD-4088-A1A2-0F72069B44F8"
-},{
- "simulatorClazz": "com.capgemini.hackathon.device.simulation.bo.Car",
- "id": "car3",
- "orgId": "0yngjl",
- "clientId": "d:0yngjl:car-simulator:car3",
- "typeId": "car-simulator",
- "deviceId": "car3",
- "apiToken": "BFFAE321-AE51-4A3C-BDE9-5F992A653C7C"
-},{
- "simulatorClazz": "com.capgemini.hackathon.device.simulation.bo.Car",
- "id": "car4",
- "orgId": "0yngjl",
- "clientId": "d:0yngjl:car-simulator:car4",
- "typeId": "car-simulator",
- "deviceId": "car4",
- "apiToken": "D2340AED-C527-4DED-97EB-31EEF58CBFAB"
-},{
- "simulatorClazz": "com.capgemini.hackathon.device.simulation.bo.Ambulance",
- "id": "ambulance0",
- "orgId": "0yngjl",
- "clientId": "d:0yngjl:ambulance-simulator:ambulance0",
- "typeId": "ambulance-simulator",
- "deviceId": "ambulance0",
- "apiToken": "FF7B5C52-98AA-4242-A110-44F306263DC5"
-},{
- "simulatorClazz": "com.capgemini.hackathon.device.simulation.bo.Ambulance",
- "id": "ambulance1",
- "orgId": "0yngjl",
- "clientId": "d:0yngjl:ambulance-simulator:ambulance1",
- "typeId": "ambulance-simulator",
- "deviceId": "ambulance1",
- "apiToken": "A27E0DA5-B118-4E2E-8200-3F06112ECD64"
-},{
- "simulatorClazz": "com.capgemini.hackathon.device.simulation.bo.Ambulance",
- "id": "ambulance2",
- "orgId": "0yngjl",
- "clientId": "d:0yngjl:ambulance-simulator:ambulance2",
- "typeId": "ambulance-simulator",
- "deviceId": "ambulance2",
- "apiToken": "41B2ED2B-2E05-44ED-A46A-0DA82CB5592C"
-},{
- "simulatorClazz": "com.capgemini.hackathon.device.simulation.bo.Hospital",
- "id": "hospital",
- "orgId": "0yngjl",
- "clientId": "d:0yngjl:hospital:hospital1",
- "typeId": "hospital",
- "deviceId": "hospital1",
- "apiToken": "FAD566AC-4C27-43E8-8DF8-EEA6576DAFFB"
-}]
+[{
+ "simulatorClazz": "com.capgemini.hackathon.device.simulation.bo.Car",
+ "id": "car0",
+ "orgId": "5rcpia",
+ "clientId": "d:5rcpia:car-simulator:car0",
+ "typeId": "car-simulator",
+ "deviceId": "car0",
+ "apiToken": "01562EAC-5459-498E-9B1C-8DA4F37D074C"
+},{
+ "simulatorClazz": "com.capgemini.hackathon.device.simulation.bo.Car",
+ "id": "car1",
+ "orgId": "5rcpia",
+ "clientId": "d:5rcpia:car-simulator:car1",
+ "typeId": "car-simulator",
+ "deviceId": "car1",
+ "apiToken": "1719BB4F-99A0-42D0-8FF2-4A76BC64EAFD"
+},{
+ "simulatorClazz": "com.capgemini.hackathon.device.simulation.bo.Car",
+ "id": "car2",
+ "orgId": "5rcpia",
+ "clientId": "d:5rcpia:car-simulator:car2",
+ "typeId": "car-simulator",
+ "deviceId": "car2",
+ "apiToken": "E3161649-B59E-4EC9-97E6-2A4711F7DB43"
+},{
+ "simulatorClazz": "com.capgemini.hackathon.device.simulation.bo.Car",
+ "id": "car3",
+ "orgId": "5rcpia",
+ "clientId": "d:5rcpia:car-simulator:car3",
+ "typeId": "car-simulator",
+ "deviceId": "car3",
+ "apiToken": "451326E3-BC56-4D78-8CD3-70B669F830F8"
+},{
+ "simulatorClazz": "com.capgemini.hackathon.device.simulation.bo.Ambulance",
+ "id": "ambulance0",
+ "orgId": "5rcpia",
+ "clientId": "d:5rcpia:ambulance-simulator:ambulance0",
+ "typeId": "ambulance-simulator",
+ "deviceId": "ambulance0",
+ "apiToken": "9DBB21F6-B888-4B36-8379-3F8C91912246"
+},{
+ "simulatorClazz": "com.capgemini.hackathon.device.simulation.bo.Ambulance",
+ "id": "ambulance1",
+ "orgId": "5rcpia",
+ "clientId": "d:5rcpia:ambulance-simulator:ambulance1",
+ "typeId": "ambulance-simulator",
+ "deviceId": "ambulance1",
+ "apiToken": "BC0CD3FD-F67E-4F23-945F-E805165D5590"
+},{
+ "simulatorClazz": "com.capgemini.hackathon.device.simulation.bo.Ambulance",
+ "id": "ambulance2",
+ "orgId": "5rcpia",
+ "clientId": "d:5rcpia:ambulance-simulator:ambulance2",
+ "typeId": "ambulance-simulator",
+ "deviceId": "ambulance2",
+ "apiToken": "AF289EC5-EE47-4458-AA3E-0A4ACB7EC058"
+},{
+ "simulatorClazz": "com.capgemini.hackathon.device.simulation.bo.Ambulance",
+ "id": "ambulance3",
+ "orgId": "5rcpia",
+ "clientId": "d:5rcpia:ambulance-simulator:ambulance3",
+ "typeId": "ambulance-simulator",
+ "deviceId": "ambulance3",
+ "apiToken": "CEC839DD-F3D4-4E97-889E-FBA8D3E0BBC7"
+},{
+ "simulatorClazz": "com.capgemini.hackathon.device.simulation.bo.Hospital",
+ "id": "hospital",
+ "orgId": "5rcpia",
+ "clientId": "d:5rcpia:hospital:hospital1",
+ "typeId": "hospital",
+ "deviceId": "hospital1",
+ "apiToken": "48E34C00-8A32-4C8B-93AC-6C38FE642A46"
+}]
diff --git a/src/main/java/com/capgemini/hackathon/device/service/DeviceClientCustom.java b/src/main/java/com/capgemini/hackathon/device/service/DeviceClientCustom.java
new file mode 100644
index 0000000..abbc219
--- /dev/null
+++ b/src/main/java/com/capgemini/hackathon/device/service/DeviceClientCustom.java
@@ -0,0 +1,223 @@
+package com.capgemini.hackathon.device.service;
+
+import java.util.Properties;
+import java.util.logging.Level;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import java.nio.charset.Charset;
+import java.util.Date;
+
+import org.eclipse.paho.client.mqttv3.MqttAsyncClient;
+import org.eclipse.paho.client.mqttv3.MqttClient;
+import org.eclipse.paho.client.mqttv3.MqttException;
+import org.eclipse.paho.client.mqttv3.MqttMessage;
+import org.eclipse.paho.client.mqttv3.MqttPersistenceException;
+import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken;
+import org.eclipse.paho.client.mqttv3.MqttCallback;
+
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import com.ibm.iotf.client.api.APIClient;
+import com.ibm.iotf.client.device.Command;
+import com.ibm.iotf.client.device.CommandCallback;
+import com.ibm.iotf.client.device.DeviceClient;
+import com.ibm.iotf.util.LoggerUtility;
+
+public class DeviceClientCustom extends DeviceClient{
+
+ /**
+ * Overrided version of DeviceClient to change the JSON Messages
+ * to format Geospatial needs.
+ */
+
+private static final String CLASS_NAME = DeviceClientCustom.class.getName();
+
+ private static final Pattern COMMAND_PATTERN = Pattern.compile("iot-2/cmd/(.+)/fmt/(.+)");
+
+ private CommandCallback commandCallback = null;
+
+ private APIClient apiClient;
+
+ public DeviceClientCustom(MqttAsyncClient arg0) {
+ super(arg0);
+
+ }
+
+ public DeviceClientCustom(MqttClient arg0) {
+ super(arg0);
+
+ }
+
+ public DeviceClientCustom(Properties options) throws Exception {
+ super(options);
+ LoggerUtility.fine(CLASS_NAME, "DeviceClientCustom", "options = " + options);
+ this.clientId = "d" + CLIENT_ID_DELIMITER + getOrgId() + CLIENT_ID_DELIMITER + getDeviceType() + CLIENT_ID_DELIMITER + getDeviceId();
+
+ if (getAuthMethod() == null) {
+ this.clientUsername = null;
+ this.clientPassword = null;
+ }
+ else if (!getAuthMethod().equals("token")) {
+ throw new Exception("Unsupported Authentication Method: " + getAuthMethod());
+ }
+ else {
+ // use-token-auth is the only authentication method currently supported
+ this.clientUsername = "use-token-auth";
+ this.clientPassword = getAuthToken();
+ }
+ createClient(this.new MqttDeviceCallBack());
+
+ options.setProperty("auth-method", "device");
+
+ apiClient = new APIClient(options);
+ }
+
+ public String getDeviceType() {
+ String type;
+ type = options.getProperty("type");
+ if(type == null) {
+ type = options.getProperty("Device-Type");
+ }
+ return trimedValue(type);
+ }
+
+ public String getFormat() {
+ String format = options.getProperty("format");
+ if(format != null && ! format.equals(""))
+ return format;
+ else
+ return "json";
+
+ }
+
+
+ private void subscribeToCommands() {
+ try {
+ mqttAsyncClient.subscribe("iot-2/cmd/+/fmt/+", 2);
+ } catch (MqttException e) {
+ e.printStackTrace();
+ }
+ }
+
+ public APIClient api() {
+ return this.apiClient;
+ }
+
+ public boolean publishEvent(String event, Object data) {
+ return publishEvent(event, data, 0);
+ }
+
+
+
+ @Override
+ public boolean publishEvent(String event, Object data, int qos) {
+ if (!isConnected()) {
+ return false;
+ }
+ final String METHOD = "publishEvent(2)";
+ JsonObject payload = new JsonObject();
+
+ String timestamp = ISO8601_DATE_FORMAT.format(new Date());
+ payload.addProperty("ts", timestamp);
+
+ // Handle null object
+ if(data == null) {
+ data = new JsonObject();
+ }
+
+ JsonElement dataElement = gson.toJsonTree(data);
+ payload.add("d", dataElement);
+
+ String topic = "iot-2/evt/" + event + "/fmt/json";
+
+ JsonObject dataJson = (JsonObject) data;
+ payload.add("latitude", dataJson.get("latitude"));
+ payload.add("longitude", dataJson.get("longitude"));
+ payload.add("vin", dataJson.get("vin"));
+
+ MqttMessage msg = new MqttMessage(payload.toString().getBytes(Charset.forName("UTF-8")));
+ msg.setQos(qos);
+ msg.setRetained(false);
+
+ try {
+ mqttAsyncClient.publish(topic, msg).waitForCompletion();
+ } catch (MqttPersistenceException e) {
+ e.printStackTrace();
+ return false;
+ } catch (MqttException e) {
+ e.printStackTrace();
+ return false;
+ }
+ return true;
+ }
+
+ private class MqttDeviceCallBack implements MqttCallbackExtended {
+
+ /**
+ * If we lose connection trigger the connect logic to attempt to
+ * reconnect to the IBM Watson IoT Platform.
+ *
+ * @param exception
+ * Throwable which caused the connection to get lost
+ */
+ public void connectionLost(Throwable exception) {
+ final String METHOD = "connectionLost";
+ LoggerUtility.log(Level.SEVERE, CLASS_NAME, METHOD, exception.getMessage());
+ try {
+ reconnect();
+ } catch (Exception e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * A completed deliver does not guarantee that the message is received by the service
+ * because devices send messages with Quality of Service (QoS) 0.
+ *
+ * The message count
+ * represents the number of messages that were sent by the device without an error on
+ * from the perspective of the device.
+ * @param token
+ * MQTT delivery token
+ */
+ public void deliveryComplete(IMqttDeliveryToken token) {
+ final String METHOD = "deliveryComplete";
+ LoggerUtility.fine(CLASS_NAME, METHOD, "token " + token.getMessageId());
+ messageCount++;
+ }
+
+ /**
+ * The Device client does not currently support subscriptions.
+ */
+ public void messageArrived(String topic, MqttMessage msg) throws Exception {
+ final String METHOD = "messageArrived";
+ if (commandCallback != null) {
+ /* Only check whether the message is a command if a callback
+ * has been defined, otherwise it is a waste of time
+ * as without a callback there is nothing to process the generated
+ * command.
+ */
+ Matcher matcher = COMMAND_PATTERN.matcher(topic);
+ if (matcher.matches()) {
+ String command = matcher.group(1);
+ String format = matcher.group(2);
+ Command cmd = new Command(command, format, msg);
+ LoggerUtility.fine(CLASS_NAME, METHOD, "Event received: " + cmd.toString());
+ commandCallback.processCommand(cmd);
+ }
+ }
+ }
+
+ @Override
+ public void connectComplete(boolean reconnect, String serverURI) {
+ // TODO Auto-generated method stub
+
+ }
+
+ }
+
+ public void setCommandCallback(CommandCallback callback) {
+ this.commandCallback = callback;
+ }
+ }
diff --git a/src/main/java/com/capgemini/hackathon/device/service/MqttCallbackExtended.java b/src/main/java/com/capgemini/hackathon/device/service/MqttCallbackExtended.java
new file mode 100644
index 0000000..7de0514
--- /dev/null
+++ b/src/main/java/com/capgemini/hackathon/device/service/MqttCallbackExtended.java
@@ -0,0 +1,11 @@
+package com.capgemini.hackathon.device.service;
+
+import org.eclipse.paho.client.mqttv3.MqttCallback;
+
+public interface MqttCallbackExtended extends MqttCallback{
+ /**
+ * Overrided version of MqttCallbackExtended. Not included in the IBM API.
+ * Required for DeviceClientCustom.
+ */
+ public void connectComplete(boolean reconnect, java.lang.String serverURI);
+}
diff --git a/src/main/java/com/capgemini/hackathon/device/simulation/bo/Ambulance.java b/src/main/java/com/capgemini/hackathon/device/simulation/bo/Ambulance.java
index dca328b..db213ac 100644
--- a/src/main/java/com/capgemini/hackathon/device/simulation/bo/Ambulance.java
+++ b/src/main/java/com/capgemini/hackathon/device/simulation/bo/Ambulance.java
@@ -1,5 +1,6 @@
package com.capgemini.hackathon.device.simulation.bo;
+import com.capgemini.hackathon.device.service.DeviceClientCustom;
import com.capgemini.hackathon.device.simulation.DeviceClientConfig;
import com.capgemini.hackathon.device.simulation.model.Emergency;
import com.capgemini.hackathon.device.simulation.model.Location;
@@ -94,7 +95,7 @@ public boolean isFree() {
}
@Override
- protected void configureDeviceClient(DeviceClient deviceClient) {
+ protected void configureDeviceClient(DeviceClientCustom deviceClient) {
}
diff --git a/src/main/java/com/capgemini/hackathon/device/simulation/bo/Car.java b/src/main/java/com/capgemini/hackathon/device/simulation/bo/Car.java
index c4c87cb..021d86f 100644
--- a/src/main/java/com/capgemini/hackathon/device/simulation/bo/Car.java
+++ b/src/main/java/com/capgemini/hackathon/device/simulation/bo/Car.java
@@ -1,5 +1,6 @@
package com.capgemini.hackathon.device.simulation.bo;
+import com.capgemini.hackathon.device.service.DeviceClientCustom;
import com.capgemini.hackathon.device.simulation.DeviceClientConfig;
import com.capgemini.hackathon.device.simulation.model.Location;
import com.google.gson.JsonObject;
@@ -26,7 +27,7 @@ protected void addMetainformationWhenPublishLocation(JsonObject event) {
}
@Override
- protected void configureDeviceClient(DeviceClient deviceClient) {
+ protected void configureDeviceClient(DeviceClientCustom deviceClient) {
// nothing to do
}
}
diff --git a/src/main/java/com/capgemini/hackathon/device/simulation/bo/Hospital.java b/src/main/java/com/capgemini/hackathon/device/simulation/bo/Hospital.java
index 0325950..41dd72c 100644
--- a/src/main/java/com/capgemini/hackathon/device/simulation/bo/Hospital.java
+++ b/src/main/java/com/capgemini/hackathon/device/simulation/bo/Hospital.java
@@ -1,164 +1,166 @@
-package com.capgemini.hackathon.device.simulation.bo;
-
-import java.util.List;
-import java.util.UUID;
-import java.util.concurrent.CopyOnWriteArrayList;
-
-import com.capgemini.hackathon.device.simulation.DeviceClientConfig;
-import com.capgemini.hackathon.device.simulation.model.Emergency;
-import com.capgemini.hackathon.device.simulation.model.Emergency.Status;
-import com.capgemini.hackathon.device.simulation.model.Location;
-import com.capgemini.hackathon.device.simulation.routing.RouteCalculator;
-import com.google.gson.JsonObject;
-import com.google.gson.JsonParser;
-import com.graphhopper.GHResponse;
-import com.ibm.iotf.client.device.Command;
-import com.ibm.iotf.client.device.CommandCallback;
-import com.ibm.iotf.client.device.DeviceClient;
-
-/**
- * Hospital simulator class which handles emergencies, and notfies next
- * ambulance.
- *
- * To notify the hospital about an emergency a json command with following
- * structure must be send to the hospital device:
- *
- *
- */
-public class Hospital extends Simulation {
-
- public static final String HOSPITAL_ID = "Hospital_Kings_Cross";
-
- private List emergencies = new CopyOnWriteArrayList();
-
- public Hospital(DeviceClientConfig deviceClientConfig, Object id) {
- super(deviceClientConfig, HOSPITAL_ID);
- }
-
- @Override
- protected void configureDeviceClient(DeviceClient deviceClient) {
- deviceClient.setCommandCallback(new EmergencyDeviceCommand());
-
- }
-
- @Override
- protected void process() {
- while (true) {
- try {
- Thread.sleep(2000);
-
- synchronized (emergencies) {
- for (Emergency emergency : emergencies) {
- publishEmergency(emergency);
- handleEmergency(emergency);
-
- }
- }
-
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- }
-
- private void handleEmergency(Emergency emergency) {
- // find ambulance to solve emergency
- if (emergency.getStatus() == Emergency.Status.OPEN) {
- Ambulance ambulance = findNearestAmbulance(emergency);
- if (ambulance != null) {
- ambulance.sendToEmergency(emergency);
- emergency.setAmbulanceVin(ambulance.getId().toString());
- emergency.setStatus(Emergency.Status.ONGING);
- }
- } else if (emergency.getStatus() == Emergency.Status.SOLVED) {
- synchronized (emergencies) {
- emergencies.remove(emergency);
- }
- }
- }
-
- private void publishEmergency(Emergency emergency) {
- try {
- // Publish event to IoT
- getDeviceClient().publishEvent(Emergency.EVENT_LOCATION, emergency.asJson());
-
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
-
- /**
- * This method finds which ambulance is the closest ambulance to the
- * emergency location
- *
- * @param emergencyLatitude
- * the latitude of the emergency location
- *
- * @param emergencyLongitude
- * the longitude of the emergency location
- */
-
- public Ambulance findNearestAmbulance(Emergency emergency) {
- List ambulances = BORegistry.getInstance().getAmbulances();
-
- Ambulance nearestAmbulance = null;
- double nearestDistance = Double.MAX_VALUE;
- for (Ambulance ambulance : ambulances) {
-
- if (ambulance.isFree()) {
- GHResponse response = RouteCalculator.getInstance().calculateRoute(
- ambulance.getCurrentLocation().getLatitude(), ambulance.getCurrentLocation().getLongitude(),
- emergency.getLocation().getLatitude(), emergency.getLocation().getLongitude());
-
- if (response.getDistance() < nearestDistance) {
- nearestAmbulance = ambulance;
- nearestDistance = response.getDistance();
- }
-
- }
- }
- return nearestAmbulance;
- }
-
- public void solveEmergency(Emergency solvedEmergency) {
- synchronized (emergencies) {
- for (Emergency emergency : emergencies) {
- if (emergency.getEmergencyId().equals(solvedEmergency.getEmergencyId())) {
- emergency.setStatus(Status.SOLVED);
- System.out.println("Hospital: Emergency " + emergency.getEmergencyId() + " solved");
-
- }
- }
- }
-
- }
-
- private class EmergencyDeviceCommand implements CommandCallback {
-
- @Override
- public void processCommand(Command command) {
- JsonObject jsonCmd = new JsonParser().parse(command.getPayload()).getAsJsonObject().get("d")
- .getAsJsonObject();
- String latitude = jsonCmd.get("latitude").getAsString();
- String longtitude = jsonCmd.get("longitude").getAsString();
-
- handleNewEmergency(latitude, longtitude);
-
- }
-
- private void handleNewEmergency(String latitude, String longtitude) {
- // new emergency
- Emergency emergency = new Emergency();
- emergency.setEmergencyId(UUID.randomUUID().toString());
- emergency.setLocation(new Location(Double.valueOf(latitude), Double.valueOf(longtitude)));
-
- synchronized (emergencies) {
- emergencies.add(emergency);
- System.out.println("Hospital: Emergency " + emergency.getEmergencyId() + " happend");
-
- }
-
- }
-
- }
-}
+package com.capgemini.hackathon.device.simulation.bo;
+
+import java.util.List;
+import java.util.UUID;
+import java.util.concurrent.CopyOnWriteArrayList;
+
+import com.capgemini.hackathon.device.simulation.DeviceClientConfig;
+import com.capgemini.hackathon.device.simulation.model.Emergency;
+import com.capgemini.hackathon.device.simulation.model.Emergency.Status;
+import com.capgemini.hackathon.device.simulation.model.Location;
+import com.capgemini.hackathon.device.simulation.routing.RouteCalculator;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParser;
+import com.graphhopper.GHResponse;
+import com.ibm.iotf.client.device.Command;
+import com.ibm.iotf.client.device.CommandCallback;
+import com.ibm.iotf.client.device.DeviceClient;
+import com.capgemini.hackathon.device.service.DeviceClientCustom;
+
+/**
+ * Hospital simulator class which handles emergencies, and notfies next
+ * ambulance.
+ *
+ * To notify the hospital about an emergency a json command with following
+ * structure must be send to the hospital device:
+ *
+ *
+ */
+public class Hospital extends Simulation {
+
+ public static final String HOSPITAL_ID = "Hospital_Kings_Cross";
+
+ private List emergencies = new CopyOnWriteArrayList();
+
+ public Hospital(DeviceClientConfig deviceClientConfig, Object id) {
+ super(deviceClientConfig, HOSPITAL_ID);
+ }
+
+ @Override
+ protected void configureDeviceClient(DeviceClientCustom deviceClient) {
+ deviceClient.setCommandCallback(new EmergencyDeviceCommand());
+
+ }
+
+ @Override
+ protected void process() {
+ while (true) {
+ try {
+ Thread.sleep(2000);
+
+ synchronized (emergencies) {
+ for (Emergency emergency : emergencies) {
+ publishEmergency(emergency);
+ handleEmergency(emergency);
+
+ }
+ }
+
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ private void handleEmergency(Emergency emergency) {
+ // find ambulance to solve emergency
+ if (emergency.getStatus() == Emergency.Status.OPEN) {
+ Ambulance ambulance = findNearestAmbulance(emergency);
+ if (ambulance != null) {
+ ambulance.sendToEmergency(emergency);
+ emergency.setAmbulanceVin(ambulance.getId().toString());
+ emergency.setStatus(Emergency.Status.ONGING);
+ }
+ } else if (emergency.getStatus() == Emergency.Status.SOLVED) {
+ synchronized (emergencies) {
+ emergencies.remove(emergency);
+ }
+ }
+ }
+
+ private void publishEmergency(Emergency emergency) {
+ try {
+ // Publish event to IoT
+ getDeviceClient().publishEvent(Emergency.EVENT_LOCATION, emergency.asJson());
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * This method finds which ambulance is the closest ambulance to the
+ * emergency location
+ *
+ * @param emergencyLatitude
+ * the latitude of the emergency location
+ *
+ * @param emergencyLongitude
+ * the longitude of the emergency location
+ */
+
+ public Ambulance findNearestAmbulance(Emergency emergency) {
+ List ambulances = BORegistry.getInstance().getAmbulances();
+
+ Ambulance nearestAmbulance = null;
+ double nearestDistance = Double.MAX_VALUE;
+ for (Ambulance ambulance : ambulances) {
+
+ if (ambulance.isFree()) {
+ GHResponse response = RouteCalculator.getInstance().calculateRoute(
+ ambulance.getCurrentLocation().getLatitude(), ambulance.getCurrentLocation().getLongitude(),
+ emergency.getLocation().getLatitude(), emergency.getLocation().getLongitude());
+
+ if (response.getDistance() < nearestDistance) {
+ nearestAmbulance = ambulance;
+ nearestDistance = response.getDistance();
+ }
+
+ }
+ }
+ return nearestAmbulance;
+ }
+
+ public void solveEmergency(Emergency solvedEmergency) {
+ synchronized (emergencies) {
+ for (Emergency emergency : emergencies) {
+ if (emergency.getEmergencyId().equals(solvedEmergency.getEmergencyId())) {
+ emergency.setStatus(Status.SOLVED);
+ System.out.println("Hospital: Emergency " + emergency.getEmergencyId() + " solved");
+
+ }
+ }
+ }
+
+ }
+
+ private class EmergencyDeviceCommand implements CommandCallback {
+ //To control Geospatial, the emergency id is created in the REST Service of the RouteWebApplication
+ @Override
+ public void processCommand(Command command) {
+ JsonObject jsonCmd = new JsonParser().parse(command.getPayload()).getAsJsonObject().get("d")
+ .getAsJsonObject();
+ String latitude = jsonCmd.get("latitude").getAsString();
+ String longtitude = jsonCmd.get("longitude").getAsString();
+ String newEmergencyID = jsonCmd.get("newEmergencyID").getAsString();
+
+ handleNewEmergency(latitude, longtitude, newEmergencyID);
+
+ }
+
+ private void handleNewEmergency(String latitude, String longtitude, String newEmergencyID) {
+ // new emergency
+ Emergency emergency = new Emergency();
+ emergency.setEmergencyId(newEmergencyID);
+ emergency.setLocation(new Location(Double.valueOf(latitude), Double.valueOf(longtitude)));
+
+ synchronized (emergencies) {
+ emergencies.add(emergency);
+ System.out.println("Hospital: Emergency " + emergency.getEmergencyId() + " happend");
+
+ }
+
+ }
+
+ }
+}
diff --git a/src/main/java/com/capgemini/hackathon/device/simulation/bo/Simulation.java b/src/main/java/com/capgemini/hackathon/device/simulation/bo/Simulation.java
index 20ffafc..f26b139 100644
--- a/src/main/java/com/capgemini/hackathon/device/simulation/bo/Simulation.java
+++ b/src/main/java/com/capgemini/hackathon/device/simulation/bo/Simulation.java
@@ -2,12 +2,13 @@
import java.util.concurrent.Callable;
+import com.capgemini.hackathon.device.service.DeviceClientCustom;
import com.capgemini.hackathon.device.simulation.DeviceClientConfig;
import com.ibm.iotf.client.device.DeviceClient;
public abstract class Simulation implements Callable {
- private DeviceClient deviceClient;
+ private DeviceClientCustom deviceClient;
private DeviceClientConfig deviceConfig;
private Object id;
@@ -18,7 +19,7 @@ public Simulation(DeviceClientConfig deviceClientConfig, Object id) {
public void connect() {
try {
- deviceClient = new DeviceClient(deviceConfig.asProperties());
+ deviceClient = new DeviceClientCustom(deviceConfig.asProperties());
// Connect to Internet of Things Foundation
deviceClient.connect();
configureDeviceClient(deviceClient);
@@ -35,7 +36,7 @@ public void disconnect() {
BORegistry.getInstance().unregister(this);
}
- public DeviceClient getDeviceClient() {
+ public DeviceClientCustom getDeviceClient() {
return deviceClient;
}
@@ -54,6 +55,6 @@ public String call() {
protected abstract void process();
- protected abstract void configureDeviceClient(DeviceClient deviceClient);
+ protected abstract void configureDeviceClient(DeviceClientCustom deviceClient);
}
diff --git a/src/main/java/com/capgemini/hackathon/device/simulation/bo/Vehicle.java b/src/main/java/com/capgemini/hackathon/device/simulation/bo/Vehicle.java
index 817cea8..3acabad 100644
--- a/src/main/java/com/capgemini/hackathon/device/simulation/bo/Vehicle.java
+++ b/src/main/java/com/capgemini/hackathon/device/simulation/bo/Vehicle.java
@@ -1,5 +1,7 @@
package com.capgemini.hackathon.device.simulation.bo;
+import org.joda.time.DateTime;
+
import com.capgemini.hackathon.device.simulation.DeviceClientConfig;
import com.capgemini.hackathon.device.simulation.model.Location;
import com.capgemini.hackathon.device.simulation.model.VehicleLocation;
@@ -13,9 +15,9 @@ public abstract class Vehicle extends Simulation {
// How close the vehicles reach their destination
private static final double DIST_LAT_LONG = 0.00005;
- private static final double DEFAULT_SPEED = 0.00005;
+ private static final double DEFAULT_SPEED = 0.0001;
// The steps driving the vehicles per iteration
- private final static double SPEED = Vehicle.getSpeed();
+ private final static double SPEED = Vehicle.getSPEED();
// current Location
private Location currentLocation;
@@ -63,69 +65,67 @@ protected void driveToDestination(Location destination) {
protected void driveToDestination(Location destination, Interruption interruption) {
// Calculate the route between the current and destination location
+
GHResponse response = RouteCalculator.getInstance().calculateRoute(currentLocation.getLatitude(),
currentLocation.getLongitude(), destination.getLatitude(), destination.getLongitude());
int i = 0;
+ long millis = DateTime.now().getMillis();
+ long previousMillis = millis;
+
if (response.getPoints() != null) {
while (response.getPoints().getSize() > i) {
-
+
double nextPointLatitude = response.getPoints().getLatitude(i);
double nextpointLongitude = response.getPoints().getLongitude(i);
- // Take the difference between current location and the
- // destination
- double distLat = currentLocation.getLatitude() - nextPointLatitude;
- double distLong = currentLocation.getLongitude() - nextpointLongitude;
-
+ // Take the difference between current location and the destination
+ double distLat = nextPointLatitude - currentLocation.getLatitude();
+ double distLong = nextpointLongitude - currentLocation.getLongitude();
+
// While the difference is bigger than the threshold x
- //int j = 0;
while ((Math.abs(distLat) > DIST_LAT_LONG || Math.abs(distLong) > DIST_LAT_LONG)) {
- // check if we have to move in lat direction
- if (Math.abs(distLat) > DIST_LAT_LONG) {
- // go xxx steps in direction
- if (distLat < 0) {
- currentLocation.setLatitude(currentLocation.getLatitude() + SPEED);
- } else {
- currentLocation.setLatitude(currentLocation.getLatitude() - SPEED);
- }
- }
- // check if we have to move in long direction
- if (Math.abs(distLong) > DIST_LAT_LONG) {
- if (distLong < 0) {
- currentLocation.setLongitude(currentLocation.getLongitude() + SPEED);
- } else {
- currentLocation.setLongitude(currentLocation.getLongitude() - SPEED);
- }
+
+ double absVec = Math.sqrt((distLat * distLat) + (distLong * distLong));
+ double factor = SPEED / absVec;
+
+ if (factor > 1) {
+ factor = 1;
}
+ currentLocation.setLatitude(currentLocation.getLatitude() + (distLat * factor));
+ currentLocation.setLongitude(currentLocation.getLongitude() + (distLong * factor));
+
try {
- try {
- Thread.sleep(20);
- } catch (InterruptedException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- //if (j % 2 == 0)
this.publishLocation();
- if (interruption.interrupt()) {
- System.out.println("Driving interrupted");
- return;
- }
-
} catch (Exception e) {
e.printStackTrace();
}
- distLat = currentLocation.getLatitude() - nextPointLatitude;
- distLong = currentLocation.getLongitude() - nextpointLongitude;
- //j++;
+ if (interruption.interrupt()) {
+ System.out.println("Driving interrupted");
+ return;
+ }
+ distLat = nextPointLatitude - currentLocation.getLatitude();
+ distLong = nextpointLongitude - currentLocation.getLongitude();
+
+ try {
+ // whatever time has passed so far, wait until 1s has passed
+ millis = DateTime.now().getMillis();
+ long diffMillies = millis - previousMillis;
+ if (diffMillies < 1000) {
+ // System.out.println("Sleeping :" + (1000 - diffMillies) + "ms");
+ Thread.sleep(1000 - diffMillies);
+ }
+
+ previousMillis = DateTime.now().getMillis();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
}
- currentLocation.setLatitude(nextPointLatitude);
- currentLocation.setLongitude(nextpointLongitude);
i = i + 1;
}
@@ -145,13 +145,14 @@ public boolean interrupt() {
}
- public static double getSpeed() {
- String speed = System.getenv("SPEED");
- if (speed != null) {
- return Double.valueOf(speed);
+ public static double getSPEED() {
+ String SPEED = System.getenv("SPEED");
+ if (SPEED != null) {
+ return Double.valueOf(SPEED);
} else {
return DEFAULT_SPEED;
}
}
}
+
diff --git a/src/main/ressources/admin.properties b/src/main/ressources/admin.properties
index 601b2b8..cfdf0bc 100644
--- a/src/main/ressources/admin.properties
+++ b/src/main/ressources/admin.properties
@@ -1,3 +1,3 @@
group.name = simulator
-nr.of.cars = 5
-nr.of.ambulances = 3
\ No newline at end of file
+nr.of.cars = 4
+nr.of.ambulances = 4
\ No newline at end of file
diff --git a/src/main/ressources/application.properties b/src/main/ressources/application.properties
index 14dd591..0a060dd 100644
--- a/src/main/ressources/application.properties
+++ b/src/main/ressources/application.properties
@@ -1,4 +1,4 @@
-api-key = a-0yngjl-qd4wocrack
-api-token = eA5HT)4ccFU2dULL7A
-orga-id = 0yngjl
+api-key = a-5rcpia-hxwn2ipopc
+api-token = tSzH3*7wou5pLfZd4e
+orga-id = 5rcpia
devices = devices/test-devices.json
diff --git a/src/main/ressources/devices/test-devices.json b/src/main/ressources/devices/test-devices.json
index 091cef9..95302a7 100644
--- a/src/main/ressources/devices/test-devices.json
+++ b/src/main/ressources/devices/test-devices.json
@@ -1,73 +1,73 @@
-[{
- "simulatorClazz": "com.capgemini.hackathon.device.simulation.bo.Car",
- "id": "car0",
- "orgId": "0yngjl",
- "clientId": "d:0yngjl:car-simulator:car0",
- "typeId": "car-simulator",
- "deviceId": "car0",
- "apiToken": "E3BF69B9-C5B6-41AE-A5AB-70A35F583E64"
-},{
- "simulatorClazz": "com.capgemini.hackathon.device.simulation.bo.Car",
- "id": "car1",
- "orgId": "0yngjl",
- "clientId": "d:0yngjl:car-simulator:car1",
- "typeId": "car-simulator",
- "deviceId": "car1",
- "apiToken": "6CFA16A6-210F-4CDD-95FA-7C3158ED9C91"
-},{
- "simulatorClazz": "com.capgemini.hackathon.device.simulation.bo.Car",
- "id": "car2",
- "orgId": "0yngjl",
- "clientId": "d:0yngjl:car-simulator:car2",
- "typeId": "car-simulator",
- "deviceId": "car2",
- "apiToken": "F36A8081-11BD-4088-A1A2-0F72069B44F8"
-},{
- "simulatorClazz": "com.capgemini.hackathon.device.simulation.bo.Car",
- "id": "car3",
- "orgId": "0yngjl",
- "clientId": "d:0yngjl:car-simulator:car3",
- "typeId": "car-simulator",
- "deviceId": "car3",
- "apiToken": "BFFAE321-AE51-4A3C-BDE9-5F992A653C7C"
-},{
- "simulatorClazz": "com.capgemini.hackathon.device.simulation.bo.Car",
- "id": "car4",
- "orgId": "0yngjl",
- "clientId": "d:0yngjl:car-simulator:car4",
- "typeId": "car-simulator",
- "deviceId": "car4",
- "apiToken": "D2340AED-C527-4DED-97EB-31EEF58CBFAB"
-},{
- "simulatorClazz": "com.capgemini.hackathon.device.simulation.bo.Ambulance",
- "id": "ambulance0",
- "orgId": "0yngjl",
- "clientId": "d:0yngjl:ambulance-simulator:ambulance0",
- "typeId": "ambulance-simulator",
- "deviceId": "ambulance0",
- "apiToken": "FF7B5C52-98AA-4242-A110-44F306263DC5"
-},{
- "simulatorClazz": "com.capgemini.hackathon.device.simulation.bo.Ambulance",
- "id": "ambulance1",
- "orgId": "0yngjl",
- "clientId": "d:0yngjl:ambulance-simulator:ambulance1",
- "typeId": "ambulance-simulator",
- "deviceId": "ambulance1",
- "apiToken": "A27E0DA5-B118-4E2E-8200-3F06112ECD64"
-},{
- "simulatorClazz": "com.capgemini.hackathon.device.simulation.bo.Ambulance",
- "id": "ambulance2",
- "orgId": "0yngjl",
- "clientId": "d:0yngjl:ambulance-simulator:ambulance2",
- "typeId": "ambulance-simulator",
- "deviceId": "ambulance2",
- "apiToken": "41B2ED2B-2E05-44ED-A46A-0DA82CB5592C"
-},{
- "simulatorClazz": "com.capgemini.hackathon.device.simulation.bo.Hospital",
- "id": "hospital",
- "orgId": "0yngjl",
- "clientId": "d:0yngjl:hospital:hospital1",
- "typeId": "hospital",
- "deviceId": "hospital1",
- "apiToken": "FAD566AC-4C27-43E8-8DF8-EEA6576DAFFB"
-}]
+[{
+ "simulatorClazz": "com.capgemini.hackathon.device.simulation.bo.Car",
+ "id": "car0",
+ "orgId": "5rcpia",
+ "clientId": "d:5rcpia:car-simulator:car0",
+ "typeId": "car-simulator",
+ "deviceId": "car0",
+ "apiToken": "01562EAC-5459-498E-9B1C-8DA4F37D074C"
+},{
+ "simulatorClazz": "com.capgemini.hackathon.device.simulation.bo.Car",
+ "id": "car1",
+ "orgId": "5rcpia",
+ "clientId": "d:5rcpia:car-simulator:car1",
+ "typeId": "car-simulator",
+ "deviceId": "car1",
+ "apiToken": "1719BB4F-99A0-42D0-8FF2-4A76BC64EAFD"
+},{
+ "simulatorClazz": "com.capgemini.hackathon.device.simulation.bo.Car",
+ "id": "car2",
+ "orgId": "5rcpia",
+ "clientId": "d:5rcpia:car-simulator:car2",
+ "typeId": "car-simulator",
+ "deviceId": "car2",
+ "apiToken": "E3161649-B59E-4EC9-97E6-2A4711F7DB43"
+},{
+ "simulatorClazz": "com.capgemini.hackathon.device.simulation.bo.Car",
+ "id": "car3",
+ "orgId": "5rcpia",
+ "clientId": "d:5rcpia:car-simulator:car3",
+ "typeId": "car-simulator",
+ "deviceId": "car3",
+ "apiToken": "451326E3-BC56-4D78-8CD3-70B669F830F8"
+},{
+ "simulatorClazz": "com.capgemini.hackathon.device.simulation.bo.Ambulance",
+ "id": "ambulance0",
+ "orgId": "5rcpia",
+ "clientId": "d:5rcpia:ambulance-simulator:ambulance0",
+ "typeId": "ambulance-simulator",
+ "deviceId": "ambulance0",
+ "apiToken": "9DBB21F6-B888-4B36-8379-3F8C91912246"
+},{
+ "simulatorClazz": "com.capgemini.hackathon.device.simulation.bo.Ambulance",
+ "id": "ambulance1",
+ "orgId": "5rcpia",
+ "clientId": "d:5rcpia:ambulance-simulator:ambulance1",
+ "typeId": "ambulance-simulator",
+ "deviceId": "ambulance1",
+ "apiToken": "BC0CD3FD-F67E-4F23-945F-E805165D5590"
+},{
+ "simulatorClazz": "com.capgemini.hackathon.device.simulation.bo.Ambulance",
+ "id": "ambulance2",
+ "orgId": "5rcpia",
+ "clientId": "d:5rcpia:ambulance-simulator:ambulance2",
+ "typeId": "ambulance-simulator",
+ "deviceId": "ambulance2",
+ "apiToken": "AF289EC5-EE47-4458-AA3E-0A4ACB7EC058"
+},{
+ "simulatorClazz": "com.capgemini.hackathon.device.simulation.bo.Ambulance",
+ "id": "ambulance3",
+ "orgId": "5rcpia",
+ "clientId": "d:5rcpia:ambulance-simulator:ambulance3",
+ "typeId": "ambulance-simulator",
+ "deviceId": "ambulance3",
+ "apiToken": "CEC839DD-F3D4-4E97-889E-FBA8D3E0BBC7"
+},{
+ "simulatorClazz": "com.capgemini.hackathon.device.simulation.bo.Hospital",
+ "id": "hospital",
+ "orgId": "5rcpia",
+ "clientId": "d:5rcpia:hospital:hospital1",
+ "typeId": "hospital",
+ "deviceId": "hospital1",
+ "apiToken": "48E34C00-8A32-4C8B-93AC-6C38FE642A46"
+}]