I can´t to read identifier nfc card with nfc_manager package. I think i need decoded the tag identifier number. My code...
'''ValueNotifier<dynamic> result = ValueNotifier(null);'''
void _tagRead() async{
bool isAvailable = await NfcManager.instance.isAvailable();
NfcManager.instance.startSession(onDiscovered: (NfcTag tag) async {
result.value = tag.data;
MifareClassic? nfca = MifareClassic.from(tag);
var read = nfca?.identifier;
}
It´s returning: identifier[xxx, xx, xxx, xx] (four int numbers).
I used the nfc_manager package and I also didn't get the expected result in my project, so I started using the flutter_nfc_kit package. Only with 'tag.id' has access to the identifier.
Below is a snippet of code taken from the example available at https://github.com/nfcim/flutter_nfc_kit
import 'dart:async';
import 'dart:io' show Platform, sleep;
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_nfc_kit/flutter_nfc_kit.dart';
import 'package:logging/logging.dart';
import 'package:ndef/ndef.dart' as ndef;
class Sensors extends StatefulWidget {
#override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<Sensors> with SingleTickerProviderStateMixin {
String _platformVersion = '';
NFCAvailability _availability = NFCAvailability.not_supported;
NFCTag? _tag;
String? _result, _writeResult;
late TabController _tabController;
List<ndef.NDEFRecord>? _records;
#override
void dispose() {
_tabController.dispose();
super.dispose();
}
#override
void initState() {
super.initState();
if (!kIsWeb)
_platformVersion =
'${Platform.operatingSystem} ${Platform.operatingSystemVersion}';
else
_platformVersion = 'Web';
initPlatformState();
_tabController = new TabController(length: 2, vsync: this);
_records = [];
}
// Platform messages are asynchronous, so we initialize in an async method.
Future<void> initPlatformState() async {
NFCAvailability availability;
try {
availability = await FlutterNfcKit.nfcAvailability;
} on PlatformException {
availability = NFCAvailability.not_supported;
}
// If the widget was removed from the tree while the asynchronous platform
// message was in flight, we want to discard the reply rather than calling
// setState to update our non-existent appearance.
if (!mounted) return;
setState(() {
// _platformVersion = platformVersion;
_availability = availability;
});
}
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text('NFC Flutter Kit Example App'),
),
body: Scrollbar(
child: SingleChildScrollView(
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
const SizedBox(height: 20),
Text('Running on: $_platformVersion\nNFC: $_availability'),
const SizedBox(height: 10),
ElevatedButton(
onPressed: () async {
try {
NFCTag tag = await FlutterNfcKit.poll();
setState(() {
_tag = tag;
});
await FlutterNfcKit.setIosAlertMessage("Working on it...");
if (tag.standard == "ISO 14443-4 (Type B)") {
String result1 =
await FlutterNfcKit.transceive("00B0950000");
String result2 = await FlutterNfcKit.transceive(
"00A4040009A00000000386980701");
setState(() {
_result = '1: $result1\n2: $result2\n';
});
} else if (tag.type == NFCTagType.iso18092) {
String result1 =
await FlutterNfcKit.transceive("060080080100");
setState(() {
_result = '1: $result1\n';
});
} else if (tag.type == NFCTagType.mifare_ultralight ||
tag.type == NFCTagType.mifare_classic ||
tag.type == NFCTagType.iso15693) {
var ndefRecords = await FlutterNfcKit.readNDEFRecords();
var ndefString = '';
for (int i = 0; i < ndefRecords.length; i++) {
ndefString += '${i + 1}: ${ndefRecords[i]}\n';
}
setState(() {
_result = ndefString;
});
} else if (tag.type == NFCTagType.webusb) {
var r = await FlutterNfcKit.transceive(
"00A4040006D27600012401");
print(r);
}
} catch (e) {
setState(() {
_result = 'error: $e';
});
}
// Pretend that we are working
if (!kIsWeb) sleep(new Duration(seconds: 1));
await FlutterNfcKit.finish(iosAlertMessage: "Finished!");
},
child: Text('Start polling'),
),
const SizedBox(height: 10),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 20),
child: _tag != null
? Text(
'ID: ${_tag!.id}\nStandard: ${_tag!.standard}\nType: ${_tag!.type}\nATQA: ${_tag!.atqa}\nSAK: ${_tag!.sak}\nHistorical Bytes: ${_tag!.historicalBytes}\nProtocol Info: ${_tag!.protocolInfo}\nApplication Data: ${_tag!.applicationData}\nHigher Layer Response: ${_tag!.hiLayerResponse}\nManufacturer: ${_tag!.manufacturer}\nSystem Code: ${_tag!.systemCode}\nDSF ID: ${_tag!.dsfId}\nNDEF Available: ${_tag!.ndefAvailable}\nNDEF Type: ${_tag!.ndefType}\nNDEF Writable: ${_tag!.ndefWritable}\nNDEF Can Make Read Only: ${_tag!.ndefCanMakeReadOnly}\nNDEF Capacity: ${_tag!.ndefCapacity}\n\n Transceive Result:\n$_result')
: const Text('No tag polled yet.')),
])))),
),
);
}
}
Related
I am trying to implement a infinite scroll pagnation in Flutter using provider for state management.
I have two page, HomePage() and TestingPage().On start up, the code is able to successfully load data from the api endpoint but the retrieved data was not displayed by the listview builder.The data is only displayed if i switch to the TestingPage() and back to HomePage().
The code will load more data if i reach the end of the scroll view, but the same problem is happening again, list view builder will not display the newly loaded data. It will only display it if i switch to TestingPage() and back to HomePage().
Reposting this because i made a mistake of posting the wrong code.
// UserInfo.dart
class UserInfo {
int userId;
int id;
String title;
String body;
UserInfo(this.userId, this.id, this.title, this.body);
factory UserInfo.fromJson(Map<String, dynamic> json) {
final userId = json['userId'];
final id = json['id'];
final title = json['title'];
final body = json['body'];
return UserInfo(userId, id, title, body);
}
#override
String toString() {
return "id: $id";
}
}
// user_info_response.dart
import 'package:end_point/models/UserInfo.dart';
class ListOfUserInfoResponse {
int? code;
List<UserInfo> listOfUserInfo;
ListOfUserInfoResponse({this.code, required this.listOfUserInfo});
factory ListOfUserInfoResponse.fromJson(int statusCode, List<dynamic> json) {
List<dynamic> list = json;
return ListOfUserInfoResponse(
code: statusCode,
listOfUserInfo: list.map((i) => UserInfo.fromJson(i)).toList());
}
}
// user_info_api.dart
import 'dart:convert';
import 'package:http/http.dart' as http;
import 'package:end_point/models/API/user_info_response.dart';
Future<ListOfUserInfoResponse> getListOfUserInfo(page) async {
final response = await http.get(Uri.parse(
"https://jsonplaceholder.typicode.com/posts?_limit=15&_page=$page"));
if (response.statusCode == 200) {
return ListOfUserInfoResponse.fromJson(
response.statusCode, jsonDecode(response.body));
} else {
throw Exception("Failed to load data");
}
}
// user_info_provider.dart
import 'dart:developer';
import 'package:flutter/material.dart';
import 'package:end_point/models/UserInfo.dart';
import 'package:end_point/api/user_info_api.dart' as UserInfoAPI;
import 'package:end_point/models/API/user_info_response.dart';
class UserInfoProvider with ChangeNotifier {
int _page = 1;
int get page => _page;
bool _isLoading = false;
bool get isLoading => _isLoading;
List<UserInfo> _listOfUserData = [];
List<UserInfo> get listOfUserData => _listOfUserData;
set listOfUserData(List<UserInfo> listOfUserData) {
_listOfUserData = listOfUserData;
notifyListeners();
}
bool _hasMore = true;
bool get hasMore => _hasMore;
Future<void> loadMoreData() async {
if (_isLoading) return;
_isLoading = true;
ListOfUserInfoResponse response =
await UserInfoAPI.getListOfUserInfo(_page);
_listOfUserData.addAll(response.listOfUserInfo);
_page++;
_isLoading = false;
if (response.listOfUserInfo.length < 20) {
_hasMore = false;
}
notifyListeners();
}
void refreshData() async {
_isLoading = false;
_hasMore = true;
_page = 1;
listOfUserData.clear();
notifyListeners();
}
}
// home.dart
import 'package:end_point/providers/user_info_provider.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'dart:developer';
class HomePage extends StatefulWidget {
const HomePage({super.key});
#override
State<HomePage> createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
final _scrollController = ScrollController();
late UserInfoProvider userInfoProvider;
#override
void initState() {
super.initState();
userInfoProvider = Provider.of<UserInfoProvider>(context, listen: false);
userInfoProvider.loadMoreData();
_scrollController.addListener(_onScroll);
}
Future<void> _onScroll() async {
if (_scrollController.position.maxScrollExtent ==
_scrollController.offset) {
await userInfoProvider.loadMoreData();
}
}
#override
void dispose() {
_scrollController.dispose();
super.dispose();
}
Future refresh() async {
userInfoProvider.refreshData();
await userInfoProvider.loadMoreData();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text("END POINT LEGGO")),
body: RefreshIndicator(
key: UniqueKey(),
onRefresh: refresh,
child: ListView.builder(
key: const PageStorageKey<String>('HP'),
itemCount: userInfoProvider.listOfUserData.length,
controller: _scrollController,
shrinkWrap: true,
itemBuilder: (context, index) {
final id = userInfoProvider.listOfUserData[index].id;
if (index < userInfoProvider.listOfUserData.length) {
return Padding(
padding: const EdgeInsets.all(2.0),
child: Container(
height: 50,
width: 200,
decoration: const BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(20)),
color: Colors.red),
child: ListTile(title: Text('$id'))),
);
} else {
return Padding(
padding: const EdgeInsets.symmetric(vertical: 32),
child: Center(
child: userInfoProvider.hasMore
? const CircularProgressIndicator()
: const Text('No more data to load'),
));
}
}),
));
}
I found the fix to this problem, #home.dart instead of using the UserInfoProvider instance that was declared in the initState().
Simply declare a new userInfoProvider instance inside the Widget build().
E.g. final data = Provider.of(context);
From what I understood, this is because the instance of the UserInfoProvider that was declared in the initState() has listen: false. false value will mean that any value changes, will not trigger a rebuild of the widget.
I am using [background_locator_2][1] plugin, However when I run it with some modification I get this error
[ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: type 'Null' is not a subtype of type 'LocationDto'
This is the code i am using
void main() => runApp(MyApp());
class MyApp extends StatefulWidget {
#override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
ReceivePort port = ReceivePort();
String logStr = '';
bool? isRunning;
LocationDto? lastLocation;
#override
void initState() {
super.initState();
if (IsolateNameServer.lookupPortByName(
LocationServiceRepository.isolateName) !=
null) {
IsolateNameServer.removePortNameMapping(
LocationServiceRepository.isolateName);
}
IsolateNameServer.registerPortWithName(
port.sendPort, LocationServiceRepository.isolateName);
port.listen(
(dynamic data) async {
await updateUI(data);
},
);
initPlatformState();
}
#override
void dispose() {
super.dispose();
}
Future<void> updateUI(LocationDto data) async {
final log = await FileManager.readLogFile();
await _updateNotificationText(data);
setState(() {
lastLocation = data;
logStr = log;
});
}
Future<void> _updateNotificationText(LocationDto data) async {
if (data == null) {
return;
}
await BackgroundLocator.updateNotificationText(
title: "new location received",
msg: "${DateTime.now()}",
bigMsg: "${data.latitude}, ${data.longitude}");
}
Future<void> initPlatformState() async {
print('Initializing...');
await BackgroundLocator.initialize();
logStr = await FileManager.readLogFile();
print('Initialization done');
final _isRunning = await BackgroundLocator.isServiceRunning();
setState(() {
isRunning = _isRunning;
});
print('Running ${isRunning.toString()}');
}
#override
Widget build(BuildContext context) {
final start = SizedBox(
width: double.maxFinite,
child: ElevatedButton(
child: Text('Start'),
onPressed: () {
_onStart();
},
),
);
final stop = SizedBox(
width: double.maxFinite,
child: ElevatedButton(
child: Text('Stop'),
onPressed: () {
onStop();
},
),
);
final clear = SizedBox(
width: double.maxFinite,
child: ElevatedButton(
child: Text('Clear Log'),
onPressed: () {
FileManager.clearLogFile();
setState(() {
logStr = '';
});
},
),
);
String msgStatus = "-";
if (isRunning != null) {
if (isRunning!) {
msgStatus = 'Is running';
} else {
msgStatus = 'Is not running';
}
}
final status = Text("Status: $msgStatus");
final log = Text(
logStr,
);
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text('Flutter background Locator'),
),
body: Container(
width: double.maxFinite,
padding: const EdgeInsets.all(22),
child: SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[start, stop, clear, status, log],
),
),
),
),
);
}
void onStop() async {
await BackgroundLocator.unRegisterLocationUpdate();
final _isRunning = await BackgroundLocator.isServiceRunning();
setState(() {
isRunning = _isRunning;
});
}
void _onStart() async {
//if (await isLocationAlwaysGranted()) {
await _startLocator();
final _isRunning = await BackgroundLocator.isServiceRunning();
setState(() {
isRunning = _isRunning;
lastLocation = null;
});
// } else {
// show error
}
}
Future<bool> isLocationAlwaysGranted() async =>
await Permission.locationAlways.isGranted;
/// Tries to ask for "location always" permissions from the user.
/// Returns `true` if successful, `false` othervise.
Future<bool> askForLocationAlwaysPermission() async {
bool granted = await Permission.locationAlways.isGranted;
if (!granted) {
granted =
await Permission.locationAlways.request() == PermissionStatus.granted;
}
return granted;
}
Future<void> _startLocator() async {
Map<String, dynamic> data = {'countInit': 1};
return await BackgroundLocator.registerLocationUpdate(
LocationCallbackHandler.callback,
initCallback: LocationCallbackHandler.initCallback,
initDataCallback: data,
disposeCallback: LocationCallbackHandler.disposeCallback,
iosSettings: IOSSettings(
accuracy: LocationAccuracy.NAVIGATION,
distanceFilter: 0,
stopWithTerminate: true),
autoStop: false,
androidSettings: AndroidSettings(
accuracy: LocationAccuracy.NAVIGATION,
interval: 5,
distanceFilter: 0,
client: LocationClient.google,
androidNotificationSettings: AndroidNotificationSettings(
notificationChannelName: 'Location tracking',
notificationTitle: 'Start Location Tracking',
notificationMsg: 'Track location in background',
notificationBigMsg:
'Background location is on to keep the app up-tp-date with your location. This is required for main features to work properly when the app is not running.',
notificationIconColor: Colors.grey,
notificationTapCallback:
LocationCallbackHandler.notificationCallback)));
}
The error is in this line under initState when I start or stop the plugin.
port.listen(
(dynamic data) async {
await updateUI(data);
},
);
The original code didn't have null safety so i tried to modify it. However it is pretty evident my knowledge is limited.
[1]: https://pub.dev/packages/background_locator_2
the data you are listening to from the port (dynamic data) can be null and you are sending it to the function updateUI which does not accept nullable type.
you can either check if the data is not null before calling await updateUI(data); or you can make the function updateUI accepts null, i.e (Future<void> updateUI(LocationDto? data) async {) and handle the case that the data is nullable inside the function
I have a audio recording page which starts when I tap in the button and stop when i tap the button once again
import 'package:flutter_sound/flutter_sound.dart';
import 'package:permission_handler/permission_handler.dart';
class AudioWidget extends StatefulWidget {
#override
State<AudioWidget> createState() => _AudioWidgetState();
}
``class _AudioWidgetState extends State<AudioWidget> {
final FirebaseAuth _auth = FirebaseAuth.instance;
String AudioUrl = '';
final recorder = FlutterSoundRecorder();
bool isRecorderReady = false;
#override
void initState() {
super.initState();
initRecorder();
record();
}
#override
void dispose() {
recorder.closeRecorder();
super.dispose();
}
Future initRecorder() async {
final status = await Permission.microphone.request();
if (status != PermissionStatus.granted) {
throw 'Microphone permission not granted';
}
await recorder.openRecorder();
isRecorderReady = true;
recorder.setSubscriptionDuration(const Duration(milliseconds: 500));
}
Future record() async {
if (!isRecorderReady) {
return;
}
await recorder.startRecorder(toFile: 'audio');
}
Future stop() async {
if (!isRecorderReady) {
return;
}
final path = await recorder.stopRecorder();
final audioFile = File(path!);
print('Recorder audio: $audioFile');
final ref = FirebaseStorage.instance
.ref()
.child('Audio')
.child(DateTime.now().toIso8601String() + ".mp3");
await ref.putData(audioFile.readAsBytesSync());
AudioUrl = await ref.getDownloadURL();
FirebaseFirestore.instance.collection('Audio').add({
'AudioUrl': AudioUrl,
'userId': _auth.currentUser!.email,
'createdAt': DateTime.now(),
});
}
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text("Audio"),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
StreamBuilder<RecordingDisposition>(
stream: recorder.onProgress,
builder: (context, snapshot) {
final duration = snapshot.hasData
? snapshot.data!.duration
: Duration.zero;
String twoDigits(int n) => n.toString().padLeft(2, '0');
final twoDigitMinutes =
twoDigits(duration.inMinutes.remainder(60));
final twoDigitSeconds =
twoDigits(duration.inSeconds.remainder(60));
if (twoDigitSeconds ==
FFAppState().AudioMaxDuration.toString()) {
stop();
}
return Text('$twoDigitMinutes:$twoDigitSeconds',
style: const TextStyle(
fontSize: 80,
fontWeight: FontWeight.bold,
));
}),
const SizedBox(height: 32),
ElevatedButton(
child: Icon(
recorder.isRecording ? Icons.stop : Icons.mic,
size: 80,
),
onPressed: () async {
if (recorder.isRecording) {
await stop();
context.pop();
} else {
await record();
}
setState(() {});
},
),
],
)),
),
);
}
}
how can I automatically start recording once I open the audio recording page and tap it to stop and tap again to start?
I tried to put the record function in initstate but it didn't work
void initState() {
super.initState();
initRecorder();
record();
}
I hope somebody can help me out on a problem that i have.
I try to explain the problem the best i can.
The idea is the following for a Desktop App
First i tried to fetch and save data locally in a Json file that i get over WebSocket. What is working.
Second i tried to display the data of the local Json file inside a Chart. What is also working.
After i tried to combine the two above scenarios i one app and here i get the following error.
Exception has occurred.
FileSystemException (FileSystemException: read failed, path = 'C:\Users\7ke19\Documents/Measure/measure.json' (OS Error: The process cannot access the file because another process has locked a portion of the file.
, errno = 33))
In my app i am using the following packages.
Getx for the state manegment. https://pub.dev/packages/get
Localstorage for the Json storage. https://pub.dev/packages/localstorage
Syncfusion_flutter_charts for the Chart. https://pub.dev/packages/syncfusion_flutter_charts
Path_provider to get access to file and folders. https://pub.dev/packages/path_provider
I think i get the above error because at some moment inside my code the app is trying to read a write to the file at the same time.
Follows the code that i have.
The code is divided in three separated files.
Main Function:
import 'package:flutter/material.dart';
import 'package:flutter_application_2/controller/diagram_controller.dart';
import 'package:flutter_application_2/home_screen.dart';
import 'package:get/get.dart';
void main() async {
Get.put(DiagramController());
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return const GetMaterialApp(
debugShowCheckedModeBanner: false,
home: HomeScreen(),
);
}
}
HomeScreen:
import 'package:flutter_application_2/controller/diagram_controller.dart';
import 'package:get/get.dart';
import 'package:flutter/material.dart';
import 'package:syncfusion_flutter_charts/charts.dart';
class HomeScreen extends StatelessWidget {
const HomeScreen({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Scaffold(
body: GetBuilder<DiagramController>(
init: DiagramController(),
initState: (_) {},
builder: (gtxs1) {
return FutureBuilder(
future: gtxs1.getJsonData(),
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (snapshot.hasData) {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Container(
//********Showing if Websocket is Connected or Disconnected*******
child: gtxs1.connectedS1Status
? const Text(
"WEBSOCKET: CONNECTED",
style: TextStyle(
fontSize: 18,
color: Colors.green,
),
)
: const Text(
"WEBSOCKET: DISCONNECTED",
style: TextStyle(
fontSize: 18,
color: Colors.red,
),
),
),
//**********************Showing Range Diagram **********************
Column(
children: [
const Text(
'Range Diagram:',
),
const SizedBox(
height: 5,
),
SizedBox(
width: 800,
height: 280,
child: SfCartesianChart(
title: ChartTitle(
borderWidth: 2,
alignment: ChartAlignment.near,
),
series: gtxs1.getSeriesRange(),
legend: Legend(isVisible: true),
),
),
],
),
const SizedBox(
height: 20,
),
//**********************Showing Force Diagram **********************
Column(
children: [
const Text(
'Force Diagram:',
),
const SizedBox(
height: 5,
),
SizedBox(
width: 800,
height: 280,
child: SfCartesianChart(
title: ChartTitle(
borderWidth: 2,
alignment: ChartAlignment.near,
),
series: gtxs1.getSeriesForce(),
legend: Legend(isVisible: true),
),
),
],
),
],
);
} else {
return const CircularProgressIndicator();
}
},
);
},
),
);
}
}
Controller:
// ignore_for_file: avoid_print
import 'package:get/get.dart';
import 'dart:async';
import 'dart:convert';
import 'dart:io';
import 'package:syncfusion_flutter_charts/charts.dart';
import 'package:path_provider/path_provider.dart';
import 'package:web_socket_channel/io.dart';
import 'package:localstorage/localstorage.dart';
final MeasureList list = MeasureList(); //List for LocalStorage
bool initialized = false; //for LocalStorage
int istcyclesJson = 0; //variable for istcycles
List<dynamic> istrangesensorJson = [0]; //variable for istrangesensor
List<dynamic> istforcesensorJson = [0]; //variable for istforcesensor
//***********************************************************************************************
//-----class MeasureItem for LocalStorage--------------------------------------------------------
//***********************************************************************************************
class MeasureItem {
int titleCountJson;
List<dynamic> titleRangeJson;
List<dynamic> titleForceJson;
MeasureItem({
required this.titleCountJson,
required this.titleRangeJson,
required this.titleForceJson,
});
toJSONEncodable() {
Map<String, dynamic> m = {};
m['count_array'] = titleCountJson;
m['range_array'] = titleRangeJson;
m['force_array'] = titleForceJson;
return m;
}
}
//***********************************************************************************************
//-----class MeasureList for LocalStorage--------------------------------------------------------
//***********************************************************************************************
class MeasureList {
List<MeasureItem> items = [];
toJSONEncodable() {
return items.map((item) {
return item.toJSONEncodable();
}).toList();
}
}
class DiagramController extends GetxController {
static DiagramController get to => Get.find();
List<List<ChartDataRange>> dataListRange = [];
List<List<ChartDataForce>> dataListForce = [];
LocalStorage storage = LocalStorage('/Measure/measure.json');
final MeasureList list = MeasureList();
late IOWebSocketChannel channel;
late bool connectedS1Status;
Directory? rootPath;
//**********************************************************************
#override
void onInit() {
connectedS1Status = false;
createFileFolder();
Future.delayed(
Duration.zero,
() async {
channelconnect();
},
);
Future.delayed(
const Duration(milliseconds: 1000),
() async {
loadStringRange();
loadStringForce();
},
);
super.onInit();
}
//***********************************************************************************************
//-----Channelconnect----------------------------------------------------------------------------
//***********************************************************************************************
channelconnect() {
try {
channel = IOWebSocketChannel.connect("ws://192.168.1.100:80");
channel.stream.listen(
(message) {
print(message);
Map<String, dynamic> jsondat = json.decode(message);
String data = json.encode(jsondat);
if (data.contains("cycle")) {
connectedS1Status = true;
update();
}
if (data.contains("count_array")) {
istcyclesJson = jsondat['count_array'];
istrangesensorJson = jsondat['range_array'];
istforcesensorJson = jsondat['force_array'];
_save();
//update();
}
},
onDone: () {
print("Web socket is closed");
connectedS1Status = false;
},
onError: (error) {
print(error.toString());
},
);
} catch (_) {
print("error on connecting to websocket.");
}
//update();
}
//***********************************************************************************************
//-----Functions to create and generate Json List using LocalStorage-----------------------------
//***********************************************************************************************
//...................................................
void _save() {
_addItem(istcyclesJson, istrangesensorJson, istforcesensorJson);
print("SAVE");
// update();
}
//...................................................
_addItem(int titlecount, List<dynamic> titlerange, List<dynamic> titleforce) {
final item = MeasureItem(
titleCountJson: titlecount,
titleRangeJson: titlerange,
titleForceJson: titleforce);
list.items.add(item);
_saveToStorage();
//update();
}
//...................................................
_saveToStorage() {
storage.setItem('measure', list.toJSONEncodable());
//update();
}
//***********************************************************************************************
//-----Functions to create Folder and File if not exist and write to the file some zero values
//-----not to get error when display the chart and the file is empty
//***********************************************************************************************
Future<File> createFileFolder() async {
rootPath = await getApplicationDocumentsDirectory();
Directory sampleFolder = Directory('${rootPath!.path}/Measure');
if (!sampleFolder.existsSync()) {
sampleFolder.createSync();
}
File sampleFile =
await File('${sampleFolder.path}/measure.json').create(recursive: true);
if (!sampleFile.existsSync()) {
sampleFolder.createSync();
}
final file = sampleFile;
return file.writeAsString(
'{"measure": [{"count": 0,"range_array": [0,0,0],"force_array": [0,0,0]}]}');
}
//**********************************************************************
Future<String> getJsonData() async {
rootPath = await getApplicationDocumentsDirectory();
Directory sampleFolder = Directory('${rootPath!.path}/Measure');
await File('${sampleFolder.path}/measure.json').create(recursive: true);
return await File('${sampleFolder.path}/measure.json').readAsString();
}
//**********************************************************************
Future loadStringRange() async {
final String jsonString = await getJsonData();
final dynamic jsonResponse = json.decode(jsonString);
List<dynamic> values = jsonResponse['measure'].last['range_array'];
List<ChartDataRange> chartDataR = [];
for (var j = 0; j < values.length; j++) {
chartDataR.add(ChartDataRange(j, values[j]));
}
dataListRange.add(chartDataR);
update();
}
//**********************************************************************
Future loadStringForce() async {
final String jsonString = await getJsonData();
final dynamic jsonResponse = json.decode(jsonString);
List<dynamic> values = jsonResponse['measure'].last['force_array'];
List<ChartDataForce> chartDataF = [];
for (var j = 0; j < values.length; j++) {
chartDataF.add(ChartDataForce(j, values[j]));
}
dataListForce.add(chartDataF);
update();
}
//**********************************************************************
List<ChartSeries<ChartDataRange, num>> getSeriesRange() {
List<ChartSeries<ChartDataRange, num>> seriesListRange = [];
for (var index = 0; index < dataListRange.length; index++) {
seriesListRange.add(
SplineSeries<ChartDataRange, num>(
dataSource: dataListRange[index],
xValueMapper: (ChartDataRange data, _) => data.x,
yValueMapper: (ChartDataRange data, _) => data.y,
),
);
}
return seriesListRange;
}
//**********************************************************************
List<ChartSeries<ChartDataForce, num>> getSeriesForce() {
List<ChartSeries<ChartDataForce, num>> seriesListForce = [];
for (var index = 0; index < dataListForce.length; index++) {
seriesListForce.add(
SplineSeries<ChartDataForce, num>(
dataSource: dataListForce[index],
xValueMapper: (ChartDataForce data, _) => data.x,
yValueMapper: (ChartDataForce data, _) => data.y,
),
);
}
return seriesListForce;
}
}
//**********************************************************************
class ChartDataRange {
final num x;
final num y;
ChartDataRange(this.x, this.y);
}
//**********************************************************************
class ChartDataForce {
final num x;
final num y;
ChartDataForce(this.x, this.y);
}
I am trying to get the data from my bluetooth device. My problem is with the Flutter code to get such data.
services/sensor.dart
import 'dart:async';
import 'dart:convert' show utf8;
import 'package:flutter/material.dart';
import 'package:flutter_blue/flutter_blue.dart';
import 'package:minertti/main.dart';
class SensorPage extends StatefulWidget {
const SensorPage({Key? key, required this.device}) : super(key: key);
final BluetoothDevice device;
#override
_SensorPageState createState() => _SensorPageState();
}
class _SensorPageState extends State<SensorPage> {
String service_uuid = "6E400001-B5A3-F393-E0A9-E50E24DCCA9E";
String charaCteristic_uuid = "6E400003-B5A3-F393-E0A9-E50E24DCCA9E";
late bool isReady;
late Stream<List<int>> stream;
late List _temphumidata;
double _charge = 0;
double _data_1 = 0;
double _data_2 = 0;
#override
void initState() {
super.initState();
super.initState();
isReady = false;
connectToDevice();
}
void dispose() {
widget.device.disconnect();
super.dispose();
}
connectToDevice() async {
if (widget.device == null) {
_pop();
return;
}
new Timer(const Duration(seconds: 15), () {
if (!isReady) {
disconnectFromDevice();
_pop();
}
});
await widget.device.connect();
discoverServices();
}
disconnectFromDevice() {
if (widget.device == null) {
_pop();
return;
}
widget.device.disconnect();
}
discoverServices() async {
if (widget.device == null) {
_pop();
return;
}
List<BluetoothService> services = await widget.device.discoverServices();
services.forEach((service) {
if (service.uuid.toString().isNotEmpty) {
service.characteristics.forEach((characteristic) {
if (characteristic.uuid.toString().isNotEmpty) {
characteristic.setNotifyValue(!characteristic.isNotifying);
stream = characteristic.value;
setState(() {
isReady = true;
});
}
});
}
});
if (!isReady) {
_pop();
}
}
_pop() {
Navigator.of(context).pop(true);
}
String _dataParser(List<int> dataFromDevice) {
return utf8.decode(dataFromDevice);
}
#override
Widget build(BuildContext context) {
return Scaffold(
// appBar: AppBar(
// title: Text('dht11 Sensor'),
// ),
body: Container(
child: !isReady
? Center(
child: Text(
"Waiting...",
style: TextStyle(
fontSize: 24, color: Color.fromARGB(255, 0, 0, 0)),
),
)
: Container(
child: StreamBuilder<List<int>>(
stream: stream,
builder: (BuildContext context,
AsyncSnapshot<List<int>> snapshot) {
if (snapshot.hasError)
return Text('Error: ${snapshot.error}');
if (snapshot.connectionState == ConnectionState.active) {
var data = snapshot.data as List<int>;
var currentValue = _dataParser(data);
print("REALDATA: $data");
_temphumidata = currentValue.split(",");
//_charge = double.parse('${_temphumidata[0]}');
//_data_1 = double.parse('${_temphumidata[1]}');
//_data_2 = _temphumidata[2];
return DeviceScreen1(
device: widget.device,
//charge: _charge,
//data_2: _data_2,
//data_1: _data_1,
charge: 90,
data_1: "Data 1",
data_2: "Data 2");
} else {
return Text('Check the stream');
}
},
),
)),
);
}
}
var data = snapshot.data as List;
var currentValue = _dataParser(data);
They do not show values. But, from my Arduino I know that it does send/notify data. That is, my problem is with reading and obtaining said data.