feat: Add device info handling and improve UI for telemetry settings

This commit is contained in:
Janez T
2025-10-14 21:20:00 +02:00
parent 9238be1a59
commit 2cb6c34167
2 changed files with 120 additions and 32 deletions

View File

@@ -133,6 +133,29 @@ class ConnectionProvider with ChangeNotifier {
onLoginFail?.call(publicKeyPrefix); onLoginFail?.call(publicKeyPrefix);
}; };
_bleService.onDeviceInfoReceived = (deviceInfo) {
print('📥 [Provider] Received DeviceInfo:');
print(' Firmware Version: ${deviceInfo['firmwareVersion']}');
print(' Max Contacts: ${deviceInfo['maxContacts']}');
print(' Max Channels: ${deviceInfo['maxChannels']}');
print(' BLE PIN: ${deviceInfo['blePin']}');
print(' Build Date: ${deviceInfo['firmwareBuildDate']}');
print(' Model: ${deviceInfo['manufacturerModel']}');
print(' Version: ${deviceInfo['semanticVersion']}');
_deviceInfo = _deviceInfo.copyWith(
firmwareVersion: deviceInfo['firmwareVersion'] as int?,
maxContacts: deviceInfo['maxContacts'] as int?,
maxChannels: deviceInfo['maxChannels'] as int?,
blePin: deviceInfo['blePin'] as int?,
firmwareBuildDate: deviceInfo['firmwareBuildDate'] as String?,
manufacturerModel: deviceInfo['manufacturerModel'] as String?,
semanticVersion: deviceInfo['semanticVersion'] as String?,
);
notifyListeners();
print('✅ [Provider] Device info updated with DeviceInfo');
};
_bleService.onSelfInfoReceived = (selfInfo) { _bleService.onSelfInfoReceived = (selfInfo) {
print('📥 [Provider] Received SelfInfo:'); print('📥 [Provider] Received SelfInfo:');
print(' TX Power: ${selfInfo['txPower']} / ${selfInfo['maxTxPower']} dBm'); print(' TX Power: ${selfInfo['txPower']} / ${selfInfo['maxTxPower']} dBm');

View File

@@ -294,10 +294,13 @@ class _DeviceConfigScreenState extends State<DeviceConfigScreen> {
_InfoRow('BLE Name', deviceInfo.deviceName ?? 'Unknown'), _InfoRow('BLE Name', deviceInfo.deviceName ?? 'Unknown'),
_InfoRow('Mesh Name', deviceInfo.selfName ?? 'Not set'), _InfoRow('Mesh Name', deviceInfo.selfName ?? 'Not set'),
_InfoRow('Type', _getDeviceTypeString(deviceInfo.deviceType)), _InfoRow('Type', _getDeviceTypeString(deviceInfo.deviceType)),
_InfoRow('Firmware', deviceInfo.firmwareVersion?.toString() ?? 'Unknown'), _InfoRow('Model', deviceInfo.manufacturerModel ?? 'Unknown'),
_InfoRow('Version', deviceInfo.semanticVersion ?? 'Unknown'),
_InfoRow('Build Date', deviceInfo.firmwareBuildDate ?? 'Unknown'),
_InfoRow('Firmware', 'v${deviceInfo.firmwareVersion?.toString() ?? "?"}'),
_InfoRow('Max Contacts', deviceInfo.maxContacts?.toString() ?? 'Unknown'), _InfoRow('Max Contacts', deviceInfo.maxContacts?.toString() ?? 'Unknown'),
_InfoRow('Max Channels', deviceInfo.maxChannels?.toString() ?? 'Unknown'), _InfoRow('Max Channels', deviceInfo.maxChannels?.toString() ?? 'Unknown'),
_InfoRow('Public Key', _getPublicKeyShort(deviceInfo.publicKey)), _CopyableInfoRow('Public Key', _getPublicKeyHex(deviceInfo.publicKey)),
], ],
), ),
), ),
@@ -339,31 +342,40 @@ class _DeviceConfigScreenState extends State<DeviceConfigScreen> {
helperText: 'Name broadcast in mesh advertisements', helperText: 'Name broadcast in mesh advertisements',
), ),
), ),
const SizedBox(height: 16), const SizedBox(height: 8),
// Telemetry Toggle // Telemetry Toggle - Compact version
SwitchListTile( Row(
title: const Text('Enable Telemetry & Location Sharing'), children: [
subtitle: const Text('Allow others to query your location and telemetry'), Expanded(
value: _telemetryEnabled, child: Text(
onChanged: (value) { 'Telemetry & Location Sharing',
setState(() { style: theme.textTheme.bodyMedium,
_telemetryEnabled = value; ),
}); ),
}, Switch(
value: _telemetryEnabled,
onChanged: (value) {
setState(() {
_telemetryEnabled = value;
});
},
),
],
), ),
const SizedBox(height: 16),
// GPS Coordinates (only show if telemetry enabled) // GPS Coordinates (only show if telemetry enabled)
if (_telemetryEnabled) ...[ if (_telemetryEnabled) ...[
const SizedBox(height: 12),
Row( Row(
children: [ children: [
Expanded( Expanded(
child: TextField( child: TextField(
controller: _latController, controller: _latController,
decoration: const InputDecoration( decoration: const InputDecoration(
labelText: 'Latitude', labelText: 'Lat',
border: OutlineInputBorder(), border: OutlineInputBorder(),
isDense: true,
), ),
keyboardType: const TextInputType.numberWithOptions( keyboardType: const TextInputType.numberWithOptions(
decimal: true, decimal: true,
@@ -371,13 +383,14 @@ class _DeviceConfigScreenState extends State<DeviceConfigScreen> {
), ),
), ),
), ),
const SizedBox(width: 16), const SizedBox(width: 8),
Expanded( Expanded(
child: TextField( child: TextField(
controller: _lonController, controller: _lonController,
decoration: const InputDecoration( decoration: const InputDecoration(
labelText: 'Longitude', labelText: 'Lon',
border: OutlineInputBorder(), border: OutlineInputBorder(),
isDense: true,
), ),
keyboardType: const TextInputType.numberWithOptions( keyboardType: const TextInputType.numberWithOptions(
decimal: true, decimal: true,
@@ -385,17 +398,14 @@ class _DeviceConfigScreenState extends State<DeviceConfigScreen> {
), ),
), ),
), ),
const SizedBox(width: 8),
IconButton.filled(
onPressed: _useCurrentLocation,
icon: const Icon(Icons.my_location, size: 20),
tooltip: 'Use current location',
),
], ],
), ),
const SizedBox(height: 12),
ElevatedButton.icon(
onPressed: _useCurrentLocation,
icon: const Icon(Icons.my_location),
label: const Text('Use Current Location'),
style: ElevatedButton.styleFrom(
minimumSize: const Size(double.infinity, 48),
),
),
], ],
], ],
), ),
@@ -542,13 +552,9 @@ class _DeviceConfigScreenState extends State<DeviceConfigScreen> {
} }
} }
String _getPublicKeyShort(List<int>? publicKey) { String _getPublicKeyHex(List<int>? publicKey) {
if (publicKey == null || publicKey.isEmpty) return 'N/A'; if (publicKey == null || publicKey.isEmpty) return 'N/A';
final hex = publicKey.map((b) => b.toRadixString(16).padLeft(2, '0')).join(''); return publicKey.map((b) => b.toRadixString(16).padLeft(2, '0')).join('');
if (hex.length >= 16) {
return '${hex.substring(0, 8)}...${hex.substring(hex.length - 8)}';
}
return hex;
} }
} }
@@ -588,3 +594,62 @@ class _InfoRow extends StatelessWidget {
); );
} }
} }
class _CopyableInfoRow extends StatelessWidget {
final String label;
final String value;
const _CopyableInfoRow(this.label, this.value);
@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.symmetric(vertical: 4),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(
width: 120,
child: Text(
label,
style: const TextStyle(
fontWeight: FontWeight.w500,
color: Colors.grey,
),
),
),
Expanded(
child: GestureDetector(
onTap: () {
Clipboard.setData(ClipboardData(text: value));
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text('Copied $label to clipboard'),
duration: const Duration(seconds: 2),
backgroundColor: Colors.green,
),
);
},
child: Row(
children: [
Expanded(
child: Text(
value,
style: const TextStyle(
fontWeight: FontWeight.w600,
fontFamily: 'monospace',
),
overflow: TextOverflow.ellipsis,
),
),
const SizedBox(width: 8),
const Icon(Icons.copy, size: 16, color: Colors.grey),
],
),
),
),
],
),
);
}
}