ETA Rules

Micro Service Code

Create a micro service

import io.boodskap.iot.MicroApi;

// ======== API Methods ================

@MicroApi(slug="lnames", desc="List all available locations")
def ListAllLocationNames(def args) {
    
    def query = '{"query":{"bool":{"must":[{"match":{"domainKey":"$dkey"}}]}},"_source":["domainKey","name"]}';

    def result = search(query, 'GEOFENCE', [:]);
    
    def narr = [];
    
    for(r : result){
        narr.add(r._source.name);
    }
 
    return narr;
}

@MicroApi(slug="lmembers", params=["destination"], desc="List all members driving to a location")
def ListAllMembers(def args) {
    
    def query = '{"query":{"bool":{"must":[{"match":{"destination":"$destination"}}]}}}';

    def result = search(query, 'RECORD', 1000L, ['destination': args.destination]);
    
    def narr = [];
    
    for(r : result){
        r._source.remove("domainKey");
        narr.add(r._source);
    }
 
    return narr;
}

@MicroApi(slug="distance", params=["destination", "lat", "lon"], types=['string', 'double', 'double'], desc="Get the distance from a geo point to a destination")
def GetDistance(def args){
    
    def fence = geofence.get(args.destination);
    
    if(null == fence){
        return [error:"Unable to find location " + args.destination];
    }
    
    def coords = "";
    def loc = fence.location;
    
    if(loc.type == 'circle' || loc.type == 'point'){
        coords += loc.coordinates[0];
        coords +=",";
        coords += loc.coordinates[1];
    }else{
        
        def len = loc.coordinates[0].size();
        
        for(int i=0;i<len;i++){
            coords += loc.coordinates[0][i][0];
            coords += ",";
            coords += loc.coordinates[0][i][1];
            
            if(i+1<len){
                coords +="|";
            }
        }
        
    }

    def key = json.parseText(domain.property('google.map.key')).get("apiKey");
    
    def jresult = rest.get("https://maps.googleapis.com/maps/api/distancematrix/json")
        .queryString("origins", String.format("%s,%s", args.lat, args.lon))
        .queryString("destinations", coords)
        .queryString("key", key)
        .asJson()
        .getBody();
        
    def vals = util.toMap(jresult);
    
    if(null != vals.rows && !vals.rows.isEmpty()){
        return vals.rows.elements[0][0];
    }
        
    return vals;
}

// ========== Helper Methods =============

def search(def queryTemplate, def type, def bargs){
    return search(queryTemplate, type, null, bargs);
}

def search(def queryTemplate, def type, def specId, def bargs){
    
    def engine = new groovy.text.SimpleTemplateEngine();
    def binding = ["dkey": domain.getDomainKey()];
    
    binding.putAll(bargs);

    def query = engine.createTemplate(queryTemplate).make(binding);
    
    if(null != specId){
        elastic.setSpecId(specId);
    }

    def result = elastic.search(type, query.toString());
 
    return result.hits.hits;
}

Location Message Rule Code

Define the message rule

try{
    
    log.info("processing...");
    
    def api = micro.api("ETA");
    
    def args = [:];
    
    args["destination"] = msg.destination;
    args['lat'] = msg.latitude;
    args['lon'] = msg.longitude;
    
    def results = api.call("distance", args);
    
    log.info("%s", results);
    
    def rec = [:];
    
    if("OK".equals(results.status)){
        
        args["stamp"] = util.millis();
        args["member"] = msg.deviceid;
        args["destination"] = msg.destination;
        args['latitude'] = msg.latitude;
        args['longitude'] = msg.longitude;
        
        args['distance'] = results.distance.value;
        args['eta'] = results.duration.value + util.millis();
        
        record.insert(1000, msg.deviceid, args);
    }
    
}catch(Exception ex){
    log.error(ex);
}