private async void FtpServer_SentData(object sender, FtpSentDataEventArgs e)
 {
     IUpgradeTasksModel upgradeTaskDataModel = ServiceLocator.Current.GetInstance <IUpgradeTasksModel>();
     await _upgradeTaskQueue.Enqueue(() => Task.Run(() =>
     {
         //var task = upgradeTaskDataModel.Select(
         var task = upgradeTaskDataModel.Data.Where(
             t => t.Status == UpgradeStatus.InProgress &&
             t.Device.ip == e.Remote.Address.ToString()
             //t => t.Device
             ).FirstOrDefault();
         if (task != null)
         {
             task.LastUpdateTime = DateTime.Now;
             task.SentDataBytes  = e.SentBytes;
             try
             {
                 upgradeTaskDataModel.UpdateAsync(
                     task,
                     t => t.SentDataBytes,
                     t => t.LastUpdateTime).Wait();
                 //DebugLog.TraceMessage(string.Format("Sent({0}) Total({1}) - {2} %)", e.SentBytes, e.FileSize, e.SentBytes * 100 / e.FileSize));
             }
             catch (Exception) { }
         }
     }
                                                    ));
 }
        private void PutUpgradeTaskInWorkingQueue(
            IUpgradeTasksModel dataModel, UpgradeTask task)
        {
            task.Status        = UpgradeStatus.InProgress;
            task.LastStartTime = task.LastUpdateTime = DateTime.Now;
            task.SentDataBytes = 0;
            try
            {
                dataModel.UpdateAsync(
                    task,
                    t => t.Status,
                    t => t.LastStartTime,
                    t => t.LastUpdateTime,
                    t => t.SentDataBytes).Wait();
            }
            catch (Exception) { }

            Func <string, string, string, CancellationToken, Task <bool> > SendNotificationFunc = null;

            switch (task.UpgradeFile.filetype)
            {
            case (int)UpgradeFileType.SoftwareUpgrade:
                SendNotificationFunc = HttpClient.SendFirmwareUpgradeNotificationAsync;
                break;

            case (int)UpgradeFileType.AddressBookUpgrade:
                SendNotificationFunc = HttpClient.SendAddressBookUpgradeNotificationAsync;
                break;

            case (int)UpgradeFileType.ScreenSaverUpgrade:
                SendNotificationFunc = HttpClient.SendResourceUpgradeNotificationAsync;
                break;

            case (int)UpgradeFileType.SecurityCardListUpgrade:
                SendNotificationFunc = HttpClient.SendCardListUpgradeNotificationAsync;
                break;
            }

            if (SendNotificationFunc != null)
            {
                this.Add(new NetworkTask
                {
                    IP       = task.Device.ip,
                    TaskFunc = async() =>
                    {
                        if (!await SendNotificationFunc(task.Device.ip,
                                                        Config.Instance.LocalIP, task.UpgradeFile.filepath, default(CancellationToken)).ConfigureAwait(false))
                        {
                            MarkUpgradeTaskTBD(dataModel, task);
                            return;
                        }

                        UpdateUpgradeTaskLastUpdateTime(dataModel, task);
                    }
                });
            }
        }
        public DialogSelectDevicesToBeUpgradedViewModel(
            ICollectionModel <Device> deviceDataModel,
            IUpgradeTasksModel upgradeTaskDataModel,
            IDialogService dialogService,
            upgrade upgradeFile)
        {
            this._deviceDataModel      = deviceDataModel;
            this._upgradeTaskDataModel = upgradeTaskDataModel;
            this._dialogService        = dialogService;
            this._upgradeFile          = upgradeFile;
            if (upgradeFile.filetype.HasValue)
            {
                if (upgradeFile.filetype == (int)UpgradeFileType.SoftwareUpgrade)
                {
                    _deviceType = (DeviceType?)upgradeFile.device_type;
                }
            }

            Devices = (ListCollectionView) new ListCollectionView((IList)_deviceDataModel.Data);
            using (Devices.DeferRefresh())
            {
                Devices.Filter = delegate(object obj)
                {
                    Device device = obj as Device;
                    if (device != null && device.type.HasValue)
                    {
                        if (_deviceType.HasValue)
                        {
                            if (device.type == (int)_deviceType)
                            {
                                return(true);
                            }
                        }
                        else
                        {
                            switch (device.type)
                            {
                            // case (int)DeviceType.Control_Server:
                            case (int)DeviceType.Door_Camera:
                            case (int)DeviceType.Lobby_Phone_Unit:
                            case (int)DeviceType.Lobby_Phone_Building:
                            case (int)DeviceType.Lobby_Phone_Area:
                            case (int)DeviceType.Indoor_Phone:
                            case (int)DeviceType.Administrator_Unit:
                            case (int)DeviceType.Indoor_Phone_SD:
                            // case (int)DeviceType.Mobile_Phone:
                            case (int)DeviceType.Emergency_Intercom_Unit:
                                // case (int)DeviceType.IPCAM:
                                return(true);
                            }
                        }
                    }
                    return(false);
                };
                Devices.SortDescriptions.Add(new SortDescription("ip", ListSortDirection.Ascending));
            }
        }
