Cannot send data from Android 5 to Bluetooth Low Energy module - android

I am writing an open source framework to use BLE Mini module with Android and iOS mobile devices using Unity engine.
This framework should allow to establish a connection between the mobile device and the BLE Mini module, and to send/receive data using it. The framework can be theoretically adapted to work with any BLE module.
The idea is to make the existing BLE Mini frameworks (available for iOS and Android) work in Unity engine, hence I am writing native plugins for iOS and Android that will allow Unity apps use the native frameworks.
The iOS plugin is working as expected, while I am having problems writing the Android plugin.
Everything works as expected except the fact that I cannot send data to my characteristic. If I send the data the BLE Mini module does not receive it.
The code controlling the BLE Mini data reception is correct because it works when iOS sends the data. So I am pretty sure the problem is in the Android plugin.
The Android plugin is composed by Android native code that can be found here:
https://github.com/giomurru/ble-framework/tree/master/AndroidPlugin/src/com/gmurru/bleframework
and by Unity c# code that can call the public java methods: https://github.com/giomurru/ble-framework/blob/master/Unity/Assets/BLE/BLEController.cs
The code contained in RBLGattAttributes.java and RBLService.java is correct because it is the framework provided by RedBearLab and I tested it and it works correctly with native Android apps.
The code in which I need help and that probably contains the bug is the one in BleFramework.java
The BleFramework class contains a series of functions that can be called by the Unity engine. The functions are called following this order:
Call the get static method BleFramework.getInstance() to get a singleton instance of the class BleFramework. This method returns one and only one instance of the BleFramework class.
After I have the instance of the class I can call the BleFramework methods using this instance (which is always the same instance).
The methods are called following this order:
1) Call the function _InitBLEFramework from Unity. The function should initialize the BLE framework. When the initialization is finished the Android plugin answer to Unity with a OnBleDidInitialize "Success" message.
2) If Unity receives the OnBleDidInitialize "Success" message, I can call the function _ScanForPeripherals from Unity. The function scans for available BLE modules peripherals. When the available peripherals are found the plugin answer to Unity with a OnBleDidCompletePeripheralScan "Success" message.
3) If Unity receives the OnBleDidCompletePeripheralScan "Success" message, I can call the function _GetListOfDevices to get the list of found devices.
4) Once I have the list of BLE module devices I found, I can try to connect to one of them using the function _ConnectPeripheralAtIndex(int peripheralIndex). When the _mGattUpdateReceiver receives RBLService.ACTION_GATT_SERVICES_DISCOVERED I can say the connection is established and I can let Unity know I am ready to send/receive data by sending a OnBleDidConnect "Success" message.
Up to here the plugin works as expected, and the connection is established.
The problem is when I try to send data in step 5.
5) When Unity receives the OnBleDidConnect "Success" message it is ready to send data through the established connection. Hence I try to send the data by using _SendData function in the plugin. Unfortunately it does not work.
This is the code:
public void _SendData(byte[] data)
{
Log.d(TAG,"_SendData: ");
BluetoothGattCharacteristic characteristic = _map.get(RBLService.UUID_BLE_SHIELD_TX);
Log.d(TAG, "Set data in the _characteristicTx");
byte[] tx = hexStringToByteArray("fefefe");
characteristic.setValue(tx);
Log.d(TAG, "Write _characteristicTx in the _mBluetoothLeService: " + tx[0] + " " + tx[1] + " " + tx[2]);
if (_mBluetoothLeService==null)
{
Log.d(TAG, "_mBluetoothLeService is null");
}
_mBluetoothLeService.writeCharacteristic(characteristic);
}
public static byte[] hexStringToByteArray(String s) {
int len = s.length();
byte[] data = new byte[len / 2];
for (int i = 0; i < len; i += 2) {
data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
+ Character.digit(s.charAt(i+1), 16));
}
return data;
}
Just for the purpose of testing I ignored byte[] data parameter and I try to send byte[] tx data that I create inside the _SendData function using hexStringToByteArray function (that I found in this StackOverflow post: Convert a string representation of a hex dump to a byte array using Java?)
I also tried to create the tx data as:
byte tx[] = new byte[] { (byte) 0xfe, (byte) 0xfe, (byte) 0xfe };
or to send the data directly like this:
public void _SendData(byte[] data)
{
Log.d(TAG,"_SendData: ");
BluetoothGattCharacteristic characteristic = _map.get(RBLService.UUID_BLE_SHIELD_TX);
Log.d(TAG, "Set data in the _characteristicTx");
characteristic.setValue(data);
Log.d(TAG, "Write _characteristicTx in the _mBluetoothLeService: " + data[0] + " " + data[1] + " " + data[2]);
if (_mBluetoothLeService==null)
{
Log.d(TAG, "_mBluetoothLeService is null");
}
_mBluetoothLeService.writeCharacteristic(characteristic);
}
In all the cases I failed to send the data.
I really can't understand why this is happening. The code I am using to search ble devices, establish connection, send receive data is very similar to the Android native samples available in ReadBearLab github page: https://github.com/RedBearLab/Android/tree/master/Examples
The only difference is that I am not extending Activity.
I tried to make BleFramework class an extension of Activity but it didn't work. The problem I had was that while BleFramework activity was running I was not able to send messages back to Unity using the UnityPlayer.UnitySendMessage function.

