From 9f77896591404dd82e4f2887e204f96056d383ca Mon Sep 17 00:00:00 2001 From: Andy Zheng <78238181+AndyZ54@users.noreply.github.com> Date: Tue, 25 Oct 2022 04:51:18 -0400 Subject: [PATCH] Networking (#25) > * Created Electrical Message and Metrics > * Changed Wrapped Message > * Message Receiver, Message Sender edited > * Moved Protobuf into metrics.dart > * Updated analyzer test to use new protobuf files > Added Protobuf files to `build.yaml` and `.gitignore`, so now you can run > > ``` > dart run build_runner build > ``` > > from `dashboard` instead of running > > ``` > protoc --dart_out=./generated Protobuf/*.proto > ``` > > from `dashboard/lib/src/data`. Co-authored-by: Levi Lesches --- .github/workflows/analyze.yml | 9 +- .github/workflows/documentation.yml | 7 +- .gitignore | 3 + .gitmodules | 3 + README.md | 7 +- analysis_options.yaml | 12 +- build.yaml | 19 ++ lib/data.dart | 5 + lib/models.dart | 2 + lib/services.dart | 27 ++- lib/src/data/Protobuf | 1 + lib/src/data/metrics.dart | 12 +- lib/src/data/wrapped_message.dart | 16 ++ lib/src/models/model.dart | 7 + lib/src/models/vitals.dart | 19 ++ lib/src/services/message_receiver.dart | 84 +++++++ lib/src/services/message_sender.dart | 41 ++++ lib/src/services/service.dart | 3 + pubspec.lock | 323 +++++++++++++++++++++++-- pubspec.yaml | 7 + 20 files changed, 572 insertions(+), 35 deletions(-) create mode 100644 .gitmodules create mode 100644 build.yaml create mode 160000 lib/src/data/Protobuf create mode 100644 lib/src/data/wrapped_message.dart create mode 100644 lib/src/models/model.dart create mode 100644 lib/src/models/vitals.dart create mode 100644 lib/src/services/message_receiver.dart create mode 100644 lib/src/services/message_sender.dart diff --git a/.github/workflows/analyze.yml b/.github/workflows/analyze.yml index 15de18806..a702d76f9 100644 --- a/.github/workflows/analyze.yml +++ b/.github/workflows/analyze.yml @@ -27,10 +27,17 @@ jobs: - uses: actions/checkout@v2 with: path: repo # keeps Flutter separate from repo + submodules: recursive # Has to be after checkout since repo won't exist - name: Add Flutter to path - run: echo "../flutter/bin" >> $GITHUB_PATH + run: echo "$GITHUB_WORKSPACE/flutter/bin" >> $GITHUB_PATH + + - name: Generate Protobuf files + run: | + flutter clean + flutter pub get + dart run build_runner build - name: Analyze run: flutter analyze --dartdocs diff --git a/.github/workflows/documentation.yml b/.github/workflows/documentation.yml index 7ebdec993..d5bd8f3df 100644 --- a/.github/workflows/documentation.yml +++ b/.github/workflows/documentation.yml @@ -30,6 +30,7 @@ jobs: with: fetch-depth: 0 path: repo # keep Flutter separate + submodules: recursive - name: Git Setup run: | @@ -42,7 +43,7 @@ jobs: git commit -m "Removed documentation" -m "Will generate new docs" - name: Add Flutter to path - run: echo "../flutter/bin" >> $GITHUB_PATH + run: echo "$GITHUB_WORKSPACE/flutter/bin" >> $GITHUB_PATH - name: Flutter Setup run: | @@ -52,7 +53,9 @@ jobs: flutter --version - name: Analyze code - run: flutter analyze --dartdocs + run: | + dart run build_runner build + flutter analyze --dartdocs - name: Output error if: failure() diff --git a/.gitignore b/.gitignore index a8e938c08..56e0c3440 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,6 @@ +# Protobuf code is generated here +lib/src/data/generated + # Miscellaneous *.class *.log diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 000000000..25116db4c --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "lib/src/data/Protobuf"] + path = lib/src/data/Protobuf + url = https://github.com/BinghamtonRover/Protobuf.git diff --git a/README.md b/README.md index 13959979d..7e0d5bdf7 100644 --- a/README.md +++ b/README.md @@ -30,6 +30,11 @@ A Dart library is technically just a file. To add more complexity, classes and f ## Compiling +Firstly, we're using [Protobuf](https://developers.google.com/protocol-buffers), which means we need to invoke the Protobuf compiler to generate Dart code before we can compile the dashboard. Thankfully, that's all handled by `package:build_runner`, the de facto code generator for Dart. +``` +dart run build_runner build +``` + To run a debug build, run the appropriate command for your computer: ``` @@ -46,7 +51,7 @@ flutter build linux flutter build macos ``` -Note that Flutter is not cross-platform, which means you can only output executables for the platform you compile on. The location of the executable differs by platform: +Note that Flutter's compiler is not cross-platform, which means you can only output executables for the platform you compile on. The location of the executable differs by platform: - Windows: `build\windows\runner\Release` - Linux: `build/linux/x64/release/bundle` diff --git a/analysis_options.yaml b/analysis_options.yaml index 3789a012d..8a67d55b3 100644 --- a/analysis_options.yaml +++ b/analysis_options.yaml @@ -1,5 +1,6 @@ # This file configures the analyzer, which statically analyzes Dart code to -# check for errors, warnings, and lints. +# check for errors, warnings, and lints. See the following for docs: +# https://dart.dev/guides/language/analysis-options # # The issues identified by the analyzer are surfaced in the UI of Dart-enabled # IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be @@ -9,6 +10,10 @@ # packages, and plugins designed to encourage good coding practices. include: package:flutter_lints/flutter.yaml +analyzer: + exclude: + - lib/src/data/generated/**.dart + linter: # The lint rules applied to this project can be customized in the # section below to disable rules from the `package:flutter_lints/flutter.yaml` @@ -240,8 +245,3 @@ linter: # Including a `key` parameter in widgets is good practice for public APIs. # However, this project is not being imported by third parties. use_key_in_widget_constructors: false - - - -# Additional information about this file can be found at -# https://dart.dev/guides/language/analysis-options diff --git a/build.yaml b/build.yaml new file mode 100644 index 000000000..12ffac4eb --- /dev/null +++ b/build.yaml @@ -0,0 +1,19 @@ +targets: + $default: + sources: + - $package$ + - lib/$lib$ + - lib/src/data/Protobuf/**.proto + builders: + protoc_builder: + options: + # Directory which is treated as the root of all Protobuf files. + # (Default: "proto/") + root_dir: "lib/src/data/Protobuf/" + # Include paths given to the Protobuf compiler during compilation. + # (Default: ["proto/"]) + proto_paths: + - "lib/src/data/Protobuf/" + # The root directory for generated Dart output files. + # (Default: "lib/src/proto") + out_dir: "lib/src/data/generated" diff --git a/lib/data.dart b/lib/data.dart index e8b3629b2..54628b547 100644 --- a/lib/data.dart +++ b/lib/data.dart @@ -8,4 +8,9 @@ /// library should import any other library. library data; +export "src/data/generated/drive_control.pb.dart"; +export "src/data/generated/sensor_control.pb.dart"; +export "src/data/generated/video_control.pb.dart"; +export "src/data/generated/wrapper.pb.dart"; export "src/data/metrics.dart"; +export "src/data/wrapped_message.dart"; diff --git a/lib/models.dart b/lib/models.dart index 361fb6394..a0d525255 100644 --- a/lib/models.dart +++ b/lib/models.dart @@ -6,3 +6,5 @@ /// /// This library may depend on the data and services library. library models; + +export "src/models/vitals.dart"; diff --git a/lib/services.dart b/lib/services.dart index 65320d8af..80612a09e 100644 --- a/lib/services.dart +++ b/lib/services.dart @@ -13,13 +13,21 @@ /// not import any other library in this project, only 3rd party plugins. library services; +import "src/services/message_receiver.dart"; +import "src/services/message_sender.dart"; import "src/services/service.dart"; +export "src/services/message_receiver.dart"; +export "src/services/message_sender.dart"; + /// A dependency injection service that manages the lifecycle of other services. /// /// All services must only be used by accessing them from this class, and this class will take care /// of calling lifecycle methods like [init] while handling possibly asynchrony. /// +/// When adding a new service, declare it as a field in this class **and** add it to the [_services] +/// list in the constructor. Otherwise, the service will fail to initialize and dispose properly. +/// /// To get an instance of this class, use [Services.instance]. class Services extends Service { /// The singleton instance of this class. @@ -27,9 +35,24 @@ class Services extends Service { /// This is the only instance of this class the app can guarantee is properly initialized. static Services instance = Services._(); + late final List _services; + /// This class has a private constructor since users should only use [Services.instance]. - Services._(); + Services._() { _services = [messageReceiver, messageSender]; } + + /// A service that receives messages from the rover over the network. + final messageReceiver = MessageReceiver(); + + /// A service that sends messages to the rover over the network. + final messageSender = MessageSender(); + + @override + Future init() async { + for (final service in _services) { await service.init(); } + } @override - Future init() async { } + Future dispose() async { + for (final service in _services) { await service.dispose(); } + } } diff --git a/lib/src/data/Protobuf b/lib/src/data/Protobuf new file mode 160000 index 000000000..6da4accac --- /dev/null +++ b/lib/src/data/Protobuf @@ -0,0 +1 @@ +Subproject commit 6da4accacd5d54ba6a99743e2b584b7a8df80877 diff --git a/lib/src/data/metrics.dart b/lib/src/data/metrics.dart index aac8e89e7..e83938a88 100644 --- a/lib/src/data/metrics.dart +++ b/lib/src/data/metrics.dart @@ -1,5 +1,5 @@ import "package:protobuf/protobuf.dart"; - +import "package:rover_dashboard/data.dart"; /// A readout of metrics reported by one of the rover's subsystems. /// /// To use this class, create a subclass that extends this class with [T] as the generated @@ -29,7 +29,7 @@ abstract class Metrics { /// These metrics represent the vitals of the rover: basics like voltage, current, and temperature /// of the various electrical components. These values aren't useful for the missions, but should /// be monitored to catch problems before they cause damage to the rover. -class ElectricalMetrics extends Metrics { +class ElectricalMetrics extends Metrics { /// A collection of metrics relevant for monitoring the rover's electrical status. const ElectricalMetrics(super.data); @@ -39,10 +39,10 @@ class ElectricalMetrics extends Metrics { // TODO: implement this @override List get allMetrics => [ - // "Battery: ${data.batteryVoltage} V, ${data.batteryCurrent} A", - // "12V supply: ${data.v12SupplyVoltage} V, ${data.v12SupplyCurrent} A, ${data.v12SupplyTemperature} °F", - // "5V supply: ${data.v5SupplyVoltage} V, ${data.v5SupplyCurrent} A, ${data.v5SupplyTemperature} °F", - // "ODrives: ${data.odriveCurrent1} A, ${data.odriveCurrent2} A, ${data.odriveCurrent3} A", + "Battery: ${data.batteryVoltage} V, ${data.batteryCurrent} A", + "12V supply: ${data.v12SupplyVoltage} V, ${data.v12SupplyCurrent} A, ${data.v12SupplyTemperature} °F", + "5V supply: ${data.v5SupplyVoltage} V, ${data.v5SupplyCurrent} A, ${data.v5SupplyTemperature} °F", + "ODrives: ${data.odrive0Current} A, ${data.odrive1Current} A, ${data.odrive2Current} A", ]; } diff --git a/lib/src/data/wrapped_message.dart b/lib/src/data/wrapped_message.dart new file mode 100644 index 000000000..6352c2540 --- /dev/null +++ b/lib/src/data/wrapped_message.dart @@ -0,0 +1,16 @@ +import "package:protobuf/protobuf.dart" as proto; +import "package:rover_dashboard/data.dart"; + +/// A cleaner name for any message generated by Protobuf. +typedef Message = proto.GeneratedMessage; + +/// A function that decodes a Protobuf messages serialized form. +/// +/// The `.fromBuffer` constructor is a type of [MessageDecoder]. +typedef MessageDecoder = T Function(List data); + +/// Decodes a wrapped Protobuf message. +extension Unwrapper on WrappedMessage { + /// Decodes the wrapped message into a message of type [T]. + T decode(MessageDecoder decoder) => decoder(data); +} diff --git a/lib/src/models/model.dart b/lib/src/models/model.dart new file mode 100644 index 000000000..3dc3b0e5b --- /dev/null +++ b/lib/src/models/model.dart @@ -0,0 +1,7 @@ +import "package:flutter/foundation.dart"; + +/// A data model that handles data from services. +abstract class Model with ChangeNotifier { + /// Initializes any data needed by this model. + Future init(); +} diff --git a/lib/src/models/vitals.dart b/lib/src/models/vitals.dart new file mode 100644 index 000000000..483b980cf --- /dev/null +++ b/lib/src/models/vitals.dart @@ -0,0 +1,19 @@ +import "model.dart"; + +/// Handles incoming data about the vitals of the rover, like voltage, power and temperature. +class Vitals extends Model { + /// The temperature of the rover, in degrees F. + int temperature = 0; + + @override + Future init() async { + // Subscribe to ElectricalMessages using the MessageReceiver service. + // When a new message arrives, update the relevant fields and call [notifyListeners]. + } + + @override + Future dispose() async { + // Cancel the subscription. + super.dispose(); + } +} diff --git a/lib/src/services/message_receiver.dart b/lib/src/services/message_receiver.dart new file mode 100644 index 000000000..c97a08887 --- /dev/null +++ b/lib/src/services/message_receiver.dart @@ -0,0 +1,84 @@ +import "dart:async"; +import "dart:io"; + +import "package:rover_dashboard/data.dart"; +import "service.dart"; + +/// A callback to execute with raw Protobuf data. +typedef RawMessageHandler = void Function(List data); + +/// A callback to execute with a specific serialized Protobuf message. +// typedef MessageHandler = void Function(T); +typedef Handler = void Function(T); + +/// The port to listen for messages on. +const port = 22201; + +/// A function that handles incoming data. +extension on RawDatagramSocket { + StreamSubscription listenForData(Handler> handler) => listen((event) { + final datagram = receive(); + if (datagram == null) return; + handler(datagram.data); + }); +} + +/// A service that receives messages over a UDP connection. +/// +/// To listen to certain messages, call [registerHandler] with the type of message you want +/// to receive, as well as a decoder and the handler callback itself. +class MessageReceiver extends Service { + /// Handlers for every possible type of Protobuf message in serialized form. + final Map _handlers = {}; + + /// The UDP socket to listen on. + /// + /// Initialized in [init]. + late final RawDatagramSocket _socket; + + /// The subscription that listens to [_socket]. + late final StreamSubscription _subscription; + + @override + Future init() async { + _socket = await RawDatagramSocket.bind(InternetAddress.anyIPv4, port); + _subscription = _socket.listenForData(_listener); + } + + @override + Future dispose() async { + await _subscription.cancel(); + _socket.close(); + } + + /// Runs every time data is received by the socket. + /// + /// The datagram contains a [WrappedMessage]. These are Protobuf messages that wrap an + /// underlying message and record their name. We use the type of the underlying message + /// to get the appropriate handler from [_handlers] which decodes the message to the + /// correct type and processes it. + void _listener(List data) { + final wrapped = WrappedMessage.fromBuffer(data); + final RawMessageHandler? rawHandler = _handlers[wrapped.name]; + if (rawHandler == null) { /* Log in some meaningful way, through the UI */ } + else { rawHandler(wrapped.data); } + } + + /// Adds a handler for a given type. + /// + /// [decoder] is a function that decodes a byte buffer to a Protobuf message class. [handler] + /// then handles that message somehow. + void registerHandler({ + required String name, + required MessageDecoder decoder, + required Handler handler + }) { + if (T == Message) { // no T was actually passed, [Message] is the default + throw ArgumentError("No message type was passed"); + } else if (_handlers.containsKey(name)) { // handler was already registered + throw ArgumentError("Message handler for type [$T] already registered"); + } else { + _handlers[name] = (List data) => handler(decoder(data)); + } + } +} diff --git a/lib/src/services/message_sender.dart b/lib/src/services/message_sender.dart new file mode 100644 index 000000000..d02ac00c4 --- /dev/null +++ b/lib/src/services/message_sender.dart @@ -0,0 +1,41 @@ +import "dart:io"; + +import "package:rover_dashboard/data.dart"; + +import "service.dart"; + +/// A service to send [Message] objects to the rover. +class MessageSender extends Service { + /// The IP address of the rover. + static final address = InternetAddress("127.0.0.1"); + + /// The port on the rover to send to. + static const port = 8082; + + /// The socket for the UDP connection. + late final RawDatagramSocket _socket; + + @override + Future init() async { + _socket = await RawDatagramSocket.bind(InternetAddress.anyIPv4, port); + } + + @override + Future dispose() async { + _socket.close(); + } + + /// Resets the connection. + /// + /// When in doubt, turn it off and back on again. + Future reset() async { + await dispose(); + await init(); + } + + /// Wraps the [message] in a [WrappedMessage] container and sends it to the rover. + Future sendMessage(Message message) async { + final wrapper = WrappedMessage(name: message.info_.messageName, data: message.writeToBuffer()); + _socket.send(wrapper.writeToBuffer(), address, port); + } +} diff --git a/lib/src/services/service.dart b/lib/src/services/service.dart index 1396f13b1..ad80791c6 100644 --- a/lib/src/services/service.dart +++ b/lib/src/services/service.dart @@ -6,4 +6,7 @@ abstract class Service { /// Initializes the service. Future init(); + + /// Cleans up any resources used by the service. + Future dispose(); } diff --git a/pubspec.lock b/pubspec.lock index 468b08ee7..9adfb6b62 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -1,13 +1,41 @@ # Generated by pub # See https://dart.dev/tools/pub/glossary#lockfile packages: + _fe_analyzer_shared: + dependency: transitive + description: + name: _fe_analyzer_shared + url: "https://pub.dartlang.org" + source: hosted + version: "49.0.0" + analyzer: + dependency: transitive + description: + name: analyzer + url: "https://pub.dartlang.org" + source: hosted + version: "5.1.0" + archive: + dependency: transitive + description: + name: archive + url: "https://pub.dartlang.org" + source: hosted + version: "3.3.2" + args: + dependency: transitive + description: + name: args + url: "https://pub.dartlang.org" + source: hosted + version: "2.3.1" async: dependency: transitive description: name: async url: "https://pub.dartlang.org" source: hosted - version: "2.8.2" + version: "2.9.0" boolean_selector: dependency: transitive description: @@ -15,27 +43,90 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "2.1.0" + build: + dependency: transitive + description: + name: build + url: "https://pub.dartlang.org" + source: hosted + version: "2.3.1" + build_config: + dependency: transitive + description: + name: build_config + url: "https://pub.dartlang.org" + source: hosted + version: "1.1.1" + build_daemon: + dependency: transitive + description: + name: build_daemon + url: "https://pub.dartlang.org" + source: hosted + version: "3.1.0" + build_resolvers: + dependency: transitive + description: + name: build_resolvers + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.10" + build_runner: + dependency: "direct dev" + description: + name: build_runner + url: "https://pub.dartlang.org" + source: hosted + version: "2.3.2" + build_runner_core: + dependency: transitive + description: + name: build_runner_core + url: "https://pub.dartlang.org" + source: hosted + version: "7.2.6" + built_collection: + dependency: transitive + description: + name: built_collection + url: "https://pub.dartlang.org" + source: hosted + version: "5.1.1" + built_value: + dependency: transitive + description: + name: built_value + url: "https://pub.dartlang.org" + source: hosted + version: "8.4.1" characters: dependency: transitive description: name: characters url: "https://pub.dartlang.org" source: hosted - version: "1.2.0" - charcode: + version: "1.2.1" + checked_yaml: dependency: transitive description: - name: charcode + name: checked_yaml url: "https://pub.dartlang.org" source: hosted - version: "1.3.1" + version: "2.0.1" clock: dependency: transitive description: name: clock url: "https://pub.dartlang.org" source: hosted - version: "1.1.0" + version: "1.1.1" + code_builder: + dependency: transitive + description: + name: code_builder + url: "https://pub.dartlang.org" + source: hosted + version: "4.3.0" collection: dependency: transitive description: @@ -43,13 +134,41 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.16.0" + convert: + dependency: transitive + description: + name: convert + url: "https://pub.dartlang.org" + source: hosted + version: "3.1.1" + crypto: + dependency: transitive + description: + name: crypto + url: "https://pub.dartlang.org" + source: hosted + version: "3.0.2" + dart_style: + dependency: transitive + description: + name: dart_style + url: "https://pub.dartlang.org" + source: hosted + version: "2.2.4" fake_async: dependency: transitive description: name: fake_async url: "https://pub.dartlang.org" source: hosted - version: "1.3.0" + version: "1.3.1" + file: + dependency: transitive + description: + name: file + url: "https://pub.dartlang.org" + source: hosted + version: "6.1.4" fixnum: dependency: transitive description: @@ -74,41 +193,132 @@ packages: description: flutter source: sdk version: "0.0.0" + frontend_server_client: + dependency: transitive + description: + name: frontend_server_client + url: "https://pub.dartlang.org" + source: hosted + version: "3.1.0" + glob: + dependency: transitive + description: + name: glob + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.0" + graphs: + dependency: transitive + description: + name: graphs + url: "https://pub.dartlang.org" + source: hosted + version: "2.2.0" + http: + dependency: transitive + description: + name: http + url: "https://pub.dartlang.org" + source: hosted + version: "0.13.5" + http_multi_server: + dependency: transitive + description: + name: http_multi_server + url: "https://pub.dartlang.org" + source: hosted + version: "3.2.1" + http_parser: + dependency: transitive + description: + name: http_parser + url: "https://pub.dartlang.org" + source: hosted + version: "4.0.2" + io: + dependency: transitive + description: + name: io + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.3" + js: + dependency: transitive + description: + name: js + url: "https://pub.dartlang.org" + source: hosted + version: "0.6.5" + json_annotation: + dependency: transitive + description: + name: json_annotation + url: "https://pub.dartlang.org" + source: hosted + version: "4.7.0" lints: dependency: transitive description: name: lints url: "https://pub.dartlang.org" source: hosted - version: "2.0.0" + version: "2.0.1" + logging: + dependency: transitive + description: + name: logging + url: "https://pub.dartlang.org" + source: hosted + version: "1.1.0" matcher: dependency: transitive description: name: matcher url: "https://pub.dartlang.org" source: hosted - version: "0.12.11" + version: "0.12.12" material_color_utilities: dependency: transitive description: name: material_color_utilities url: "https://pub.dartlang.org" source: hosted - version: "0.1.4" + version: "0.1.5" meta: dependency: transitive description: name: meta url: "https://pub.dartlang.org" source: hosted - version: "1.7.0" + version: "1.8.0" + mime: + dependency: transitive + description: + name: mime + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.2" + package_config: + dependency: transitive + description: + name: package_config + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.0" path: dependency: transitive description: name: path url: "https://pub.dartlang.org" source: hosted - version: "1.8.1" + version: "1.8.2" + pool: + dependency: transitive + description: + name: pool + url: "https://pub.dartlang.org" + source: hosted + version: "1.5.1" protobuf: dependency: "direct main" description: @@ -116,6 +326,43 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "2.1.0" + protoc_builder: + dependency: "direct dev" + description: + path: "." + ref: windows-fix + resolved-ref: "40b4a4bb78f0f97957ff2ed3ee233e9a02aee9c2" + url: "https://github.com/Levi-Lesches/dart-protoc-builder.git" + source: git + version: "0.2.1+1" + pub_semver: + dependency: transitive + description: + name: pub_semver + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.2" + pubspec_parse: + dependency: transitive + description: + name: pubspec_parse + url: "https://pub.dartlang.org" + source: hosted + version: "1.2.1" + shelf: + dependency: transitive + description: + name: shelf + url: "https://pub.dartlang.org" + source: hosted + version: "1.4.0" + shelf_web_socket: + dependency: transitive + description: + name: shelf_web_socket + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.2" sky_engine: dependency: transitive description: flutter @@ -127,7 +374,7 @@ packages: name: source_span url: "https://pub.dartlang.org" source: hosted - version: "1.8.2" + version: "1.9.0" stack_trace: dependency: transitive description: @@ -142,27 +389,48 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "2.1.0" + stream_transform: + dependency: transitive + description: + name: stream_transform + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.1" string_scanner: dependency: transitive description: name: string_scanner url: "https://pub.dartlang.org" source: hosted - version: "1.1.0" + version: "1.1.1" term_glyph: dependency: transitive description: name: term_glyph url: "https://pub.dartlang.org" source: hosted - version: "1.2.0" + version: "1.2.1" test_api: dependency: transitive description: name: test_api url: "https://pub.dartlang.org" source: hosted - version: "0.4.9" + version: "0.4.12" + timing: + dependency: transitive + description: + name: timing + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.0" + typed_data: + dependency: transitive + description: + name: typed_data + url: "https://pub.dartlang.org" + source: hosted + version: "1.3.1" vector_math: dependency: transitive description: @@ -170,5 +438,26 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "2.1.2" + watcher: + dependency: transitive + description: + name: watcher + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.2" + web_socket_channel: + dependency: transitive + description: + name: web_socket_channel + url: "https://pub.dartlang.org" + source: hosted + version: "2.2.0" + yaml: + dependency: transitive + description: + name: yaml + url: "https://pub.dartlang.org" + source: hosted + version: "3.1.1" sdks: - dart: ">=2.17.6 <3.0.0" + dart: ">=2.18.0 <3.0.0" diff --git a/pubspec.yaml b/pubspec.yaml index 561af216c..667d4c801 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -31,6 +31,13 @@ dev_dependencies: # See `analysis_options.yaml` for details about lints. flutter_lints: ^2.0.0 + build_runner: ^2.3.2 + # Using my fork due to a bug on Windows. + # See: https://github.com/pikaju/dart-protoc-builder/issues/5 + protoc_builder: + git: + url: https://github.com/Levi-Lesches/dart-protoc-builder.git + ref: windows-fix # The following section is specific to Flutter packages. flutter: