Friday 14 September 2018

Moving Marker In Map Using SignalR in ng-map In AngularJS



            In this article, I would like to know you about using of SignalR in ng-map In AngularJS.
So , To view map in the application, we have to add the angular script of  ng-map and also to use SignalR, we have to add angular-signalr-hub from nuget package manager.
This angular-signalr-hub establish the connection from client to server and having some predefined properties like setting the rootpath and can write user defined listeners and methods that can establish the connection and stop the connection.
And also jquery.signalR-2.2.0.min.js is also added along with that, so that it can work with web sockets and connects the client with server and if any connection dropout happens, or any connection problems,  it throws error message every second.
To create this application we need two projects in one solution, one is client side project i.e., in angularjs and the other is server side project i.e., webapi.
Create the empty project and add index.html and index.js files as follows for angularjs application
index.html :-
<!DOCTYPE html>
<html>
<head>
    <title></title>
    <meta charset="utf-8" />
    <title>AngularJS - Google Maps</title>
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css">
    <script src="scripts/jquery-1.6.4.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.4/angular.min.js"></script>

   <!—To use google map we have to use below script -->
    <script src="scripts/ng-map.min.js"></script>
<!—To use SignalR in Angularjs -->
    <script src="scripts/angular-signalr-hub.js"></script>
<!—To support working in SignalR, this JQuery SignalR should be used  -->
    <script src="scripts/jquery.signalR-2.2.0.min.js"></script>

    <script src="index.js"></script>
</head>
<body>
    <div ng-app="angulargooglemaplocationtrackApp" ng-controller="locationtrackerCtrl as maplocation">
        <div map-lazy-load="https://maps.google.com/maps/api/js" map-lazy-load-params="{{maplocation.googleMapsUrl}}">
            <ng-map center="{{maplocation.center}}" style="height: 700px"
                    zoom="{{maplocation.zoom}}" mapTypeId="ROADMAP"
                    map-type-control="false">

                <marker position="{{maplocation.devicePoint}}"></marker>
                <!--<shape name="polyline" path="{{maplocation.positions}}"
                         geodesic="true"
                         stroke-color="#FF0000"
                         stroke-opacity="1.0"
                         stroke-weight="2">
                </shape>-->

                <info-window id="info">
                    <div ng-non-bindable="">
                        Device: {{maplocation.deviceId}}<br />
                    </div>
                </info-window>
            </ng-map>
        </div>
        <div>
            <input type="text" ng-model="maplocation.deviceId" />
            <input type="button" ng-click="maplocation.drawMap(maplocation.deviceId)" value="Show Tracks" />
        </div>

    </div>
</body>
</html>

index.js
var locapp = angular.module('angulargooglemaplocationtrackApp', ['ngMap','SignalR']);
locapp.controller('locationtrackerCtrl', ['$scope', '$http', 'Hub', 'NgMap', function ($scope, $http, Hub, NgMap) {
    var serviceBasePath = 'http://localhost:58171';
    var maplocation = this;
    NgMap.getMap().then(function (map) {
        maplocation.map = map;
    });
//To load the Maps JavaScript API, use a script tag having Google API Key
    maplocation.googleMapsUrl = "https://maps.googleapis.com/maps/api/js?key=AIzaSyC7QgeORUjgqSFlvmr9kT2mh8beqqB4buw";

   
    maplocation.startPoint = "";
    maplocation.devicePoint = "";
    maplocation.positions = [];
    maplocation.data = []
    maplocation.center = "23.4440644, 79.0486879";
    maplocation.zoom = 4;

    var devId = "";
    maplocation.drawMap = function () {
        i = 1;
        maplocation.devicePoint = "";
        console.log(maplocation.deviceId);
        if (devId) {
            hub.removeDeviceFromGroup(devId);
        }
        hub.addDeviceToGroup(maplocation.deviceId);
        devId = maplocation.deviceId;
        $http.get(serviceBasePath + '/api/LocationTracker/ChangeDeviceLocations', {
            params: { deviceId: maplocation.deviceId }
        }).then(
            function (response) {

            }, function (error) {
                //console.log(error);
            });


    }

    var i = 1;

    //Hub setup
    var hub = new Hub('LocationTrackHub', {
        listeners: {
            'getDeviceLocation': function (lat, lng) {
                var position = "[" + lat + "," + lng + "]";
                maplocation.devicePoint = position;
                // maplocation.positions.push(position);
                if (i == 1) {
                    maplocation.zoom = 4;
                    maplocation.center = position;
                    i++;
                }
                $scope.$apply();
            }

        },
        rootPath: serviceBasePath + '/signalr',
        methods: ['addDeviceToGroup', 'removeDeviceFromGroup'],
        errorHandler: function (error) {
            console.error(error);
        }
    });

}]);

