Beispiel #1
0
        private async Task ProcessSubscription(AssetUpdateSubscriptionModel subscriptionModel)
        {
            try
            {
                //Get machines
                //https://3dproductivity.myvisionlink.com/t/trimble.com/vss-3dproductivity/2.0/projects/a530371d-20a1-40cf-99ce-e11c54140be4/machines
                var route    = $"/projects/{subscriptionModel.ProjectUid}/machines";
                var machines = await _productivity3dV2ProxyNotification.ExecuteGenericV2Request <Machine3DStatuses>(route,
                                                                                                                    HttpMethod.Get,
                                                                                                                    null,
                                                                                                                    subscriptionModel.Headers());

                if (machines.Code != ContractExecutionStatesEnum.ExecutedSuccessfully || !machines.MachineStatuses.Any())
                {
                    //Nothing to do here. Breaking.
                    return;
                }

                var processingAssets = new List <Task>();

                //Now for each machine try to identify a matching asset
                foreach (var machine in machines.MachineStatuses)
                {
                    var task = ProcessAssetEvents(machine, subscriptionModel.ProjectUid, subscriptionModel.CustomerUid, subscriptionModel.Headers());
                    processingAssets.Add(task);
                }

                await Task.WhenAll(processingAssets);
            }
            catch (Exception e)
            {
                _log.LogError(e, $"Exception when running subscription {JsonConvert.SerializeObject(subscriptionModel)}");
            }
        }
Beispiel #2
0
        public async Task StartProcessingAssets(Guid projectUid)
        {
            // Handy for debugging, but not needed normally
            Logger.LogInformation($"Client requesting information for ProjectUID: {projectUid}");

            var token = AuthorizationToken;
            var jwt   = JwtAssertion;

            if (string.IsNullOrEmpty(token) || string.IsNullOrEmpty(jwt))
            {
                throw new UnauthorizedAccessException("Missing Authentication Headers");
            }

            // Do we need to check authentication here???
            var model = new AssetUpdateSubscriptionModel()
            {
                AuthorizationHeader = token,
                JWTAssertion        = jwt,
                CustomerUid         = Guid.Parse(CustomerUid),
                ProjectUid          = projectUid
            };

            // SignalR needs to await tasks, note from Microsoft Site:
            // Use await when calling asynchronous methods that depend on the hub staying alive. For example, a method such as Clients.All.SendAsync(...) can fail if it's called without await and the hub method completes before SendAsync finishes.
            await assetState.AddSubscription(Context.ConnectionId, model);
        }
Beispiel #3
0
        /// <inheritdoc />
        public Task AddSubscription(string clientIdentifier, AssetUpdateSubscriptionModel model)
        {
            lock (lockObj)
            {
                // Remove it it exists, a connection can only subscribe to one project
                // (multiple browsers will have multiple connections)
                connectionMapping.Remove(clientIdentifier);
                connectionMapping.Add(clientIdentifier, model);
            }

            return(Task.CompletedTask);
        }
