desktop push
This commit is contained in:
@@ -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;
|
||||
|
||||
196
lib/backend/modules/networking.dart
Normal file
196
lib/backend/modules/networking.dart
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user