Пример #1
0
        private static IProcessor GetProcessor(CollarFile file, GetTelonicsParametersForArgosDatesResult parameters)
        {
            switch (file.Format)
            {
            case 'E':
            case 'F':
                switch (parameters.CollarModel)
                {
                case "Gen3":
                    return(GetGen3Processor(parameters));

                case "Gen4":
                    return(GetGen4Processor(parameters));

                case "GPS8000":
                    return(GetGps8000Processor(parameters));

                default:
                    throw new InvalidOperationException("Unsupported collar model '" + parameters.CollarModel +
                                                        "'. (supported models are Gen3, and Gen4)");
                }

            case 'G':
                return(new DebevekProcessor());

            default:
                throw new InvalidOperationException("Unsupported CollarFile Format '" + file.Format +
                                                    "'. (supported formats are E,F,G)");
            }
        }
Пример #2
0
        private static void ProcessDataLogFile(CollarFile file)
        {
            LogGeneralMessage(String.Format("Start local processing of file {0}", file.FileId));
            var databaseFunctions = new AnimalMovementFunctions();

            //FIXME: check that this is generic to all telonics processing and not just Argos files
            databaseFunctions.ArgosFile_ClearProcessingResults(file.FileId);

            var processor = new Gen4Processor(null);
            var lines     = processor.ProcessDataLog(file.Contents.ToArray());
            //Add a newline, so that it exactly matches the direct output from TDC
            var data       = Encoding.UTF8.GetBytes(String.Join(Environment.NewLine, lines) + Environment.NewLine);
            var filename   = Path.GetFileNameWithoutExtension(file.FileName) + "_" + DateTime.Now.ToString("yyyyMMdd") + ".csv";
            var fileLoader = new FileLoader(filename, data)
            {
                Project = file.Project,
                Owner   = file.ProjectInvestigator,
                Collar  = new Collar
                {
                    CollarManufacturer = file.CollarManufacturer,
                    CollarId           = file.CollarId
                },
                Status          = file.Status,
                ParentFileId    = file.FileId,
                AllowDuplicates = true
            };

            fileLoader.Load();
            LogGeneralMessage("Finished local processing of file");
        }
Пример #3
0
 private static bool ProcessOnServer(CollarFile file, ArgosPlatform platform = null)
 {
     if (NeedTelonicsSoftware(file) && !HaveAccessToTelonicsSoftware())
     {
         if (OnDatabaseServer())
         {
             throw new InvalidOperationException("No access to Telonics software to process files.");
         }
         LogGeneralMessage(String.Format("Start processing file {0} on database", file.FileId));
         var database = new AnimalMovementFunctions();
         //FIXME: ProcessOnServer may be called with H and I (Teloncs files which need processing, but are not ArgosFiles)
         //FIXME: If called by Animal Movement App Upload Form on client machine with H or I files, this code will fail
         // if teloncs file but not argos
         // database.TelonicsData_Process(file.FileId);
         // if not telonics or not Argos then fail with warning
         if (platform == null)
         {
             database.ArgosFile_Process(file.FileId);
         }
         else
         {
             database.ArgosFile_ProcessPlatform(file.FileId, platform.PlatformId);
         }
         LogGeneralMessage("Finished processing file on database");
         return(true);
     }
     return(false);
 }
Пример #4
0
        /// <summary>
        /// Validates and loads the file to the database
        /// </summary>
        /// <returns>Returns the newly created collar file, complete with database calculated fields</returns>
        public CollarFile Load()
        {
            Validate();
            if (FileFormatRequiresCollar && Collar == null)
            {
                Collar = FileCollar;
            }
            // The entity objects I got from the callers (i.e. Project, Owner, Collar)
            // came from a foreign DataContext, so they cannot be used as associated
            // entities with a new entity in this datacontext.
            var file = new CollarFile
            {
                ProjectId          = Project == null ? null : Project.ProjectId,
                FileName           = Path.GetFileName(FilePath),
                CollarManufacturer = Collar == null ? null : Collar.CollarManufacturer,
                CollarId           = Collar == null ? null : Collar.CollarId,
                Owner             = Owner == null ? null : Owner.Login,
                Status            = Status,
                Contents          = Contents,
                ParentFileId      = ParentFileId,
                ArgosDeploymentId = ArgosDeploymentId,
                CollarParameterId = CollarParameterId
            };

            Database.CollarFiles.InsertOnSubmit(file);
            Database.SubmitChanges();
            //Linq TO SQL Insert with SPROC dos not set associations, and provides not partial methods to expand
            file.LookupCollarFileFormat = Database.LookupCollarFileFormats.First(l => l.Code == file.Format);
            return(file);
        }
