web bluetooth - `getPrimaryService` call gets stuck - progressive-web-apps

I'm trying to print from a device from a PWA - the device is https://www.sunmi.com/en/v2-pro/ - I can connect to the device, but when I try to get the service, the promise gets stuck i.e. neither the "catch" nor the "finally" callbacks are called.
navigator.bluetooth.requestDevice({
acceptAllDevices: true,
optionalServices: ['00001101-0000-1000-8000-00805f9b34fb'],
})
.then((device) => {
console.log('> Found ' + device.name);
console.log('Connecting to GATT Server...');
return device.gatt.connect();
})
.then((server) => {
console.log('> Connected ' + server.connected);
console.log('getPrimaryService...');
return server.getPrimaryService('00001101-0000-1000-8000-00805f9b34fb');
})
.then((service) => {
console.log('getCharacteristic...');
return service.getCharacteristic('00001101-0000-1000-8000-00805f9b34fb');
})
.then((characteristic) => {
console.log('> Characteristic UUID: ' + characteristic.uuid);
})
.catch((error) => {
console.log('Argh! ' + error);
})
.finally(() => {
console.log('> Finally');
});
console.log('whatsup?');
https://share.getcloudapp.com/5zuLxBE4 - the logs until "getPrimaryService...". The device does not show any dialog or requests any interaction. So not sure why this would get stuck.
I've used the nRF connect app to get the uuid - https://share.getcloudapp.com/GGulYQYz
Not sure if I'm doing something wrong here, any help would be appreciated.

This is probably an implementation issue, as the browser needs to call out to the operating system to get the list of primary services and this can fail for a myriad of reasons. Can you file an bug report on the issue tracker for the browser you are using (e.g. crbug.com for Google Chrome) with details about the device and operating system on which you are encountering this issue? It would also be useful information to know if this issue occured on multiple platforms (e.g. Android and Windows).

The "00001101-0000-1000-8000-00805f9b34fb" UUID you use is the one used for the standardised Serial Port Profile (SPP).
According to https://social.msdn.microsoft.com/Forums/azure/en-US/e3466b1f-b67a-4217-ab53-c64921493ec1/what-bluetooth-service-is-needed-to-connect-a-remote-device-to-a-windows-10-virtual-port?forum=wdk, SPP is not supported on BLE devices.
I'm surprised though the getPrimaryService() promise does not reject. As suggested by Reilly Grant, please file a bug. See https://sites.google.com/a/chromium.org/dev/developers/how-tos/file-web-bluetooth-bugs

Related

Local Fulfilment with multiple devices

