Files
Bus-Infotainment--IBus-/lib/backend/modules/commands.dart
2024-07-13 19:25:15 +01:00

284 lines
8.0 KiB
Dart

import 'dart:convert';
import 'package:bus_infotainment/auth/api_constants.dart';
import 'package:bus_infotainment/backend/live_information.dart';
import 'package:bus_infotainment/tfl_datasets.dart';
import 'package:bus_infotainment/utils/audio%20wrapper.dart';
import 'package:bus_infotainment/utils/delegates.dart';
import 'package:appwrite/appwrite.dart' as appwrite;
import 'package:appwrite/models.dart' as models;
import 'package:uuid/uuid.dart';
import '../../auth/auth_api.dart';
import 'info_module.dart';
class CommandModule extends InfoModule {
final String sessionID;
late final String clientID;
List<CommandInfo> _commandHistory = [];
get commandHistory => _commandHistory;
EventDelegate<CommandInfo> onCommandReceived = EventDelegate();
CommandModule(this.sessionID){
// generate a random client ID
var uuid = Uuid();
clientID = uuid.v4();
if (liveInformation.auth.isAuthenticated()){
print("Auth is authenticated");
_setupListener();
} else {
print("Auth is not authenticated");
liveInformation.auth.onLogin.addListener((value) {
_setupListener();
});
}
}
// Will execute the command an event which is triggered when a response is received
Future<EventDelegate> executeCommand(String command) async {
EventDelegate<String> delegate = EventDelegate();
final client = liveInformation.auth.client;
final databases = appwrite.Databases(client);
if (true) {
try {
final response = await databases.listDocuments(
databaseId: "6633e85400036415ab0f",
collectionId: "6633e85d0020f52f3771",
queries: [
appwrite.Query.search("SessionID", liveInformation.roomCode!)
]
);
List<String> pastCommands = [];
response.documents.first.data["Commands"].forEach((element) {
pastCommands.add(element);
});
pastCommands.add(command);
final document = await databases.updateDocument(
databaseId: "6633e85400036415ab0f",
collectionId: "6633e85d0020f52f3771",
documentId: liveInformation.roomDocumentID!,
data: {
"Commands": pastCommands,
"LastUpdater": clientID,
}
);
} catch (e) {
print("Failed to send command");
}
}
_onCommandReceived(CommandInfo(command, clientID));
return delegate;
}
Future<void> _onCommandReceived(CommandInfo commandInfo) async {
commandHistory.add(commandInfo);
onCommandReceived.trigger(commandInfo);
print("Received command: ${commandInfo.command}");
List<String> commandParts = splitCommand(commandInfo.command);
String command = commandParts[0];
List<String> args = commandParts.sublist(1);
if (command == "Response:") {
}
else if (command == "initroom") {
// initroom <roomCode>
}
else if (command == "announce") {
final displayText = args[1];
if (args[0] == "manual") {
// announce manual <DisplayText> <AudioFileName>... <ScheduledTime>
List<String> audioFileNames = args.sublist(2);
try {
if (int.parse(audioFileNames.last) != null) {
audioFileNames.removeLast();
}
} catch (e) {}
DateTime scheduledTime = LiveInformation().syncedTimeModule.Now().add(Duration(seconds: 1));
try {
if (int.parse(args.last) != null) {
scheduledTime = DateTime.fromMillisecondsSinceEpoch(int.parse(args.last));
}
} catch (e) {}
liveInformation.announcementModule.queueAnnounceByAudioName(
displayText: displayText,
audioNames: audioFileNames,
scheduledTime: scheduledTime,
sendToServer: false
);
}
else if (args[0] == "info") {
int InfoIndex = int.parse(args[1]);
DateTime scheduledTime = LiveInformation().syncedTimeModule.Now();
try {
if (int.parse(args.last) != null) {
scheduledTime = DateTime.fromMillisecondsSinceEpoch(int.parse(args.last));
}
} catch (e) {}
liveInformation.announcementModule.queueAnnouncementByInfoIndex(
infoIndex: InfoIndex,
scheduledTime: scheduledTime,
sendToServer: false
);
}
else if (args[0].startsWith("dest")) {
// announce destination <RouteNumber> <RouteVariantIndex> <ScheduledTime>
print("Checkpoint 1");
String routeNumber = args[1];
int routeVariantIndex = int.parse(args[2]);
DateTime scheduledTime = LiveInformation().syncedTimeModule.Now();
try {
if (int.parse(args.last) != null) {
scheduledTime = DateTime.fromMillisecondsSinceEpoch(int.parse(args.last));
}
} catch (e) {}
print("Checkpoint 2");
BusRoute route = LiveInformation().busSequences.routes[routeNumber]!;
BusRouteVariant routeVariant = route.routeVariants.values.toList()[routeVariantIndex];
print("Checkpoint 3");
liveInformation.announcementModule.queueAnnouncementByRouteVariant(
routeVariant: routeVariant,
scheduledTime: scheduledTime,
sendToServer: false
);
}
}
else if (command == "setroute") {
// setroute <RouteNumber> <RouteVariantIndex>
LiveInformation liveInformation = LiveInformation();
String routeNumber = args[0];
int routeVariantIndex = int.parse(args[1]);
BusRoute route = liveInformation.busSequences.routes[routeNumber]!;
BusRouteVariant routeVariant = route.routeVariants.values.toList()[routeVariantIndex];
liveInformation.setRouteVariant(
routeVariant
);
// Update the server
if (liveInformation.isHost) {
print("Updating server");
final client = liveInformation.auth.client;
final databases = appwrite.Databases(client);
final response = await databases.listDocuments(
databaseId: "6633e85400036415ab0f",
collectionId: "6633e85d0020f52f3771",
queries: [
appwrite.Query.search("SessionID", liveInformation.roomCode!)
]
);
final document = await databases.updateDocument(
databaseId: "6633e85400036415ab0f",
collectionId: "6633e85d0020f52f3771",
documentId: response.documents.first.$id,
data: {
"CurrentRoute": routeNumber,
"CurrentRouteVariant": routeVariantIndex,
}
);
try {
print("Updated server");
} catch (e) {
print("Failed to update server");
}
}
}
}
appwrite.RealtimeSubscription? _subscription;
Future<void> _setupListener() async {
if (_subscription != null) {
return;
}
// final realtime = appwrite.Realtime(LiveInformation().auth.client);
//
// _subscription = realtime.subscribe(
// ['databases.${ApiConstants.INFO_Q_DATABASE_ID}.collections.${ApiConstants.COMMANDS_COLLECTION_ID}.documents']
// );
// _subscription!.stream.listen((event) {
// print(jsonEncode(event.payload));
//
// // Only do something if the document was created or updated
// if (!(event.events.first.contains("create") || event.events.first.contains("update"))) {
// return;
// }
//
// final commandInfo = CommandInfo(event.payload['command'], event.payload['client_id']);
//
// if (commandInfo.clientID != clientID) {
// _onCommandReceived(commandInfo);
// }
//
// });
print("Listening for commands");
await Future.delayed(Duration(seconds: 90));
await _subscription!.close();
_subscription = null;
_setupListener();
}
}
class CommandInfo {
final String command;
final String clientID;
CommandInfo(this.command, this.clientID);
}
List<String> splitCommand(String command) {
var regex = RegExp(r'([^\s"]+)|"([^"]*)"');
var matches = regex.allMatches(command);
return matches.map((match) => match.group(0)!.replaceAll('"', '')).toList();
}