Detect beacons uuid and name with react native - react-native

I have simulated a beacon from computer and i'm trying to read beacon info (uuid,identifier etc) from my react native app.
I decided to use this library
https://github.com/dotintent/react-native-ble-plx as the library.
The issue i'm facing is although it shows some devices when i scan, the name,uuid and other info shows as null.
For ex:
'device', { serviceUUIDs: null,
isConnectable: null,
overflowServiceUUIDs: null,
txPowerLevel: null,
serviceData: null,
manufacturerData: 'TEACFCd6h5jcoxKqh9ACQqwTAAOBqZYcxQ==',
name: null,
mtu: 23,
rssi: -47,
solicitedServiceUUIDs: null,
localName: null,
id: '32:BD:32:6C:E9:C2',
And this is my code
const bluetoothInstance = new BleManager();
const scanAndConnect = () => {
bluetoothInstance.startDeviceScan(null, { allowDuplicates: true }, (error, device) => {
console.log('device', device);
console.log('error', error);
if (error) {
// Handle error (scanning will be stopped automatically)
return;
}
if (device?.name === 'MyProjectName') {
bluetoothInstance.stopDeviceScan();
} else {
// bluetoothInstance.stopDeviceScan();
}
});
};
useEffect(() => {
bluetoothInstance.onStateChange((state) => {
console.log('state', state);
if (state === 'PoweredOn') {
scanAndConnect();
}
}, true);
}, []);
How i can read the beacon uuid and name? Is there any other library you can recommend? Or is there something missing in the code? Any help would be appreciated.

The scanning code is probably working fine. The information you are looking for is either not always present or present in a different field.
The iBeacon Proximity UUID is actually embedded inside the manufacturerData field. However, on iOS devices this field is deleted by the operating system for all iBeacon packets as a security mechanism by Apple. Apple forbids using the CoreBluetooth framework (used by react-react-native-ble-plx under the hood) to detect iBeacon. On iOS you must use CoreLocation. For that you can try react-native-beacons-manager. For Android, react-native-ble-plx will work fine to detect iBeacon but you must parse out the beacon fields yourself from the manyfacturerData field.
The Bluetooth name is only populated (in the name field) if a scan response packet containing the name has been received recently before the main advertisement packet. It is unclear how iOS will handle this process for forbidden iBeacon advertisements, but it will probably work for non-iBeacon advertisements just fine. On Android it will work fine, too. Just do not expect it to be populated 100% of the time on either platform.

Related

React Native - Is there a way to use bluetooth in peripheral mode?

I am developing an app in ReactNative offline.
One of the functionalities is to use bluetooth to synchronize the data (that the app was collecting) with other devices that use the same app.
I started to develop this task with the react-native-ble-manager library, i can connect from device A to device B, but I don't understand how to listen to the incoming connection in device B. I need to know this to show a certain view.
can anybody help me?
I am using the correct library?
Thanks!
You can't use only the react-native-ble-manager for this project. The library states in its readme that it is based on cordova-plugin-ble-central, which can only act as a central. For a BLE connection you need a central and a peripheral.
Take a look at react-native-peripheral. It allows you to act as a perihperal, create a characteristic with some data, add it to a service and register it so other devices can find it. This is their usage example:
import Peripheral, { Service, Characteristic } from 'react-native-peripheral'
Peripheral.onStateChanged(state => {
// wait until Bluetooth is ready
if (state === 'poweredOn') {
// first, define a characteristic with a value
const ch = new Characteristic({
uuid: '...',
value: '...', // Base64-encoded string
properties: ['read', 'write'],
permissions: ['readable', 'writeable'],
})
// add the characteristic to a service
const service = new Service({
uuid: '...',
characteristics: [ch],
})
// register GATT services that your device provides
Peripheral.addService(service).then(() => {
// start advertising to make your device discoverable
Peripheral.startAdvertising({
name: 'My BLE device',
serviceUuids: ['...'],
})
})
}
})
There is a section about dynamic values where they explain how you can use the onReadRequest and onWriteRequest callbacks to listen to read and write operations on the peripheral and even return dynamic values on each read request:
new Characteristic({
uuid: '...',
properties: ['read', 'write'],
permissions: ['readable', 'writeable'],
onReadRequest: async (offset?: number) => {
const value = '...' // calculate the value
return value // you can also return a promise
},
onWriteRequest: async (value: string, offset?: number) => {
// store or do something with the value
this.value = value
},
})

How to send session info and do automated page tracking in expo react native segment and amplitude integration

I am using Segment[expo-analytics-segment] to send tracking info to Amplitude(Configured as the destination in app.segment.com) in an expo react native app. Though I am sending session info(epoch time) - The session always gets registered as -1, hence I am unable to access 'funnel' feature in Amplitude.
Also - How do we enable automatic page tracking in expo segment+amplitude configuration?
This is what I have done so far in App.tsx
Segment.initialize({
androidWriteKey: 'androidKey', // from Segment
iosWriteKey: 'iOsKey', // from segment
});
global.epochInMilliSeconds = Date.now();
Segment.identifyWithTraits(
user.sub,
{ email: 'notgood#gmail.com' },
{
event: 'App Started',
integrations: {
Amplitude: {
sessionId: global.epochInMilliSeconds,
},
},
}
);
Segment.trackWithProperties(
'App Started',
{ email: 'fancyemail#gmail.com' },
{ integrations: { Amplitude: { session_id: global.epochInMilliSeconds } } }
); <------------------- Did not work. Session id is -1**
Segment.track('App Started'); // <-----------------------Session id is -1
More info - https://github.com/expo/expo/issues/10559
I followed this example for the above code sample: https://community.amplitude.com/instrumentation-and-data-management-57/how-do-we-set-session-in-amplitude-while-using-segment-in-cloud-mode-111
Amplitude website mentions that session Ids are not automatically tracked.
https://help.amplitude.com/hc/en-us/articles/217934128-Segment-Amplitude-Integration
In case the link changes, it says:
6. Why do all of my events have a sessionId of -1?
You need to use Segment's client-side bundled integration to have our native SDKs track Session IDs for you.

Can't connect to a device using react-native-bluetooth-classic

I am trying to send data from one android phone to another using "react-native-bluetooth-classic". I successfully run the example in the repo, but I am not able to connect to the paired devices. Sometimes, I can connect to a phone but the other can't connect back.
Is there any configuration I should to the phone's bluetooth?
Merged the pull request last night, should be able to connect from one device to another with the provided BluetoothClassicExample app using the Accept Connection button at the bottom of the device list.
async acceptConnections() {
console.log("App is accepting connections now...");
this.setState({ isAccepting: true });
try {
let connectedDevice = await RNBluetoothClassic.accept();
if (connectedDevice) { // Undefined if cancelled
this.setState({ connectedDevice, isAccepting: false });
}
} catch(error) {
console.log(error);
this.refs.toast.show(
`Unable to accept client connection`,
DURATION.LENGTH_SHORT
);
this.setSTate({ isAccepting: false });
}
}
This is only available on Android as from what I've seen, there are no ways to see the connection on IOS. I was able to connect my Android to my IOS using the example app, but without the Android MFi protocols, the data just gets sent into the IOS void.

Retrying Geolocation after error in React Native

I am using React Native's Geolocation API to get user's location or ask user to turn location on:
// Handle PermissionsAndroid
this.watchID = navigator.geolocation.watchPosition(
(position) => {
// Update position
},
(error) => {
switch (error.code)
{
Case 1: {
// Ask user to turn on Location (Permission has already been asked for)
}
}
}
);
Now, I want to retry the watchPosition if user ever turned location on at some later point.
Using AppState, I tried getting an event if user started to interact with the notification bar (maybe user is trying to turn on Location). But it only calls back if application is sent to background or is activated again (but not during notification bar interactions).
Since Geolocation conforms with W3 standards, I tried searching for solutions in web development world. But the only solution that I found, was using iFrame which is browser-only.
Also, a non-elegant solution would be to setInterval (say every 5 seconds) and then clearInterval only if a position has been returned.
Is there a proper way to do this?
You should initiate the flow by getting the current location first, then create the watch. The following is from the Geolocation docs.
navigator.geolocation.getCurrentPosition(
(position) => {
if (position) {
//Handle first position
}
},
(error) => (console.log(error)),
{enableHighAccuracy: true, timeout: 20000, maximumAge: 1000}
);
this.watchID = navigator.geolocation.watchPosition((position) => {
if (position) {
// Handle new position
}
});
I've found this recovers from location errors itself, as well as handling permission requests (tested on iOS 10).

difference between udid and client_identification_sequence

I cannot understand somethings about the push notification with quickblox
I have a chat (a webchat) in a webview in a Xamarin apps (i know isn't very clever approach)
i try to create a subscrition via javascript
but i cannot undestand the way for calculate
uuid and client_identification_sequence
var params = {
notification_channels: 'gcm',
device: {
platform: 'android',
udid: '538a068a-d66a-44d4-86c8-18ffed7f20d8'
},
push_token: {
environment: 'development',
client_identification_sequence: ''
}
}; 
QB.pushnotifications.subscriptions.create(params, function (err, res) {
debugger;
if (err) {
debugger;
// error
} else {
debugger;
// success
}
});
i've tried to calculate the uuid with "Xam.Plugin.DeviceInfo"
but what is the way for client_identification_sequence?
should I take this value from the "apns" (for apple push notification) but where?
I have the same roblem with the xamarin project
var d = await wbWrapper.SubscribeForPushNotificationAsync([pushtoken], CrossDeviceInfo.Current.GenerateAppId());
thankyou
uuid - it's your device unique identifier. It's actually can be anything that uniquely identify current particular device.
client_identification_sequence - it's your push token.
For Android - it's registration id (or registration token).
For iOS - it's device token