Пример #5
0
        /// <summary>
        /// Retrieves data for an Argos Platform from the Argos Web Server
        /// </summary>
        /// <param name="platform">The Argos Platform to retrieve from the server</param>
        /// <param name="daysToRetrieve">The number of most recent days to retrieve from the server</param>
        public static void DownloadArgosPlatform(ArgosPlatform platform, int?daysToRetrieve = null)
        {
            int daysSinceLastDownload;

            if (daysToRetrieve.HasValue)
            {
                daysSinceLastDownload = daysToRetrieve.Value;
            }
            else
            {
                var database           = new AnimalMovementDataContext();
                var dateOfLastDownload = (from log in database.ArgosDownloads
                                          where log.PlatformId == platform.PlatformId && log.FileId != null
                                          orderby log.TimeStamp descending
                                          select log.TimeStamp).FirstOrDefault();
                daysSinceLastDownload = (DateTime.Now - dateOfLastDownload).Days;
            }
            var days = Math.Min(ArgosWebSite.MaxDays, daysSinceLastDownload);

            if (days < ArgosWebSite.MinDays)
            {
                return;
            }
            var    program = platform.ArgosProgram;
            string errors;
            var    results = ArgosWebSite.GetCollar(program.UserName, program.Password, platform.PlatformId, days,
                                                    out errors);
            CollarFile file = FileLoader.LoadPlatfrom(platform, days, results, errors);

            if (file == null)
            {
                return;
            }
            FileProcessor.ProcessFile(file);
        }
Пример #6
0
 internal FileDetailsForm(CollarFile file)
 {
     InitializeComponent();
     RestoreWindow();
     File        = file;
     CurrentUser = Environment.UserDomainName + @"\" + Environment.UserName;
     LoadDataContext();
     SetUpControls();
 }
Пример #7
0
        private static void ProcessIdfFile(CollarFile file)
        {
            LogGeneralMessage(String.Format("Start local processing of file {0}", file.FileId));

            var databaseViews = new AnimalMovementViews();
            var idfLink       = databaseViews.CollarParametersForIridiumDownload(file.FileId).FirstOrDefault();

            if (idfLink == null)
            {
                LogGeneralMessage("No parameters found.  Skipping file.");
                return;
            }
            var database = new AnimalMovementDataContext();
            var tpfFile  = database.CollarParameterFiles.FirstOrDefault(f => f.FileId == idfLink.ParameterFileId);

            if (tpfFile == null)
            {
                LogGeneralMessage("No collar parameter file found.  Skipping file.");
                return;
            }
            var collar = database.Collars.FirstOrDefault(
                c => c.CollarManufacturer == idfLink.CollarManufacturer &&
                (c.CollarId == idfLink.CollarId || c.CollarId == idfLink.CollarId.Substring(0, 6)));

            if (collar == null)
            {
                LogGeneralMessage("No collar found.  Skipping file.");
                return;
            }

            var databaseFunctions = new AnimalMovementFunctions();

            //FIXME: check that this is generic to all telonics processing and not just Argos files
            databaseFunctions.ArgosFile_ClearProcessingResults(file.FileId);
            databaseFunctions.CollarFile_FixOwnerOfIdfFile((file.FileId));

            var processor = new Gen4Processor(tpfFile.Contents.ToArray());
            var lines     = processor.ProcessIdf(file.Contents.ToArray());

            var data       = Encoding.UTF8.GetBytes(String.Join(Environment.NewLine, lines) + Environment.NewLine);
            var filename   = Path.GetFileNameWithoutExtension(file.FileName) + "_" + DateTime.Now.ToString("yyyyMMdd") + ".csv";
            var fileLoader = new FileLoader(filename, data)
            {
                Project         = null,
                Owner           = tpfFile.ProjectInvestigator, //Must match result from databaseFunctions.CollarFile_FixOwnerOfIdfFile
                Collar          = collar,
                Status          = file.Status,
                ParentFileId    = file.FileId,
                AllowDuplicates = false
            };

            fileLoader.Load();
            LogGeneralMessage("Finished local processing of file");
        }
