Skip to main content

Detecting device status changes

Code similar to the following can be used to detect when a device goes offline:

CREATE  TYPE MyUser  ( 
	name java.lang.String , 
        myid java.lang.String  
 ) ;

CREATE  CACHE LoadIDsCache USING FileReader ( 
  wildcard: 'user.csv',
  directory: '.'
) 
PARSE USING Global.DSVParser () 
QUERY (  keytomap: 'myid' ) OF  MyUser;

CREATE  CQ PopulateMasterStream 
INSERT INTO MasterStream
SELECT * FROM admin.LoadIDsCache c, heartbeat(interval 5 second) h;

CREATE  WINDOW MasterWinow OVER MasterStream KEEP 1 ROWS  PARTITION BY myid;

CREATE  SOURCE LiveEventStream USING TCPReader  ( 
  IPAddress: 'localhost',
  portno: 1234
 ) 
 PARSE USING DSVParser  ()
  headerlineno: 0
 ) 
OUTPUT TO liveEvStream ;

CREATE OR REPLACE CQ CreateLiveEventsCQ 
  INSERT INTO liveObjectStream
  SELECT TO_STRING(data[0]) as myId FROM liveEvStream l;

CREATE OR REPLACE JUMPING WINDOW LiveObjWindow
  OVER liveObjectStream KEEP 1 ROWS WITHIN 10 second PARTITION BY myId;

/* select * from admin.NonExistObjStream;
[
   myID = 1
   cnt = 1
   status = existent
]
[
   myID = null 
   cnt = 4
   status = non-existent
]
*/

select lw.myId as myID, count(*) as cnt, 
CASE WHEN lw.myId IS NULL 
  THEN "non-existent" 
  ELSE "existent" END as status
from   MasterWinow mw 
left join LiveObjWindow lw on mw.myid = lw.myId
group by lw.myId;

The cache file has the format:

device_name_a,1
device_name_b,2
...

Code similar to the following can be used detect both when a device goes offline and comes back online:

CREATE OR REPLACE CQ UserStateCQ
INSERT INTO CurrentUserStateStream
SELECT
	lw.myId as myID, 
	count(*) as cnt, 
	DNOW() as StateTime,
	CASE WHEN lw.myId IS NULL THEN "offline" ELSE "online" 
	END as status
	
FROM   MasterWinow mw 
LEFT JOIN LiveObjWindow lw on mw.myid = lw.myId
GROUP BY lw.myId;

CREATE SLIDING WINDOW UserState OVER CurrentUserStateStream KEEP 2 ROW PARTITION BY myId;

CREATE OR REPLACE CQ WatchUserStateCQ
INSERT INTO ChangedUserStateStream
SELECT
	lw.myId as myID, 
	TO_LONG(LAST(w.StateTime) - FIRST(w.StateTime)) as StateChangeInterval,
	CASE 
		WHEN LAST(w.status) == 'online' AND FIRST(w.status) == 'online'  THEN "up"
		WHEN LAST(w.status) == 'online' AND FIRST(w.status) == 'offline'  THEN "online"
		WHEN LAST(w.status) == 'offline' AND FIRST(w.status) == 'online'  THEN "down"
		WHEN LAST(w.status) == 'offline' AND FIRST(w.status) == 'offline'  THEN "offline"
	END as ChangeLabel
FROM   UserState w 
GROUP BY w.myID
HAVING ChangeLabel = 'down' OR ChangeLabel ='online';

The two-row window acts as a two-node state machine. The addition of a CQ can generate events that meet business requirements:

  • alerts on state changes

  • accumulating statistics on device uptime, downtime, frequency of change, and so on