Get "handles" of characteristics using FlutterBlue? - flutter

Repeat of https://github.com/pauldemarco/flutter_blue/issues/868
On Windows, I have some code that looks like:
wclGattClient.ReadCharacteristicValue(errorchar, wclGattOperationFlag.goNone, out var Value);
foreach (uint16 handle in Value)
{
foreach(chars in service)
if(chars.handle == handle)
{
wclGattClient.ReadCharacteristicValue(errorchar, wclGattOperationFlag.goNone, out var Val2);
print("UUID %s is flagged : %s", chars.uuid, Val2.toString());
}
}
ie, the device is returning a list of Handles that are in an alert status (so I can read them and present the condition to the user), and I need to match that up with the Handle of the char in the discoverServices so I know which ones to get the data from...
How do I do this with flutter_blue?

The flutter_blue documentation on Github includes a part about reading and writing characteristics:
// Reads all characteristics
var characteristics = service.characteristics;
for(BluetoothCharacteristic c in characteristics) {
List<int> value = await c.read();
print(value);
}
// Writes to a characteristic
await c.write([0x12, 0x34])
In this example BluetoothCharacteristic cwould be your handle you can use to read and write values to.

Related

Getting data from Realtime Database with a conditional statement

how I can show DeliveryBoys in a specific location, in my realtime database I have a value that I need to compare drivers with which is "City" I would like to have all DeliveryBoys that are in a specific city. How can I do that? Using flutter
Am only able to get all drivers without a conditional statement
**This is my Function that i want to modify **
retrieveOnlineDriversInformation(List onlineNearestDriversList) async {
DatabaseReference ref =
FirebaseDatabase.instance.ref().child("DeliveryBoys");
for (int i = 0; i < onlineNearestDriversList.length; i++) {
await ref
.child(onlineNearestDriversList[i].driverId.toString())
.once()
.then((dataSnapshot) {
var driverKeyInfo = dataSnapshot.snapshot.value;
dList.add(driverKeyInfo);
});
}
}
Database Structure
Based on your responses and as far as I can see, you don't need the loop where you have it. Therefore, I am going to ignore it and simply show you the code that will return the list of driver ids of all drivers for city 'Lusaka'.
Future<List<String>> retrieveOnlineDriversInformation() async {
final driverIds = <String>[];
DatabaseReference ref = FirebaseDatabase.instance.ref().child("drivers");
try {
await ref.orderByChild("city")
.equalTo("Lusaka")
.once()
.then(
(event) {
if (event.snapshot.value != null) {
final driverListData =
Map<String, dynamic>.from(event.snapshot.value! as Map);
driverListData.forEach((key, value) {
driverIds.add(key);
});
}
},
} on FirebaseException catch (error, stackTrace) {
// < Some code here to print database error details or otherwise deal with it >
} catch (error, stackTrace) {
// < Some code here to print other error details or otherwise deal with it >
}
return driverIds;
}
You could instead modify this to just return the Map 'driverListData' which contains each driver's id and associated driver data.
A couple of other points:
You don't stick to a standard naming convention for your database node and field names. I suggest that you always use lowerCamelCase as the standard (so for example, change DriverLicense to driverLicense) as it will match what you typically name the variables within the Flutter/Dart code.
You don't need to hold the driver id as a separate field in the driver node. It is a duplicate (and therefore wastes space on the database) of the driver record key, which is already accessible to you.
As you see, you should always wrap your database call logic in a try / catch clauses in order to handle any errors that the call to the database may return. There are specific exceptions that can be tested for with the on clause.

Problems reading Bluetooth Device data and returning it into code in Flutter/Dart

The following is the function code I am using to read the data from the Bluetooth Device
Future listServices() async {
List<BluetoothService>? services = await primBms?.device.discoverServices();
List values = [];
services?.forEach((service) async {
if (service.uuid.toString() == primBmsUuids[0]) {
for (BluetoothCharacteristic c in service.characteristics) {
List<int> value = await c.read();
int val = int.parse(String.fromCharCode(value[0]) + String.fromCharCode(value[1]));
print(value);
print(val);
values.add(val);
}
}
});
return values;
}
I am parsing the character codes from the read data packet, however using this function returns an empty list. I used a print function to confirm whether value and val return valid values and they do, however for whatever reason these do not get added to the list.
Can someone kindly help me figure out the solution to my problem ?

Multiple local HMS ML Kit translator models in Flutter?

I've defined a class that wraps the HMS ML Kit in-device translator.
This class has two translator instances, with two different settings:
MLLocalTranslator translatorSend = new MLLocalTranslator();
MLLocalTranslator translatorReceive = new MLLocalTranslator();
MLTranslateSetting settingSend = new MLTranslateSetting();
MLTranslateSetting settingReceive = new MLTranslateSetting();
translatorSend translates request from a language (for example it) to English (en). translatorReceive translates the response of the request from en to it.
However, the prepare method only downloads the model for en_it translation and not the it_en model (if exists).
HMSTranslator(String languageCode) {
settingSend.sourceLangCode = languageCode;
settingSend.targetLangCode = "en";
settingReceive.sourceLangCode = "en";
settingReceive.targetLangCode = languageCode;
}
Future<bool> prepare() async {
if(settingSend.sourceLangCode != settingSend.targetLangCode) {
bool isSendPrepared = await translatorSend.prepareModel(setting: settingSend)
bool isReceivePrepared = await translatorReceive.prepareModel(setting: settingReceive);
isPrepared = isSendPrepared && isReceivePrepared;
}
else {
isPrepared = false;
}
return isPrepared;
}
The problem comes when I translate a string with translatorSend.
Future<String> translateString(String stringToTranslate) async {
if(settingSend.sourceLangCode != settingSend.targetLangCode) {
String result;
if (isPrepared) {
result = await translatorSend.asyncTranslate(sourceText: stringToTranslate);
}
else {
settingSend.sourceTextOnRemote = stringToTranslate;
result = await sendRemoteTranslator.asyncTranslate(setting: settingSend);
}
return result;
}
else {
return stringToTranslate;
}
}
This method should translate an it String to an en String. However, it seems to call the en_it model and fails the translation:
I/flutter (28228): TRANSLATOR: it to en
I/flutter (28228): TRANSLATOR: PREPARED
I/MLLocalTranslator(28228): translate sourceLanguage: en targetLanguage: it
WHAT: vestiti usati -> vestiti usati - WHERE applicazione -> applicazione
The translation of the response, from en to it works.
I've tested other languages and that happens also with fr.
Further testing showed that the process worked with es:
WHAT: ropa usada -> Used clothing - WHERE aplicación -> application
Pls check whether you are using the new version of the Flutter plug-in.
Language packs can be used in two-way. For example, en-it can be used for en to it or it to en.
The following are for your reference:
Modify based on the plugin Demo in the official website
The same instance is used for bidirectional translation by invoking multiple times.
//Entry function
_translationMake() async {
try {
await _prepareModel_run("it","en","vestiti usati");
await _prepareModel_run("en","it","application");
} on Exception catch (e) {
print(e.toString());
}
}
_prepareModel_run(String srcLang, String dstLang, String content) async {
setting.sourceLangCode = srcLang;
setting.targetLangCode = dstLang;
try {
final bool res = await translator.prepareModel(setting: setting);
if (res) {
final String s = await _localTranslate_run(content);
if (s != null) {
print("_prepareModel_run " + content + " translate to "+s);
}
}else {
print("_prepareModel_run res false");
}
} on Exception catch (e) {
print(e.toString());
}
}
Future<String> _localTranslate_run(String Content) async {
try {
final String s =
await translator.syncTranslate(sourceText: Content);
if (s != null) {
_stopLocalTranslate();
setState(() => _translateResult = s);
return s;
} else {
print("no Translation");
setState(() => _translateResult = "no translation");
return "no translation";
}
} on Exception catch (e) {
print(e.toString());
}
}
And the log print results are as follows:
_prepareModel_run vestiti usati translate to Used clothes
_prepareModel_run application translate to applicazione
We can use HMS ML kit to translate text into different languages. The following is the info. you can take reference for.
ML services can currently translate texts between 12 languages: Simplified Chinese, English, French, Arabic, Thai, Spanish, Turkish, Portuguese, Japanese, German, Italian, and Russian.
Step 1: Text is fetched from UI and provided to ML model
Step 2: Parameters are set before making API call to server
    · Source language code
    · Desired Language code
    · String which needs to be translated.
Step 3: Once API data reaches the server ML Model translates the text into desired output
Step 4: Server returns the translated output to application.
Step 5: Application shows output to UI.
Precautions: The machine learning model is stored on cloud. An Internet call is made so its permission is required.
Below are the changes you have to do in order to run build and run the project
Open App.gradle file and add this line on top.
apply plugin: 'com.huawei.agconnect'
To use Text Translation service add this dependency to pro
mplementation 'com.huawei.hms:ml-computer-translate:1.0.3.300'
MLRemoteTranslateSetting object is being created which takes Source Language as setSourceLangCode() and Output Language as setTargetLangCode()
MLRemoteTranslator object is created by passing previously created MLRemoteTranslateSetting object to it.
You can create a Task where mlRemoteTranslator will have an async call by asyncTranslate() and we will provide user string as the input to this method.
This task will yield to 2 callbacks
addOnSuccessListener
addOnFailureListener
As the name suggests you can add your code in success listener and can add notification/Log in failure listener.
For Flutter:
First:
create MlTranslatorSettings object and instance in initState
Second:
set the settings to the translator, for example, initial language and final language of the translation, see below example.
In the properties, you can customize the type of map, controls, camera position, initial position, etc.
Here are also some detailed info. regarding how to use HMS ML kit with Flutter:
Link Hope it will be helpful to you.

Flutter: Search inside the List

I am trying to using the mobile_number plugin. Basically, I am fetching the SimCard number.
Here is the code.
String _mobileNumber = '';
List<SimCard> _simCard = <SimCard>[];
Future<void> initMobileNumberState() async {
if (!await MobileNumber.hasPhonePermission) {
await MobileNumber.requestPhonePermission;
return;
}
String mobileNumber = '';
// Platform messages may fail, so we use a try/catch PlatformException.
try {
mobileNumber = await MobileNumber.mobileNumber;
_simCard = await MobileNumber.getSimCards;
} on PlatformException catch (e) {
debugPrint("Failed to get mobile number because of '${e.message}'");
}
// 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(() {
_mobileNumber = mobileNumber;
});
}
Widget fillCards() {
List<Widget> widgets = _simCard
.map((SimCard sim) => Text(
'Sim Card Number: (${sim.countryPhonePrefix}) - ${sim.number}\nCarrier Name: ${sim.carrierName}\nCountry Iso: ${sim.countryIso}\nDisplay Name: ${sim.displayName}\nSim Slot Index: ${sim.slotIndex}\n\n'))
.toList();
return Column(children: widgets);
}
This is working fine I can see the mobile number.
But now I need to search the number inside the list.
I checked some of the questions on SO to get it done but I am not good with lists.
I tried using some of the examples and comes up with below. But this is incorrect with so many errors.
var comparenumber = _simCard.map((SimCard sim).where((sim.number) => sim.number.toLowerCase().contains(mobile.toLowerCase()).toList();
If you want to search if the list has a number or part of a number (say the result would be true searching for 641 in a list that has a number 641-819-xxxx)
you can use this code
bool searchNumber(String number) {
return _simCard.where((element) => element.number.contains(number)).isNotEmpty;
}
if you want to search for an exact number match replace element.number.contains(number) with element.number == number as in dart == for strings compare the string value, not pointers as in Java for example.
So, what is where?
where is a function in the abstract class Iterable (and lists in dart are iterable) that take a predicate or a test function and returns an iterable that has only elements that match the predicate.
returned iterable can be collected to a list or you can use some other functions or properties directly on it like isNotEmpty in our case

Reliable Dictionary and Transactions Commit

I'm facing an issue in the Reliable Dictionary where I update a particular entry, but do not commit the transaction. It appears that the transaction abort does not reset the updated entry.
In my logic, I have to check if a few seats are available in a reliable dictionary. If they are, I assign them to the Order. If one of them isn't available, I'd ideally like to abort the transaction ensuring that the previously assigned seats would roll back to their original state, since I didn't commit the transaction.
Could I be doing something wrong here?
Here is the code I'm building:
var unavailableSeats = new List<string>();
using (var tx = StateManager.CreateTransaction())
{
foreach (var requestSeat in request.Seats)
{
var match = await dict.Value.TryGetValueAsync(tx, requestSeat.ToString(), LockMode.Update);
if (!match.HasValue)
{
response.SetError($"No Seat found matching the Seat Key: {requestSeat} provided.");
return response;
}
var seatEntry = match.Value;
if (seatEntry.IsAvailable())
{
seatEntry.AssignToOrder(request.OrderId, request.RequestId.ToString());
await dict.Value.SetAsync(tx, requestSeat.ToString(), seatEntry, TimeSpan.FromSeconds(4),
cancellationToken);
}
else
{
unavailableSeats.Add(requestSeat.ToString());
}
}
if (!unavailableSeats.Any())
{
await tx.CommitAsync();
response.Success = true;
response.RequestId = request.RequestId;
return response;
}
tx.Abort();
}
You are modifying the in memory entity which is what is stored in the dictionary. You need to make a copy of the object before you modify any property. This is documented in a few places, but specifically mentioned in this article https://learn.microsoft.com/en-us/azure/service-fabric/service-fabric-work-with-reliable-collections in the common pitfalls section.
Instead of
var seatEntry = match.Value
do
var seatEntry = new SeatEntryType(match.Value) // assuming copy constructor