diff --git a/sensors/others/sensorhub-driver-meshtastic/build.gradle b/sensors/others/sensorhub-driver-meshtastic/build.gradle index 6d19135d6..315854d2e 100644 --- a/sensors/others/sensorhub-driver-meshtastic/build.gradle +++ b/sensors/others/sensorhub-driver-meshtastic/build.gradle @@ -5,12 +5,12 @@ plugins { description = 'Meshtastic Driver' ext.details = "Driver that utilizes a meshtastic Radio pre-configured with meshtastic Node Software to communicate with other meshtastic Radio" -version = '1.0.0' +version = '1.0.1' dependencies { implementation 'org.sensorhub:sensorhub-core:' + oshCoreVersion - embeddedImpl "com.google.protobuf:protobuf-java:3.25.1" + embeddedImpl "com.google.protobuf:protobuf-java:4.28.2" testImplementation "junit:junit:4.13.1" testImplementation project(':sensorhub-comm-jssc') } @@ -18,7 +18,7 @@ dependencies { // PROTOBUF PLUGIN CONFIGURATION protobuf { protoc { - artifact = "com.google.protobuf:protoc:3.25.1" + artifact = "com.google.protobuf:protoc:4.28.2" } // CONFIGURE THE PLUGIN TO GENERATE JAVA FILES generateProtoTasks { diff --git a/sensors/others/sensorhub-driver-meshtastic/src/main/java/org/sensorhub/impl/sensor/meshtastic/MeshtasticOutputNodeInfo.java b/sensors/others/sensorhub-driver-meshtastic/src/main/java/org/sensorhub/impl/sensor/meshtastic/MeshtasticOutputNodeInfo.java index 3f041210d..be76c9a5c 100644 --- a/sensors/others/sensorhub-driver-meshtastic/src/main/java/org/sensorhub/impl/sensor/meshtastic/MeshtasticOutputNodeInfo.java +++ b/sensors/others/sensorhub-driver-meshtastic/src/main/java/org/sensorhub/impl/sensor/meshtastic/MeshtasticOutputNodeInfo.java @@ -20,16 +20,15 @@ import org.vast.swe.SWEHelper; import org.vast.swe.helper.GeoPosHelper; -import java.util.ArrayList; import java.util.Base64; /** * Output specification and provider for {@link MeshtasticSensor}. */ public class MeshtasticOutputNodeInfo extends MeshtasticOutputPacketInfo implements MeshtasticOutputInterface{ - static final String OUTPUT_NAME = "NodeInfo"; - static final String OUTPUT_LABEL = "meshtastic Node Information Packet"; - static final String OUTPUT_DESCRIPTION = "Output data for the Node Info"; + private static final String OUTPUT_NAME = "NodeInfo"; + private static final String OUTPUT_LABEL = "meshtastic Node Information Packet"; + private static final String OUTPUT_DESCRIPTION = "Output data for the Node Info"; private final Object processingLock = new Object(); @@ -113,8 +112,6 @@ public void setData(MeshProtos.MeshPacket packetData, ByteString payload) { String nodePrimaryKey = Base64.getEncoder().encodeToString(nodeInfoData.getPublicKey().toByteArray()); String nodeHwModel = nodeInfoData.getHwModel().toString(); String nodeRole = (nodeInfoData.getRole() == ConfigProtos.Config.DeviceConfig.Role.UNRECOGNIZED) ? "Unknown Role" : nodeInfoData.getRole().name(); -// boolean isUnmessageable = node_info.getIsUnmessagable(); -// boolean canBeMessaged = node_info.hasIsUnmessagable(); DataBlock dataBlock = latestRecord == null ? packetRecord.createDataBlock() : latestRecord.renew(); diff --git a/sensors/others/sensorhub-driver-meshtastic/src/main/java/org/sensorhub/impl/sensor/meshtastic/MeshtasticOutputPacketInfo.java b/sensors/others/sensorhub-driver-meshtastic/src/main/java/org/sensorhub/impl/sensor/meshtastic/MeshtasticOutputPacketInfo.java index 89e8080d0..5ae5bb62f 100644 --- a/sensors/others/sensorhub-driver-meshtastic/src/main/java/org/sensorhub/impl/sensor/meshtastic/MeshtasticOutputPacketInfo.java +++ b/sensors/others/sensorhub-driver-meshtastic/src/main/java/org/sensorhub/impl/sensor/meshtastic/MeshtasticOutputPacketInfo.java @@ -28,10 +28,9 @@ public class MeshtasticOutputPacketInfo extends VarRateSensorOutput { private static final double INITIAL_SAMPLING_PERIOD = 1.0; - public DataRecord packetRecord; - public DataEncoding dataEncoding; - - public int packetRecordSize; + protected DataRecord packetRecord; + protected DataEncoding dataEncoding; + protected int packetRecordSize; // Packet Variables String packetId; @@ -174,11 +173,11 @@ public void populatePacketDataStructure(DataBlock dataBlock){ public String convert32IntToString(int data){ - long unsigned_num = Integer.toUnsignedLong(data); - return String.format("!%08x", unsigned_num); + long unsignedNum = Integer.toUnsignedLong(data); + return String.format("!%08x", unsignedNum); } public Instant convert32IntToInstant(int data){ - long unsigned_num = Integer.toUnsignedLong(data); - return Instant.ofEpochSecond(unsigned_num); + long unsignedNum = Integer.toUnsignedLong(data); + return Instant.ofEpochSecond(unsignedNum); } } diff --git a/sensors/others/sensorhub-driver-meshtastic/src/main/java/org/sensorhub/impl/sensor/meshtastic/MeshtasticOutputPosition.java b/sensors/others/sensorhub-driver-meshtastic/src/main/java/org/sensorhub/impl/sensor/meshtastic/MeshtasticOutputPosition.java index 5526fbc09..4c9dbc118 100644 --- a/sensors/others/sensorhub-driver-meshtastic/src/main/java/org/sensorhub/impl/sensor/meshtastic/MeshtasticOutputPosition.java +++ b/sensors/others/sensorhub-driver-meshtastic/src/main/java/org/sensorhub/impl/sensor/meshtastic/MeshtasticOutputPosition.java @@ -23,8 +23,8 @@ */ public class MeshtasticOutputPosition extends MeshtasticOutputPacketInfo implements MeshtasticOutputInterface{ private static final String OUTPUT_NAME = "MeshtasticPosition"; - private static final String OUTPUT_LABEL = "meshtastic Position Packet"; - private static final String OUTPUT_DESCRIPTION = "Output data for a meshtastic Device's position"; + private static final String OUTPUT_LABEL = "meshtastic Position Packet"; + private static final String OUTPUT_DESCRIPTION = "Output data for a meshtastic Device's position"; private final Object processingLock = new Object(); @@ -58,7 +58,6 @@ void doInit() { /** * Sets the data for the output and publishes it. */ -// public void setData(String packet_id, String packet_from, double lat, double lon, double alt) { @Override public void setData(MeshProtos.MeshPacket packetData, ByteString payload) { synchronized (processingLock) { diff --git a/sensors/others/sensorhub-driver-meshtastic/src/main/java/org/sensorhub/impl/sensor/meshtastic/MeshtasticOutputTextMessage.java b/sensors/others/sensorhub-driver-meshtastic/src/main/java/org/sensorhub/impl/sensor/meshtastic/MeshtasticOutputTextMessage.java index d6dc25ff1..583d3a131 100644 --- a/sensors/others/sensorhub-driver-meshtastic/src/main/java/org/sensorhub/impl/sensor/meshtastic/MeshtasticOutputTextMessage.java +++ b/sensors/others/sensorhub-driver-meshtastic/src/main/java/org/sensorhub/impl/sensor/meshtastic/MeshtasticOutputTextMessage.java @@ -22,9 +22,9 @@ * Output specification and provider for {@link MeshtasticSensor}. */ public class MeshtasticOutputTextMessage extends MeshtasticOutputPacketInfo implements MeshtasticOutputInterface{ - static String OUTPUT_NAME = "MeshtasticText"; - static String OUTPUT_LABEL = "meshtastic Text Message"; - static String OUTPUT_DESCRIPTION = "Text provided by a meshtastic Device"; + private static final String OUTPUT_NAME = "MeshtasticText"; + private static final String OUTPUT_LABEL = "meshtastic Text Message"; + private static final String OUTPUT_DESCRIPTION = "Text provided by a meshtastic Device"; private final Object processingLock = new Object(); diff --git a/sensors/others/sensorhub-driver-meshtastic/src/main/java/org/sensorhub/impl/sensor/meshtastic/MeshtasticSensor.java b/sensors/others/sensorhub-driver-meshtastic/src/main/java/org/sensorhub/impl/sensor/meshtastic/MeshtasticSensor.java index 09efe93c9..fc12f219f 100644 --- a/sensors/others/sensorhub-driver-meshtastic/src/main/java/org/sensorhub/impl/sensor/meshtastic/MeshtasticSensor.java +++ b/sensors/others/sensorhub-driver-meshtastic/src/main/java/org/sensorhub/impl/sensor/meshtastic/MeshtasticSensor.java @@ -15,8 +15,6 @@ import org.sensorhub.api.comm.ICommProvider; import org.sensorhub.api.common.SensorHubException; import org.sensorhub.impl.sensor.AbstractSensorModule; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import org.vast.ogc.om.MovingFeature; import java.io.IOException; @@ -36,7 +34,6 @@ public class MeshtasticSensor extends AbstractSensorModule { static final String UID_PREFIX = "urn:osh:sensor:meshtastic:"; static final String XML_PREFIX = "meshtastic"; - private static final Logger logger = LoggerFactory.getLogger(MeshtasticSensor.class); private ICommProvider commProvider; private final ExecutorService executor = Executors.newSingleThreadExecutor(); AtomicBoolean isProcessing = new AtomicBoolean(false); @@ -185,61 +182,7 @@ private void startProcessing() { try (InputStream in = commProvider.getInputStream()){ isProcessing.set(true); while (isProcessing.get()) { - int b; - // find START1 in Input Stream, indicating that a Protobuf messages is being sent - do { - b = in.read(); - if (b == -1) return; -// if (b != START1) { -//// optional: treat as debug ASCII -// System.out.print((char) b); -// } - } while (b != START1); - - // If START1(0x94) is found, expect START2 - b = in.read(); - // invalid header - if (b != START2) { - getLogger().warn("Invalid header"); - continue; - } - - // GET LENGTH OF PROTOBUF MESSAGE - int lenMSB = in.read(); - int lenLSB = in.read(); - if (lenMSB == -1 || lenLSB == -1) break; - - int length = ((lenMSB & 0xFF) << 8) | (lenLSB & 0xFF); - if (length <= 0 || length > 512) { - getLogger().info("Invalid length, resyncing..."); - continue; - } - - // PROTOBUF DATA - byte[] payload = new byte[length]; - int read = 0; - while (read < length) { - int r = in.read(payload, read, length - read); - if (r == -1) break; - read += r; - } - - if (read < length) { - getLogger().info("Truncated packet, resyncing..."); - continue; - } - - // parse protobuf - try { - MeshProtos.FromRadio msg = MeshProtos.FromRadio.parseFrom(payload); - if(msg.hasPacket()){ - MeshProtos.MeshPacket packet = msg.getPacket(); - meshtasticHandler.handlePacket(packet); - } -// getLogger().info("New message: " + msg); - } catch (Exception e) { - getLogger().error("Invalid protobuf: " + e.getMessage()); - } + processNextPacket(in); } } catch (IOException e) { @@ -252,6 +195,86 @@ private void startProcessing() { }); } + + private void processNextPacket(InputStream in) throws IOException { + // CHECK TO SEE IF PACKET SHOULD PROCESS + if (!findStartOfPacket(in)){ + return; + } + + // GET LENGTHH OF PACKET AND CHECK THAT IT MATCHES STYLE + int length = readPacketLength(in); + if (length <= 0 || length > 512) { + getLogger().info("Invalid length, resyncing..."); + return; + } + + // READ PROTOBUF PAYLOAD DATA + byte[] payload = readPayload(in, length); + if(payload.length == 0){ + getLogger().info("Truncated packet, resyncing..."); + return; + } + + // PARSE PROTOBUF PAYLOAD USING MESHTASTIC PROTOS + parseProtobuf(payload); + } + + private boolean findStartOfPacket(InputStream in) throws IOException { + int b; + // find START1 in Input Stream, indicating that a Protobuf messages is being sent + do { + b = in.read(); + if (b == -1) return false; + } while (b != START1); + + // If START1(0x94) is found, expect START2 + b = in.read(); + // invalid header + if (b != START2) { + getLogger().warn("Invalid header"); + return false; + } + + return true; + } + + // GET LENGTH OF PROTOBUF MESSAGE + private int readPacketLength(InputStream in) throws IOException { + int lenMSB = in.read(); + int lenLSB = in.read(); + if (lenMSB == -1 || lenLSB == -1) return -1; + return ((lenMSB & 0xFF) <<8 | (lenLSB & 0xFF)); + } + + // READ A PAYLOAD FROM INPUT STREAM + private byte[] readPayload(InputStream in, int length) throws IOException { + byte[] payload = new byte[length]; + int read = 0; + while(read < length ){ + int r = in.read(payload,read,length-read); + if (r == -1) { + return new byte[0]; + } + read += r; + } + return payload; + } + + // PARSE MESHTASTIC RADIO MESSAGE + private void parseProtobuf(byte[] payload){ + try { + MeshProtos.FromRadio msg = MeshProtos.FromRadio.parseFrom(payload); + if(msg.hasPacket()){ + MeshProtos.MeshPacket packet = msg.getPacket(); + meshtasticHandler.handlePacket(packet); + } + } catch (Exception e) { + getLogger().error("Invalid protobuf: {} ", e.getMessage()); + } + } + + public boolean sendMessage(MeshProtos.ToRadio message) { byte[] bytes = message.toByteArray();