How check my device is connected (IOTCore - GCP) [duplicate] - java

Does anybody know of an easy way to trigger an event when a device on Google Core IoT goes offline? Before I switched to Google's IoT implementation, this was very easily handled by triggering an event when MQTT disconnects, but it seems Google has no easy way of doing this.
Does anybody know if there is something planned for this?
Who's back do I need to scratch to get them to see that something like this is a basic requirement for IoT device management!
Other platforms like AWS and Microsoft already have this implemented (or some way to handle it easily):
https://docs.aws.amazon.com/iot/latest/developerguide/life-cycle-events.html
Device connectivity(online/offline)status with the Auzure iot hub
I wish I had known this before writing all my code and implementing my setup using Google's IoT platform, I guess that's my fault for assuming something so simple and that should be standard for IoT devices would be available.
How are you going to compete with other IoT providers if you can't even provide basic offline/online events?!
My reply in this SO question shows how I had to write 100+ lines of code just to create a firebase function to check if a device is online (but that still doesn't handle offline events, and is just a hack for something that should be native to ANY IoT service provider!):
https://stackoverflow.com/a/54609628/378506
I'm hoping someone else has figured out a way to do this, as i've spent numerous days searching SO, Google, Google Core IoT Documentation, and still have not found anything.
Even if MQTT Last Will was supported we could make that work, but even that IS NOT SUPPORTED by Google (https://cloud.google.com/iot/docs/requirements) ... come on guys!

Your cloud project does have access to the individual MQTT connect/disconnect events, but currently they only show up in the Stackdriver logs. Within the cloud console, you can create an exporter that will publish these events to a Pub/Sub topic:
Visit the Stackdriver Logs in the
Cloud Console.
Enter the following advanced filter:
resource.type="cloudiot_device"
jsonPayload.eventType="DISCONNECT" OR "CONNECT"
Click CREATE EXPORT
Enter a value for Sink Name
Select Cloud Pub/Sub for Sink Service
Create a new Cloud Pub/Sub topic as the Sink Destination
The exporter publishes the full LogEntry, which you can then consume from a cloud function subscribed to the same Pub/Sub topic:
export const checkDeviceOnline = functions.pubsub.topic('online-state').onPublish(async (message) => {
const logEntry = JSON.parse(Buffer.from(message.data, 'base64').toString());
const deviceId = logEntry.labels.device_id;
let online;
switch (logEntry.jsonPayload.eventType) {
case 'CONNECT':
online = true;
break;
case 'DISCONNECT':
online = false;
break;
default:
throw new Error('Invalid message type');
}
// ...write updated state to Firebase...
});
Note that in cases of connectivity loss, the time lag between the device being unreachable and an actual DISCONNECT event could be as long the MQTT keep-alive interval. If you need an immediate check on whether a device is reachable, you can send a command to that device.

The best solution i think is that
We need 3 things
cloud sheduler ,
and 2 cloud functions
The first function will be the #devunwired answer but instant of
// ...write updated state to Firebase... schedule a second function to trigger in 2-3 min (let device to recconect)
the seccond function will send a command to device
if the device resposne to command
if stored status is connected dont do nothing
else if the stored status is disconnected then update the status to connected and do what ever you want maybe email
else
if stored status is disconnected dont do nothing
if stored status is connected change the status alert by email or something

Related

What function does RemoteMessage.send() trigger on Firebase?

What I really need to accomplish is an instant messaging feature using Firebase.
I've been reading the Firebase Cloud Messaging docs, but I get very confused about the pourposes of the example codes on the server side.
I thought about this solution:
Send a message on the client app to Firebase via RemoteMessage.send()
On Firebase, I catch that message and "redirect" it to the message reciever, who is another client of the app.
In my client app I have this code that I took from the documentation (Firebase was previously initialized):
instance.send(new RemoteMessage.Builder(senderID + "#fcm.googleapis.com")
.setMessageId(Integer.toString(messageID))
.addData("message", message)
.addData("action", "SAY_HELLO")
.build());
That would be the first part of the solution, but now I'm stuck on the part of the code where Firebase should "catch" the message and sends it to another user.
I was trying to write a node.js function to accomplish this, but the problem is that I don't know what is triggered when Firebase gets a RemoteMessage.
Would you mind explaining me how can I do this?
Any code example will be welcome. Thanks :)

Android/Firebase - Check to see if you are subscribed to topic

I am wondering if there is a way to test to see if you are subscribed to a topic on the android side of things.
Basically, I am HOPING that all devices will subscribe to a topic during their installation, when the token is first obtained by the device. However, there is always a chance that the device fails to subscribe. The FCM registration token should be installed on the device for a long time, and thus, the onTokenRefresh() method shouldn't be called again without clearing data, uninstall/reinstall, etc.
My idea was to test to see if the device is subscribed to a topic in my MainActivity, and if not, then try to subscribe again. If it fails to subscribe, then get a new token and try again, etc.
#Override
public void onTokenRefresh() {
// Get updated InstanceID token.
String refreshedToken = FirebaseInstanceId.getInstance().getToken();
Log.e(TAG, "Refreshed token: " + refreshedToken);
// Subscribe to a topic
Log.e(TAG, "Subscribing to topic");
FirebaseMessaging.getInstance().subscribeToTopic("test");
So, I can subscribe and unsubscribe, but how do I check if the device is subscribed to a topic? I did my fair share of googling, and couldn't find anything, unfortunately.
I would greatly appreciate any/all assistance. Thanks!
There is currently no way to check on the client side if they are subscribed to a topic.
The behavior for subscribeToTopic is it would immediately subscribe to the specified topic, if it fails, it would retry on it's own (unless your app was killed). See my answer here.
I think that forcing the onTokenRefresh call just to make sure that subscribeToTopic is too much. You could simply just call it in your initial activity if you want, that way, everytime the app starts, it sends the subscription request.
Actually this can be done by using this api: https://developers.google.com/instance-id/reference/server#get_information_about_app_instances
As IID_TOKEN you need the FCM token and in the header you have to pass Authentication: key=YOUR_SERVER_KEY. You can find the server key as described here: Firebase messaging, where to get Server Key?.
Don't forget to include details=true as query parameter in the url, otherwise the topics won't be included in the response.
I would recommend writing a Cloud Function to encapsulate it, so you don't deploy your server key to the client.

Azure notification hub: Send notification - Getting the impacted users

I'm using azure-notificationhubs-java-backend to send notifications to Azure hub. I have Azure tags created per application user. Business require me to send notification to multiple users (this part is achieved), and report back the execution status, i.e. whom Azure was able to deliver the notification, and who all were missed (so that other communication can be made with those users). We've this scenario that not all users are yet registered with Azure. Below is the call I am making:
SyncCallback<NotificationOutcome> callback = new SyncCallback<>();
notificationHub.sendNotificationAsync(templateNotification, recipientTags, callback);
NotificationOutcome outcome = callback.getResult();
// outcome has just the notificationId, and trackingId
Any suggestion how can I get success and failed tags. Or there's some other call I can make using the notificationId or trackingId to meet the desired. Thanks!
You can get this data from per message telemetry. Please see below blog for more information.
https://azure.microsoft.com/en-us/blog/retrieve-platform-notification-system-error-details-with-azure-notification-hubs/

Amazon SimpleEmail: how to check if an Email has been delivered?

I tried to send emails with Amazon SES, with the Java AWS SDK, and it worked. I would like to be able to check (at a later time) whether the delivery was successful. I will define it successful if the final mailserver accepted the mail for delivery.
I saw that when you send an email you can get a messageId that uniquely identifies your email:
SendEmailRequest request = new SendEmailRequest(from, destination, message);
SendEmailResult result = service.sendEmail(request);
String messageId = result.getMessageId();
However I saw that you can get only aggregated statistics, for example with SendDataPoint (Represents sending statistics data. Each SendDataPoint contains statistics for a 15-minute period of sending activity).
I'm not using SES to send bulk emails, but personalized notifications on a very low volume and I'd be interested to check every single message.
Did I overlook something? Is it possible to do this type of check with SES?
Amazon does provide a mechanism for you to capture bounces, which provides you with contrapositive verification.
You can create a mailbox to receive bounce notifications, then tell SES to forward bounce notifications there. e.g.:
request.setReturnPath("bounces#example.com");
You can then write code to periodically check that mailbox, and parse the messages for the destination email address.
Amazon provides a brief explanation of how they handle bounces & complaints here:
http://aws.amazon.com/ses/faqs/#37
However, if you want to check if the message avoided the spam filter or was read by the end user, that is beyond the scope of SES (although they work hard to ensure deliverability).
We use Bouncely.com. You simply set the ReturnPath to bounces#bouncely.com and it tracks all the bounces and spam reports. It also has an API that allows us to unsubscribe users automatically.
Use Amazon Simple Notification Service and define an HTTP endpoint to receive notification in case of email bounces. Works perfectly.

How to use Javapns to Support Apple's Enhanced Notification Format

Greetings,
I am creating a Java based server to create push notifications for Apple's iOS APNs service. I have found Javapns on google code which seems to provide a simple basic framework to communicate with APNs, and which seems to be fairly wide used.
http://code.google.com/p/javapns/
However, reading Apple's docs, there is an "enhanced format" for notifications which supports "expiry" i.e. setting a time (well, in seconds) for a notification to expire if it hasn't yet been delivered. I do not see any way to set this using Javapns, and I am unsure how the APNs service handles expiry of notifications if you do not explicitly set it. So,
Does anyone know how to support the enhanced notification format of APNs specifically how to set the expiry?
Does anyone know how Apple handles notification expiry if it isn't explicitly set?
Does anyone have any suggestions that don't require me to start from scratch, as the server is currently functional as is?
Thanks in advance.
Andrew
I have recently made substantial contributions to the JavaPNS project, which lead to the release of JavaPNS 2.0 a few days ago. That version provides full support for the enhanced notification format, including the ability to set your own expiry.
Sylvain
Nice that you found the java library... to bad you didn't read the docs there.
I'll post some of the highlights below:
The existing code uses the 'Simple notification format' which does not return an error EVER.
See docs at:
http://developer.apple.com/library/ios/#documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/CommunicatingWIthAPS/CommunicatingWIthAPS.html
I've tried updating to the 'Enhanced notification format' which is supposed to return an error, but I'm unable to get any errors back from the APNS. (also in the link above)
With the Enhanced format, the connection isn't being dropped immediately after sending data, but I'm not getting anything back from my socket.getInputSocket.read() call.
This issue will have to be tabled until I have more time to troubleshoot.
(Someone else commented)
Thanks a lot for looking into it.
I got the same result as yours. Maybe it has something to do with Apple Gateway.
So... you could:
1) Build your own
2) Help improve the existing library
3) Try another library like: https://github.com/notnoop/java-apns
4) Do nothing
Enhanced ios push here.
To send a notification, you can do it in three steps:
Setup the connection
ApnsService service =
APNS.newService()
.withCert("/path/to/certificate.p12", "MyCertPassword")
.withSandboxDestination()
.build();
Create and send the message
String payload = APNS.newPayload().alertBody("Can't be simpler than this!").build();
String token = "fedfbcfb....";
service.push(token, payload);
To query the feedback service for inactive devices:
Map<String, Date> inactiveDevices = service.getInactiveDevices();
for (String deviceToken : inactiveDevices.keySet()) {
Date inactiveAsOf = inactiveDevices.get(deviceToken);
...
}

Categories