Send data using react-native-ble-plx package - javascript

In order to realize a project of connected objects. I need to implement a Bluetooth connection between the various devices.
Here, the goal is to create an application in React Native and then send data from this application to my Raspberry. This Raspberry has a connected HC-08 module that takes care of Bluetooth communication.
Now, I would like to use react-native-ble-plx library to send data through Bluetooth. I'm able to connect my Android to the module. But I don't understand how to send data ...
Here's my code :
constructor() {
super()
this.manager = new BleManager()
}
componentWillMount() {
console.log("mounted")
const subscription = this.manager.onStateChange((state) => {
if (state === 'PoweredOn') {
this.scanAndConnect();
subscription.remove();
}
}, true);
}
scanAndConnect() {
this.manager.startDeviceScan(null, null, (error, device) => {
if (error) {
// Handle error (scanning will be stopped automatically)
return
}
console.log(device.name)
// Check if it is a device you are looking for based on advertisement data
// or other criteria.
if (device.name === 'SH-HC-08') {
// Stop scanning as it's not necessary if you are scanning for one device.
this.manager.stopDeviceScan();
console.log(`Found ${device.name}`)
this.setState({
device: device
})
// Proceed with connection.
device.connect()
.then((device) => {
console.log(device)
return device.discoverAllServicesAndCharacteristics()
})
.then((device) => {
console.log(device)
})
.then((result) => {
// Do work on device with services and characteristics
//console.log(this.manager.characteristicsForService("00001800-0000-1000-8000-00805f9b34fb"))
console.log(result)
console.log("connected")
})
.catch((error) => {
// Handle errors
console.log(error)
});
}
});
}
send() {
this.manager.writeCharacteristicWithResponseForDevice("58:7A:62:4F:EF:6D",
this.device.serviceUUIDs[0],
this.manager.characteristicsForDevice(this.device.id),
"ok")
.catch((error) => {
console.log('error in writing data');
console.log(error);
})
}
I would like to have a send method that will send data whenever I want to. But I don't really understand how it works :/
Could someone help me or even give me an example ? I would be really appreciated.
Best regards.

