Communicate with Android bluetooth device via NodeJS and Termux - android

We are looking to communicate with a bluetooth device connected to an Android tablet. We are using Termux and have NodeJS installed. Does anyone know if it is even possible to communicate with a bluetooth device? Would we have to attempt to communicate with the device directly through the /dev folder?
It is my understanding that Android is built on top of the Linux kernel, however, it has implemented specific things on top of it to interact for other things such as connectivity. Would the device even be accessible through the /dev folder via NodejS "serialport" or another tool?
As a last resort, if this is not possible, I guess we could try to build NodeJS in the Android OS through a rooted terminal. I've heard this isn't as easy as one would think though. Through Termux I am able to access the /dev folder and see all the devices. Not sure how the permission would work though. Thanks.

You can communicate through the serial port using this tool. I have never use this tool but providing this only as a reference, since android is built on a linux kernel this might work. Please note that the examples are same as documentation.
https://github.com/eelcocramer/node-bluetooth-serial-port
Basic client usage
var btSerial = new (require('bluetooth-serial-port')).BluetoothSerialPort();
btSerial.on('found', function(address, name) {
btSerial.findSerialPortChannel(address, function(channel) {
btSerial.connect(address, channel, function() {
console.log('connected');
btSerial.write(new Buffer('my data', 'utf-8'), function(err, bytesWritten) {
if (err) console.log(err);
});
btSerial.on('data', function(buffer) {
console.log(buffer.toString('utf-8'));
});
}, function () {
console.log('cannot connect');
});
// close the connection when you're ready
btSerial.close();
}, function() {
console.log('found nothing');
});
});
btSerial.inquire();
Basic server usage (only on Linux)
var server = new(require('bluetooth-serial-port')).BluetoothSerialPortServer();
var CHANNEL = 10; // My service channel. Defaults to 1 if omitted.
var UUID = '38e851bc-7144-44b4-9cd8-80549c6f2912'; // My own service UUID. Defaults to '1101' if omitted
server.listen(function (clientAddress) {
console.log('Client: ' + clientAddress + ' connected!');
server.on('data', function(buffer) {
console.log('Received data from client: ' + buffer);
// ...
console.log('Sending data to the client');
server.write(new Buffer('...'), function (err, bytesWritten) {
if (err) {
console.log('Error!');
} else {
console.log('Send ' + bytesWritten + ' to the client!');
}
});
});
}, function(error){
console.error("Something wrong happened!:" + error);
}, {uuid: UUID, channel: CHANNEL} );

Related

Accessing SerialPort from Android Phone with React Native

I have developed a React Native app for Android device to connect with a HW board and one of the functionality is to communicate with HW board with Serial I/F Adapter from Mobile .
I have tried out multiple npm packages and none of them I could get to work.
Here is my sample code
import SerialPortAPI from 'react-native-serial-port-api';
const path = await SerialPortAPI.devicePaths(paths => {
console.log("List paths", paths)
})
const connectDevice = async (cfg) => {
const { baudRate, serialPortName, stopBits } = cfg
serialPort = await SerialPortAPI.open(serialPortName, { baudRate, stopBits});
const sub = serialPort.onReceived(buff => {
const str = buff.toString('hex').toUpperCase()
console.log(str);
})
await serialPort.send('A7B7');
}
It is NOT listing the device List connected and also not able to open/write/read.
Other packages I tried are:
react-native-usbserial
react-native-serialport
react-native-usb-serialport
react-native-serial-port-api
I any pointers and working sample will be of great help.
Regards
Raghu VT
Are you connecting the phone to your pc or it should work as host? I think that is key point to understand.
My phone is Host and I started with Android code.
Would recommend to use Android to test if possible.
You want to pay attention to the port type used.
If you use a USB AB connector you need to use an otg cable or adapter.
if case of type C , this will be detected automatically.
Hope could provide some hints

"TypeError: Network request failed" (React Native) Android fetch fails to work with local backend