I answer my own question just for reference if anybody is interested in the solution I found.
I fixed the bug by updating the code to the latest Android APIs. Please check out the commits from June 15th 2019 to June 22nd 2019 in the repository if you are interested in the modifications. In particular the commit named "Android tx/rx works"
https://github.com/giomurru/ble-framework

Related

Xamarin SqlServer cant get a connection

I'm building an app with the Entity Framework on Xamarin that lets me compare some data. But when I start my "fetchdata" function, I receive the Error:
System.Data.SqlClient.SqlException (0x80131904): Snix_Connect (provider: SNI_PN7, error: 35 - SNI_ERROR_35)Snix_Connect (provider: SNI_PN7, error: 35 - SNI_ERROR_35)
I see many posts about Xamarin / Android & that it is not possible to get a connection to a SQL Server. Is there any way to fetch data from a SQL Server with .NET Core on Xamarin?
This is the string I put into SQL_Class folder with Sql_Common.cs
Fill up the brace brackets with actual parameters (removing the brace brakets too).
public static string SQL_connection_string = #"data source={server_address};initial catalog={database_name};user id={user_id};password={password};Connect Timeout={seconds}";
Then I access whenever I need it from any xamarin code just like we use in our asp.net c#
This works for me on my app without any issues.
using (SqlConnection Sql_Connection = new SqlConnection(Sql_Common.saralEHR_connection_string))
But as #Jason mentioned in his first reply, I too would get once again check the security part. I fexperienced before publishing Package to Google Play, they encrypt the App files with Hash Key Code and then only it gets upload to server
Yes it is possible (HuurrAYY!):
Im new in .net core, c# and so on and for me it was a hell of a work to get it working..
So here for the other noobs who are seeking for Help:
Guide´s i used:
Building Android Apps with Entity Framework
https://medium.com/#yostane/data-persistence-in-xamarin-using-entity-framework-core-e3a58bdee9d1
https://blog.xamarin.com/building-android-apps-entity-framework/
Scaffolding
https://cmatskas.com/scaffolding-dbcontext-and-models-with-entityframework-core-2-0-and-the-cli/
How i did it:
Build your normal Xamarin app.
create new .net solution like in the tutorials (DONT WRITE YOUR Entity Framework CLASSES)
create a third solution what has to be a .net core console application
Scaffold your DB in your CONSOLE application move all created classes & folders in your "xamarin .net" solution & change the namespaces
Ready to Go!
Side Node: NuGets you need in every solution:
Microsoft.EntityFrameworkCore
Microsoft.EntityFrameworkCore.SqlServer
[EDIT: NuGets you need in every solution]
I am doing this way (working snippet):
string connectionString = #"data source={server};initial catalog={database};user id={user};password={password};Connect Timeout=10";
string databaseTable = "{table name}";
string selectQuery = String.Format("SELECT count(*) as Orders FROM {0}", databaseTable);
try
{
using (SqlConnection connection = new SqlConnection(connectionString))
{
//open connection
connection.Open();
SqlCommand command = new SqlCommand(selectQuery, connection);
command.Connection = connection;
command.CommandText = selectQuery;
var result = command.ExecuteScalar().ToString();
//check if there is result
if(result != null)
{
OrdersLabel.Text = result;
}
}
}
catch (Exception ex)
{
OrdersLabel.Text = ex.Message;
}
It is working fine, but API call more elegant.
I hope it helps.

Qt BLE For Android: Cannot read value of characteristic for Custom Service