I try to create a Google Home Action with Local Fulfilment and with multiple devices that are detected through mDNS.
As such, I have a GCloud Fulfillment Function that returns the required sync:
response.payload.devices.push({
id: "elgato-device-id",
name: {
name: "Elgato",
},
"otherDeviceIds": [{
"deviceId": "local-elgato-device-id"
}],
// ...
});
As well as my Javascript file to handle the local part:
.onIdentify((request) => {
const device = request.inputs[0].payload.device;
return new Promise((resolve, reject) => {
const response = {
intent: smarthome.Intents.IDENTIFY,
requestId: request.requestId,
payload: {
device: {
id: device.id || "",
verificationId: "local-elgato-device-id"
},
},
};
resolve(response);
});
})
(I am using https://github.com/sirdarckcat/sirdarckcat.github.io/tree/master/fakeauth as a starting point.)
When debugging my app, I can see that onIdentify is correctly called twice, once with each of my two devices. Still, only one device appears in the Google Home app and manipulating that one will randomly control either of both physical devices.
https://developers.home.google.com/local-home/fulfillment-app says:
Note: The verificationId must match one of the otherDeviceIds in your SYNC response, in order for the Local Home platform to know it’s the same device (this process is called deduplication).
Is it possible to have multiple devices with the same deviceId? Or do I have to implement this differently? If so, how?
(I didn't consider to implement a hub yet, since https://stackoverflow.com/a/66031681 states that the Local Fulfilment SDK "uniquely identify the device by their network address" which is true for the two devices.)
When integrating Google Home you will need to have a unique device id for each of your devices. You can learn more about Local Fulfillment by going through Enable Local Fulfillment for Smart Home Actions Codelab.

Connection awareness

Is there a way to be aware of connection status with Prisma?
I understand it does everything automatically so I don't have to worry about anything related to connection.
But what if I want to?
Basically I miss two things:
Catchable event. Either client.on('disconnected', ...) or implementing an interface (e.g. onDisconnected() { ... })
$connect() throwing error if it can not connect. No exception raised when DB is not started and I start the application.
// Context:
// - DB not started yet
try {
await client.$connect();
console.log('DB connected');
} catch (e) {
console.log('DB is unavailable');
}
// Output
//
// > DB connected
My use case: I would like to send a system message to maintainers and shut the whole service down if the DB stopped and could not recover connection within a time frame.
Okay, I was able to overcome it. I guess it's rather a bug than a feature.
So $connect() does not throw error it could connect successfully before but the DB has been stopped meanwhile and $disconnect() was not called.
So, calling $disconnect() when lost connection is recognized resulted in $connect() throwing error if still not able to connect.
I still miss the ability to watch for connection events but this is enough for me now.

Extremely high loading times - Requests not running async. Mongoose

Overview
I've built an application with Vue, Express and MongoDB (mongoose ORM).
On loading the landing page, a series of GET requests are made for various bits of data. The loading times are extremely high, I've recorded some times as high as 22s for a particular route. It's lead me to believe that my requests are running sequentially, despite specifying in my logic that everything should run async
I've tried reducing the size of the objects being returned from the requests as well as using the .lean() method. These attempts shaved off a couple of seconds, but the overall issue is not remotely sorted. Times are still stupid high. To give an example:
From This:
// Method to find all users
var users = await User.find({});
To:
// Method to find all users
var users = await User.find({}, "username, uid").lean();
On the page in question, there are about 5 main components. Each component is making a get request. One of these is a Chat Column and the code for it is as follows:
ChatCol.vue
beforeMount () {
this.$store.dispatch('retrieve_chat')
}
Store.js (am using Vuex store)
retrieve_chat (context) {
return new Promise((resolve, reject) => {
axios({
url: api.dev + 'api/v1/chat',
method: 'GET',
})
.then(res => {
context.commit('set_chat', res.data)
resolve(res);
}).catch(err => {
// alert(err)
reject(err);
})
})
},
Requests in this format are being made on all the components. About 5 of them in the page in question.
Backend / Server Code
To give some context into the requests being made.
The client will hit the route 'http://localhost:3000/api/v1/chat'
and the code that makes the request on the server is the following:
var Chat = require("../models/ChatMessage");
module.exports = {
// LIMIT CHAT TO 100 MESSAGES
async get_chat(req, res) {
Chat.find({}, function(err, messages) {
if (err) {
return res.status(500).send({
message: "Interval Server Error",
type: "MONGO_CHAT_DOCUMENT_QUERY",
err: err,
})
}
if (!messages) {
return res.status(400).send({
message: "Resource not found",
type: "MONGO_CHAT_DOCUMENT_QUERY",
details: "!messages - no messages found",
})
}
messages.reverse();
return res.status(200).json({
messages,
});
}).sort({"_id": -1}).limit(30);
},
}
If I look at the network tab on the chrome dev tools, this is how the requests appear. Apologies for the long winded post, I literally have no idea what is causing this
Important Note:
It was mentioned to me that mongodb has this feature where it locks when mutating the data, and I thought that might be the case, but there are no mutations taking place. It's just 3/4 get requests happening in parallel, albeit pretty big requests, but they shouldn't be taking as long as they are
Screenshot of the network tab:
(ignore the failed req, and some of the duplicate named requests)
StackOverflow sempais please help. It's a very big application and I don't know what the issue is exactly, so If I've missed out any details - Apologies, I'll clarify anything that needs clarity.
Large amount of base64 encoded data from a previously abandoned and poorly implemented image upload feature was being stored in each chat message as well as other places, causing large amounts of data to be loaded in and ultimately lead to huge loading times.
Thank you Neil Lunn.

How to use API in actions-on-google

I have tried the following javascript code, using a railway API in aog for getting names of trains between 2 stations.
train : function(conv,src,dst) {
const options={
method:'GET',
url : `https://api.railwayapi.com/v2/between/source/${src}/dest/${dst}/date/23-09-2018/apikey/<api_key>/`,
json : true
};
var data=[];
return rp(options)
.then(function(parseBody){
for(var i=0;i<2;i++){
data.push(parseBody.trains[i].name);
}
console.log(data);
return conv.ask(data[0] + data[1]);
}).catch(err=>{
console.log("api error" + err);
});
}
When I run it in my computer using terminal(node filename.js) it shows the data[] array with correct values. But when I try to run it from actions-on-google simulator it catches an error as follows...
api errorRequestError: Error: getaddrinfo ENOTFOUND api.railwayapi.com api.railwayapi.com:443
If you are trying to do this using Firebase Cloud Functions (FCF) or the Dialogflow Built-In editor (which uses FCF under the covers), the most likely cause is that you are using the free tier of FCF which does not allow calls outside Google's network.
You can upgrade to the Blaze Plan to get around this. While this does require a credit card to be on file, it includes a free tier which is quite sufficient for some basic testing and probably even some very light usage once you're in production. Once you have your Action approved, you will be eligible to receive cloud credits from Google which can be used to offset costs associated with using Cloud Functions.

How to link BluetoothSerial setDataAvailableCallback() to update text display

I'm very new to react-native. I'm using https://github.com/rusel1989/react-native-bluetooth-serial to connect my Android app to a BT device. This GitHub repo has an example, which works. I was able to send commands from app to device.
Now I want my device to send data back to the app. Think of it as IoT data, just a few bytes sent every few seconds. I know that setDataAvailableCallback() can be used. My question is that if I create a <Text /> element in JSX, how can I link that with the callback. Thanks.
API: https://github.com/derektu/react-native-bluetooth-serial
I figured it out by trying out a few changes on the example I had. Within render(), I included the following: <Text>{this.state.myText}</Text>
In the constructor of that class, I added a new field to this.state that is initially set to an empty string:
this.state = {
...
myText: ''
}
In the same constructor, I set up this polling at 100 ms periodicity:
setInterval(() => {
BluetoothSerial.read()
.then((res) => {
this.setState({ myText: res })
})
}, 1000);
I will enhance this to read only when bytes are available. Also, my installation did not have setDataAvailableCallback(), which is why I couldn't use it.