Beispiel #4
0
        public void TestProcessing3dand2dAssets()
        {
            var job = serviceProvider.GetService <IJob>();

            Assert.IsNotNull(job);

            var subscription = new AssetUpdateSubscriptionModel()
            {
                ProjectUid          = Guid.Parse("7842662B-F8E5-4752-A64B-261CE7EDA152"),
                CustomerUid         = Guid.Parse("8BB0D3A3-A755-4AD9-A4FA-999D6C1C104C"),
                AuthorizationHeader = "TEST AUTH",
                JWTAssertion        = "TEST JWT"
            };

            var assetUid = "47C03885-4845-4637-90B5-4CCE5D8DA040";

            var machine = new MachineStatus(55743,
                                            "Test Machine from 3d",
                                            true,
                                            "LAST DESIGN FROM 3D",
                                            15215,
                                            new DateTime(2018, 1, 2, 3, 4, 5, DateTimeKind.Utc),
                                            0.59915074193701334, // radians
                                            -1.470376021323053,  // radians
                                            null,
                                            null,
                                            Guid.Parse(assetUid));

            var machineResult = new Machine3DStatuses(ContractExecutionStatesEnum.ExecutedSuccessfully);

            machineResult.MachineStatuses.Add(machine);

            var assetDetails = new AssetDetails()
            {
                AssetId  = "55743 - test",
                AssetUid = assetUid,
                LastReportedLocationLatitude  = 123.45d,
                LastReportedLocationLongitude = 43.1d,
                LastLocationUpdateUtc         = machine.lastKnownTimeStamp.Value.AddSeconds(1),
                FuelLevelLastReported         = 2.1d,
                LastPercentFuelRemainingUtc   = new DateTime(2019, 1, 1, 23, 41, 23, DateTimeKind.Utc)
            };

            var expectedResult = new AssetAggregateStatus()
            {
                CustomerUid            = subscription.CustomerUid,
                ProjectUid             = subscription.ProjectUid,
                LocationLastUpdatedUtc = assetDetails.LastLocationUpdateUtc.ToUniversalTime(),
                AssetUid  = Guid.Parse(assetUid),
                Design    = machine.lastKnownDesignName,
                FuelLevel = assetDetails.FuelLevelLastReported,
                FuelLevelLastUpdatedUtc = assetDetails.FuelReportedTimeUtc,
                Latitude        = assetDetails.LastReportedLocationLatitude,
                Longitude       = assetDetails.LastReportedLocationLongitude,
                LiftNumber      = 15215,
                AssetIdentifier = "55743 - test", // will take this from the 2d data, as a higher priority that the 3d machine name
                MachineName     = "Test Machine from 3d"
            };

            var expectedHeaders = GetExpectedHeaders(subscription.CustomerUid, subscription.AuthorizationHeader, subscription.JWTAssertion);
            AssetAggregateStatus resultStatus = null; // Keep a reference to the event generated for comparasion

            // Setup the returns
            mockAssetStatusServerHubClient
            .Setup(m => m.GetSubscriptions())
            .Returns(Task.FromResult(new List <AssetUpdateSubscriptionModel> {
                subscription
            }));

            mockProductivity3dV2ProxyNotification.Setup(m =>
                                                        m.ExecuteGenericV2Request <Machine3DStatuses>(
                                                            It.IsAny <string>(),
                                                            It.IsAny <HttpMethod>(),
                                                            It.IsAny <Stream>(),
                                                            It.IsAny <IHeaderDictionary>()))
            .Returns(Task.FromResult(machineResult));

            mockFleetAssetDetails
            .Setup(m => m.GetAssetDetails(
                       It.IsAny <string>(),
                       It.IsAny <IHeaderDictionary>()))
            .Returns(Task.FromResult(assetDetails));

            mockAssetStatusServerHubClient
            .Setup(m => m.UpdateAssetLocationsForClient(It.IsAny <AssetAggregateStatus>()))
            .Returns(Task.FromResult(true))
            .Callback <AssetAggregateStatus>((e) => { resultStatus = e; });

            // Run the test
            job.Run(null).Wait();

            // Validate the calls
            // We should have this called for our asset uid which matched to the 3d asset id
            mockFleetAssetDetails
            .Verify(m => m.GetAssetDetails(
                        It.Is <string>(s => Guid.Parse(s) == Guid.Parse(assetDetails.AssetUid)),
                        It.Is <IHeaderDictionary>(d => DictionaryContentEquals(d, expectedHeaders))),
                    Times.Once);

            // We should have received one event
            mockAssetStatusServerHubClient
            .Verify(m =>
                    m.UpdateAssetLocationsForClient(It.IsAny <AssetAggregateStatus>()),
                    Times.Once());

            // Validate it is the expected result
            Assert.IsNotNull(resultStatus);
            resultStatus.Should().BeEquivalentTo(expectedResult);
        }