Here is the setup:
A coworker created a small firmware that changes the value of a custom characteristic within a custom service (non standard unique 128 bit UUID) about once every second. The device used to transmit uses a BLE (Bluetooth low power) implementation.
I needed to implement a small App (as a working example ONLY) to monitor said value. However I've run into a small problem. I've follwed the instructions here: http://doc.qt.io/qt-5/qtbluetooth-le-overview.html and I've manged to discover the service and "read it" (I get us UUID) by using this code:
void BLETest::on_stateChanged(QLowEnergyService::ServiceState state){
#ifdef DBUG
logger->out("Service Monitor State: " + lowEnergyServiceStateToString(state),Logger::LC_ORANGE);
#endif
if (state == QLowEnergyService::ServiceDiscovered){
QString chars = "";
QList<QLowEnergyCharacteristic> clist = monitoredService->characteristics();
for (int i = 0; i < clist.size(); i++){
chars = clist.at(i).uuid().toString() + " - " + clist.at(i).name() + ": " + QString(clist.at(i).value());
chars = chars + ". Value size: " + QString::number(clist.at(i).value().size()) + "<br>";
}
if (chars.isEmpty()){
chars = "No characteristics found";
}
logger->out(chars);
}
}
Now this prints the UUID of the service but the size of the value byte array is zero. Using another (private App) we can actually see the value field for the characteristic in that service changing. Furthermore, even though there was a connection done to the service's object characteristicChanged singal, that signal is never triggered, which I imagine is because the characteristic value can't be read.
My question is: Is there anything wrong with the code that you can't think of? Or is it simply that is not possible to monitor custom services and characteristics with the current BLE implementation of Qt Bluetooth?
PD: I'm using Qt 5.7.1
you must enable the chracteristic notification by write 0x01 to client characteristic configuration descriptor (CCCD).
foreach(QLowEnergyCharacteristic c, srv->characteristics()){
QLowEnergyDescriptor d = c.descriptor(QBluetoothUuid::ClientCharacteristicConfiguration);
if(!c.isValid()){
continue;
}
if(c.properties() & QLowEnergyCharacteristic::Notify){ // enable notification
srv->writeDescriptor(d, QByteArray::fromHex("0100"));
}
if(c.properties() & QLowEnergyCharacteristic::Indicate){ // enable indication
srv->writeDescriptor(d, QByteArray::fromHex("0200"));
}
}

i want to create android app to control arduino car with bluetooth

my project has 2 steps:
Establish a connection between my phone and the arduino board
Use accelerometer sensor to move the car
The motion part i can handle it, but i can't find a way to use bluetooth. I just can't figure how to work with this Api.
What should i do to connect to the arduino and start sending signals to it?
Check this link out, its a Guide on Connecting Android Device with Arduino and Bluetooth
I'll just paste the Steps here, in case the link expires someday.
At the top of your source code, include these libs.
#include "SoftwareSerial.h"
#include "Bluetooth.h"
To start using it, at the top of your source declare a public variable to access it:
Bluetooth *blue = new Bluetooth(2, 3);
With Bluetooth(RX_Pin, TX_Pin)
The default pin is 1234, name is “PNGFramework” and baudrate is 9600
Now, on your Setup(), add the follow line:
void setup(){
Serial.begin(9600);
blue->setupBluetooth();
}
Send a message when we receive some data from Serial.
void loop(){
String msg = blue->Read();
if(msg.length() > 1){
Serial.print("Received: ");
Serial.println(msg);
}
if(Serial.available()){
blue->Send("Example message#");
}
}
In Android
First, create a bluetooth object, use the following code, make sure to use the same RobotName that you used in the Arduino project. (default is “PNGFramework”).
BluetoothArduino mBlue = BluetoothArduino.getInstance("PNGFramework");
To connect with the Arduino, add the command bellow:
mBlue.Connect();
Now, to read a message, run the command:
String msg = mBlue.getLastMessage();

Issue with phonegap/cordova android websocket plugin - onmessage is not called

I am using this plugin: https://github.com/mkuklis/phonegap-websocket/*.
Unfortunately, onmessage is not called when we receive a message.
var ws = new WebSocket("ws://" + window.location.host + "" + "/my/socket");
ws.onopen = function() {
console.log("wsStatus Connected to WebSocket server!");
};
ws.onmessage = function(e) {
alert(e.data);
};
This is never called - which is bizarre because onopen is called. Is there anything specific I need to do/check - add a listener? I looked in the example code for the plugin and see the event ping is used rather than onmessage.
* having tried most of the options here: Phonegap websocket plugin with android version >4.0.3 not working and finding this is the only one which appears to work.
since websocket doesnt support android<4.2, the above code fails.. you should try cross browser socket supported with fallback mode included, socket.io
link

int32 decoding with google protobuf between android and visual-c++

I'm having a problem communicating protobufs through tcp sockets where the client is working in Android emulator (running eclipse + ADP + SDK android-15) and the server in C++ (Visual Studio 2010), both on Windows 7. Protobuf version: 2.4.1
.proto
package pck;
option java_package = "my.messages.package";
option java_outer_classname = "ClassName";
option optimize_for = LITE_RUNTIME;
message msg_name {
optional int32 VARIABLE = 6;
//moro...
}
client: android side
msg_name outMsg = to_send.build();
ByteArrayOutputStream output = new ByteArrayOutputStream();
outMsg.writeTo(output);
//now output.toString() is sent via tcp socket...
What I get, and the reason I'm asking here is: communication works, messages reach server endpoint, but values for the int32 variable are as following:
(values sent on android ->> values read on visual-c++ side)
android: [0, 127] ->> visual-c++: [0, 127] Works fine, ok.
android: [128, 255] -->> visual-c++: 3104751
android: [256, 383] -->> visual-c++: 5201903
...
So, is it a problem of encoding? Is my problem with protobufs on client-android side? (I must say it's my first day on android, opss!)

Categories

Resources