Forráskód Böngészése

added senslog model + senslog sql client + senslog ogcSensorThings gateway

MSI\matet 5 éve
szülő
commit
ec61381114

+ 8 - 0
build.gradle

@@ -80,6 +80,14 @@ project(":connector-model") {
     }
 }
 
+project(":connector-module-senslog1") {
+
+    dependencies {
+        compile group: 'org.jdbi', name: 'jdbi3-core', version: '3.17.0'
+        compile group: 'org.postgresql', name: 'postgresql', version: '42.1.4'
+    }
+}
+
 // settings for all 'connector-module-*'
 configure(moduleNames) {
 

+ 17 - 0
config/ogc2afc.yaml

@@ -1,7 +1,24 @@
 
 
 services:
+  SensLog1:
+    name: "SensLogV1"
+    provider: "io.connector.module.senslog1.SensLog1ModuleProvider"
 
+    user: "<user>"
+    group: "<group>"
+
+    sensorServiceHost:
+      domain: ""
+      path: ""
+
+    dataServiceHost:
+      domain: ""
+      path: ""
+
+    feederServiceHost:
+      domain: ""
+      path: ""
   AFC:
       retrievalApi:
         domain: "http://torcos.etsist.upm.es:9219/"

+ 305 - 0
connector-module-senslog1/src/main/java/io/connector/module/senslog1/SensLog1SQLClient.java

@@ -1,6 +1,311 @@
 package io.connector.module.senslog1;
 
+import io.connector.module.senslog1.entity.*;
+import io.connector.module.senslog1.jdbi.JDBI;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.jdbi.v3.core.mapper.RowMapper;
+import org.jdbi.v3.core.statement.StatementContext;
+
+import java.sql.ResultSet;
+import java.sql.ResultSetMetaData;
+import java.sql.SQLException;
+import java.util.List;
+
 public class SensLog1SQLClient {
 
+    static class UnitMapper implements RowMapper<Unit> {
+
+        @Override
+        public Unit map(ResultSet rs, StatementContext ctx) throws SQLException {
+            Unit unit = new Unit();
+            unit.setId(rs.getLong("unit_id"));
+            unit.setHolderId(rs.getInt("holder_id"));
+            unit.setDescription(rs.getString("description"));
+            unit.setMobile(rs.getBoolean("is_mobile"));
+            unit.setUnitTypeId(rs.getString("unit_type_id"));
+
+            return unit;
+        }
+    }
+
+    static class SensorMapper implements RowMapper<Sensor> {
+
+        @Override
+        public Sensor map(ResultSet rs, StatementContext ctx) throws SQLException {
+            Sensor sensor = new Sensor();
+            sensor.setId(rs.getLong("sensor_id"));
+            sensor.setName(rs.getString("sensor_name"));
+            sensor.setType(rs.getString("sensor_type"));
+            sensor.setPhenomenonId(rs.getString("phenomenon_id"));
+
+            return sensor;
+        }
+    }
+
+    static class ObservationMapper implements RowMapper<Observation> {
+
+        @Override
+        public Observation map(ResultSet rs, StatementContext ctx) throws SQLException {
+            Observation observation = new Observation();
+            observation.setId(rs.getInt("observation_id"));
+            observation.setGid(rs.getInt("gid"));
+            observation.setTimestamp(rs.getTimestamp("time_stamp"));
+            observation.setObservedValue(rs.getDouble("observed_value"));
+            observation.setSensorId(rs.getLong("sensor_id"));
+            observation.setUnitId(rs.getLong("unit_id"));
+            observation.setTimeReceived(rs.getTimestamp("time_received"));
+
+            return observation;
+        }
+    }
+
+    static class PhenomenonMapper implements RowMapper<Phenomenon> {
+
+        @Override
+        public Phenomenon map(ResultSet rs, StatementContext ctx) throws SQLException {
+            Phenomenon phenomenon = new Phenomenon();
+            phenomenon.setId(rs.getString("phenomenon_id"));
+            phenomenon.setName(rs.getString("phenomenon_name"));
+            phenomenon.setUnit(rs.getString("unit"));
+
+            return phenomenon;
+        }
+    }
+
+    static class UnitPositionMapper implements RowMapper<UnitPosition> {
+
+        @Override
+        public UnitPosition map(ResultSet rs, StatementContext ctx) throws SQLException {
+            UnitPosition unitPosition = new UnitPosition();
+
+            // POINT (x y) x je lon (longtitude) a y je lat (latitude)
+            String coords = rs.getString("coords");
+            String numbers = coords.substring(coords.indexOf("(") + 1, coords.indexOf(")"));
+            String[] split = numbers.split(" ");
+            double lon = Double.parseDouble(split[0]);
+            double lat = Double.parseDouble(split[1]);
+            unitPosition.setGid(rs.getInt("gid"));
+            unitPosition.setLongitude(lon);
+            unitPosition.setLatitude(lat);
+            unitPosition.setUnitId(rs.getLong("unit_id"));
+            unitPosition.setDop(rs.getDouble("dop"));
+            unitPosition.setSpeed(rs.getDouble("speed"));
+            unitPosition.setAltitude(rs.getDouble("altitude"));
+            unitPosition.setTimeReceived(rs.getTimestamp("time_received"));
+            unitPosition.setFirstTimeStamp(rs.getTimestamp("first_time_stamp"));
+
+            return unitPosition;
+        }
+    }
+
+    static class DatastreamMapper implements RowMapper<Datastream> {
+
+        @Override
+        public Datastream map(ResultSet rs, StatementContext ctx) throws SQLException {
+            Datastream datastream = new Datastream();
+
+            Unit unit = new Unit();
+            unit.setId(rs.getLong("unit_id"));
+            unit.setHolderId(rs.getInt("holder_id"));
+            unit.setDescription(rs.getString("description"));
+            unit.setMobile(rs.getBoolean("is_mobile"));
+            unit.setUnitTypeId(rs.getString("unit_type_id"));
+            datastream.setUnit(unit);
+
+            Sensor sensor = new Sensor();
+            sensor.setId(rs.getLong("sensor_id"));
+            sensor.setName(rs.getString("sensor_name"));
+            sensor.setType(rs.getString("sensor_type"));
+            sensor.setPhenomenonId(rs.getString("phenomenon_id"));
+            datastream.setSensor(sensor);
+
+            Phenomenon phenomenon = new Phenomenon();
+            phenomenon.setId(rs.getString("phenomenon_id"));
+            phenomenon.setName(rs.getString("phenomenon_name"));
+            phenomenon.setUnit(rs.getString("unit"));
+            datastream.setPhenomenon(phenomenon);
+
+            UnitPosition unitPosition = new UnitPosition();
+//             POINT (x y) x je lon (longtitude) a y je lat (latitude)
+            String coords = rs.getString("coords");
+            String numbers = coords.substring(coords.indexOf("(") + 1, coords.indexOf(")"));
+            String[] split = numbers.split(" ");
+            double lon = Double.parseDouble(split[0]);
+            double lat = Double.parseDouble(split[1]);
+            unitPosition.setGid(rs.getInt("gid"));
+            unitPosition.setLongitude(lon);
+            unitPosition.setLatitude(lat);
+            unitPosition.setUnitId(rs.getLong("unit_id"));
+            unitPosition.setDop(rs.getDouble("dop"));
+            unitPosition.setSpeed(rs.getDouble("speed"));
+            unitPosition.setAltitude(rs.getDouble("altitude"));
+            unitPosition.setTimeReceived(rs.getTimestamp("time_received"));
+            unitPosition.setFirstTimeStamp(rs.getTimestamp("first_time_stamp"));
+            datastream.setUnitPosition(unitPosition);
+//
+            return datastream;
+        }
+    }
+
+    public List<Unit> getAllUnits() {
+        return JDBI.get().withHandle(handle -> handle.createQuery("SELECT * FROM units").map(new UnitMapper()).list());
+    }
+
+    public Unit getUnit(long id) {
+        return JDBI.get().withHandle(handle -> handle.createQuery("SELECT * FROM units WHERE unit_id = :id").
+                bind("id", id).
+                map(new UnitMapper()).findOne()).orElse(null);
+    }
+
+    public Sensor getSensor(long id) {
+        return JDBI.get().withHandle(handle -> handle.createQuery("SELECT * FROM sensors WHERE sensor_id = :id").
+                bind("id", id).
+                map(new SensorMapper()).findOne()).orElse(null);
+    }
+
+    public Observation getObservation(int id) {
+        return JDBI.get().withHandle(handle -> handle.createQuery("SELECT * FROM observations WHERE observation_id = :id").
+                bind("id", id).
+                map(new ObservationMapper()).findOne()).orElse(null);
+    }
+
+    public UnitPosition getUnitPosition(int id) {
+        return JDBI.get().withHandle(handle -> handle.createQuery("SELECT up.*, ST_AsText(the_geom) AS coords FROM units_positions AS up WHERE up.gid = :gid").
+                bind("gid", id).
+                map(new UnitPositionMapper()).findOne()).orElse(null);
+    }
+
+    public List<UnitPosition> getLastPositionsForUnit(long unitId) {
+        return JDBI.get().withHandle(handle ->
+                handle.createQuery("SELECT up.*, ST_AsText(the_geom) AS coords FROM units_positions AS up WHERE up.unit_id = :unitId ORDER BY up.time_received ASC LIMIT 1").
+                        bind("unitId", unitId).
+                        map(new UnitPositionMapper()).list());
+    }
+
+    public UnitPosition getSecondLatestPosition(int positionId) {
+        // najit lokaci s id = :id, zjistit jaky patri veci, a najit lokaci pro tuhle veci ktera je pred lokaci s id = :id
+        // SELECT up.* FROM units_positions AS up INNER JOIN units_positions AS up_2
+        // ON up.unit_id = up_2.unit_id
+        // WHERE up.gid = :positionId ORDER BY up.time_received ASC LIMIT 2 OFFSET 1
+
+        return JDBI.get().withHandle(handle ->
+                handle.createQuery(
+                        "SELECT up.*, ST_AsText(up.the_geom) AS coords FROM units_positions AS up INNER JOIN units_positions AS up_2 " +
+                                "ON up.unit_id = up_2.unit_id " +
+                                "WHERE up.gid = :positionId ORDER BY up.time_received ASC LIMIT 2 OFFSET 1").
+                        bind("positionId", positionId).
+                        map(new UnitPositionMapper()).findOne()).orElse(null);
+    }
+
+    public Unit getUnitByLocation(int locationId) {
+        // SELECT DISTINCT * FROM units AS u INNER JOIN units_positions AS up ON u.unit_id = up.unit_id WHERE up.gid = :locationId
+        return JDBI.get().withHandle(handle -> handle.createQuery(
+                "SELECT DISTINCT * FROM units AS u INNER JOIN units_positions AS up ON u.unit_id = up.unit_id WHERE up.gid = :locationId").
+                bind("locationId", locationId).
+                map(new UnitMapper()).findOne()).orElse(null);
+    }
+
+    public Phenomenon getPhenomenon(String id) {
+        return JDBI.get().withHandle(handle -> handle.createQuery("SELECT * FROM phenomenons AS p WHERE p.phenomenon_id = :id").
+                bind("id", id).
+                map(new PhenomenonMapper()).findOne()).orElse(null);
+    }
+
+    private static final Logger logger = LogManager.getLogger(SensLog1SQLClient.class);
+
+    public Datastream getDataStream(long unitId, long sensorId) {
+        // SELECT u.*, s.*, p.* FROM units AS u, sensors AS s, phenomenons AS p WHERE p.id = s.phenomenon_id;
+        return JDBI.get().withHandle(handle -> handle.createQuery(
+                "SELECT u.*, s.*, p.*, up.*, ST_AsText(up.the_geom) AS coords FROM units AS u, sensors AS s, phenomenons AS p, units_positions AS up " +
+                        "WHERE u.unit_id = :unitId " +
+                        "AND s.sensor_id = :sensorId " +
+                        "AND p.phenomenon_id = s.phenomenon_id " +
+                        "AND up.unit_id = :unitId " +
+                        "ORDER BY up.time_received ASC LIMIT 1").
+                bind("unitId", unitId).
+                bind("sensorId", sensorId).
+                map(new DatastreamMapper()).findOne()).orElse(null);
+    }
+
+    public List<Datastream> getDataStreamsForUnit(long unitId) {
+        // SELECT * FROM sensors INNER JOIN units_to_sensors uts ON uts.unit_id = :unitId;
+        return JDBI.get().withHandle(handle -> handle.createQuery(
+                "SELECT u.*, s.*, p.*, up.*, ST_AsText(up.the_geom) AS coords FROM units AS u, sensors AS s, phenomenons AS p, units_positions AS up " +
+                        "INNER JOIN units_to_sensors AS uts ON uts.unit_id = :unitId " +
+                        "WHERE s.sensor_id = uts.sensor_id " +
+                        "AND p.phenomenon_id = s.phenomenon_id " +
+                        "AND up.gid = (SELECT uup.gid FROM units_positions AS uup WHERE uup.unit_id = :unitId ORDER BY uup.time_received ASC LIMIT 1)").
+                bind("unitId", unitId).
+                map(new DatastreamMapper()).list());
+    }
+
+    public List<Datastream> getDataStreamsForSensor(long sensorId) {
+        // SELECT * FROM sensors INNER JOIN units_to_sensors uts ON uts.sensor_id = :sensorId;
+        return JDBI.get().withHandle(handle -> handle.createQuery(
+                "SELECT u.*, s.*, p.*, up.*, ST_AsText(up.the_geom) AS coords FROM units AS u, sensors AS s, phenomenons AS p, units_positions AS up " +
+                        "INNER JOIN units_to_sensors AS uts ON uts.sensor_id = :sensorId " +
+                        "WHERE u.unit_id = uts.unit_id " +
+                        "AND p.phenomenon_id = s.phenomenon_id " +
+                        "AND up.gid = (SELECT uup.gid FROM units_positions AS uup WHERE uup.unit_id = uts.unit_id ORDER BY uup.time_received ASC LIMIT 1)").
+                bind("sensorId", sensorId).
+                map(new DatastreamMapper()).list());
+    }
+
+    public Datastream getDataStreamForPhenomenon(String phenomenonId) {
+        // SELECT u.*, s.*, p.* FROM units AS u
+        // INNER JOIN units_to_sensors AS uts ON uts.sensor_id = u.unit_id
+        // INNER JOIN sensors AS s ON s.sensor_id = uts.sensor_id
+        // INNER JOIN phenomenons AS p ON p.phenomenon_id = '1';
+
+        return JDBI.get().withHandle(handle -> handle.createQuery(
+                "SELECT u.*, s.*, p.*, up.*, ST_AsText(up.the_geom) AS coords FROM units AS u " +
+                        "INNER JOIN units_to_sensors AS uts ON uts.sensor_id = u.unit_id " +
+                        "INNER JOIN sensors AS s ON s.sensor_id = uts.sensor_id " +
+                        "INNER JOIN phenomenons AS p ON p.phenomenon_id = :phenomenonId " +
+                        "INNER JOIN units_positions AS up ON up.gid = (SELECT uup.gid FROM units_positions AS uup WHERE uup.unit_id = uts.unit_id ORDER BY uup.time_received ASC LIMIT 1)").
+                bind("phenomenonId", phenomenonId).
+                map(new DatastreamMapper()).findOne()).orElse(null);
+
+//        return JDBI.get().withHandle(handle -> handle.createQuery(
+//                "SELECT u.*, s.*, p.* FROM units AS u, sensors AS s, phenomenons AS p " +
+//                        "INNER JOIN units_to_sensors AS uts ON uts.sensor_id = s.sensor_id " +
+//                        "WHERE u.unit_id = uts.unit_id " +
+//                        "AND s.phenomenon_id = :phenomenonId").
+//                bind("phenomenonId", phenomenonId).
+//                map(new DatastreamMapper()).findOne()).orElse(null);
+    }
+
+    public Datastream getDataStreamForObservation(int observationId) {
+        // SELECT u.*, s.*, p.* FROM units AS u, sensors AS s, phenomenons AS p
+        // CROSS JOIN observations AS o
+        // WHERE o.observation_id = :observationId AND o.unit_id = u.unit_id AND o.sensor_id = o.sensor_id
+        return JDBI.get().withHandle(handle -> handle.createQuery(
+                "SELECT u.*, s.*, p.*, up.*, ST_AsText(up.the_geom) AS coords FROM units AS u, sensors AS s, phenomenons AS p, units_positions AS up " +
+                        "CROSS JOIN observations AS o " +
+                        "WHERE o.observation_id = :observationId " +
+                        "AND o.unit_id = u.unit_id " +
+                        "AND o.sensor_id = o.sensor_id " +
+                        "AND up.gid = (SELECT uup.gid FROM units_positions AS uup WHERE uup.unit_id = o.unit_id ORDER BY uup.time_received ASC LIMIT 1)").
+                bind("observationId", observationId).
+                map(new DatastreamMapper()).findOne()).orElse(null);
+    }
+
+    public Phenomenon getPhenomenonBySensor(long sensorId) {
+        // SELECT * FROM phenomenons AS p INNER JOIN sensors AS s ON p.phenomenon_id = s.phenomenon_id WHERE s.sensor_id = :sensorId
+        return JDBI.get().withHandle(handle -> handle.createQuery(
+                "SELECT * FROM phenomenons AS p INNER JOIN sensors AS s " +
+                        "ON p.phenomenon_id = s.phenomenon_id WHERE s.sensor_id = :sensorId").
+                bind("sensorId", sensorId).
+                map(new PhenomenonMapper()).findOne()).orElse(null);
+    }
+
+    public List<Observation> getObservationByUnitAndSensor(long unitId, long sensorId) {
+        return JDBI.get().withHandle(handle -> handle.createQuery(
+                "SELECT * FROM observations AS o WHERE o.unit_id = :unitId AND o.sensor_id = :sensorId").
+                bind("unitId", unitId).
+                bind("sensorId", sensorId).
+                map(new ObservationMapper()).list());
+    }
 
 }

+ 44 - 0
connector-module-senslog1/src/main/java/io/connector/module/senslog1/entity/Datastream.java

@@ -0,0 +1,44 @@
+package io.connector.module.senslog1.entity;
+
+public class Datastream {
+
+    private Unit unit;
+
+    private Sensor sensor;
+
+    private Phenomenon phenomenon;
+
+    private UnitPosition unitPosition;
+
+    public Unit getUnit() {
+        return unit;
+    }
+
+    public void setUnit(Unit unit) {
+        this.unit = unit;
+    }
+
+    public Sensor getSensor() {
+        return sensor;
+    }
+
+    public void setSensor(Sensor sensor) {
+        this.sensor = sensor;
+    }
+
+    public Phenomenon getPhenomenon() {
+        return phenomenon;
+    }
+
+    public void setPhenomenon(Phenomenon phenomenon) {
+        this.phenomenon = phenomenon;
+    }
+
+    public UnitPosition getUnitPosition() {
+        return unitPosition;
+    }
+
+    public void setUnitPosition(UnitPosition unitPosition) {
+        this.unitPosition = unitPosition;
+    }
+}

+ 76 - 0
connector-module-senslog1/src/main/java/io/connector/module/senslog1/entity/Observation.java

@@ -0,0 +1,76 @@
+package io.connector.module.senslog1.entity;
+
+import java.sql.Timestamp;
+
+public class Observation {
+
+    private int id;
+
+    private int gid;
+
+    private Timestamp timestamp;
+
+    private double observedValue;
+
+    private long sensorId;
+
+    private long unitId;
+
+    private Timestamp timeReceived;
+
+    public int getId() {
+        return id;
+    }
+
+    public void setId(int id) {
+        this.id = id;
+    }
+
+    public int getGid() {
+        return gid;
+    }
+
+    public void setGid(int gid) {
+        this.gid = gid;
+    }
+
+    public Timestamp getTimestamp() {
+        return timestamp;
+    }
+
+    public void setTimestamp(Timestamp timestamp) {
+        this.timestamp = timestamp;
+    }
+
+    public double getObservedValue() {
+        return observedValue;
+    }
+
+    public void setObservedValue(double observedValue) {
+        this.observedValue = observedValue;
+    }
+
+    public long getSensorId() {
+        return sensorId;
+    }
+
+    public void setSensorId(long sensorId) {
+        this.sensorId = sensorId;
+    }
+
+    public long getUnitId() {
+        return unitId;
+    }
+
+    public void setUnitId(long unitId) {
+        this.unitId = unitId;
+    }
+
+    public Timestamp getTimeReceived() {
+        return timeReceived;
+    }
+
+    public void setTimeReceived(Timestamp timeReceived) {
+        this.timeReceived = timeReceived;
+    }
+}

+ 34 - 0
connector-module-senslog1/src/main/java/io/connector/module/senslog1/entity/Phenomenon.java

@@ -0,0 +1,34 @@
+package io.connector.module.senslog1.entity;
+
+public class Phenomenon {
+
+    private String id;
+
+    private String name;
+
+    private String unit;
+
+    public String getId() {
+        return id;
+    }
+
+    public void setId(String id) {
+        this.id = id;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public String getUnit() {
+        return unit;
+    }
+
+    public void setUnit(String unit) {
+        this.unit = unit;
+    }
+}

+ 44 - 0
connector-module-senslog1/src/main/java/io/connector/module/senslog1/entity/Sensor.java

@@ -0,0 +1,44 @@
+package io.connector.module.senslog1.entity;
+
+public class Sensor {
+
+    private long id;
+
+    private String name;
+
+    private String type;
+
+    private String phenomenonId;
+
+    public long getId() {
+        return id;
+    }
+
+    public void setId(long id) {
+        this.id = id;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public String getType() {
+        return type;
+    }
+
+    public void setType(String type) {
+        this.type = type;
+    }
+
+    public String getPhenomenonId() {
+        return phenomenonId;
+    }
+
+    public void setPhenomenonId(String phenomenonId) {
+        this.phenomenonId = phenomenonId;
+    }
+}

+ 54 - 0
connector-module-senslog1/src/main/java/io/connector/module/senslog1/entity/Unit.java

@@ -0,0 +1,54 @@
+package io.connector.module.senslog1.entity;
+
+public class Unit {
+
+    private long id;
+
+    private int holderId;
+
+    private String description;
+
+    private boolean mobile;
+
+    private String unitTypeId;
+
+    public long getId() {
+        return id;
+    }
+
+    public void setId(long id) {
+        this.id = id;
+    }
+
+    public int getHolderId() {
+        return holderId;
+    }
+
+    public void setHolderId(int holderId) {
+        this.holderId = holderId;
+    }
+
+    public String getDescription() {
+        return description;
+    }
+
+    public void setDescription(String description) {
+        this.description = description;
+    }
+
+    public boolean isMobile() {
+        return mobile;
+    }
+
+    public void setMobile(boolean mobile) {
+        this.mobile = mobile;
+    }
+
+    public String getUnitTypeId() {
+        return unitTypeId;
+    }
+
+    public void setUnitTypeId(String unitTypeId) {
+        this.unitTypeId = unitTypeId;
+    }
+}

+ 96 - 0
connector-module-senslog1/src/main/java/io/connector/module/senslog1/entity/UnitPosition.java

@@ -0,0 +1,96 @@
+package io.connector.module.senslog1.entity;
+
+import java.sql.Timestamp;
+
+public class UnitPosition {
+
+    private int gid;
+
+    private double longitude;
+
+    private double latitude;
+
+    private long unitId;
+
+    private double dop;
+
+    private double speed;
+
+    private double altitude;
+
+    private Timestamp timeReceived;
+
+    private Timestamp firstTimeStamp;
+
+    public int getGid() {
+        return gid;
+    }
+
+    public void setGid(int gid) {
+        this.gid = gid;
+    }
+
+    public double getLongitude() {
+        return longitude;
+    }
+
+    public void setLongitude(double longitude) {
+        this.longitude = longitude;
+    }
+
+    public double getLatitude() {
+        return latitude;
+    }
+
+    public void setLatitude(double latitude) {
+        this.latitude = latitude;
+    }
+
+    public long getUnitId() {
+        return unitId;
+    }
+
+    public void setUnitId(long unitId) {
+        this.unitId = unitId;
+    }
+
+    public double getDop() {
+        return dop;
+    }
+
+    public void setDop(double dop) {
+        this.dop = dop;
+    }
+
+    public double getSpeed() {
+        return speed;
+    }
+
+    public void setSpeed(double speed) {
+        this.speed = speed;
+    }
+
+    public double getAltitude() {
+        return altitude;
+    }
+
+    public void setAltitude(double altitude) {
+        this.altitude = altitude;
+    }
+
+    public Timestamp getTimeReceived() {
+        return timeReceived;
+    }
+
+    public void setTimeReceived(Timestamp timeReceived) {
+        this.timeReceived = timeReceived;
+    }
+
+    public Timestamp getFirstTimeStamp() {
+        return firstTimeStamp;
+    }
+
+    public void setFirstTimeStamp(Timestamp firstTimeStamp) {
+        this.firstTimeStamp = firstTimeStamp;
+    }
+}

+ 422 - 0
connector-module-senslog1/src/main/java/io/connector/module/senslog1/gateway/OGCSensorThingsGateway.java

@@ -1,10 +1,30 @@
 package io.connector.module.senslog1.gateway;
 
 import io.connector.core.AbstractGateway;
+import io.connector.core.http.RequestUriComponent;
+import io.connector.model.sensorthings.*;
 import io.connector.module.senslog1.SensLog1SQLClient;
+import io.connector.module.senslog1.entity.Phenomenon;
+import io.connector.module.senslog1.entity.Unit;
+import io.connector.module.senslog1.entity.UnitPosition;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+
+import java.util.*;
+import java.util.function.Supplier;
+
+import static io.connector.core.http.ContentType.APPLICATION_JSON;
+import static io.connector.core.http.Header.CONTENT_TYPE;
+import static io.connector.core.AddressPath.Creator.create;
+import static io.vertx.core.json.Json.encode;
+import static java.lang.String.format;
+import static java.util.Arrays.asList;
+import static java.util.Optional.ofNullable;
 
 public class OGCSensorThingsGateway extends AbstractGateway {
 
+    private final static Logger logger = LogManager.getLogger(OGCSensorThingsGateway.class);
+
     private final SensLog1SQLClient client;
 
     public OGCSensorThingsGateway(String id, SensLog1SQLClient client) {
@@ -14,6 +34,408 @@ public class OGCSensorThingsGateway extends AbstractGateway {
 
     @Override
     protected void run() {
+        router().get(create("Things")).handler(ctx -> { // Unit - OVERENO
+            RequestUriComponent uriComponent = parseUriToComponents(ctx.request());
+            List<Unit> units = client.getAllUnits();
+            List<Thing> things = Converter.toThing(units, uriComponent);
+            ctx.response().putHeader(CONTENT_TYPE, APPLICATION_JSON).end(encode(things));
+        });
+
+        router().get(create("Things(:id)")).handler(ctx -> { // OVERENO
+            RequestUriComponent uriComponent = parseUriToComponents(ctx.request());
+            String id = ctx.pathParam("id");
+            Unit unit = client.getUnit(Long.parseLong(id));
+            Thing thing = Converter.toThing(unit, uriComponent);
+            ctx.response().putHeader(CONTENT_TYPE, APPLICATION_JSON).end(encode(thing));
+        });
+
+        router().get(create("Datastreams(:id)/Thing")).handler(ctx -> { // OVERENO
+            logger.info("Handling a request: {}.", ctx.request().absoluteURI());
+            RequestUriComponent uriComponent = parseUriToComponents(ctx.request());
+            String id = ctx.pathParam("id"); // resourceUrn + observedProperty
+            String[] idCmp = Converter.disassemblyId(id);
+            String unitId = idCmp[0];
+            ctx.reroute(format("%s/Things(%s)", uriComponent.getGatewayPath(), unitId));
+        });
+
+        router().get(create("HistoricalLocations(:id)/Thing")).handler(ctx -> { // OVERENO
+            // z tabulky unit positions vytahnout radek s id = :id, a z unit_id zjistit jak vec se ma vratit
+            RequestUriComponent uriComponent = parseUriToComponents(ctx.request());
+            String id = ctx.pathParam("id");
+            Unit unit = client.getUnitByLocation(Integer.parseInt(id));
+            Thing ogcThing = Converter.toThing(unit, uriComponent);
+            ctx.response().putHeader(CONTENT_TYPE, APPLICATION_JSON).end(ogcThing.encode());
+        });
+
+        router().get(create("Datastreams(:id)")).handler(ctx -> { // OVERENO
+            logger.info("Handling a request: {}.", ctx.request().absoluteURI());
+            RequestUriComponent uriComponent = parseUriToComponents(ctx.request());
+            String id = ctx.pathParam("id"); // resource + measurement + time
+            String[] idCmp = Converter.disassemblyId(id);
+            io.connector.module.senslog1.entity.Datastream senslogDataStream = client.getDataStream(Long.parseLong(idCmp[0]), Long.parseLong(idCmp[1]));
+            Datastream ogcDataStream = Converter.toDataStream(senslogDataStream, uriComponent);
+            ctx.response().putHeader(CONTENT_TYPE, APPLICATION_JSON).end(ogcDataStream.encode());
+        });
+
+        router().get(create("Things(:id)/Datastreams")).handler(ctx -> { // OVERENO
+            logger.info("Handling a request: {}.", ctx.request().absoluteURI());
+            RequestUriComponent uriComponent = parseUriToComponents(ctx.request());
+            String id = ctx.pathParam("id");
+            List<io.connector.module.senslog1.entity.Datastream> senslogDataStreams = client.getDataStreamsForUnit(Long.parseLong(id));
+            List<Datastream> ogcDataStreams = Converter.toDataStreams(senslogDataStreams, uriComponent);
+            ctx.response().putHeader(CONTENT_TYPE, APPLICATION_JSON).end(encode(ogcDataStreams));
+        });
+
+        router().get(create("Sensors(:id)/Datastreams")).handler(ctx -> { // sensor OEVERENO
+            logger.info("Handling a request: {}.", ctx.request().absoluteURI());
+            RequestUriComponent uriComponent = parseUriToComponents(ctx.request());
+            String id = ctx.pathParam("id");
+            List<io.connector.module.senslog1.entity.Datastream> senslogDataStreams = client.getDataStreamsForSensor(Long.parseLong(id));
+            List<Datastream> ogcDataStreams = Converter.toDataStreams(senslogDataStreams, uriComponent);
+            ctx.response().putHeader(CONTENT_TYPE, APPLICATION_JSON).end(encode(ogcDataStreams));
+        });
+
+        router().get(create("ObservedProperties(:id)/Datastream")).handler(ctx -> { // observedProperties = phenomenons OVERENO
+            // sensor ma v sobe phenomenon id, podle toho se nsjde sensor a pak se z units_to_sensor najde unit
+            // to je jediny spojeni o kterym vim
+            logger.info("Handling a request: {}.", ctx.request().absoluteURI());
+            RequestUriComponent uriComponent = parseUriToComponents(ctx.request());
+            String id = ctx.pathParam("id");
+            io.connector.module.senslog1.entity.Datastream senslogDataStream = client.getDataStreamForPhenomenon(id);
+            Datastream ogcDataStream = Converter.toDataStream(senslogDataStream, uriComponent);
+            ctx.response().putHeader(CONTENT_TYPE, APPLICATION_JSON).end(encode(ogcDataStream));
+        });
+
+        router().get(create("Observations(:id)/Datastream")).handler(ctx -> { // Observations OVERENO
+            // observation ma v sobe unitId a sensorId - to tvori datastream
+            // tabulka observations ma v sobe jak unit tak sensor id
+            logger.info("Handling a request: {}.", ctx.request().absoluteURI());
+            RequestUriComponent uriComponent = parseUriToComponents(ctx.request());
+            String id = ctx.pathParam("id");
+            io.connector.module.senslog1.entity.Datastream senslogDataStream = client.getDataStreamForObservation(Integer.parseInt(id));
+            Datastream ogcDataStream = Converter.toDataStream(senslogDataStream, uriComponent);
+            ctx.response().putHeader(CONTENT_TYPE, APPLICATION_JSON).end(encode(ogcDataStream));
+        });
+
+        router().get(create("Sensors(:id)")).handler(ctx -> { // OVERENO
+            RequestUriComponent uriComponent = parseUriToComponents(ctx.request());
+            String id = ctx.pathParam("id");
+            io.connector.module.senslog1.entity.Sensor senslogSensor = client.getSensor(Long.parseLong(id));
+            io.connector.model.sensorthings.Sensor ogcSensor = Converter.toSensor(senslogSensor, uriComponent);
+            ctx.response().putHeader(CONTENT_TYPE, APPLICATION_JSON).end(encode(ogcSensor));
+        });
+
+        // unitId(thing):sensorId(sensor)
+        router().get(create("Datastreams(:id)/Sensor")).handler(ctx -> { // OVERENO
+            logger.info("Handling a request: {}.", ctx.request().absoluteURI());
+            RequestUriComponent uriComponent = parseUriToComponents(ctx.request());
+            String id = ctx.pathParam("id"); // resourceUrn + observedProperty
+            String[] idCmp = Converter.disassemblyId(id);
+            String resourceUrn = idCmp[1];
+            ctx.reroute(format("%s/Sensors(%s)", uriComponent.getGatewayPath(), resourceUrn));
+        });
+
+        router().get(create("ObservedProperties(:id)")).handler(ctx -> { // phenomenons OVERENO
+            RequestUriComponent uriComponent = parseUriToComponents(ctx.request());
+            String id = ctx.pathParam("id");
+            Phenomenon phenomenon = client.getPhenomenon(id);
+            ObservedProperty observedProperty = Converter.toObservedProperty(phenomenon, uriComponent);
+            ctx.response().putHeader(CONTENT_TYPE, APPLICATION_JSON).end(observedProperty.encode());
+        });
+
+        // observedProperty = phenomenons
+        router().get(create("Datastreams(:id)/ObservedProperty")).handler(ctx -> { // OVERENO
+            // id datstreamu obsahuje sensorID kterej ma v sobe phenomenonId
+            logger.info("Handling a request: {}.", ctx.request().absoluteURI());
+            RequestUriComponent uriComponent = parseUriToComponents(ctx.request());
+            String id = ctx.pathParam("id");
+            String[] idCmp = Converter.disassemblyId(id);
+            String sensorId = idCmp[1];
+            Phenomenon phenomenon = client.getPhenomenonBySensor(Long.parseLong(sensorId));
+            ObservedProperty observedProperty = Converter.toObservedProperty(phenomenon, uriComponent);
+            ctx.response().putHeader(CONTENT_TYPE, APPLICATION_JSON).end(observedProperty.encode());
+        });
+
+        router().get(create("Observations(:id)")).handler(ctx -> { // tabulka observations OVERENO
+            RequestUriComponent uriComponent = parseUriToComponents(ctx.request());
+            String id = ctx.pathParam("id");
+
+            final Supplier<IllegalArgumentException> exception = () -> new IllegalArgumentException(format(
+                    "Can not find Observation with @iot.id '%s'.", id));
+
+            Optional<io.connector.module.senslog1.entity.Observation> observationOpt = ofNullable(client.getObservation(Integer.parseInt(id)));
+            io.connector.module.senslog1.entity.Observation senslogObservation = observationOpt.orElseThrow(exception);
+
+            io.connector.model.sensorthings.Observation ogcObservation = Converter.toObservation(senslogObservation, uriComponent);
+            ctx.response().putHeader(CONTENT_TYPE, APPLICATION_JSON).end(ogcObservation.encode());
+        });
+
+        router().get(create("Datastreams(:id)/Observations")).handler(ctx -> { // OVERENO
+            // observations ma sensor a unit ID, takze najdu observaci podle IDcek co se dostanou v requestu
+            logger.info("Handling a request: {}.", ctx.request().absoluteURI());
+            RequestUriComponent uriComponent = parseUriToComponents(ctx.request());
+            String id = ctx.pathParam("id");
+            String[] idCmp = Converter.disassemblyId(id);
+            String unitId = idCmp[0];
+            String sensorId = idCmp[1];
+            List<io.connector.module.senslog1.entity.Observation> senslogObservations = client.getObservationByUnitAndSensor(Long.parseLong(unitId), Long.parseLong(sensorId));
+            List<io.connector.model.sensorthings.Observation> ogcObservations = Converter.toObservation(senslogObservations, uriComponent);
+            ctx.response().putHeader(CONTENT_TYPE, APPLICATION_JSON).end(encode(ogcObservations));
+        });
+
+        router().get(create("FeaturesOfInterest(:id)")).handler(ctx -> {
+            // TODO - SKIP
+        });
+
+        router().get(create("Locations(:id)")).handler(ctx -> {   // lokace pro dany id OVERENO
+            RequestUriComponent uriComponent = parseUriToComponents(ctx.request());
+            String id = ctx.pathParam("id");
+            UnitPosition unitPosition = client.getUnitPosition(Integer.parseInt(id));
+            Location location = Converter.toLocation(unitPosition, uriComponent);
+            ctx.response().putHeader(CONTENT_TYPE, APPLICATION_JSON).end(location.encode());
+        });
+
+        router().get(create("Things(:id)/Locations")).handler(ctx -> { // posledni lokaci pro things s :id OVERENO
+            RequestUriComponent uriComponent = parseUriToComponents(ctx.request());
+            String id = ctx.pathParam("id");
+            List<UnitPosition> unitPositions = client.getLastPositionsForUnit(Long.parseLong(id));
+            List<Location> locations = Converter.toLocation(unitPositions, uriComponent);
+            ctx.response().putHeader(CONTENT_TYPE, APPLICATION_JSON).end(encode(locations));
+        });
+
+        router().get(create("HistoricalLocations(:id)/Locations")).handler(ctx -> { // reroutovani na Locations(:id) OVERENO
+            RequestUriComponent uriComponent = parseUriToComponents(ctx.request());
+            String id = ctx.pathParam("id");
+            ctx.reroute(format("%s/Locations(%s)", uriComponent.getGatewayPath(), id));
+        });
+
+        router().get(create("HistoricalLocations(:id)")).handler(ctx -> { // reroutovani na Locations(:id) OVERENO
+            RequestUriComponent uriComponent = parseUriToComponents(ctx.request());
+            String id = ctx.pathParam("id");
+            UnitPosition unitPosition = client.getUnitPosition(Integer.parseInt(id));
+            HistoricalLocation historicalLocation = Converter.toHistoricalLocation(unitPosition, uriComponent);
+            ctx.response().putHeader(CONTENT_TYPE, APPLICATION_JSON).end(historicalLocation.encode());
+        });
+
+        router().get(create("Things(:id)/HistoricalLocations")).handler(ctx -> { // vratit posledni location pro unit s :id OVERENO
+            RequestUriComponent uriComponent = parseUriToComponents(ctx.request());
+            String id = ctx.pathParam("id");
+            List<UnitPosition> unitPositions = client.getLastPositionsForUnit(Long.parseLong(id));
+            List<HistoricalLocation> historicalLocations = Converter.toHistoricalLocation(unitPositions, uriComponent);
+            ctx.response().putHeader(CONTENT_TYPE, APPLICATION_JSON).end(encode(historicalLocations));
+        });
+
+        router().get(create("Locations(:id)/HistoricalLocations")).handler(ctx -> { // vratit lokaci ktera je pred lokaci s id = :id OVERENO
+            // vratit lokaci s id - 1
+            // najit lokaci s id = :id, zjistit jaky patri veci, a najit lokaci pro tuhle veci ktera je pred lokaci s id = :id
+            RequestUriComponent uriComponent = parseUriToComponents(ctx.request());
+            String id = ctx.pathParam("id");
+            UnitPosition unitPosition = client.getSecondLatestPosition(Integer.parseInt(id));
+            HistoricalLocation historicalLocation = Converter.toHistoricalLocation(unitPosition, uriComponent); // TODO tady se v afc vraci list
+            ctx.response().putHeader(CONTENT_TYPE, APPLICATION_JSON).end(historicalLocation.encode());
+        });
+    }
+
+    private static class Converter {
+
+        private static final String DELIMITER = ":";
+
+        static String assemblyId(String... parts) {
+            return String.join(DELIMITER, parts);
+        }
+
+        static String[] disassemblyId(String id) {
+            return id.split(DELIMITER);
+        }
+
+        static List<Datastream> toDataStreams(List<io.connector.module.senslog1.entity.Datastream> senslogDatastreams,
+                                              RequestUriComponent uriComponent) {
+            logger.info("Mapuju datastreamy");
+            List<Datastream> ogcDataStreams = new ArrayList<>(senslogDatastreams.size());
+            for (io.connector.module.senslog1.entity.Datastream dataStream : senslogDatastreams) {
+                ogcDataStreams.add(toDataStream(dataStream, uriComponent));
+            }
+            return ogcDataStreams;
+        }
+
+        static Datastream toDataStream(io.connector.module.senslog1.entity.Datastream senslogDatastream,
+                                       RequestUriComponent uriComponent) {
+            logger.info("Mapuju datastream");
+            Unit unit = senslogDatastream.getUnit();
+            io.connector.module.senslog1.entity.Sensor sensor = senslogDatastream.getSensor();
+            Phenomenon phenomenon = senslogDatastream.getPhenomenon();
+
+            String dataStreamId = assemblyId(String.valueOf(unit.getId()), String.valueOf(sensor.getId()));
+            String absoluteUrl = uriComponent.getGatewayUri();
+
+            Datastream datastream = new Datastream();
+            datastream.setId(dataStreamId);
+            datastream.setSelfLink(format("%s/Datastreams(%s)", absoluteUrl, dataStreamId));
+            datastream.setThingNavigationLink(format("%s/Datastreams(%s)/Thing", absoluteUrl, dataStreamId));
+            datastream.setSensorNavigationLink(format("%s/Datastreams(%s)/Sensor", absoluteUrl, dataStreamId));
+            datastream.setObservedPropertyNavigationLink(format("%s/Datastreams(%s)/ObservedProperty", absoluteUrl, dataStreamId));
+            datastream.setObservationsNavigationLink(format("%s/Datastreams(%s)/Observations", absoluteUrl, dataStreamId));
+            datastream.setName(sensor.getName());
+            datastream.setDescription(unit.getDescription());
+
+            Datastream.UnitOfMeasurement uom = new Datastream.UnitOfMeasurement();
+            uom.setName(phenomenon.getName());
+            uom.setSymbol("");
+            uom.setDefinition(phenomenon.getUnit());
+            datastream.setUnitOfMeasurement(uom);
+
+            datastream.setObservationType("http://www.opengis.net/def/observationType/OGC-OM/2.0/OM_Measurement");
+
+            UnitPosition unitPosition = senslogDatastream.getUnitPosition();
+            Geometry geometry = new Geometry();
+            geometry.setType("Point");
+            geometry.setCoordinates(asList(unitPosition.getLongitude(), unitPosition.getLatitude(), unitPosition.getAltitude()));
+            datastream.setObservedArea(geometry);
+
+//            String startDate = "<none>"; TODO
+//            String endDate = telemetry == null || telemetry.getObservations().isEmpty() ? "<none>" : telemetry.getObservations().get(0).getTime();
+//            String time = startDate + "/" + endDate;
+//            datastream.setPhenomenonTime(time);
+//            datastream.setResultTime(time);
+
+            logger.info("konec mapovani datastreamu");
+            return datastream;
+        }
+
+        static Thing toThing(Unit unit, RequestUriComponent uriComponent) {
+            Objects.requireNonNull(unit);
+            Objects.requireNonNull(uriComponent);
+
+            Thing thing = new Thing();
+            String thingId = String.valueOf(unit.getId());
+            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(); // TODO - co sem hodit unitTypeId?
+            thing.setDescription(unit.getDescription());
+            thing.setProperties(null);
+
+            return thing;
+        }
+
+        static List<Thing> toThing(List<Unit> units, RequestUriComponent uriComponent) {
+            List<Thing> things = new ArrayList<>(units.size());
+            for (Unit unit : units) {
+                things.add(toThing(unit, uriComponent));
+            }
+            return things;
+        }
+
+        static List<Location> toLocation(List<UnitPosition> unitPositions, RequestUriComponent uriComponent) {
+            List<Location> locations = new ArrayList<>(unitPositions.size());
+            for (UnitPosition unitPosition : unitPositions) {
+                locations.add(toLocation(unitPosition, uriComponent));
+            }
+            return locations;
+        }
+
+        static Location toLocation(UnitPosition unitPosition, RequestUriComponent uriComponent) {
+            Location location = new Location();
+            String locationId = String.valueOf(unitPosition.getGid());
+            String absoluteUrl = uriComponent.getGatewayUri();
+            location.setId(locationId);
+            location.setSelfLink(format("%s/Locations(%s)", absoluteUrl, locationId));
+            location.setHistoricalLocationsNavigationLink(format("%s/Locations(%s)/HistoricalLocations", absoluteUrl, locationId));
+//            location.setName(); // TODO
+//            location.setDescription(); // TODO
+            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");
+            geometry.setCoordinates(Arrays.asList(unitPosition.getLongitude(), unitPosition.getLatitude(), unitPosition.getAltitude()));
+            info.setGeometry(geometry);
+
+            return location;
+        }
+
+        static List<HistoricalLocation> toHistoricalLocation(List<UnitPosition> unitPositions, RequestUriComponent uriComponent) {
+            List<HistoricalLocation> historicalLocations = new ArrayList<>(unitPositions.size());
+            for (UnitPosition unitPosition : unitPositions) {
+                historicalLocations.add(toHistoricalLocation(unitPosition, uriComponent));
+            }
+            return historicalLocations;
+        }
+
+        static HistoricalLocation toHistoricalLocation(UnitPosition unitPosition, RequestUriComponent uriComponent) {
+            HistoricalLocation historicalLocation = new HistoricalLocation();
+
+            String locationId = String.valueOf(unitPosition.getUnitId());
+            String absoluteUrl = uriComponent.getGatewayUri();
+            historicalLocation.setId(locationId);
+            historicalLocation.setSelfLink(format("%s/HistoricalLocations(%s)", absoluteUrl, locationId));
+            historicalLocation.setLocationsNavigationLink(format("%s/HistoricalLocations(%s)/Locations", absoluteUrl, locationId));
+            historicalLocation.setThingNavigationLink(format("%s/HistoricalLocations(%s)/Thing", absoluteUrl, locationId));
+            historicalLocation.setTime(unitPosition.getFirstTimeStamp().toString());
+
+            return historicalLocation;
+        }
+
+        static ObservedProperty toObservedProperty(Phenomenon phenomenon, RequestUriComponent uriComponent) {
+            ObservedProperty observedProperty = new ObservedProperty();
+            String observedPropertyId = phenomenon.getId();
+            String absoluteUrl = uriComponent.getGatewayUri();
+            observedProperty.setId(observedPropertyId);
+            observedProperty.setSelfLink(format("%s/ObservedProperties(%s)", absoluteUrl, observedPropertyId));
+            observedProperty.setDataStreamNavigationLink(format("%s/ObservedProperties(%s)/Datastream", absoluteUrl, observedPropertyId));
+            observedProperty.setName(phenomenon.getName());
+//            observedProperty.setDescription();  // TODO
+//            observedProperty.setDefinition();   // TODO
+
+            return observedProperty;
+        }
+
+        static List<io.connector.model.sensorthings.Observation> toObservation(List<io.connector.module.senslog1.entity.Observation> senslogObservations,
+                                                                         RequestUriComponent uriComponent) {
+            List<io.connector.model.sensorthings.Observation> observations = new ArrayList<>(senslogObservations.size());
+            for (io.connector.module.senslog1.entity.Observation senslogObservation : senslogObservations) {
+                observations.add(toObservation(senslogObservation, uriComponent));
+            }
+            return observations;
+        }
+
+        static io.connector.model.sensorthings.Observation toObservation(io.connector.module.senslog1.entity.Observation senslogObservation, RequestUriComponent uriComponent) {
+            Observation observation = new Observation();
+            String observationId = String.valueOf(senslogObservation.getId());
+            String absoluteUrl = uriComponent.getGatewayUri();
+            observation.setId(observationId);
+            observation.setSelfLink(format("%s/Observations(%s)", absoluteUrl, observationId));
+            // TODO - co s feature of interest?
+            // observation.setFeatureOfInterestNavigationLink(format("Observations(%s)/FeatureOfInterest", observationId));
+//            observation.setFeatureOfInterestNavigationLink("https://storage07-afarcloud.qa.pdmfc.com/storage/rest/registry/getAllObservationTypes");
+            observation.setDataStreamNavigationLink(format("%s/Observations(%s)/Datastream", absoluteUrl, observationId));
+            observation.setPhenomenonTime(senslogObservation.getTimestamp().toString());
+            observation.setResultTime(senslogObservation.getTimeReceived().toString());
+            observation.setResult(senslogObservation.getObservedValue());
+            return observation;
+        }
+
+        static Sensor toSensor(io.connector.module.senslog1.entity.Sensor senslogSensor, RequestUriComponent uriComponent) {
+            String afcDomain = "https://storage07-afarcloud.qa.pdmfc.com/storage/rest"; // TODO - naco zmenit tohle
+
+            Sensor sensor = new Sensor();
+            String sensorId = String.valueOf(senslogSensor.getId());
+            String absoluteUrl = uriComponent.getGatewayUri();
+            sensor.setId(sensorId);
+            sensor.setSelfLink(format("%s/Sensors(%s)", absoluteUrl, sensorId));
+            sensor.setDataStreamNavigationLink(format("%s/Sensors(%s)/Datastreams", absoluteUrl, sensorId));
+            sensor.setName(senslogSensor.getName());
+            sensor.setDescription(senslogSensor.getType());
+            sensor.setEncodingType("application/json");
+            sensor.setMetadata(format("%s/registry/getSensor/%s", afcDomain, sensorId));
+
+            return sensor;
+        }
 
     }
 }

+ 16 - 0
connector-module-senslog1/src/main/java/io/connector/module/senslog1/jdbi/JDBI.java

@@ -0,0 +1,16 @@
+package io.connector.module.senslog1.jdbi;
+
+import org.jdbi.v3.core.Jdbi;
+
+public class JDBI {
+
+    private static Jdbi connection;
+
+    public static Jdbi get() {
+        if (connection == null) {
+            connection = Jdbi.create("jdbc:postgresql://localhost:5432/senslog1", "postgres", "root");
+        }
+
+        return connection;
+    }
+}