I am trying to fetch from my react native app using my local backend, and it keeps failing. The fetch doesn't even hit my backend, I made debug messages and tested on my browser to make sure the rest api worked. It works on iOS. I am also able to access other websites, so the internet works on the emulator.
UPDATE: After further debugging and trying other fetch requests, I have found a different error, maybe they are related?
error Could not open fetch.umd.js in the editor.
info When running on Windows, file names are checked against a whitelist to protect against remote code execution attacks. File names may consist only of alphanumeric characters (all languages), periods, dashes, slashes, and underscores.
I've already added "android:usesCleartextTraffic="true" in my AndroidManifest.xml. I have also tried upgrading my react native to version 63.4 but the problem persists.
It prints to console "[GET] http://127.0.0.1:8090/api/v1/user/check/email/test#gmail.com" but then the app gets
"TypeError: Network request failed"
immediately after.
When I try that URL in my browser, it properly prints
{"transok":"0","errno":"001003","errmsg":"","timestamp":"1612157175224","data":{}}
I've spent days in frustration on this, if anyone could lead me in the right direction I would be unimaginably greatful. Please let me know if any more information is needed, I will edit this question to provide the details
This is the code for the fetch which doesnt work:
const APP_SERVER_HOST = 'http://127.0.0.1:8090';
const API_BASE = APP_SERVER_HOST + '/api';
const API_VERSION = '/v1';
const API_HOST = API_BASE + API_VERSION;
isEmailExist(callback) {
var url = API_HOST + '/user/check/email/'+this.state.email;
var options = {
method: 'GET',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
}
};
console.log('[GET] ' + url);
//url is http://127.0.0.1:8090/api/v1/user/check/email/test#gmail.com
//url should post {"transok":"0","errno":"001003","errmsg":"","timestamp":"1612157175224","data":{}}
fetch(url, options).then((response) => response.json())
.then((responseData) => {
var retCode = responseData.errno;
console.log('[RTN] ' + responseData);
console.log('[RTN] ' + JSON.stringify(responseData));
if(retCode == Env.dic.ERROR_EMAIL_NOT_REG) {
console.log('[RTN] error email not reg');
return callback(false);
} else if(retCode == Env.dic.ERROR_EMAIL_EXIST){
console.log('[RTN] error email exist');
return callback(true);
}
}).done();
}
127.0.0.1 represents the emulator's localhost address. If you want to hit your machine's localhost you'll have to replace it with 10.0.2.2.
See Android docs for more information on why this is the case.

Retrieving Data from GEAR S3 Heart Rate Monitor (HRM) to Mobile or Server