And now add another WebAPI project to the solution and install Microsoft.AspNet.SignalR.Core and Microsoft.AspNet.SignalR.SystemWeb
And add a folder named Hubs and add a .cs file named HubAction.cs  to synchronize and send messages to the client side,for that implement Listeners using SignalR HubContext  for continous interaction between the client side and server side application as below:

HubAction.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace WebApi_ngMapSignalRHub.Hubs
{
    public class HubActions
    {
        private static Microsoft.AspNet.SignalR.IHubContext GetDeviceHub()
        {
            return Microsoft.AspNet.SignalR.GlobalHost.ConnectionManager.GetHubContext<LocationTrackHub>();
        }

        public static void SendLocationUpdate(string DeviceId, double latitude, double longitude)
        {

            GetDeviceHub().Clients.Group(DeviceId).getDeviceLocation(latitude, longitude);
        }
    }
}
And add another .cs file to implement the hub to connect and disconnect or start and stop the connection through websocket to client side application as below :

LocationTrackHub.cs

using Microsoft.AspNet.SignalR;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Web;

namespace WebApi_ngMapSignalRHub.Hubs
{
    public class LocationTrackHub :Hub
    {
        public override Task OnConnected()
        {

            Clients.Caller.hello("Hello!");
            return base.OnConnected();
        }
        public void addDeviceToGroup(string deviceid)
        {
            Groups.Add(Context.ConnectionId, deviceid);
        }
        public void removeDeviceFromGroup(string deviceid)
        {
            Groups.Remove(Context.ConnectionId, deviceid);

        }
    }
}

And to access the locations from an API, for that add DeviceTrackerController and write the logic to get the saved locations or static locations. The code is as below:

DeviceTrackerController.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Threading;
using System.Web.Http;
using WebApi_ngMapSignalRHub.Hubs;

namespace WebApi_ngMapSignalRHub.Controllers
{
    public class DeviceTrackerController : ApiController
    {
        [Route("api/DeviceTracker/ChangeDeviceLocations")]
        [HttpGet]
        public void ChangeDeviceLocations()
        {
            LocationDetailList locLst = new LocationDetailList();
            var locList = locLst.LocationList;
            foreach (var item in locList)
            {
                HubActions.SendLocationUpdate(item.DeviceId, item.Latitude, item.Longitude);
                Thread.Sleep(5000);
            }
        }
    }
    // Class LocationDetails
    public class LocationDetails
    {
        public string DeviceId { get; set; }
        public double Latitude { get; set; }
        public double Longitude { get; set; }
    }

    // The Below class is having property named 'LocationList' with get; set; accessors
    public class LocationDetailList
    {
        //  To get data from list
        public List<LocationDetails> LocationList
        {
            get { return locationList; }
        }

        //  Binding data to List i.e., set data to list
        List<LocationDetails> locationList = new List<LocationDetails>()
        {
           new LocationDetails() {
               DeviceId ="1001",
               Latitude =17.4246285829186,
               Longitude =78.3438836269752
           },
            new LocationDetails() {
               DeviceId ="1001",
               Latitude =17.52462858246374,
               Longitude =78.4438836285764
           },
             new LocationDetails() {
               DeviceId ="1001",
               Latitude =17.62462858285758,
               Longitude =78.5438836205945
           },
              new LocationDetails() {
               DeviceId ="1001",
               Latitude =17.72462858854758,
               Longitude =78.6438836636475
           },
               new LocationDetails() {
               DeviceId ="1001",
               Latitude =17.82462857656475,
               Longitude =78.7438836756667
           },
           new LocationDetails() {
               DeviceId ="1001",
               Latitude =18.4246285829186,
               Longitude =79.3438836269752
           },
           new LocationDetails() {
               DeviceId ="1002",
               Latitude =23.4440644,
               Longitude =79.0486879
           },
            new LocationDetails() {
               DeviceId ="1001",
               Latitude =19.4246285829186,
               Longitude =80.3438836269752
           },
              new LocationDetails() {
               DeviceId ="1002",
               Latitude =24.4440644,
               Longitude =80.0486879
           },

    };


    }
}

While trying to hit Client Project to Server Project then, we will get CORS error, to rectify the CORS (Cross Origin Request Sharing) error, add reference Microsoft.AspNet.WebApi.Cors and add the below code in Register method In WebApiConfig file

var cors = new EnableCorsAttribute("*", "*", "*");

 config.EnableCors(cors);

Now Run the application

Output :
 After running the application it looks as below :

Enter the Device id in the search box as below : 



Now Click on Show Tracks, now the output will be as below :

No comments:

Post a Comment

Note: only a member of this blog may post a comment.