desktop push

This commit is contained in:
ImBenji
2024-05-20 09:06:38 +01:00
parent e5a8d78bf1
commit 639faddfc8
19 changed files with 2455 additions and 996 deletions

View File

@@ -27,7 +27,7 @@ class AnnouncementModule extends InfoModule {
// Files
String _bundleLocation = "assets/ibus_recordings.zip";
Uint8List? _bundleBytes;
void setBundleBytes(Uint8List bytes) {
void setBundleBytes(Uint8List? bytes) {
_bundleBytes = bytes;
}
Future<Uint8List> getBundleBytes() async {
@@ -35,7 +35,6 @@ class AnnouncementModule extends InfoModule {
if (_bundleBytes != null) {
return _bundleBytes!;
} else {
// Try to load them from shared preferences
try {
SharedPreferences prefs = await SharedPreferences.getInstance();
@@ -47,17 +46,7 @@ class AnnouncementModule extends InfoModule {
} catch (e) {
throw Exception("Loading announcements from assets has been deprecated.");
}
// if (kIsWeb) {
// throw Exception("Cannot load bundle bytes on web");
// }
//
// final bytes = await rootBundle.load(_bundleLocation);
// return bytes.buffer.asUint8List();
}
}
// Queue
@@ -165,7 +154,14 @@ class AnnouncementModule extends InfoModule {
}
// Configuration
int get defaultAnnouncementDelay => liveInformation.auth.isAuthenticated() ? 1 : 0;
Duration get defaultAnnouncementDelay {
if (liveInformation.inRoom) {
return Duration(milliseconds: 500);
} else {
print("Not in room");
return Duration.zero;
}
}
// Methods
Future<void> queueAnnounceByAudioName({
@@ -177,7 +173,9 @@ class AnnouncementModule extends InfoModule {
if (sendToServer && _shouldSendToServer()) {
scheduledTime ??= liveInformation.syncedTimeModule.Now().add(Duration(seconds: defaultAnnouncementDelay));
scheduledTime ??= liveInformation.syncedTimeModule.Now().add(defaultAnnouncementDelay);
String audioNamesString = "";
@@ -232,7 +230,7 @@ class AnnouncementModule extends InfoModule {
if (sendToServer && _shouldSendToServer()) {
scheduledTime ??= liveInformation.syncedTimeModule.Now().add(Duration(seconds: defaultAnnouncementDelay));
scheduledTime ??= liveInformation.syncedTimeModule.Now().add(defaultAnnouncementDelay);
liveInformation.SendCommand("announce info $infoIndex ${scheduledTime.millisecondsSinceEpoch}");
queueAnnouncementByInfoIndex(
@@ -262,7 +260,9 @@ class AnnouncementModule extends InfoModule {
if (sendToServer && _shouldSendToServer()) {
scheduledTime ??= liveInformation.syncedTimeModule.Now().add(Duration(seconds: defaultAnnouncementDelay));
print("Sending route announcement to server");
scheduledTime ??= liveInformation.syncedTimeModule.Now().add(defaultAnnouncementDelay);
String routeNumber = routeVariant.busRoute.routeNumber;
int routeVariantIndex = routeVariant.busRoute.routeVariants.values.toList().indexOf(routeVariant);
@@ -326,7 +326,7 @@ class AnnouncementModule extends InfoModule {
// Server check
bool _shouldSendToServer() {
bool condition = liveInformation.roomCode != null;
bool condition = liveInformation.inRoom;
print("Should send to server? " + (condition.toString()));
return condition;

View File

@@ -0,0 +1,196 @@
import 'dart:async';
import 'dart:io';
import 'package:flutter/foundation.dart';
import 'package:network_info_plus/network_info_plus.dart';
import 'package:shelf/shelf.dart';
import 'package:shelf/shelf_io.dart' as io;
import 'package:shelf_web_socket/shelf_web_socket.dart';
import 'package:web_socket_channel/web_socket_channel.dart';
import 'package:bus_infotainment/backend/modules/info_module.dart';
import 'package:bus_infotainment/utils/delegates.dart';
class NetworkingModule extends InfoModule {
// Host websocket server
String host = "ws://0.0.0.0:8080";
HttpServer? _server;
WebSocketChannel? _channel;
// Store connected WebSocket channels
final List<WebSocketChannel> _connectedClients = [];
EventDelegate<String>? onMessageReceived = EventDelegate();
NetworkingModule() {
_refresh();
refreshTimer();
}
Future<bool> startWebSocketServer() async {
try {
var handler = webSocketHandler((WebSocketChannel webSocket) {
_connectedClients.add(webSocket); // Add the client to the list
print('Client connected: ${webSocket}'); // Log client connection
webSocket.stream.listen((message) {
// Handle messages from the client here
print('Received message: $message');
// Forward message to all clients except the sender
for (var client in _connectedClients) {
if (client != webSocket) {
client.sink.add(message);
}
}
_onMessageReceived(message);
}, onDone: () {
_connectedClients.remove(webSocket); // Remove client on disconnect
print('Client disconnected: ${webSocket}'); // Log client disconnection
});
});
_server = await io.serve(handler, InternetAddress.anyIPv4, 8080);
print('WebSocket server started at ${_server?.address.address}:${_server?.port}');
return true;
} catch (e) {
print('Failed to start WebSocket server: $e');
return false;
}
}
bool stopWebSocketServer() {
if (_server == null) {
throw Exception('WebSocket server is not running');
}
try {
for (var client in _connectedClients) {
client.sink.close();
}
_connectedClients.clear();
_server?.close(force: true);
_server = null;
print('WebSocket server stopped');
return true;
} catch (e) {
print('Failed to stop WebSocket server: $e');
return false;
}
}
Future<bool> connectToWebSocketServer(String url) async {
try {
_channel = await WebSocketChannel.connect(Uri.parse(url));
_channel?.stream.listen((message) {
// Handle messages from the server here
print('Received message from server: $message');
_onMessageReceived(message);
});
print('Connected to WebSocket server at $url');
return true;
} catch (e) {
print('Failed to connect to WebSocket server: $e');
return false;
}
}
bool disconnectFromWebSocketServer() {
if (_channel == null) {
throw Exception('No active WebSocket connection');
}
try {
_channel?.sink.close();
_channel = null;
print('Disconnected from WebSocket server');
return true;
} catch (e) {
print('Failed to disconnect from WebSocket server: $e');
return false;
}
}
bool sendMessage(String message) {
// If hosting a server, send message to all clients
if (_server != null) {
return sendMessageToClients(message);
}
if (_channel == null) {
throw Exception('No active WebSocket connection');
}
try {
_channel?.sink.add(message);
print('Sent message: $message');
return true;
} catch (e) {
print('Failed to send message: $e');
return false;
}
}
bool sendMessageToClients(String message) {
if (_connectedClients.isEmpty) {
print('No clients connected');
return false;
}
try {
for (var client in _connectedClients) {
client.sink.add(message);
}
print('Sent message to all clients: $message');
return true;
} catch (e) {
print('Failed to send message to clients: $e');
return false;
}
}
void _onMessageReceived(String message) {
// Notify all listeners that a message has been received.
onMessageReceived?.trigger(message);
}
// Useful boilerplate
String _localIP = "";
String get localIP => _localIP;
Timer refreshTimer() => Timer.periodic(const Duration(seconds: 10), (timer) {
if (kIsWeb) return;
_refresh();
});
Future<void> _refresh() async {
print("Refreshing network info...");
{
// Update the local IP address
// First try NetworkInfo
_localIP = (await NetworkInfo().getWifiIP()) ?? "";
// If null, try NetworkInterface
// Only look for ethernet. Wifi would have been found by NetworkInfo
if (_localIP.isEmpty) {
for (var interface in await NetworkInterface.list()) {
if (!interface.name.toLowerCase().contains("eth") || interface.name.contains(" ")) {
continue;
}
for (var addr in interface.addresses) {
print('Interface ${interface.name} has address ${addr.address}');
if (addr.type == InternetAddressType.IPv4 && !addr.isLoopback) {
_localIP = addr.address;
break;
}
}
}
}
}
}
}