/// <summary>
        /// Serializes a JSON file into an object list
        /// Ref: http://stackoverflow.com/questions/6115721/how-to-save-restore-serializable-object-to-from-file
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="fileName"></param>
        /// <returns></returns>
        public void SerializeJSONObject <T>(T serializableObject, string fileName)
        {
            if (serializableObject == null)
            {
                return;
            }

            try
            {
                string output = JsonConvert.SerializeObject(serializableObject);
                File.WriteAllText(fileName, output);
                //JsonSerializer serializer = new JsonSerializer();
                //using (StreamWriter sw = new StreamWriter(fileName))
                //{
                //    using (JsonWriter writer = new JsonTextWriter(sw))
                //    {
                //        writer.Formatting = Formatting.Indented;
                //        serializer.Serialize(writer, serializableObject);
                //        writer.Close();
                //    }
                //}
            }
            catch (Exception ex)
            {
                //Log exception here
                LogUpdateEventArgs args = new LogUpdateEventArgs();
                args.logMessage = String.Format("Exception serializing file: {0}.", fileName);
                OnLogUpdate(args);
            }
        }
Exemple #2
0
 void c_SSimulatorLogUpdate(object sender, LogUpdateEventArgs e)
 {
     this.Dispatcher.Invoke(() =>
     {
         runLogSS.AppendText(string.Format("{0}\n", e.logMessage));
     });
 }
Exemple #3
0
        //public event EventHandler<TaskUpdateEventArgs> TaskUpdate;
        protected virtual void OnLogUpdate(LogUpdateEventArgs e)
        {
            EventHandler <LogUpdateEventArgs> handler = LogUpdate;

            if (handler != null)
            {
                handler(this, e);
            }
        }
        /// <summary>
        /// Deserializes an json file into an object list
        /// Ref: http://stackoverflow.com/questions/6115721/how-to-save-restore-serializable-object-to-from-file
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="fileName"></param>
        /// <returns></returns>
        public T DeSerializeJSONObject <T>(string fileName)
        {
            if (string.IsNullOrEmpty(fileName))
            {
                return(default(T));
            }

            T objectOut = default(T);

            try
            {
                string jsonString = File.ReadAllText(fileName);
                objectOut = JsonConvert.DeserializeObject <T>(jsonString);//((T)JsonConvert.DeserializeObject(jsonString, typeof(T)));
            }
            catch (Exception ex)
            {
                //Log exception here
                LogUpdateEventArgs args = new LogUpdateEventArgs();
                args.logMessage = String.Format("Exception deserializing file: {0}.", fileName);
                OnLogUpdate(args);
            }
            return(objectOut);
        }
