Setup code works with new version

This commit is contained in:
2025-12-23 17:22:50 -06:00
parent bd9ce4022f
commit 3215702893
5 changed files with 89 additions and 21 deletions

View File

@@ -54,7 +54,13 @@
<key>NSAllowsLocalNetworking</key>
<true/>
</dict>
<key>NSLocalNetworkUsageDescription</key>
<string>This app uses the local network for debugging and development.</string>
<string>Allow the app to find and connect to the Dart VM for debugging purposes.</string>
<key>NSBonjourServices</key>
<array>
<string>_dartvm._tcp</string>
</array>
</dict>
</plist>

View File

@@ -8,7 +8,7 @@ import 'package:socket_io_client/socket_io_client.dart' as IO;
String local = Platform.isAndroid ? '10.0.2.2' : 'localhost';
String fromDevice = '192.168.1.190';
String host = local;
String host = fromDevice;
int port = 3000;
String socketString = "$scheme://$host:$port";
String scheme = 'http';

View File

@@ -123,7 +123,8 @@ class _AddDeviceState extends State<AddDevice> {
}
Widget _buildScanResultTiles() {
final res = _scanResults.where((r) => r.advertisementData.advName == "BlindMaster Device" && r.rssi > -55);
// final res = _scanResults.where((r) => r.advertisementData.advName == "BlindMaster Device" && r.rssi > -55);
final res = _scanResults.where((r) => r.advertisementData.advName == "BlindMaster-C6");
return (res.isNotEmpty)
? ListView(
children: [

View File

@@ -44,6 +44,7 @@ class DeviceSetup extends StatefulWidget {
}
class _DeviceSetupState extends State<DeviceSetup> {
bool refreshing = false;
List<BluetoothService> _services = [];
List<Map<String, dynamic>> networks = [];
@@ -82,7 +83,8 @@ class _DeviceSetupState extends State<DeviceSetup> {
try {
final val = utf8.decode(rawData);
networks = json.decode(val) as List<Map<String, dynamic>>;
final decoded = json.decode(val) as List;
networks = decoded.map((e) => e as Map<String, dynamic>).toList();
} catch (e) {
if(!mounted)return;
ScaffoldMessenger.of(context).showSnackBar(errorSnackbar(e));
@@ -118,6 +120,12 @@ class _DeviceSetupState extends State<DeviceSetup> {
],
);
});
try {
await ssidRefreshChar.write(utf8.encode("Done"), withoutResponse: ssidRefreshChar.properties.writeWithoutResponse);
} catch (e) {
throw Exception ("Handshake Termination Error. Restart setup process.");
}
refreshing = false;
}
} catch (e) {
if(!mounted)return;
@@ -242,7 +250,9 @@ class _DeviceSetupState extends State<DeviceSetup> {
),
TextButton(
onPressed: () {
Navigator.pop(dialogContext, passControl.text);
Navigator.pop(dialogContext, (ent ?
{"uname": unameControl.text, "password": passControl.text}
: (open ? {} : {"password": passControl.text})));
passControl.clear();
unameControl.clear();
},
@@ -286,7 +296,8 @@ class _DeviceSetupState extends State<DeviceSetup> {
}
final connectConfirmChar = _services[0].characteristics.lastWhere((c) => c.uuid.str == "0005");
final tokenEntryChar = _services[0].characteristics.lastWhere((c) => c.uuid.str == "0003");
final tokenEntryChar = _services[0].characteristics.lastWhere((c) => c.uuid.str == "0002");
final authConfirmChar = _services[0].characteristics.lastWhere((c) => c.uuid.str == "0003");
await connectConfirmChar.setNotifyValue(true);
_confirmSub = connectConfirmChar.onValueReceived.listen((List<int> connectVal) {
try {
@@ -297,7 +308,7 @@ class _DeviceSetupState extends State<DeviceSetup> {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => SetDeviceName(tokenEntryChar: tokenEntryChar, device: widget.device),
builder: (context) => SetDeviceName(tokenEntryChar: tokenEntryChar, authConfirmChar: authConfirmChar, device: widget.device),
)
).then((_) {
if (widget.device.isConnected) {
@@ -318,6 +329,8 @@ class _DeviceSetupState extends State<DeviceSetup> {
}
Future refreshWifiList() async{
if (refreshing) return;
refreshing = true;
final ssidRefreshChar = _services[0].characteristics.lastWhere((c) => c.uuid.str == "0004");
setState(() {
wifiList = null;

View File

@@ -1,3 +1,4 @@
import 'dart:async';
import 'dart:convert';
import 'package:blind_master/BlindMasterResources/error_snackbar.dart';
@@ -10,8 +11,9 @@ import 'package:flutter_blue_plus/flutter_blue_plus.dart';
import 'package:google_fonts/google_fonts.dart';
class SetDeviceName extends StatefulWidget {
const SetDeviceName({super.key, required this.tokenEntryChar, required this.device});
const SetDeviceName({super.key, required this.tokenEntryChar, required this.authConfirmChar, required this.device});
final BluetoothCharacteristic tokenEntryChar;
final BluetoothCharacteristic authConfirmChar;
final BluetoothDevice device;
@override
@@ -21,6 +23,7 @@ class SetDeviceName extends StatefulWidget {
class _SetDeviceNameState extends State<SetDeviceName> {
final deviceNameController = TextEditingController();
Widget? screen;
StreamSubscription<List<int>>? _authSub;
@override
void initState() {
@@ -30,6 +33,7 @@ class _SetDeviceNameState extends State<SetDeviceName> {
@override
void dispose() {
_authSub?.cancel();
deviceNameController.dispose();
super.dispose();
}
@@ -75,6 +79,48 @@ class _SetDeviceNameState extends State<SetDeviceName> {
return;
}
// Set up authentication confirmation listener
try {
await widget.authConfirmChar.setNotifyValue(true);
} catch (e) {
if (!mounted) return;
ScaffoldMessenger.of(context).showSnackBar(errorSnackbar(Exception("Failed to set up authentication listener")));
return;
}
_authSub = widget.authConfirmChar.onValueReceived.listen((List<int> authVal) async {
try {
final authResponse = utf8.decode(authVal);
if (authResponse == "Authenticated") {
if (!mounted) return;
_authSub?.cancel();
await widget.device.disconnectAndUpdateStream().catchError((e) {
if(!mounted) return;
ScaffoldMessenger.of(context).showSnackBar(errorSnackbar(e));
});
if (!mounted) return;
Navigator.pushAndRemoveUntil(
context,
MaterialPageRoute(builder: (context) => HomeScreen()),
(route) => false,
);
} else if (authResponse == "Error") {
_authSub?.cancel();
throw Exception("Authentication failed. Please try again.");
}
} catch (e) {
if (!mounted) return;
ScaffoldMessenger.of(context).showSnackBar(errorSnackbar(e));
setState(() {
initScreen();
});
return;
}
});
// Write the token
try {
try {
await widget.tokenEntryChar.write(utf8.encode(token), withoutResponse: widget.tokenEntryChar.properties.writeWithoutResponse);
@@ -84,20 +130,12 @@ class _SetDeviceNameState extends State<SetDeviceName> {
} catch (e){
if(!mounted)return;
ScaffoldMessenger.of(context).showSnackBar(errorSnackbar(e));
_authSub?.cancel();
setState(() {
initScreen();
});
return;
}
await widget.device.disconnectAndUpdateStream().catchError((e) {
if(!mounted) return;
ScaffoldMessenger.of(context).showSnackBar(errorSnackbar(e));
});
if (!mounted) return;
Navigator.pushAndRemoveUntil(
context,
MaterialPageRoute(builder: (context) => HomeScreen()),
(route) => false,
);
}
Future onPressed() async {
@@ -120,7 +158,17 @@ class _SetDeviceNameState extends State<SetDeviceName> {
body: SizedBox(
height: MediaQuery.of(context).size.height * 0.6,
child: Center(
child: screen ?? CircularProgressIndicator(color: Theme.of(context).primaryColorLight),
child: screen ?? Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
CircularProgressIndicator(color: Theme.of(context).primaryColorLight),
SizedBox(height: 10),
Text(
"Authenticating device...",
textAlign: TextAlign.center,
),
],
),
)
)
);