No notifications from characteristicvaluechanged in web bluetooth - javascript

I have a LM068 BLE serial adapter which I'm trying to communicate with from a web app. I have tested it from the nRF Connect app on Android, where the communication works fine.
The characteristic has the properties "notify" and "writeWithoutResponse".
When calling characteristic.startNotifications() I get an error "GATT Error: invalid attribute length.".
Calling characteristic.writeValue() successfully sends the data, and I can see the incoming data in my serial monitor. When sending data from the serial terminal, the characteristicvaluechanged event never fires. Notifications works from the nRF Connect app.
This is part of my current code:
const characteristic = await service.getCharacteristic(characteristicName)
try {
await characteristic.startNotifications()
} catch (e) {
console.log(e.message)
// GATT Error: invalid attribute length.
}
const encoder = new TextEncoder('utf-8')
characteristic.writeValue(encoder.encode('test')) // Works
characteristic.addEventListener('characteristicvaluechanged', handleValueChanged) // Never gets called

So it turns out that the way I was testing the web app was the issue. I didn't have a BLE dongle for my workstation, so I was using my phone to access my development server. Of course web bluetooth needs to be either run on localhost or from https, so I simply ran the development server on https and accessed it on the network from my phone (like https://192.168.0.x). I proceeded even though chrome deemed it unsafe, but apparently only part of web bluetooth works this way.
Pairing and writeWithoutResponse works with an unsigned certificate. Notifications does not.
I'm leaving this here in case anyone else makes the same mistake.

Related

Why is the c# websocket client not receiving data?

There is a very good utility called ttyd, which allows you to run a console application on your computer and display this console in the browser.
After startup, the utility starts an http web server on the specified port and when accessing localhost, a website with a web application that connects using web sockets to localhost:<port>/ws, and already with the help of them there is communication between the web application and the ttyd agent running on the computer.
I want to implement a client for ttyd in c#. I studied with the help of chrome tools what data the web application sends before receiving the data output to the console. This is just a string: {"authToken":"","columns":211,"rows":46} and tried to repeat the same actions in the c# client. But for some reason, no data from ttyd is returned to me.
Comparing the data output by ttyd to its console in the OS itself, it can be seen that it does not even create a process when accessing from my client.
Here is the code I use with the Websocket.Client package
var exitEvent = new ManualResetEvent(false);
var url = new Uri("ws://localhost:7681/ws");
using (var client = new WebsocketClient(url))
{
client.ReconnectTimeout = TimeSpan.FromSeconds(30);
client.ReconnectionHappened.Subscribe(info =>
Console.WriteLine($"Reconnection happened, type: {info.Type}"));
client.MessageReceived.Subscribe(msg => Console.WriteLine($"Message received: {msg}"));
client.Start();
Task.Run(() => client.Send("{\"AuthToken\":\"\",\"columns\":211,\"rows\":46}"));
exitEvent.WaitOne();
}
I have absolutely no idea how to get ttyd to send data to my client. Do you have any idea what action the browser is doing I'm missing in my c# client?
I tried different libraries for web sockets in c#, and also used postman with copying all the headers that the original web application sends to the ttyd agent, but this does not change anything. That is, ttyd, something is fundamentally interfering, as if my web client is not doing something that the browser is doing.

Websocket Server in Node.js return RSV1 error when accessing from the phone APP

