mirror of
https://github.com/zjs81/meshcore-open.git
synced 2026-04-20 22:13:48 +00:00
formats all dart files using `dart format .` from the root project dir this makes the code style repeatable by new contributors and makes PR review easier
263 lines
8.3 KiB
Dart
263 lines
8.3 KiB
Dart
import 'dart:typed_data';
|
|
import '../connector/meshcore_protocol.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.remaining >= 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;
|
|
}
|
|
|
|
static List<Map<String, dynamic>> parseByChannel(Uint8List bytes) {
|
|
final buffer = BufferReader(bytes);
|
|
final Map<int, Map<String, dynamic>> channels = {};
|
|
|
|
while (buffer.remaining >= 2) {
|
|
final channel = buffer.readUInt8();
|
|
final type = buffer.readUInt8();
|
|
|
|
// Optional: stop on padding (00 00)
|
|
if (channel == 0 && type == 0) {
|
|
break;
|
|
}
|
|
|
|
final channelData = channels.putIfAbsent(
|
|
channel,
|
|
() => {'channel': channel, 'values': <String, dynamic>{}},
|
|
);
|
|
|
|
switch (type) {
|
|
case lppGenericSensor:
|
|
channelData['values']['generic'] = buffer.readUInt32BE();
|
|
break;
|
|
case lppLuminosity:
|
|
channelData['values']['luminosity'] = buffer.readUInt16BE();
|
|
break;
|
|
case lppPresence:
|
|
channelData['values']['presence'] = buffer.readUInt8() != 0;
|
|
break;
|
|
case lppTemperature:
|
|
channelData['values']['temperature'] = buffer.readInt16BE() / 10.0;
|
|
break;
|
|
case lppRelativeHumidity:
|
|
channelData['values']['humidity'] = buffer.readUInt8() / 2.0;
|
|
break;
|
|
case lppBarometricPressure:
|
|
channelData['values']['pressure'] = buffer.readUInt16BE() / 10.0;
|
|
break;
|
|
case lppVoltage:
|
|
channelData['values']['voltage'] = buffer.readInt16BE() / 100.0;
|
|
break;
|
|
case lppCurrent:
|
|
channelData['values']['current'] = buffer.readInt16BE() / 1000.0;
|
|
break;
|
|
case lppPercentage:
|
|
channelData['values']['percentage'] = buffer.readUInt8();
|
|
break;
|
|
case lppConcentration:
|
|
channelData['values']['concentration'] = buffer.readUInt16BE();
|
|
break;
|
|
case lppPower:
|
|
channelData['values']['power'] = buffer.readUInt16BE();
|
|
break;
|
|
case lppGps:
|
|
channelData['values']['gps'] = {
|
|
'latitude': buffer.readInt24BE() / 10000.0,
|
|
'longitude': buffer.readInt24BE() / 10000.0,
|
|
'altitude': buffer.readInt24BE() / 100.0,
|
|
};
|
|
break;
|
|
// Add more types as needed...
|
|
default:
|
|
// Unknown type: skip or handle error?
|
|
continue;
|
|
}
|
|
}
|
|
|
|
final List<Map<String, dynamic>> channelsOut = channels.values.toList();
|
|
channelsOut.sort((a, b) => a['channel'].compareTo(b['channel']));
|
|
return channelsOut;
|
|
}
|
|
}
|