/// <summary>
 /// Initializes a new instance of the <see cref="FeedProcessor"/> class.
 /// </summary>
 /// <param name="api">The <see cref="GeotabDataOnlyPlanAPI"/> instance to use.</param>
 /// <param name="useFaultDataFeed">Indicates whether to use the <see cref="Geotab.Checkmate.ObjectModel.Engine.FaultData"/> feed.</param>
 /// <param name="useStatusDataFeed">Indicates whether to use the <see cref="Geotab.Checkmate.ObjectModel.Engine.StatusData"/> feed.</param>
 public FeedProcessor(GeotabDataOnlyPlanAPI api, bool useFaultDataFeed, bool useStatusDataFeed)
 {
     this.api           = api;
     _                  = api.AuthenticateAsync();
     controllerCache    = new Dictionary <Id, Controller>();
     deviceCache        = new Dictionary <Id, Device>();
     diagnosticCache    = new Dictionary <Id, Diagnostic>();
     failureModeCache   = new Dictionary <Id, FailureMode>();
     unitOfMeasureCache = new Dictionary <Id, UnitOfMeasure>();
     UseFaultDataFeed   = useFaultDataFeed;
     UseStatusDataFeed  = useStatusDataFeed;
 }
Exemple #2
0
        public static async Task Run(GeotabDataOnlyPlanAPI api)
        {
            ConsoleUtility.LogExampleStarted(typeof(AuthenticateAsyncExample).Name);

            try
            {
                string server   = ConsoleUtility.GetUserInput("server").ToLower();
                string database = ConsoleUtility.GetUserInput("database").ToLower();
                string username = ConsoleUtility.GetUserInput("username");
                string password = ConsoleUtility.GetUserInputMasked("password");
                await api.AuthenticateAsync(server, database, username, password);
            }
            catch (Exception ex)
            {
                ConsoleUtility.LogError(ex);
            }

            ConsoleUtility.LogExampleFinished(typeof(AuthenticateAsyncExample).Name);
        }
        static async Task Main()
        {
            IList <ConfigItem> configItems;
            bool           trackSpecificVehicles = false;
            IList <Device> devicesToTrack        = null;

            Common.FeedStartOption feedStartOption         = Common.FeedStartOption.CurrentTime;
            DateTime              feedStartSpecificTimeUTC = DateTime.MinValue;
            int                   feedIntervalSeconds      = 60;
            IList <Diagnostic>    diagnosticsToTrack       = null;
            string                parentOutputFolder;
            string                outputFolder;
            int                   maximumFileSizeBytes = 1024000;
            GeotabDataOnlyPlanAPI api;

            string username = "";
            string password = "";
            string server   = "my.geotab.com";
            string database = "";
            string title    = "";

            try
            {
                // Set title.
                title         = AppDomain.CurrentDomain.FriendlyName.Replace(".", " ");
                Console.Title = title;
                ConsoleUtility.LogUtilityStartup(title);

                // Request MyGeotab credentials and database name.
                server   = ConsoleUtility.GetUserInput($"MyGeotab server");
                database = ConsoleUtility.GetUserInput($"Database to run examples against.").ToLower();
                username = ConsoleUtility.GetUserInput($"MyGeotab username");
                password = ConsoleUtility.GetUserInputMasked($"MyGeotab password");

                // Create Geotab Data-Only Plan API instance and authenticate.
                api = new GeotabDataOnlyPlanAPI(server, database, username, password);
                ConsoleUtility.LogInfoStart("Authenticating...");
                await api.AuthenticateAsync();

                ConsoleUtility.LogOk();

                // Load configuration information from the config file.
                configItems = GetConfigItems("configuration");

                // Validate output folder and create subfolder for output files.
                parentOutputFolder = configItems.Where(configItem => configItem.Key == ArgNameOutputFolder).FirstOrDefault().Value;
                if (!Directory.Exists(parentOutputFolder))
                {
                    throw new ArgumentException($"The specified output folder, '{parentOutputFolder}', does not exist.");
                }
                DirectoryInfo directoryInfo = new DirectoryInfo(parentOutputFolder);
                string        subfolderName = $"Output_{DateTime.Now.ToString("yyyyMMdd_HHmmss")}";
                directoryInfo.CreateSubdirectory(subfolderName);
                outputFolder = Path.Combine(directoryInfo.FullName, subfolderName);

                // Validate and set maximum file size.
                string maxFileSizeMBString = configItems.Where(configItem => configItem.Key == ArgNameMaximumFileSizeMB).FirstOrDefault().Value;
                if (int.TryParse(maxFileSizeMBString, out int maxFileSizeMB))
                {
                    if (maxFileSizeMB > 0)
                    {
                        maximumFileSizeBytes = maxFileSizeMB * Common.MegabyteToByteMultiplier;
                    }
                }

                // Get the vehicle tracking option.
                string vehicleTrackingOption = configItems.Where(configItem => configItem.Key == ArgNameVehicleTrackingOption).FirstOrDefault().Value;
                switch (vehicleTrackingOption)
                {
                case nameof(Common.VehicleTrackingOption.Reporting):
                    trackSpecificVehicles = false;
                    break;

                case nameof(Common.VehicleTrackingOption.Specific):
                    trackSpecificVehicles = true;
                    break;

                default:
                    break;
                }

                // If specific vehicles are to be tracked, validate the supplied list of device IDs against the current database.  Discard any supplied items that are not valid device IDs.  If no valid device IDs are supplied, switch back to tracking vehicles that are currently reporting data.
                if (trackSpecificVehicles == true)
                {
                    ConsoleUtility.LogInfo("Validating SpecificVehiclesToTrack...");
                    string   vehicleListSupplied = configItems.Where(configItem => configItem.Key == ArgNameSpecificVehiclesToTrack).FirstOrDefault().Value;
                    string[] vehicleList         = vehicleListSupplied.Split(",");
                    devicesToTrack = new List <Device>();
                    IList <Device> devices = await GetAllDevicesAsync(api);

                    for (int vehicleListIndex = 0; vehicleListIndex < vehicleList.Length; vehicleListIndex++)
                    {
                        string vehicleDeviceId = vehicleList[vehicleListIndex];
                        Device checkedDevice   = devices.Where(device => device.Id.ToString() == vehicleDeviceId).FirstOrDefault();
                        if (checkedDevice == null)
                        {
                            ConsoleUtility.LogListItem($"Note - The following is not a valid device Id", $"{vehicleDeviceId}", Common.ConsoleColorForUnchangedData, Common.ConsoleColorForErrors);
                            continue;
                        }
                        devicesToTrack.Add(checkedDevice);
                    }
                    if (devicesToTrack.Count == 0)
                    {
                        ConsoleUtility.LogWarning($"No valid device IDs have been entered. Switching to tracking of vehicles that are currently reporting data.");
                        trackSpecificVehicles = false;
                    }
                }

                // Get diagnostics to be tracked.
                ConsoleUtility.LogInfo("Validating DiagnosticsToTrack...");
                string   diagnosticListSupplied = configItems.Where(configItem => configItem.Key == ArgNameDiagnosticsToTrack).FirstOrDefault().Value;
                string[] diagnosticList         = diagnosticListSupplied.Split(",");
                diagnosticsToTrack = new List <Diagnostic>();
                IList <Diagnostic> diagnostics = await GetAllDiagnosticsAsync(api);

                for (int diagnosticListIndex = 0; diagnosticListIndex < diagnosticList.Length; diagnosticListIndex++)
                {
                    string     diagnosticId      = diagnosticList[diagnosticListIndex];
                    Diagnostic checkedDiagnostic = diagnostics.Where(diagnostic => diagnostic.Id.ToString() == diagnosticId).FirstOrDefault();
                    if (checkedDiagnostic == null)
                    {
                        ConsoleUtility.LogListItem($"Note - The following is not a valid diagnostic Id", $"{diagnosticId}", Common.ConsoleColorForUnchangedData, Common.ConsoleColorForErrors);
                        continue;
                    }
                    diagnosticsToTrack.Add(checkedDiagnostic);
                }
                if (diagnosticsToTrack.Count == 0)
                {
                    ConsoleUtility.LogWarning($"No valid diagnostic IDs have been entered. As such, no diagnostics will be tracked.");
                }

                // Get the feed start option.
                string feedStartOptionString = configItems.Where(configItem => configItem.Key == ArgNameFeedStartOption).FirstOrDefault().Value;
                switch (feedStartOptionString)
                {
                case nameof(Common.FeedStartOption.CurrentTime):
                    feedStartOption = Common.FeedStartOption.CurrentTime;
                    break;

                case nameof(Common.FeedStartOption.FeedResultToken):
                    feedStartOption = Common.FeedStartOption.FeedResultToken;
                    break;

                case nameof(Common.FeedStartOption.SpecificTime):
                    string feedStartSpecificTimeUTCString = configItems.Where(configItem => configItem.Key == ArgNameFeedStartSpecificTimeUTC).FirstOrDefault().Value;
                    if (DateTime.TryParse(feedStartSpecificTimeUTCString, null, System.Globalization.DateTimeStyles.RoundtripKind, out feedStartSpecificTimeUTC) == false)
                    {
                        ConsoleUtility.LogWarning($"The value of '{feedStartSpecificTimeUTCString}' specified for FeedStartSpecificTimeUTC is invalid. As such, the current date and time will be used instead.");
                        feedStartOption = Common.FeedStartOption.CurrentTime;
                    }
                    else
                    {
                        feedStartOption = Common.FeedStartOption.SpecificTime;
                    }
                    break;

                default:
                    break;
                }

                // Get the feed interval.
                string feedIntervalSecondsString = configItems.Where(configItem => configItem.Key == ArgNameFeedIntervalSeconds).FirstOrDefault().Value;
                if (int.TryParse(feedIntervalSecondsString, out int feedIntervalSecondsInt))
                {
                    if (feedIntervalSecondsInt < ShortestAllowedFeedIntervalSeconds)
                    {
                        ConsoleUtility.LogListItem($"Note - The specified FeedIntervalSeconds value of '{feedIntervalSecondsString}' is less then the shortest allowed value of '{ShortestAllowedFeedIntervalSeconds.ToString()}'.  FeedIntervalSeconds will be set to:", ShortestAllowedFeedIntervalSeconds.ToString(), Common.ConsoleColorForUnchangedData, Common.ConsoleColorForErrors);
                        feedIntervalSeconds = ShortestAllowedFeedIntervalSeconds;
                    }
                    else
                    {
                        feedIntervalSeconds = feedIntervalSecondsInt;
                    }
                }
                else
                {
                    ConsoleUtility.LogListItem($"Note - The specified FeedIntervalSeconds value of '{feedIntervalSecondsString}' is invalid.  FeedIntervalSeconds will be set to:", ShortestAllowedFeedIntervalSeconds.ToString(), Common.ConsoleColorForUnchangedData, Common.ConsoleColorForErrors);
                    feedIntervalSeconds = ShortestAllowedFeedIntervalSeconds;
                }

                // Instantiate a DatabaseWorker to start processing the data feeds.
                bool   continuous        = true;
                Worker worker            = new DatabaseWorker(username, password, database, server, parentOutputFolder, outputFolder, maximumFileSizeBytes, feedIntervalSeconds, feedStartOption, feedStartSpecificTimeUTC, trackSpecificVehicles, devicesToTrack, diagnosticsToTrack);
                var    cancellationToken = new CancellationTokenSource();
                Task   task = Task.Run(async() => await worker.DoWorkAsync(continuous), cancellationToken.Token);
                if (continuous && Console.ReadLine() != null)
                {
                    worker.RequestStop();
                    cancellationToken.Cancel();
                }
            }
            catch (Exception ex)
            {
                ConsoleUtility.LogError(ex);
            }
            finally
            {
                ConsoleUtility.LogUtilityShutdown(title);
                Console.ReadKey();
            }
        }
