kopia lustrzana https://github.com/bertrik/ttnhabbridge
Don't bother with using 'final' for local variables.
rodzic
1488846f5a
commit
5202da0444
|
@ -22,10 +22,10 @@ public final class CayenneMessage {
|
|||
* @throws CayenneException in case of a parsing problem
|
||||
*/
|
||||
public static CayenneMessage parse(byte[] data) throws CayenneException {
|
||||
final CayenneMessage message = new CayenneMessage();
|
||||
final ByteBuffer bb = ByteBuffer.wrap(data);
|
||||
CayenneMessage message = new CayenneMessage();
|
||||
ByteBuffer bb = ByteBuffer.wrap(data);
|
||||
while (bb.hasRemaining()) {
|
||||
final CayenneItem item = CayenneItem.parse(bb);
|
||||
CayenneItem item = CayenneItem.parse(bb);
|
||||
message.add(item);
|
||||
}
|
||||
return message;
|
||||
|
|
|
@ -27,7 +27,7 @@ public final class BooleanFormatter extends BaseFormatter {
|
|||
|
||||
@Override
|
||||
public Double[] parse(ByteBuffer bb) {
|
||||
final Double[] values = new Double[length];
|
||||
Double[] values = new Double[length];
|
||||
for (int i = 0; i < length; i++) {
|
||||
values[i] = (getValue(bb, size, signed) > 0) ? 1.0 : 0.0;
|
||||
}
|
||||
|
@ -36,7 +36,7 @@ public final class BooleanFormatter extends BaseFormatter {
|
|||
|
||||
@Override
|
||||
public String[] format(Double[] values) {
|
||||
final String[] formatted = new String[length];
|
||||
String[] formatted = new String[length];
|
||||
for (int i = 0; i < length; i++) {
|
||||
formatted[i] = String.format(Locale.US, "%d", values[i].intValue());
|
||||
}
|
||||
|
|
|
@ -40,7 +40,7 @@ public final class FloatFormatter extends BaseFormatter {
|
|||
|
||||
@Override
|
||||
public Double[] parse(ByteBuffer bb) {
|
||||
final Double[] values = new Double[length];
|
||||
Double[] values = new Double[length];
|
||||
for (int i = 0; i < length; i++) {
|
||||
values[i] = scale * getValue(bb, size, signed);
|
||||
}
|
||||
|
@ -49,7 +49,7 @@ public final class FloatFormatter extends BaseFormatter {
|
|||
|
||||
@Override
|
||||
public String[] format(Double[] values) {
|
||||
final String[] formatted = new String[length];
|
||||
String[] formatted = new String[length];
|
||||
for (int i = 0; i < length; i++) {
|
||||
formatted[i] = String.format(Locale.ROOT, formatString, values[i]);
|
||||
}
|
||||
|
|
|
@ -13,9 +13,9 @@ public final class GpsFormatter extends BaseFormatter {
|
|||
|
||||
@Override
|
||||
public Double[] parse(ByteBuffer bb) {
|
||||
final double lat = LAT_LON_SCALE * getValue(bb, 3, true);
|
||||
final double lon = LAT_LON_SCALE * getValue(bb, 3, true);
|
||||
final double alt = ALT_SCALE * getValue(bb, 3, true);
|
||||
double lat = LAT_LON_SCALE * getValue(bb, 3, true);
|
||||
double lon = LAT_LON_SCALE * getValue(bb, 3, true);
|
||||
double alt = ALT_SCALE * getValue(bb, 3, true);
|
||||
return new Double[] {lat, lon, alt};
|
||||
}
|
||||
|
||||
|
|
|
@ -49,8 +49,8 @@ public final class TtnHabBridge {
|
|||
* @throws MqttException in case of a problem starting MQTT client
|
||||
*/
|
||||
public static void main(String[] arguments) throws IOException, MqttException {
|
||||
final ITtnHabBridgeConfig config = readConfig(new File(CONFIG_FILE));
|
||||
final TtnHabBridge app = new TtnHabBridge(config);
|
||||
ITtnHabBridgeConfig config = readConfig(new File(CONFIG_FILE));
|
||||
TtnHabBridge app = new TtnHabBridge(config);
|
||||
|
||||
Thread.setDefaultUncaughtExceptionHandler(app::handleUncaughtException);
|
||||
|
||||
|
@ -66,7 +66,7 @@ public final class TtnHabBridge {
|
|||
private TtnHabBridge(ITtnHabBridgeConfig config) {
|
||||
this.ttnListener = new TtnListener(this::handleTTNMessage,
|
||||
config.getTtnMqttUrl(), config.getTtnAppId(), config.getTtnAppKey());
|
||||
final IHabitatRestApi restApi =
|
||||
IHabitatRestApi restApi =
|
||||
HabitatUploader.newRestClient(config.getHabitatUrl(), config.getHabitatTimeout());
|
||||
this.habUploader = new HabitatUploader(restApi);
|
||||
this.mapper = new ObjectMapper();
|
||||
|
@ -98,17 +98,17 @@ public final class TtnHabBridge {
|
|||
private void handleTTNMessage(String topic, String textMessage) {
|
||||
try {
|
||||
// decode from JSON
|
||||
final TtnMessage message = mapper.readValue(textMessage, TtnMessage.class);
|
||||
final Sentence sentence = decoder.decode(message);
|
||||
final String line = sentence.format();
|
||||
TtnMessage message = mapper.readValue(textMessage, TtnMessage.class);
|
||||
Sentence sentence = decoder.decode(message);
|
||||
String line = sentence.format();
|
||||
|
||||
// collect list of listeners
|
||||
final Instant now = Instant.now();
|
||||
final List<HabReceiver> receivers = new ArrayList<>();
|
||||
Instant now = Instant.now();
|
||||
List<HabReceiver> receivers = new ArrayList<>();
|
||||
for (TtnMessageGateway gw : message.getMetaData().getMqttGateways()) {
|
||||
final String gwName = gw.getId();
|
||||
final Location gwLocation = gw.getLocation();
|
||||
final HabReceiver receiver = new HabReceiver(gwName, gwLocation);
|
||||
String gwName = gw.getId();
|
||||
Location gwLocation = gw.getLocation();
|
||||
HabReceiver receiver = new HabReceiver(gwName, gwLocation);
|
||||
receivers.add(receiver);
|
||||
|
||||
// send listener data only if it has a valid location and hasn't been sent recently
|
||||
|
@ -153,7 +153,7 @@ public final class TtnHabBridge {
|
|||
}
|
||||
|
||||
private static ITtnHabBridgeConfig readConfig(File file) throws IOException {
|
||||
final TtnHabBridgeConfig config = new TtnHabBridgeConfig();
|
||||
TtnHabBridgeConfig config = new TtnHabBridgeConfig();
|
||||
try (FileInputStream fis = new FileInputStream(file)) {
|
||||
config.load(fis);
|
||||
} catch (IOException e) {
|
||||
|
|
|
@ -61,7 +61,7 @@ public final class TtnHabBridgeConfig implements ITtnHabBridgeConfig {
|
|||
* @throws IOException in case of a problem reading the file
|
||||
*/
|
||||
public void load(InputStream is) throws IOException {
|
||||
final Properties properties = new Properties();
|
||||
Properties properties = new Properties();
|
||||
properties.load(is);
|
||||
for (EConfigItem e : EConfigItem.values()) {
|
||||
String value = properties.getProperty(e.key);
|
||||
|
|
|
@ -30,7 +30,7 @@ public final class ExpiringCache {
|
|||
*/
|
||||
public boolean add(String id, Instant instant) {
|
||||
cleanUp(instant);
|
||||
final Instant previous = map.putIfAbsent(id, instant);
|
||||
Instant previous = map.putIfAbsent(id, instant);
|
||||
return previous == null;
|
||||
}
|
||||
|
||||
|
@ -40,7 +40,7 @@ public final class ExpiringCache {
|
|||
* @param now the current date
|
||||
*/
|
||||
private void cleanUp(Instant now) {
|
||||
final Instant limit = now.minusSeconds(expiryTimeSec);
|
||||
Instant limit = now.minusSeconds(expiryTimeSec);
|
||||
map.forEach((k,v) -> {
|
||||
if (v.isBefore(limit)) {
|
||||
map.remove(k, v);
|
||||
|
|
|
@ -45,11 +45,11 @@ public final class PayloadDecoder {
|
|||
*/
|
||||
public Sentence decode(TtnMessage message) throws DecodeException {
|
||||
// common fields
|
||||
final String callSign = message.getDevId();
|
||||
final int counter = message.getCounter();
|
||||
String callSign = message.getDevId();
|
||||
int counter = message.getCounter();
|
||||
|
||||
// specific fields
|
||||
final Sentence sentence;
|
||||
Sentence sentence;
|
||||
switch (encoding) {
|
||||
case SODAQ_ONE:
|
||||
sentence = decodeSodaqOne(message, callSign, counter);
|
||||
|
@ -81,14 +81,14 @@ public final class PayloadDecoder {
|
|||
|
||||
try {
|
||||
// SODAQ payload
|
||||
final SodaqOnePayload sodaq = SodaqOnePayload.parse(message.getPayloadRaw());
|
||||
SodaqOnePayload sodaq = SodaqOnePayload.parse(message.getPayloadRaw());
|
||||
|
||||
// construct a sentence
|
||||
final double latitude = sodaq.getLatitude();
|
||||
final double longitude = sodaq.getLongitude();
|
||||
final double altitude = sodaq.getAltitude();
|
||||
final Instant instant = Instant.ofEpochSecond(sodaq.getTimeStamp());
|
||||
final Sentence sentence = new Sentence(callSign, counter, instant, latitude, longitude, altitude);
|
||||
double latitude = sodaq.getLatitude();
|
||||
double longitude = sodaq.getLongitude();
|
||||
double altitude = sodaq.getAltitude();
|
||||
Instant instant = Instant.ofEpochSecond(sodaq.getTimeStamp());
|
||||
Sentence sentence = new Sentence(callSign, counter, instant, latitude, longitude, altitude);
|
||||
sentence.addField(String.format(Locale.ROOT, "%.0f", sodaq.getBoardTemp()));
|
||||
sentence.addField(String.format(Locale.ROOT, "%.2f", sodaq.getBattVoltage()));
|
||||
return sentence;
|
||||
|
@ -110,14 +110,14 @@ public final class PayloadDecoder {
|
|||
LOG.info("Decoding 'json' message...");
|
||||
|
||||
try {
|
||||
final Instant time = message.getMetaData().getTime();
|
||||
final ObjectNode fields = message.getPayloadFields();
|
||||
final double latitude = fields.get("lat").doubleValue();
|
||||
final double longitude = fields.get("lon").doubleValue();
|
||||
final double altitude = fields.get("gpsalt").doubleValue();
|
||||
final Sentence sentence = new Sentence(callSign, counter, time, latitude, longitude, altitude);
|
||||
final JsonNode tempNode = fields.get("temp");
|
||||
final JsonNode vccNode = fields.get("vcc");
|
||||
Instant time = message.getMetaData().getTime();
|
||||
ObjectNode fields = message.getPayloadFields();
|
||||
double latitude = fields.get("lat").doubleValue();
|
||||
double longitude = fields.get("lon").doubleValue();
|
||||
double altitude = fields.get("gpsalt").doubleValue();
|
||||
Sentence sentence = new Sentence(callSign, counter, time, latitude, longitude, altitude);
|
||||
JsonNode tempNode = fields.get("temp");
|
||||
JsonNode vccNode = fields.get("vcc");
|
||||
if ((tempNode != null) && (vccNode != null)) {
|
||||
sentence.addField(String.format(Locale.ROOT, "%.1f", tempNode.doubleValue()));
|
||||
sentence.addField(String.format(Locale.ROOT, "%.3f", vccNode.doubleValue()));
|
||||
|
@ -141,20 +141,20 @@ public final class PayloadDecoder {
|
|||
LOG.info("Decoding 'cayenne' message...");
|
||||
|
||||
try {
|
||||
final Instant time = message.getMetaData().getTime();
|
||||
final CayenneMessage cayenne = CayenneMessage.parse(message.getPayloadRaw());
|
||||
Instant time = message.getMetaData().getTime();
|
||||
CayenneMessage cayenne = CayenneMessage.parse(message.getPayloadRaw());
|
||||
|
||||
// decode location
|
||||
final CayenneItem gpsItem = cayenne.ofType(ECayenneItem.GPS_LOCATION);
|
||||
final Double[] location = gpsItem.getValues();
|
||||
final double latitude = location[0];
|
||||
final double longitude = location[1];
|
||||
final double altitude = location[2];
|
||||
final Sentence sentence = new Sentence(callSign, counter, time, latitude, longitude, altitude);
|
||||
CayenneItem gpsItem = cayenne.ofType(ECayenneItem.GPS_LOCATION);
|
||||
Double[] location = gpsItem.getValues();
|
||||
double latitude = location[0];
|
||||
double longitude = location[1];
|
||||
double altitude = location[2];
|
||||
Sentence sentence = new Sentence(callSign, counter, time, latitude, longitude, altitude);
|
||||
|
||||
// temperature and battery
|
||||
final CayenneItem tempItem = cayenne.ofType(ECayenneItem.TEMPERATURE);
|
||||
final CayenneItem battItem = cayenne.ofType(ECayenneItem.ANALOG_INPUT);
|
||||
CayenneItem tempItem = cayenne.ofType(ECayenneItem.TEMPERATURE);
|
||||
CayenneItem battItem = cayenne.ofType(ECayenneItem.ANALOG_INPUT);
|
||||
if ((tempItem != null) && (battItem != null)) {
|
||||
sentence.addField(tempItem.format()[0]);
|
||||
sentence.addField(battItem.format()[0]);
|
||||
|
|
|
@ -60,23 +60,23 @@ public final class Sentence {
|
|||
*/
|
||||
public String format() {
|
||||
// format time
|
||||
final LocalDateTime local = LocalDateTime.ofInstant(time, ZoneId.of("UTC"));
|
||||
final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("HH:mm:ss", Locale.ROOT);
|
||||
final String timeString = local.format(formatter);
|
||||
LocalDateTime local = LocalDateTime.ofInstant(time, ZoneId.of("UTC"));
|
||||
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("HH:mm:ss", Locale.ROOT);
|
||||
String timeString = local.format(formatter);
|
||||
|
||||
// format basic string
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(String.format(Locale.ROOT, "%s,%d,%s,%.6f,%.6f,%.1f", callSign, id, timeString, latitude, longitude,
|
||||
altitude));
|
||||
for (String s : extras) {
|
||||
sb.append(',');
|
||||
sb.append(s);
|
||||
}
|
||||
final String basic = sb.toString();
|
||||
String basic = sb.toString();
|
||||
|
||||
// append header, checksum, etc
|
||||
final byte[] bytes = basic.getBytes(StandardCharsets.US_ASCII);
|
||||
final int crcValue = crc16.calculate(bytes, 0xFFFF);
|
||||
byte[] bytes = basic.getBytes(StandardCharsets.US_ASCII);
|
||||
int crcValue = crc16.calculate(bytes, 0xFFFF);
|
||||
return String.format(Locale.ROOT, "$$%s*%04X\n", basic, crcValue);
|
||||
}
|
||||
|
||||
|
|
|
@ -58,17 +58,17 @@ public final class SodaqOnePayload {
|
|||
* @throws BufferUnderflowException in case of a buffer underflow
|
||||
*/
|
||||
public static SodaqOnePayload parse(byte[] raw) throws BufferUnderflowException {
|
||||
final ByteBuffer bb = ByteBuffer.wrap(raw).order(ByteOrder.LITTLE_ENDIAN);
|
||||
final long time = bb.getInt() & 0xFFFFFFFFL;
|
||||
final double voltage = 3.0 + 0.01 * (bb.get() & 0xFF);
|
||||
final double boardTemp = bb.get();
|
||||
final double latitude = bb.getInt() / 1e7;
|
||||
final double longitude = bb.getInt() / 1e7;
|
||||
final int altitude = bb.getShort();
|
||||
final double sog = bb.getShort() / 360.0;
|
||||
final int cog = bb.get();
|
||||
final int numSats = bb.get();
|
||||
final int ttf = bb.get();
|
||||
ByteBuffer bb = ByteBuffer.wrap(raw).order(ByteOrder.LITTLE_ENDIAN);
|
||||
long time = bb.getInt() & 0xFFFFFFFFL;
|
||||
double voltage = 3.0 + 0.01 * (bb.get() & 0xFF);
|
||||
double boardTemp = bb.get();
|
||||
double latitude = bb.getInt() / 1e7;
|
||||
double longitude = bb.getInt() / 1e7;
|
||||
int altitude = bb.getShort();
|
||||
double sog = bb.getShort() / 360.0;
|
||||
int cog = bb.get();
|
||||
int numSats = bb.get();
|
||||
int ttf = bb.get();
|
||||
|
||||
return new SodaqOnePayload(time, voltage, boardTemp, latitude, longitude, altitude, sog, cog, numSats, ttf);
|
||||
}
|
||||
|
|
|
@ -112,15 +112,15 @@ public final class HabitatUploader {
|
|||
LOG.info("Uploading for {} receivers: {}", receivers.size(), sentence.trim());
|
||||
|
||||
// encode sentence as raw bytes
|
||||
final byte[] bytes = sentence.getBytes(StandardCharsets.US_ASCII);
|
||||
byte[] bytes = sentence.getBytes(StandardCharsets.US_ASCII);
|
||||
|
||||
// determine docId
|
||||
final String docId = createDocId(bytes);
|
||||
String docId = createDocId(bytes);
|
||||
|
||||
for (HabReceiver receiver : receivers) {
|
||||
// create Json
|
||||
final PayloadTelemetryDoc doc = new PayloadTelemetryDoc(instant, receiver.getCallsign(), bytes);
|
||||
final String json = doc.format();
|
||||
PayloadTelemetryDoc doc = new PayloadTelemetryDoc(instant, receiver.getCallsign(), bytes);
|
||||
String json = doc.format();
|
||||
|
||||
// submit it to our processing thread
|
||||
executor.submit(() -> uploadPayloadTelemetry(docId, json));
|
||||
|
@ -136,7 +136,7 @@ public final class HabitatUploader {
|
|||
private void uploadPayloadTelemetry(String docId, String json) {
|
||||
LOG.info("Upload payload telemetry doc {}: {}", docId, json);
|
||||
try {
|
||||
final String response = restClient.updateListener(docId, json).execute().body();
|
||||
String response = restClient.updateListener(docId, json).execute().body();
|
||||
LOG.info("Result payload telemetry doc {}: {}", docId, response);
|
||||
} catch (IOException e) {
|
||||
LOG.warn("Caught exception: {}", e.getMessage());
|
||||
|
@ -153,8 +153,8 @@ public final class HabitatUploader {
|
|||
* @return the document id
|
||||
*/
|
||||
private String createDocId(byte[] bytes) {
|
||||
final byte[] base64 = base64Encoder.encode(bytes);
|
||||
final byte[] hash = sha256.digest(base64);
|
||||
byte[] base64 = base64Encoder.encode(bytes);
|
||||
byte[] hash = sha256.digest(base64);
|
||||
return DatatypeConverter.printHexBinary(hash).toLowerCase(Locale.ROOT);
|
||||
}
|
||||
|
||||
|
@ -179,21 +179,21 @@ public final class HabitatUploader {
|
|||
try {
|
||||
// get two uuids
|
||||
LOG.info("Getting UUIDs for listener data upload...");
|
||||
final UuidsList list = restClient.getUuids(2).execute().body();
|
||||
final List<String> uuids = list.getUuids();
|
||||
UuidsList list = restClient.getUuids(2).execute().body();
|
||||
List<String> uuids = list.getUuids();
|
||||
if ((uuids != null) && (uuids.size() >= 2)) {
|
||||
LOG.info("Got {} UUIDs", uuids.size());
|
||||
|
||||
// upload payload listener info
|
||||
LOG.info("Upload listener info using UUID {}...", uuids.get(0));
|
||||
final ListenerInformationDoc info = new ListenerInformationDoc(instant, receiver);
|
||||
final UploadResult infoResult = restClient.uploadDocument(uuids.get(0), info.format()).execute().body();
|
||||
ListenerInformationDoc info = new ListenerInformationDoc(instant, receiver);
|
||||
UploadResult infoResult = restClient.uploadDocument(uuids.get(0), info.format()).execute().body();
|
||||
LOG.info("Result listener info: {}", infoResult);
|
||||
|
||||
// upload payload telemetry
|
||||
LOG.info("Upload listener telemetry using UUID {}...", uuids.get(1));
|
||||
final ListenerTelemetryDoc telem = new ListenerTelemetryDoc(instant, receiver);
|
||||
final UploadResult telemResult =
|
||||
ListenerTelemetryDoc telem = new ListenerTelemetryDoc(instant, receiver);
|
||||
UploadResult telemResult =
|
||||
restClient.uploadDocument(uuids.get(1), telem.format()).execute().body();
|
||||
LOG.info("Result listener telemetry: {}", telemResult);
|
||||
} else {
|
||||
|
|
|
@ -34,7 +34,7 @@ public abstract class ListenerDoc {
|
|||
* @return the JSON representation
|
||||
*/
|
||||
public String format() {
|
||||
final ObjectNode topNode = factory.objectNode();
|
||||
ObjectNode topNode = factory.objectNode();
|
||||
topNode.set("type", factory.textNode(type));
|
||||
topNode.set("time_created", factory.textNode(dateFormat.format(date)));
|
||||
topNode.set("time_uploaded", factory.textNode(dateFormat.format(date)));
|
||||
|
|
|
@ -33,10 +33,10 @@ public final class ListenerInformationDoc extends ListenerDoc {
|
|||
|
||||
@Override
|
||||
protected JsonNode createDataNode() {
|
||||
final ObjectNode node = factory().objectNode();
|
||||
ObjectNode node = factory().objectNode();
|
||||
node.set("callsign", factory().textNode(receiver.getCallsign()));
|
||||
node.set("radio", factory().textNode("TheThingsNetwork"));
|
||||
final String antenna = String.format(Locale.US, "%.0f m", receiver.getLocation().getAlt());
|
||||
String antenna = String.format(Locale.US, "%.0f m", receiver.getLocation().getAlt());
|
||||
node.set("antenna", factory().textNode(antenna));
|
||||
return node;
|
||||
}
|
||||
|
|
|
@ -29,7 +29,7 @@ public final class ListenerTelemetryDoc extends ListenerDoc {
|
|||
|
||||
@Override
|
||||
protected JsonNode createDataNode() {
|
||||
final ObjectNode node = factory().objectNode();
|
||||
ObjectNode node = factory().objectNode();
|
||||
node.set("callsign", factory().textNode(receiver.getCallsign()));
|
||||
node.set("latitude", factory().numberNode(receiver.getLocation().getLat()));
|
||||
node.set("longitude", factory().numberNode(receiver.getLocation().getLon()));
|
||||
|
|
|
@ -40,18 +40,18 @@ public final class PayloadTelemetryDoc {
|
|||
* @return the payload telemetry doc as JSON string
|
||||
*/
|
||||
public String format() {
|
||||
final JsonNodeFactory factory = new JsonNodeFactory(false);
|
||||
final ObjectNode topNode = factory.objectNode();
|
||||
JsonNodeFactory factory = new JsonNodeFactory(false);
|
||||
ObjectNode topNode = factory.objectNode();
|
||||
|
||||
// create data node
|
||||
final ObjectNode dataNode = factory.objectNode();
|
||||
ObjectNode dataNode = factory.objectNode();
|
||||
dataNode.set("_raw", factory.binaryNode(rawBytes));
|
||||
|
||||
// create receivers node
|
||||
final ObjectNode receiverNode = factory.objectNode();
|
||||
ObjectNode receiverNode = factory.objectNode();
|
||||
receiverNode.set("time_created", factory.textNode(dateFormat.format(dateCreated)));
|
||||
receiverNode.set("time_uploaded", factory.textNode(dateFormat.format(dateUploaded)));
|
||||
final ObjectNode receiversNode = factory.objectNode();
|
||||
ObjectNode receiversNode = factory.objectNode();
|
||||
receiversNode.set(callSign, receiverNode);
|
||||
|
||||
// put it together in the top node
|
||||
|
|
|
@ -57,7 +57,7 @@ public final class TtnListener {
|
|||
// connect
|
||||
LOG.info("Connecting as user '{}' to MQTT server {}", appId, url);
|
||||
this.mqttClient = new MqttClient(url, clientId, new MemoryPersistence());
|
||||
final MqttConnectOptions options = new MqttConnectOptions();
|
||||
MqttConnectOptions options = new MqttConnectOptions();
|
||||
options.setUserName(appId);
|
||||
options.setPassword(appKey.toCharArray());
|
||||
options.setAutomaticReconnect(false);
|
||||
|
@ -78,7 +78,7 @@ public final class TtnListener {
|
|||
* @throws Exception who knows?
|
||||
*/
|
||||
private void messageArrived(String topic, MqttMessage mqttMessage) throws Exception {
|
||||
final String message = new String(mqttMessage.getPayload(), StandardCharsets.US_ASCII);
|
||||
String message = new String(mqttMessage.getPayload(), StandardCharsets.US_ASCII);
|
||||
LOG.info("Message arrived on topic '{}': {}", topic, message);
|
||||
// forward it to our user
|
||||
callback.messageReceived(topic, message);
|
||||
|
|
|
@ -20,9 +20,9 @@ public final class TtnHabBridgeConfigTest {
|
|||
*/
|
||||
@Test
|
||||
public void testLoadSave() throws IOException {
|
||||
final byte[] data;
|
||||
byte[] data;
|
||||
// save
|
||||
final TtnHabBridgeConfig config = new TtnHabBridgeConfig();
|
||||
TtnHabBridgeConfig config = new TtnHabBridgeConfig();
|
||||
try (ByteArrayOutputStream os = new ByteArrayOutputStream()) {
|
||||
config.save(os);
|
||||
data = os.toByteArray();
|
||||
|
@ -38,7 +38,7 @@ public final class TtnHabBridgeConfigTest {
|
|||
*/
|
||||
@Test
|
||||
public void testAllProps() {
|
||||
final TtnHabBridgeConfig config = new TtnHabBridgeConfig();
|
||||
TtnHabBridgeConfig config = new TtnHabBridgeConfig();
|
||||
Assert.assertNotNull(config.getHabitatUrl());
|
||||
Assert.assertNotNull(config.getHabitatTimeout());
|
||||
Assert.assertNotNull(config.getTtnMqttUrl());
|
||||
|
|
|
@ -21,10 +21,10 @@ public final class CrcCcitt16Test {
|
|||
*/
|
||||
@Test
|
||||
public void testCrc() throws UnsupportedEncodingException {
|
||||
final String s = "hadie,181,10:42:10,54.422829,-6.741293,27799.3,1:10";
|
||||
final byte[] data = s.getBytes(StandardCharsets.US_ASCII);
|
||||
String s = "hadie,181,10:42:10,54.422829,-6.741293,27799.3,1:10";
|
||||
byte[] data = s.getBytes(StandardCharsets.US_ASCII);
|
||||
|
||||
final CrcCcitt16 crc = new CrcCcitt16();
|
||||
CrcCcitt16 crc = new CrcCcitt16();
|
||||
int value = crc.calculate(data, 0xFFFF);
|
||||
|
||||
Assert.assertEquals(0x002A, value);
|
||||
|
|
|
@ -15,21 +15,21 @@ public final class ExpiringCacheTest {
|
|||
*/
|
||||
@Test
|
||||
public void testExpiry() {
|
||||
final ExpiringCache cache = new ExpiringCache(1);
|
||||
ExpiringCache cache = new ExpiringCache(1);
|
||||
|
||||
// add two items
|
||||
final Instant date1 = Instant.now();
|
||||
final Instant date2 = date1.plusMillis(500);
|
||||
Instant date1 = Instant.now();
|
||||
Instant date2 = date1.plusMillis(500);
|
||||
Assert.assertTrue(cache.add("1", date1));
|
||||
Assert.assertTrue(cache.add("2", date2));
|
||||
|
||||
// verify they are cached
|
||||
final Instant date = date1.plusMillis(750);
|
||||
Instant date = date1.plusMillis(750);
|
||||
Assert.assertFalse(cache.add("1", date));
|
||||
Assert.assertFalse(cache.add("2", date));
|
||||
|
||||
// add another item, causing item 1 to expire, but not yet item 2
|
||||
final Instant date3 = date1.plusMillis(1250);
|
||||
Instant date3 = date1.plusMillis(1250);
|
||||
Assert.assertTrue(cache.add("3", date3));
|
||||
Assert.assertTrue(cache.add("1", date3));
|
||||
|
||||
|
|
|
@ -24,7 +24,7 @@ public final class PayloadDecoderTest {
|
|||
*/
|
||||
@Test
|
||||
public void testDecodeJson() throws IOException, DecodeException {
|
||||
final String data = "{\"app_id\":\"spaceballoon\",\"dev_id\":\"devtrack\","
|
||||
String data = "{\"app_id\":\"spaceballoon\",\"dev_id\":\"devtrack\","
|
||||
+ "\"hardware_serial\":\"00490B7EB25521E6\",\"port\":1,\"counter\":1707,"
|
||||
+ "\"payload_raw\":\"AAsm1AxMAUEAY/wCNh68EwKaihEClAEAAwAF\",\"payload_fields\":{\"baralt\":321,"
|
||||
+ "\"gpsalt\":660,\"hacc\":3,\"hpa\":994,\"lat\":51.5642112,\"lon\":4.3682304,\"mode\":0,\"rssi\":-99,"
|
||||
|
@ -38,11 +38,11 @@ public final class PayloadDecoderTest {
|
|||
+ "\"latitude\":51.57847,\"longitude\":4.4564,\"altitude\":4},{\"gtw_id\":\"eui-aa555a00080e0096\","
|
||||
+ "\"timestamp\":422749595,\"time\":\"2017-03-24T19:02:45.89182Z\",\"channel\":3,\"rssi\":-118,"
|
||||
+ "\"snr\":-0.8}]}}";
|
||||
final TtnMessage message = mapper.readValue(data, TtnMessage.class);
|
||||
TtnMessage message = mapper.readValue(data, TtnMessage.class);
|
||||
Assert.assertEquals(3, message.getMetaData().getMqttGateways().size());
|
||||
|
||||
final PayloadDecoder decoder = new PayloadDecoder(EPayloadEncoding.JSON.getName());
|
||||
final Sentence sentence = decoder.decode(message);
|
||||
PayloadDecoder decoder = new PayloadDecoder(EPayloadEncoding.JSON.getName());
|
||||
Sentence sentence = decoder.decode(message);
|
||||
|
||||
Assert.assertEquals("$$devtrack,1707,19:02:46,51.564211,4.368230,660.0,1.1,3.148*B35B",
|
||||
sentence.format().trim());
|
||||
|
@ -56,7 +56,7 @@ public final class PayloadDecoderTest {
|
|||
*/
|
||||
@Test
|
||||
public void testDecodeSodaqOne() throws IOException, DecodeException {
|
||||
final String data = "{\"app_id\":\"ttnmapper\",\"dev_id\":\"mapper2\","
|
||||
String data = "{\"app_id\":\"ttnmapper\",\"dev_id\":\"mapper2\","
|
||||
+ "\"hardware_serial\":\"0004A30B001ADBC5\",\"port\":1,\"counter\":4,"
|
||||
+ "\"payload_raw\":\"loeaWW4T2+8BHzYZzAIeAA8A/QUS\","
|
||||
+ "\"metadata\":{\"time\":\"2017-08-21T07:11:18.313946438Z\",\"frequency\":868.3,"
|
||||
|
@ -65,14 +65,14 @@ public final class PayloadDecoderTest {
|
|||
+ "\"time\":\"2017-08-21T07:11:18.338662Z\",\"channel\":1,\"rssi\":-114,\"snr\":-0.2,"
|
||||
+ "\"rf_chain\":1,\"latitude\":52.0182,\"longitude\":4.70844,\"altitude\":27}]}}";
|
||||
|
||||
final TtnMessage message = mapper.readValue(data, TtnMessage.class);
|
||||
TtnMessage message = mapper.readValue(data, TtnMessage.class);
|
||||
|
||||
// check gateway field
|
||||
Assert.assertEquals(27, message.getMetaData().getMqttGateways().get(0).getAltitude(), 0.1);
|
||||
|
||||
// decode payload
|
||||
final PayloadDecoder decoder = new PayloadDecoder(EPayloadEncoding.SODAQ_ONE.getName());
|
||||
final Sentence sentence = decoder.decode(message);
|
||||
PayloadDecoder decoder = new PayloadDecoder(EPayloadEncoding.SODAQ_ONE.getName());
|
||||
Sentence sentence = decoder.decode(message);
|
||||
|
||||
Assert.assertEquals("$$mapper2,4,07:11:18,52.022064,4.693023,30.0,19,4.10*81FD", sentence.format().trim());
|
||||
}
|
||||
|
@ -85,18 +85,18 @@ public final class PayloadDecoderTest {
|
|||
*/
|
||||
@Test
|
||||
public void testDecodeCayenne() throws IOException, DecodeException {
|
||||
final String data = "{\"app_id\":\"habhub\",\"dev_id\":\"ttntest1\",\"hardware_serial\":\"0004A30B001ADBC5\","
|
||||
String data = "{\"app_id\":\"habhub\",\"dev_id\":\"ttntest1\",\"hardware_serial\":\"0004A30B001ADBC5\","
|
||||
+ "\"port\":1,\"counter\":9,\"payload_raw\":\"AYgH8BwAt08AETACAgGlA2cBIg==\","
|
||||
+ "\"metadata\":{\"time\":\"2017-09-08T16:53:10.446526987Z\",\"frequency\":868.1,"
|
||||
+ "\"modulation\":\"LORA\",\"data_rate\":\"SF7BW125\",\"coding_rate\":\"4/5\","
|
||||
+ "\"gateways\":[{\"gtw_id\":\"eui-008000000000b8b6\",\"timestamp\":2382048707,"
|
||||
+ "\"time\":\"2017-09-08T16:53:10.342388Z\",\"channel\":0,\"rssi\":-119,\"snr\":-2,\"rf_chain\":1,"
|
||||
+ "\"latitude\":52.0182,\"longitude\":4.70844,\"altitude\":27}]}}";
|
||||
final TtnMessage message = mapper.readValue(data, TtnMessage.class);
|
||||
TtnMessage message = mapper.readValue(data, TtnMessage.class);
|
||||
|
||||
// decode payload
|
||||
final PayloadDecoder decoder = new PayloadDecoder(EPayloadEncoding.CAYENNE.getName());
|
||||
final Sentence sentence = decoder.decode(message);
|
||||
PayloadDecoder decoder = new PayloadDecoder(EPayloadEncoding.CAYENNE.getName());
|
||||
Sentence sentence = decoder.decode(message);
|
||||
|
||||
Assert.assertEquals("$$ttntest1,9,16:53:10,52.022000,4.692700,44.0,29.0,4.21*A3A9", sentence.format().trim());
|
||||
}
|
||||
|
@ -106,7 +106,7 @@ public final class PayloadDecoderTest {
|
|||
*/
|
||||
@Test(expected = NullPointerException.class)
|
||||
public void testInvalidEncoding() {
|
||||
final PayloadDecoder decoder = new PayloadDecoder("unknown");
|
||||
PayloadDecoder decoder = new PayloadDecoder("unknown");
|
||||
Assert.assertNotNull(decoder);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,9 +15,9 @@ public final class SentenceTest {
|
|||
*/
|
||||
@Test
|
||||
public void testSentence() {
|
||||
final Instant instant = Instant.ofEpochSecond(0);
|
||||
final Sentence sentence = new Sentence("CALL", 1, instant, 3.45, 6.78, 9.0);
|
||||
final String s = sentence.format();
|
||||
Instant instant = Instant.ofEpochSecond(0);
|
||||
Sentence sentence = new Sentence("CALL", 1, instant, 3.45, 6.78, 9.0);
|
||||
String s = sentence.format();
|
||||
|
||||
Assert.assertEquals("$$CALL,1,00:00:00,3.450000,6.780000,9.0*25E9\n", s);
|
||||
}
|
||||
|
@ -27,9 +27,9 @@ public final class SentenceTest {
|
|||
*/
|
||||
@Test
|
||||
public void testSentenceExtras() {
|
||||
final Sentence sentence = new Sentence("CALL", 1, Instant.now(), 3.45, 6.78, 9.0);
|
||||
Sentence sentence = new Sentence("CALL", 1, Instant.now(), 3.45, 6.78, 9.0);
|
||||
sentence.addField("hello");
|
||||
final String s = sentence.format();
|
||||
String s = sentence.format();
|
||||
|
||||
Assert.assertTrue(s.contains("hello"));
|
||||
}
|
||||
|
|
|
@ -15,9 +15,9 @@ public final class SodaqOnePayloadTest {
|
|||
*/
|
||||
@Test
|
||||
public void testParse() {
|
||||
final String encoded = "wd6dWXEOiQMCH9ELzAIXAAAAAAUB";
|
||||
final byte[] data = Base64.getDecoder().decode(encoded);
|
||||
final SodaqOnePayload payload = SodaqOnePayload.parse(data);
|
||||
String encoded = "wd6dWXEOiQMCH9ELzAIXAAAAAAUB";
|
||||
byte[] data = Base64.getDecoder().decode(encoded);
|
||||
SodaqOnePayload payload = SodaqOnePayload.parse(data);
|
||||
|
||||
Assert.assertEquals(1503518401, payload.getTimeStamp());
|
||||
Assert.assertNotNull(payload.toString());
|
||||
|
|
|
@ -25,20 +25,20 @@ public final class HabitatUploaderTest {
|
|||
@Test
|
||||
public void testUploadPayload() throws IOException {
|
||||
// create a mocked rest client
|
||||
final IHabitatRestApi restClient = Mockito.mock(IHabitatRestApi.class);
|
||||
IHabitatRestApi restClient = Mockito.mock(IHabitatRestApi.class);
|
||||
Mockito.when(restClient.updateListener(Mockito.anyString(), Mockito.anyString()))
|
||||
.thenReturn(Calls.response("OK"));
|
||||
Mockito.when(restClient.getUuids(Mockito.anyInt()))
|
||||
.thenReturn(Calls.response(new UuidsList(Arrays.asList("uuid1", "uuid2"))));
|
||||
|
||||
final HabitatUploader uploader = new HabitatUploader(restClient);
|
||||
HabitatUploader uploader = new HabitatUploader(restClient);
|
||||
|
||||
// verify upload using the uploader
|
||||
uploader.start();
|
||||
try {
|
||||
final HabReceiver receiver = new HabReceiver("BERTRIK", LOCATION);
|
||||
final Instant instant = Instant.now();
|
||||
final Sentence sentence = new Sentence("NOTAFLIGHT", 1, instant, 52.0182307, 4.695772, 1000);
|
||||
HabReceiver receiver = new HabReceiver("BERTRIK", LOCATION);
|
||||
Instant instant = Instant.now();
|
||||
Sentence sentence = new Sentence("NOTAFLIGHT", 1, instant, 52.0182307, 4.695772, 1000);
|
||||
|
||||
uploader.schedulePayloadTelemetryUpload(sentence.format(), Arrays.asList(receiver), instant);
|
||||
Mockito.verify(restClient, Mockito.timeout(3000).times(1)).updateListener(Mockito.anyString(),
|
||||
|
@ -54,19 +54,19 @@ public final class HabitatUploaderTest {
|
|||
@Test
|
||||
public void testUploadListener() {
|
||||
// create a mocked rest client
|
||||
final IHabitatRestApi restClient = Mockito.mock(IHabitatRestApi.class);
|
||||
IHabitatRestApi restClient = Mockito.mock(IHabitatRestApi.class);
|
||||
Mockito.when(restClient.getUuids(Mockito.anyInt()))
|
||||
.thenReturn(Calls.response(new UuidsList(Arrays.asList("uuid1", "uuid2"))));
|
||||
Mockito.when(restClient.uploadDocument(Mockito.anyString(), Mockito.anyString()))
|
||||
.thenReturn(Calls.response(new UploadResult(true, "id", "rev")));
|
||||
|
||||
final HabitatUploader uploader = new HabitatUploader(restClient);
|
||||
HabitatUploader uploader = new HabitatUploader(restClient);
|
||||
|
||||
// verify upload using the uploader
|
||||
uploader.start();
|
||||
try {
|
||||
final HabReceiver receiver = new HabReceiver("BERTRIK", LOCATION);
|
||||
final Instant instant = Instant.now();
|
||||
HabReceiver receiver = new HabReceiver("BERTRIK", LOCATION);
|
||||
Instant instant = Instant.now();
|
||||
|
||||
uploader.scheduleListenerDataUpload(receiver, instant);
|
||||
|
||||
|
@ -86,13 +86,13 @@ public final class HabitatUploaderTest {
|
|||
@Test
|
||||
@Ignore("this is not a junit test")
|
||||
public void testActualPayloadUpload() throws InterruptedException {
|
||||
final IHabitatRestApi restClient = HabitatUploader.newRestClient("http://habitat.habhub.org", 3000);
|
||||
final HabitatUploader uploader = new HabitatUploader(restClient);
|
||||
IHabitatRestApi restClient = HabitatUploader.newRestClient("http://habitat.habhub.org", 3000);
|
||||
HabitatUploader uploader = new HabitatUploader(restClient);
|
||||
uploader.start();
|
||||
try {
|
||||
final Instant instant = Instant.now();
|
||||
final Sentence sentence = new Sentence("NOTAFLIGHT", 1, instant, 52.0182307, 4.695772, 1000);
|
||||
final HabReceiver receiver = new HabReceiver("BERTRIK", null);
|
||||
Instant instant = Instant.now();
|
||||
Sentence sentence = new Sentence("NOTAFLIGHT", 1, instant, 52.0182307, 4.695772, 1000);
|
||||
HabReceiver receiver = new HabReceiver("BERTRIK", null);
|
||||
uploader.schedulePayloadTelemetryUpload(sentence.format(), Arrays.asList(receiver), instant);
|
||||
Thread.sleep(3000);
|
||||
} finally {
|
||||
|
@ -108,11 +108,11 @@ public final class HabitatUploaderTest {
|
|||
@Test
|
||||
@Ignore("this is not a junit test")
|
||||
public void testActualListenerUpload() throws InterruptedException {
|
||||
final IHabitatRestApi restClient = HabitatUploader.newRestClient("http://habitat.habhub.org", 3000);
|
||||
final HabitatUploader uploader = new HabitatUploader(restClient);
|
||||
IHabitatRestApi restClient = HabitatUploader.newRestClient("http://habitat.habhub.org", 3000);
|
||||
HabitatUploader uploader = new HabitatUploader(restClient);
|
||||
try {
|
||||
final Instant instant = Instant.now();
|
||||
final HabReceiver receiver = new HabReceiver("BERTRIK", new Location(52.0182307, 4.695772, 15.0));
|
||||
Instant instant = Instant.now();
|
||||
HabReceiver receiver = new HabReceiver("BERTRIK", new Location(52.0182307, 4.695772, 15.0));
|
||||
uploader.scheduleListenerDataUpload(receiver, instant);
|
||||
Thread.sleep(3000);
|
||||
} finally {
|
||||
|
|
|
@ -18,10 +18,10 @@ public final class ListenerInfoDocTest {
|
|||
*/
|
||||
@Test
|
||||
public void testFormat() {
|
||||
final Instant instant = Instant.now();
|
||||
final HabReceiver receiver = new HabReceiver("BERTRIK", new Location(52.0162, 4.4753, 0.0));
|
||||
final ListenerInformationDoc doc = new ListenerInformationDoc(instant, receiver);
|
||||
final String json = doc.format();
|
||||
Instant instant = Instant.now();
|
||||
HabReceiver receiver = new HabReceiver("BERTRIK", new Location(52.0162, 4.4753, 0.0));
|
||||
ListenerInformationDoc doc = new ListenerInformationDoc(instant, receiver);
|
||||
String json = doc.format();
|
||||
|
||||
Assert.assertNotNull(json);
|
||||
}
|
||||
|
|
|
@ -18,10 +18,10 @@ public final class ListenerTelemetryDocTest {
|
|||
*/
|
||||
@Test
|
||||
public void testFormat() {
|
||||
final Instant instant = Instant.now();
|
||||
final HabReceiver receiver = new HabReceiver("BERTRIK", new Location(1.23, 4.56, 7.8));
|
||||
final ListenerTelemetryDoc doc = new ListenerTelemetryDoc(instant, receiver);
|
||||
final String json = doc.format();
|
||||
Instant instant = Instant.now();
|
||||
HabReceiver receiver = new HabReceiver("BERTRIK", new Location(1.23, 4.56, 7.8));
|
||||
ListenerTelemetryDoc doc = new ListenerTelemetryDoc(instant, receiver);
|
||||
String json = doc.format();
|
||||
|
||||
Assert.assertNotNull(json);
|
||||
}
|
||||
|
|
|
@ -15,9 +15,9 @@ public final class PayloadTelemetryDocTest {
|
|||
*/
|
||||
@Test
|
||||
public void testFormat() {
|
||||
final Instant instant = Instant.now();
|
||||
final PayloadTelemetryDoc doc = new PayloadTelemetryDoc(instant, "BERTRIK", new byte[] {1, 2, 3});
|
||||
final String json = doc.format();
|
||||
Instant instant = Instant.now();
|
||||
PayloadTelemetryDoc doc = new PayloadTelemetryDoc(instant, "BERTRIK", new byte[] {1, 2, 3});
|
||||
String json = doc.format();
|
||||
|
||||
Assert.assertNotNull(json);
|
||||
}
|
||||
|
|
|
@ -20,9 +20,9 @@ public final class TtnMessageGatewayTest {
|
|||
*/
|
||||
@Test
|
||||
public void testJson() throws JsonProcessingException {
|
||||
final TtnMessageGateway gw = new TtnMessageGateway("id", true, "time", 0.0, 1.1, 2.2);
|
||||
final ObjectMapper mapper = new ObjectMapper();
|
||||
final String json = mapper.writeValueAsString(gw);
|
||||
TtnMessageGateway gw = new TtnMessageGateway("id", true, "time", 0.0, 1.1, 2.2);
|
||||
ObjectMapper mapper = new ObjectMapper();
|
||||
String json = mapper.writeValueAsString(gw);
|
||||
|
||||
Assert.assertNotNull(json);
|
||||
Assert.assertFalse(json.contains("location") || json.contains("Location"));
|
||||
|
@ -33,10 +33,10 @@ public final class TtnMessageGatewayTest {
|
|||
*/
|
||||
@Test
|
||||
public void testLocation() {
|
||||
final TtnMessageGateway gw = new TtnMessageGateway("id", true, "time", 0.0, 1.1, 2.2);
|
||||
TtnMessageGateway gw = new TtnMessageGateway("id", true, "time", 0.0, 1.1, 2.2);
|
||||
Assert.assertTrue(gw.getLocation().isValid());
|
||||
|
||||
final Location location = gw.getLocation();
|
||||
Location location = gw.getLocation();
|
||||
Assert.assertNotNull(location);
|
||||
Assert.assertEquals(1.1, location.getLon(), 0.01);
|
||||
}
|
||||
|
@ -46,10 +46,10 @@ public final class TtnMessageGatewayTest {
|
|||
*/
|
||||
@Test
|
||||
public void testNoLocation() {
|
||||
final TtnMessageGateway gw1 = new TtnMessageGateway("id", true, "time", null, null, null);
|
||||
TtnMessageGateway gw1 = new TtnMessageGateway("id", true, "time", null, null, null);
|
||||
Assert.assertFalse(gw1.getLocation().isValid());
|
||||
|
||||
final TtnMessageGateway gw2 = new TtnMessageGateway("id", true, "time", null, 1.1, 2.2);
|
||||
TtnMessageGateway gw2 = new TtnMessageGateway("id", true, "time", null, 1.1, 2.2);
|
||||
Assert.assertFalse(gw2.getLocation().isValid());
|
||||
}
|
||||
|
||||
|
|
|
@ -19,14 +19,14 @@ public final class TtnMessageMetaDataTest {
|
|||
*/
|
||||
@Test
|
||||
public void testTime() {
|
||||
final String time = "2017-08-23T17:18:02.509425571Z";
|
||||
final List<TtnMessageGateway> gws = new ArrayList<>();
|
||||
final TtnMessageMetaData data = new TtnMessageMetaData(time, gws);
|
||||
final Instant instant = data.getTime();
|
||||
String time = "2017-08-23T17:18:02.509425571Z";
|
||||
List<TtnMessageGateway> gws = new ArrayList<>();
|
||||
TtnMessageMetaData data = new TtnMessageMetaData(time, gws);
|
||||
Instant instant = data.getTime();
|
||||
Assert.assertNotNull(instant);
|
||||
|
||||
final Sentence sentence = new Sentence("call", 0, instant, 0.0, 0.0, 0.0);
|
||||
final String line = sentence.format();
|
||||
Sentence sentence = new Sentence("call", 0, instant, 0.0, 0.0, 0.0);
|
||||
String line = sentence.format();
|
||||
Assert.assertTrue(line.contains("17:18:02"));
|
||||
}
|
||||
|
||||
|
|
Ładowanie…
Reference in New Issue