Beispiel #5
0
        public void TestProcessing3dAssetsOnly()
        {
            var job = serviceProvider.GetService <IJob>();

            Assert.IsNotNull(job);

            var subscription = new AssetUpdateSubscriptionModel()
            {
                ProjectUid          = Guid.Parse("038A3ACB-C985-4E3A-AB98-FF3C939B30BF"),
                CustomerUid         = Guid.Parse("12DCFAF5-96A4-4E27-BE53-28A226A7AAB6"),
                AuthorizationHeader = "TEST AUTH",
                JWTAssertion        = "TEST JWT"
            };

            var machine1 = new MachineStatus(123,
                                             "Test Machine1",
                                             true,
                                             "LAST DESIGN 1",
                                             6433,
                                             new DateTime(2010, 1, 2, 3, 4, 5, DateTimeKind.Utc),
                                             0.59915074193701334, // radians
                                             -1.470376021323053,  // radians
                                             null,
                                             null);

            var machineResult = new Machine3DStatuses(ContractExecutionStatesEnum.ExecutedSuccessfully);

            machineResult.MachineStatuses.Add(machine1);

            var expectedResult = new AssetAggregateStatus()
            {
                AssetIdentifier        = "Test Machine1",
                LiftNumber             = 6433,
                CustomerUid            = subscription.CustomerUid,
                ProjectUid             = subscription.ProjectUid,
                LocationLastUpdatedUtc = machine1.lastKnownTimeStamp,
                AssetUid  = null,
                Design    = machine1.lastKnownDesignName,
                FuelLevel = null,
                FuelLevelLastUpdatedUtc = null,
                Latitude    = machine1.lastKnownLatitude * RADIANS_TO_DEGREES,
                Longitude   = machine1.lastKnownLongitude * RADIANS_TO_DEGREES,
                MachineName = "Test Machine1"
            };

            var expectedHeaders = GetExpectedHeaders(subscription.CustomerUid, subscription.AuthorizationHeader, subscription.JWTAssertion);
            AssetAggregateStatus resultStatus = null; // Keep a reference to the event generated for comparasion

            // Setup the returns
            mockAssetStatusServerHubClient
            .Setup(m => m.GetSubscriptions())
            .Returns(Task.FromResult(new List <AssetUpdateSubscriptionModel> {
                subscription
            }));

            mockProductivity3dV2ProxyNotification.Setup(m =>
                                                        m.ExecuteGenericV2Request <Machine3DStatuses>(
                                                            It.IsAny <string>(),
                                                            It.IsAny <HttpMethod>(),
                                                            It.IsAny <Stream>(),
                                                            It.IsAny <IHeaderDictionary>()))
            .Returns(Task.FromResult(machineResult));

            mockAssetStatusServerHubClient
            .Setup(m => m.UpdateAssetLocationsForClient(It.IsAny <AssetAggregateStatus>()))
            .Returns(Task.FromResult(true))
            .Callback <AssetAggregateStatus>((e) => { resultStatus = e; });

            // Run the test
            job.Run(null).Wait();

            // Validate the calls

            // CCSSSCON-85 not possible with WM devices
            //// We should not call this if we have not matching 3d/2d assets
            //mockAssetResolverProxy
            //  .Verify(m => m.GetMatching3D2DAssets(It.IsAny<MatchingAssetsDisplayModel>(),
            //      It.IsAny<IHeaderDictionary>()),
            //    Times.Never);

            // We should have received one event
            mockAssetStatusServerHubClient
            .Verify(m =>
                    m.UpdateAssetLocationsForClient(It.IsAny <AssetAggregateStatus>()),
                    Times.Once());

            // Validate it is the expected result
            Assert.IsNotNull(resultStatus);
            resultStatus.Should().BeEquivalentTo(expectedResult);
        }
Beispiel #6
0
        public void TestProcessingSubscriptions()
        {
            var job = serviceProvider.GetService <IJob>();

            Assert.IsNotNull(job);

            var subscription1 = new AssetUpdateSubscriptionModel()
            {
                ProjectUid          = Guid.Parse("4A856F8C-08D7-4C6E-B6BF-6852658E6A72"),
                CustomerUid         = Guid.Parse("A66D7657-59FC-4C56-8E92-495AADEFD819"),
                AuthorizationHeader = "TEST AUTH",
                JWTAssertion        = "TEST JWT"
            };

            var subscription2 = new AssetUpdateSubscriptionModel()
            {
                ProjectUid          = Guid.Parse("5DADE1FA-7FAF-4822-93D9-DAE9CFC9BA77"),
                CustomerUid         = Guid.Parse("E04F38AD-44C7-4C8B-95E3-F597E4A1C205"),
                AuthorizationHeader = "TEST AUTH",
                JWTAssertion        = "TEST JWT"
            };

            Assert.AreNotEqual(subscription1.ProjectUid, subscription2.ProjectUid, "Mock subscriptions must be different");
            Assert.AreNotEqual(subscription1.CustomerUid, subscription2.CustomerUid, "Mock subscriptions must be different");

            var subscriptions = new List <AssetUpdateSubscriptionModel> {
                subscription1, subscription2
            };

            // We will ensure that we get the correct subscriptions, and process each subscription
            mockAssetStatusServerHubClient.Setup(m => m.GetSubscriptions()).Returns(Task.FromResult(subscriptions));

            // The first step is to call out to 3dp for each subscription, ensure we do this (with the correct headers)
            mockProductivity3dV2ProxyNotification.Setup(m =>
                                                        m.ExecuteGenericV2Request <Machine3DStatuses>(
                                                            It.IsAny <string>(),
                                                            It.IsAny <HttpMethod>(),
                                                            It.IsAny <Stream>(),
                                                            It.IsAny <IHeaderDictionary>()))
            .Returns(Task.FromResult(new Machine3DStatuses()));

            // Execute the call to the job
            job.Run(null).Wait();

            // Now we should have called out for the subscriptions, and for each one called out to raptor with the correct project UID and headers
            // First Confirm the subscriptions
            mockAssetStatusServerHubClient.Verify(m => m.GetSubscriptions(), Times.Once);

            var subscription1Headers = GetExpectedHeaders(subscription1.CustomerUid, subscription1.AuthorizationHeader, subscription1.JWTAssertion);

            var subscription1Route = string.Format(EXPECTED_RAPTOR_MACHINE_ROUTE_FORMAT, subscription1.ProjectUid);

            mockProductivity3dV2ProxyNotification.Verify(m => m.ExecuteGenericV2Request <Machine3DStatuses>(
                                                             It.Is <string>(s => s == subscription1Route),
                                                             It.IsAny <HttpMethod>(),
                                                             It.IsAny <Stream>(),
                                                             It.Is <IHeaderDictionary>(d => DictionaryContentEquals(d, subscription1Headers))),
                                                         Times.Once);

            // Ensure the second subscription was called too
            var subscription2Headers = GetExpectedHeaders(subscription2.CustomerUid, subscription2.AuthorizationHeader, subscription2.JWTAssertion);
            var subscription2Route   = string.Format(EXPECTED_RAPTOR_MACHINE_ROUTE_FORMAT, subscription2.ProjectUid);

            mockProductivity3dV2ProxyNotification.Verify(m => m.ExecuteGenericV2Request <Machine3DStatuses>(
                                                             It.Is <string>(s => s == subscription2Route),
                                                             It.IsAny <HttpMethod>(),
                                                             It.IsAny <Stream>(),
                                                             It.Is <IHeaderDictionary>(d => DictionaryContentEquals(d, subscription2Headers))),
                                                         Times.Once);

            // And confirm there are no other calls to the request
            mockProductivity3dV2ProxyNotification.Verify(m => m.ExecuteGenericV2Request <Machine3DStatuses>(
                                                             It.IsAny <string>(),
                                                             It.IsAny <HttpMethod>(),
                                                             It.IsAny <Stream>(),
                                                             It.IsAny <IHeaderDictionary>()),
                                                         Times.Exactly(2));
        }
