mirror of
https://github.com/zjs81/meshcore-open.git
synced 2026-07-04 07:50:57 +10:00
Added telemetry to repeater interface.
This commit is contained in:
@@ -0,0 +1,103 @@
|
||||
import 'dart:convert';
|
||||
import 'dart:typed_data';
|
||||
|
||||
class BufferReader {
|
||||
int pointer = 0;
|
||||
final Uint8List buffer;
|
||||
|
||||
BufferReader(Uint8List data) : buffer = Uint8List.fromList(data);
|
||||
|
||||
int getRemainingBytesCount() {
|
||||
return buffer.length - pointer;
|
||||
}
|
||||
|
||||
int readByte() {
|
||||
return readBytes(1)[0];
|
||||
}
|
||||
|
||||
Uint8List readBytes(int count) {
|
||||
final data = buffer.sublist(pointer, pointer + count);
|
||||
pointer += count;
|
||||
return data;
|
||||
}
|
||||
|
||||
Uint8List readRemainingBytes() {
|
||||
return readBytes(getRemainingBytesCount());
|
||||
}
|
||||
|
||||
String readString() {
|
||||
return utf8.decode(readRemainingBytes());
|
||||
}
|
||||
|
||||
String readCString(int maxLength) {
|
||||
final value = <int>[];
|
||||
final bytes = readBytes(maxLength);
|
||||
for (final byte in bytes) {
|
||||
// if we find a null terminator character, we have reached the end of the cstring
|
||||
if (byte == 0) {
|
||||
return utf8.decode(Uint8List.fromList(value));
|
||||
}
|
||||
value.add(byte);
|
||||
}
|
||||
return utf8.decode(Uint8List.fromList(value));
|
||||
}
|
||||
|
||||
int readInt8() {
|
||||
final bytes = readBytes(1);
|
||||
return ByteData.view(bytes.buffer).getInt8(0);
|
||||
}
|
||||
|
||||
int readUInt8() {
|
||||
final bytes = readBytes(1);
|
||||
return ByteData.view(bytes.buffer).getUint8(0);
|
||||
}
|
||||
|
||||
int readUInt16LE() {
|
||||
final bytes = readBytes(2);
|
||||
return ByteData.view(bytes.buffer).getUint16(0, Endian.little);
|
||||
}
|
||||
|
||||
int readUInt16BE() {
|
||||
final bytes = readBytes(2);
|
||||
return ByteData.view(bytes.buffer).getUint16(0, Endian.big);
|
||||
}
|
||||
|
||||
int readUInt32LE() {
|
||||
final bytes = readBytes(4);
|
||||
return ByteData.view(bytes.buffer).getUint32(0, Endian.little);
|
||||
}
|
||||
|
||||
int readUInt32BE() {
|
||||
final bytes = readBytes(4);
|
||||
return ByteData.view(bytes.buffer).getUint32(0, Endian.big);
|
||||
}
|
||||
|
||||
int readInt16LE() {
|
||||
final bytes = readBytes(2);
|
||||
return ByteData.view(bytes.buffer).getInt16(0, Endian.little);
|
||||
}
|
||||
|
||||
int readInt16BE() {
|
||||
final bytes = readBytes(2);
|
||||
return ByteData.view(bytes.buffer).getInt16(0, Endian.big);
|
||||
}
|
||||
|
||||
int readInt32LE() {
|
||||
final bytes = readBytes(4);
|
||||
return ByteData.view(bytes.buffer).getInt32(0, Endian.little);
|
||||
}
|
||||
|
||||
int readInt24BE() {
|
||||
// read 24-bit (3 bytes) big endian integer
|
||||
var value = (readByte() << 16) | (readByte() << 8) | readByte();
|
||||
|
||||
// convert 24-bit signed integer to 32-bit signed integer
|
||||
// 0x800000 is the sign bit for a 24-bit value
|
||||
// if it's set, value is negative in 24-bit two's complement
|
||||
if ((value & 0x800000) != 0) {
|
||||
value -= 0x1000000;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
import 'dart:convert';
|
||||
import 'dart:typed_data';
|
||||
|
||||
class BufferWriter {
|
||||
final BytesBuilder _builder = BytesBuilder();
|
||||
|
||||
Uint8List toBytes() {
|
||||
return _builder.toBytes();
|
||||
}
|
||||
|
||||
void writeBytes(Uint8List bytes) {
|
||||
_builder.add(bytes);
|
||||
}
|
||||
|
||||
void writeByte(int byte) {
|
||||
_builder.addByte(byte);
|
||||
}
|
||||
|
||||
void writeUInt16LE(int num) {
|
||||
final bytes = Uint8List(2);
|
||||
final data = ByteData.view(bytes.buffer);
|
||||
data.setUint16(0, num, Endian.little);
|
||||
writeBytes(bytes);
|
||||
}
|
||||
|
||||
void writeUInt32LE(int num) {
|
||||
final bytes = Uint8List(4);
|
||||
final data = ByteData.view(bytes.buffer);
|
||||
data.setUint32(0, num, Endian.little);
|
||||
writeBytes(bytes);
|
||||
}
|
||||
|
||||
void writeInt32LE(int num) {
|
||||
final bytes = Uint8List(4);
|
||||
final data = ByteData.view(bytes.buffer);
|
||||
data.setInt32(0, num, Endian.little);
|
||||
writeBytes(bytes);
|
||||
}
|
||||
|
||||
void writeString(String string) {
|
||||
writeBytes(Uint8List.fromList(utf8.encode(string)));
|
||||
}
|
||||
|
||||
void writeCString(String string, int maxLength) {
|
||||
final bytes = Uint8List(maxLength);
|
||||
final encodedString = utf8.encode(string);
|
||||
|
||||
for (var i = 0; i < maxLength && i < encodedString.length; i++) {
|
||||
bytes[i] = encodedString[i];
|
||||
}
|
||||
|
||||
// ensure the last byte is always a null terminator
|
||||
bytes[maxLength - 1] = 0;
|
||||
|
||||
writeBytes(bytes);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,191 @@
|
||||
import 'dart:typed_data';
|
||||
import 'buffer_reader.dart';
|
||||
import 'buffer_writer.dart';
|
||||
|
||||
class CayenneLpp {
|
||||
static const int lppDigitalInput = 0; // 1 byte
|
||||
static const int lppDigitalOutput = 1; // 1 byte
|
||||
static const int lppAnalogInput = 2; // 2 bytes, 0.01 signed
|
||||
static const int lppAnalogOutput = 3; // 2 bytes, 0.01 signed
|
||||
static const int lppGenericSensor = 100; // 4 bytes, unsigned
|
||||
static const int lppLuminosity = 101; // 2 bytes, 1 lux unsigned
|
||||
static const int lppPresence = 102; // 1 byte, bool
|
||||
static const int lppTemperature = 103; // 2 bytes, 0.1°C signed
|
||||
static const int lppRelativeHumidity = 104; // 1 byte, 0.5% unsigned
|
||||
static const int lppAccelerometer = 113; // 2 bytes per axis, 0.001G
|
||||
static const int lppBarometricPressure = 115; // 2 bytes 0.1hPa unsigned
|
||||
static const int lppVoltage = 116; // 2 bytes 0.01V unsigned
|
||||
static const int lppCurrent = 117; // 2 bytes 0.001A unsigned
|
||||
static const int lppFrequency = 118; // 4 bytes 1Hz unsigned
|
||||
static const int lppPercentage = 120; // 1 byte 1-100% unsigned
|
||||
static const int lppAltitude = 121; // 2 byte 1m signed
|
||||
static const int lppConcentration = 125; // 2 bytes, 1 ppm unsigned
|
||||
static const int lppPower = 128; // 2 byte, 1W, unsigned
|
||||
static const int lppDistance = 130; // 4 byte, 0.001m, unsigned
|
||||
static const int lppEnergy = 131; // 4 byte, 0.001kWh, unsigned
|
||||
static const int lppDirection = 132; // 2 bytes, 1deg, unsigned
|
||||
static const int lppUnixTime = 133; // 4 bytes, unsigned
|
||||
static const int lppGyrometer = 134; // 2 bytes per axis, 0.01 °/s
|
||||
static const int lppColour = 135; // 1 byte per RGB Color
|
||||
static const int lppGps = 136; // 3 byte lon/lat 0.0001 °, 3 bytes alt 0.01 meter
|
||||
static const int lppSwitch = 142; // 1 byte, 0/1
|
||||
static const int lppPolyline = 240; // 1 byte size, 1 byte delta factor, 3 byte lon/lat 0.0001° * factor, n (size-8) bytes deltas
|
||||
|
||||
final BufferWriter _writer = BufferWriter();
|
||||
|
||||
Uint8List toBytes() {
|
||||
return _writer.toBytes();
|
||||
}
|
||||
|
||||
void addDigitalInput(int channel, int value) {
|
||||
_writer.writeByte(channel);
|
||||
_writer.writeByte(lppDigitalInput);
|
||||
_writer.writeByte(value);
|
||||
}
|
||||
|
||||
void addTemperature(int channel, double value) {
|
||||
_writer.writeByte(channel);
|
||||
_writer.writeByte(lppTemperature);
|
||||
final val = (value * 10).toInt();
|
||||
_writer.writeBytes(_int16ToBE(val));
|
||||
}
|
||||
|
||||
void addVoltage(int channel, double value) {
|
||||
_writer.writeByte(channel);
|
||||
_writer.writeByte(lppVoltage);
|
||||
final val = (value * 100).toInt();
|
||||
_writer.writeBytes(_int16ToBE(val));
|
||||
}
|
||||
|
||||
void addGps(int channel, double lat, double lon, double alt) {
|
||||
_writer.writeByte(channel);
|
||||
_writer.writeByte(lppGps);
|
||||
_writer.writeBytes(_int24ToBE((lat * 10000).toInt()));
|
||||
_writer.writeBytes(_int24ToBE((lon * 10000).toInt()));
|
||||
_writer.writeBytes(_int24ToBE((alt * 100).toInt()));
|
||||
}
|
||||
|
||||
Uint8List _int16ToBE(int value) {
|
||||
final bytes = Uint8List(2);
|
||||
final data = ByteData.view(bytes.buffer);
|
||||
data.setInt16(0, value, Endian.big);
|
||||
return bytes;
|
||||
}
|
||||
|
||||
Uint8List _int24ToBE(int value) {
|
||||
final bytes = Uint8List(3);
|
||||
bytes[0] = (value >> 16) & 0xFF;
|
||||
bytes[1] = (value >> 8) & 0xFF;
|
||||
bytes[2] = value & 0xFF;
|
||||
return bytes;
|
||||
}
|
||||
|
||||
static List<Map<String, dynamic>> parse(Uint8List bytes) {
|
||||
final buffer = BufferReader(bytes);
|
||||
final telemetry = <Map<String, dynamic>>[];
|
||||
|
||||
while (buffer.getRemainingBytesCount() >= 2) {
|
||||
final channel = buffer.readUInt8();
|
||||
final type = buffer.readUInt8();
|
||||
|
||||
if (channel == 0 && type == 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
case lppGenericSensor:
|
||||
telemetry.add({
|
||||
'channel': channel,
|
||||
'type': type,
|
||||
'value': buffer.readUInt32BE(),
|
||||
});
|
||||
break;
|
||||
case lppLuminosity:
|
||||
telemetry.add({
|
||||
'channel': channel,
|
||||
'type': type,
|
||||
'value': buffer.readUInt16BE(),
|
||||
});
|
||||
break;
|
||||
case lppPresence:
|
||||
telemetry.add({
|
||||
'channel': channel,
|
||||
'type': type,
|
||||
'value': buffer.readUInt8(),
|
||||
});
|
||||
break;
|
||||
case lppTemperature:
|
||||
telemetry.add({
|
||||
'channel': channel,
|
||||
'type': type,
|
||||
'value': buffer.readInt16BE() / 10,
|
||||
});
|
||||
break;
|
||||
case lppRelativeHumidity:
|
||||
telemetry.add({
|
||||
'channel': channel,
|
||||
'type': type,
|
||||
'value': buffer.readUInt8() / 2,
|
||||
});
|
||||
break;
|
||||
case lppBarometricPressure:
|
||||
telemetry.add({
|
||||
'channel': channel,
|
||||
'type': type,
|
||||
'value': buffer.readUInt16BE() / 10,
|
||||
});
|
||||
break;
|
||||
case lppVoltage:
|
||||
telemetry.add({
|
||||
'channel': channel,
|
||||
'type': type,
|
||||
'value': buffer.readInt16BE() / 100,
|
||||
});
|
||||
break;
|
||||
case lppCurrent:
|
||||
telemetry.add({
|
||||
'channel': channel,
|
||||
'type': type,
|
||||
'value': buffer.readInt16BE() / 1000,
|
||||
});
|
||||
break;
|
||||
case lppPercentage:
|
||||
telemetry.add({
|
||||
'channel': channel,
|
||||
'type': type,
|
||||
'value': buffer.readUInt8(),
|
||||
});
|
||||
break;
|
||||
case lppConcentration:
|
||||
telemetry.add({
|
||||
'channel': channel,
|
||||
'type': type,
|
||||
'value': buffer.readUInt16BE(),
|
||||
});
|
||||
break;
|
||||
case lppPower:
|
||||
telemetry.add({
|
||||
'channel': channel,
|
||||
'type': type,
|
||||
'value': buffer.readUInt16BE(),
|
||||
});
|
||||
break;
|
||||
case lppGps:
|
||||
telemetry.add({
|
||||
'channel': channel,
|
||||
'type': type,
|
||||
'value': {
|
||||
'latitude': buffer.readInt24BE() / 10000,
|
||||
'longitude': buffer.readInt24BE() / 10000,
|
||||
'altitude': buffer.readInt24BE() / 100,
|
||||
},
|
||||
});
|
||||
break;
|
||||
default:
|
||||
return telemetry;
|
||||
}
|
||||
}
|
||||
|
||||
return telemetry;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user