kopia lustrzana https://github.com/bertrik/ttnhabbridge
Implement proper check on whether a GW has a location and add a gateway cache.
rodzic
aab2ef03f6
commit
57f56c9e8a
|
@ -13,12 +13,12 @@ import org.slf4j.LoggerFactory;
|
|||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
|
||||
import nl.sikken.bertrik.hab.ExpiringCache;
|
||||
import nl.sikken.bertrik.hab.PayloadDecoder;
|
||||
import nl.sikken.bertrik.hab.Sentence;
|
||||
import nl.sikken.bertrik.hab.habitat.HabReceiver;
|
||||
import nl.sikken.bertrik.hab.habitat.HabitatUploader;
|
||||
import nl.sikken.bertrik.hab.habitat.IHabitatRestApi;
|
||||
import nl.sikken.bertrik.hab.habitat.Location;
|
||||
import nl.sikken.bertrik.hab.ttn.TtnListener;
|
||||
import nl.sikken.bertrik.hab.ttn.TtnMessage;
|
||||
import nl.sikken.bertrik.hab.ttn.TtnMessageGateway;
|
||||
|
@ -38,6 +38,7 @@ public final class TtnHabBridge {
|
|||
private final HabitatUploader habUploader;
|
||||
private final PayloadDecoder decoder;
|
||||
private final ObjectMapper mapper;
|
||||
private final ExpiringCache gwCache;
|
||||
|
||||
/**
|
||||
* Main application entry point.
|
||||
|
@ -67,6 +68,7 @@ public final class TtnHabBridge {
|
|||
this.habUploader = new HabitatUploader(restApi);
|
||||
this.mapper = new ObjectMapper();
|
||||
this.decoder = new PayloadDecoder();
|
||||
this.gwCache = new ExpiringCache(600);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -98,20 +100,16 @@ public final class TtnHabBridge {
|
|||
final String line = sentence.format();
|
||||
|
||||
// create listeners
|
||||
final Date now = new Date();
|
||||
final List<HabReceiver> receivers = new ArrayList<>();
|
||||
for (TtnMessageGateway gw : message.getMetaData().getMqttGateways()) {
|
||||
final Double latitude = gw.getLatitude();
|
||||
final Double longitude = gw.getLongitude();
|
||||
final Double altitude = gw.getAltitude();
|
||||
if ((latitude != null) && (longitude != null) && (altitude != null)) {
|
||||
final HabReceiver receiver = new HabReceiver(gw.getId(),
|
||||
new Location(gw.getLatitude(), gw.getLongitude(), gw.getAltitude()));
|
||||
receivers.add(receiver);
|
||||
}
|
||||
if (gw.hasLocation() && gwCache.add(gw.getId(), now)) {
|
||||
final HabReceiver receiver = new HabReceiver(gw.getId(), gw.getLocation());
|
||||
receivers.add(receiver);
|
||||
}
|
||||
}
|
||||
|
||||
// send listener data
|
||||
final Date now = new Date();
|
||||
for (HabReceiver receiver : receivers) {
|
||||
habUploader.scheduleListenerDataUpload(receiver, now);
|
||||
}
|
||||
|
@ -134,6 +132,7 @@ public final class TtnHabBridge {
|
|||
LOG.info("Stopping TTN HAB bridge application");
|
||||
ttnListener.stop();
|
||||
habUploader.stop();
|
||||
LOG.info("Stopped TTN HAB bridge application");
|
||||
}
|
||||
|
||||
private static ITtnHabBridgeConfig readConfig(File file) throws IOException {
|
||||
|
|
|
@ -0,0 +1,51 @@
|
|||
package nl.sikken.bertrik.hab;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
* Simple expiring cache.
|
||||
*/
|
||||
public final class ExpiringCache {
|
||||
|
||||
private final Map<String, Date> map = new ConcurrentHashMap<String, Date>();
|
||||
private final long expiryTimeMs;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param expiryTimeSec the expiry time (seconds)
|
||||
*/
|
||||
public ExpiringCache(int expiryTimeSec) {
|
||||
this.expiryTimeMs = expiryTimeSec * 1000L;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the item to the cache.
|
||||
*
|
||||
* @param id the id of the item
|
||||
* @param date the date
|
||||
* @return true if the item was newly added
|
||||
*/
|
||||
public boolean add(String id, Date date) {
|
||||
cleanUp(date);
|
||||
final Date previous = map.putIfAbsent(id, date);
|
||||
return previous == null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Cleans up the cache, removing all items from before the current date minus the expiration timeout.
|
||||
*
|
||||
* @param now the current date
|
||||
*/
|
||||
private void cleanUp(Date now) {
|
||||
final Date limit = new Date(now.getTime() - expiryTimeMs);
|
||||
map.forEach((k,v) -> {
|
||||
if (v.before(limit)) {
|
||||
map.remove(k, v);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
|
@ -1,8 +1,11 @@
|
|||
package nl.sikken.bertrik.hab.ttn;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
import nl.sikken.bertrik.hab.habitat.Location;
|
||||
|
||||
/**
|
||||
* Representation of a gateway in the metadata of the TTN MQTT JSON format.
|
||||
*/
|
||||
|
@ -27,6 +30,30 @@ public final class TtnMessageGateway {
|
|||
@JsonProperty("altitude")
|
||||
private Double altitude;
|
||||
|
||||
private TtnMessageGateway() {
|
||||
// jackson constructor
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param id the id (name)
|
||||
* @param trusted whether it is trusted
|
||||
* @param time the time
|
||||
* @param lat the latitude (degrees)
|
||||
* @param lon the longitude (degrees)
|
||||
* @param alt the altitude (meters)
|
||||
*/
|
||||
public TtnMessageGateway(String id, boolean trusted, String time, Double lat, Double lon, Double alt) {
|
||||
this();
|
||||
this.id = id;
|
||||
this.trusted = trusted;
|
||||
this.time = time;
|
||||
this.latitude = lat;
|
||||
this.longitude = lon;
|
||||
this.altitude = alt;
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
@ -51,4 +78,14 @@ public final class TtnMessageGateway {
|
|||
return altitude;
|
||||
}
|
||||
|
||||
@JsonIgnore
|
||||
public boolean hasLocation() {
|
||||
return latitude != null && longitude != null && altitude != null;
|
||||
}
|
||||
|
||||
@JsonIgnore
|
||||
public Location getLocation() {
|
||||
return new Location(latitude, longitude, altitude);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Ładowanie…
Reference in New Issue