public static ServerDeviceConfig GetConfiguration(ServerCredentials credentials, string deviceId, string currentConfigData)
        {
            var req = WebRequest.Create($"{credentials.serverUrl}/device-config");

            var reqMessage = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(new DeviceConfigRequest()
            {
                deviceid            = deviceId,
                current_config_data = currentConfigData,
            }));

            req.Method        = "POST";
            req.ContentType   = "text/json";
            req.ContentLength = reqMessage.Length;

            var reqTx = req.GetRequestStream();

            reqTx.Write(reqMessage, 0, reqMessage.Length);
            reqTx.Close();

            var reqRx       = req.GetResponse().GetResponseStream();
            var reqRxReader = new StreamReader(reqRx);

            var rxData = reqRxReader.ReadToEnd();

            var res  = JsonConvert.DeserializeObject <ServerResponseConfigMessage>(rxData);
            var res2 = JsonConvert.DeserializeObject <ServerResponseConfigMessage>(res.config_data);

            return(new ServerDeviceConfig {
                userId = res2.userid,
                deviceConfig = res2.config_data,
            });
        }
        static bool UploadDataToServer(ServerCredentials credentials, ServerUploadHeader header, string dataFilePath)
        {
            header.datasize = (ulong)(new FileInfo(dataFilePath)).Length;

            var headerJson  = JsonConvert.SerializeObject(header);
            var headerBytes = Encoding.UTF8.GetBytes(headerJson);

            return(true);
        }
        static bool HandleVolumeMountForUpload(string path, ProgramConfig config)
        {
            Console.WriteLine($"HandleVolumeMountForUpload: handling volume at path {path} for upload");

            if (!IsVolumeMountPointForUploadValid(path))
            {
                Console.WriteLine($"HandleVolumeMountForUpload: mount point for volume failed inner validity check");
                return(false);
            }

            var configText   = File.ReadAllText($"{path}MISC\\settings.json");
            var configParsed = JsonConvert.DeserializeObject <JObject>(configText);
            var serialNumber = configParsed["info"]["serial-number"].ToObject <string>();

            var creds = new ServerCredentials()
            {
                serverUrl = config.dbUrl,
            };

            var serverConfig = ServerUtility.GetConfiguration(creds, serialNumber, configText);

            if (IsBC300ConfigTheSame(configText, serverConfig.deviceConfig))
            {
                File.WriteAllText($"{path}MISC\\settings.json", serverConfig.deviceConfig);
            }

            var serverReportedUserId = serverConfig.userId;

            // Scan for data files.
            foreach (var sdir in Directory.EnumerateDirectories($"{path}DCIM\\"))
            {
                foreach (var sfile in Directory.EnumerateFiles(sdir))
                {
                    var baseName  = Path.GetFileNameWithoutExtension(sfile);
                    var baseParts = baseName.Split('_');

                    if (baseParts.Length < 3)
                    {
                        continue;
                    }

                    var fullPath   = sfile;
                    var dataSize   = new FileInfo(fullPath).Length;
                    var dataType   = Path.GetExtension(sfile).Substring(1).ToLower();
                    var dateString = baseParts[2].Substring(0, 8);
                    var dateDay    = dateString.Substring(2, 2);
                    var dateMonth  = dateString.Substring(0, 2);
                    var dateYear   = dateString.Substring(4, 4);

                    dateString = $"{dateYear}-{dateMonth}-{dateDay}";

                    var timeString = baseParts[2].Substring(8, 6);

                    var dataStream = File.OpenRead(fullPath);

                    Console.WriteLine($"Uploading {fullPath}");

                    var uploadTask = MDACS.API.Database.UploadAsync(
                        config.authUrl, config.dbUrl,
                        config.username, config.password,
                        dataSize, dataType,
                        dateString, serialNumber, timeString,
                        serverReportedUserId,
                        dataStream
                        );

                    Console.WriteLine("Waiting...");

                    uploadTask.Wait();

                    Console.WriteLine("Done upload..");

                    var uploadResult = uploadTask.Result;

                    dataStream.Close();

                    if (uploadResult.success && uploadResult.security_id.Length != 0)
                    {
                        Console.WriteLine("Upload success");
                        File.Delete(fullPath);
                    }
                    else
                    {
                        Console.WriteLine("Upload failure");
                    }
                }
            }

            // Would be nice to be able to run a chkdsk /F command on the volume just to help over time correct some issues.

            /*var processInfo = new ProcessStartInfo()
             * {
             *  FileName = "chkdsk.exe",
             *  Arguments = $"{path} /f /r /x",
             * };
             *
             * var chkdskProcess = Process.Start(processInfo);
             * chkdskProcess.StandardInput.WriteLine("Y");
             * chkdskProcess.StandardInput.WriteLine("Y");
             * chkdskProcess.StandardInput.WriteLine("Y");
             * chkdskProcess.WaitForExit(1000 * 60 * 5);
             */

            return(true);
        }