public async Task UpdateVehicleListAsync() { this.IsBusy = true; try { if (!_reachability.IsConnected()) { _toast.Show("No internet connection!"); } else { var vehicleViews = await _gatewayService.GetVehicleViewsAsync(); var vehicleViewVehicles = new Dictionary <string, IEnumerable <Models.BaseVehicle> >(vehicleViews.Count()); foreach (var vehicleView in vehicleViews) { vehicleViewVehicles.Add(vehicleView.Title, await _gatewayService.GetVehiclesAsync(vehicleView.Title)); } var vehiclesAndTrailers = vehicleViewVehicles.SelectMany(vvv => vvv.Value).DistinctBy(v => v.ID); var vehicles = vehiclesAndTrailers.Where(bv => !bv.IsTrailer).Select(bv => new Models.Vehicle(bv)); if (vehicles != null) { await _vehicleRepository.DeleteAllAsync(); try { await _vehicleRepository.InsertAsync(vehicles); } catch (Exception ex) { MvxTrace.Error("\"{0}\" in {1}.{2}\n{3}", ex.Message, "VehicleRepository", "InsertAsync", ex.StackTrace); throw; } Vehicles = _originalVehicleList = await _vehicleRepository.GetAllAsync(); //Recalls the filter text if there is text in the search field. if (VehicleSearchText != null) { this.FilterList(); } } } await UpdateSafetyProfilesAsync(); } finally { this.IsBusy = false; } }
public async Task UpdateInstructionsListAsync() { if (!_reachability.IsConnected()) { _toast.Show("No internet connection!"); } else { // Force a poll for instructions await _gatewayPollingService.PollForInstructionsAsync(); } }
public async Task EnterCodeAsync() { if (string.IsNullOrWhiteSpace(this.CustomerCode)) { //TODO: probably should additionally implement presentation layer required field validation so we don't even get this far. await _userInteraction.AlertAsync("To register this device, submit a customer code"); return; } if (!_reachability.IsConnected()) { await _userInteraction.AlertAsync("To set-up this device, a connection to the internet is required"); } else { bool success = false; ProgressTitle = _progressTitleForCustomerCode; ProgressMessage = _progressMessageForCustomerCode; this.IsBusy = true; try { success = await this.SetupDeviceAsync(); } catch (Exception ex) { MvxTrace.Warning("Exception while setting up device: {0} at {1}", ex.Message, ex.StackTrace); success = false; _errorMessage = _unexpectedErrorMessage; } finally { this.IsBusy = false; } if (success) { ProgressTitle = _progressTitleForCheckIn; ProgressMessage = _progressMessageForCheckIn; IsBusy = true; await _navigationService.MoveToNextAsync(); IsBusy = false; } else { await _userInteraction.AlertAsync(_errorMessage); } } }
public async Task <AuthenticationResult> AuthenticateAsync(string passcode) { Mvx.Trace("Looking up passcode in local repository"); var driver = await GetMatchingDriverAsync(passcode); // driver not in local DB, update from BlueSphere (if we can) if (driver == null && _reachability.IsConnected()) { Mvx.Trace("Driver not found - refreshing driver list from Gateway"); await UpdateDriversAsync(); Mvx.Trace("Driver list updated - looking up passcode in local repository again"); driver = await GetMatchingDriverAsync(passcode); } // the passcode doesn't match any driver we know about if (driver == null) { return new AuthenticationResult { Success = false, AuthenticationFailedMessage = "The driver passcode you submitted doesn't exist, check the passcode and try again." } } ; // check if driver is licensed if (await IsLicensedAsync(driver)) { return new AuthenticationResult { Success = true, AuthenticationFailedMessage = null, Driver = driver } } ; else { return new AuthenticationResult { Success = false, AuthenticationFailedMessage = "Request for user license failed. Please contact Proteo for licensing queries." } }; }
/// <summary> /// This method uploads the database to the FTP server under the Android Device ID /// </summary> /// <param name="databasePath">The locations of the mySql Database</param> public async Task <bool> UploadDiagnosticsAsync(string databasePath) { if (!_reachability.IsConnected()) { return(false); } var config = await _repositories.ConfigRepository.GetAsync(); if (config == null || string.IsNullOrWhiteSpace(config.FtpUrl) || string.IsNullOrWhiteSpace(config.FtpUsername) || string.IsNullOrWhiteSpace(config.FtpPassword)) { await Mvx.Resolve <ICustomUserInteraction>().AlertAsync("Your FTP credentials have not been set up, you cannot upload support data until they have been set up."); return(false); } bool success = false; LogMessage exceptionMsg = null; try { var uriString = string.Format("{0}/{1}/{2}", config.FtpUrl, _deviceInfo.AndroidId, Path.GetFileName(databasePath)); var uri = new Uri(uriString); success = await _upload.UploadFileAsync(uri, config.FtpUsername, config.FtpPassword, databasePath); } catch (Exception ex) { exceptionMsg = _loggingService.GetExceptionLogMessage(ex); } if (exceptionMsg != null) { await _loggingService.LogEventAsync(exceptionMsg); } return(success); }
public async Task UploadDiagnosticsAsync() { if (!_reachability.IsConnected()) { await _userInteraction.AlertAsync("You need a connection to the internet to submit diagnostics."); } else { bool success = false; this.IsBusy = true; try { success = await _diagnosticsService.UploadDiagnosticsAsync(_dataService.DatabasePath); } catch (Exception) { success = false; } finally { this.IsBusy = false; } if (success) { await _userInteraction.AlertAsync("Support diagnostic information uploaded successfully.", null, "Upload Complete"); await _navigationService.MoveToNextAsync(); } else { await _userInteraction.AlertAsync(_unexpectedErrorMessage); } } }
public async Task PollForInstructionsAsync() { try { if (!_reachability.IsConnected()) { return; } using (await _lock.LockAsync()) { var data = await _repositories.ApplicationRepository.GetAllAsync(); var applicationProfile = data.FirstOrDefault(); if (applicationProfile != null) { _dataRetention = applicationProfile.DataRetention; _dataSpan = applicationProfile.DataSpan; } } Mvx.Trace("Begin Polling For Instructions"); string exceptionMsg = null; try { if (!_dataRetention.HasValue || !_dataSpan.HasValue) { var applicationProfile = await _repositories.ApplicationRepository.GetAsync(); _dataRetention = applicationProfile.DataRetention; _dataSpan = applicationProfile.DataSpan; } var instructionNotificationsToPublish = new Dictionary <Guid, Messages.GatewayInstructionNotificationMessage.NotificationCommand>(); // Remove any existing instructions that fall before the data retention period Mvx.Trace("Removing obsolete instructions."); var obsoleteInstructions = await _repositories.MobileDataRepository.GetObsoleteInstructionsAsync(_dataRetention.Value); Mvx.Trace("{0} obsolete instructions to remove.", obsoleteInstructions.Any() ? obsoleteInstructions.Count().ToString() : "No"); foreach (var instruction in obsoleteInstructions) { await _repositories.MobileDataRepository.DeleteAsync(instruction); instructionNotificationsToPublish[instruction.ID] = Messages.GatewayInstructionNotificationMessage.NotificationCommand.Delete; } // Call to BlueSphere to check for instructions var instructions = await _gatewayService.GetDriverInstructionsAsync( _infoService.CurrentVehicleRegistration, _infoService.CurrentDriverID.Value, DateTime.Today.AddDays(-_dataRetention.Value), DateTime.Today.AddDays(_dataSpan.Value)); // Check if we have anything in the response if (!instructions.Any()) { Mvx.Trace("No instructions were available."); } else { Mvx.Trace(string.Format("Successfully pulled {0} instructions.", instructions.Count())); var currentViewModel = _customPresenter.CurrentFragmentViewModel as BaseFragmentViewModel; var manifestInstructionVMsForNotification = new List <ManifestInstructionViewModel>(instructions.Count()); // We have a response so check what we need to do (Save/Update/Delete) foreach (var instruction in instructions) { var popupNotifyInstruction = false; Mvx.Trace("started processing instruction." + instruction.ID); instruction.VehicleId = _infoService.CurrentVehicleID.Value; switch (instruction.SyncState) { case SyncState.Add: Mvx.Trace("started adding instruction." + instruction.ID); var instructionToAdd = await _repositories.MobileDataRepository.GetByIDAsync(instruction.ID); if (instructionToAdd == null) { try { await _repositories.MobileDataRepository.InsertAsync(instruction); } catch (Exception ex) { MvxTrace.Error("\"{0}\" in {1}.{2}\n{3}", ex.Message, "MobileDataRepository", "InsertAsync", ex.StackTrace); throw; } popupNotifyInstruction = true; } Mvx.Trace("completed adding instruction." + instruction.ID); instructionNotificationsToPublish[instruction.ID] = Messages.GatewayInstructionNotificationMessage.NotificationCommand.Add; break; case SyncState.Update: Mvx.Trace("started updating instruction." + instruction.ID); var instructionToUpdate = await _repositories.MobileDataRepository.GetByIDAsync(instruction.ID); if (instructionToUpdate != null) { var progress = instructionToUpdate.ProgressState; await _repositories.MobileDataRepository.DeleteAsync(instructionToUpdate); instruction.ProgressState = progress; instruction.LatestDataChunkSequence = instructionToUpdate.LatestDataChunkSequence; } try { await _repositories.MobileDataRepository.InsertAsync(instruction); } catch (Exception ex) { MvxTrace.Error("\"{0}\" in {1}.{2}\n{3}", ex.Message, "MobileDataRepository", "InsertAsync", ex.StackTrace); throw; } popupNotifyInstruction = true; Mvx.Trace("completed updating instruction." + instruction.ID); instructionNotificationsToPublish[instruction.ID] = Messages.GatewayInstructionNotificationMessage.NotificationCommand.Update; break; case SyncState.Delete: Mvx.Trace("started deleting instruction." + instruction.ID); var oldInstruction = await _repositories.MobileDataRepository.GetByIDAsync(instruction.ID); if (oldInstruction != null) { await _repositories.MobileDataRepository.DeleteAsync(oldInstruction); if (oldInstruction.ProgressState != InstructionProgress.Complete) { popupNotifyInstruction = true; } } Mvx.Trace("completed deleting instruction." + instruction.ID); instructionNotificationsToPublish[instruction.ID] = Messages.GatewayInstructionNotificationMessage.NotificationCommand.Delete; break; } if (popupNotifyInstruction) { manifestInstructionVMsForNotification.Add(new ManifestInstructionViewModel(currentViewModel, instruction)); } } Mvx.Trace("Successfully inserted/updated/deleted instructions in repository."); //Acknowledge that they are on the Device (Not however acknowledged by the driver) await this.AcknowledgeInstructionsAsync(instructions); Mvx.Trace("Successfully sent device acknowledgement."); if (manifestInstructionVMsForNotification.Any()) { var notifiedInstructionVMs = await Mvx.Resolve <ICustomUserInteraction>().PopUpInstructionNotificationAsync( manifestInstructionVMsForNotification, title: "Manifest Update", okButton: "Acknowledge"); await this.SendReadChunksAsync(notifiedInstructionVMs); } if (instructionNotificationsToPublish.Any()) { _messenger.Publish(new Messages.GatewayInstructionNotificationMessage(this, instructionNotificationsToPublish)); } } } catch (Exception ex) { // catch and log the error, but this will not acknowledge the message so we can try again exceptionMsg = ex.Message; } if (exceptionMsg != null) { await _loggingService.LogEventAsync("Gateway Polling Processing Failed", LogType.Error, exceptionMsg); } } catch (Exception ex) { // if there is an error here, then just continue as this is probably related to a connection issue MvxTrace.Warning("Failed to poll for instructions: {0} at {1}", ex.Message, ex.StackTrace); } }
/// <summary> /// This method sends photos and comments to bluesphere, if the sender is on an /// instruction page then the instruction will be associated with the photos /// </summary> /// <param name="comment">The comment for the photos</param> /// <param name="photos">The collection of photos to be sent up</param> public async Task SendPhotoAndCommentAsync(string comment, List <Image> photos, Guid driverID, string driverDisplayName, IEnumerable <MobileData> mobileDatas) { if (!_reachability.IsConnected()) { return; } Mvx.Resolve <IToast>().Show("Now uploading images"); Encoding encoding = Encoding.UTF8; int uploadedCount = 0; var config = await _repositories.ConfigRepository.GetAsync(); if (config == null && string.IsNullOrWhiteSpace(config.HEUrl)) { await Mvx.Resolve <ICustomUserInteraction>().AlertAsync("Your HE Url has not been setup, you cannot upload images unless it has been setup."); return; } UploadCameraImageObject imageUpload = new UploadCameraImageObject(); imageUpload.Smp = _gpsService.GetSmpData(Enums.ReportReason.Comment); imageUpload.ID = Guid.NewGuid(); imageUpload.DriverTitle = driverDisplayName; imageUpload.DriverId = driverID; imageUpload.Pictures = photos; imageUpload.Comment = comment; imageUpload.DateTimeOfUpload = DateTime.Now; //If the user is not on the manifest screen they should be on an instruction page if (mobileDatas != null) { imageUpload.MobileApplicationIDs = mobileDatas.Select(md => md.ID).ToList(); imageUpload.OrderIDs = string.Join(",", mobileDatas.SelectMany(md => md.Order.Items.Select(i => i.ItemIdFormatted))); } foreach (var image in imageUpload.Pictures) { var postParameters = new Dictionary <string, string>(); postParameters.Add("filename", image.Filename); postParameters.Add("fileformat", "jpg"); postParameters.Add("MwfInternalId", image.ID.ToString()); postParameters.Add("DriverName", imageUpload.DriverTitle); postParameters.Add("PhotoComment", string.IsNullOrEmpty(imageUpload.Comment) ? string.Empty : imageUpload.Comment); postParameters.Add("PhotoDateTime", imageUpload.DateTimeOfUpload.ToString("o")); postParameters.Add("Latitude", (_gpsService.GetLatitude() ?? 0d).ToString()); postParameters.Add("Longitude", (_gpsService.GetLongitude() ?? 0d).ToString()); postParameters.Add("MobileApplicationDataIds", (imageUpload.MobileApplicationIDs == null) ? string.Empty : string.Join(",", imageUpload.MobileApplicationIDs.Select(x => x.ToString()))); postParameters.Add("HEOrderIds", string.IsNullOrWhiteSpace(imageUpload.OrderIDs) ? string.Empty : imageUpload.OrderIDs.ToString()); Uri postUrl = new Uri(string.Format("{0}/Mwf/ReceiveMwfPhoto.aspx", config.HEUrl)); using (var request = new HttpRequestMessage(HttpMethod.Post, postUrl.AbsoluteUri)) using (var fileContent = new ByteArrayContent(image.Bytes)) { var formContent = new MultipartFormDataContent(); foreach (var postParameter in postParameters) { formContent.Add(new StringContent(postParameter.Value), postParameter.Key); } fileContent.Headers.ContentDisposition = new System.Net.Http.Headers.ContentDispositionHeaderValue("attachment") { FileName = image.Filename, }; formContent.Add(fileContent); request.Content = formContent; try { var response = await _httpService.SendAsyncPlainResponse <HttpResponseMessage>(request); if (response.StatusCode == HttpStatusCode.OK) { await _loggingService.LogEventAsync("Image sent successfully.", Enums.LogType.Info); uploadedCount++; } else { await _loggingService.LogEventAsync(string.Format("Image failed to send, Status Code: {0}.", response.StatusCode), Enums.LogType.Error); } } catch (Exception ex) { throw; } } } if (uploadedCount != imageUpload.Pictures.Count) { await Mvx.Resolve <ICustomUserInteraction>().AlertAsync(string.Format("Only {0} of {1} were uploaded successful.", uploadedCount, imageUpload.Pictures.Count), title: "Upload Failed"); } else { Mvx.Resolve <IToast>().Show("Successfully uploaded images"); } }
public async Task UploadLoggedEventsAsync() { if (_isSubmitting) { return; } _isSubmitting = true; try { var events = await _loggedRepository.GetAllAsync(); if (events != null && events.Count() > 0) { events = events.OrderBy(e => e.LogDateTime); } if (events != null && events.Any()) { if (!_reachability.IsConnected()) { return; } var deviceIdentifier = _deviceInfo.GetDeviceIdentifier(); foreach (var e in events) { int messageLength = e.Message.Length; var deviceMessage = new DeviceLogMessage { Message = e.Message.Substring(0, Math.Min(messageLength, MAX_MESSAGE_LENGTH)), LogDateTime = e.LogDateTime, DeviceIdentifier = deviceIdentifier }; var isException = false; try { var response = await _gatewayService.PostLogMessageAsync(deviceMessage); isException = !response.Succeeded; } catch { isException = true; } if (isException) { await this.HandleLoggingFailureAsync(e, events.ToList()); } await _loggedRepository.DeleteAsync(e); } } } finally { _isSubmitting = false; } }
public async Task UpdateTrailerListAsync() { if (!_reachability.IsConnected()) { _toast.Show("No internet connection!"); return; } this.ProgressMessage = "Updating Trailers."; this.IsBusy = true; try { IDictionary <string, IEnumerable <Models.BaseVehicle> > vehicleViewVehicles; try { var vehicleViews = await _gatewayService.GetVehicleViewsAsync(); vehicleViewVehicles = new Dictionary <string, IEnumerable <Models.BaseVehicle> >(vehicleViews.Count()); foreach (var vehicleView in vehicleViews) { vehicleViewVehicles.Add(vehicleView.Title, await _gatewayService.GetVehiclesAsync(vehicleView.Title)); } } catch (TaskCanceledException) { // Although we have used reachability to determine that there is an available network connection, // it is still possible for the data fetch to fail which triggers a TaskCanceledException. _toast.Show("Connection failure!"); return; } var vehiclesAndTrailers = vehicleViewVehicles.SelectMany(vvv => vvv.Value).DistinctBy(v => v.ID); var trailers = vehiclesAndTrailers.Where(bv => bv.IsTrailer).Select(bv => new Models.Trailer(bv)); if (trailers != null) { await _repositories.TrailerRepository.DeleteAllAsync(); try { await _repositories.TrailerRepository.InsertAsync(trailers); } catch (Exception ex) { MvxTrace.Error("\"{0}\" in {1}.{2}\n{3}", ex.Message, "TrailerRepository", "InsertAsync", ex.StackTrace); throw; } await GetTrailerModelsAsync(); //Recalls the filter text if there is text in the search field. if (TrailerSearchText != null) { this.FilterList(); } } } finally { this.IsBusy = false; } await UpdateVehicleListAsync(); await UpdateSafetyProfilesAsync(); }