ServiceFabric + ASA = Crime Detection, Smurf Part2

This blog captures a story of an idea which was in my mind from a long time, but did not prove to be feasible in past. With Service Fabric and Azure Stream Analytics this has now become possible for us to perceive the potential of technology to prevent crime.

Scenario

Here in this story we have tried to emulate a scenario wherein there are multiple traffic cameras capturing the vehicle number plates and sending it to ASA(Azure Stream Analytics) service. Suppose there is a vehicle that got stolen and has been reported just now. Law agencies need to add this vehicle in lookout table. Now the stolen vehicle happens to pass from Camera3. Camera3 which is continuously emitting data to Event Hub which in turn goes to ASA, captures the number plate data. ASA queries the input against the lookout table and filters the vehicle data as soon as it is scanned by the ASA query into the database. PowerMap sheet provides a analysis based on the database content and shows a pointer at Camera3 location, thus providing the law agencies a quick mechanism to track the vehicle

Problem Breakdown 

Broadly for our POC we need to see these 2 paths
1. Simulate the traffic cam scenario which is sending continuous data to event hubs
2. Input is read by ASA and stolen vehicle details with the Camera details are sent to output DB
 

Technical details

Input

In order to have input. We created a Stateless Service Fabric Actor project. As Service Fabric Actor has a compute and a state , this is feasible to simulate a traffic camera.
 
Broadly we are looking for following data structures. StolenCarModel is a datastructure that is holding the Car details such as SerialId (Any identification, we are considering this as unique id, and this will help us to create the clustered index in our db), Vehicle Number(Captured from image), CameraSerial(Identification Id of Camera), CaptureTime(Timestamp when it was captured, which will help in tracking investigation)
 
 public class StolenCarModel
    {
        public int SerialId { get; set; }
        public string VehicleNumber { get; set; }
        public string CameraSerial { get; set; }
        public string CaptureTime { get; set; }
    }
 
Another datastructure that needs to be maintained is CameraDetails , which will have the CameraID, Latitude and Longitude where Camera is positioned (This will help us to point in powermap), and Area which will have the name of the area
 
    public class CameraDetails
    {
        public string CamID { get; set; }
        public string Latitude { get; set; }
        public string Longitude { get; set; }
        public string Area { get; set; }
    }
 

Service Fabric Details 

First and foremost is the interface Actor for our service
 
public interface IStolenCarStatelessActor : IActor
    {
        Task<bool> StartSendingCarDetails(List<StolenCarModel> stolenCarList);
    }
 
Corresponding to the interface the Actor Class should have the implementation
 
public async Task<bool> StartSendingCarDetails(List<StolenCarModel> cameraDetails)
        {
            ActorEventSource.Current.ActorMessage(this, "Start Sending Data");
            EventHubLayer hub = new EventHubLayer();
            var sendDetails = await hub.SendEventsToEventHub(cameraDetails);
            return sendDetails;
        }
 

Smurf Details 

We are using Smurf core libraries in order to send data to event Hubs. Please refer to my previous blog on Smurf Core api at http://nabaruns.blogspot.com/2015/03/smurfan-asa-based-tool-in-making-part-1.html
 
In order to populate the StolenCarDetails class, we are using this function
 
/// <summary>
        /// Get List of sample StolenCarModel details which can be sent later to the event hub
        /// </summary>
        /// <returns>Returns the list of stolen car model</returns>

        private static List<StolenCarModel> GetMetricDataList(string camera)
        {
            Random rand = new Random();
            var metricDataList = new List<StolenCarModel>();
 
            Console.WriteLine();
            Console.WriteLine("#####################{0}####################", camera);
            for (var loop = 0; loop < 5; loop++)
            {
                var date = DateTime.Now;
                var serialId = rand.Next(0, 50);
                var nowTime = date.Ticks.ToString();
               
                Console.Write("Camera:{0} SerialId:{1} TimeStamp:{2} Vehicle:{3}", camera, serialId, nowTime, "ADC01" + serialId);
                Console.WriteLine();
                var info = new StolenCarModel() { CameraSerial = camera, SerialId = serialId, CaptureTime = nowTime, VehicleNumber = "ADC01" + serialId };
                metricDataList.Add(info);
            }
            Console.WriteLine("##############################################");
            Console.WriteLine();
            return metricDataList;
        }
 