Пример #8
0
 internal static void exceptionHandler(Exception ex, CollarFile file, ArgosPlatform platform)
 {
     if (file == null)
     {
         ReportException(
             String.Format("Unexpected Exception ({0}) when Loading an unknown collar file",
                           ex.Message));
     }
     else
     {
         ReportException(
             String.Format("Unexpected Exception ({0}) when Loading collar file (id: {1}, name:{2}",
                           ex.Message, file.FileId, file.FileName));
     }
 }
Пример #9
0
        private static void ProcessParameterSet(CollarFile file, ArgosFile argos, DateTime first, DateTime last,
                                                IEnumerable <ArgosTransmission> transmissions,
                                                GetTelonicsParametersForArgosDatesResult parameters)
        {
            LogGeneralMessage(String.Format("    Start processing collar {0}/{1}", parameters.CollarManufacturer,
                                            parameters.CollarId));
            var start = parameters.StartDate ?? DateTime.MinValue;

            if (start < first)
            {
                start = first;
            }
            var end = parameters.EndDate ?? DateTime.MaxValue;

            if (last < end)
            {
                end = last;
            }
            var processor          = GetProcessor(file, parameters);
            var transmissionSubset = transmissions.Where(t => start <= t.DateTime && t.DateTime <= end);
            var lines      = processor.ProcessTransmissions(transmissionSubset, argos);
            var data       = Encoding.UTF8.GetBytes(String.Join(Environment.NewLine, lines) + Environment.NewLine);
            var filename   = Path.GetFileNameWithoutExtension(file.FileName) + "_" + parameters.CollarId + ".csv";
            var fileLoader = new FileLoader(filename, data)
            {
                Project = file.Project,
                Owner   = file.ProjectInvestigator,
                Collar  = new Collar {
                    CollarManufacturer = parameters.CollarManufacturer,
                    CollarId           = parameters.CollarId
                },
                Status            = file.Status,
                ParentFileId      = file.FileId,
                ArgosDeploymentId = parameters.DeploymentId,
                CollarParameterId = parameters.ParameterId,
                AllowDuplicates   = true
            };

            fileLoader.Load();
            var message =
                String.Format(
                    "    Successfully added Argos {0} transmissions from {1:g} to {2:g} to Collar {3}/{4}",
                    parameters.PlatformId, start, end,
                    parameters.CollarManufacturer, parameters.CollarId);

            LogGeneralMessage(message);
        }
Пример #10
0
        private static void HandleException(Exception ex, CollarFile file, ArgosPlatform platform)
        {
            if (file == null)
            {
                Console.WriteLine("Processor exception handler called without a file: {0}", ex.Message);
                return;
            }
            if (file.LookupCollarFileFormat.ArgosData != 'Y')
            {
                Console.WriteLine("Processor exception handler called with a Non-Argos Data file({1}): {0}", ex.Message, file.FileId);
                return;
            }
            var db = new AnimalMovementDataContext();

            db.ArgosFileProcessingIssues_Insert(file.FileId, ex.Message, platform == null ? null : platform.PlatformId,
                                                null, null, null, null);
        }
Пример #11
0
        private static ArgosFile GetArgosFile(CollarFile file)
        {
            switch (file.Format)
            {
            case 'E':
                return(new ArgosEmailFile(file.Contents.ToArray()));

            case 'F':
                return(new ArgosAwsFile(file.Contents.ToArray()));

            case 'G':
                return(new DebevekFile(file.Contents.ToArray()));

            default:
                throw new InvalidOperationException("Unsupported file format: " + file.Format +
                                                    " (supported formats are E,F,G)");
            }
        }
