I'm using Cordova/Phonegap plugin Ble Central to connect to BLE devices using Android Phone.
As per the documentation on github code is :
onConnect = function(device) {
ble.isConnected(deviceId,
function() {
console.log("Connected");
},
function() {
console.error("Disconnected");
}
);
ble.readRSSI(deviceId, function(rssi) {
console.log('read RSSI',rssi,'with device', deviceId);
});
};
ble.connect(deviceId, onConnect, app.onError);
Even though ble.isConnected() fucntion returns true, RSSI value never returns.
What could be the issue here ?? Has anyone tried using cordova-plugin-ble-central to retrieve RSSI ?
Try retrieving rssi from Peripheral data.
onConnect = function(device) {
console.log('rssi' + device.rssi);
};
See if it gives a proper value.
Related
I encountered a strange problem when trying to unpair and pair again with my smartphone. Currently I write a C# application on UWP (Windows 10) for BLE connection with a remote device. I use my smartphone with nRF Connect App as the peripheral.
After being paired for a while (and being inactive), when unpairing and pairing again, the application gets stuck when trying to pair again.
I broke everything down to the most basal application I could create. This is a Console App that scans the existing devices and then unpairs and pairs with the selected device:
using BLE_Test;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace ConsoleApp1
{
class Program
{
static async Task Main(string[] args)
{
Dictionary<ulong, string> uuidDict = BleModule.Scan().Result;
Console.WriteLine("Devices found:");
int i = 0;
foreach (var uuid in uuidDict.Keys)
Console.WriteLine(string.Format("ID: {0}, UUID: {1}, Local Name: {2}", i++, uuid, uuidDict[uuid]));
Console.WriteLine("Select ID!");
int id = int.Parse(Console.ReadLine());
ulong selectedUuid = (uuidDict.ElementAt(id)).Key;
await BleModule.Unpair(selectedUuid);
await BleModule.Pair(selectedUuid);
Console.ReadLine();
}
}
}
It calls an UWP DLL called "BLE_Test" with the class "BleModule":
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Windows.Devices.Bluetooth;
using Windows.Devices.Bluetooth.Advertisement;
using Windows.Devices.Enumeration;
namespace BLE_Test
{
public class BleModule
{
public static async Task<Dictionary<ulong, string>> Scan()
{
var uuidDict = new Dictionary<ulong, string>();
BluetoothLEAdvertisementWatcher watcher = new BluetoothLEAdvertisementWatcher();
watcher.Received += (BluetoothLEAdvertisementWatcher sender, BluetoothLEAdvertisementReceivedEventArgs eventArgs)
=> AddAdvertisement(eventArgs, uuidDict);
watcher.Start();
await Task.Delay(10000);
watcher.Stop();
return uuidDict;
}
private static void AddAdvertisement(BluetoothLEAdvertisementReceivedEventArgs eventArgs, Dictionary<ulong, string> uuidDict)
{
if (uuidDict.ContainsKey(eventArgs.BluetoothAddress) == false)
uuidDict.Add(eventArgs.BluetoothAddress, eventArgs.Advertisement.LocalName);
}
public static async Task Pair(ulong uuid)
{
Console.WriteLine("Pairing...");
var bluetoothLEDevice = await BluetoothLEDevice.FromBluetoothAddressAsync(uuid);
if (bluetoothLEDevice == null)
{
Console.WriteLine("UUID not found!");
return;
}
DeviceInformationCustomPairing customPairing = bluetoothLEDevice.DeviceInformation.Pairing.Custom;
customPairing.PairingRequested += (DeviceInformationCustomPairing sender, DevicePairingRequestedEventArgs args) => args.Accept(); // We auto-accept numeric comparison result for the sake of simplicity
DevicePairingResult result = await customPairing.PairAsync(DevicePairingKinds.ConfirmPinMatch);
Console.WriteLine("Pairing Result: " + result.Status.ToString());
}
public static async Task Unpair(ulong uuid)
{
Console.WriteLine("Unpairing...");
var bluetoothLEDevice = await BluetoothLEDevice.FromBluetoothAddressAsync(uuid);
if (bluetoothLEDevice == null)
{
Console.WriteLine("UUID not found!");
return;
}
DeviceUnpairingResult result = await bluetoothLEDevice.DeviceInformation.Pairing.UnpairAsync();
Console.WriteLine("Unpairing Result: " + result.Status.ToString());
}
}
}
If I start the program for the first time, the pairing works fine (the unpairing will be ignored as the devices are not paired yet). If I start it immediately again afterwards, it also works fine. Unpairing and pairing will both take place. But if I wait a while (typically 5-10 minutes) while not doing anything, when I start the program again, it will unpair, but then it will wait indefinitely for PairAsync() to return. No coupling request will show on the nRF Connect App, and no PairingRequested event will appear.
Aborting the stuck program and restarting it won't help. In this case, even though the smartphone is found by the BluetoothLEAdvertisementWatcher, BluetoothLEDevice.FromBluetoothAddressAsync(uuid) will return null and the device can't be paired anymore. This can only be resolved by restarting the computer or switching off and on the advertisement in the nRF Connect App, as in this case a new random BLE Address is created for the device.
I have taken a snapshot of the BLE events using Btetlparse and Wireshark. It seems that there is a problem with a malformed package:
However, I don't really understand what is going wrong. Is this a problem of the nRF Connect App? Or the UWP commands? Or did I do something wrong? I tried two different smartphones (a Samsung Galaxy and an Oppo), so I doubt that it is a problem of the smartphone. I also added a DeviceWatcher, but this didn't change anything. Can anyone help me here?
I have an Android App build in Apache Cordova, it works with Bluetooth 4.0(BLE) the plugin GitHub repostory indicates this shape for send information to a ble device (in my case a HM10 module):
this function writes data to a characteristic.
ble.write(device_id, service_uuid, characteristic_uuid, data, success, failure);
Description
Function write writes data to a characteristic.
Parameters:
device_id: UUID or MAC address of the peripheral
service_uuid: UUID of the BLE service
characteristic_uuid: UUID of the BLE characteristic
data: binary data, use an ArrayBuffer
success: Success callback function that is invoked when the connection is successful. [optional]
failure: Error callback function, invoked when error occurs. [optional]
I have tried to send data for this way but failure function is called immediately
function startBed() {
var UiidS="FFE0"; //UUID SERVICE: AT+UUID? => 0xFFE0
var UiidC="FFE1"; //UUID CHARACTERISTICS AT+CHAR? => 0xFFE1
var data = new Uint8Array(1);
data[0] = 1;
setTimeout(ble.write(hMac,UiidS,UiidC,data.buffer,success,failure),2000);
function success() {
document.getElementById("btstate1").innerHTML = "Dato enviado!!!";
}
function failure() {
document.getElementById("btstate1").innerHTML = "Dato NO enviado!!!";
var time=2000;
navigator.vibrate(time);
}
}
if I take the text box value and send it directly, the HM10 receives an unrecognized characters like Ó.
var UiidS="FFE0";
var UiidC="FFE1";
var dato =document.getElementById("btstate6").value;
setTimeout(ble.write(hMac,UiidS,UiidC,dato,success,failure),2000);
In conclution
I don't know why the module not receive the data correctly or in other cases the data isn't send. Maybe is for something of UUID.
I'm still trying to solve my problem, I confirmed that the UUID is correct, but I have the doubt about whether I am sending the data well as ArrayBuffer
Using a different plugin (https://github.com/randdusing/cordova-plugin-bluetoothle)
I used the following
var encodedString = bluetoothle.bytesToEncodedString([145,0,14,0,255]);
bluetoothle.write(this.writeSuccess.bind(this), this.writeError.bind(this), {
"value": encodedString,
"service": this.serviceUuid,
"characteristic": this.serviceCharacteristic,
"type": "noResponse",
"address": this.currentConnectedDevice
});
Where
// From plugin source:
encodedStringToBytes: function(string) {
var data = atob(string);
var bytes = new Uint8Array(data.length);
for (var i = 0; i < bytes.length; i++)
{
bytes[i] = data.charCodeAt(i);
}
return bytes;
},
bytesToEncodedString: function(bytes) {
return btoa(String.fromCharCode.apply(null, bytes));
},
I hope this helps
Advertising data is in readable format for iPhone, but it is in decimal format for android. How to read and interpret the advertising packet for android.
this.scanner = this.ble.scan(["00EDSE-0000-00AE-9VVQ-9125475145125"], 1).subscribe((response) => {
console.log("success scan.." + JSON.stringify(response));
this.ble.connect(response.id).subscribe((response) => {
this.toast.show("Successfully paired", '2000', 'bottom').subscribe((toast) => {
console.log(toast);
this.spinnerDialog.hide();
});
Android advertising data is received as an ArrayBuffer. You need to convert it to a human readable string using javascripts String.fromCharCode method:
let stringResult = String.fromCharCode.apply(null, new Uint8Array(buffer));
Where buffer is the advertising property of you response object. You can find the ionic-native docs for BLE here.
I'm developing android app in cordova where i want read data sent from bluetooth.
I'm testing on Android Lolipop (Sony XPERIA M2) and bluetooth barcode scanner.
For this purpose i tried to use plugins for cordova.
Tested:
https://www.npmjs.com/package/cordova-plugin-bluetoothle
https://www.npmjs.com/package/cordova-plugin-networking-bluetooth
https://github.com/tanelih/phonegap-bluetooth-plugin
https://github.com/don/BluetoothSerial
and many others.
Every time i was possible to find my device but none of these plugins allow me to connect to scanner.
I got error: READ FAILED, SOCKET MIGHT CLOSED OR TIMEOUT, ERROR CODE: 9
My mobile is connected and paired with scanner correctly but i cant figure out why i cant connect via my app.
EDIT:
onDeviceReady: function () {
var dev = {};
app.receivedEvent('deviceready');
window.bluetooth.enable(function () {
alert("SUCCESS");
}, function () {
alert("FAILED");
});
window.bluetooth.startDiscovery(onDeviceDiscovered, onDiscoveryFinished, onError);
function onDeviceDiscovered(device) {
alert("Found device " + device.address);
if (device.address === "40:83:DE:4B:D4:12") { // address of scanner
window.bluetooth.getUuids(onUuidsRetrieved, onError, device.address);
}
}
function onDiscoveryFinished() {
alert("SUCC FINISHED");
if (dev.address === "40:83:DE:4B:D4:12") {
alert("Trying to connect...");
window.bluetooth.connect(onConnected, onErrorConn, {
address: dev.address,
uuid: dev.uuids[0]
});
}
}
function onConnected() {
alert("Connected");
}
function onUuidsRetrieved(device) {
alert(device.address + " UUID: " + device.uuids);
if (device.address === "40:83:DE:4B:D4:12") {
dev = device;
}
}
function onError() {
alert("ERROR");
}
function onErrorConn(error) {
alert(error.code + " " + error.message);
}
}
Was someone facing to same issue ?
Thanks for all your help.
try using the cordova-plugin-networking-bluetooth for the central and for the central I have used cordova-plugin-ble-peripheral.
works great, able to send service and chariteristics changes, and do file transfer
When gps is enabled geolocationsuccess work perfectly. But when gps diabled it not calling geolocationerror in mobile device.Working on ionic framework using phonegap geolocation for checking is gps enable or not. codes are here
var locOptions = {
maximumAge : 10000,
timeout : 5000,
enableHighAccuracy : true
};
function onLocationSuccess(position) {
console.log(position);
// alert('success');
$rootScope.pos = new google.maps.LatLng(position.coords.latitude,
position.coords.longitude);
var geocoder = new google.maps.Geocoder();
geocoder.geocode({'latLng': $rootScope.pos}, function address(results, status) {
if (status == google.maps.GeocoderStatus.OK) {
if (results[1]) {
$rootScope.currentposition = results[1].formatted_address;
console.log($rootScope.currentposition);
if($scope.switchToState=='signedIn'){
$ionicLoading.hide();
$http.get($rootScope.url +'api/price/?key=movo1026868hk738hkl')
.success(function(response) {
$rootScope.truckfare=response.datasets;
});
console.log('reached here2');
$state.go('app.home');
}
else{
$ionicLoading.hide();
$state.go('start');
}
}
}
});
}
// onError Callback receives a PositionError object
//
function onLocationError(error) {
alert("Geolocation error: #" + e.code + "\n" + e.message);
}
navigator.geolocation.getCurrentPosition(onLocationSuccess, onLocationError, locOptions);
Geolocation API will not give you an error if the GPS is off because that is not an error state. It will just timeout if it is not able to get a lock in the time limit you specify.
Unfortunately, this is a real problem. If you turn off GPS and Geolocation API times out, you will not be able to make it work again unless you restart a whole application. So even if you turn GPS back online API will not work again unless an application is restarted.
There's a simple workaround here. Before you initialize Geolocation API check if GPS is online. You can do that using this PhoneGap/Cordova plugin:
https://github.com/mablack/cordova-diagnostic-plugin
Essentially, this plugin will solve your initial problem + problem I mentioned you before.