In our POC at time t=0, we are assuming there are 5 events getting generated by each camera. We are currently simulating the camera details as mentioned in the marked line
 
This is giving us the following input
 
 
 
Now moving ahead we need to simulate multiple actors as cameras.
 
var camera1 = ActorProxy.Create<IStolenCarStatelessActor>(ActorId.NewId(), "fabric:/StolenCarStatelessActorApplication");
            var camera2 = ActorProxy.Create<IStolenCarStatelessActor>(ActorId.NewId(), "fabric:/StolenCarStatelessActorApplication");
         ...
            var camera10 = ActorProxy.Create<IStolenCarStatelessActor>(ActorId.NewId(), "fabric:/StolenCarStatelessActorApplication");
            int loop = 0;
            do
            {
                var tollboothList = GetMetricDataList("Camera1");
                var sendSuccess = camera1.StartSendingCarDetails(tollboothList);
                Console.WriteLine("Sending Camera1 Details {0}: {1}", camera1.GetActorId(), sendSuccess.Result);
                Thread.Sleep(5000);
                tollboothList = GetMetricDataList("Camera2");
                sendSuccess = camera2.StartSendingCarDetails(tollboothList);
                Console.WriteLine("Sending Camera2 details {0}: {1}", camera2.GetActorId(), sendSuccess.Result);
                Thread.Sleep(5000);
                ...
                tollboothList = GetMetricDataList("Camera10");
                sendSuccess = camera10.StartSendingCarDetails(tollboothList);
                Console.WriteLine("Sending Camera10 details {0}: {1}", camera10.GetActorId(), sendSuccess.Result);
                Thread.Sleep(5000);
                loop++;
            } while (loop < 10);
 
In above code we are creating 10 actor objects calling the Stolen Car service and then sending random data under them
 
Now having done the input part next is ASA query which will help us populate the data to db
 

ASA Query

In order to have a POC for the idea, our ASA query is very simple
 
SELECT SerialId, VehicleNumber, CameraSerial, CaptureTime FROM CallStream WHERE VehicleNumber='ADC0116';
 
In here we are saying that the stolen vehicle is ADC0116, if I get any data related to that , populate the data in my database.
 

SQL Database

In order to create a database which will keep a track of the stolen vehicles we need to create a table similar to the StolenCar Schema
 
Keeping it very simple I create the table as follows
 
Create table StolenCardTable (SerialId varchar(255), VehicleNumber varchar(255), CameraSerial varchar(255), CaptureTime varchar(255));
 
CREATE CLUSTERED INDEX StolenCardTable
    ON StolenCardTable(SerialId ASC);
GO 

Action Time

Till now I have all pieces in place to verify my app. Here is a screenshot which verifies the stateless service actor app deployed on my localhost cluster
 
 
Now after starting the client first point of verification is event hub dashboard and logs which should start receiving the events
 
 
Second verification will be ASA dashboard and logs
 
 
If till now you have seen everything is fine most probably you will get the data in database
 
16 ADC0116 Camera7 NULL
16 ADC0116 Camera9 NULL
16 ADC0116 Camera7 NULL
16 ADC0116 Camera10 NULL
16 ADC0116 Camera3 NULL
16 ADC0116 Camera2 NULL
16 ADC0116 Camera2 NULL
16 ADC0116 Camera9 NULL
16 ADC0116 Camera2 NULL
I have got this sample output in my db which says ADC0116 was first seen in Camera7 then 9 then again 7 and so on , eventually ending in 2. This can be now easily highlighted in PowerMap based on camera details and location which will be my next blog.
 
I think by now I am having a story to share with you all. The intent of this blog is to utilize the potent technologies and try to make this world a better place. Hope you will like it. Please feel free to comment your views or suggestions.

Continuation blog is at http://nabaruns.blogspot.com/2015/05/servicefabric-asa-crime-detection-part2.html

Comments

Popular posts from this blog

Firebase authentication with Ionic creator

Big Data - SWOT Analysis

LINKEDIN api call using NODE.JS OAUTH module