I have used the Tizen sample Heart Rate Monitor code for Samsung Gear S3 from https://developer.tizen.org/ko/community/tip-tech/accessing-heart-rate-monitor-hrm-sensor-data-native-applications?langredirect=1
I want to develop Android or Tizen for Retrieving Data from the Heart Rate Monitor which is in S3 Gear. I found the sample code from https://developer.tizen.org/ko/development/guides/web-application/sensors/human-activity-monitor?langredirect=1#retrieve
How can I integrate this. Pls share your ideas. Thanks a lot.
With Samsung Accessory SDK, you can develop an app in Android which can communicate with Tizen app(Gear).
Here is a working example
How to integrate Samsung Gear Steps in android Application?
Edit:
Here i am giving the code to measure Heart Rate and return back to Android phone when a request is sent from Android . I have just modified code from previously mentioned post and sharing here.
Here i am giving only contents from dataOnReceive function
if (!SAAgent.channelIds[0]) {
createHTML("Something goes wrong...NO CHANNEL ID!");
return;
}
function sendHrData(heartRate){
// return Data to Android
SASocket.sendData(SAAgent.channelIds[0], 'HR: '+heartRate);
createHTML("Send massage:<br />" +
newData);
tizen.humanactivitymonitor.stop('HRM');
}
var heartRateData=0;
function onsuccessCB(hrmInfo) {
console.log('Heart rate: ' + hrmInfo.heartRate);
heartRateData = hrmInfo.heartRate;
// holding 15 seconds as HRM sensor needs some time
setTimeout(function(){
sendHrData(heartRateData);
}, 15000);
}
function onerrorCB(error) {
tizen.humanactivitymonitor.stop('HRM');
console.log('Error occurred: ' + error.message);
}
function onchangedCB(hrmInfo) {
//alert("onChanged...");
tizen.humanactivitymonitor.getHumanActivityData('HRM', onsuccessCB, onerrorCB);
}
tizen.humanactivitymonitor.start('HRM', onchangedCB);
And this code continuously returning Heart Rate. Please modified according to your requirements, i am just sharing the idea to communicate between Android phone and Samsung Gear.
Send Data to Server:
You can use Ajax or XmlHttpRequest to send data to server
Ajax:
function sendDataToServer() {
'use strict';
console.log( "ready!" );
$.ajax({
type: "Post",
url: "http://YOUR_URL",
success: function (data) {
console.log(JSON.stringify(data));
}
});
}
XmlHttpRequest:
function postDataToServer() {
var xmlHttp = new XMLHttpRequest();
xmlHttp.onreadystatechange = function() {
if (xmlHttp.readyState == 4) {
if (xmlHttp.status == 200) {
alert("data posted successfully..");
} else {
alert("failed to send data..");
}
}
}
xmlHttp.open("POST", "YOUR_URL");
xmlHttp.send("_TEST_STRING_DATA");
Auto generated code from REST viewer not working in Tizen IDE(Wearable) web app
XmlHttpRequest on Tizen TV exits application
RESTful service on emulator
Note: You need to install Samsung Gear application in your Android phone.

How to attach file to email in Ionic Framework Android?

I'm using Ionic Framework to build an iOS / Android app which writes sqlite data to a CSV file, then attaches that file to an Email and sends it. The following code works correctly on iOS (actual device iPhone 5).
I don't have an Android device, but in the Android emulator (nexus 5), the file sent never has a file attachment (despite the emulator showing that it does).
Is there a different way I should be writing this code?
I looked at the documentation here, but it does not clarify
https://github.com/katzer/cordova-plugin-email-composer#adding-attachments
$cordovaFile.writeFile(cordova.file.dataDirectory,
"PatientEncounters.csv",
data.join("\n"),
true)
.then(function (success) {
$cordovaEmailComposer.isAvailable().then(function() {
var emailOpts = {
to: [email],
attachments: ['' +
cordova.file.dataDirectory.replace('file://','') + "PatientEncounters.csv"],
subject: 'Patient Encounters',
body: 'A CSV containing Patient Encounters is attached',
isHtml: false
};
$cordovaEmailComposer.open(emailOpts).then(null, function () {
// user cancelled email
});
return;
}, function (error) {
return;
});
}, function () {
// not available
});
My problem was using cordova.file.dataDirectory instead of cordova.file.externalDataDirectory. The mail app in android would not allow attaching files from internal storage.

Protractor's waitForAngular() fails on angular-webapp (appium/chrome on real device)

I'm (newly) using protractor to run e2e cucumber tests.
I got a web-app which is angularJS based. I'm using appium to remotely run the test on a real android device. Here are the versions i'm using :
windows8.1
protractor#1.3.1 (with submodule selenium-webdriver#2.43.5)
appium#1.3.0beta1
android device with 4.4.4
my protractor configuration (extracts), corresponding to https://github.com/angular/protractor/blob/master/docs/browser-setup.md:
currentDeviceUDID = (...);
var appToTestURL = 'http://my.website.com:9000/app/index.html';
exports.config = {
seleniumAddress: 'http://localhost:4723/wd/hub';
chromeOnly: false,
specs: ['features/sample.feature'],
capabilities: {
browserName: 'chrome',
'appium-version': '1.0',
platformName: 'Android',
platformVersion: '4.4.4',
udid: currentDeviceUDID
},
baseUrl: appToTestURL
framework: 'cucumber',
cucumberOpts: {
require: 'features/stepDefinitionsSample.js',
tags: '#dev',
format: 'progress'
},
// configuring wd in onPrepare
onPrepare: function () {
var wd = require('wd'),
protractor = require('protractor'),
wdBridge = require('wd-bridge')(protractor, wd);
wdBridge.initFromProtractor(exports.config);
},
allScriptsTimeout: 30000,
getPageTimeout: 30000
};
As you can see, i have replaced the protractor's webdriver url with the appium webdriver. i start the appium from commandline with "appium &", then i run the test with "protactor cucumbertest.conf"
The phone opens chrome browser and navigates to the url i give it with "browser.get(url)"
the problem is the following:
the call waitForAngular(), which is asynchronously waiting for the website to load and on all open http request (as far as i understand), is not executed sucessfully on the phone. the phone does not react to the call, and the webdriver proxy returns a 500.
Corresponding to https://github.com/angular/protractor/issues/1358, i understood that the waitForAngular() function is mixed in protractor into the calls
['getCurrentUrl', 'getPageSource', 'getTitle'];
Behind waitForAngular() in the file protractor.js is the function below, which is proxied to the phone:
functions.waitForAngular = function(selector, callback) {
var el = document.querySelector(selector);
try {
if (angular.getTestability) {
angular.getTestability(el).whenStable(callback);
} else {
angular.element(el).injector().get('$browser').
notifyWhenNoOutstandingRequests(callback);
}
} catch (e) {
callback(e);
}
};
Additional information: when i stimulate an error on the webdriver (browser) object, the error message points to the chromedriver.exe inside the protractor directory. i dont understand why the error is not from appium's chromedriver
so tldr;
without the successful call waitForAngular, i cannot (stable or at all) access elements on the page on the phone, so not testing. maybe im misunderstanding some fundamental configuration detail here, all hints are welcome.
edit: added appium server logs here: http://pastebin.com/vqBGUdXH
I assume i have identified the problem. Appium and Protractor work fine.
My angularJS app causes the issue. It uses $timeout for polling (im forced on angular 1.07 which has no $interval). This causes protractor to expect the page to be still in the loading stage and not finished. Therefore the function call waitForAngular() never returns and the test timeouts after the specified timeout-timespan.
This behaviour is expected and known, also documented (better read doc first ;) ) at http://angular.github.io/protractor/#/timeouts
The doc suggests the following for continuous polling: replace $timeout with $interval:
If your application continuously polls $timeout or $http, it will never be registered as completely loaded. You should use the $interval service (interval.js) for anything that polls continuously (introduced in Angular 1.2rc3).
For now, i fixed the issue another way: disable the built-in angular sync and manually sync
this.Before(function(next){
ptor = protractor.getInstance();
ptor.ignoreSynchronization = true; //disables waitForangular()
next();
});
Sync method 1:
//at a testcase, wait for an element to be visible with a promise/then
browser.wait(function () {
element.all(by.css('.myCssClass')).then(function (items) {
items[0].getText().then(function (text) {
console.log(text);
});
});
return true;
}
Sync method 2 :
// "eventually" (chai-as-promised) internally uses "promise" (and therefore acts like "then")
browser.get(url);
expect(browser.getTitle()).to.eventually.equal("connect me").and.notify(next);

Categories

Resources