Пример #12
0
        /// <summary>
        /// Retrieves data for an Argos Program from the Argos Web Server
        /// </summary>
        /// <param name="program">The Argos Program (contains Platforms) to retrieve from the server</param>
        /// <param name="daysToRetrieve">The number of most recent days to retrieve from the server</param>
        public static void DownloadArgosProgram(ArgosProgram program, int?daysToRetrieve = null)
        {
            int daysSinceLastDownload;

            if (daysToRetrieve.HasValue)
            {
                daysSinceLastDownload = daysToRetrieve.Value;
            }
            else
            {
                var database           = new AnimalMovementDataContext();
                var dateOfLastDownload = (from log in database.ArgosDownloads
                                          where log.ProgramId == program.ProgramId && log.FileId != null
                                          orderby log.TimeStamp descending
                                          select log.TimeStamp).FirstOrDefault();
                //Problem: using Days always truncates.
                // If I download at 1am on day 1, and then 11pm on day 2, (1.9 days -> 1day),
                //   I will miss any data created between 1am and 11pm on day 1.
                // However, rounding up may cause a lot of duplication,
                // (i.e. 6:01am on day1 and then 6:02am on day2, will need to download 2 days to get the extra minute)
                // by default we should round up to make sure that all data is obtained.  However, since this is
                // typically called on a scheduled task at the same time (+/- download/processing time) everyday.
                // I will check if we are close to an even day, and then round tword that day
                var timespan = DateTime.Now - dateOfLastDownload;
                int extraDay = timespan.Hours == 0 && timespan.Minutes < 5 ? 0 : 1;
                daysSinceLastDownload = timespan.Days + extraDay;
            }
            var days = Math.Min(ArgosWebSite.MaxDays, daysSinceLastDownload);

            if (days < ArgosWebSite.MinDays)
            {
                return;
            }
            string errors;
            var    results = ArgosWebSite.GetProgram(program.UserName, program.Password, program.ProgramId, days,
                                                     out errors);
            CollarFile file = FileLoader.LoadProgram(program, days, results, errors);

            if (file == null)
            {
                return;
            }
            FileProcessor.ProcessFile(file);
        }
Пример #13
0
        private static void ProcessFile(CollarFile file, ArgosFile argos, ArgosPlatform platform)
        {
            LogGeneralMessage(String.Format("Start local processing of file {0}", file.FileId));
            var databaseFunctions = new AnimalMovementFunctions();

            if (platform == null)
            {
                databaseFunctions.ArgosFile_ClearProcessingResults(file.FileId);
                if (IsArgosAwsFileIncomplete(argos as ArgosAwsFile) ?? false)
                {
                    LogIssueForFile(file.FileId,
                                    "The Argos server could not return all the data requested and this file is incomplete.");
                }
            }
            else
            {
                databaseFunctions.ArgosFile_UnProcessPlatform(file.FileId, platform.PlatformId);
            }

            var transmissionsByPlatform = from transmission in argos.GetTransmissions()
                                          group transmission by transmission.PlatformId
                                          into transmissions
                                          where platform == null || transmissions.Key == platform.PlatformId
                                          select transmissions;

            foreach (var transmissionSet in transmissionsByPlatform)
            {
                try
                {
                    ProcessTransmissions(file, argos, transmissionSet);
                }
                catch (Exception ex)
                {
                    var message = String.Format("ERROR {0} adding Argos {1} transmissions",
                                                ex.Message, transmissionSet.Key);
                    LogIssueForFile(file.FileId, message, transmissionSet.Key);
                }
            }
            LogGeneralMessage("Finished local processing of file");
        }
Пример #14
0
 /// <summary>
 /// Full or partial processing of Telonics data in an Argos file
 /// </summary>
 /// <param name="file">The collar file with Argos data to processes.  Must not be null</param>
 /// <param name="platform">The Argos platform in the file to process.
 /// If this is null, then all the platforms will be processed.</param>
 public static void ProcessFile(CollarFile file, ArgosPlatform platform = null)
 {
     if (file == null)
     {
         throw new ArgumentNullException("file", "No collar file was provided to process.");
     }
     if (!ProcessOnServer(file, platform))
     {
         if (file.Format == 'H')
         {
             ProcessDataLogFile(file);
         }
         else if (file.Format == 'I')
         {
             ProcessIdfFile(file);
         }
         else
         {
             ProcessFile(file, GetArgosFile(file), platform);
         }
     }
 }
Пример #15
0
        /// <summary>
        /// Loads and logs the download data for an Argos Platform
        /// </summary>
        /// <param name="platform">The Argos PlatformId that this data is for</param>
        /// <param name="days">The number of days that are included in this data set</param>
        /// <param name="results">The data returned from the Argos Web Server (may be null)</param>
        /// <param name="errors">Any errors returned by the Argos Web Server (may be null)</param>
        /// <returns>Returns the newly created collar file, complete with database calculated fields</returns>
        /// <remarks>Only one of results and errors can be non-null.</remarks>
        internal static CollarFile LoadPlatfrom(ArgosPlatform platform, int days,
                                                ArgosWebSite.ArgosWebResult results, string errors)
        {
            //if results is null, then errors should be non-null (database rule, insert will fail if false)
            CollarFile file     = null;
            var        database = new AnimalMovementDataContext();

            //Linq to SQL wraps the changes in a transaction so file will not be created if log cannot be written
            if (results != null)
            {
                file = new CollarFile
                {
                    Owner    = platform.ArgosProgram.Manager,
                    FileName = "platform_" + platform.PlatformId + "_" + DateTime.Now.ToString("yyyyMMdd") + ".aws",
                    Status   = 'A',
                    Contents = results.ToBytes()
                };
                database.CollarFiles.InsertOnSubmit(file);
            }
            //Linq to SQL does not return the PK (timestamp) of the new ArgosDownload object, so don't use it in this data context
            var log = new ArgosDownload
            {
                PlatformId   = platform.PlatformId,
                CollarFile   = file,
                Days         = days,
                ErrorMessage = errors
            };

            database.ArgosDownloads.InsertOnSubmit(log);
            database.SubmitChanges();
            //Linq TO SQL Insert with SPROC dos not set associations, and provides not partial methods to expand
            if (file != null)
            {
                file.LookupCollarFileFormat = database.LookupCollarFileFormats.First(l => l.Code == file.Format);
            }
            return(file);
        }
