Merge pull request #11 from oob-provisioning-for-iot/justin
Merging to have a usable version
This commit is contained in:
commit
449c0c73c7
|
@ -56,7 +56,7 @@ jobs:
|
|||
name: Android APK
|
||||
path: |
|
||||
build/app/outputs/flutter-apk/app-release.apk
|
||||
build/app/outputs/flutter-apk/app-release.sha1
|
||||
build/app/outputs/flutter-apk/app-release.apk.sha1
|
||||
|
||||
- name: Upload APK as release
|
||||
uses: "marvinpinto/action-automatic-releases@latest"
|
||||
|
@ -67,4 +67,4 @@ jobs:
|
|||
title: "Android APK"
|
||||
files: |
|
||||
build/app/outputs/flutter-apk/app-release.apk
|
||||
build/app/outputs/flutter-apk/app-release.sha1
|
||||
build/app/outputs/flutter-apk/app-release.apk.sha1
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
buildscript {
|
||||
ext.kotlin_version = '1.6.10'
|
||||
ext.kotlin_version = '1.7.20'
|
||||
repositories {
|
||||
google()
|
||||
mavenCentral()
|
||||
|
|
|
@ -17,7 +17,9 @@ class BluetoothDeviceEntry extends ListTile {
|
|||
onTap: onTap,
|
||||
onLongPress: onLongPress,
|
||||
enabled: enabled,
|
||||
leading: Icon(bluetoothObject.isConnected ? Icons.bluetooth_connected : Icons.bluetooth),
|
||||
leading: bluetoothObject.isConnected
|
||||
? const Icon(Icons.bluetooth_connected, color: Colors.blue)
|
||||
: const Icon(Icons.bluetooth),
|
||||
title: Text(bluetoothObject.name),
|
||||
subtitle: Text(bluetoothObject.address.toString()),
|
||||
trailing: Row(
|
||||
|
|
|
@ -16,15 +16,16 @@ class BluetoothObject {
|
|||
|
||||
String id = "";
|
||||
String _primaryThumbprint = "";
|
||||
String _secondaryThumbprint = "";
|
||||
final String _secondaryThumbprint = "";
|
||||
|
||||
late BluetoothConnection? _connection;
|
||||
late Stream<Uint8List> _connectionStream;
|
||||
late StreamSubscription<Uint8List> _connectionStreamSubscription;
|
||||
late BuildContext _context;
|
||||
|
||||
CloudServiceAPI _cloudServiceAPI = CloudServiceAPI();
|
||||
final CloudServiceAPI _cloudServiceAPI = CloudServiceAPI();
|
||||
|
||||
late Uint8List _messageBufferBits;
|
||||
//late Uint8List _messageBufferBits;
|
||||
late String _messageBufferChars = "";
|
||||
|
||||
bool _isDisconnecting = false;
|
||||
|
@ -69,7 +70,7 @@ class BluetoothObject {
|
|||
_connection = null;
|
||||
}
|
||||
|
||||
Future<void> bondDevice() async {
|
||||
Future<void> bondDevice(BuildContext context) async {
|
||||
try {
|
||||
bool bonded = false;
|
||||
if (_device.isBonded) {
|
||||
|
@ -81,22 +82,7 @@ class BluetoothObject {
|
|||
bonded = (await FlutterBluetoothSerial.instance.bondDeviceAtAddress(_address))!;
|
||||
debugPrint('Bonding with $_address has ${bonded ? 'succed' : 'failed'}.');
|
||||
}
|
||||
/*setState(() {
|
||||
_discoveryResults[_discoveryResults.indexOf(
|
||||
result)] =
|
||||
BluetoothDiscoveryResult(
|
||||
device: BluetoothDevice(
|
||||
name: device.name ?? '',
|
||||
address: address,
|
||||
type: device.type,
|
||||
bondState: bonded
|
||||
? BluetoothBondState.bonded
|
||||
: BluetoothBondState.none,
|
||||
),
|
||||
rssi: result.rssi);
|
||||
});*/
|
||||
} catch (ex) {
|
||||
/*
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (BuildContext context) {
|
||||
|
@ -114,7 +100,7 @@ class BluetoothObject {
|
|||
],
|
||||
);
|
||||
},
|
||||
);*/
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -133,12 +119,15 @@ class BluetoothObject {
|
|||
_connection = null;
|
||||
}
|
||||
|
||||
_connection = await BluetoothConnection.toAddress(_address);
|
||||
debugPrint("Connected to the device");
|
||||
|
||||
_connectionStream = _connection!.input!;
|
||||
_connectionStreamSubscription = _connectionStream.listen(_connectionOnListen);
|
||||
_connectionStreamSubscription.onDone(_connectionOnDone);
|
||||
try {
|
||||
_connection = await BluetoothConnection.toAddress(_address);
|
||||
debugPrint("Connected to the device");
|
||||
_connectionStream = _connection!.input!;
|
||||
_connectionStreamSubscription = _connectionStream.listen(_connectionOnListen);
|
||||
_connectionStreamSubscription.onDone(_connectionOnDone);
|
||||
} catch (ex) {
|
||||
debugPrint("$ex");
|
||||
}
|
||||
}
|
||||
|
||||
void _connectionOnDone() {
|
||||
|
@ -151,113 +140,58 @@ class BluetoothObject {
|
|||
|
||||
Future<void> _connectionOnListen(Uint8List data) async {
|
||||
final String dataDecoded = const AsciiDecoder().convert(data);
|
||||
|
||||
debugPrint("received: $data");
|
||||
debugPrint("received decoded: $dataDecoded");
|
||||
|
||||
_messageBufferChars += dataDecoded;
|
||||
|
||||
if (data[data.length - 1] == 10) {
|
||||
debugPrint("received buffer: $_messageBufferChars");
|
||||
int spaceIndex = _messageBufferChars.indexOf(" ");
|
||||
String firstParameter = "";
|
||||
String secondParameter = "";
|
||||
try {
|
||||
firstParameter = _messageBufferChars.substring(0, spaceIndex);
|
||||
secondParameter = _messageBufferChars.substring(spaceIndex + 1, _messageBufferChars.length - 2);
|
||||
} catch (ex) {
|
||||
debugPrint(ex.toString());
|
||||
}
|
||||
debugPrint("we still go on!");
|
||||
if (!(data[data.length - 1] == 10)) {
|
||||
return;
|
||||
}
|
||||
if (!_messageBufferChars.contains(" ")) {
|
||||
_messageBufferChars = "";
|
||||
debugPrint("first: $firstParameter");
|
||||
debugPrint("second: $secondParameter");
|
||||
if (firstParameter == "fingerprint") {
|
||||
debugPrint("received final buffer: $secondParameter");
|
||||
_primaryThumbprint = secondParameter;
|
||||
debugPrint("{ _secondaryThumbprint: $_secondaryThumbprint }");
|
||||
debugPrint("{ id: $id, _primaryThumbprint: $_primaryThumbprint, _secondaryThumbprint: $_secondaryThumbprint }");
|
||||
await _registerDevice();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
// Allocate buffer for parsed data
|
||||
int backspacesCounter = 0;
|
||||
for (var byte in data) {
|
||||
if (byte == 8 || byte == 127) {
|
||||
backspacesCounter++;
|
||||
}
|
||||
List<String> input = _messageBufferChars.split(" ");
|
||||
if (input[0] == "fingerprint") {
|
||||
_primaryThumbprint = input[1].trim();
|
||||
debugPrint("_primaryThumbprint: ${const AsciiEncoder().convert(_primaryThumbprint)}");
|
||||
debugPrint("id: ${const AsciiEncoder().convert(id)}");
|
||||
debugPrint("_secondaryThumbprint: $_secondaryThumbprint");
|
||||
await _registerDevice();
|
||||
}
|
||||
Uint8List buffer = Uint8List(data.length - backspacesCounter);
|
||||
int bufferIndex = buffer.length;
|
||||
|
||||
// Apply backspace control character
|
||||
backspacesCounter = 0;
|
||||
for (int i = data.length - 1; i >= 0; i--) {
|
||||
if (data[i] == 8 || data[i] == 127) {
|
||||
backspacesCounter++;
|
||||
} else {
|
||||
if (backspacesCounter > 0) {
|
||||
backspacesCounter--;
|
||||
} else {
|
||||
buffer[--bufferIndex] = data[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Create message if there is new line character
|
||||
String dataString = String.fromCharCodes(buffer);
|
||||
int index = buffer.indexOf(13);
|
||||
if (~index != 0) {
|
||||
_messageBuffer = dataString.substring(index);
|
||||
} else {
|
||||
_messageBuffer = (backspacesCounter > 0
|
||||
? _messageBuffer.substring(0, _messageBuffer.length - backspacesCounter)
|
||||
: _messageBuffer + dataString);
|
||||
}
|
||||
*/
|
||||
_messageBufferChars = "";
|
||||
}
|
||||
|
||||
Future<void> sendData(String output) async {
|
||||
Future<void> sendData(BuildContext context, String output) async {
|
||||
if (_connection == null) return;
|
||||
bool nameAvailable = await _cloudServiceAPI.checkNameAvailability(output);
|
||||
// String output = "0123456789 abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ";// !§%&()=?#!?";
|
||||
// String output = "myDevice123";// !§%&()=?#!?";
|
||||
if (!nameAvailable) return;
|
||||
id = output;
|
||||
_connection!.output.add(Uint8List.fromList(const AsciiEncoder().convert("$output \r\n")));
|
||||
await _connection!.output.allSent;
|
||||
_context = context;
|
||||
debugPrint("sent: $output");
|
||||
}
|
||||
|
||||
Future<void> _registerDevice() async {
|
||||
bool registered = false;
|
||||
registered = await _cloudServiceAPI.createDevice(id, _primaryThumbprint, "");
|
||||
_confirmRegistration(registered);
|
||||
}
|
||||
|
||||
String statusText =
|
||||
registered ? "das Gerät wurde erfolgreich registriert" : "das Gerät konnte nicht registriert werden";
|
||||
Fluttertoast.showToast(
|
||||
msg: statusText,
|
||||
toastLength: Toast.LENGTH_SHORT,
|
||||
gravity: ToastGravity.BOTTOM,
|
||||
timeInSecForIosWeb: 2,
|
||||
backgroundColor: Colors.grey[200],
|
||||
textColor: Colors.black,
|
||||
fontSize: 16.0);
|
||||
void _confirmRegistration(bool registered) {
|
||||
showDialog<String>(
|
||||
context: _context,
|
||||
builder: (BuildContext context) => AlertDialog(
|
||||
title: const Text('Device Info'),
|
||||
content: Text(registered ? "das Gerät wurde erfolgreich registriert" : "das Gerät konnte nicht registriert werden"),
|
||||
backgroundColor: Colors.white,
|
||||
actions: <Widget>[
|
||||
TextButton(onPressed: () => Navigator.pop(context, 'Cancel'),
|
||||
child: const Text('OK'),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/*setState(() {
|
||||
_discoveryResults[_discoveryResults.indexOf(
|
||||
result)] =
|
||||
BluetoothDiscoveryResult(
|
||||
device: BluetoothDevice(
|
||||
name: device.name ?? '',
|
||||
address: address,
|
||||
type: device.type,
|
||||
isConnected: connected,
|
||||
),
|
||||
rssi: result.rssi);
|
||||
});
|
||||
*/
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import 'dart:convert';
|
||||
import 'dart:developer';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:fluttertoast/fluttertoast.dart';
|
||||
|
@ -24,6 +23,7 @@ class CloudServiceAPI {
|
|||
static String _password = "";
|
||||
static late Map<String, String> _headers;
|
||||
static bool _initState = false;
|
||||
static List<DeviceModel> devices = List<DeviceModel>.empty(growable: true);
|
||||
|
||||
CloudServiceAPI() {
|
||||
if (!_initState) {
|
||||
|
@ -44,6 +44,7 @@ class CloudServiceAPI {
|
|||
'accept': 'application/json',
|
||||
};
|
||||
log("init Config $_headers");
|
||||
await updateDeviceList();
|
||||
}
|
||||
|
||||
Future<void> reloadConfig() async {
|
||||
|
@ -64,7 +65,6 @@ class CloudServiceAPI {
|
|||
List<DeviceModel> remoteObjectsList = remoteObjectsMap.toList();
|
||||
return remoteObjectsList;
|
||||
}
|
||||
|
||||
Future<DeviceInfoModel> getDeviceInfo(String deviceID) async {
|
||||
Uri url = Uri.https(_address, '/api/devices/$deviceID');
|
||||
Response response = await get(url, headers: _headers);
|
||||
|
@ -72,12 +72,31 @@ class CloudServiceAPI {
|
|||
DeviceInfoModel deviceInfoModel = DeviceInfoModel.fromJson(jsonObject);
|
||||
return deviceInfoModel;
|
||||
}
|
||||
Future<List<DeviceInfoModel>> getDevicesInfo() async {
|
||||
updateDeviceList();
|
||||
List<DeviceInfoModel> deviceInfoModelList = List<DeviceInfoModel>.empty(growable: true);
|
||||
for(DeviceModel tmp in devices){
|
||||
deviceInfoModelList.add(await getDeviceInfo(tmp.id));
|
||||
}
|
||||
return deviceInfoModelList;
|
||||
}
|
||||
Future updateDeviceList() async {
|
||||
devices = await getDevices();
|
||||
}
|
||||
|
||||
Future<Map<String, dynamic>> getInformation() async {
|
||||
Uri url = Uri.https(_address, '/api/app');
|
||||
Response response = await get(url, headers: _headers);
|
||||
return json.decode(response.body) as Map<String, dynamic>;
|
||||
}
|
||||
Future<bool> deleteDevice(String clientId) async {
|
||||
Uri url = Uri.https(_address, '/api/devices/$clientId');
|
||||
Response response = await delete(url, headers: _headers);
|
||||
if(response.statusCode == 204){
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
Future<bool> createDevice(String id, String primaryThumbprint, String secondaryThumbprint) async {
|
||||
Uri url = Uri.https(_address, '/api/devices');
|
||||
|
@ -114,7 +133,7 @@ class CloudServiceAPI {
|
|||
String statusText = status ? "die eingegebene ID ist verfügbar" : "die eingegebene ID ist nicht verfügbar";
|
||||
Fluttertoast.showToast(
|
||||
msg: statusText,
|
||||
toastLength: Toast.LENGTH_SHORT,
|
||||
toastLength: Toast.LENGTH_LONG,
|
||||
gravity: ToastGravity.BOTTOM,
|
||||
timeInSecForIosWeb: 2,
|
||||
backgroundColor: Colors.grey[200],
|
||||
|
@ -148,4 +167,7 @@ class CloudServiceAPI {
|
|||
_password = input;
|
||||
reloadConfig();
|
||||
}
|
||||
List<dynamic> getLoadedDevices(){
|
||||
return devices;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,8 +14,8 @@ class BluetoothDeviceSettings extends StatefulWidget {
|
|||
|
||||
class BluetoothDeviceSettingsState extends State<BluetoothDeviceSettings> {
|
||||
late BluetoothObject _bluetoothObject;
|
||||
|
||||
String _messageBuffer = "";
|
||||
bool _isRegistering = false;
|
||||
String _textInput = ""; // 0123456789 abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
|
@ -23,9 +23,6 @@ class BluetoothDeviceSettingsState extends State<BluetoothDeviceSettings> {
|
|||
_bluetoothObject = widget.bluetoothObject;
|
||||
}
|
||||
|
||||
String _textInput = "0123456789 abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
||||
String _textOuput = "";
|
||||
|
||||
ButtonStyle buttonStyle = ElevatedButton.styleFrom(
|
||||
foregroundColor: Colors.black,
|
||||
backgroundColor: const Color(0xFFFDE100), // Text Color (Foreground color)
|
||||
|
@ -53,13 +50,13 @@ class BluetoothDeviceSettingsState extends State<BluetoothDeviceSettings> {
|
|||
),
|
||||
ListTile(
|
||||
title: const Text("Device Connection State"),
|
||||
subtitle:
|
||||
Text(_bluetoothObject.isConnected ? "ConnectionState.DISCONECTED" : "ConnectionState.CONNECED"),
|
||||
subtitle: Text(
|
||||
_bluetoothObject.isConnected ? "ConnectionState.DISCONNECTED" : "ConnectionState.CONNECTED"),
|
||||
),
|
||||
],
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16.0),
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 0.0),
|
||||
child: Row(mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [
|
||||
// const EdgeInsets defaultContentPadding = EdgeInsets.symmetric(horizontal: 16.0);
|
||||
Expanded(
|
||||
|
@ -85,35 +82,48 @@ class BluetoothDeviceSettingsState extends State<BluetoothDeviceSettings> {
|
|||
))
|
||||
])),
|
||||
const Divider(),
|
||||
ElevatedButton(
|
||||
onPressed: () async {
|
||||
_bluetoothObject.sendData(_textInput);
|
||||
},
|
||||
style: buttonStyle,
|
||||
child: const Text("Send Data"),
|
||||
),
|
||||
ElevatedButton(
|
||||
onPressed: () async {
|
||||
setState(() {
|
||||
_textOuput = "";
|
||||
});
|
||||
},
|
||||
style: buttonStyle,
|
||||
child: const Text("Clear Output"),
|
||||
),
|
||||
Text(_textOuput),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 16.0),
|
||||
child: TextField(
|
||||
decoration: const InputDecoration(
|
||||
border: OutlineInputBorder(),
|
||||
hintText: 'Enter the device name',
|
||||
SingleSection(title: "Cloud Registration", children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 0.0),
|
||||
child: TextFormField(
|
||||
obscureText: false,
|
||||
decoration: InputDecoration(
|
||||
border: const OutlineInputBorder(),
|
||||
hintText: 'Enter the device name',
|
||||
labelText: "Device Name",
|
||||
filled: false,
|
||||
suffixIcon: _isRegistering
|
||||
? FittedBox(
|
||||
child: Container(
|
||||
height: 10,
|
||||
width: 10,
|
||||
margin: const EdgeInsets.all(8.0),
|
||||
child: const CircularProgressIndicator(
|
||||
strokeWidth: 2.0,
|
||||
),
|
||||
),
|
||||
) // : const I
|
||||
: IconButton(
|
||||
icon: const Icon(Icons.login),
|
||||
onPressed: () async {
|
||||
FocusScopeNode currentFocus = FocusScope.of(context);
|
||||
currentFocus.unfocus();
|
||||
setState(() {
|
||||
_isRegistering = true;
|
||||
});
|
||||
await _bluetoothObject.sendData(context, _textInput);
|
||||
setState(() {
|
||||
_isRegistering = false;
|
||||
});
|
||||
},
|
||||
)),
|
||||
keyboardType: TextInputType.text,
|
||||
onChanged: (String newValue) {
|
||||
_textInput = newValue;
|
||||
},
|
||||
),
|
||||
onChanged: (String newValue) {
|
||||
_textInput = newValue;
|
||||
},
|
||||
),
|
||||
),
|
||||
]),
|
||||
]),
|
||||
]),
|
||||
));
|
||||
|
|
|
@ -50,21 +50,36 @@ class _BluetoothScreen extends State<BluetoothScreen> {
|
|||
_activeObject = null;
|
||||
_streamSubscription = null;
|
||||
if (widget.start) {
|
||||
_startDiscovery();
|
||||
_initAsync();
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _initAsync() async {
|
||||
await _enablePermissions();
|
||||
await _enableBluetooth();
|
||||
await _startDiscovery();
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
// Avoid memory leak (`setState` after dispose) and cancel discovery
|
||||
_streamSubscription?.cancel();
|
||||
_activeObject?.disconnectDevice();
|
||||
debugPrint("called dispose");
|
||||
_disposeAsync();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
Future<void> _disposeAsync() async {
|
||||
await _streamSubscription?.cancel();
|
||||
await _activeObject?.disconnectDevice();
|
||||
List<BluetoothDevice> bondedDevices = await FlutterBluetoothSerial.instance.getBondedDevices();
|
||||
debugPrint(bondedDevices.toString());
|
||||
super.dispose();
|
||||
debugPrint("called dispose");
|
||||
}
|
||||
|
||||
|
||||
|
||||
Future<void> _enablePermissions() async {
|
||||
debugPrint("Test");
|
||||
PermissionStatus bluetoothScan = await Permission.bluetoothScan.request();
|
||||
PermissionStatus bluetoothConnect = await Permission.bluetoothConnect.request();
|
||||
bool granted = bluetoothScan.isGranted && bluetoothConnect.isGranted;
|
||||
|
@ -74,7 +89,14 @@ class _BluetoothScreen extends State<BluetoothScreen> {
|
|||
}
|
||||
|
||||
Future<void> _enableBluetooth() async {
|
||||
if (!_enabledPermissions) {
|
||||
if (_enabledBluetooth) {
|
||||
return;
|
||||
}
|
||||
BluetoothState state = await FlutterBluetoothSerial.instance.state;
|
||||
if (state == BluetoothState.STATE_ON) {
|
||||
setState(() {
|
||||
_enabledBluetooth = true;
|
||||
});
|
||||
return;
|
||||
}
|
||||
bool? enabled = await FlutterBluetoothSerial.instance.requestEnable();
|
||||
|
@ -85,7 +107,8 @@ class _BluetoothScreen extends State<BluetoothScreen> {
|
|||
}
|
||||
|
||||
Future<void> _startDiscovery() async {
|
||||
if (!_enabledPermissions) {
|
||||
debugPrint("enabled: $_enabledPermissions");
|
||||
if (!_enabledPermissions && !_enabledBluetooth) {
|
||||
return;
|
||||
}
|
||||
setState(() => _isDiscovering = true);
|
||||
|
@ -137,9 +160,6 @@ class _BluetoothScreen extends State<BluetoothScreen> {
|
|||
_activeObject!.isConnected ? await bluetoothObject.disconnectDevice() : await bluetoothObject.connectDevice();
|
||||
}
|
||||
|
||||
//stty -F /dev/service 19200 parenb -parodd -cstopb cs8
|
||||
//cat /dev/service | xargs -n 1 /home/script/automaticcloud.sh
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
|
@ -173,6 +193,7 @@ class _BluetoothScreen extends State<BluetoothScreen> {
|
|||
CustomListTile(
|
||||
title: _enabledBluetooth ? "Bluetooth Enabled" : "Please Enable Bluetooth (click me)",
|
||||
icon: _enabledBluetooth ? Icons.check_circle_outline_rounded : Icons.info_outline_rounded,
|
||||
iconColor: _enabledPermissions ? Colors.green : Colors.red,
|
||||
onTap: () async {
|
||||
await _enableBluetooth();
|
||||
},
|
||||
|
@ -180,6 +201,7 @@ class _BluetoothScreen extends State<BluetoothScreen> {
|
|||
CustomListTile(
|
||||
title: _enabledPermissions ? "Permissions Granted" : "Please Grant Permissions (click me)",
|
||||
icon: _enabledPermissions ? Icons.check_circle_outline_rounded : Icons.info_outline_rounded,
|
||||
iconColor: _enabledPermissions ? Colors.green : Colors.red,
|
||||
onTap: () async {
|
||||
await _enablePermissions();
|
||||
},
|
||||
|
@ -193,38 +215,6 @@ class _BluetoothScreen extends State<BluetoothScreen> {
|
|||
),
|
||||
],
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16.0),
|
||||
child: Row(mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [
|
||||
// const EdgeInsets defaultContentPadding = EdgeInsets.symmetric(horizontal: 16.0);
|
||||
Expanded(
|
||||
child: ElevatedButton(
|
||||
onPressed: () async {
|
||||
/*await Permission.bluetoothConnect.request();
|
||||
await Permission.bluetoothScan.request();
|
||||
if (await Permission.bluetoothScan.request().isGranted) {
|
||||
// Either the permission was already granted before or the user just granted it.
|
||||
debugPrint("Location Permission is granted");
|
||||
} else {
|
||||
debugPrint("Location Permission is denied.");
|
||||
}*/
|
||||
},
|
||||
style: buttonStyle,
|
||||
child: const Text("Get BT Permissions"),
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 16.0),
|
||||
Expanded(
|
||||
child: ElevatedButton(
|
||||
onPressed: () async {
|
||||
_restartDiscovery();
|
||||
},
|
||||
style: buttonStyle,
|
||||
child: const Text("Restart Scan"),
|
||||
),
|
||||
)
|
||||
]),
|
||||
),
|
||||
const Divider(),
|
||||
SingleSection(
|
||||
title: "Bluetooth Devices",
|
||||
|
@ -252,9 +242,11 @@ class _BluetoothScreen extends State<BluetoothScreen> {
|
|||
bluetoothObject: bluetoothObject,
|
||||
onTap: () async {
|
||||
await _toggleConnection(bluetoothObject);
|
||||
await _restartDiscovery();
|
||||
},
|
||||
onLongPress: () async {
|
||||
await bluetoothObject.bondDevice();
|
||||
await bluetoothObject.bondDevice(context);
|
||||
await _restartDiscovery();
|
||||
},
|
||||
);
|
||||
},
|
||||
|
|
|
@ -1,61 +0,0 @@
|
|||
import 'dart:convert';
|
||||
import 'dart:developer';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
|
||||
import '../objects/cloud_service_api.dart';
|
||||
import '../widgets/sidebar.dart';
|
||||
|
||||
Future<Map<String, dynamic>> readJson() async {
|
||||
final String data = await rootBundle.loadString('config/credentials.json');
|
||||
final Map<String, dynamic> dataMap = json.decode(data);
|
||||
log("loaded json input $dataMap");
|
||||
return dataMap;
|
||||
}
|
||||
|
||||
class CloudService extends StatefulWidget {
|
||||
const CloudService({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
State<CloudService> createState() => _CloudService();
|
||||
}
|
||||
|
||||
class _CloudService extends State<CloudService> {
|
||||
late final Map<String, dynamic> credentials;
|
||||
CloudServiceAPI cloudServiceAPI = CloudServiceAPI();
|
||||
static SharedPreferences? preferencesInstance;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: const Text("Cloud Service"),
|
||||
),
|
||||
body: Center(
|
||||
child: TextButton(
|
||||
onPressed: () async {
|
||||
// List<BluetoothObjectRemote> respond1 = await cloudServiceAPI.getDevices();
|
||||
// debugPrint('Devices: ${respond1[0].toString()}');
|
||||
// debugPrint('Devices: ${respond1[0].toString()}');
|
||||
|
||||
//dynamic respond2 = await cloudServiceAPI.getInformation();
|
||||
//debugPrint('Information: ${respond2.toString()}');
|
||||
|
||||
// dynamic respond3 = await cloudServiceAPI.createDevice('1', 'asdas', 'sdwe1');
|
||||
// debugPrint('CreateDevice: ${respond3.toString()}');*/
|
||||
|
||||
//dynamic respond4 = await cloudServiceAPI.getDeviceInfo("PFC200V3-430EB3");
|
||||
//debugPrint('Information: ${respond4.toString()}');
|
||||
|
||||
//bool respond5 = await cloudServiceAPI.createDevice("PFC200V3-430EB2", "60987668030DF277AD7706D7C1FA683F37230D202A80EE5135B05EF928E3BF88", "");
|
||||
//debugPrint('Information: ${respond5.toString()}');
|
||||
},
|
||||
child: const Text("Example"),
|
||||
),
|
||||
),
|
||||
drawer: const Sidebar(),
|
||||
);
|
||||
}
|
||||
}
|
|
@ -63,6 +63,21 @@ class _RegisteredDevicesScreen extends State<RegisteredDevicesScreen> {
|
|||
super.initState();
|
||||
}
|
||||
|
||||
Future searchDevice(String clientId) async {
|
||||
List<DeviceInfoModel> searchResult = List<DeviceInfoModel>.empty(growable: true);
|
||||
for(DeviceInfoModel tmp in _registeredInfoDevices!){
|
||||
if(clientId == ""){
|
||||
// _fetchRegisteredDevices();
|
||||
// break;
|
||||
// missing implementation
|
||||
}
|
||||
if(tmp.id.contains(clientId)){
|
||||
searchResult.add(tmp);
|
||||
}
|
||||
}
|
||||
_registeredInfoDevices = searchResult;
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
|
@ -99,17 +114,17 @@ class _RegisteredDevicesScreen extends State<RegisteredDevicesScreen> {
|
|||
obscureText: false,
|
||||
decoration: InputDecoration(
|
||||
border: const OutlineInputBorder(),
|
||||
hintText: 'Enter the server password',
|
||||
hintText: 'Search for Devices',
|
||||
labelText: "Search",
|
||||
suffixIcon: IconButton(
|
||||
icon: const Icon(Icons.search),
|
||||
onPressed: () {
|
||||
setState(() {
|
||||
// TODO Suchfunktion
|
||||
searchDevice(_searchText);
|
||||
});
|
||||
},
|
||||
),
|
||||
filled: true,
|
||||
filled: false,
|
||||
),
|
||||
keyboardType: TextInputType.text,
|
||||
onChanged: (String newValue) {
|
||||
|
@ -130,8 +145,39 @@ class _RegisteredDevicesScreen extends State<RegisteredDevicesScreen> {
|
|||
DeviceInfoModel entry = _registeredInfoDevices![index];
|
||||
//DeviceInfoModel entryInfo = await _cloudServiceAPI.getDeviceInfo(entry.id);
|
||||
return CustomListTile(
|
||||
title: "${entry.id} \nentrypoint: ${entry.endpoint} \nstatus: ${entry.status} \nconnection: ${entry.connectionState} \nlast activity: ${entry.lastActivityTime}",
|
||||
title: entry.id,
|
||||
icon: Icons.devices,
|
||||
onTap: () => showDialog<String>(
|
||||
context: context,
|
||||
builder: (BuildContext context) => AlertDialog(
|
||||
title: const Text('Device Info'),
|
||||
content: Text("ID: ${entry.id} "
|
||||
"\n\nentrypoint: ${entry.endpoint} "
|
||||
"\n\nstatus: ${entry.status} "
|
||||
"\n\nconnection: ${entry.connectionState} "
|
||||
"\n\nlast activity: ${entry.lastActivityTime}"
|
||||
"\n\nprimaryThumbprint: ${entry.primaryThumbprint}"),
|
||||
backgroundColor: Colors.white,
|
||||
actions: <Widget>[
|
||||
TextButton(onPressed: () => Navigator.pop(context, 'Cancel'),
|
||||
child: const Text('Cancel'),
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
_cloudServiceAPI.deleteDevice(entry.id);
|
||||
Navigator.pop(context, 'delete device');
|
||||
},
|
||||
child: const Text('Delete Device'),
|
||||
),
|
||||
],
|
||||
),
|
||||
)
|
||||
/*
|
||||
Navigator.push(context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) => DeviceOptions(deviceInfoModel: entry)));
|
||||
*/
|
||||
|
||||
);
|
||||
},
|
||||
),
|
||||
|
|
|
@ -85,6 +85,7 @@ class _SettingsState extends State<Settings> {
|
|||
border: const OutlineInputBorder(),
|
||||
hintText: 'Enter the server password',
|
||||
labelText: "Password",
|
||||
filled: false,
|
||||
suffixIcon: IconButton(
|
||||
icon: Icon(_passwordVisible ? Icons.visibility : Icons.visibility_off),
|
||||
onPressed: () {
|
||||
|
@ -93,7 +94,6 @@ class _SettingsState extends State<Settings> {
|
|||
});
|
||||
},
|
||||
),
|
||||
filled: true,
|
||||
),
|
||||
initialValue: Settings.password,
|
||||
keyboardType: TextInputType.text,
|
||||
|
@ -105,10 +105,6 @@ class _SettingsState extends State<Settings> {
|
|||
),
|
||||
],
|
||||
),
|
||||
const SingleSection(
|
||||
title: "Theme Settings",
|
||||
children: <Widget>[],
|
||||
)
|
||||
]),
|
||||
)
|
||||
]),
|
||||
|
|
|
@ -3,6 +3,7 @@ import 'package:flutter/material.dart';
|
|||
class CustomListTile extends StatelessWidget {
|
||||
final String title;
|
||||
final IconData icon;
|
||||
final Color? iconColor;
|
||||
final VoidCallback? onTap;
|
||||
|
||||
//final Widget? trailing;
|
||||
|
@ -11,6 +12,7 @@ class CustomListTile extends StatelessWidget {
|
|||
Key? key,
|
||||
required this.title,
|
||||
required this.icon,
|
||||
this.iconColor,
|
||||
this.onTap,
|
||||
//this.trailing,
|
||||
}) : super(key: key);
|
||||
|
@ -19,7 +21,7 @@ class CustomListTile extends StatelessWidget {
|
|||
Widget build(BuildContext context) {
|
||||
return ListTile(
|
||||
title: Text(title),
|
||||
leading: Icon(icon),
|
||||
leading: Icon(icon, color: iconColor),
|
||||
onTap: onTap,
|
||||
//trailing: trailing,
|
||||
);
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
import 'package:flutter/material.dart';
|
||||
|
||||
import '../screens/bluetooth_screen.dart';
|
||||
import '../screens/cloud_service_ui.dart';
|
||||
import '../screens/main_screen.dart';
|
||||
import '../screens/registered_devices_screen.dart';
|
||||
import '../screens/settings.dart';
|
||||
|
@ -50,13 +49,6 @@ class Sidebar extends StatelessWidget {
|
|||
Navigator.push(context, MaterialPageRoute(builder: (context) => const Settings()));
|
||||
},
|
||||
),
|
||||
ListTile(
|
||||
leading: const Icon(Icons.cloud),
|
||||
title: const Text("Cloud Service"),
|
||||
onTap: () {
|
||||
Navigator.push(context, MaterialPageRoute(builder: (context) => const CloudService()));
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
|
|
20
pubspec.lock
20
pubspec.lock
|
@ -5,10 +5,10 @@ packages:
|
|||
dependency: "direct main"
|
||||
description:
|
||||
name: app_settings
|
||||
sha256: "7a5b880e2dd41dba8877108180380a1d28d874c231f7c0f9022127a4061b88e1"
|
||||
sha256: "66715a323ac36d6c8201035ba678777c0d2ea869e4d7064300d95af10c3bb8cb"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "4.1.8"
|
||||
version: "4.2.0"
|
||||
async:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -340,18 +340,18 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: shared_preferences_linux
|
||||
sha256: "28aefc1261746e7bad3d09799496054beb84e8c4ffcdfed7734e17b4ada459a5"
|
||||
sha256: fbc3cd6826896b66a5f576b025e4f344f780c84ea7f8203097a353370607a2c8
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.1"
|
||||
version: "2.1.2"
|
||||
shared_preferences_macos:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: shared_preferences_macos
|
||||
sha256: fbb94bf296576f49be37a1496d5951796211a8db0aa22cc0d68c46440dad808c
|
||||
sha256: "81b6a60b2d27020eb0fc41f4cebc91353047309967901a79ee8203e40c42ed46"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.0.4"
|
||||
version: "2.0.5"
|
||||
shared_preferences_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -372,10 +372,10 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: shared_preferences_windows
|
||||
sha256: "97f7ab9a7da96d9cf19581f5de520ceb529548498bd6b5e0ccd02d68a0d15eba"
|
||||
sha256: "07c274c2115d4d5e4280622abb09f0980e2c5b1fcdc98ae9f59a3bad5bfc1f26"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.1"
|
||||
version: "2.1.2"
|
||||
sky_engine:
|
||||
dependency: transitive
|
||||
description: flutter
|
||||
|
@ -449,10 +449,10 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: win32
|
||||
sha256: ca121dbbadb3e43b449053feab0cdf3f2bff93b107cacf0290e3d29f717374b6
|
||||
sha256: c9ebe7ee4ab0c2194e65d3a07d8c54c5d00bb001b76081c4a04cdb8448b59e46
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.1.2"
|
||||
version: "3.1.3"
|
||||
xdg_directories:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
|
@ -9,12 +9,10 @@ import 'package:flutter/material.dart';
|
|||
import 'package:flutter_provisioning_for_iot/screens/main_screen.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
|
||||
import 'package:flutter_provisioning_for_iot/main.dart';
|
||||
|
||||
void main() {
|
||||
testWidgets('Counter increments smoke test', (WidgetTester tester) async {
|
||||
// Build our app and trigger a frame.
|
||||
await tester.pumpWidget(const MainPage());
|
||||
await tester.pumpWidget(const MainScreen());
|
||||
|
||||
// Verify that our counter starts at 0.
|
||||
expect(find.text('0'), findsOneWidget);
|
||||
|
|
Loading…
Reference in New Issue