|
|
@@ -2,20 +2,30 @@ package io.connector.module.afarcloud.gateway;
|
|
|
|
|
|
import io.connector.core.AbstractGateway;
|
|
|
import io.connector.core.http.RequestUriComponent;
|
|
|
-import io.connector.model.afarcloud.Unit;
|
|
|
+import io.connector.model.afarcloud.MultiSensor;
|
|
|
+import io.connector.model.afarcloud.ResourceMeasurement;
|
|
|
+import io.connector.model.afarcloud.SensorTelemetry;
|
|
|
import io.connector.model.sensorthings.*;
|
|
|
import io.connector.module.afarcloud.AFCClient;
|
|
|
-import io.vertx.core.json.JsonObject;
|
|
|
+import io.connector.module.afarcloud.Filter;
|
|
|
|
|
|
-import java.util.ArrayList;
|
|
|
-import java.util.List;
|
|
|
+import java.time.Instant;
|
|
|
+import java.time.ZoneId;
|
|
|
+import java.time.format.DateTimeFormatter;
|
|
|
+import java.time.format.DateTimeFormatterBuilder;
|
|
|
+import java.util.*;
|
|
|
+import java.util.function.Supplier;
|
|
|
|
|
|
import static cz.senslog.common.http.HttpContentType.APPLICATION_JSON;
|
|
|
import static cz.senslog.common.http.HttpHeader.CONTENT_TYPE;
|
|
|
import static io.connector.core.AddressPath.Creator.create;
|
|
|
import static io.vertx.core.json.Json.encode;
|
|
|
+import static java.lang.Math.sqrt;
|
|
|
+import static java.lang.StrictMath.pow;
|
|
|
import static java.lang.String.format;
|
|
|
+import static java.time.format.DateTimeFormatter.ofPattern;
|
|
|
import static java.util.Arrays.asList;
|
|
|
+import static java.util.Optional.ofNullable;
|
|
|
|
|
|
public class OGCSensorThingsGateway extends AbstractGateway {
|
|
|
|
|
|
@@ -29,236 +39,647 @@ public class OGCSensorThingsGateway extends AbstractGateway {
|
|
|
@Override
|
|
|
protected void run() {
|
|
|
|
|
|
- router().get(create("Things(:id)")).handler(ctx -> {
|
|
|
+ router().get(create("Things")).handler(ctx -> {
|
|
|
RequestUriComponent uriComponent = parseUriToComponents(ctx.request());
|
|
|
- String id = ctx.pathParam("id");
|
|
|
+ List<MultiSensor> afcMultiSensors = client.getAllMultiSensors();
|
|
|
+ List<Thing> ogcThings = Converter.convertToThing(afcMultiSensors, uriComponent);
|
|
|
+ ctx.response().putHeader(CONTENT_TYPE, APPLICATION_JSON).end(encode(ogcThings));
|
|
|
+ });
|
|
|
|
|
|
- Think think = new Think();
|
|
|
- think.setId(id);
|
|
|
- think.setSelfLink(format("%s/Things(%s)", uriComponent.getGatewayUri(), id));
|
|
|
- think.setLocationsNavigationLink(format("Things(%s)/Locations", id));
|
|
|
- think.setDataStreamNavigationLink(format("Things(%s)/Datastreams", id));
|
|
|
- think.setHistoricalLocationsNavigationLink(format("Things(%s)/HistoricalLocations", id));
|
|
|
- think.setName("Oven");
|
|
|
- think.setDescription("This thing is an oven.");
|
|
|
- think.setProperties(new JsonObject()
|
|
|
- .put("owner", "Noah Liang")
|
|
|
- .put("color", "Black")
|
|
|
- );
|
|
|
+ router().get(create("Things(:id)")).handler(ctx -> {
|
|
|
+ RequestUriComponent uriComponent = parseUriToComponents(ctx.request());
|
|
|
+ String resourceUrn = ctx.pathParam("id"); // resourceUrn
|
|
|
+ MultiSensor afcMultiSensor = client.getSensorByResourceUrn(resourceUrn);
|
|
|
+ Thing ogcThing = Converter.convertToThing(afcMultiSensor, uriComponent);
|
|
|
+ ctx.response().putHeader(CONTENT_TYPE, APPLICATION_JSON).end(ogcThing.encode());
|
|
|
+ });
|
|
|
|
|
|
- ctx.response().putHeader(CONTENT_TYPE, APPLICATION_JSON).end(think.encode());
|
|
|
+ router().get(create("Datastreams(:id)/Thing")).handler(ctx -> {
|
|
|
+ RequestUriComponent uriComponent = parseUriToComponents(ctx.request());
|
|
|
+ String id = ctx.pathParam("id"); // resourceUrn + observedProperty
|
|
|
+ String[] idCmp = Converter.disassemblyId(id);
|
|
|
+ String resourceUrn = idCmp[0];
|
|
|
+ ctx.reroute(format("%s/Things(%s)", uriComponent.getGatewayPath(), resourceUrn));
|
|
|
});
|
|
|
|
|
|
- router().get(create("Locations(:id)")).handler(ctx -> {
|
|
|
+ router().get(create("HistoricalLocations(:id)/Thing")).handler(ctx -> {
|
|
|
RequestUriComponent uriComponent = parseUriToComponents(ctx.request());
|
|
|
- String id = ctx.pathParam("id");
|
|
|
+ String id = ctx.pathParam("id"); // resourceUrn + observedProperty + time
|
|
|
|
|
|
- Unit afcUnit = client.getSensor(id);
|
|
|
+ String [] idCmp = Converter.disassemblyId(id);
|
|
|
+ String resourceUrn = idCmp[0];
|
|
|
|
|
|
- Location ogcLocation = new Location();
|
|
|
- ogcLocation.setId(id);
|
|
|
- ogcLocation.setSelfLink(format("%s/Locations(%s)", uriComponent.getGatewayUri(), id));
|
|
|
- ogcLocation.setHistoricalLocationsNavigationLink("unknown");
|
|
|
- ogcLocation.setName(afcUnit.getResourceType());
|
|
|
- ogcLocation.setDescription(afcUnit.getResourceUrn());
|
|
|
- ogcLocation.setEncodingType("application/vnd.geo+json");
|
|
|
+ MultiSensor afcMultiSensor = client.getSensorByResourceUrn(resourceUrn);
|
|
|
+ Thing ogcThing = Converter.convertToThing(afcMultiSensor, uriComponent);
|
|
|
+ ctx.response().putHeader(CONTENT_TYPE, APPLICATION_JSON).end(ogcThing.encode());
|
|
|
+ });
|
|
|
|
|
|
- Location.Info info = new Location.Info();
|
|
|
- info.setType("Feature");
|
|
|
- ogcLocation.setLocation(info);
|
|
|
+ router().get(create("Datastreams(:id)")).handler(ctx -> {
|
|
|
+ RequestUriComponent uriComponent = parseUriToComponents(ctx.request());
|
|
|
+ String id = ctx.pathParam("id"); // resourceUrn + observedProperty
|
|
|
+ String[] idCmp = Converter.disassemblyId(id);
|
|
|
+ String resourceUrn = idCmp[0], observedProperty = idCmp[1];
|
|
|
+ MultiSensor afcMultiSensor = client.getSensorByResourceUrn(resourceUrn);
|
|
|
+ List<ResourceMeasurement> afcMeasurements = client.getLatestObservationsBySensor(new Filter()
|
|
|
+ .limit(1)
|
|
|
+ .entityNames(afcMultiSensor.getResourceId())
|
|
|
+ .measurements(observedProperty)
|
|
|
+ );
|
|
|
+ final Supplier<IllegalArgumentException> exception = () -> new IllegalArgumentException("Can not find Datastream with @iot.id \"" + id + "\".");
|
|
|
|
|
|
- Geometry geometry = new Geometry();
|
|
|
- geometry.setType("Point");
|
|
|
- geometry.setCoordinates(asList(afcUnit.getLatitude(), afcUnit.getLongitude()));
|
|
|
- info.setGeometry(geometry);
|
|
|
+ Optional<MultiSensor.SensorSchema> afcSensorOpt = afcMultiSensor.getObservations().stream().filter(s -> s.getObservedProperty().equals(observedProperty)).findFirst();
|
|
|
+ MultiSensor.SensorSchema afcSensor = afcSensorOpt.orElseThrow(exception);
|
|
|
|
|
|
- /*
|
|
|
- Location example = new Location();
|
|
|
- example.setId(Integer.parseInt(id));
|
|
|
- example.setSelfLink(format("%s/Locations(%s)", uriComponent.getGatewayUri(), id));
|
|
|
- example.setHistoricalLocationsNavigationLink(format("Locations(%s)/HistoricalLocations", id));
|
|
|
- example.setEncodingType("application/vnd.geo+json");
|
|
|
+ Optional<ResourceMeasurement> afcMeasurementOpt = ofNullable(afcMeasurements.size() == 1 ? afcMeasurements.get(0) : null);
|
|
|
+ ResourceMeasurement afcMeasurement = afcMeasurementOpt.orElseThrow(exception);
|
|
|
|
|
|
- example.setName("CCIT");
|
|
|
- example.setDescription("Calgary Center for Innvative Technologies");
|
|
|
+ Optional<SensorTelemetry> afcTelemetryOpt = ofNullable(afcMeasurement.getMeasurements().size() == 1 ? afcMeasurement.getMeasurements().get(0) : null);
|
|
|
+ SensorTelemetry afcTelemetry = afcTelemetryOpt.orElseThrow(exception);
|
|
|
|
|
|
- Location.Info exampleInfo = new Location.Info();
|
|
|
- exampleInfo.setType("Feature");
|
|
|
- example.setLocation(exampleInfo);
|
|
|
+ Datastream datastream = Converter.convertToDataStream(afcMultiSensor, afcSensor, afcTelemetry, uriComponent);
|
|
|
+ ctx.response().putHeader(CONTENT_TYPE, APPLICATION_JSON).end(datastream.encode());
|
|
|
+ });
|
|
|
|
|
|
- Geometry exampleGeometry = new Geometry();
|
|
|
- exampleGeometry.setType("Point");
|
|
|
- exampleGeometry.setCoordinates(asList(-114.06,51.05));
|
|
|
- exampleInfo.setGeometry(exampleGeometry);
|
|
|
- */
|
|
|
+ router().get(create("Things(:id)/Datastreams")).handler(ctx -> {
|
|
|
+ RequestUriComponent uriComponent = parseUriToComponents(ctx.request());
|
|
|
+ String resourceUrn = ctx.pathParam("id"); // resourceUrn
|
|
|
+ MultiSensor afcMultiSensor = client.getSensorByResourceUrn(resourceUrn);
|
|
|
+ List<ResourceMeasurement> afcMeasurements = client.getLatestObservationsBySensor(new Filter()
|
|
|
+ .limit(1)
|
|
|
+ .entityNames(afcMultiSensor.getResourceId())
|
|
|
+ );
|
|
|
+ ResourceMeasurement afcMeasurement = afcMeasurements.size() == 1 ? afcMeasurements.get(0) : null;
|
|
|
+ List<Datastream> ogcDataStream = Converter.convertToDataStream(afcMultiSensor, afcMeasurement, uriComponent);
|
|
|
+ ctx.response().putHeader(CONTENT_TYPE, APPLICATION_JSON).end(encode(ogcDataStream));
|
|
|
+ });
|
|
|
|
|
|
- ctx.response().putHeader(CONTENT_TYPE, APPLICATION_JSON).end(ogcLocation.encode());
|
|
|
+ router().get(create("Sensors(:id)/Datastreams")).handler(ctx -> {
|
|
|
+ RequestUriComponent uriComponent = parseUriToComponents(ctx.request());
|
|
|
+ String resourceUrn = ctx.pathParam("id"); // resourceUrn
|
|
|
+ ctx.reroute(format("%s/Things(%s)/Datastreams", uriComponent.getGatewayPath(), resourceUrn));
|
|
|
});
|
|
|
|
|
|
- router().get(create("Datastreams(:id)")).handler(ctx -> {
|
|
|
+ router().get(create("ObservedProperties(:id)/Datastream")).handler(ctx -> {
|
|
|
RequestUriComponent uriComponent = parseUriToComponents(ctx.request());
|
|
|
- String id = ctx.pathParam("id");
|
|
|
+ String id = ctx.pathParam("id"); // resourceUrn + observedProperty
|
|
|
+ ctx.reroute(format("%s/Datastreams(%s)", uriComponent.getGatewayPath(), id));
|
|
|
+ });
|
|
|
|
|
|
- Datastream datastream = new Datastream();
|
|
|
- datastream.setId(id);
|
|
|
- datastream.setSelfLink(format("%s/Datastreams(%s)", uriComponent.getGatewayUri(), id));
|
|
|
- datastream.setThingNavigationLink(format("HistoricalLocations(%s)/Thing", id));
|
|
|
- datastream.setSensorNavigationLink(format("Datastreams(%s)/Sensor", id));
|
|
|
- datastream.setObservedPropertyNavigationLink(format("Datastreams(%s)/ObservedProperty", id));
|
|
|
- datastream.setObservationsNavigationLink(format("Datastreams(%s)/Observations", id));
|
|
|
- datastream.setName("oven temperature");
|
|
|
- datastream.setDescription("This is a datastream measuring the air temperature in an oven.");
|
|
|
-
|
|
|
- Datastream.Unit unit = new Datastream.Unit();
|
|
|
- unit.setName("degree Celsius");
|
|
|
- unit.setSymbol("\u00B0" + "C");
|
|
|
- unit.setDefinition("http://unitsofmeasure.org/ucum.html#para-30");
|
|
|
- datastream.setUnitOfMeasurement(unit);
|
|
|
+ router().get(create("Observations(:id)/Datastream")).handler(ctx -> {
|
|
|
+ RequestUriComponent uriComponent = parseUriToComponents(ctx.request());
|
|
|
+ String id = ctx.pathParam("id"); // resource + measurement + time
|
|
|
+ String[] idCmp = Converter.disassemblyId(id);
|
|
|
+ String resource = idCmp[0], measurement = idCmp[1];
|
|
|
+ MultiSensor afcMultiSensor = client.getSensorByResourceId(resource);
|
|
|
+ String resourceUrn = afcMultiSensor.getResourceUrn();
|
|
|
+ ctx.reroute(format("%s/Datastreams(%s)", uriComponent.getGatewayPath(), Converter.assemblyId(resourceUrn, measurement)));
|
|
|
+ });
|
|
|
|
|
|
- datastream.setObservationType("http://www.opengis.net/def/observationType/OGC-OM/2.0/OM_Measurement");
|
|
|
+ router().get(create("Sensors(:id)")).handler(ctx -> {
|
|
|
+ RequestUriComponent uriComponent = parseUriToComponents(ctx.request());
|
|
|
+ String resourceUrn = ctx.pathParam("id"); // resourceUrn
|
|
|
+ MultiSensor afcMultiSensor = client.getSensorByResourceUrn(resourceUrn);
|
|
|
+ Sensor ogcSensor = Converter.convertToSensor(afcMultiSensor, uriComponent);
|
|
|
+ ctx.response().putHeader(CONTENT_TYPE, APPLICATION_JSON).end(ogcSensor.encode());
|
|
|
+ });
|
|
|
|
|
|
- Datastream.Area area = new Datastream.Area();
|
|
|
- area.setType("Polygon");
|
|
|
- area.setCoordinates(asList(
|
|
|
- asList(100, 0),
|
|
|
- asList(101, 0),
|
|
|
- asList(101, 1),
|
|
|
- asList(100, 1),
|
|
|
- asList(100, 0)
|
|
|
- ));
|
|
|
- datastream.setObservedArea(area);
|
|
|
+ router().get(create("Datastreams(:id)/Sensor")).handler(ctx -> {
|
|
|
+ RequestUriComponent uriComponent = parseUriToComponents(ctx.request());
|
|
|
+ String id = ctx.pathParam("id"); // resourceUrn + observedProperty
|
|
|
+ String[] idCmp = Converter.disassemblyId(id);
|
|
|
+ String resourceUrn = idCmp[0];
|
|
|
+ ctx.reroute(format("%s/Sensors(%s)", uriComponent.getGatewayPath(), resourceUrn));
|
|
|
+ });
|
|
|
|
|
|
- datastream.setPhenomenonTime("2014-03-01T13:00:00Z/2015-05-11T15:30:00Z");
|
|
|
- datastream.setResultTime("2014-03-01T13:00:00Z/2015-05-11T15:30:00Z");
|
|
|
+ router().get(create("ObservedProperties(:id)")).handler(ctx -> {
|
|
|
+ RequestUriComponent uriComponent = parseUriToComponents(ctx.request());
|
|
|
+ String id = ctx.pathParam("id"); // resourceUrn + observedProperty
|
|
|
+ String[] idCmp = Converter.disassemblyId(id);
|
|
|
+ String resourceUrn = idCmp[0], observedProperty = idCmp[1];
|
|
|
+ final Supplier<IllegalArgumentException> exception = () -> new IllegalArgumentException("Can not find Datastream with @iot.id \"" + id + "\".");
|
|
|
+ MultiSensor afcMultiSensor = client.getSensorByResourceUrn(resourceUrn);
|
|
|
+ Optional<MultiSensor.SensorSchema> afcSensorOpt = afcMultiSensor.getObservations().stream().filter(s -> s.getObservedProperty().equals(observedProperty)).findFirst();
|
|
|
+ MultiSensor.SensorSchema afcSensor = afcSensorOpt.orElseThrow(exception);
|
|
|
+ ObservedProperty property = Converter.convertToObservedProperty(afcMultiSensor, afcSensor, uriComponent);
|
|
|
+ ctx.response().putHeader(CONTENT_TYPE, APPLICATION_JSON).end(property.encode());
|
|
|
+ });
|
|
|
|
|
|
- ctx.response().putHeader(CONTENT_TYPE, APPLICATION_JSON).end(datastream.encode());
|
|
|
+ router().get(create("Datastreams(:id)/ObservedProperty")).handler(ctx -> {
|
|
|
+ RequestUriComponent uriComponent = parseUriToComponents(ctx.request());
|
|
|
+ String id = ctx.pathParam("id"); // resourceUrn + observedProperty
|
|
|
+ ctx.reroute(format("%s/ObservedProperties(%s)", uriComponent.getGatewayPath(), id));
|
|
|
});
|
|
|
|
|
|
- router().get(create("HistoricalLocations(:id)")).handler(ctx -> {
|
|
|
+ router().get(create("Observations(:id)")).handler(ctx -> {
|
|
|
RequestUriComponent uriComponent = parseUriToComponents(ctx.request());
|
|
|
- int id = Integer.parseInt(ctx.pathParam("id"));
|
|
|
+ String id = ctx.pathParam("id"); // resource + measurement + time
|
|
|
+ String[] idCmp = Converter.disassemblyId(id);
|
|
|
+ String resource = idCmp[0], measurement = idCmp[1];
|
|
|
|
|
|
- HistoricalLocation historicalLocation = new HistoricalLocation();
|
|
|
+ List<ResourceMeasurement> measurements = client.getLatestObservationsBySensor(new Filter()
|
|
|
+ .limit(1).entityNames(resource).measurements(measurement)
|
|
|
+ );
|
|
|
+ final Supplier<IllegalArgumentException> exception = () -> new IllegalArgumentException("Can not find Datastream with @iot.id \"" + id + "\".");
|
|
|
|
|
|
- List<HistoricalLocation.Value> valueList = new ArrayList<>();
|
|
|
- for (int valueId = id; valueId < id + 2; valueId++) {
|
|
|
- HistoricalLocation.Value value = new HistoricalLocation.Value();
|
|
|
- value.setId(String.valueOf(valueId));
|
|
|
- value.setSelfLink(format("%s/HistoricalLocations(%s)", uriComponent.getGatewayUri(), valueId));
|
|
|
- value.setLocationsNavigationLink(format("HistoricalLocations(%s)/Locations", valueId));
|
|
|
- value.setThingNavigationLink(format("HistoricalLocations(%s)/Thing", valueId));
|
|
|
- value.setTime("2015-01-25T12:00:00-07:00");
|
|
|
- valueList.add(value);
|
|
|
- }
|
|
|
- historicalLocation.setValue(valueList);
|
|
|
- historicalLocation.setNextLink(format("%s/Things(%s)/HistoricalLocations?$skip=%s&top=%s", uriComponent.getDomain(), id, valueList.size(), valueList.size()));
|
|
|
+ Optional<ResourceMeasurement> measurementOpt = ofNullable(measurements.size() == 1 ? measurements.get(0) : null);
|
|
|
+ ResourceMeasurement afcMeasurement = measurementOpt.orElseThrow(exception);
|
|
|
+
|
|
|
+ Optional<SensorTelemetry> telemetryOpt = ofNullable(afcMeasurement.getMeasurements().size() == 1 ? afcMeasurement.getMeasurements().get(0) : null);
|
|
|
+ SensorTelemetry afcTelemetry = telemetryOpt.orElseThrow(exception);
|
|
|
+
|
|
|
+ Optional<io.connector.model.afarcloud.Observation> observationOpt = ofNullable(afcTelemetry.getObservations().size() == 1 ? afcTelemetry.getObservations().get(0) : null);
|
|
|
+ io.connector.model.afarcloud.Observation afcObservation = observationOpt.orElseThrow(exception);
|
|
|
|
|
|
- ctx.response().putHeader(CONTENT_TYPE, APPLICATION_JSON).end(historicalLocation.encode());
|
|
|
+ Observation ogcObservation = Converter.convertToObservation(afcMeasurement, afcTelemetry, afcObservation, uriComponent);
|
|
|
+ ctx.response().putHeader(CONTENT_TYPE, APPLICATION_JSON).end(ogcObservation.encode());
|
|
|
});
|
|
|
|
|
|
- router().get(create("Sensors")).handler(ctx -> {
|
|
|
+ // without filter
|
|
|
+ router().get(create("Datastreams(:id)/Observations")).handler(ctx -> {
|
|
|
RequestUriComponent uriComponent = parseUriToComponents(ctx.request());
|
|
|
- List<Unit> afcAllSensors = client.getAllSensors();
|
|
|
- List<Sensor> ogcSensors = Converter.convertSensors(afcAllSensors, uriComponent);
|
|
|
- ctx.response().putHeader(CONTENT_TYPE, APPLICATION_JSON).end(encode(ogcSensors));
|
|
|
+ String id = ctx.pathParam("id"); // resourceUrn + observedProperty
|
|
|
+ String filter = ctx.request().getParam("filter"); // TODO filter
|
|
|
+
|
|
|
+ String [] idCmp = Converter.disassemblyId(id);
|
|
|
+ String resourceUrn = idCmp[0], observedProperty = idCmp[1];
|
|
|
+
|
|
|
+ MultiSensor afcMultiSensor = client.getSensorByResourceUrn(resourceUrn);
|
|
|
+ List<ResourceMeasurement> measurements = client.getLatestObservationsBySensor(new Filter()
|
|
|
+ .limit(1).entityNames(afcMultiSensor.getResourceId()).measurements(observedProperty)
|
|
|
+ );
|
|
|
+ final Supplier<IllegalArgumentException> exception = () -> new IllegalArgumentException("Can not find Datastream with @iot.id \"" + id + "\".");
|
|
|
+
|
|
|
+ Optional<ResourceMeasurement> measurementOpt = ofNullable(measurements.size() == 1 ? measurements.get(0) : null);
|
|
|
+ ResourceMeasurement afcMeasurement = measurementOpt.orElseThrow(exception);
|
|
|
+
|
|
|
+ Optional<SensorTelemetry> telemetryOpt = ofNullable(afcMeasurement.getMeasurements().size() == 1 ? afcMeasurement.getMeasurements().get(0) : null);
|
|
|
+ SensorTelemetry afcTelemetry = telemetryOpt.orElseThrow(exception);
|
|
|
+
|
|
|
+ Optional<io.connector.model.afarcloud.Observation> observationOpt = ofNullable(afcTelemetry.getObservations().size() == 1 ? afcTelemetry.getObservations().get(0) : null);
|
|
|
+ io.connector.model.afarcloud.Observation afcObservation = observationOpt.orElseThrow(exception);
|
|
|
+
|
|
|
+ Observation ogcObservation = Converter.convertToObservation(afcMeasurement, afcTelemetry, afcObservation, uriComponent);
|
|
|
+ List<Observation> ogcObservations = Collections.singletonList(ogcObservation);
|
|
|
+ ctx.response().putHeader(CONTENT_TYPE, APPLICATION_JSON).end(encode(ogcObservations));
|
|
|
});
|
|
|
|
|
|
- router().get(create("Sensors(:id)")).handler(ctx -> {
|
|
|
+ router().get(create("FeaturesOfInterest(:id)")).handler(ctx -> {
|
|
|
RequestUriComponent uriComponent = parseUriToComponents(ctx.request());
|
|
|
String id = ctx.pathParam("id");
|
|
|
- Unit afcUnit = client.getSensor(id);
|
|
|
- Sensor ogcSensor = Converter.convertSensor(afcUnit, uriComponent);
|
|
|
-
|
|
|
- /*
|
|
|
- Sensor example = new Sensor();
|
|
|
- example.setId(Integer.parseInt(id));
|
|
|
- example.setSelfLink(format("%s/Sensors(%s)", uriComponent.getGatewayUri(), id));
|
|
|
- example.setDataStreamNavigationLink(format("Sensors(%s)/Datastreams", id));
|
|
|
- example.setName("TMP36");
|
|
|
- example.setDescription("TMP36 - Analog Temperature sensor");
|
|
|
- example.setEncodingType("application/pdf");
|
|
|
- example.setMetadata("http://example.org/TMP35_36_37.pdf");
|
|
|
- */
|
|
|
+ FeatureOfInterest featureOfInterest = new FeatureOfInterest();
|
|
|
+ featureOfInterest.setId(id);
|
|
|
+ featureOfInterest.setSelfLink("https://storage07-afarcloud.qa.pdmfc.com/storage/rest/registry/getAllObservationTypes");
|
|
|
|
|
|
- ctx.response().putHeader(CONTENT_TYPE, APPLICATION_JSON).end(ogcSensor.encode());
|
|
|
+ ctx.response().putHeader(CONTENT_TYPE, APPLICATION_JSON).end(featureOfInterest.encode());
|
|
|
});
|
|
|
|
|
|
- router().get(create("ObservedProperties(:id)")).handler(ctx -> {
|
|
|
+ router().get(create("Locations(:id)")).handler(ctx -> {
|
|
|
RequestUriComponent uriComponent = parseUriToComponents(ctx.request());
|
|
|
- String id = ctx.pathParam("id");
|
|
|
+ String id = ctx.pathParam("id"); // resourceUrn + observedProperty + time
|
|
|
+ String [] idCmp = Converter.disassemblyId(id);
|
|
|
+ String resourceUrn = idCmp[0], observedProperty = idCmp[1], time = idCmp[2];
|
|
|
+ final DateTimeFormatter formatter = new DateTimeFormatterBuilder().append(ofPattern("yyyy-MM-dd HH:mm"))
|
|
|
+ .toFormatter().withZone(ZoneId.of("UTC"));
|
|
|
+
|
|
|
+ Instant startTime = Instant.parse(time);
|
|
|
+ Instant endTime = startTime.plusSeconds(60);
|
|
|
+
|
|
|
+ MultiSensor afcMultiSensor = client.getSensorByResourceUrn(resourceUrn);
|
|
|
+ List<ResourceMeasurement> afcMeasurements = client.getObservationsBySensor(new Filter()
|
|
|
+ .startTime(formatter.format(startTime)).endTime(formatter.format(endTime))
|
|
|
+ .entityNames(afcMultiSensor.getResourceId()).measurements(observedProperty)
|
|
|
+ );
|
|
|
+ final Supplier<IllegalArgumentException> exception = () -> new IllegalArgumentException("Can not find Location with @iot.id \"" + resourceUrn + "\".");
|
|
|
|
|
|
- ObservedProperty observedProperty = new ObservedProperty();
|
|
|
- observedProperty.setId(id);
|
|
|
- observedProperty.setSelfLink(format("%s/ObservedProperties(%s)", uriComponent.getGatewayUri(), id));
|
|
|
- observedProperty.setDataStreamNavigationLink(format("ObservedProperties(%s)/Datastreams", id));
|
|
|
- observedProperty.setDescription("The dewpoint temperature is the temperature to which the air must be cooled, at constant pressure, for dew to form. As the grass and other objects near the ground cool to the dewpoint, some of the water vapor in the atmosphere condenses into liquid water on the objects.");
|
|
|
- observedProperty.setName("DewPoint Temperature");
|
|
|
- observedProperty.setDefinition("http://dbpedia.org/page/Dew_point");
|
|
|
-
|
|
|
- ctx.response().putHeader(CONTENT_TYPE, APPLICATION_JSON).end(observedProperty.encode());
|
|
|
+ Optional<ResourceMeasurement> afcMeasurementOpt = ofNullable(afcMeasurements.size() == 1 ? afcMeasurements.get(0) : null);
|
|
|
+ ResourceMeasurement afcMeasurement = afcMeasurementOpt.orElseThrow(exception);
|
|
|
+
|
|
|
+ AFCLocationList afcLocations = AFCLocationUtils.sort(afcMeasurement);
|
|
|
+ Optional<AFCAggrLocation> afcLastLocationOpt = ofNullable(afcLocations.getLast());
|
|
|
+ AFCAggrLocation afcLastLocation = afcLastLocationOpt.orElseThrow(exception);
|
|
|
+
|
|
|
+ Location ogcLocation = Converter.convertToLocation(afcMultiSensor, afcLastLocation, uriComponent);
|
|
|
+ ctx.response().putHeader(CONTENT_TYPE, APPLICATION_JSON).end(ogcLocation.encode());
|
|
|
});
|
|
|
|
|
|
- router().get(create("Observations(:id)")).handler(ctx -> {
|
|
|
+ router().get(create("Things(:id)/Locations")).handler(ctx -> {
|
|
|
RequestUriComponent uriComponent = parseUriToComponents(ctx.request());
|
|
|
- String id = ctx.pathParam("id");
|
|
|
+ String resourceUrn = ctx.pathParam("id"); // resourceUrn
|
|
|
|
|
|
- Observation observation = new Observation();
|
|
|
- observation.setId(id);
|
|
|
- observation.setSelfLink(format("%s/Observations(%s)", uriComponent.getGatewayUri(), id));
|
|
|
- observation.setFeatureOfInterestNavigationLink(format("Observations(%s)/FeatureOfInterest", id));
|
|
|
- observation.setDataStreamNavigationLink(format("Observations(%s)/Datastream", id));
|
|
|
- observation.setPhenomenonTime("2014-12-31T11:59:59.00+08:00");
|
|
|
- observation.setResultTime("2014-12-31T11:59:59.00+08:00");
|
|
|
- observation.setResult(70.4);
|
|
|
-
|
|
|
- ctx.response().putHeader(CONTENT_TYPE, APPLICATION_JSON).end(observation.encode());
|
|
|
+ MultiSensor afcMultiSensor = client.getSensorByResourceUrn(resourceUrn);
|
|
|
+ List<ResourceMeasurement> afcMeasurements = client.getLatestObservationsBySensor(new Filter()
|
|
|
+ .limit(1).entityNames(afcMultiSensor.getResourceId())
|
|
|
+ );
|
|
|
+ final Supplier<IllegalArgumentException> exception = () -> new IllegalArgumentException("Can not find Thing with @iot.id \"" + resourceUrn + "\".");
|
|
|
+
|
|
|
+ Optional<ResourceMeasurement> afcMeasurementOpt = ofNullable(afcMeasurements.size() == 1 ? afcMeasurements.get(0) : null);
|
|
|
+ ResourceMeasurement afcMeasurement = afcMeasurementOpt.orElseThrow(exception);
|
|
|
+
|
|
|
+ AFCLocationList afcLocations = AFCLocationUtils.sort(afcMeasurement);
|
|
|
+ Optional<AFCAggrLocation> afcLastLocationOpt = ofNullable(afcLocations.getFirst());
|
|
|
+ AFCAggrLocation afcLastLocation = afcLastLocationOpt.orElseThrow(exception);
|
|
|
+
|
|
|
+ Location ogcLocation = Converter.convertToLocation(afcMultiSensor, afcLastLocation, uriComponent);
|
|
|
+ List<Location> ogcLocations = Collections.singletonList(ogcLocation);
|
|
|
+ ctx.response().putHeader(CONTENT_TYPE, APPLICATION_JSON).end(encode(ogcLocations));
|
|
|
});
|
|
|
|
|
|
- router().get(create("FeaturesOfInterest(:id)")).handler(ctx -> {
|
|
|
+ router().get(create("HistoricalLocations(:id)/Locations")).handler(ctx -> {
|
|
|
RequestUriComponent uriComponent = parseUriToComponents(ctx.request());
|
|
|
- String id = ctx.pathParam("id");
|
|
|
+ String id = ctx.pathParam("id"); // resourceUrn + observedProperty + time
|
|
|
+ ctx.reroute(format("%s/Locations(%s)", uriComponent.getGatewayPath(), id));
|
|
|
+ });
|
|
|
|
|
|
- FeatureOfInterest featureOfInterest = new FeatureOfInterest();
|
|
|
- featureOfInterest.setId(id);
|
|
|
- featureOfInterest.setSelfLink(format("%s/FeaturesOfInterest(%s)", uriComponent.getGatewayUri(), id));
|
|
|
- featureOfInterest.setObservationsNavigationLink(format("FeaturesOfInterest(%s)/Observations", id));
|
|
|
- featureOfInterest.setName("Weather Station YYC.");
|
|
|
- featureOfInterest.setDescription("This is a weather station located at the Calgary Airport.");
|
|
|
- featureOfInterest.setEncodingType("application/vnd.geo+json");
|
|
|
+ router().get(create("HistoricalLocations(:id)")).handler(ctx -> {
|
|
|
+ RequestUriComponent uriComponent = parseUriToComponents(ctx.request());
|
|
|
+ String id = ctx.pathParam("id"); // resourceUrn + observedProperty + time
|
|
|
|
|
|
- FeatureOfInterest.Feature feature = new FeatureOfInterest.Feature();
|
|
|
- feature.setType("Feature");
|
|
|
- featureOfInterest.setFeature(feature);
|
|
|
+ String [] idCmp = Converter.disassemblyId(id);
|
|
|
+ String resourceUrn = idCmp[0], observedProperty = idCmp[1], time = idCmp[2];
|
|
|
+ final DateTimeFormatter formatter = new DateTimeFormatterBuilder().append(ofPattern("yyyy-MM-dd HH:mm"))
|
|
|
+ .toFormatter().withZone(ZoneId.of("UTC"));
|
|
|
|
|
|
- Geometry geometry = new Geometry();
|
|
|
- geometry.setType("Point");
|
|
|
- geometry.setCoordinates(asList(-114.06, 51.05));
|
|
|
- feature.setGeometry(geometry);
|
|
|
+ Instant startTime = Instant.parse(time);
|
|
|
+ Instant endTime = startTime.plusSeconds(60);
|
|
|
|
|
|
- ctx.response().putHeader(CONTENT_TYPE, APPLICATION_JSON).end(featureOfInterest.encode());
|
|
|
+ MultiSensor afcMultiSensor = client.getSensorByResourceUrn(resourceUrn);
|
|
|
+ List<ResourceMeasurement> afcMeasurements = client.getObservationsBySensor(new Filter()
|
|
|
+ .startTime(formatter.format(startTime)).endTime(formatter.format(endTime))
|
|
|
+ .entityNames(afcMultiSensor.getResourceId()).measurements(observedProperty)
|
|
|
+ );
|
|
|
+ final Supplier<IllegalArgumentException> exception = () -> new IllegalArgumentException("Can not find Location with @iot.id \"" + resourceUrn + "\".");
|
|
|
+
|
|
|
+ Optional<ResourceMeasurement> afcMeasurementOpt = ofNullable(afcMeasurements.size() == 1 ? afcMeasurements.get(0) : null);
|
|
|
+ ResourceMeasurement afcMeasurement = afcMeasurementOpt.orElseThrow(exception);
|
|
|
+
|
|
|
+ AFCLocationList afcLocations = AFCLocationUtils.sort(afcMeasurement);
|
|
|
+ Optional<AFCAggrLocation> afcLastLocationOpt = ofNullable(afcLocations.getLast());
|
|
|
+ AFCAggrLocation afcLocation = afcLastLocationOpt.orElseThrow(exception);
|
|
|
+
|
|
|
+ HistoricalLocation ogcLocation = Converter.convertToHistoricalLocation(afcMultiSensor, afcLocation, uriComponent);
|
|
|
+ ctx.response().putHeader(CONTENT_TYPE, APPLICATION_JSON).end(ogcLocation.encode());
|
|
|
+ });
|
|
|
+
|
|
|
+ // without filter
|
|
|
+ router().get(create("Things(:id)/HistoricalLocations")).handler(ctx -> {
|
|
|
+ RequestUriComponent uriComponent = parseUriToComponents(ctx.request());
|
|
|
+ String resourceUrn = ctx.pathParam("id"); // resourceUrn
|
|
|
+ String filter = ctx.request().getParam("filter"); // TODO filter
|
|
|
+
|
|
|
+ final DateTimeFormatter formatter = new DateTimeFormatterBuilder().append(ofPattern("yyyy-MM-dd HH:mm"))
|
|
|
+ .toFormatter().withZone(ZoneId.of("UTC"));
|
|
|
+
|
|
|
+ MultiSensor afcMultiSensor = client.getSensorByResourceUrn(resourceUrn);
|
|
|
+ List<ResourceMeasurement> afcMeasurements;
|
|
|
+ if (filter != null && !filter.isEmpty()) {
|
|
|
+ String time = ""; // TODO parse filter
|
|
|
+
|
|
|
+ Instant startTime = Instant.parse(time);
|
|
|
+ Instant endTime = startTime.plusSeconds(60);
|
|
|
+
|
|
|
+ afcMeasurements = client.getObservationsBySensor(new Filter()
|
|
|
+ .startTime(formatter.format(startTime)).endTime(formatter.format(endTime))
|
|
|
+ .entityNames(afcMultiSensor.getResourceId())
|
|
|
+ );
|
|
|
+ } else {
|
|
|
+ afcMeasurements = client.getLatestObservationsBySensor(new Filter()
|
|
|
+ .limit(1).entityNames(afcMultiSensor.getResourceId())
|
|
|
+ );
|
|
|
+ }
|
|
|
+
|
|
|
+ final Supplier<IllegalArgumentException> exception = () -> new IllegalArgumentException("Can not find HistoricalLocations of the Thing with @iot.id \"" + resourceUrn + "\".");
|
|
|
+
|
|
|
+ Optional<ResourceMeasurement> afcMeasurementOpt = ofNullable(afcMeasurements.size() == 1 ? afcMeasurements.get(0) : null);
|
|
|
+ ResourceMeasurement afcMeasurement = afcMeasurementOpt.orElseThrow(exception);
|
|
|
+
|
|
|
+ AFCLocationList afcLocations = AFCLocationUtils.sort(afcMeasurement);
|
|
|
+
|
|
|
+ List<HistoricalLocation> locations = Converter.convertToHistoricalLocation(afcMultiSensor, afcLocations.getList(), uriComponent);
|
|
|
+ ctx.response().putHeader(CONTENT_TYPE, APPLICATION_JSON).end(encode(locations));
|
|
|
});
|
|
|
+
|
|
|
+ // without filter
|
|
|
+ router().get(create("Locations(:id)/HistoricalLocations")).handler(ctx -> {
|
|
|
+ RequestUriComponent uriComponent = parseUriToComponents(ctx.request());
|
|
|
+ String id = ctx.pathParam("id"); // resourceUrn + observedProperty + time
|
|
|
+ String filter = ctx.request().getParam("filter"); // TODO filter
|
|
|
+
|
|
|
+ String [] idCmp = Converter.disassemblyId(id);
|
|
|
+ String resourceUrn = idCmp[0], observedProperty = idCmp[1], time = idCmp[2];
|
|
|
+
|
|
|
+ final DateTimeFormatter formatter = new DateTimeFormatterBuilder().append(ofPattern("yyyy-MM-dd HH:mm"))
|
|
|
+ .toFormatter().withZone(ZoneId.of("UTC"));
|
|
|
+
|
|
|
+ final Supplier<IllegalArgumentException> exception =
|
|
|
+ () -> new IllegalArgumentException("Can not find HistoricalLocations of the Thing with @iot.id \"" + resourceUrn + "\".");
|
|
|
+
|
|
|
+ MultiSensor afcMultiSensor = client.getSensorByResourceUrn(resourceUrn);
|
|
|
+
|
|
|
+ Instant startTime = Instant.parse(time);
|
|
|
+ Instant endTime = startTime.plusSeconds(60*60); // 1h
|
|
|
+
|
|
|
+ List<ResourceMeasurement> afcMeasurements = client.getObservationsBySensor(new Filter()
|
|
|
+ .startTime(formatter.format(startTime)).endTime(formatter.format(endTime))
|
|
|
+ .entityNames(afcMultiSensor.getResourceId()).measurements(observedProperty)
|
|
|
+ );
|
|
|
+
|
|
|
+ Optional<ResourceMeasurement> afcMeasurementOpt = ofNullable(afcMeasurements.size() == 1 ? afcMeasurements.get(0) : null);
|
|
|
+ ResourceMeasurement afcMeasurement = afcMeasurementOpt.orElseThrow(exception);
|
|
|
+
|
|
|
+ AFCLocationList afcLocations = AFCLocationUtils.sort(afcMeasurement);
|
|
|
+
|
|
|
+ List<HistoricalLocation> locations = Converter.convertToHistoricalLocation(afcMultiSensor, afcLocations.getList(), uriComponent);
|
|
|
+ ctx.response().putHeader(CONTENT_TYPE, APPLICATION_JSON).end(encode(locations));
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ private static class AFCAggrLocation implements Comparable<AFCAggrLocation> {
|
|
|
+ private final String measurement;
|
|
|
+ private final io.connector.model.afarcloud.Observation observation;
|
|
|
+
|
|
|
+ public AFCAggrLocation(String measurement, io.connector.model.afarcloud.Observation observation) {
|
|
|
+ this.measurement = measurement;
|
|
|
+ this.observation = observation;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public boolean equals(Object o) {
|
|
|
+ if (this == o) return true;
|
|
|
+ if (o == null || getClass() != o.getClass()) return false;
|
|
|
+ AFCAggrLocation that = (AFCAggrLocation) o;
|
|
|
+ return this.compareTo(that) == 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public int hashCode() {
|
|
|
+ return Objects.hash(measurement, observation);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public int compareTo(AFCAggrLocation o) {
|
|
|
+ io.connector.model.afarcloud.Observation o1 = this.observation;
|
|
|
+ io.connector.model.afarcloud.Observation o2 = o.observation;
|
|
|
+
|
|
|
+ Instant o1Time = Instant.parse(o1.getTime());
|
|
|
+ Instant o2Time = Instant.parse(o2.getTime());
|
|
|
+
|
|
|
+ if (o1Time.equals(o2Time)) {
|
|
|
+ Double o1Dist = sqrt(pow(o1.getLongitude(), 2) + pow(o1.getLatitude(), 2) + pow(o1.getAltitude(), 2));
|
|
|
+ Double o2Dist = sqrt(pow(o2.getLongitude(), 2) + pow(o2.getLatitude(), 2) + pow(o2.getAltitude(), 2));
|
|
|
+ return o1Dist.compareTo(o2Dist);
|
|
|
+ } else {
|
|
|
+ return o1Time.compareTo(o2Time);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private static class AFCLocationList {
|
|
|
+ private final List<AFCAggrLocation> list;
|
|
|
+
|
|
|
+ AFCLocationList() {
|
|
|
+ this.list = new ArrayList<>();
|
|
|
+ }
|
|
|
+
|
|
|
+ public void sort() {
|
|
|
+ Collections.sort(list);
|
|
|
+ }
|
|
|
+
|
|
|
+ public void add(AFCAggrLocation location) {
|
|
|
+ list.add(location);
|
|
|
+ }
|
|
|
+
|
|
|
+ public AFCAggrLocation getFirst() {
|
|
|
+ return list.isEmpty() ? null : list.get(0);
|
|
|
+ }
|
|
|
+
|
|
|
+ public AFCAggrLocation getLast() {
|
|
|
+ return list.isEmpty() ? null : list.get(list.size()-1);
|
|
|
+ }
|
|
|
+
|
|
|
+ public AFCAggrLocation get(int index) {
|
|
|
+ return list.get(index);
|
|
|
+ }
|
|
|
+
|
|
|
+ public List<AFCAggrLocation> getList() {
|
|
|
+ return list;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private static class AFCLocationUtils {
|
|
|
+
|
|
|
+ static AFCLocationList sort(ResourceMeasurement afcMeasurement) {
|
|
|
+ Objects.requireNonNull(afcMeasurement);
|
|
|
+
|
|
|
+ AFCLocationList aggrLocations = new AFCLocationList();
|
|
|
+ for (SensorTelemetry measurement : afcMeasurement.getMeasurements()) {
|
|
|
+ for (io.connector.model.afarcloud.Observation observation : measurement.getObservations()) {
|
|
|
+ aggrLocations.add(new AFCAggrLocation(measurement.getMeasurement(), observation));
|
|
|
+ }
|
|
|
+ }
|
|
|
+ aggrLocations.sort();
|
|
|
+
|
|
|
+ List<AFCAggrLocation> list = aggrLocations.list;
|
|
|
+ if (list.size() > 1) {
|
|
|
+ Iterator<AFCAggrLocation> iterator = list.iterator();
|
|
|
+ AFCAggrLocation previous = iterator.next();
|
|
|
+ while (iterator.hasNext()) {
|
|
|
+ AFCAggrLocation current = iterator.next();
|
|
|
+ if (previous.equals(current)) {
|
|
|
+ iterator.remove(); continue;
|
|
|
+ }
|
|
|
+ previous = current;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return aggrLocations;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
private static class Converter {
|
|
|
|
|
|
- static Sensor convertSensor(Unit afcUnit, RequestUriComponent uriComponent) {
|
|
|
- Sensor ogcSensor = new Sensor();
|
|
|
- ogcSensor.setId(afcUnit.getResourceId());
|
|
|
- ogcSensor.setSelfLink(format("%s/Sensors(%s)", uriComponent.getGatewayUri(), afcUnit.getResourceId()));
|
|
|
- ogcSensor.setDataStreamNavigationLink("unknown"); // TODO add Datastream navigation link
|
|
|
- ogcSensor.setName(afcUnit.getResourceType());
|
|
|
- ogcSensor.setDescription(afcUnit.getResourceUrn());
|
|
|
- ogcSensor.setEncodingType("unknown");
|
|
|
- ogcSensor.setMetadata("none");
|
|
|
- return ogcSensor;
|
|
|
+ private static final String DELIMITER = String.valueOf(0x2b); //
|
|
|
+
|
|
|
+ static String assemblyId(String... parts) {
|
|
|
+ return String.join(DELIMITER, parts);
|
|
|
+ }
|
|
|
+
|
|
|
+ static String[] disassemblyId(String id) {
|
|
|
+ return id.split(DELIMITER);
|
|
|
+ }
|
|
|
+
|
|
|
+ static HistoricalLocation convertToHistoricalLocation(MultiSensor afcMultiSensor, AFCAggrLocation afcLocation, RequestUriComponent uriComponent) {
|
|
|
+ HistoricalLocation historicalLocation = new HistoricalLocation();
|
|
|
+ String locationId = assemblyId(afcMultiSensor.getResourceUrn(), afcLocation.measurement, afcLocation.observation.getTime());
|
|
|
+ historicalLocation.setId(locationId);
|
|
|
+ historicalLocation.setSelfLink(format("%s/HistoricalLocations(%s)", uriComponent.getGatewayUri(), locationId));
|
|
|
+ historicalLocation.setLocationsNavigationLink(format("HistoricalLocations(%s)/Locations", locationId));
|
|
|
+ historicalLocation.setThingNavigationLink(format("HistoricalLocations(%s)/Thing", locationId));
|
|
|
+ historicalLocation.setTime(afcLocation.observation.getTime());
|
|
|
+ return historicalLocation;
|
|
|
+ }
|
|
|
+
|
|
|
+ static List<HistoricalLocation> convertToHistoricalLocation(MultiSensor afcMultiSensor, List<AFCAggrLocation> afcLocations, RequestUriComponent uriComponent) {
|
|
|
+ List<HistoricalLocation> historicalLocations = new ArrayList<>(afcLocations.size());
|
|
|
+ for (AFCAggrLocation afcLocation : afcLocations) {
|
|
|
+ historicalLocations.add(convertToHistoricalLocation(afcMultiSensor, afcLocation, uriComponent));
|
|
|
+ }
|
|
|
+ return historicalLocations;
|
|
|
+ }
|
|
|
+
|
|
|
+ static Location convertToLocation(MultiSensor afcMultiSensor, AFCAggrLocation afcLocation, RequestUriComponent uriComponent) {
|
|
|
+ Location location = new Location();
|
|
|
+ String locationId = assemblyId(afcMultiSensor.getResourceUrn(), afcLocation.measurement, afcLocation.observation.getTime());
|
|
|
+ location.setId(locationId);
|
|
|
+ location.setSelfLink(format("%s/Locations(%s)", uriComponent.getGatewayUri(), locationId));
|
|
|
+ location.setHistoricalLocationsNavigationLink(format("Locations(%s)/HistoricalLocations", locationId));
|
|
|
+ location.setName(afcMultiSensor.getResourceType());
|
|
|
+ location.setDescription(afcLocation.observation.getProvider());
|
|
|
+ location.setEncodingType("application/vnd.geo+json");
|
|
|
+
|
|
|
+ Location.Info info = new Location.Info();
|
|
|
+ info.setType("Feature");
|
|
|
+ location.setLocation(info);
|
|
|
+
|
|
|
+ Geometry geometry = new Geometry();
|
|
|
+ geometry.setType("Point");
|
|
|
+ io.connector.model.afarcloud.Observation afcObservation = afcLocation.observation;
|
|
|
+ geometry.setCoordinates(asList(afcObservation.getLongitude(), afcObservation.getLatitude(), afcObservation.getAltitude()));
|
|
|
+ info.setGeometry(geometry);
|
|
|
+
|
|
|
+ return location;
|
|
|
+ }
|
|
|
+
|
|
|
+ static Observation convertToObservation(ResourceMeasurement afcMeasurement, SensorTelemetry afcTelemetry, io.connector.model.afarcloud.Observation afcObservation, RequestUriComponent uriComponent) {
|
|
|
+ Observation observation = new Observation();
|
|
|
+ String observationId = assemblyId(afcMeasurement.getResource(), afcTelemetry.getMeasurement(), afcObservation.getTime());
|
|
|
+ observation.setId(observationId);
|
|
|
+ observation.setSelfLink(format("%s/Observations(%s)", uriComponent.getGatewayUri(), observationId));
|
|
|
+ // observation.setFeatureOfInterestNavigationLink(format("Observations(%s)/FeatureOfInterest", observationId));
|
|
|
+ observation.setFeatureOfInterestNavigationLink("https://storage07-afarcloud.qa.pdmfc.com/storage/rest/registry/getAllObservationTypes");
|
|
|
+ observation.setDataStreamNavigationLink(format("Observations(%s)/Datastream", observationId));
|
|
|
+ observation.setPhenomenonTime(afcObservation.getTime());
|
|
|
+ observation.setResultTime(afcObservation.getTime());
|
|
|
+ observation.setResult(afcObservation.getValue());
|
|
|
+ return observation;
|
|
|
+ }
|
|
|
+
|
|
|
+ static ObservedProperty convertToObservedProperty(MultiSensor afcMultiSensor, MultiSensor.SensorSchema afcSensor, RequestUriComponent uriComponent) {
|
|
|
+ Objects.requireNonNull(afcMultiSensor);
|
|
|
+ Objects.requireNonNull(afcSensor);
|
|
|
+ Objects.requireNonNull(uriComponent);
|
|
|
+
|
|
|
+ ObservedProperty observedProperty = new ObservedProperty();
|
|
|
+ String observedPropertyId = assemblyId(afcMultiSensor.getResourceUrn(), afcSensor.getObservedProperty());
|
|
|
+ observedProperty.setId(observedPropertyId);
|
|
|
+ observedProperty.setSelfLink(format("%s/ObservedProperties(%s)", uriComponent.getGatewayUri(), observedPropertyId));
|
|
|
+ observedProperty.setDataStreamNavigationLink(format("ObservedProperties(%s)/Datastream", observedPropertyId));
|
|
|
+ observedProperty.setName(afcSensor.getObservedProperty());
|
|
|
+ observedProperty.setDescription(afcSensor.getObservedProperty());
|
|
|
+ observedProperty.setDefinition(afcSensor.getUom());
|
|
|
+ return observedProperty;
|
|
|
+ }
|
|
|
+
|
|
|
+ static Thing convertToThing(MultiSensor afcMultiSensor, RequestUriComponent uriComponent) {
|
|
|
+ Objects.requireNonNull(afcMultiSensor);
|
|
|
+ Objects.requireNonNull(uriComponent);
|
|
|
+
|
|
|
+ Thing thing = new Thing();
|
|
|
+ String thingId = afcMultiSensor.getResourceUrn();
|
|
|
+ thing.setId(thingId);
|
|
|
+ thing.setSelfLink(format("%s/Things(%s)", uriComponent.getGatewayUri(), thingId));
|
|
|
+ thing.setLocationsNavigationLink(format("Things(%s)/Locations", thingId));
|
|
|
+ thing.setDataStreamNavigationLink(format("Things(%s)/Datastreams", thingId));
|
|
|
+ thing.setHistoricalLocationsNavigationLink(format("Things(%s)/HistoricalLocations", thingId));
|
|
|
+ thing.setName(afcMultiSensor.getResourceType());
|
|
|
+ thing.setDescription(afcMultiSensor.getResourceType());
|
|
|
+ thing.setProperties(null);
|
|
|
+ return thing;
|
|
|
}
|
|
|
|
|
|
- static List<Sensor> convertSensors(List<Unit> afcUnits, RequestUriComponent uriComponent) {
|
|
|
- List<Sensor> ogcSensors = new ArrayList<>(afcUnits.size());
|
|
|
- for (Unit afcUnit : afcUnits) {
|
|
|
- ogcSensors.add(convertSensor(afcUnit, uriComponent));
|
|
|
+ static List<Thing> convertToThing(List<MultiSensor> afcMultiSensors, RequestUriComponent uriComponent) {
|
|
|
+ List<Thing> ogcThings = new ArrayList<>(afcMultiSensors.size());
|
|
|
+ for (MultiSensor afcMultiSensor : afcMultiSensors) {
|
|
|
+ ogcThings.add(convertToThing(afcMultiSensor, uriComponent));
|
|
|
}
|
|
|
- return ogcSensors;
|
|
|
+ return ogcThings;
|
|
|
}
|
|
|
+
|
|
|
+ static Datastream convertToDataStream(MultiSensor afcMultiSensor, MultiSensor.SensorSchema afcSensor, SensorTelemetry telemetry, RequestUriComponent uriComponent) {
|
|
|
+ Objects.requireNonNull(afcMultiSensor);
|
|
|
+ Objects.requireNonNull(afcSensor);
|
|
|
+ Objects.requireNonNull(uriComponent);
|
|
|
+
|
|
|
+ Datastream datastream = new Datastream();
|
|
|
+ String dataStreamId = assemblyId(afcMultiSensor.getResourceUrn(), afcSensor.getObservedProperty());
|
|
|
+ datastream.setId(dataStreamId);
|
|
|
+ datastream.setSelfLink(format("%s/Datastreams(%s)", uriComponent.getGatewayUri(), dataStreamId));
|
|
|
+ datastream.setThingNavigationLink(format("Datastreams(%s)/Thing", dataStreamId));
|
|
|
+ datastream.setSensorNavigationLink(format("Datastreams(%s)/Sensor", dataStreamId));
|
|
|
+ datastream.setObservedPropertyNavigationLink(format("Datastreams(%s)/ObservedProperty", dataStreamId));
|
|
|
+ datastream.setObservationsNavigationLink(format("Datastreams(%s)/Observations", dataStreamId));
|
|
|
+ datastream.setName(afcSensor.getObservedProperty());
|
|
|
+ datastream.setDescription(afcSensor.getObservedProperty());
|
|
|
+
|
|
|
+ Datastream.UnitOfMeasurement uom = new Datastream.UnitOfMeasurement();
|
|
|
+ uom.setName(afcSensor.getObservedProperty());
|
|
|
+ uom.setSymbol("");
|
|
|
+ uom.setDefinition(afcSensor.getUom());
|
|
|
+ datastream.setUnitOfMeasurement(uom);
|
|
|
+
|
|
|
+ datastream.setObservationType("http://www.opengis.net/def/observationType/OGC-OM/2.0/OM_Measurement");
|
|
|
+
|
|
|
+ Geometry geometry = new Geometry();
|
|
|
+ geometry.setType("Point");
|
|
|
+ geometry.setCoordinates(asList(afcMultiSensor.getLongitude(), afcMultiSensor.getLatitude()));
|
|
|
+ datastream.setObservedArea(geometry);
|
|
|
+
|
|
|
+ String startDate = "<none>";
|
|
|
+ String endDate = telemetry == null || telemetry.getObservations().isEmpty() ? "<none>" : telemetry.getObservations().get(0).getTime();
|
|
|
+ String time = startDate + "/" + endDate;
|
|
|
+ datastream.setPhenomenonTime(time);
|
|
|
+ datastream.setResultTime(time);
|
|
|
+
|
|
|
+ return datastream;
|
|
|
+ }
|
|
|
+
|
|
|
+ static List<Datastream> convertToDataStream(MultiSensor afcMultiSensor, ResourceMeasurement measurement, RequestUriComponent uriComponent) {
|
|
|
+ Objects.requireNonNull(afcMultiSensor);
|
|
|
+ Objects.requireNonNull(uriComponent);
|
|
|
+
|
|
|
+ List<Datastream> datastreams = new ArrayList<>(afcMultiSensor.getObservations().size());
|
|
|
+
|
|
|
+ Map<String, SensorTelemetry> sensors = new HashMap<>();
|
|
|
+ if (measurement != null) {
|
|
|
+ for (SensorTelemetry telemetry : measurement.getMeasurements()) {
|
|
|
+ sensors.put(telemetry.getMeasurement(), telemetry);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ for (MultiSensor.SensorSchema sensor : afcMultiSensor.getObservations()) {
|
|
|
+ datastreams.add(convertToDataStream(afcMultiSensor, sensor, sensors.get(sensor.getObservedProperty()), uriComponent));
|
|
|
+ }
|
|
|
+
|
|
|
+ return datastreams;
|
|
|
+ }
|
|
|
+
|
|
|
+ static Sensor convertToSensor(MultiSensor afcMultiSensor, RequestUriComponent uriComponent) {
|
|
|
+ Objects.requireNonNull(afcMultiSensor);
|
|
|
+ Objects.requireNonNull(uriComponent);
|
|
|
+
|
|
|
+ String afcDomain = "https://storage07-afarcloud.qa.pdmfc.com/storage/rest";
|
|
|
+
|
|
|
+ Sensor sensor = new Sensor();
|
|
|
+ String thingId = afcMultiSensor.getResourceUrn();
|
|
|
+ sensor.setId(thingId);
|
|
|
+ sensor.setSelfLink(format("%s/Sensors(%s)", uriComponent.getGatewayUri(), thingId));
|
|
|
+ sensor.setDataStreamNavigationLink(format("Sensors(%s)/Datastreams", thingId));
|
|
|
+ sensor.setName(afcMultiSensor.getResourceType());
|
|
|
+ sensor.setDescription(afcMultiSensor.getResourceType());
|
|
|
+ sensor.setEncodingType("application/json");
|
|
|
+ sensor.setMetadata(format("%s/registry/getSensor/%s", afcDomain, afcMultiSensor.getResourceId()));
|
|
|
+
|
|
|
+ return sensor;
|
|
|
+ }
|
|
|
+
|
|
|
}
|
|
|
}
|