should have push notifs as well as Battery SOC monitoring

This commit is contained in:
2026-03-09 02:31:49 -05:00
parent 8776fe9679
commit ea0326394f
22 changed files with 354 additions and 16 deletions

View File

@@ -1,3 +1,4 @@
import 'package:blind_master/BlindMasterResources/fcm_service.dart';
import 'package:blind_master/BlindMasterResources/secure_transmissions.dart';
import 'package:blind_master/BlindMasterScreens/Startup/create_user_screen.dart';
import 'package:blind_master/BlindMasterScreens/Startup/forgot_password_screen.dart';
@@ -84,6 +85,7 @@ class _LoginScreenState extends State<LoginScreen> {
if (token.isEmpty) throw Exception('Token Not Received');
final storage = FlutterSecureStorage();
await storage.write(key: 'token', value: token);
await FcmService.register();
} catch(e) {
if (!mounted) return;

View File

@@ -1,6 +1,7 @@
import 'dart:async';
import 'dart:convert';
import 'package:blind_master/BlindMasterResources/fcm_service.dart';
import 'package:blind_master/BlindMasterResources/secure_transmissions.dart';
import 'package:blind_master/BlindMasterScreens/home_screen.dart';
import 'package:blind_master/BlindMasterScreens/Startup/login_screen.dart';
@@ -50,6 +51,7 @@ class _SplashScreenState extends State<SplashScreen> {
}
nextScreen = HomeScreen();
await FcmService.register();
} else {
nextScreen = LoginScreen();
}

View File

@@ -121,7 +121,7 @@ abstract class BaseVerificationWaitingScreenState<T extends BaseVerificationWait
child: ListView(
physics: AlwaysScrollableScrollPhysics(),
children: [
Container(
SizedBox(
height: MediaQuery.of(context).size.height,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,

View File

@@ -24,6 +24,7 @@ class _DeviceScreenState extends State<DeviceScreen> {
List occports = [];
Widget? peripheralList;
String deviceName = "...";
int? batterySoc;
@override
void initState() {
@@ -48,7 +49,8 @@ class _DeviceScreenState extends State<DeviceScreen> {
final body = json.decode(response.body) as Map<String, dynamic>;
setState(() {
deviceName = body['device_name'];
});
batterySoc = body['battery_soc'] as int?;
});
}
} catch (e) {
if (!mounted) return;
@@ -355,12 +357,30 @@ class _DeviceScreenState extends State<DeviceScreen> {
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(
deviceName,
style: GoogleFonts.aBeeZee(),
),
title: Text(deviceName, style: GoogleFonts.aBeeZee()),
backgroundColor: Theme.of(context).primaryColorLight,
foregroundColor: Colors.white,
actions: [
if (batterySoc != null)
Padding(
padding: const EdgeInsets.symmetric(horizontal: 16),
child: Row(
children: [
Icon(
batterySoc! <= 10 ? Icons.battery_alert
: batterySoc! <= 20 ? Icons.battery_1_bar
: batterySoc! <= 40 ? Icons.battery_2_bar
: batterySoc! <= 60 ? Icons.battery_3_bar
: batterySoc! <= 80 ? Icons.battery_5_bar
: Icons.battery_full,
color: batterySoc! <= 10 ? Colors.red : Colors.white,
),
const SizedBox(width: 4),
Text('$batterySoc%', style: const TextStyle(color: Colors.white)),
],
),
),
],
),
body: peripheralList ?? SizedBox(
height: MediaQuery.of(context).size.height * 0.8,

View File

@@ -124,6 +124,27 @@ class _PeripheralScreenState extends State<PeripheralScreen> {
}
});
socket?.on("battery_alert", (data) {
if (data is! Map<String, dynamic>) return;
if (data['deviceId'] != widget.deviceId) return;
if (!mounted) return;
final type = data['type'] as String? ?? '';
final soc = data['soc'] as int? ?? 0;
final (String message, Color color) = switch (type) {
'overvoltage' => ('Battery fault detected. Please check your charger.', Colors.red),
'critical_low' => ('Battery critically low ($soc%). Device shutting down.', Colors.red),
'low_voltage_warning' => ('Battery voltage dip detected ($soc%). Monitor closely.', Colors.orange),
'low_20' => ('Battery low: $soc% remaining. Consider charging soon.', Colors.orange),
'low_10' => ('Battery very low: $soc% remaining. Charge now.', Colors.deepOrange),
_ => ('Battery alert received ($soc%).', Colors.orange),
};
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
content: Text(message),
backgroundColor: color,
duration: const Duration(seconds: 6),
));
});
socket?.on("calib", (periphData) {
if (periphData is Map<String, dynamic>) {
if (periphData['periphID'] == widget.peripheralId) {