Пример #16
0
        private static bool NeedTelonicsSoftware(CollarFile file)
        {
            var database = new AnimalMovementViews();

            return(database.FileHasGen4Data(file.FileId) ?? false);
        }
Пример #17
0
 /// <summary>
 /// Full or partially processes telonics data in argos files.  This program is designed to run regularly
 /// as a scheduled task (with no arguments) as well as being called by the database with a single fileid
 /// argument (to fully process that file), or with two arguments, platformid and fileid (to partially
 /// process that file for just the single platform).  When a file is fully or partially processed, it
 /// clears any prior processing results and issues, to prevent duplicates.
 /// Any processing errors are written to the database, any other errors are written to the console.
 /// </summary>
 /// <param name="args">
 /// If there are no args then ask the database for a list of files that need processing and process them all.
 /// If there is only one argument and that argument is the login (domain\username) of a project
 ///   investigator in the database, then process all the files that belong to the PI or his projects and
 ///   need processing.
 /// If the argument matches /np[latform], or '/na[rgos]', then the remaining files will be fully processed
 /// If the argument matches /nf[ile], then the next argos platform specified will not be used to
 ///   partially process the previously specified file
 /// If the argument matches /a[rgos]:xxx or /p[latform]:xxx or xxx and xxx is a platform id in the
 ///   database, then the previously specified file (or the next file if no has been specified) will be
 ///   partially processed for only this platform.
 /// if the argument matches /f[ile]:xxx or xxx, and xxx is a fileid in the database, then the file will
 ///   be partially processed if an argos platform has been provided as a prior argument, otherwise it will
 ///   be fully processed.
 /// In the unlikely event that an argument matches a valid platform and a valid file, then the tie will go
 ///   to the file.
 /// Any other argument is ignored with a warning
 /// Note:
 ///   A project investigator login will be accepted as an argument in any position, but is only
 ///     meaningful as the first and only argument
 ///   If you want to partially process a file, you must provide the Argos platform first
 /// Examples:
 ///   To fully process multiple files
 ///     ArgosProcessor,exe f1 f2 f3 ...
 ///   To partially process multiple files with for one Argos platform
 ///     ArgosProcessor,exe p1 f1 f2 f3 ...
 ///   To partially process one file for multiple Argos platforms
 ///     ArgosProcessor,exe p1 f1 p2 p3 ...
 ///   To partially process multiple files with multiple Argos platforms
 ///     ArgosProcessor,exe p1 f1 p2 p3 /nf p4 f2 p5 p6 ...
 ///   To fully process files f1 and f2 and partially process files f3 and f4
 ///     ArgosProcessor,exe f1 f2 p1 f3 p2 /nf p3 f4 p4 ...
 ///     or ArgosProcessor,exe p1 f3 p2 /nf p3 f4 p4 /np f1 f2 ...
 /// </param>
 /// <remarks>
 /// If a copy of TDC.exe is available from this program (as specified in the config file),
 /// then the processor will be make use of it to process the files locally and send the
 /// results to the database, otherwise the processor will request that the database
 /// invoke the ArgosProcessor on the server.
 /// </remarks>
 private static void Main(string[] args)
 {
     try
     {
         if (args.Length == 0)
         {
             FileProcessor.ProcessAll(HandleException);
         }
         else
         {
             ArgosPlatform       platform = null;
             CollarFile          file     = null;
             ProjectInvestigator pi       = null;
             foreach (var arg in args)
             {
                 if (ClearPlatform(arg))
                 {
                     platform = null;
                 }
                 else
                 {
                     if (ClearCollarFile(arg))
                     {
                         file = null;
                     }
                     else
                     {
                         var fileArg = GetCollarFile(arg);
                         if (fileArg != null)
                         {
                             file = fileArg;
                         }
                         else
                         {
                             var platformArg = GetPlatform(arg);
                             if (platformArg != null)
                             {
                                 platform = platformArg;
                             }
                             else
                             {
                                 var piArg = GetProjectInvestigator(arg);
                                 if (piArg != null)
                                 {
                                     pi = piArg;
                                 }
                                 else
                                 {
                                     Console.WriteLine("Unhandled argument: {0}", arg);
                                 }
                             }
                         }
                     }
                 }
                 if (args.Length == 1 && pi != null)
                 {
                     FileProcessor.ProcessAll(HandleException, pi);
                 }
                 if (file != null)
                 {
                     try
                     {
                         FileProcessor.ProcessFile(file, platform);
                     }
                     catch (Exception ex)
                     {
                         HandleException(ex, file, platform);
                     }
                 }
             }
         }
     }
     catch (Exception ex)
     {
         Console.WriteLine("Unhandled Exception: {0}", ex.Message);
     }
 }