Beispiel #7
0
        public void TestAddAndRemove()
        {
            var state = new InMemoryAssetStatusState() as IAssetStatusState;

            Assert.NotNull(state);

            {
                var count = state.GetSubscriptions().Result.Count;
                Assert.True(count == 0, $"Expected a zero count with a new state, got ${count} instead");
            }

            const string clientId1 = "307CA37C-2422-4AD9-A512-34DFB3BC7507";
            const string clientId2 = "B0CCDF38-AA7E-4BCB-8692-53C898D6A469";

            var model1 = new AssetUpdateSubscriptionModel()
            {
                ProjectUid = Guid.Parse("2A131E56-880E-44E8-901F-86D3CD3CBDBB")
            };
            var model2 = new AssetUpdateSubscriptionModel()
            {
                ProjectUid = Guid.Parse("D5C5A0FA-2480-4ACB-BDCE-0CDF10998BF8")
            };
            var model3 = new AssetUpdateSubscriptionModel()
            {
                ProjectUid = Guid.Parse("BDE14152-1B1B-4809-85B2-384DA1D91B43")
            };

            // Add the first model
            state.AddSubscription(clientId1, model1);

            // count should be 1
            {
                var items = state.GetSubscriptions().Result;
                Assert.True(items.Count == 1, $"Added a model, count should be one but it is ${items.Count}");
                Assert.Equal(model1, items[0]);
            }

            // Add the second model, with the same identifier (this should replace the existing one)
            state.AddSubscription(clientId1, model2);

            // count should be 1
            {
                var items = state.GetSubscriptions().Result;
                Assert.True(items.Count == 1, $"Added a model with the same identifier, count should be one but it is ${items.Count}");
                Assert.Equal(model2, items[0]);
            }

            // Add another model, with another identifier
            state.AddSubscription(clientId2, model3);

            // Count should be 2
            {
                var items = state.GetSubscriptions().Result;
                Assert.True(items.Count == 2, $"Added a model with a new identifier, count should be two but it is ${items.Count}");
                Assert.Contains(model2, items);
                Assert.Contains(model3, items);
            }

            // Remove the first subscription and an unknown subscription
            state.RemoveSubscription(clientId1);
            state.RemoveSubscription("does not exist id");

            // Count should be 1
            {
                var items = state.GetSubscriptions().Result;
                Assert.True(items.Count == 1, $"Removed a subscription, count should be one but it is ${items.Count}");
                Assert.Contains(model3, items);
            }

            state.RemoveSubscription(clientId2);

            // should be empty
            {
                var count = state.GetSubscriptions().Result.Count;
                Assert.True(count == 0, $"Expected a zero count with all clients removed, got ${count} instead");
            }
        }