Exemple #5
0
        public int startLiveDownloadTask(DateTime pollingStart, DateTime pollingEnd, double pollingFrequency)
        {
            lasttimeTimeURLField = 0;
            int downloadState = 0;

            //NOTE: polling freq: 19s < bk freq: 60s < save freq: 3600s
            downloadedGPSXMLData_UNSAVED = new ConcurrentDictionary <Tuple <long, string>, Vehicle>(); //GPSTime & VehID as tuple index
            DateTime nextDownloadTime;                                                                 // = DateTime.Now.ToLocalTime().AddSeconds(pollingFrequency);
            DateTime nextBackupTime;                                                                   // = DateTime.Now.ToLocalTime().AddSeconds(bkSaveFreq);
            //DateTime nextSaveTime = DateTime.Now.ToLocalTime().AddSeconds(fileSaveFreq);
            DateTime nextSaveTime;                                                                     // = pollingStart.Date.AddSeconds(pollingStart.Hour * 3600 - 1 + fileSaveFreq);//save on the last second of the next hour
            long     lastLogUpdatedSave = 0;
            string   bkfilename         = "current-GPSXML-bk.xml";

            ////load last saved backup, if it is from within the last 5 minutes
            //if ((DateTime.Now.DateTimeToEpochTime() - File.GetLastWriteTime(bkfilename).DateTimeToEpochTime()) < (5 * 60))
            //{
            //    List<Vehicle> bkGPSPoints = new List<Vehicle>();
            //    bkGPSPoints = DeSerializeXMLObject<List<Vehicle>>(xmlGPSFolderPath + bkfilename);
            //    foreach (Vehicle aGPSPoint in bkGPSPoints)
            //    {
            //        downloadedGPSXMLData_UNSAVED.AddOrUpdate(new Tuple<long, string>(aGPSPoint.GPStime, aGPSPoint.Id), aGPSPoint, (k, v) => aGPSPoint);//replaces existing if it exists
            //    }
            //}

            if (pollingStart.DateTimeToEpochTime() >= DateTime.Now.ToLocalTime().DateTimeToEpochTime())//future download - put thread to sleep until start - proper state
            {
                //return pollingStart.DateTimeToEpochTime() - downloadStartTime.DateTimeToEpochTime();
                Thread.Sleep(Convert.ToInt32(1000 * (pollingStart.DateTimeToEpochTime() - DateTime.Now.ToLocalTime().DateTimeToEpochTime() - 1)));
                nextDownloadTime = pollingStart.AddSeconds(0);
                nextBackupTime   = pollingStart.AddSeconds(0);
                nextSaveTime     = pollingStart.Date.AddSeconds(pollingStart.Hour * 3600 - 1 + fileSaveFreq);                                                                                           //assume file save frequency is at the hour
            }
            else if ((pollingStart.DateTimeToEpochTime() <= DateTime.Now.ToLocalTime().DateTimeToEpochTime()) && (pollingEnd.DateTimeToEpochTime() > DateTime.Now.ToLocalTime().DateTimeToEpochTime())) //some missing downloads - start period is before download can take place
            {
                //polling reschedule message
                LogUpdateEventArgs args = new LogUpdateEventArgs();
                args.logMessage = String.Format("NextBus Polling to Start at: {0}.", DateTime.Now.ToLocalTime().Date.AddSeconds(DateTime.Now.ToLocalTime().Hour * 3600 + fileSaveFreq).DateTimeISO8601Format());
                OnLogUpdate(args);

                Thread.Sleep(Convert.ToInt32(1000 * (3600 - (DateTime.Now.ToLocalTime().Minute * 60 + DateTime.Now.ToLocalTime().Second - 1))));
                downloadState    = -1;
                nextDownloadTime = DateTime.Now.ToLocalTime();
                nextBackupTime   = DateTime.Now.ToLocalTime();
                nextSaveTime     = DateTime.Now.ToLocalTime().Date.AddSeconds(DateTime.Now.ToLocalTime().Hour * 3600 - 1 + fileSaveFreq);//assume file save frequency is at the hour
            }
            else //if (pollingEnd.DateTimeToEpochTime() <= DateTime.Now.ToLocalTime().DateTimeToEpochTime())//nothing to download - end period is before download can take place
            {
                nextDownloadTime = new DateTime();
                nextBackupTime   = new DateTime();
                nextSaveTime     = new DateTime();
                downloadState    = -2;
                return(downloadState);
            }

            //initial save message
            if (lastLogUpdatedSave != nextSaveTime.DateTimeToEpochTime())
            {
                lastLogUpdatedSave = nextSaveTime.DateTimeToEpochTime();
                LogUpdateEventArgs args = new LogUpdateEventArgs();
                args.logMessage = String.Format("NextBus Upcoming Save: {0}.", nextSaveTime.DateTimeISO8601Format());
                OnLogUpdate(args);
            }

            //download started after a proper wait - proper state, or start immediate if some data can be downloaded (state: -1)
            while (pollingEnd.DateTimeToEpochTime() >= DateTime.Now.ToLocalTime().DateTimeToEpochTime())
            {
                List <long> nextOpTime = new List <long>();
                nextOpTime.Add(nextDownloadTime.DateTimeToEpochTime());
                nextOpTime.Add(nextBackupTime.DateTimeToEpochTime());
                nextOpTime.Add(nextSaveTime.DateTimeToEpochTime());
                nextOpTime.Sort();
                if ((nextOpTime[0] > DateTime.Now.ToLocalTime().DateTimeToEpochTime()))
                {
                    if (lastLogUpdatedSave != nextSaveTime.DateTimeToEpochTime())
                    {
                        lastLogUpdatedSave = nextSaveTime.DateTimeToEpochTime();
                        LogUpdateEventArgs args = new LogUpdateEventArgs();
                        args.logMessage = String.Format("NextBus Upcoming Save: {0}.", nextSaveTime.DateTimeISO8601Format());
                        OnLogUpdate(args);
                    }

                    long sleepTime = nextOpTime[0] - DateTime.Now.ToLocalTime().DateTimeToEpochTime();
                    Thread.Sleep(Convert.ToInt32(1000 * sleepTime));//brief sleep in between operations
                }
                //this condition structure prioritize download to mem, then backup, then save
                if (nextDownloadTime.DateTimeToEpochTime() <= DateTime.Now.ToLocalTime().DateTimeToEpochTime())
                {
                    nextDownloadTime = nextDownloadTime.AddSeconds(pollingFrequency);
                    downloadCurrentGPSXMLFromWeb(pollingFrequency);
                    //List<Vehicle> newGPSPoints = downloadCurrentGPSXMLFromWeb(pollingFrequency);
                    //foreach (Vehicle aGPSPoint in newGPSPoints)
                    //{
                    //    downloadedGPSXMLData_UNSAVED.AddOrUpdate(new Tuple<long, string>(aGPSPoint.GPStime, aGPSPoint.Id), aGPSPoint, (k, v) => aGPSPoint);//replaces existing if it exists
                    //}
                }
                else if (nextBackupTime.DateTimeToEpochTime() <= DateTime.Now.ToLocalTime().DateTimeToEpochTime())
                {
                    nextBackupTime = nextBackupTime.AddSeconds(bkSaveFreq);
                    SSUtil.SerializeXMLObject(downloadedGPSXMLData_UNSAVED.Values.ToList(), xmlGPSFolderPath + bkfilename);
                }
                else if (nextSaveTime.DateTimeToEpochTime() <= DateTime.Now.ToLocalTime().DateTimeToEpochTime())
                {
                    if (downloadedGPSXMLData_UNSAVED.Values.Count > 0)//avoid saving empty file
                    {
                        string newfilename = string.Format(xmlGPSFilenameFormat, nextSaveTime.AddSeconds(-fileSaveFreq + 1).ToUniversalTime().DateTimeNamingFormat(), nextSaveTime.ToUniversalTime().DateTimeNamingFormat());
                        SSUtil.SerializeXMLObject(downloadedGPSXMLData_UNSAVED.Values.ToList(), xmlGPSFolderPath + newfilename);
                        downloadedGPSXMLData_UNSAVED.Clear();//clear mem
                    }
                    nextSaveTime = nextSaveTime.AddSeconds(fileSaveFreq);
                }
            }
            return(downloadState);
            //downloadState = -2;//no download has taken place, date out of range
            //downloadState = -1;//download completed with some error - some missing data
            //downloadState = 0;//download completed with no error
        }
