How to detect if Firebase connection is online/offline - Unity - firebase

The only solution I found online was for Android- not for Unity- by listening to ('.info/connected')
like here- Detect if Firebase connection is lost/regained.
But I tried it and it doesn't work (tried to translate their Android solution to C#)-
DatabaseReference connectedRef = FirebaseDatabase.DefaultInstance.GetReference(".info/connected");
connectedRef.ValueChanged += (object sender, ValueChangedEventArgs a) => {
bool isConnected = (bool)a.Snapshot.Value;
print("isConnected" + isConnected);
};
When I try my code:
Test #1:
Connected to the internet- starting the app
log- isConnected = true
disconnect from the internet
a lot of socket errors, no calls to isConnected anymore (still true)
Test #2:
Disconnected to the internet- starting the app
log- isConnected = false
a lot of socket errors
Connect to the internet
log- isConnected = true
Which means= listeners don't work on offline mode
and the reason why I get isConnected = false only on test #2 is because the function is being called once on start...
How can I tell when the user isn't connected? It's important because I have to manage everything manually until the user is online again- to update the database.

Related

Connecting to IoT Core MQTT

I am trying to connect to Google's MQTT server but I am getting errors
I created all the certificates and registered my device (Adafruit huzzah32)
and the documentation says you connect to mqtt.googleapis.com:8883
So I do
WiFiClientSecure wifi;
MQTTClient client;
client.begin("mqtt.googleapis.com", 8883, wifi);
When I try to connect I use the device path
const char* jwt = "{json web token}";
const char* device = "projects/{project-id}/locations/{cloud-region}/registries/{registry-id}/devices/{device-id}";
Serial.print("Connecting to mqtt");
while (!client.connect(device,"unused",jwt)) {
Serial.print(".");
delay(1000);
}
Serial.println();
Serial.println("Connected to mqtt");
but it never connects
I verified the google certificate by calling
openssl s_client -showcerts -connect mqtt.googleapis.com:8883
and I put in my RSA Private key and certificate key that was made
wifi.setCACert(googleCertificate2);
wifi.setCertificate(myCertificate);
wifi.setPrivateKey(privateCert);
What am I doing wrong?
Here is the connection documentation
https://cloud.google.com/iot/docs/how-tos/mqtt-bridge
Update
I made a quick java example to see if I can connect going off the example they have for connecting and I get a MqttException saying Bad user name or password (4)
Here is the code for that
private void doStuff(){
String clientId = String.format("ssl://%s:%s", "mqtt.googleapis.com", 8883);
String mqttClientId = String.format("projects/%s/locations/%s/registries/%s/devices/%s","{project_id}", "us-central1", "{register}", "{device}");
MqttConnectOptions connectOptions = new MqttConnectOptions();
connectOptions.setMqttVersion(MqttConnectOptions.MQTT_VERSION_3_1_1);
Properties sslProps = new Properties();
sslProps.setProperty("com.ibm.ssl.protocol", "TLSv1.2");
connectOptions.setSSLProperties(sslProps);
connectOptions.setUserName("unused");
try{
String jwt = createJwtRsa("{project-id}");
connectOptions.setPassword(jwt.toCharArray());
MqttClient client = new MqttClient(clientId, mqttClientId, new MemoryPersistence());
while(!client.isConnected()){
try{
client.connect(connectOptions);
}catch (MqttException e) {
e.printStackTrace();
}
}
Log.d("","");
}catch (Exception e){
e.printStackTrace();
}
}
private String createJwtRsa(String projectId) throws Exception {
DateTime now = new DateTime();
JwtBuilder jwtBuilder =
Jwts.builder().setIssuedAt(now.toDate()).setExpiration(now.plusDays(1000000).toDate()).setAudience(projectId);
byte[] keyBytes = readBytes(getAssets().open("rsa_private_pkcs8"));
PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(keyBytes);
KeyFactory kf = KeyFactory.getInstance("RSA");
PrivateKey k = kf.generatePrivate(spec);
return jwtBuilder.signWith(SignatureAlgorithm.RS256, k).compact();
}
As you can see here I have the IoT service acount added to IAM
Does that mean my keys that I generated with openssl are incorrect?
My problem ended up being that I was trying to set a really large expiration date on my Json Web Token (on purpose so I didnt have to keep generating new ones since I have not found a way to do that in arduino) and it looks like that google's mqtt server does not accept anything over a day so the keys will have to be updated daily.
Also inorder to connect to the MQTT server I had to change the buffer size of the MqttClient on the arduino to have a buffer size of 1024 bytes.
MQTTClient client(1024);
anything less I would get an error saying buffer isnt big enough.
here the IAM roles are being explained ...the paragraph here sounds alike what you describe:
On the IAM page in Google Cloud Platform Console, verify that the role Cloud IoT Core Service Agent appears in the Members list for the relevant project service account. (Look for the project service account that ends in #gcp-sa-cloudiot.iam.gserviceaccount.com.)
If the Cloud IoT Core Service Agent role does not appear in the Members list, use gcloud to add the cloudiot.serviceAgent role to the relevant project service account. This role includes permission to publish to Pub/Sub topics.
if not yet having installed it, the Cloud SDK is required for all those gcloud CLI commands, which can be used to list & edit the configurations (of which all can be done through the console, as well)... it's maybe easier, because all of the examples there use it, too.
update ...
concerning JWT refresh tokens, see this article or have some Q & A or the specification: JSON Web Token (JWT), JSON Web Token (JWT) Profile for OAuth 2.0 Client Authentication and Authorization Grants.
here's another relevant article: https://medium.com/google-cloud/refreshing-json-web-tokens-jwts-for-google-cloud-iot-core-897318df3836

Firebase .info/connected showing 'CONNECTED' when offline

So I have this code on my web app:
const connectedRef = firebase.database().ref('.info/connected')
connectedRef.on('value', function(snap) {
if (snap.val() === true) {
console.log('CONNECT')
connected = true
} else {
console.log('DISCONNECT')
connected = false
}
})
When I go offline using the "offline" checkbox in the Developer tools, I expect to see a single DISCONNECT message. What I see instead is:
-- app starts
DISCONNECT
CONNECT
-- here I go "Offline"
DISCONNECT
CONNECT -- What ?
I don't undestand why I see my application getting immediately "connected" again while I'm still offline. Bug? Or I'm doing something wrong?

Windows BLE UWP disconnect

How one forces Windows to disconnect from BLE device being used in UWP app? I receive notifications from some characteristics but at some point I want to stop receiving them and make sure I disconnect from the BLE device to save BLE device's battery?
Assuming your application is running as a gatt client and you have the following instances your are working with in your code:
GattCharacteristic myGattchar; // The gatt characteristic you are reading or writing on your BLE peripheral
GattDeviceService myGattServ; // The BLE peripheral' gatt service on which you are connecting from your application
BluetoothLEDevice myBleDev; // The BLE peripheral device your are connecting to from your application
When you are already connected to your BLE peripheral, if you call the Dispose() methods like this :
myBleDev.Dispose(); and/or myGattServ.Dispose(); and/or myGattchar.Service.Dispose()
you surely will free resources in your app but will not cleanly close the BLE connection: The application looses access to control resources for the connection. Nevertheless, connection remains established on the lower levels of the stack (On my peripheral device the Bluetooth connection active LED remains ON after calling any of Dispose() methods).
Forcing disconnection is done by first disabling notifications and indications on the concerned characteristic (i.e. myGattchar in my example above) by writing a 0 (zero) to the Client Characteristic Configuration descriptor for that characteristic through call to method WriteClientCharacteristicConfigurationDescriptorAsync with parameter GattClientCharacteristicConfigurationDescriptorValue.None :
GattCommunicationStatus status =
await myGattchar.WriteClientCharacteristicConfigurationDescriptorAsync(
GattClientCharacteristicConfigurationDescriptorValue.None);
Just dispose all objects related to the device. That will disconnect the device, unless there are other apps connected to it.
For my UWP app, even though I've used Dispose() methods, I still received notifications. What helped me was setting my device and characteristics to null. Example:
device.Dispose();
device = null;
Not all to certain of how "correct" this programming is, but it's been working fine for me so far.
The UWP Bluetooth BLE sample code from Microsoft (dispose the BLE device) didn't work for me. I had to add code (dispose the service) to disconnect the device.
private async Task<bool> ClearBluetoothLEDeviceAsync()
{
if (subscribedForNotifications)
{
// Need to clear the CCCD from the remote device so we stop receiving notifications
var result = await registeredCharacteristic.WriteClientCharacteristicConfigurationDescriptorAsync(GattClientCharacteristicConfigurationDescriptorValue.None);
if (result != GattCommunicationStatus.Success)
{
return false;
}
else
{
selectedCharacteristic.ValueChanged -= Characteristic_ValueChanged;
subscribedForNotifications = false;
}
}
selectedService?.Dispose(); //added code
selectedService = null; //added code
bluetoothLeDevice?.Dispose();
bluetoothLeDevice = null;
return true;
}
Remember you must call -= for events you have called += or Dispose() will never really garbage collect correctly. It's a little more code, I know. But it's the way it is.
Not just with bluetooth stuff, I will remind you - with everything. You can't have hard referenced event handlers and get garbage collection to work as expected.
Doing all the disposing and null references suggested didn't achieve the Windows (Windows Settings) disconnection I was looking for.
But dealing with IOCTL through DeviceIoControl did the job.
I found that after calling GattDeviceService.GetCharacteristicsAsync(), BluetoothLeDevice.Dispose() does not work. So I dispose the Service I don't need.
GattCharacteristicsResult characteristicsResult = await service.GetCharacteristicsAsync();
if (characteristicsResult.Status == GattCommunicationStatus.Success)
{
foreach (GattCharacteristic characteristic in characteristicsResult.Characteristics)
{
if (characteristic.Uuid.Equals(writeGuid))
{
write = characteristic;
}
if (characteristic.Uuid.Equals(notifyGuid))
{
notify = characteristic;
}
}
if (write == null && notify == null)
{
service.Dispose();
Log($"Dispose service: {service.Uuid}");
}
else
{
break;
}
}
Finally, when I want to disconnect the Bluetooth connection
write.Service.Dispose();
device.Dispose();
device = null;

SignalR self host connection issue

I recently created a proof of concept console application using SignalR (self host). It worked a treat for our use. The client connected fine and I was able to send updates from the server to the client. Lovely!
I've now transferred the code from the Console application to a winforms application for a prettier UI. Now that same client won't connect to the server yet it will still connect to the old Console version.
Winforms code:
string url = "http://localhost:8080";
using (WebApp.Start(url))
{
// Let the app know the server is up
}
Console code:
string url = "http://localhost:8080";
using (WebApp.Start(url))
{
Console.WriteLine("Server running on {0}", url);
Console.ReadLine();
}
Client connection code:
if (!connected)
{
int i = 0;
// Try 3 times
while (i <= 2)
{
try
{
string server = Properties.Settings.Default.Server + ":" + Properties.Settings.Default.PortNumber.ToString();
connection = new HubConnection(server);
connection.StateChanged += connection_StateChanged;
hub = connection.CreateHubProxy("MyHub");
connection.Start().Wait();
hub.On<string>("addMessage", param => { UpdateAlarmStatus(param); });
return true;
}
catch (Exception)
{
i++;
}
}
return false;
}
else
{
return true;
}
The error the client is reporting is:
Exception:Thrown: "No connection could be made because the target machine actively refused it" (System.Net.Sockets.SocketException)
A System.Net.Sockets.SocketException was thrown: "No connection could be made because the target machine actively refused it"
Time: 25/01/2015 15:09:23
Thread:Worker Thread[8232]
Why would the target machine (localhost) refuse itself which the Console version doesn't? I've been looking at the code over and over and I cannot see where I'm going wrong. Can anyone point me in the right direction please?
Thank you for reading.
Paul.
I suspect this is an issue with the configuration of your machine/infrastructure rather than the code itself, which looks fine at first glance.
Have you checked the console debug output in Visual Studio? I recently encountered an issue with similar symptoms and that was what gave me the initial clue to keep investigating. In my particular case, an exception was written to the console debug output that didn't make it to the client.
SignalR will normally negotiate with the server automatically to determine the best transport method to use. In a .NET client, the available options are LongPollingTransport, ServerSentEventsTransport and WebSocketTransport. So for some reason, your console app can use at least one of those methods, whereas your WinForms client cannot.
You can perhaps enable tracing to give you more information to work with. To do this, enter the below before you create the hub proxy:
hubConnection.TraceLevel = TraceLevels.All;
hubConnection.TraceWriter = Console.Out;
ASP.NET doco on SignalR tracing

HttpContext.Current.User.Identity.IsAuthenticated false when using WebRequestCreator.ClientHttp

I'm using ServiceStack with ClientHttp web request mode and when I try to check if the user is currently logged in (for sometime I'll need a bridge between asp.net authentication and SS one) I got false for IsAuthenticated...I've configured my service client this way
jsonServiceClient = new ServiceStack.ServiceClient.Web.JsonServiceClient(BaseAddressHelper.GetBasePathWithApiPath());
jsonServiceClient.ShareCookiesWithBrowser = true;
jsonServiceClient.UseBrowserHttpHandling = false;
jsonServiceClient.StoreCookies = true;
But when I'm on the Service I got false... if I use jsonServiceClient.UseBrowserHttpHandling = true; that part is ok but when I got an exception I don't get it deserialized correctly.. anyone of you got the same problem?
Thanks in advance

Resources