예제 #1
0
        private async Task ProcessAssetEvents(MachineStatus machine, Guid projectUid, Guid customerUid, IHeaderDictionary headers)
        {
            AssetAggregateStatus statusEvent = null;

            if (machine.AssetUid.HasValue)
            {
                // CCSSCOON-85 it's not possible to match radio types in WM cws/ProfileX
                // var matchingAsset = await _deviceProxy.GetMatching3D2DAssets(new MatchingAssetsDisplayModel() {AssetUID3D = assetList.First().Key.ToString()}, headers);
                //Change that for the actual matched asset. Since we supplied 3d asset get data for the matching 2d asset.
                //if there is no 2d asset we should try using SNM asset

                var(details, summary) = await GetAssetData(machine.AssetUid.ToString(), headers);

                statusEvent = GenerateEvent(customerUid, projectUid, machine.AssetUid, machine, details, summary);
            }
            else
            {
                // Cant find some information, build a cut down event
                statusEvent = GenerateEvent(customerUid, projectUid, null, machine, null, null);
            }

            if (statusEvent != null)
            {
                await _assetStatusServerHubClient.UpdateAssetLocationsForClient(statusEvent);
            }
        }
예제 #2
0
        /// <inheritdoc />
        public async Task <bool> UpdateAssetLocationsForClient(AssetAggregateStatus assets)
        {
            var connections = await assetState.GetClientsForProject(assets.CustomerUid, assets.ProjectUid);

            await hub.Clients.Clients(connections).UpdateAssetStatus(assets);

            return(true);
        }
예제 #3
0
        /// <summary>
        /// Trigger an event for a particular Asset - this will cause the signalR hub to notify all relevant UI clients
        /// </summary>
        public async Task <bool> UpdateAssetLocationsForClient(AssetAggregateStatus assets)
        {
            if (Connected)
            {
                return(await Connection.InvokeAsync <bool>(nameof(IAssetStatusServerHub.UpdateAssetLocationsForClient), assets));
            }

            Logger.LogWarning("Not connected - cannot update locations");
            return(false);
        }
예제 #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);
        }
예제 #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);
        }
예제 #6
0
        /// <summary>
        /// Generate a UI Event based on the information passed in
        /// Add any new fields that need populating to this method
        /// </summary>
        private AssetAggregateStatus GenerateEvent(Guid customerUid, Guid projectUid, Guid?assetUid, MachineStatus machineStatus, AssetDetails details, AssetSummary summary)
        {
            var result = new AssetAggregateStatus
            {
                ProjectUid         = projectUid,
                CustomerUid        = customerUid,
                AssetUid           = assetUid,
                UtilizationSummary = summary
            };

            // This is where all the magic happens, in terms of mapping data we have from 3d / 2d endpoints into an event for the UI
            // details / summary can be null, machineStatus won't be.
            var lastLocationTimeUtc = machineStatus.lastKnownTimeStamp;

            // These values are in radians, where the AssetDetails values are in degrees
            result.Latitude    = machineStatus.lastKnownLatitude?.LatRadiansToDegrees();
            result.Longitude   = machineStatus.lastKnownLongitude?.LonRadiansToDegrees();
            result.Design      = machineStatus.lastKnownDesignName;
            result.LiftNumber  = machineStatus.lastKnownLayerId;
            result.MachineName = machineStatus.MachineName;

            // If we have a Asset ID (which matches Asset ID in Fleet management) from UF, use that, otherwise machine name
            result.AssetIdentifier = !string.IsNullOrEmpty(details?.AssetId)
        ? details.AssetId
        : machineStatus.MachineName;

            // Extract data from Asset Details
            if (details != null)
            {
                // Do we have a newer location?
                if (lastLocationTimeUtc == null || details.LastLocationUpdateUtc > lastLocationTimeUtc)
                {
                    result.Latitude     = details.LastReportedLocationLatitude;
                    result.Longitude    = details.LastReportedLocationLongitude;
                    lastLocationTimeUtc = details.LastLocationUpdateUtc;
                }

                result.FuelLevel = details.FuelLevelLastReported;
                result.FuelLevelLastUpdatedUtc = details.FuelReportedTimeUtc;
                result.AssetIcon         = details.AssetIcon;
                result.AssetSerialNumber = details.AssetSerialNumber;
                if (details.Devices?.Count > 0)
                {
                    result.DeviceName = string.Join(", ", details.Devices.Select(d => d.DeviceType));
                }
            }

            // Clear the values if we don't have everything
            if (lastLocationTimeUtc == null || result.Latitude == null || result.Longitude == null)
            {
                _log.LogWarning($"Clearing event information due to missing data. Lat: {result.Latitude}, Lon: {result.Longitude}, Time: {result.LocationLastUpdatedUtc}");
                result.LocationLastUpdatedUtc = null;
                result.Latitude  = null;
                result.Longitude = null;
            }
            else
            {
                result.LocationLastUpdatedUtc = lastLocationTimeUtc;
            }

            return(result);
        }