Skip to content

Commit

Permalink
Added CustomChecksumSentence and NmeaSentenceType.custom
Browse files Browse the repository at this point in the history
  • Loading branch information
ricardoboss committed Jan 11, 2023
1 parent bd9c259 commit fc3dc6c
Show file tree
Hide file tree
Showing 9 changed files with 93 additions and 30 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
Changelog
=========

Version 3.1.0
-------------

* Added `CustomChecksumSentence` and changed parent of `CustomSentence` to `NmeaSentence`.
* Added `NmeaSentenceType.custom` for custom sentences.

Version 3.0.0
-------------

Expand Down
6 changes: 3 additions & 3 deletions example/example.dart
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ void main() {
MsgSentence.id, (line) => MsgSentence(raw: line))
..registerProprietarySentence(AcmeProprietarySentence.id,
(line) => AcmeProprietarySentence(raw: line))
..registerCustomSentence(MyCustomSentence.id,
..registerCustomChecksumSentence(MyCustomSentence.id,
(line) => MyCustomSentence(raw: line, validateChecksums: false)))
.listen((nmea.NmeaSentence sentence) {
print("${sentence.raw} is a valid ${sentence.type.name} sentence");
Expand All @@ -25,7 +25,7 @@ void main() {
// Output:
// $--MSG,A,1,0,0,0,0*29 is a valid talker sentence
// $PACME{'test':true} is a valid proprietary sentence
// $CST,first,second is a valid unknown sentence
// $CST,first,second is a valid custom sentence
}

class MsgSentence extends nmea.TalkerSentence {
Expand Down Expand Up @@ -55,7 +55,7 @@ class AcmeProprietarySentence extends nmea.ProprietarySentence {
dynamic get data => jsonDecode(json);
}

class MyCustomSentence extends nmea.CustomSentence {
class MyCustomSentence extends nmea.CustomChecksumSentence {
static const String id = "CST";

MyCustomSentence({required super.raw, super.validateChecksums = true})
Expand Down
1 change: 1 addition & 0 deletions lib/nmea.dart
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ export 'src/nmea_sentence.dart'
show NmeaSentence, nmeaPrefix, nmeaSuffix, nmeaFieldSeparator;
export 'src/proprietary_sentence.dart'
show ProprietarySentence, nmeaProprietaryDenominator, nmeaProprietaryPrefix;
export 'src/custom_checksum_sentence.dart' show CustomChecksumSentence;
export 'src/custom_sentence.dart' show CustomSentence;
export 'src/talker_sentence.dart' show TalkerSentence;
export 'src/multipart_sentence.dart' show MultipartSentence;
Expand Down
26 changes: 26 additions & 0 deletions lib/src/custom_checksum_sentence.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import 'package:nmea/src/checksum_sentence.dart';
import 'package:nmea/src/nmea_sentence_type.dart';

/// A [ChecksumSentence] where the data format is completely customizable, as
/// long as it fits in the general envelope of an NMEA0183 sentence (begins with
/// '$' and ends with windows-style newline characters) and has a checksum.
class CustomChecksumSentence extends ChecksumSentence {
/// Returns the identifier used to identify this sentence type
final String identifier;

/// Decides whether or not to validate the checksum on this sentence
final bool validateChecksums;

/// The [CustomChecksumSentence] constructor forwards all arguments to the
/// [ChecksumSentence] constructor, except the [type] parameter.
/// The [type] is always [NmeaSentenceType.custom].
CustomChecksumSentence(
{required this.identifier,
required super.raw,
super.prefix,
this.validateChecksums = true})
: super(type: NmeaSentenceType.custom);

@override
bool get hasValidChecksum => super.hasValidChecksum || !validateChecksums;
}
26 changes: 10 additions & 16 deletions lib/src/custom_sentence.dart
Original file line number Diff line number Diff line change
@@ -1,21 +1,15 @@
import 'package:nmea/src/checksum_sentence.dart';
import 'package:nmea/src/nmea_sentence_type.dart';
import 'package:nmea/nmea.dart';

/// The data format is completely customizable, as long as it fits in the general
/// envelope of an NMEA0183 sentence (begins with '$' and ends with windows-
/// style newline characters).
class CustomSentence extends ChecksumSentence {
/// An [NmeaSentence] where the data format is completely customizable, as
/// long as it fits in the general envelope of an NMEA0183 sentence (begins with
/// '$' and ends with windows-style newline characters).
class CustomSentence extends NmeaSentence {
/// Returns the identifier used to identify this sentence type
final String identifier;
final bool validateChecksums;

CustomSentence(
{required this.identifier,
required super.raw,
super.prefix,
this.validateChecksums = true})
: super(type: NmeaSentenceType.unknown);

@override
bool get hasValidChecksum => super.hasValidChecksum || !validateChecksums;
/// The [CustomChecksumSentence] constructor forwards all arguments to the
/// [NmeaSentence] constructor, except the [type] parameter.
/// The [type] is always [NmeaSentenceType.custom].
CustomSentence({required this.identifier, required super.raw, super.prefix})
: super(type: NmeaSentenceType.custom);
}
34 changes: 33 additions & 1 deletion lib/src/nmea_decoder.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import 'dart:async';
import 'dart:convert';

import 'package:nmea/src/custom_checksum_sentence.dart';
import 'package:nmea/src/custom_sentence.dart';
import 'package:nmea/src/limited_size_queue.dart';
import 'package:nmea/src/multipart_sentence.dart';
Expand All @@ -13,6 +14,11 @@ import 'package:nmea/src/talker_sentence.dart';
/// identifier.
typedef CustomSentenceFactory = CustomSentence Function(String line);

/// A function to create a [CustomChecksumSentence] from a raw string and an
/// identifier.
typedef CustomChecksumSentenceFactory = CustomChecksumSentence Function(
String line);

/// A function to create a [ProprietarySentence] from a raw string and a
/// manufacturer id.
typedef ProprietarySentenceFactory = ProprietarySentence Function(String line);
Expand Down Expand Up @@ -46,6 +52,8 @@ typedef OnIncompleteMultipartSentence = MultipartSentence? Function(
/// data it receives as a complete NMEA sentence.
class NmeaDecoder extends StreamTransformerBase<String, NmeaSentence> {
final Map<String, CustomSentenceFactory> _customGenerators = {};
final Map<String, CustomChecksumSentenceFactory> _customChecksumGenerators =
{};
final Map<String, OptionalProprietarySentenceFactory> _proprietaryGenerators =
{};
final Map<String, TalkerSentenceFactory> _talkerGenerators = {};
Expand Down Expand Up @@ -95,6 +103,14 @@ class NmeaDecoder extends StreamTransformerBase<String, NmeaSentence> {
_customGenerators[identifier] = factory;
}

/// Registers a [CustomChecksumSentenceFactory] for a given identifier.
void registerCustomChecksumSentence(
String identifier,
CustomChecksumSentenceFactory factory,
) {
_customChecksumGenerators[identifier] = factory;
}

/// Registers a [ProprietarySentenceFactory] for a given manufacturer id.
void registerProprietarySentence(
String manufacturer,
Expand Down Expand Up @@ -174,7 +190,9 @@ class NmeaDecoder extends StreamTransformerBase<String, NmeaSentence> {
return decodeQuery(line);
}

return decodeTalker(line) ?? decodeCustom(line);
return decodeTalker(line) ??
decodeCustomChecksum(line) ??
decodeCustom(line);
}

/// Tries to decode the given line as a custom sentence.
Expand All @@ -191,6 +209,20 @@ class NmeaDecoder extends StreamTransformerBase<String, NmeaSentence> {
return null;
}

/// Tries to decode the given line as a custom sentence with a checksum.
/// The identifier is extracted from the line and the corresponding
/// [CustomChecksumSentenceFactory] is used to create the sentence.
/// If none is found `null` is returned.
CustomChecksumSentence? decodeCustomChecksum(String line) {
for (final identifier in _customChecksumGenerators.keys) {
if (line.startsWith(nmeaPrefix + identifier)) {
return _customChecksumGenerators[identifier]!(line);
}
}

return null;
}

/// Tries to decode the given line as a proprietary sentence.
/// The manufacturer id is extracted from the line and the corresponding
/// [ProprietarySentenceFactory] is used to create the sentence.
Expand Down
4 changes: 4 additions & 0 deletions lib/src/nmea_sentence_type.dart
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,8 @@ enum NmeaSentenceType {
/// This sentence is a proprietary sentence, whose format or function is not
/// further specified (see [ProprietarySentence]).
proprietary,

/// This sentence is a completely custom sentence which might contain
/// unexpected data (see [CustomSentence] and [CustomChecksumSentence]).
custom,
}
2 changes: 1 addition & 1 deletion pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ homepage: https://github.com/ricardoboss/dart_nmea
repository: https://github.com/ricardoboss/dart_nmea
issue_tracker: https://github.com/ricardoboss/dart_nmea/issues

version: 3.0.0
version: 3.1.0

environment:
sdk: ">=2.17.1 <3.0.0"
Expand Down
18 changes: 9 additions & 9 deletions test/nmea_decoder_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,9 @@ void main() {

test("decodes custom sentences with invalid checksums", () {
final decoder = NmeaDecoder()
..registerCustomSentence(
..registerCustomChecksumSentence(
TestCustomSentence.id, (line) => TestCustomSentence(raw: line));
final decoded = decoder.decodeCustom("\$CST,123,345*56");
final decoded = decoder.decodeCustomChecksum("\$CST,123,345*56");

expect(decoded, isNotNull);
expect(decoded!.fields, equals(["CST", "123", "345"]));
Expand All @@ -36,9 +36,9 @@ void main() {

test("decodes custom sentences with valid checksums", () {
final decoder = NmeaDecoder()
..registerCustomSentence(
..registerCustomChecksumSentence(
TestCustomSentence.id, (line) => TestCustomSentence(raw: line));
final decoded = decoder.decodeCustom("\$CST,123,345*46");
final decoded = decoder.decodeCustomChecksum("\$CST,123,345*46");

expect(decoded, isNotNull);
expect(decoded!.fields, equals(["CST", "123", "345"]));
Expand All @@ -51,9 +51,9 @@ void main() {

test("decodes custom sentences with skipped checksums", () {
final decoder = NmeaDecoder()
..registerCustomSentence(TestCustomSentence.id,
..registerCustomChecksumSentence(TestCustomSentence.id,
(line) => TestCustomSentence(raw: line, validateChecksums: false));
final decoded = decoder.decodeCustom("\$CST,123,345*56");
final decoded = decoder.decodeCustomChecksum("\$CST,123,345*56");

expect(decoded, isNotNull);
expect(decoded!.fields, equals(["CST", "123", "345"]));
Expand All @@ -67,9 +67,9 @@ void main() {
test("decodes invalid custom sentences although checksum checks are skipped",
() {
final decoder = NmeaDecoder()
..registerCustomSentence(TestCustomSentence.id,
..registerCustomChecksumSentence(TestCustomSentence.id,
(line) => TestCustomSentence(raw: line, validateChecksums: false));
final decoded = decoder.decodeCustom("\$CST,123345*56");
final decoded = decoder.decodeCustomChecksum("\$CST,123345*56");

expect(decoded, isNotNull);
expect(decoded!.fields, equals(["CST", "123345"]));
Expand Down Expand Up @@ -106,7 +106,7 @@ class TestTalkerSentence extends TalkerSentence {
TestTalkerSentence({required super.raw});
}

class TestCustomSentence extends CustomSentence {
class TestCustomSentence extends CustomChecksumSentence {
static const String id = "CST";
TestCustomSentence({required super.raw, super.validateChecksums = true})
: super(identifier: id);
Expand Down

0 comments on commit fc3dc6c

Please sign in to comment.