I had success implementing the following:
scanAndConnect() {
this.manager.startDeviceScan(null, null, (error, device) => {
this.info("Scanning...");
console.log(device);
if (error) {
this.error(error.message);
return
}
if (device.name ==='MyDevice') {
this.info("Connecting to Tappy");
this.manager.stopDeviceScan();
device.connect()
.then((device) => {
this.info("Discovering services and characteristics");
return device.discoverAllServicesAndCharacteristics()
})
.then((device) => {
this.info(device.id);
device.writeCharacteristicWithResponseForService('12ab', '34cd', 'aGVsbG8gbWlzcyB0YXBweQ==')
.then((characteristic) => {
this.info(characteristic.value);
return
})
})
.catch((error) => {
this.error(error.message)
})
}
});
Where I use 12ab, insert the UUID of your BLE service. Similarly, where I use 34cd, insert the UUID of your BLE characteristic. Lastly, include a base64 encoding of whatever message you're trying to send where I have aGVsbG8gbWlzcyB0YXBweQ==.
Hope this helps.

Related

Structuring read/write characteristics code In React Native for ble-plx

needing a guide for how to layout functionality for a React Native app that's pairing with an ESP32 that will eventually feed back weight readings using read Characteristic, and be able to toggle a DI via write to a characteristic.
i can currently scan and connect to the ESP32 and show the values from the ESP32 (random changing values for now) and also toggle the LED via changing a hardcoded value. But i want to be able to do this via a button in the app.
const scanDevices = () => {
//set isLoading to true to show activity Indicator
setIsLoading(true);
//scan for devices, (UUIDs, ScanOptions(error, device))
manager.startDeviceScan(null, null, (error, device) => {
if (error) {
console.log("Error in scanning", error.message)
return;
}
if (device) {
//if a device is scanned, add the name & id details into the scannedDevice object via reducer
dispatch({type: 'DEVICE_ADD', payload: {name: device.name, id: device.id}});
}
});
//end scan after 3 seconds, stop the activity indicator swirly thing
setTimeout(() => {
console.log("Scan timeout after 5 seconds");
manager.stopDeviceScan();
setIsLoading(false);
}, 5000);
};
const deviceConnect = (device) => {
console.log("Connecting to:", device.name, device.id);
setIsConnected(true);
setConnectedDevice(device);
manager.connectToDevice(device.id)
.then((device) => {
console.log("Discovering all services & chars");
return device.discoverAllServicesAndCharacteristics()
}).then((device) => {
// console.log("Write Value inside deviceConnect:", writeValue)
console.log("Device:", device.name, "has been connected.");
return deviceNotifications(device, writeValue);
}).catch((error) => {
console.log("device connect error:", device.name, error)
//JSON.stringify(error)
});
};
const deviceNotifications = async (device, writeValue) => {
const service = "af493e2a-f002-11eb-9a03-0242ac130003";
const characteristicTX = "af49423a-f002-11eb-9a03-0242ac130003";
const characteristicRX = "af49414a-f002-11eb-9a03-0242ac130003";
if (device) {
try {
device.monitorCharacteristicForService(service, characteristicTX, (error, characteristic) => {
if (error) {
console.log(error);
} else {
setCharacteristicValue(() => {
return [{id: uuid.v4(), value: (base64.decode(characteristic.value))}];
})}
});
device.writeCharacteristicWithResponseForService(service, characteristicRX, base64.encode(writeValue));
console.log("Writing to RX:", writeValue);
}
catch (err) {
console.log("deviceNotification catch error:", err);
}
};
}
I'm getting pretty confused trying to sort through the [ble-plx documentation][1] ([github wiki][2])
Currently the only way i can get the LED to turn on/off, is i have the LED toggle section inside the deviceNotifications async function and have to manually change the value that's being encoded and written in the code itself, rather than from the App UI using an useState value.
I tried using the useState toggle off a button (which toggled the value and logged out OK), and then re-calling the deviceConnect function, but the commented out console.log in the .then promise section didn't work past the first one, returning which turned the LED on (writing 'A' to the characteristic).
thanks for any help in advance, i know a lot of these ble-plx questions go unanswered.
//this is at a top level inside the main function
const [writeValue, setWriteValue] = useState('A');
const toggleLED = () => {
if (writeValue == 'B') {
setWriteValue('A');
console.log("Toggling write value:", writeValue);
} else {
setWriteValue('B')
console.log("Toggling write value", writeValue)
};
};
[1]: https://dotintent.github.io/react-native-ble-plx/
[2]: https://github.com/dotintent/react-native-ble-plx/wiki
[3]: https://www.polidea.com/blog/ReactNative_and_Bluetooth_to_An_Other_level/

Manipulate MySql timestamp value in JavaScript

I'm working with a MySql database and a web application; I use Firebase Functions (Google Cloud Functions) to retrieve data from tables and send it to the web app. When the record's create_dt and update_dt fields make it to the web application, they're an object that doesn't have any accessible properties.
I'm trying to display the create and update date values in my application, but whenever I try to display one of the values, the web application displays [object Object]. Looking at the object in the console, it looks like an empty object with nothing but prototype properties
I've looked around here and other places on the Internet and found a bunch of articles that show how to manipulate a MySql Timestamp (as a time string) in JavaScript, but none that shows how to actually access the timestamp value.
My goal right now is just to display the time/date value in my app, but ultimately I want to get it as a JavaScript Date object so I can format the output the way I want in my app. Can someone please show me how to do this? I don't get why the timestamp shows up in the browser as an object with no accessible properties.
My function looks like this:
export const get = functions
.runWith({
vpcConnector: 'myapp-connector',
vpcConnectorEgressSettings: 'PRIVATE_RANGES_ONLY'
})
.https.onCall((data, context) => {
// Checking that the user is authenticated.
if (!context.auth) {
// Throwing an HttpsError so that the client gets the error details.
throw new functions.https.HttpsError(AUTHCODE, AUTHMSG);
}
const idx = data.idx;
if (idx) {
let cmd = `SELECT * FROM companies WHERE id=${idx}`;
return sqlStuff.executeQuery(cmd)
.then(result => {
functions.logger.log('Query result', result);
return { result: result };
}).catch(err => {
functions.logger.log('ERROR', err);
return { err: err };
});
} else {
functions.logger.log('Missing index');
return { result: {} };
}
});
The query code looks like this:
export async function executeQuery(cmd: string) {
const mySQLConfig = {
connectionLimit: 10,
host: functions.config().sql.prodhost,
user: functions.config().sql.produser,
password: functions.config().sql.prodpswd,
database: functions.config().sql.proddatabase,
}
var pool: any;
if (!pool) {
pool = mysql.createPool(mySQLConfig);
}
return new Promise(function (resolve, reject) {
pool.query(cmd, function (error, results) {
if (error) {
return reject(error);
}
resolve(results);
});
});
}
On the client, I'm using AngularFireFunctions since this is an Angular (Ionic) app.
getCompany(idx: number) {
const companyGet = this.fireFunc.httpsCallable('companyGet');
companyGet({ idx }).subscribe(
data => {
if (data.result && data.result.length > 0) {
this.company = Object.assign({}, data.result[0]);
} else {
this.alertController.create({
header: 'Company Lookup',
message: `The specified company record (${idx}) does not exist`,
buttons: ['OK']
}).then(alert => {
alert.present();
this.router.navigate(['/companies']);
});
}
},
err => {
this.alertController.create({
header: 'Company Refresh',
message: `The process reported the following error: ${err.message}`,
buttons: ['OK']
}).then(alert => alert.present());
},
() => {
console.log('CompanyPage: Company request completed');
}
);
});
}