예제 #4
0
        public UpgradeTasksViewModel(
            IUpgradeTasksModel dataModel,
            IDialogService dialogService)
        {
            this._dataModel              = dataModel;
            this._dialogService          = dialogService;
            UpgradeTasks                 = (ListCollectionView)CollectionViewSource.GetDefaultView((IList)_dataModel.Data);
            UpgradeTasks.CurrentChanged += UpgradeTasks_CurrentChanged;

            RefreshCommand.Execute(null);
        }
 private void UpdateUpgradeTaskLastUpdateTime(
     IUpgradeTasksModel dataModel, UpgradeTask task)
 {
     task.LastUpdateTime = DateTime.Now;
     try
     {
         dataModel.UpdateAsync(
             task,
             t => t.LastUpdateTime).Wait();
     }
     catch (Exception) { }
 }
 private void MarkUpgradeTaskRemoved(
     IUpgradeTasksModel dataModel, UpgradeTask task)
 {
     task.Status = UpgradeStatus.Removed;
     try
     {
         //if (!task.DeletedByUser)
         dataModel.UpdateAsync(task, t => t.Status).Wait();
         //else
         //    dataModel.Delete(task);
     }
     catch (Exception) { }
 }
 private void MarkUpgradeTaskComplete(
     IUpgradeTasksModel dataModel, UpgradeTask task)
 {
     task.Status         = UpgradeStatus.Complete;
     task.LastUpdateTime = DateTime.Now;
     try
     {
         //if (!task.DeletedByUser)
         dataModel.UpdateAsync(
             task,
             t => t.Status,
             t => t.LastUpdateTime).Wait();
         //else
         //    dataModel.Delete(task);
     }
     catch (Exception) { }
 }
 private void MarkUpgradeTaskTBD(
     IUpgradeTasksModel dataModel, UpgradeTask task)
 {
     task.Status        = UpgradeStatus.TBD;
     task.LastStartTime = task.LastUpdateTime = null;
     task.SentDataBytes = 0;
     try
     {
         //if (!task.DeletedByUser)
         dataModel.UpdateAsync(
             task,
             t => t.Status,
             t => t.LastStartTime,
             t => t.LastUpdateTime,
             t => t.SentDataBytes).Wait();
         //else
         //    dataModel.Delete(task);
     }
     catch (Exception) { }
 }
        private async void FtpServer_NewDataConnection(object sender, FtpDataConnectionEventArgs e)
        {
            IUpgradeTasksModel upgradeTaskDataModel = ServiceLocator.Current.GetInstance <IUpgradeTasksModel>();

            await _upgradeTaskQueue.Enqueue(() => Task.Run(() =>
            {
                try
                {
                    // TODO: check 存取 upgradeTaskDataModel.Data 是否需要 mutex 保護
                    var task = upgradeTaskDataModel.Data.Where(
                        t => t.Status == UpgradeStatus.InProgress &&
                        t.Device.ip == e.Remote.Address.ToString()
                        //t => t.Device
                        ).FirstOrDefault();
                    if (task != null)
                    {
                        UpdateUpgradeTaskLastUpdateTime(upgradeTaskDataModel, task);
                    }
                }
                catch (Exception) { }
            }
                                                           ));
        }
        private async void FtpServer_ClosedDataConnection(object sender, FtpDataConnectionEventArgs e)
        {
            IUpgradeTasksModel upgradeTaskDataModel = ServiceLocator.Current.GetInstance <IUpgradeTasksModel>();

            await _upgradeTaskQueue.Enqueue(() => Task.Run(() =>
            {
                try
                {
                    //var task = upgradeTaskDataModel.Select(
                    var task = upgradeTaskDataModel.Data.Where(
                        t => t.Status == UpgradeStatus.InProgress &&
                        t.Device.ip == e.Remote.Address.ToString()
                        //t => t.Device,
                        //t => t.UpgradeFile
                        ).FirstOrDefault();
                    if (task != null)
                    {
                        if (task.UpgradeFile == null || task.UpgradeFile.FileSize == 0)
                        {
                            MarkUpgradeTaskRemoved(upgradeTaskDataModel, task);
                            return;
                        }

                        if (task.UpgradeFile.FileSize == task.SentDataBytes)
                        {
                            MarkUpgradeTaskComplete(upgradeTaskDataModel, task);
                        }
                        else
                        {
                            MarkUpgradeTaskTBD(upgradeTaskDataModel, task);
                        }
                    }
                }
                catch (Exception) { }
            }
                                                           ));
        }
        private void UpgradeTask(CancellationToken cancelToken)
        {
            IUpgradeTasksModel upgradeTaskDataModel = ServiceLocator.Current.GetInstance <IUpgradeTasksModel>();
            var deviceComparer = new DeviceEqualityComparer();

            try
            {
                FtpServer.Instance.NewDataConnection    += FtpServer_NewDataConnection;
                FtpServer.Instance.ClosedDataConnection += FtpServer_ClosedDataConnection;
                FtpServer.Instance.SentData             += FtpServer_SentData;

                upgradeTaskDataModel.RefillDataAsync().Wait();
                //upgradeTaskDataModel.Data.Where(
                upgradeTaskDataModel.Select(
                    t => t.Status == UpgradeStatus.InProgress &&
                    (t.LastStartTime == null ||
                     t.LastStartTime < _serviceStartTime)).ToList()
                .ForEach(task => MarkUpgradeTaskTBD(upgradeTaskDataModel, task));

                while (true)
                {
                    _token.ThrowIfCancellationRequested();

                    // 刪除被使用者標記要刪除且非運行中的 Task
                    //var tasksToBeRemoved = upgradeTaskDataModel.Data.Where(
                    var tasksToBeRemoved = upgradeTaskDataModel.Select(
                        t => t.DeletedByUser &&
                        t.Status != UpgradeStatus.InProgress).ToList();
                    if (tasksToBeRemoved != null)
                    {
                        upgradeTaskDataModel.Delete(tasksToBeRemoved);
                    }

                    // 挑選出狀態為運行中但超過 20 秒未動作的 tasks,將其標記為 TBD
                    upgradeTaskDataModel.Select(
                        t => t.Status == UpgradeStatus.InProgress &&
                        (t.LastUpdateTime == null ||
                         (DateTime.Now - (DateTime)t.LastUpdateTime).TotalSeconds > 20)).ToList()
                    .ForEach(t => { MarkUpgradeTaskTBD(upgradeTaskDataModel, t); });

                    //var upgradeTasks = upgradeTaskDataModel.Data.Where(
                    //    t => t.Status != UpgradeStatus.Removed).ToList();
                    var upgradeTasks = upgradeTaskDataModel.Select(
                        t => t.Status != UpgradeStatus.Removed,
                        t => t.Device,
                        t => t.UpgradeFile).ToList();
                    if (upgradeTasks != null)
                    {
                        var devices = (from t in upgradeTasks
                                       where t.Device.online == 1
                                       select t.Device).Distinct(deviceComparer).ToList();

                        //List<Task> tasks = new List<Task>();

                        foreach (var device in devices)
                        {
                            _token.ThrowIfCancellationRequested();

                            //tasks.Add(Task.Run(() => UpgradeTaskForEachDevice(upgradeTaskDataModel, device, cancelToken)));
                            UpgradeTaskForEachDevice(upgradeTaskDataModel, device, cancelToken);
                        }
                        //Task.WaitAll(tasks.ToArray());
                    }
                    Thread.Sleep(100);
                }
            }
            catch (OperationCanceledException) { }
            finally
            {
                FtpServer.Instance.NewDataConnection    -= FtpServer_NewDataConnection;
                FtpServer.Instance.ClosedDataConnection -= FtpServer_ClosedDataConnection;
                FtpServer.Instance.SentData             -= FtpServer_SentData;
            }
        }
        // ConcurrentQueue<Task> updateTaskQueueForUpgradeTask = new ConcurrentQueue<Task>();
        private void UpgradeTaskForEachDevice(IUpgradeTasksModel upgradeTaskDataModel, Device device, CancellationToken cancelToken)
        {
            // 刪除被使用者標記要刪除且非運行中的 Task
            //var tasksToBeRemoved = upgradeTaskDataModel.Data.Where(
            var tasksToBeRemoved = upgradeTaskDataModel.Select(
                t => t.DeletedByUser &&
                t.Status != UpgradeStatus.InProgress).ToList();

            if (tasksToBeRemoved != null)
            {
                upgradeTaskDataModel.Delete(tasksToBeRemoved);
            }

            //var updateTasksPerDevice = upgradeTaskDataModel.Data.Where(
            //    t => t.DeviceID == device.id && t.Status != UpgradeStatus.Removed
            var updateTasksPerDevice = upgradeTaskDataModel.Select(
                t => t.DeviceID == device.id && t.Status != UpgradeStatus.Removed,
                t => t.Device,
                t => t.UpgradeFile
                ).OrderByDescending(t => t.UpgradeFile.filetype);
            UpgradeTask candidateTask = null;
            bool        stopTrace     = false;

            try
            {
                foreach (var task in updateTasksPerDevice)
                {
                    if (candidateTask == null ||
                        candidateTask.UpgradeFile.filetype != task.UpgradeFile.filetype)
                    {
                        //if (candidateTask != null && candidateTask.Status == UpgradeStatus.TBD)
                        //{
                        // put candidateTask to working queue
                        //PutUpgradeTaskInWorkingQueue(upgradeTaskDataModel, candidateTask);
                        //}
                        candidateTask = task;
                        stopTrace     = false;
                    }
                    else if (!stopTrace)
                    {
                        // similar tasks:
                        // case 1.1: (x, T)         // remove
                        //           (1, T)         // pick
                        // case 1.2: (1, C or W)
                        //           (1, T)         // remove
                        // case 1.3: (1, C or W)
                        //           (2, T)         // pick if 1 is C
                        // case 2.1: (x, T)         // remove
                        //           (x, T)         // remove
                        //           (1, T)         // pick
                        // case 2.2: (1, C or W)
                        //           (x, T)         // remove
                        //           (1, T)         // remove
                        // case 2.3: (1, C or W)
                        //           (x, T)         // remove
                        //           (2, T)         // pick if 1 is C
                        if (task.Status == UpgradeStatus.TBD)
                        {
                            MarkUpgradeTaskRemoved(upgradeTaskDataModel, task);
                        }
                        else
                        {   // Complete or Working
                            if (candidateTask.UpgradeID == task.UpgradeID)
                            {
                                MarkUpgradeTaskRemoved(upgradeTaskDataModel, candidateTask);
                            }
                            else
                            {
                                if (task.Status != UpgradeStatus.Complete)
                                {
                                    candidateTask = task;
                                }
                            }
                            stopTrace = true;
                        }
                    }
                }
            } catch (Exception) { return; }

            //if (candidateTask != null && candidateTask.Status == UpgradeStatus.TBD)
            //{
            //    // put candidateTask to working queue
            //    //PutUpgradeTaskInWorkingQueue(upgradeTaskDataModel, candidateTask);
            //}
            if (device.online == 0)
            {
                return;
            }

            var taskInProgress = (from t in updateTasksPerDevice.AsParallel()
                                  where t.Status == UpgradeStatus.InProgress
                                  select t).FirstOrDefault();

            if (taskInProgress == null)
            {
                candidateTask = (from t in updateTasksPerDevice.AsParallel()
                                 where t.Status == UpgradeStatus.TBD &&
                                 !t.DeletedByUser
                                 orderby t.ID
                                 select t).FirstOrDefault();
                if (candidateTask != null)
                {
                    PutUpgradeTaskInWorkingQueue(upgradeTaskDataModel, candidateTask);
                }
            }
        }