Exemple #4
0
        static async Task Main()
        {
            GeotabDataOnlyPlanAPI api;
            string username;
            string password;
            string title = "";

            string lastCreateDatabaseResult;
            string lastAddedDeviceServer         = "";
            string lastAddedDeviceDatabase       = "";
            string lastAddedDeviceId             = "";
            string lastAddedUserServer           = "";
            string lastAddedUserDatabase         = "";
            string lastAddedUserId               = "";
            string lastAddedDriverChangeServer   = "";
            string lastAddedDriverChangeDatabase = "";
            string lastAddedDriverChangeId       = "";

            try
            {
                // Set title.
                title         = AppDomain.CurrentDomain.FriendlyName.Replace(".", " ");
                Console.Title = title;
                ConsoleUtility.LogUtilityStartup(title);

                // Request MyGeotab credentials and database name.
                string server   = ConsoleUtility.GetUserInput($"MyGeotab server");
                string database = ConsoleUtility.GetUserInput($"Database to run examples against.").ToLower();
                username = ConsoleUtility.GetUserInput($"MyGeotab username");
                password = ConsoleUtility.GetUserInputMasked($"MyGeotab password");

                // Create Geotab Data-Only Plan API instance and authenticate.
                api = new GeotabDataOnlyPlanAPI(server, database, username, password);
                ConsoleUtility.LogInfoStart("Authenticating...");
                await api.AuthenticateAsync();

                ConsoleUtility.LogOk();

                bool exit = false;
                while (exit == false)
                {
                    // List the examples that the user may select from.
                    ConsoleUtility.LogExamplesMenuHeader();
                    IList <KeyValuePair <int, string> > listItems = new List <KeyValuePair <int, string> >();
                    string[] GeotabDataOnlyPlanAPIExamples        = Enum.GetNames(typeof(GeotabDataOnlyPlanAPIExample));
                    for (int GeotabDataOnlyPlanAPIExampleId = 0; GeotabDataOnlyPlanAPIExampleId < GeotabDataOnlyPlanAPIExamples.Length; GeotabDataOnlyPlanAPIExampleId++)
                    {
                        listItems.Add(new KeyValuePair <int, string>(GeotabDataOnlyPlanAPIExampleId, GeotabDataOnlyPlanAPIExamples[GeotabDataOnlyPlanAPIExampleId]));
                    }
                    ConsoleUtility.LogListItems(listItems, Common.ConsoleColorForListItemIds, Common.ConsoleColorForListItems);

                    // Get user to select which example to run.
                    bool exampleSelected = false;
                    while (!exampleSelected)
                    {
                        exampleSelected = true;
                        string input = ConsoleUtility.GetUserInput("number of the example to run (from the above list), or 'x' to quit.");

                        if (input == "x" || input == "X")
                        {
                            exit = true;
                            break;
                        }

                        if (int.TryParse(input, out int selection))
                        {
                            switch (selection)
                            {
                            case (int)GeotabDataOnlyPlanAPIExample.AddDeviceAsync:
                                lastAddedDeviceId = await AddDeviceAsyncExample.Run(api);

                                lastAddedDeviceServer   = server;
                                lastAddedDeviceDatabase = database;
                                break;

                            case (int)GeotabDataOnlyPlanAPIExample.AddDriverChangeAsync:
                                if (lastAddedDeviceDatabase == database && lastAddedDeviceId != "" && lastAddedUserDatabase == database && lastAddedUserId != "")
                                {
                                    lastAddedDriverChangeId = await AddDriverChangeAsyncExample.Run(api, lastAddedDeviceId, lastAddedUserId);

                                    lastAddedDriverChangeServer   = server;
                                    lastAddedDriverChangeDatabase = database;
                                }
                                else if (lastAddedDeviceId == "" || lastAddedUserId == "")
                                {
                                    ConsoleUtility.LogError($"The 'AddDeviceAsync' and 'AddUserAsync' examples must be run before the 'AddDriverChangeAsync' example can be run.");
                                }
                                else
                                {
                                    if (lastAddedDeviceDatabase != lastAddedUserDatabase)
                                    {
                                        ConsoleUtility.LogError($"The 'AddDeviceAsync' example was last run against the '{lastAddedDeviceDatabase}' database on the '{lastAddedDeviceServer}' server and added the device '{lastAddedDeviceId}'.  The 'AddUserAsync' example was last run against the '{lastAddedUserDatabase}' database on the '{lastAddedUserServer}' server and added the user '{lastAddedUserId}'.  The 'AddDeviceAsync' and 'AddUserAsync' examples must be run on the same database before the 'AddDriverChangeAsync' example can be run.");
                                    }
                                }
                                break;

                            case (int)GeotabDataOnlyPlanAPIExample.AddTextMessageAsync:
                                if (lastAddedDeviceDatabase == database && lastAddedDeviceId != "" && lastAddedUserDatabase == database && lastAddedUserId != "")
                                {
                                    await AddTextMessageAsyncExample.Run(api, lastAddedDeviceId, lastAddedUserId);
                                }
                                else if (lastAddedDeviceId == "" || lastAddedUserId == "")
                                {
                                    ConsoleUtility.LogError($"The 'AddDeviceAsync' and 'AddUserAsync' examples must be run before the 'AddTextMessageAsync' example can be run.");
                                }
                                else
                                {
                                    if (lastAddedDeviceDatabase != lastAddedUserDatabase)
                                    {
                                        ConsoleUtility.LogError($"The 'AddDeviceAsync' example was last run against the '{lastAddedDeviceDatabase}' database on the '{lastAddedDeviceServer}' server and added the device '{lastAddedDeviceId}'.  The 'AddUserAsync' example was last run against the '{lastAddedUserDatabase}' database on the '{lastAddedUserServer}' server and added the user '{lastAddedUserId}'.  The 'AddDeviceAsync' and 'AddUserAsync' examples must be run on the same database before the 'AddTextMessageAsync' example can be run.");
                                    }
                                }
                                break;

                            case (int)GeotabDataOnlyPlanAPIExample.AddUserAsync:
                                lastAddedUserId = await AddUserAsyncExample.Run(api);

                                lastAddedUserServer   = server;
                                lastAddedUserDatabase = database;
                                break;

                            case (int)GeotabDataOnlyPlanAPIExample.ArchiveDeviceAsync:
                                if (lastAddedDeviceDatabase == database && lastAddedDeviceId != "")
                                {
                                    await ArchiveDeviceAsyncExample.Run(api, lastAddedDeviceId);
                                }
                                else if (lastAddedDeviceId == "")
                                {
                                    ConsoleUtility.LogError($"The 'AddDeviceAsync' example must be run before the 'ArchiveDeviceAsync' example can be run.");
                                }
                                else if (lastAddedDeviceDatabase != database)
                                {
                                    ConsoleUtility.LogError($"The 'AddDeviceAsync' example was last run against the '{lastAddedDeviceDatabase}' database on the '{lastAddedDeviceServer}' server and added the device '{lastAddedDeviceId}'.  Please run the 'AuthenticateAsync' example to authenticate against the '{lastAddedDeviceDatabase}' database on the '{lastAddedDeviceServer}' server before running the 'ArchiveDeviceAsync' example.");
                                }
                                break;

                            case (int)GeotabDataOnlyPlanAPIExample.AuthenticateAsync:
                                await AuthenticateAsyncExample.Run(api);

                                database = api.Credentials.Database;
                                break;

                            case (int)GeotabDataOnlyPlanAPIExample.CreateDatabaseAsync:
                                lastCreateDatabaseResult = await CreateDatabaseAsyncExample.Run(api);

                                // Get the server and database information for the new database.
                                string[] serverAndDatabase = (lastCreateDatabaseResult).Split('/');
                                server   = serverAndDatabase.First();
                                database = serverAndDatabase.Last();
                                break;

                            case (int)GeotabDataOnlyPlanAPIExample.DatabaseExistsAsync:
                                await DatabaseExistsAsyncExample.Run(api);

                                break;

                            case (int)GeotabDataOnlyPlanAPIExample.GenerateCaptchaAsync:
                                await GenerateCaptchaAsyncExample.Run(api);

                                break;

                            case (int)GeotabDataOnlyPlanAPIExample.GetBinaryDataAsync:
                                await GetBinaryDataAsyncExample.Run(api);

                                break;

                            case (int)GeotabDataOnlyPlanAPIExample.GetControllersAsync:
                                await GetControllersAsyncExample.Run(api);

                                break;

                            case (int)GeotabDataOnlyPlanAPIExample.GetCountOfDeviceAsync:
                                await GetCountOfDeviceAsyncExample.Run(api);

                                break;

                            case (int)GeotabDataOnlyPlanAPIExample.GetCountOfUserAsync:
                                await GetCountOfUserAsyncExample.Run(api);

                                break;

                            case (int)GeotabDataOnlyPlanAPIExample.GetFailureModesAsync:
                                await GetFailureModesAsyncExample.Run(api);

                                break;

                            case (int)GeotabDataOnlyPlanAPIExample.GetFeedCustomDataAsync:
                                await GetFeedCustomDataAsyncExample.Run(api);

                                break;

                            case (int)GeotabDataOnlyPlanAPIExample.GetFeedDeviceAsyncExample:
                                await GetFeedDeviceAsyncExample.Run(api);

                                break;

                            case (int)GeotabDataOnlyPlanAPIExample.GetFeedDiagnosticAsyncExample:
                                await GetFeedDiagnosticAsyncExample.Run(api);

                                break;

                            case (int)GeotabDataOnlyPlanAPIExample.GetFeedDriverChangeAsyncExample:
                                await GetFeedDriverChangeAsyncExample.Run(api);

                                break;

                            case (int)GeotabDataOnlyPlanAPIExample.GetFeedFaultDataAsync:
                                await GetFeedFaultDataAsyncExample.Run(api);

                                break;

                            case (int)GeotabDataOnlyPlanAPIExample.GetFeedLogRecordAsync:
                                await GetFeedLogRecordAsyncExample.Run(api);

                                break;

                            case (int)GeotabDataOnlyPlanAPIExample.GetFeedIoxAddOnAsync:
                                await GetFeedIoxAddOnAsyncExample.Run(api);

                                break;

                            case (int)GeotabDataOnlyPlanAPIExample.GetFeedStatusDataAsync:
                                await GetFeedStatusDataAsyncExample.Run(api);

                                break;

                            case (int)GeotabDataOnlyPlanAPIExample.GetFeedTripAsync:
                                await GetFeedTripAsyncExample.Run(api);

                                break;

                            case (int)GeotabDataOnlyPlanAPIExample.GetFeedUserAsyncExample:
                                await GetFeedUserAsyncExample.Run(api);

                                break;

                            case (int)GeotabDataOnlyPlanAPIExample.GetFlashCodesAsync:
                                await GetFlashCodesAsyncExample.Run(api);

                                break;

                            case (int)GeotabDataOnlyPlanAPIExample.GetSourceAsync:
                                await GetSourceAsyncExample.Run(api);

                                break;

                            case (int)GeotabDataOnlyPlanAPIExample.GetSourcesAsync:
                                await GetSourcesAsyncExample.Run(api);

                                break;

                            case (int)GeotabDataOnlyPlanAPIExample.GetSystemTimeUtcAsync:
                                await GetSystemTimeUtcAsyncExample.Run(api);

                                break;

                            case (int)GeotabDataOnlyPlanAPIExample.GetTimeZonesAsync:
                                await GetTimeZonesAsyncExample.Run(api);

                                break;

                            case (int)GeotabDataOnlyPlanAPIExample.GetUnitOfMeasureAsync:
                                await GetUnitOfMeasureAsyncExample.Run(api);

                                break;

                            case (int)GeotabDataOnlyPlanAPIExample.GetUnitsOfMeasureAsync:
                                await GetUnitsOfMeasureAsyncExample.Run(api);

                                break;

                            case (int)GeotabDataOnlyPlanAPIExample.GetVersionAsync:
                                await GetVersionAsyncExample.Run(api);

                                break;

                            case (int)GeotabDataOnlyPlanAPIExample.GetVersionInformationAsync:
                                await GetVersionInformationAsyncExample.Run(api);

                                break;

                            case (int)GeotabDataOnlyPlanAPIExample.RemoveDriverChangeAsync:
                                if (lastAddedDriverChangeDatabase == database && lastAddedDriverChangeId != "")
                                {
                                    await RemoveDriverChangeAsyncExample.Run(api, lastAddedDriverChangeId);

                                    lastAddedDriverChangeDatabase = "";
                                    lastAddedDriverChangeId       = "";
                                }
                                else if (lastAddedDriverChangeId == "")
                                {
                                    ConsoleUtility.LogError($"The 'AddDriverChangeAsync' example must be run before the 'RemoveDriverChangeAsync' example can be run.");
                                }
                                else if (lastAddedDriverChangeDatabase != database)
                                {
                                    ConsoleUtility.LogError($"The 'AddDriverChangeAsync' example was last run against the '{lastAddedDriverChangeDatabase}' database on the '{lastAddedDriverChangeServer}' server and added the DriverChange '{lastAddedDriverChangeId}'.  Please run the 'AuthenticateAsync' example to authenticate against the '{lastAddedDriverChangeDatabase}' database on the '{lastAddedDriverChangeServer}' server before running the 'RemoveDriverChangeAsync' example.");
                                }
                                break;

                            case (int)GeotabDataOnlyPlanAPIExample.RemoveDeviceAsync:
                                if (lastAddedDeviceDatabase == database && lastAddedDeviceId != "")
                                {
                                    await RemoveDeviceAsyncExample.Run(api, lastAddedDeviceId);

                                    lastAddedDeviceDatabase = "";
                                    lastAddedDeviceId       = "";
                                }
                                else if (lastAddedDeviceId == "")
                                {
                                    ConsoleUtility.LogError($"The 'AddDeviceAsync' example must be run before the 'RemoveDeviceAsync' example can be run.");
                                }
                                else if (lastAddedDeviceDatabase != database)
                                {
                                    ConsoleUtility.LogError($"The 'AddDeviceAsync' example was last run against the '{lastAddedDeviceDatabase}' database on the '{lastAddedDeviceServer}' server and added the device '{lastAddedDeviceId}'.  Please run the 'AuthenticateAsync' example to authenticate against the '{lastAddedDeviceDatabase}' database on the '{lastAddedDeviceServer}' server before running the 'RemoveDeviceAsync' example.");
                                }
                                break;

                            case (int)GeotabDataOnlyPlanAPIExample.RemoveUserAsync:
                                if (lastAddedUserDatabase == database && lastAddedUserId != "")
                                {
                                    await RemoveUserAsyncExample.Run(api, lastAddedUserId);

                                    lastAddedUserDatabase = "";
                                    lastAddedUserId       = "";
                                }
                                else if (lastAddedUserId == "")
                                {
                                    ConsoleUtility.LogError($"The 'AddUserAsync' example must be run before the 'RemoveUserAsync' example can be run.");
                                }
                                else if (lastAddedUserDatabase != database)
                                {
                                    ConsoleUtility.LogError($"The 'AddUserAsync' example was last run against the '{lastAddedUserDatabase}' database on the '{lastAddedUserServer}' server and added the user '{lastAddedUserId}'.  Please run the 'AuthenticateAsync' example to authenticate against the '{lastAddedUserDatabase}' database on the '{lastAddedUserServer}' server before running the 'RemoveUserAsync' example.");
                                }
                                break;

                            case (int)GeotabDataOnlyPlanAPIExample.SetDeviceAsync:
                                if (lastAddedDeviceDatabase == database && lastAddedDeviceId != "")
                                {
                                    await SetDeviceAsyncExample.Run(api, lastAddedDeviceId);
                                }
                                else if (lastAddedDeviceId == "")
                                {
                                    ConsoleUtility.LogError($"The 'AddDeviceAsync' example must be run before the 'SetDeviceAsync' example can be run.");
                                }
                                else if (lastAddedDeviceDatabase != database)
                                {
                                    ConsoleUtility.LogError($"The 'AddDeviceAsync' example was last run against the '{lastAddedDeviceDatabase}' database on the '{lastAddedDeviceServer}' server and added the device '{lastAddedDeviceId}'.  Please run the 'AuthenticateAsync' example to authenticate against the '{lastAddedDeviceDatabase}' database on the '{lastAddedDeviceServer}' server before running the 'SetDeviceAsync' example.");
                                }
                                break;

                            case (int)GeotabDataOnlyPlanAPIExample.SetUserAsync:
                                if (lastAddedUserDatabase == database && lastAddedUserId != "")
                                {
                                    await SetUserAsyncExample.Run(api, lastAddedUserId);
                                }
                                else if (lastAddedUserId == "")
                                {
                                    ConsoleUtility.LogError($"The 'AddUserAsync' example must be run before the 'SetUserAsync' example can be run.");
                                }
                                else if (lastAddedUserDatabase != database)
                                {
                                    ConsoleUtility.LogError($"The 'AddUserAsync' example was last run against the '{lastAddedUserDatabase}' database on the '{lastAddedUserServer}' server and added the user '{lastAddedUserId}'.  Please run the 'AuthenticateAsync' example to authenticate against the '{lastAddedUserDatabase}' database on the '{lastAddedUserServer}' server before running the 'SetUserAsync' example.");
                                }
                                break;

                            default:
                                exampleSelected = false;
                                ConsoleUtility.LogError($"The value '{input}' is not valid.");
                                break;
                            }
                        }
                        else
                        {
                            exampleSelected = false;
                            ConsoleUtility.LogError($"The value '{input}' is not valid.");
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                ConsoleUtility.LogError(ex);
            }
            finally
            {
                ConsoleUtility.LogUtilityShutdown(title);
                _ = Console.ReadKey();
            }
        }
        /// <summary>
        /// IMPORTANT: This example should be used sparingly - only when a new database is actually required!
        /// </summary>
        /// <param name="api"></param>
        /// <returns></returns>
        public static async Task <string> Run(GeotabDataOnlyPlanAPI api)
        {
            ConsoleUtility.LogExampleStarted(typeof(CreateDatabaseAsyncExample).Name);

            string createDatabaseResult = "";

            try
            {
                // Confirm user wishes to proceed with database creation.
                ConsoleUtility.LogWarning("By proceeding, you will be requesting the creation of a new MyGeotab database.");
                string input = ConsoleUtility.GetUserInput("'y' to confirm you wish to create a new database, or 'n' to cancel.");
                if (input != "y")
                {
                    ConsoleUtility.LogInfo("Cancelled CreateDatabaseAsync example.");
                    return(createDatabaseResult);
                }

                // Re-authenticate against "my.geotab.com".
                ConsoleUtility.LogInfoStart("Reauthenticating against my.geotab.com...");
                await api.AuthenticateAsync("my.geotab.com", "", api.Credentials.UserName, api.Credentials.Password);

                ConsoleUtility.LogComplete();

                string database = "";

                // Generate a database name and ensure that it is not already used.
                bool databaseExists = true;
                while (databaseExists == true)
                {
                    database       = Guid.NewGuid().ToString().Replace("-", "");
                    databaseExists = await api.DatabaseExistsAsync(database);
                }

                ConsoleUtility.LogInfoStartMultiPart($"Creating database named '{database}'.", $"THIS MAY TAKE SEVERAL MINUTES...", Common.ConsoleColorForWarnings);

                // Set parameter values for CreateDatabaseAsync call.
                string username      = api.Credentials.UserName;
                string password      = api.Credentials.Password;
                string companyName   = "Customer XYZ Ltd.";
                string firstName     = "John";
                string lastName      = "Smith";
                string phoneNumber   = "+1 (555) 123-4567";
                string resellerName  = "Reseller 123 Inc.";
                int    fleetSize     = 1;
                bool   signUpForNews = false;
                string timeZoneId    = "America/Toronto";
                string comments      = "some comments";

                // Create database.
                createDatabaseResult = await api.CreateDatabaseAsync(database, username, password, companyName, firstName, lastName, phoneNumber, resellerName, fleetSize, signUpForNews, timeZoneId, comments);

                ConsoleUtility.LogComplete();

                // Get the server and database information for the new database.
                string[] serverAndDatabase = (createDatabaseResult).Split('/');
                string   server            = serverAndDatabase.First();
                string   createdDatabase   = serverAndDatabase.Last();
                ConsoleUtility.LogInfo($"Created database '{createdDatabase}' on server '{server}'.");

                // Authenticate against the new database so that additional api calls (the 'Add', 'Set' and 'Remove' ones in particular) can be executed.
                ConsoleUtility.LogInfoStart($"Authenticating against '{createdDatabase}' database...");
                await api.AuthenticateAsync(server, createdDatabase, api.Credentials.UserName, api.Credentials.Password);

                ConsoleUtility.LogComplete();
            }
            catch (Exception ex)
            {
                ConsoleUtility.LogError(ex);
            }

            ConsoleUtility.LogExampleFinished(typeof(CreateDatabaseAsyncExample).Name);
            return(createDatabaseResult);
        }