How to read BLE Peripheral Characteristics in react native using react-native-ble-plx

I'm developing an application which scans for BLE devices(Peripherals), then connect to them, read their services and characteristics. For now, I was able to connect to an iPhone which acting as a Peripheral device with certain characteristics and also was able to connect to Fitbit Versa Watch to read the heart sensor data. Although I was able to discover their services, I wasn't able to extract more information from the services like ServiceUUId and their characteristics.
Below is my code is written in react native.
scanAndConnect() {
console.log("Scanning Started");
this.manager.startDeviceScan(null, null, (error, device) => {
if (error) {
// Handle error (scanning will be stopped automatically)
console.log("Error in scanning devices:", error);
return
}
// Check if it is a device you are looking for based on advertisement data
// or other criteria.
console.log("Detected Device Details:", device.id, device.name);
// ||device.localName === 'BLEPeripheralApp')
if (device.name === 'Versa Lite'){ //
// Stop scanning as it's not necessary if you are scanning for one device.
console.log("Device Found, Stopping the Scan.");
console.log("Connecting to:",device.name)
this.manager.stopDeviceScan();
device.connect()
.then((device) => {
// this.info("Discovering services and characteristics")
console.log("Connected...Discovering services and characteristics");
return device.discoverAllServicesAndCharacteristics()
})
.then((device) => {
console.log('Services and characteristics discovered');
//return this.testChar(device)
const services = device.services()
console.log(services);
return device.readCharacteristicForService(services)
// device.readCharacteristicForService("abbaff00-e56a-484c-b832-8b17cf6cbfe8")
// this.info("Setting notifications")
//return this.setupNotifications(device)
})
.then(() => {
const characteristicsData = device.readCharacteristicForService();
console.log(characteristicsData);
//this.info("Listening...")
}, (error) => {
console.warn(error.message);
// this.error(error.message)
})
}
});
}
How do I extract the serviceUUId from the Service method and also read the characteristics of that service? For my iPhone peripheral, I have two mutable characteristics that I should be able to read and write.
How do I read them from service to characteristics to the real value?
Any help/suggestions are much appreciated.
Thanks.
You're missing the method characteristicsForService.
Loop over all the services, get their characteristics by
await device.discoverAllServicesAndCharacteristics();
const services = await device.services();
services.forEach(async service => {
const characteristics = await device.characteristicsForService(service.uuid);
characteristics.forEach(console.log);
});