Пример #18
0
        private static void ProcessTransmissions(CollarFile file, ArgosFile argos,
                                                 IGrouping <string, ArgosTransmission> group)
        {
            LogGeneralMessage(String.Format("  Start processing transmissions for Argos Id {0}", group.Key));
            var platformId    = group.Key;
            var transmissions = group.ToList();
            var first         = transmissions.Min(t => t.DateTime);
            var last          = transmissions.Max(t => t.DateTime);
            var databaseViews = new AnimalMovementViews();
            var parameterSets =
                databaseViews.GetTelonicsParametersForArgosDates(platformId, first, last)
                .OrderBy(c => c.StartDate)
                .ToList();

            if (parameterSets.Count == 0)
            {
                var msg = String.Format("No Collar for ArgosId {0} from {1:g} to {2:g}",
                                        platformId, first, last);
                LogIssueForFile(file.FileId, msg, platformId, null, null, first, last);
                return;
            }
            if (parameterSets[0].StartDate != null && first < parameterSets[0].StartDate)
            {
                var msg = String.Format("No Collar for ArgosId {0} from {1:g} to {2:g}",
                                        platformId, first, parameterSets[0].StartDate);
                LogIssueForFile(file.FileId, msg, platformId, null, null, first, parameterSets[0].StartDate);
            }
            int lastIndex = parameterSets.Count - 1;

            if (parameterSets[lastIndex].EndDate != null && parameterSets[lastIndex].EndDate < last)
            {
                var msg = String.Format("No Collar for ArgosId {0} from {1:g} to {2:g}",
                                        platformId, parameterSets[lastIndex].EndDate, last);
                LogIssueForFile(file.FileId, msg, platformId, null, null, parameterSets[lastIndex].EndDate, last);
            }
            foreach (var parameterSet in parameterSets)
            {
                if (parameterSet.ParameterId == null ||
                    (parameterSet.CollarModel == "Gen3" && parameterSet.Gen3Period == null) ||
                    (parameterSet.CollarModel == "Gen4" && parameterSet.Format == null))
                {
                    var start = parameterSet.StartDate ?? first;
                    var end   = parameterSet.EndDate ?? last;
                    var msg   = String.Format("No Telonics Parameters for Collar {0}/{3} from {1:g} to {2:g}",
                                              parameterSet.CollarManufacturer, start, end, parameterSet.CollarId);
                    LogIssueForFile(file.FileId, msg, platformId, parameterSet.CollarManufacturer, parameterSet.CollarId, start, end);
                    continue;
                }
                try
                {
                    ProcessParameterSet(file, argos, first, last, transmissions, parameterSet);
                }
                catch (Exception ex)
                {
                    var message = String.Format(
                        "ERROR {0} adding Argos {1} transmissions from {2:g} to {3:g} to Collar {4}/{5}",
                        ex.Message, parameterSet.PlatformId, first, last,
                        parameterSet.CollarManufacturer, parameterSet.CollarId);
                    LogIssueForFile(file.FileId, message, parameterSet.PlatformId, parameterSet.CollarManufacturer,
                                    parameterSet.CollarId, first, last);
                }
            }
            LogGeneralMessage("  Finished processing transmissions");
        }