/// <summary>
        /// Updates the <see cref="Device"/> cache.  All new or changed <see cref="Device"/>s are obtained using a GetFeed() call.  Then, <see cref="Device"/>s that are already in the cache are replaced and any <see cref="Device"/>s not in the cache are added to the cache.
        /// </summary>
        /// <returns></returns>
        async Task UpdateDeviceCacheAsync()
        {
            ConsoleUtility.LogInfoStart("Updating Device cache...");

            // Populate the deviceCache, adding new items and updating existing items with their changed counterparts from the database.  Repeat execution of the GetFeedDeviceAsync method until no more results are returned to ensure that the cache is complete and up-to-date.
            FeedResult <Device> feedResult = null;
            bool keepGoing = true;

            while (keepGoing == true)
            {
                feedResult = await api.GetFeedDeviceAsync(lastDeviceFeedVersion);

                lastDeviceFeedVersion = feedResult.ToVersion;
                foreach (Device feedResultDevice in feedResult.Data)
                {
                    if (deviceCache.ContainsKey(feedResultDevice.Id))
                    {
                        deviceCache[feedResultDevice.Id] = feedResultDevice;
                    }
                    else
                    {
                        deviceCache.Add(feedResultDevice.Id, feedResultDevice);
                    }
                }
                if (feedResult.Data.Count < DefaultFeedResultsLimitDevice)
                {
                    keepGoing = false;
                }
            }

            ConsoleUtility.LogComplete(Common.ConsoleColorForUnchangedData);
            ConsoleUtility.LogListItem($"Device cache records added/updated:", feedResult.Data.Count.ToString(), Common.ConsoleColorForListItems, (feedResult.Data.Count > 0) ? Common.ConsoleColorForChangedData : Common.ConsoleColorForUnchangedData);
        }
        public static async Task Run(GeotabDataOnlyPlanAPI api)
        {
            ConsoleUtility.LogExampleStarted(typeof(GetFeedDeviceAsyncExample).Name);

            try
            {
                // Feed parameters.
                // See MyGeotab SDK <a href="https://geotab.github.io/sdk/software/guides/concepts/#result-limits">Result Limits</a> and <a href="https://geotab.github.io/sdk/software/api/reference/#M:Geotab.Checkmate.Database.DataStore.GetFeed1">GetFeed()</a> documentation for information about the feed result limit defined below.
                const int DefaultFeedResultsLimitDevice    = 5000;
                int       getFeedNumberOfCallsToMake       = 5;
                int       getFeedSecondsToWaitBetweenCalls = 5;
                long?     feedVersion = 0;

                List <Device>       deviceCache = new List <Device>();
                FeedResult <Device> feedResult;

                // Start by populating the deviceCache with a list of all devices.
                ConsoleUtility.LogListItem($"Population of deviceCache started.");
                bool isFirstCall = true;
                bool keepGoing   = true;
                while (keepGoing == true)
                {
                    feedResult = await api.GetFeedDeviceAsync(feedVersion);

                    feedVersion = feedResult.ToVersion;
                    ConsoleUtility.LogListItem("GetFeedDeviceAsync executed:");
                    ConsoleUtility.LogListItem("FeedResult ToVersion:", feedVersion.ToString(), Common.ConsoleColorForUnchangedData, Common.ConsoleColorForSuccess);
                    ConsoleUtility.LogListItem("FeedResult Records:", feedResult.Data.Count.ToString(), Common.ConsoleColorForUnchangedData, Common.ConsoleColorForSuccess);
                    if (isFirstCall == true)
                    {
                        deviceCache.AddRange(feedResult.Data);
                        isFirstCall = false;
                    }
                    else
                    {
                        // Add new items to the cache, or update existing items with their changed counterparts.
                        foreach (Device feedResultDevice in feedResult.Data)
                        {
                            Device cachedDeviceToUpdate = deviceCache.Where(device => device.Id == feedResultDevice.Id).FirstOrDefault();
                            if (cachedDeviceToUpdate == null)
                            {
                                deviceCache.Add(feedResultDevice);
                            }
                            else
                            {
                                var index = deviceCache.IndexOf(cachedDeviceToUpdate);
                                deviceCache[index] = feedResultDevice;
                            }
                        }
                    }
                    if (feedResult.Data.Count < DefaultFeedResultsLimitDevice)
                    {
                        keepGoing = false;
                    }
                }
                ConsoleUtility.LogListItem($"Population of deviceCache completed.");

                // Execute a GetFeed loop for the prescribed number of iterations, adding new items to the cache, or updating existing items with their changed counterparts.
                for (int getFeedCallNumber = 1; getFeedCallNumber < getFeedNumberOfCallsToMake + 1; getFeedCallNumber++)
                {
                    feedResult = await api.GetFeedDeviceAsync(feedVersion);

                    feedVersion = feedResult.ToVersion;
                    ConsoleUtility.LogListItem("GetFeedDeviceAsync executed.  Iteration:", getFeedCallNumber.ToString(), Common.ConsoleColorForUnchangedData, Common.ConsoleColorForSuccess);
                    ConsoleUtility.LogListItem("FeedResult ToVersion:", feedVersion.ToString(), Common.ConsoleColorForUnchangedData, Common.ConsoleColorForSuccess);
                    ConsoleUtility.LogListItem("FeedResult Records:", feedResult.Data.Count.ToString(), Common.ConsoleColorForUnchangedData, Common.ConsoleColorForSuccess);
                    // Add new items to the cache, or update existing items with their changed counterparts.
                    foreach (Device feedResultDevice in feedResult.Data)
                    {
                        Device cachedDeviceToUpdate = deviceCache.Where(device => device.Id == feedResultDevice.Id).FirstOrDefault();
                        if (cachedDeviceToUpdate == null)
                        {
                            deviceCache.Add(feedResultDevice);
                        }
                        else
                        {
                            var index = deviceCache.IndexOf(cachedDeviceToUpdate);
                            deviceCache[index] = feedResultDevice;
                        }
                    }
                    // Wait for the prescribed amount of time before making the next GetFeed call.
                    Thread.Sleep(getFeedSecondsToWaitBetweenCalls * 1000);
                }
            }
            catch (Exception ex)
            {
                ConsoleUtility.LogError(ex);
            }

            ConsoleUtility.LogExampleFinished(typeof(GetFeedDeviceAsyncExample).Name);
        }