Exemple #6
0
 private void _cronDaemon_OnLogUpdate(object sender, LogUpdateEventArgs e)
 {
     UpdateLogText(e.LogLine);
 }
        public int startLiveDownloadTask(DateTime pollingStart, DateTime pollingEnd, double pollingFrequency)
        {
            //fileSaveFreq must be 1 day, otherwise, needs to modify nextSaveTime
            int downloadState = 0;

            //NOTE: polling freq: 60s < bk freq: 120s < save freq: 3600s * 24 = 1 day
            downloadedINCIXMLData_UNSAVED = new ConcurrentDictionary <string, Closure>(); //INCITime & VehID as tuple index
            DateTime nextDownloadTime;                                                    // = DateTime.Now.ToLocalTime().AddSeconds(pollingFrequency);
            DateTime nextBackupTime;                                                      // = DateTime.Now.ToLocalTime().AddSeconds(bkSaveFreq);
            //DateTime nextSaveTime = DateTime.Now.ToLocalTime().AddSeconds(fileSaveFreq);
            DateTime nextSaveTime;                                                        // = pollingStart.Date.AddSeconds(pollingStart.Hour * 3600 - 1 + fileSaveFreq);//save on the last second of the next hour
            long     lastLogUpdatedSave = 0;
            string   bkfilename         = "current-RRXML-bk.xml";

            //load last saved backup, if it is from within the last 5 minutes
            if ((DateTime.Now.DateTimeToEpochTime() - File.GetLastWriteTime(bkfilename).DateTimeToEpochTime()) < (5 * 60))
            {
                List <Closure> bkINCIPoints = new List <Closure>();
                bkINCIPoints = SSUtil.DeSerializeXMLObject <List <Closure> >(xmlINCIFolderPath + bkfilename);
                foreach (Closure aINCIPoint in bkINCIPoints)
                {
                    downloadedINCIXMLData_UNSAVED.AddOrUpdate(aINCIPoint.Id, aINCIPoint, (k, v) => aINCIPoint);//replaces existing if it exists
                }
            }

            if (pollingStart.DateTimeToEpochTime() >= DateTime.Now.ToLocalTime().DateTimeToEpochTime())//future download - put thread to sleep until start - proper state
            {
                //return pollingStart.DateTimeToEpochTime() - downloadStartTime.DateTimeToEpochTime();
                Thread.Sleep(Convert.ToInt32(1000 * (pollingStart.DateTimeToEpochTime() - DateTime.Now.ToLocalTime().DateTimeToEpochTime() - 1)));
                nextDownloadTime = pollingStart.AddSeconds(0);
                nextBackupTime   = pollingStart.AddSeconds(0);
                nextSaveTime     = DateTime.Now.ToLocalTime().Date.AddSeconds(-1 + fileSaveFreq);                                                                                                       //asume save frequencies are in the scale of days, save at midnighht
            }
            else if ((pollingStart.DateTimeToEpochTime() <= DateTime.Now.ToLocalTime().DateTimeToEpochTime()) && (pollingEnd.DateTimeToEpochTime() > DateTime.Now.ToLocalTime().DateTimeToEpochTime())) //some missing downloads - start period is before download can take place
            {
                //download at next hour, catch whatever data can be retrived.
                //Thread.Sleep(Convert.ToInt32(1000 * (3600 - (DateTime.Now.ToLocalTime().Minute * 60 + DateTime.Now.ToLocalTime().Second) - 1)));
                downloadState    = -1;
                nextDownloadTime = DateTime.Now.ToLocalTime().AddSeconds(0);                      //no delay for download
                nextBackupTime   = DateTime.Now.ToLocalTime().AddSeconds(0);                      //no delay for backup
                nextSaveTime     = DateTime.Now.ToLocalTime().Date.AddSeconds(-1 + fileSaveFreq); //asume save frequencies are in the scale of days, save at midnighht
            }
            else //if (pollingEnd.DateTimeToEpochTime() <= DateTime.Now.ToLocalTime().DateTimeToEpochTime())//nothing to download - end period is before download can take place
            {
                nextDownloadTime = new DateTime();
                nextBackupTime   = new DateTime();
                nextSaveTime     = new DateTime();
                downloadState    = -2;
                return(downloadState);
            }

            //initial save message
            if (lastLogUpdatedSave != nextSaveTime.DateTimeToEpochTime())
            {
                lastLogUpdatedSave = nextSaveTime.DateTimeToEpochTime();
                LogUpdateEventArgs args = new LogUpdateEventArgs();
                args.logMessage = String.Format("Rd Closures Upcoming Save: {0}.", nextSaveTime.DateTimeISO8601Format());
                OnLogUpdate(args);
            }

            //download started after a proper wait - proper state, or start immediate if some data can be downloaded (state: -1)
            while (pollingEnd.DateTimeToEpochTime() >= DateTime.Now.ToLocalTime().DateTimeToEpochTime())
            {
                List <long> nextOpTime = new List <long>();
                nextOpTime.Add(nextDownloadTime.DateTimeToEpochTime());
                nextOpTime.Add(nextBackupTime.DateTimeToEpochTime());
                nextOpTime.Add(nextSaveTime.DateTimeToEpochTime());
                nextOpTime.Sort();
                if ((nextOpTime[0] > DateTime.Now.ToLocalTime().DateTimeToEpochTime()))
                {
                    if (lastLogUpdatedSave != nextSaveTime.DateTimeToEpochTime())
                    {
                        lastLogUpdatedSave = nextSaveTime.DateTimeToEpochTime();
                        LogUpdateEventArgs args = new LogUpdateEventArgs();
                        args.logMessage = String.Format("Rd Closures Upcoming Save: {0}.", nextSaveTime.DateTimeISO8601Format());
                        OnLogUpdate(args);
                    }

                    long sleepTime = nextOpTime[0] - DateTime.Now.ToLocalTime().DateTimeToEpochTime();
                    Thread.Sleep(Convert.ToInt32(1000 * sleepTime));//brief sleep in between operations
                }
                //this condition structure prioritize download to mem, then backup, then save
                if (nextDownloadTime.DateTimeToEpochTime() <= DateTime.Now.ToLocalTime().DateTimeToEpochTime())
                {
                    nextDownloadTime = nextDownloadTime.AddSeconds(pollingFrequency);
                    downloadCurrentINCIXMLFromWeb(pollingFrequency);
                    //List < Closure > newINCIPoints = downloadCurrentINCIXMLFromWeb(pollingFrequency);
                    //foreach (Closure aINCIPoint in downloadedINCIXML)
                    //{
                    //    downloadedINCIXMLData_UNSAVED.AddOrUpdate(aINCIPoint.Id, aINCIPoint, (k, v) => aINCIPoint);//replaces existing if it exists
                    //}
                }
                else if (nextBackupTime.DateTimeToEpochTime() <= DateTime.Now.ToLocalTime().DateTimeToEpochTime())
                {
                    nextBackupTime = nextBackupTime.AddSeconds(bkSaveFreq);
                    SSUtil.SerializeXMLObject(downloadedINCIXMLData_UNSAVED.Values.ToList(), xmlINCIFolderPath + bkfilename);
                }
                else if (nextSaveTime.DateTimeToEpochTime() <= DateTime.Now.ToLocalTime().DateTimeToEpochTime())
                {
                    if (downloadedINCIXMLData_UNSAVED.Values.Count > 0)//avoid saving empty file
                    {
                        string newfilename = string.Format(xmlINCIFilenameFormat, nextSaveTime.AddSeconds(-fileSaveFreq + 1).ToUniversalTime().DateTimeNamingFormat(), nextSaveTime.ToUniversalTime().DateTimeNamingFormat());
                        SSUtil.SerializeXMLObject(downloadedINCIXMLData_UNSAVED.Values.ToList(), xmlINCIFolderPath + newfilename);
                        downloadedINCIXMLData_UNSAVED.Clear();//clear mem
                    }
                    nextSaveTime = nextSaveTime.AddSeconds(fileSaveFreq);
                }
            }
            return(downloadState);
            //downloadState = -2;//no download has taken place, date out of range
            //downloadState = -1;//download completed with some error - some missing data
            //downloadState = 0;//download completed with no error
        }
        public int startLiveDownloadTask(DateTime pollingStart, DateTime pollingEnd, double pollingFrequency)
        {
            int downloadState = 0;

            //NOTE: polling freq: 60s < bk freq: 120s < save freq: 3600s * 24 = 1 day
            downloadedWeatherJSONData_UNSAVED         = new ConcurrentDictionary <Tuple <int, long>, List>(); //INCITime & VehID as tuple index
            downloadedForecastWeatherJSONData_UNSAVED = new ConcurrentDictionary <Tuple <int, long>, List>(); //INCITime & VehID as tuple index

            List <List> lastDownloadedData = new List <List>();                                               //check actual data downloaded - a package of last downloaded data
            long        currentServerDelay;
            //lastDownloadedData.list[1].dt
            DateTime currentServerDownloadTime;
            DateTime nextDownloadTime;                    // = DateTime.Now.ToLocalTime().AddSeconds(pollingFrequency);
            DateTime nextForecastDownloadTime;            // = DateTime.Now.ToLocalTime().AddSeconds(pollingFrequency);
            double   forecast_pollingFrequency = 10 * 60; //poll every hour
            DateTime nextBackupTime;                      // = DateTime.Now.ToLocalTime().AddSeconds(bkSaveFreq);
            //DateTime nextSaveTime = DateTime.Now.ToLocalTime().AddSeconds(fileSaveFreq);
            DateTime nextSaveTime;                        // = pollingStart.Date.AddSeconds(pollingStart.Hour * 3600 - 1 + fileSaveFreq);//save on the last second of the next hour - time stamp save
            DateTime nextActualSaveTime;                  // = pollingStart.Date.AddSeconds(pollingStart.Hour * 3600 - 1 + fileSaveFreq);//appropriate save time based on server delay!
            long     lastLogUpdatedSave = 0;
            string   bkfilename         = "current-WeatherJSON-bk.json";

            //load last saved backup, if it is from within the last 5 minutes
            if (File.Exists(jsonWeatherFolderPath + bkfilename) && File.Exists(jsonForecastWeatherFolderPath + bkfilename))
            {
                if ((DateTime.Now.DateTimeToEpochTime() - File.GetLastWriteTime(jsonWeatherFolderPath + bkfilename).DateTimeToEpochTime()) < (5 * 60))
                {
                    List <List> bkWeatherPoints = new List <List>();
                    bkWeatherPoints = DeSerializeJSONObject <List <List> >(jsonWeatherFolderPath + bkfilename);
                    foreach (List aWeatherPoint in bkWeatherPoints)
                    {
                        downloadedWeatherJSONData_UNSAVED.AddOrUpdate(new Tuple <int, long>(aWeatherPoint.id, aWeatherPoint.dt), aWeatherPoint, (k, v) => aWeatherPoint);//replaces existing if it exists
                    }
                    bkWeatherPoints = DeSerializeJSONObject <List <List> >(jsonForecastWeatherFolderPath + bkfilename);
                    foreach (List aWeatherPoint in bkWeatherPoints)
                    {
                        downloadedForecastWeatherJSONData_UNSAVED.AddOrUpdate(new Tuple <int, long>(aWeatherPoint.id, aWeatherPoint.dt), aWeatherPoint, (k, v) => aWeatherPoint);//replaces existing if it exists
                    }
                }
            }

            downloadCurrentWeatherJSONFromWeb();
            currentServerDownloadTime = downloadedWeatherJSONData_UNSAVED.Count == 0 ? DateTime.Now : SSUtil.EpochTimeToLocalDateTime(downloadedWeatherJSONData_UNSAVED.Values.Select(c => c.dt).ToList().Max());
            currentServerDelay        = DateTime.Now.ToLocalTime().DateTimeToEpochTime() - currentServerDownloadTime.DateTimeToEpochTime(); //in secs
            //server delay will be accounted for, in the next polling request --> a delay results in later start and later stop download time
            if (pollingStart.DateTimeToEpochTime() >= (DateTime.Now.ToLocalTime().DateTimeToEpochTime() - currentServerDelay))              //future download - put thread to sleep until start - proper state
            {
                while (pollingStart.DateTimeToEpochTime() >= (DateTime.Now.ToLocalTime().DateTimeToEpochTime() - currentServerDelay))
                {
                    //return pollingStart.DateTimeToEpochTime() - downloadStartTime.DateTimeToEpochTime();
                    Thread.Sleep(Convert.ToInt32(1000 * pollingFrequency));                                                                         //check delay at polling frequency (minute), until it is time for download

                    downloadCurrentWeatherJSONFromWeb();                                                                                            //lastDownloadedData =
                    currentServerDownloadTime = downloadedWeatherJSONData_UNSAVED.Count == 0 ? DateTime.Now : SSUtil.EpochTimeToLocalDateTime(downloadedWeatherJSONData_UNSAVED.Values.Select(c => c.dt).ToList().Max());
                    currentServerDelay        = DateTime.Now.ToLocalTime().DateTimeToEpochTime() - currentServerDownloadTime.DateTimeToEpochTime(); //in secs
                }

                //start late as per server delays
                nextDownloadTime         = pollingStart.AddSeconds(0 + currentServerDelay);
                nextForecastDownloadTime = pollingStart.AddSeconds(0);
                nextBackupTime           = pollingStart.AddSeconds(0);                                                                                                                                                                                //no delay for backup
                nextActualSaveTime       = pollingStart.Date.AddSeconds(-1 + fileSaveFreq + currentServerDelay);                                                                                                                                      //assume file save frequency is at the hour
                nextSaveTime             = DateTime.Now.ToLocalTime().Date.AddSeconds(-1 + fileSaveFreq);                                                                                                                                             //asume save frequencies are in the scale of days
            }
            else if ((pollingStart.DateTimeToEpochTime() <= (DateTime.Now.ToLocalTime().DateTimeToEpochTime() - currentServerDelay)) && (pollingEnd.DateTimeToEpochTime() > (DateTime.Now.ToLocalTime().DateTimeToEpochTime() - currentServerDelay))) //some missing downloads - start period is before download can take place
            {
                //start late as per server delays - save at the hour, polling appropriately
                downloadState            = -1;
                nextDownloadTime         = DateTime.Now.ToLocalTime().AddSeconds(0);                      //no delay for download
                nextForecastDownloadTime = DateTime.Now.ToLocalTime().AddSeconds(0);                      //no delay for download
                nextBackupTime           = DateTime.Now.ToLocalTime().AddSeconds(0);                      //no delay for backup
                nextSaveTime             = DateTime.Now.ToLocalTime().Date.AddSeconds(-1 + fileSaveFreq); //asume save frequencies are in the scale of days
                nextActualSaveTime       = nextSaveTime.AddSeconds(currentServerDelay);                   //assume file save frequency is at the hour
            }
            else //if (pollingEnd.DateTimeToEpochTime() <= DateTime.Now.ToLocalTime().DateTimeToEpochTime())//nothing to download - end period is before download can take place
            {
                downloadState = -2;
                return(downloadState);
            }

            //initial save message
            if (lastLogUpdatedSave != nextSaveTime.DateTimeToEpochTime())
            {
                lastLogUpdatedSave = nextSaveTime.DateTimeToEpochTime();
                LogUpdateEventArgs args = new LogUpdateEventArgs();
                args.logMessage = String.Format("Weather Upcoming Save: {0}.", nextSaveTime.DateTimeISO8601Format());
                OnLogUpdate(args);
            }

            //download started after a proper wait - proper state, or start immediate if some data can be downloaded (state: -1)
            while (pollingEnd.DateTimeToEpochTime() >= (DateTime.Now.ToLocalTime().DateTimeToEpochTime() - currentServerDelay))//delay completion of survey as per server delay
            {
                List <long> nextOpTime = new List <long>();
                nextOpTime.Add(nextDownloadTime.DateTimeToEpochTime());
                nextOpTime.Add(nextForecastDownloadTime.DateTimeToEpochTime());
                nextOpTime.Add(nextBackupTime.DateTimeToEpochTime());
                //nextOpTime.Add(nextSaveTime.DateTimeToEpochTime());
                nextOpTime.Add(nextActualSaveTime.DateTimeToEpochTime());
                nextOpTime.Sort();//ascending
                if ((nextOpTime[0] > DateTime.Now.ToLocalTime().DateTimeToEpochTime()))
                {
                    if (lastLogUpdatedSave != nextSaveTime.DateTimeToEpochTime())
                    {
                        lastLogUpdatedSave = nextSaveTime.DateTimeToEpochTime();
                        LogUpdateEventArgs args = new LogUpdateEventArgs();
                        args.logMessage = String.Format("Weather Upcoming Save: {0}.", nextSaveTime.DateTimeISO8601Format());
                        OnLogUpdate(args);
                    }

                    long sleepTime = nextOpTime[0] - DateTime.Now.ToLocalTime().DateTimeToEpochTime();
                    Thread.Sleep(Convert.ToInt32(1000 * sleepTime));//brief sleep in between operations
                }
                //this condition structure prioritize download to mem, then backup, then save
                //Download - current weather
                if (nextDownloadTime.DateTimeToEpochTime() <= DateTime.Now.ToLocalTime().DateTimeToEpochTime())
                {
                    nextDownloadTime = DateTime.Now.AddSeconds(pollingFrequency);                                                                //nextDownloadTime.AddSeconds(pollingFrequency);
                    downloadCurrentWeatherJSONFromWeb();                                                                                         //List<List> newWeatherPoints =
                    currentServerDownloadTime = downloadedWeatherJSONData_UNSAVED.Count == 0 ? DateTime.Now : SSUtil.EpochTimeToLocalDateTime(downloadedWeatherJSONData_UNSAVED.Values.Select(c => c.dt).ToList().Max());
                    if ((DateTime.Now.ToLocalTime().DateTimeToEpochTime() - currentServerDownloadTime.DateTimeToEpochTime()) > 0)                //data cannot be from the future
                    {
                        currentServerDelay = DateTime.Now.ToLocalTime().DateTimeToEpochTime() - currentServerDownloadTime.DateTimeToEpochTime(); //in secs
                    }
                    else
                    {
                        currentServerDelay = 0;
                    }
                    //update next save time based on server delay
                    nextActualSaveTime = nextSaveTime.AddSeconds(currentServerDelay);//approximated next actual save time
                }
                //Download - Forecast weather
                if (nextForecastDownloadTime.DateTimeToEpochTime() <= DateTime.Now.ToLocalTime().DateTimeToEpochTime())
                {
                    nextForecastDownloadTime = DateTime.Now.AddSeconds(forecast_pollingFrequency); //nextDownloadTime.AddSeconds(pollingFrequency);
                    downloadCurrentWeatherJSONFromWeb(true);                                       //List<List> newWeatherPoints =
                }
                //Backup
                if (nextBackupTime.DateTimeToEpochTime() <= DateTime.Now.ToLocalTime().DateTimeToEpochTime())
                {
                    nextBackupTime = DateTime.Now.Subtract(nextBackupTime).TotalSeconds > bkSaveFreq?DateTime.Now.AddSeconds(bkSaveFreq) : nextBackupTime.AddSeconds(bkSaveFreq);

                    SerializeJSONObject(downloadedWeatherJSONData_UNSAVED.Values.ToList(), jsonWeatherFolderPath + bkfilename);
                    SerializeJSONObject(downloadedForecastWeatherJSONData_UNSAVED.Values.ToList(), jsonForecastWeatherFolderPath + bkfilename);
                }
                //Save
                if (nextActualSaveTime.DateTimeToEpochTime() <= DateTime.Now.ToLocalTime().DateTimeToEpochTime())
                {
                    if (downloadedWeatherJSONData_UNSAVED.Values.Count > 0)//avoid saving empty file
                    {
                        string newfilename = string.Format(jsonWeatherFilenameFormat, nextSaveTime.AddSeconds(-fileSaveFreq + 1).ToUniversalTime().DateTimeNamingFormat(), nextSaveTime.ToUniversalTime().DateTimeNamingFormat());
                        SerializeJSONObject(downloadedWeatherJSONData_UNSAVED.Values.ToList(), jsonWeatherFolderPath + newfilename);
                        SerializeJSONObject(downloadedForecastWeatherJSONData_UNSAVED.Values.ToList(), jsonForecastWeatherFolderPath + newfilename);
                        downloadedWeatherJSONData_UNSAVED.Clear();                    //clear mem
                        downloadedForecastWeatherJSONData_UNSAVED.Clear();            //clear mem
                    }
                    nextSaveTime       = nextSaveTime.AddSeconds(fileSaveFreq);       //next save time stamp
                    nextActualSaveTime = nextSaveTime.AddSeconds(currentServerDelay); //approximated next actual save time
                }
            }
            //clear backupFiles
            return(downloadState);
            //downloadState = -2;//no download has taken place, date out of range
            //downloadState = -1;//download completed with some error - some missing data
            //downloadState = 0;//download completed with no error
        }