Tracking Google OAuth2 token changes [duplicate]

I have a simple single-page javascript webapp which uses "Google Sign-In for Websites": https://developers.google.com/identity/sign-in/web/sign-in
How can I get an access token for the user? I need a verifiable assertion of the user's identity on my server. I don't want offline access; I just want to know that when the web client sends an ajax request to my server, I can trust the identity of the logged-in user.
For verification purposes it would be better to use the id_token which is part of the auth response, and can be retrieved at any point like this:
gapi.auth2.getAuthInstance().currentUser.get().getAuthResponse().id_token
The Google API Client libraries offer functions to verify the id_token and give you the associated user information on the server side: https://developers.google.com/api-client-library/
First, you need to initialize the SDK
Then call the following function to get the access-token
gapi.auth2.getAuthInstance().currentUser.get().getAuthResponse().access_token;
This solution help for me to get access token in javascript.
Hope your are doing well.
Here is the solution, You may try this:
Actually there is no such a function name getAccessToken (Android Only) define in GoogleSignin.android.js as written here https://github.com/devfd/react-native-google-signin.
But the best part is they have already implemented the solution in GoogleSignin.android.js. just take a look at the code below from GoogleSignin.android.js
currentUserAsync() {
return new Promise((resolve, reject) => {
const sucessCb = DeviceEventEmitter.addListener('RNGoogleSignInSilentSuccess', (user) => {
this._user = user;
RNGoogleSignin.getAccessToken(user).then((token) => {
this._user.accessToken = token;
this._removeListeners(sucessCb, errorCb);
resolve(this._user);
})
.catch(err => {
this._removeListeners(sucessCb, errorCb);
resolve(this._user);
});
});
The thing is only we have do use this code wisely.
I have use the below code to get access_token and it help me to solve my access token problem.
I change above function like this in GoogleSignin.android.js
currentUserAsync() {
return new Promise((resolve, reject) => {
const sucessCb = DeviceEventEmitter.addListener('RNGoogleSignInSilentSuccess', (user) => {
this._user = user;
RNGoogleSignin.getAccessToken(user).then((token) => {
this._user.accessToken = token;
this._removeListeners(sucessCb, errorCb);
resolve(token);
})
.catch(err => {
this._removeListeners(sucessCb, errorCb);
resolve(this._user);
});
});
and I call this function like this from index.android.js.
_signIn() {
GoogleSignin.signIn()
.then((user) => {
console.log('this1' + JSON.stringify(user));
this.setState({user: user});
var gettoken = GoogleSignin.currentUserAsync(user).then((token) => {
console.log('USER token', token);
this.setState({user: user});
}).done();
}).catch((err) => {
console.log('WRONG SIGNIN', err);
})
.done();
}
You can call it as a individual function it look like this.
in GoogleSignin.android.js
getAccessTok(user)
{
RNGoogleSignin.getAccessToken(user).then((token) => {
this._user.accessToken = token;
resolve(token);
})
.catch(err => {
this._removeListeners(sucessCb, errorCb);
console.log('got error');
resolve(this._user);
});
}
and from index.android.js just call this function like this
_getToken(){
console.log(GoogleSignin.getAccessTok(this.state.user));
}
only you have to do is to pass the current user to get access token.
Hope this will help you.Have a great day.Thank You.
Yeah, it is 2021. And I was facing the same problem.
My solution is
gapi.signin2.render(this.id, {
scope: this.scope,
width: this._width,
height: this._height,
longtitle: this._longTitle,
theme: this.theme,
// Set to true, otherwise only user actively logging in with Google will have access token
onsuccess: (googleUser: gapi.auth2.GoogleUser) => googleUser.getAuthResponse(true),
onfailure: () => this.handleFailure()
});

How to get the access token from Google Sign-In Javascript SDK?

I have a simple single-page javascript webapp which uses "Google Sign-In for Websites": https://developers.google.com/identity/sign-in/web/sign-in
How can I get an access token for the user? I need a verifiable assertion of the user's identity on my server. I don't want offline access; I just want to know that when the web client sends an ajax request to my server, I can trust the identity of the logged-in user.
For verification purposes it would be better to use the id_token which is part of the auth response, and can be retrieved at any point like this:
gapi.auth2.getAuthInstance().currentUser.get().getAuthResponse().id_token
The Google API Client libraries offer functions to verify the id_token and give you the associated user information on the server side: https://developers.google.com/api-client-library/
First, you need to initialize the SDK
Then call the following function to get the access-token
gapi.auth2.getAuthInstance().currentUser.get().getAuthResponse().access_token;
This solution help for me to get access token in javascript.
Hope your are doing well.
Here is the solution, You may try this:
Actually there is no such a function name getAccessToken (Android Only) define in GoogleSignin.android.js as written here https://github.com/devfd/react-native-google-signin.
But the best part is they have already implemented the solution in GoogleSignin.android.js. just take a look at the code below from GoogleSignin.android.js
currentUserAsync() {
return new Promise((resolve, reject) => {
const sucessCb = DeviceEventEmitter.addListener('RNGoogleSignInSilentSuccess', (user) => {
this._user = user;
RNGoogleSignin.getAccessToken(user).then((token) => {
this._user.accessToken = token;
this._removeListeners(sucessCb, errorCb);
resolve(this._user);
})
.catch(err => {
this._removeListeners(sucessCb, errorCb);
resolve(this._user);
});
});
The thing is only we have do use this code wisely.
I have use the below code to get access_token and it help me to solve my access token problem.
I change above function like this in GoogleSignin.android.js
currentUserAsync() {
return new Promise((resolve, reject) => {
const sucessCb = DeviceEventEmitter.addListener('RNGoogleSignInSilentSuccess', (user) => {
this._user = user;
RNGoogleSignin.getAccessToken(user).then((token) => {
this._user.accessToken = token;
this._removeListeners(sucessCb, errorCb);
resolve(token);
})
.catch(err => {
this._removeListeners(sucessCb, errorCb);
resolve(this._user);
});
});
and I call this function like this from index.android.js.
_signIn() {
GoogleSignin.signIn()
.then((user) => {
console.log('this1' + JSON.stringify(user));
this.setState({user: user});
var gettoken = GoogleSignin.currentUserAsync(user).then((token) => {
console.log('USER token', token);
this.setState({user: user});
}).done();
}).catch((err) => {
console.log('WRONG SIGNIN', err);
})
.done();
}
You can call it as a individual function it look like this.
in GoogleSignin.android.js
getAccessTok(user)
{
RNGoogleSignin.getAccessToken(user).then((token) => {
this._user.accessToken = token;
resolve(token);
})
.catch(err => {
this._removeListeners(sucessCb, errorCb);
console.log('got error');
resolve(this._user);
});
}
and from index.android.js just call this function like this
_getToken(){
console.log(GoogleSignin.getAccessTok(this.state.user));
}
only you have to do is to pass the current user to get access token.
Hope this will help you.Have a great day.Thank You.
Yeah, it is 2021. And I was facing the same problem.
My solution is
gapi.signin2.render(this.id, {
scope: this.scope,
width: this._width,
height: this._height,
longtitle: this._longTitle,
theme: this.theme,
// Set to true, otherwise only user actively logging in with Google will have access token
onsuccess: (googleUser: gapi.auth2.GoogleUser) => googleUser.getAuthResponse(true),
onfailure: () => this.handleFailure()
});

Categories