diff --git a/lib/positioning/services/positioning.dart b/lib/positioning/services/positioning.dart index a1c517dee..8fab3d6fa 100644 --- a/lib/positioning/services/positioning.dart +++ b/lib/positioning/services/positioning.dart @@ -14,9 +14,10 @@ import 'package:priobike/positioning/sources/interface.dart'; import 'package:priobike/positioning/sources/mock.dart'; import 'package:priobike/routing/models/route.dart'; import 'package:priobike/routing/services/routing.dart'; -import 'package:priobike/settings/models/backend.dart'; +import 'package:priobike/settings/models/backend.dart' hide Simulator; import 'package:priobike/settings/models/positioning.dart'; import 'package:priobike/settings/services/settings.dart'; +import 'package:priobike/simulator/services/simulator.dart'; class Positioning with ChangeNotifier { final log = Logger("Positioning"); @@ -204,10 +205,14 @@ class Positioning with ChangeNotifier { // TODO: Hier MQTT einbauen + final Simulator simulator = getIt(); + positionSubscription = positionStream.listen( (Position position) { if (!isGeolocating) return; lastPosition = position; + simulator.sendCurrentPosition(); + positions.add(position); // Snap the position to the route. if (route != null && route!.route.length > 2) { diff --git a/lib/simulator/services/simulator.dart b/lib/simulator/services/simulator.dart index b721d2641..5173345a5 100644 --- a/lib/simulator/services/simulator.dart +++ b/lib/simulator/services/simulator.dart @@ -1,12 +1,8 @@ import 'dart:async'; import 'dart:convert'; -import 'dart:ffi'; -import 'dart:math'; - import 'package:flutter/foundation.dart'; import 'package:mqtt_client/mqtt_client.dart'; import 'package:mqtt_client/mqtt_server_client.dart'; -import 'package:path/path.dart'; import 'package:priobike/logging/logger.dart'; import 'package:priobike/main.dart'; import 'package:priobike/positioning/services/positioning.dart'; @@ -22,50 +18,75 @@ class Simulator { /// The mqtt client. MqttServerClient? client; - /// The last time the current speed was sent to the simulator. - DateTime? lastSend; - - /// The timer that is used to periodically calculate the prediction. - Timer? calcTimer; - - double currentSpeed = 20.0; - - final deviceId = UniqueKey().toString(); - - /// How often the current speed should be sent to the simulator. - final Duration sendInterval = const Duration(seconds: 1); + /// The unique key to identify the device in the simulator. + final deviceId = UniqueKey().toString().replaceAll("[", "").replaceAll("]", "").replaceAll("#", ""); askForPermission() { // TODO: implement askForPermission } - conntectWithDevice() { + conntectWithSensor() { // TODO: implement conntectWithDevice } - sendReadyToPair() { - // TODO: + /// Sends a ready pair request to the simulator via MQTT. + Future sendReadyPairRequest() async { + if (client == null) await connectMQTTClient(); + + const topic = "simulation"; + const qualityOfService = MqttQos.atLeastOnce; + + Map json = {}; + json['type'] = 'ReadyPairRequest'; + json['deviceID'] = deviceId; + + final String message = jsonEncode(json); + + await sendViaMQTT( + message: message, + topic: topic, + qualityOfService: qualityOfService, + ); + // TODO: muss ich hier noch irgendwie auf eine Antwort warten?? } - Future sendCurrentSpeedToMQTT() async { + /// Send the current position to the simulator via MQTT. + Future sendCurrentPosition() async { if (client == null) await connectMQTTClient(); const topic = "simulation"; const qualityOfService = MqttQos.atMostOnce; - // Debug-Feature: Set the current speed to a random value between 20 and 40 and set Debug-Speed. - final oldSpeed = currentSpeed; - double newSpeed = 0.0; - const minSpeed = 20.0; - const maxSpeed = 40.0; - while (newSpeed > maxSpeed || newSpeed < minSpeed || (newSpeed - oldSpeed).abs() > 2) { - newSpeed = minSpeed + Random().nextDouble() * (maxSpeed - minSpeed); - } - currentSpeed = newSpeed; - final positioning = getIt(); - positioning.setDebugSpeed(currentSpeed / 3.6); + final Positioning positioning = getIt(); + final position = positioning.lastPosition; + if (position == null) return; + final longitude = position.longitude; + final latitude = position.latitude; + final heading = position.heading; + + // Format: + // {"type":"NextCoordinate", "deviceID":"1234567890", "longitude":"10. + // 12345", "latitude":"50.12345", "bearing":"-80"} + + Map json = {}; + json['type'] = 'NextCoordinate'; + json['deviceID'] = deviceId; + json['longitude'] = longitude.toString(); + json['latitude'] = latitude.toString(); + json['bearing'] = heading.toString(); + + final String message = jsonEncode(json); + + await sendViaMQTT( + message: message, + topic: topic, + qualityOfService: qualityOfService, + ); + } - final String message = "$deviceId ${currentSpeed.toStringAsFixed(2)}"; + /// Sends a message to the simulator via MQTT. + Future sendViaMQTT({required String message, required String topic, required MqttQos qualityOfService}) async { + if (client == null) await connectMQTTClient(); // convert message to byte array final Uint8List data = Uint8List.fromList(utf8.encode(message)); @@ -81,6 +102,7 @@ class Simulator { } } + /// Connects the MQTT client to the simulator. Future connectMQTTClient() async { // Get the backend that is currently selected. final settings = getIt(); @@ -120,10 +142,8 @@ class Simulator { .startClean() .withWillQos(MqttQos.atMostOnce); - // Start the timer that updates the prediction once per second. - calcTimer = Timer.periodic(sendInterval, (timer) { - sendCurrentSpeedToMQTT(); - }); + await sendReadyPairRequest(); + // TODO: implement MQTT handshake } catch (e, stacktrace) { client = null; final hint = "Failed to connect the simulator MQTT client: $e, $stacktrace"; @@ -140,8 +160,6 @@ class Simulator { } Future disconnectMQTTClient() async { - calcTimer?.cancel(); - calcTimer = null; if (client != null) { client!.disconnect(); client = null;