kopia lustrzana https://github.com/bertrik/ttnhabbridge
Rename classes, prepare for helium support.
rodzic
2c0ced163f
commit
59202b25a1
|
@ -22,9 +22,9 @@ 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.TtnUplinkMessage;
|
||||
import nl.sikken.bertrik.hab.ttn.TtnUplinkMessage.GatewayInfo;
|
||||
import nl.sikken.bertrik.hab.lorawan.MqttListener;
|
||||
import nl.sikken.bertrik.hab.lorawan.LoraWanUplinkMessage;
|
||||
import nl.sikken.bertrik.hab.lorawan.LoraWanUplinkMessage.GatewayInfo;
|
||||
|
||||
/**
|
||||
* Bridge between the-things-network and the habhub network.
|
||||
|
@ -35,7 +35,7 @@ public final class TtnHabBridge {
|
|||
private static final Logger LOG = LoggerFactory.getLogger(TtnHabBridge.class);
|
||||
private static final String CONFIG_FILE = "ttnhabbridge.properties";
|
||||
|
||||
private final TtnListener ttnListener;
|
||||
private final MqttListener ttnListener;
|
||||
private final HabitatUploader habUploader;
|
||||
private final PayloadDecoder decoder;
|
||||
private final ExpiringCache gwCache;
|
||||
|
@ -65,7 +65,7 @@ public final class TtnHabBridge {
|
|||
* @param config the application configuration
|
||||
*/
|
||||
private TtnHabBridge(ITtnHabBridgeConfig config) {
|
||||
this.ttnListener = new TtnListener(this::handleTTNMessage, config.getTtnMqttUrl(), config.getTtnAppId(),
|
||||
this.ttnListener = new MqttListener(this::handleTTNMessage, config.getTtnMqttUrl(), config.getTtnAppId(),
|
||||
config.getTtnAppKey());
|
||||
IHabitatRestApi restApi = HabitatUploader.newRestClient(config.getHabitatUrl(), config.getHabitatTimeout());
|
||||
this.habUploader = new HabitatUploader(restApi);
|
||||
|
@ -94,7 +94,7 @@ public final class TtnHabBridge {
|
|||
* @param textMessage the message contents
|
||||
* @param now message arrival time
|
||||
*/
|
||||
private void handleTTNMessage(TtnUplinkMessage message) {
|
||||
private void handleTTNMessage(LoraWanUplinkMessage message) {
|
||||
Instant now = Instant.now();
|
||||
try {
|
||||
// decode from JSON
|
||||
|
|
|
@ -13,7 +13,7 @@ import nl.sikken.bertrik.cayenne.CayenneException;
|
|||
import nl.sikken.bertrik.cayenne.CayenneItem;
|
||||
import nl.sikken.bertrik.cayenne.CayenneMessage;
|
||||
import nl.sikken.bertrik.cayenne.ECayennePayloadFormat;
|
||||
import nl.sikken.bertrik.hab.ttn.TtnUplinkMessage;
|
||||
import nl.sikken.bertrik.hab.lorawan.LoraWanUplinkMessage;
|
||||
|
||||
/**
|
||||
* Decodes a payload and encodes it into a UKHAS sentence.
|
||||
|
@ -41,7 +41,7 @@ public final class PayloadDecoder {
|
|||
* @return the UKHAS sentence
|
||||
* @throws DecodeException in case of a problem decoding the message
|
||||
*/
|
||||
public Sentence decode(TtnUplinkMessage message) throws DecodeException {
|
||||
public Sentence decode(LoraWanUplinkMessage message) throws DecodeException {
|
||||
// common fields
|
||||
String callSign = message.getDevId();
|
||||
int counter = message.getCounter();
|
||||
|
@ -74,7 +74,7 @@ public final class PayloadDecoder {
|
|||
* @return the UKHAS sentence
|
||||
* @throws DecodeException in case of a problem decoding the message
|
||||
*/
|
||||
private Sentence decodeSodaqOne(TtnUplinkMessage message, String callSign, int counter) throws DecodeException {
|
||||
private Sentence decodeSodaqOne(LoraWanUplinkMessage message, String callSign, int counter) throws DecodeException {
|
||||
LOG.info("Decoding 'sodaqone' message...");
|
||||
|
||||
try {
|
||||
|
@ -107,7 +107,7 @@ public final class PayloadDecoder {
|
|||
* @return the UKHAS sentence
|
||||
* @throws DecodeException in case of a problem decoding the message
|
||||
*/
|
||||
private Sentence decodeJson(TtnUplinkMessage message, String callSign, int counter) throws DecodeException {
|
||||
private Sentence decodeJson(LoraWanUplinkMessage message, String callSign, int counter) throws DecodeException {
|
||||
LOG.info("Decoding 'json' message...");
|
||||
|
||||
try {
|
||||
|
@ -154,7 +154,7 @@ public final class PayloadDecoder {
|
|||
* @return the UKHAS sentence
|
||||
* @throws DecodeException
|
||||
*/
|
||||
private Sentence decodeCayenne(TtnUplinkMessage message, String callSign, int counter) throws DecodeException {
|
||||
private Sentence decodeCayenne(LoraWanUplinkMessage message, String callSign, int counter) throws DecodeException {
|
||||
LOG.info("Decoding 'cayenne' message...");
|
||||
|
||||
try {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
package nl.sikken.bertrik.hab.ttn;
|
||||
package nl.sikken.bertrik.hab.lorawan;
|
||||
|
||||
/**
|
||||
* Interface of the callback from the TTN listener.
|
||||
|
@ -9,6 +9,6 @@ public interface IMessageReceived {
|
|||
* Indicates that a message was received.
|
||||
* @param message the message
|
||||
*/
|
||||
void messageReceived(TtnUplinkMessage message);
|
||||
void messageReceived(LoraWanUplinkMessage message);
|
||||
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package nl.sikken.bertrik.hab.ttn;
|
||||
package nl.sikken.bertrik.hab.lorawan;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.ArrayList;
|
||||
|
@ -10,10 +10,10 @@ import java.util.Map;
|
|||
import nl.sikken.bertrik.hab.habitat.Location;
|
||||
|
||||
/**
|
||||
* Uplink message, TTN stack version independent, containing all information
|
||||
* needed to create a habhub sentence
|
||||
* LoRaWAN uplink message, stack independent, containing all information needed
|
||||
* to create a habhub sentence
|
||||
*/
|
||||
public final class TtnUplinkMessage {
|
||||
public final class LoraWanUplinkMessage {
|
||||
|
||||
private final Instant time;
|
||||
private final String appId;
|
||||
|
@ -25,7 +25,7 @@ public final class TtnUplinkMessage {
|
|||
private final boolean isRetry;
|
||||
private final List<GatewayInfo> gateways = new ArrayList<>();
|
||||
|
||||
public TtnUplinkMessage(Instant time, String appId, String deviceId, int counter, int port, byte[] payloadRaw,
|
||||
public LoraWanUplinkMessage(Instant time, String appId, String deviceId, int counter, int port, byte[] payloadRaw,
|
||||
boolean isRetry) {
|
||||
this.time = Instant.from(time);
|
||||
this.appId = appId;
|
|
@ -1,4 +1,4 @@
|
|||
package nl.sikken.bertrik.hab.ttn;
|
||||
package nl.sikken.bertrik.hab.lorawan;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
|
@ -16,11 +16,11 @@ import com.fasterxml.jackson.core.JsonProcessingException;
|
|||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
|
||||
/**
|
||||
* Listener process for receiving data from the TTN.
|
||||
* Listener process for receiving data from an MQTT server.
|
||||
*/
|
||||
public final class TtnListener {
|
||||
public final class MqttListener {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(TtnListener.class);
|
||||
private static final Logger LOG = LoggerFactory.getLogger(MqttListener.class);
|
||||
private static final long DISCONNECT_TIMEOUT_MS = 3000;
|
||||
|
||||
private final IMessageReceived callback;
|
||||
|
@ -36,7 +36,7 @@ public final class TtnListener {
|
|||
* @param appId the user name
|
||||
* @param appKey the password
|
||||
*/
|
||||
public TtnListener(IMessageReceived callback, String url, String appId, String appKey) {
|
||||
public MqttListener(IMessageReceived callback, String url, String appId, String appKey) {
|
||||
LOG.info("Creating client for MQTT server '{}' for app '{}'", url, appId);
|
||||
try {
|
||||
this.mqttClient = new MqttClient(url, MqttClient.generateClientId(), new MemoryPersistence());
|
||||
|
@ -57,7 +57,7 @@ public final class TtnListener {
|
|||
// notify our caller in a thread safe manner
|
||||
private void handleMessage(String topic, String payload) {
|
||||
try {
|
||||
TtnUplinkMessage uplinkMessage = convertMessage(topic, payload);
|
||||
LoraWanUplinkMessage uplinkMessage = convertMessage(topic, payload);
|
||||
callback.messageReceived(uplinkMessage);
|
||||
} catch (JsonProcessingException e) {
|
||||
LOG.warn("Caught {}", e.getMessage());
|
||||
|
@ -68,7 +68,7 @@ public final class TtnListener {
|
|||
}
|
||||
|
||||
// package private for testing
|
||||
TtnUplinkMessage convertMessage(String topic, String payload) throws JsonProcessingException {
|
||||
LoraWanUplinkMessage convertMessage(String topic, String payload) throws JsonProcessingException {
|
||||
Ttnv3UplinkMessage v3message = objectMapper.readValue(payload, Ttnv3UplinkMessage.class);
|
||||
return v3message.toUplinkMessage();
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package nl.sikken.bertrik.hab.ttn;
|
||||
package nl.sikken.bertrik.hab.lorawan;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.ArrayList;
|
||||
|
@ -86,8 +86,8 @@ public final class Ttnv3UplinkMessage {
|
|||
private double altitude = Double.NaN;
|
||||
}
|
||||
|
||||
public TtnUplinkMessage toUplinkMessage() {
|
||||
TtnUplinkMessage uplink = new TtnUplinkMessage(Instant.parse(receivedAt),
|
||||
public LoraWanUplinkMessage toUplinkMessage() {
|
||||
LoraWanUplinkMessage uplink = new LoraWanUplinkMessage(Instant.parse(receivedAt),
|
||||
endDeviceIds.applicationIds.applicationId, endDeviceIds.deviceId, uplinkMessage.fcnt,
|
||||
uplinkMessage.fport, uplinkMessage.payload, false);
|
||||
for (RxMetadata metadata : uplinkMessage.rxMetadata) {
|
|
@ -1,86 +0,0 @@
|
|||
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.
|
||||
*/
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public final class TtnMessageGateway {
|
||||
|
||||
@JsonProperty("gtw_id")
|
||||
private String id;
|
||||
|
||||
@JsonProperty("gtw_trusted")
|
||||
private boolean trusted;
|
||||
|
||||
@JsonProperty("time")
|
||||
private String time;
|
||||
|
||||
@JsonProperty("latitude")
|
||||
private double latitude = Double.NaN;
|
||||
|
||||
@JsonProperty("longitude")
|
||||
private double longitude = Double.NaN;
|
||||
|
||||
@JsonProperty("altitude")
|
||||
private double altitude = Double.NaN;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
public boolean isTrusted() {
|
||||
return trusted;
|
||||
}
|
||||
|
||||
public String getTime() {
|
||||
return time;
|
||||
}
|
||||
|
||||
public Double getLatitude() {
|
||||
return latitude;
|
||||
}
|
||||
|
||||
public Double getLongitude() {
|
||||
return longitude;
|
||||
}
|
||||
|
||||
public Double getAltitude() {
|
||||
return altitude;
|
||||
}
|
||||
|
||||
@JsonIgnore
|
||||
public Location getLocation() {
|
||||
return new Location(latitude, longitude, altitude);
|
||||
}
|
||||
|
||||
}
|
|
@ -6,7 +6,7 @@ import java.util.Base64;
|
|||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import nl.sikken.bertrik.hab.ttn.TtnUplinkMessage;
|
||||
import nl.sikken.bertrik.hab.lorawan.LoraWanUplinkMessage;
|
||||
|
||||
/**
|
||||
* Unit tests for PayloadDecoder.
|
||||
|
@ -29,7 +29,7 @@ public final class PayloadDecoderTest {
|
|||
*/
|
||||
@Test
|
||||
public void testCayenne2() throws DecodeException {
|
||||
TtnUplinkMessage message = new TtnUplinkMessage(Instant.parse("2020-02-05T22:00:58.930936Z"), "test", "test",
|
||||
LoraWanUplinkMessage message = new LoraWanUplinkMessage(Instant.parse("2020-02-05T22:00:58.930936Z"), "test", "test",
|
||||
123, 1, Base64.getDecoder().decode("AYgH1ecAzV4AC7gCZwArAwIBhg=="), false);
|
||||
// decode payload
|
||||
PayloadDecoder decoder = new PayloadDecoder(EPayloadEncoding.CAYENNE);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
package nl.sikken.bertrik.hab.ttn;
|
||||
package nl.sikken.bertrik.hab.lorawan;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
@ -9,7 +9,9 @@ import org.junit.Test;
|
|||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
|
||||
import nl.sikken.bertrik.hab.ttn.TtnUplinkMessage.GatewayInfo;
|
||||
import nl.sikken.bertrik.hab.lorawan.LoraWanUplinkMessage;
|
||||
import nl.sikken.bertrik.hab.lorawan.Ttnv3UplinkMessage;
|
||||
import nl.sikken.bertrik.hab.lorawan.LoraWanUplinkMessage.GatewayInfo;
|
||||
|
||||
public final class Ttnv3UplinkMessageTest {
|
||||
|
||||
|
@ -20,7 +22,7 @@ public final class Ttnv3UplinkMessageTest {
|
|||
InputStream is = getClass().getClassLoader().getResourceAsStream("ttnv3_uplink.json");
|
||||
Ttnv3UplinkMessage message = MAPPER.readValue(is, Ttnv3UplinkMessage.class);
|
||||
|
||||
TtnUplinkMessage uplinkMessage = message.toUplinkMessage();
|
||||
LoraWanUplinkMessage uplinkMessage = message.toUplinkMessage();
|
||||
|
||||
Assert.assertEquals("test2id", uplinkMessage.getAppId());
|
||||
Assert.assertEquals("v3demo1", uplinkMessage.getDevId());
|
Ładowanie…
Reference in New Issue