11

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!

sMyles
  • 2,418
  • 1
  • 30
  • 44
  • See https://firebase.google.com/docs/database/android/offline-capabilities#section-presence – Frank van Puffelen Feb 09 '19 at 23:27
  • @FrankvanPuffelen okay but that's specific to firebase, I need something like that for Google Core IoT devices – sMyles Feb 10 '19 at 00:35
  • By the use of your other SO question I assume you're device is using Firebase. I'm not a Java dev so I didn't put an answer, but I would use whatever event stream or notification channel you have (in JS it would be an rx Observable or Subject) and write an event provider based on online/offline state? – Dennis Smolek Feb 18 '19 at 17:14
  • @DennisSmolek that's the problem though, removing firebase from having anything to do with this... there's no way to determine when a device goes offline -- i was referencing Firebase as that's what I used to manually check the device status by comparing timestamps for the device (or sending command and checking response) – sMyles Feb 19 '19 at 00:04
  • So I basically have to run that function EVERYTIME my app is loaded, or page is changed, to make sure the device has not gone offline. Even if they just added LWT to MQTT implementation I could come up with a way to trigger a pub/sub and update the db to mark it as offline .. but right now Google has NOTHING for this which I really just can't fathom why they don't – sMyles Feb 19 '19 at 00:05

2 Answers2

13

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:

  1. Visit the Stackdriver Logs in the Cloud Console.
  2. Enter the following advanced filter:

    resource.type="cloudiot_device"
    jsonPayload.eventType="DISCONNECT" OR "CONNECT"
    
  3. Click CREATE EXPORT

  4. Enter a value for Sink Name
  5. Select Cloud Pub/Sub for Sink Service
  6. 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.

devunwired
  • 62,780
  • 12
  • 127
  • 139
  • Devunwired -- you sir are a godsend! Thank you thank you thank you thank you!! Works perfectly, this is amazing!! – sMyles Feb 22 '19 at 15:17
  • 5
    For those coming here trying to solve the problem, devunwired is missing a step. You must enable at least "Info" logging for your IoT Core registry. Go to IoT Core > Registries > [your registry] > Edit Registry > Select "Info" log level > Click save. – calumb Mar 06 '19 at 01:51
  • 1
    Stackdriver logs sometimes does not keep order. In case `DISCONNECT` followed by `CONNECT` event, sometimes Stackdriver logs `CONNECT` first then `DISCONNECT`. Firebase status does not match the actual state. Any idea for avoid this? – N.F. Oct 04 '20 at 23:26
0

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