In Node.js, I have implemented a WebSocket server which is used by a smartphone app. In some cases I got this kind of error (Invalid WebSocket frame: RSV1 must be clear):
This kind of application is running on many different servers across the world, but have the problem only with one instance. The app crashes randomly when using the communication between smartphones (Android or IOS) but it did not crash if I try to send messages over WebSocket using Java.
Looking at the doc of WebSocket specification have found that:
Currently, I can't find what could be wrong. Do you think it could be some "network set-up issue"?
The libraries used for WebSocket in Node.js is ws 6.2.1.
The service is running inside a docker using alpine:8 image. As I told I have a problem only in one environment in all other environments everything works fine. Any idea what else to check?
Well in my case i was sending an object, when i JSON.stringify() it , it started working
For my case I put in return and it solves my issue:
Before:
if (pathname === "/foo/1") {
wss.handleUpgrade(request, socket, head, function done(ws) {
wss.emit("connection", ws, request);
});
}
After:
if (pathname === "/foo/1") {
wss.handleUpgrade(request, socket, head, function done(ws) {
wss.emit("connection", ws, request);
});
return;
}
I think the RSV1 bit can be related to compression setting. There is a similar question to yours ("Invalid WebSocket frame: RSV1 must be clear) here: "Error: Invalid WebSocket frame: RSV1 must be clear" while using Socket.IO
All you need to do is on the server side, pass on an option related to the
"Sec-WebSocket-Extensions: permessage-deflate;"
,
for example,
new Server({
perMessageDeflate {
...
}
});

Firebase 'A network error (such as timeout, interrupted connection or unreachable host) has occurred.'

I'm trying to write some tests for my database client which requires me to first authenticate into Firebase.
I'm using Jest as my test runner.
My test looks like:
it ('should sign in ', async (done) => {
try {
await auth.signInWithEmailAndPassword('testabc#test.com', 'testuser');
} catch (e) {
console.log(e);
}
done();
});
My firebase app has been initialized and I have validated that the API key is correct.
A couple of interesting notes are that even though I get:
'A network error (such as timeout, interrupted connection or unreachable host) has occurred.'
On the firebase console, I see that my test user has signed in. Mirroring: Firebase throws “auth/network-request-failed” on signInAnonymously() while running jest tests
It doesn't seem like an authentication issue (wrong password/wrong email) as I get the same error for attempting to login as a user that does not exist.
Sign in via launching my app through the browser and inputting credentials into input fields works with no issues.
Any ideas?
I've had similar results when there was Proxy and/or certificate issues blocking things.
What I would do is first enable logging: firebase.database.enableLogging(true);
Then take a look at what it says. If you can't see what is blocking I'd then run Wireshark, we were able to see what was happening then.
This problem occurs when there is no active internet connection in your mobile.
I received the same error because I forgot to enable my network connection in my device. First check your Android manifest file to make sure you have granted network permissions. In my case it was done. So I used my emulator then it started working fine. (For more thorough diagnasis you can use if clause to check whether internet connection is active or not)
1- Reason is Simple ! Check if Device has internet connection.
2- if you have google services enabled
In my case It happened using the Android Emulator.
Closing and restarting the Emulator solved the problem
In my case it worked when I changed
auth.useEmulator('http://localhost:9099')
to
auth.useEmulator('http://127.0.0.1:9099')
in my jest tests.
I had also the same problem, Just restart your IDE and emulator and make sure that have connected wifi. Then open again and run your app.

When using SignalR how does my Web Server know where localhost is?

I am using SignalR in a web application that is hosted on a separate server that has nothing to do with the client.
In the code, I have a function that connects to a SignalR Self-Hosted Service (C#) that is running on the client's computer who is clicking / doing things on the web application (it has been installed by the client). If the client clicks a certain button on my web application, then my service will get data sent to it from the JavaScript code since my server is running on http://*:8080.
Everything appears to be working fine. My question is, how?
My web application is setting the connection in the Server Side JS Code to say this
MyWebApp.cshtml
//Set the hubs URL for the connection
$.connection.hub.url = "http://localhost:8080/signalr";
My C# Service running on the client's computer in the background (that has been installed) is saying this:
MyService.cs
protected override void OnStart(string[] args)
{
eventLog1.WriteEntry("Service started");
//string url = "http://localhost:8080";
string url = "http://*:8080";
SignalR = WebApp.Start(url);
eventLog1.WriteEntry("Server running on " + url);
}
How is it possible that they are even communicating when the server side code is saying "Hey look for localhost on 8080!"
And the service says "Hey start on *:8080!" ( I don't even understand what * means)
Last but not least, if I uncomment the line in my service that is currently commented out and use that to start the service it will not work! Why will my service start up on http//*:8080 but not on http://localhost:8080 ?
This code:
WebApp.Start("http://*:8080")
Says "listen for connections on port 8080 on any IP address available". So it will bind to localhost (127.0.0.1) and any other assigned IP addresses the machine has. It is basically a wildcard binding.
This code:
$.connection.hub.url = "http://localhost:8080/signalr";
Says the server is on localhost which resolves to 127.0.0.1.
For your last point as to why it doesn't work if the server started on http://localhost:8080, I assume this is because SignalR is having trouble mapping to the correct IP address. Try using http://127.0.0.1:8080 instead.

Websocket can't send/receive messages on Chrome/Firefox, works fine on Microsoft Edge

I'm making a remote debugging tool for Unity(C#), and I've set up a C# WebSocket server in the game that emits Log messages.
The remote debugging client is in JavaScript, on a page served by an http server also created by the game.
I seem to be running into issues sending messages on some browsers, and I'm not sure why. I am running the websocket server on localhost and running the client locally, and I know that kind of stuff is not really liked by chrome/firefox. But the weird thing is that I'm not getting any hard errors or exceptions. Failures seem to fail silently.
I'm pretty certain that the issue is JS/Browser related as the C# websocket server works and receives connections in all cases.
Anyway, here's the socket part of the JS code:
var socket = null;
var host = "ws://"+window.location.hostname;
var port = 55000;
var url = host+":"+port+"/msg";
function CheckSocketStatus()
{
if(socket!=null){
console.log(socket.readyState);
}
}
function CreateSocket()
{
socket = new WebSocket(url);
socket.onopen = function()
{
// // Web Socket is connected, send data using send()
console.log("Socket Open!");
socket.send("Here's a client message for ya!");
};
socket.onmessage = function (evt)
{
var message = evt.data;
console.log("MSG: " + message);
var obj = JSON.parse(message);
console.log(obj)
console.log(obj.type)
if(obj.type == "log"){
console.log("Recieved Log");
handleLogMessage(obj);
}
};
socket.onerror = function()
{
console.log("Error!");
}
socket.onclose = function(event)
{
// websocket is closed.
console.log(event.code);
console.log("Connection is closed...");
socket = null;
};
}
In all cases, when I call CreateSocket() a socket gets created and successfully connects to the server. I also have that CheckSocketStatus() function which returns "1" after the socket opens (Which should mean open/ready to send/receive). After that, here are the results:
Chrome:
Chrome will immediately close after connecting. The only thing I do in the onopen() function is a console.log() and a send(). If I remove the send() then the socket will stay open. I do not receive any messages from the server.
Firefox:
Firefox will keep the socket open indefinitely even if I call the send() function in onopen(). However, the server does not receive any messages from the client and vice versa. I feel like I managed to it to send client->server earlier but I could not reproduce that while testing for this question.
Microsoft Edge:
Weirdly enough, Edge works just fine. I can receive and send messages. Works exactly as intended.
Node Webkit (nw.js):
I'm also trying to write this as a nw.js app. Predictably, as it's running on chromium (or something googly), it produces the same results as Chrome.
So I'm not really sure what's going on. I'm not really a web programmer so intricate http stuff is not really my forte. I'm really hoping it's just a Local file issue with chrome/firefox and that it'll work fine on those platforms if I'm connecting to an external host. I'll try to test this tomorrow at work with some non-localhost server, and I'll update with my findings.
I guess the answer I'm looking for is what these symptoms point to and how I can get chrome/firefox/webkit to work properly.
Also what does Edge do here that the others do not?
Thanks in advance! If you need any more info from me please just ask! I didn't want to overload this question just in case there's a simple answer.
Update:
So I just tried connecting from my laptop to my desktop and the same issues still persist. So to my surprise it's not a local issue. I'm a bit stumped. I might have to look at the server code as well. I've also been told to try to use a wrapper, like socket.io, that might solve some platform dependent issues.I've worked with Socket.io/Unity before but I don't think I was having these issues (I wasn't running a server on the C# side that time, there don't seem to be any good socket.io server implementations on C#, and I'm not sure if socket.io interfaces with normal websockets). So that might point to a problem with my implementation on the C# side.
So I figured it out, thanks to gman. I looked at some of his code and noticed that he used a setting in his WebSocketBehavior class called "Ignore Extensions".
The websocket-sharp documentation has this to say:
"If it's set to true, the service will not return the Sec-WebSocket-Extensions header in its handshake response."
"I think this is useful when you get something error in connecting the server and exclude the extensions as a cause of the error."
So I guess that that header did not jive well with Chrome/Firefox. I'm still doing some testing but this solved the behavior I was seeing with those browsers.
So if you get similar errors, do that!

Categories