示例#1
0
        public async Task Start()
        {
            //ЗАПУСК СЛУШАТЕЛЯ ДЛЯ ТЕРМИНАЛОВ---------------------------------------------------------
            if (Listener != null)
            {
                var taskListener = Listener.RunServer(ProviderTerminal);
                BackGroundTasks.Add(taskListener);
            }

            //ЗАПУСК ОПРОСА КАССИРОВ-------------------------------------------------------------------
            if (MasterSerialPort != null)
            {
                var taskSerialPort = Task.Factory.StartNew(async() =>
                {
                    if (await MasterSerialPort.CycleReConnect())
                    {
                        var taskCashierEx = MasterSerialPort.RunExchange();
                        BackGroundTasks.Add(taskCashierEx);
                    }
                });
                BackGroundTasks.Add(taskSerialPort);
            }

            //КОНТРОЛЬ ФОНОВЫХ ЗАДАЧ
            var taskFirst = await Task.WhenAny(BackGroundTasks);

            if (taskFirst.Exception != null)                           //критическая ошибка фоновой задачи
            {
                ErrorString = taskFirst.Exception.ToString();
            }
        }
示例#2
0
        public void LoadSetting()
        {
            //ЗАГРУЗКА НАСТРОЕК----------------------------------------------------------------
            XmlListenerSettings       xmlListener;
            XmlSerialSettings         xmlSerial;
            XmlLogSettings            xmlLog;
            List <XmlCashierSettings> xmlCashier;

            try
            {
                var xmlFile = XmlWorker.LoadXmlFile("Settings", "Setting.xml"); //все настройки в одном файле
                if (xmlFile == null)
                {
                    return;
                }

                xmlListener = XmlListenerSettings.LoadXmlSetting(xmlFile);
                xmlSerial   = XmlSerialSettings.LoadXmlSetting(xmlFile);
                xmlLog      = XmlLogSettings.LoadXmlSetting(xmlFile);
                xmlCashier  = XmlCashierSettings.LoadXmlSetting(xmlFile);
            }
            catch (FileNotFoundException ex)
            {
                ErrorString = ex.ToString();
                return;
            }
            catch (Exception ex)
            {
                ErrorString = "ОШИБКА в узлах дерева XML файла настроек:  " + ex;
                return;
            }


            //СОЗДАНИЕ ЛОГА--------------------------------------------------------------------------
            LogTicket = new Log("TicketLog.txt", xmlLog);


            //СОЗДАНИЕ СЛУШАТЕЛЯ ДЛЯ ТЕРМИНАЛОВ-------------------------------------------------------
            Listener         = new ListenerTcpIp(xmlListener);
            ProviderTerminal = new Server2TerminalExchangeDataProvider();
            ProviderTerminal.PropertyChanged += (o, e) =>
            {
                var provider = o as Server2TerminalExchangeDataProvider;
                if (provider != null)
                {
                    if (e.PropertyName == "InputData")
                    {
                        TicketItem ticket;
                        provider.OutputData = provider.OutputData ?? new TerminalOutData();
                        switch (provider.InputData.NumberQueue)
                        {
                        //ПРИГОРОДНЫЕ КАСС
                        case 1:
                            switch (provider.InputData.Action)
                            {
                            //ИНФОРМАЦИЯ ОБ ОЧЕРЕДИ
                            case TerminalAction.Info:
                                provider.OutputData.NumberQueue   = provider.InputData.NumberQueue;
                                provider.OutputData.CountElement  = (ushort)QueueVilage.Count;
                                provider.OutputData.NumberElement = (ushort)(TicketFactoryVilage.GetCurrentTicketNumber + 1);
                                provider.OutputData.AddedTime     = DateTime.Now;
                                break;

                            //ДОБАВИТЬ БИЛЕТ В ОЧЕРЕДЬ
                            case TerminalAction.Add:
                                ticket = TicketFactoryVilage.Create((ushort)QueueVilage.Count);

                                provider.OutputData.NumberQueue   = provider.InputData.NumberQueue;
                                provider.OutputData.CountElement  = ticket.CountElement;
                                provider.OutputData.NumberElement = (ushort)ticket.NumberElement;
                                provider.OutputData.AddedTime     = ticket.AddedTime;

                                QueueVilage.Enqueue(ticket);
                                break;
                            }
                            break;

                        //ДАЛЬНЕГО СЛЕДОВАНИЯ КАССЫ
                        case 2:
                            switch (provider.InputData.Action)
                            {
                            //ИНФОРМАЦИЯ ОБ ОЧЕРЕДИ
                            case TerminalAction.Info:
                                provider.OutputData.NumberQueue   = provider.InputData.NumberQueue;
                                provider.OutputData.CountElement  = (ushort)QueueLong.Count;
                                provider.OutputData.NumberElement = (ushort)(TicketFactoryLong.GetCurrentTicketNumber + 1);
                                provider.OutputData.AddedTime     = DateTime.Now;
                                break;

                            //ДОБАВИТЬ БИЛЕТ В ОЧЕРЕДЬ
                            case TerminalAction.Add:
                                ticket = TicketFactoryLong.Create((ushort)QueueLong.Count);

                                provider.OutputData.NumberQueue   = provider.InputData.NumberQueue;
                                provider.OutputData.CountElement  = ticket.CountElement;
                                provider.OutputData.NumberElement = (ushort)ticket.NumberElement;
                                provider.OutputData.AddedTime     = ticket.AddedTime;

                                QueueLong.Enqueue(ticket);
                                break;
                            }
                            break;
                        }
                    }
                }
            };


            //СОЗДАНИЕ КАССИРОВ------------------------------------------------------------------------------------------------
            foreach (var xmlCash in xmlCashier)
            {
                var casher = new Сashier(xmlCash.Id, (xmlCash.Prefix == "A") ? QueueVilage : QueueLong, xmlCash.MaxCountTryHanding);
                DeviceCashiers.Add(new DeviceCashier(casher));
            }


            //СОЗДАНИЕ ПОСЛЕД. ПОРТА ДЛЯ ОПРОСА КАССИРОВ-----------------------------------------------------------------------
            MasterSerialPort       = new MasterSerialPort(xmlSerial);
            CashierExchangeService = new CashierExchangeService(DeviceCashiers, xmlSerial.TimeRespoune);
            MasterSerialPort.AddFunc(CashierExchangeService.ExchangeService);
            MasterSerialPort.PropertyChanged += (o, e) =>
            {
                var port = o as MasterSerialPort;
                if (port != null)
                {
                    if (e.PropertyName == "StatusString")
                    {
                        ErrorString = port.StatusString;
                    }
                }
            };
        }
示例#3
0
 public void Dispose()
 {
     Listener?.Dispose();
     MasterSerialPort?.Dispose();
 }
示例#4
0
        public async Task ExchangeService(MasterSerialPort port, CancellationToken ct)
        {
            if (port == null)
            {
                return;
            }

            foreach (var devCashier in _deviceCashiers)              //Запуск опроса кассиров
            {
                var readProvider = new Server2CashierReadDataProvider {
                    InputData = devCashier.Cashier.Id
                };
                devCashier.DataExchangeSuccess = await port.DataExchangeAsync(_timeRespone, readProvider, ct);

                if (!devCashier.IsConnect)
                {
                    devCashier.Cashier.DisconectHandling();
                    continue;
                }

                if (readProvider.IsOutDataValid)
                {
                    TicketItem item;
                    var        cashierInfo = readProvider.OutputData;

                    if (!cashierInfo.IsWork)
                    {
                        continue;
                    }

                    switch (cashierInfo.Handling)
                    {
                    case CashierHandling.IsSuccessfulHandling:
                        devCashier.Cashier.SuccessfulHandling();
                        break;

                    case CashierHandling.IsErrorHandling:
                        devCashier.Cashier.ErrorHandling();
                        break;

                    case CashierHandling.IsStartHandling:
                        item = devCashier.Cashier.StartHandling();
                        var writeProvider = new Server2CashierWriteDataProvider {
                            InputData = item
                        };
                        await port.DataExchangeAsync(_timeRespone, writeProvider, ct);

                        if (writeProvider.IsOutDataValid)                    //завершение транзакции ( успешная передача билета кассиру)
                        {
                            devCashier.Cashier.SuccessfulStartHandling();
                        }
                        break;

                    case CashierHandling.IsSuccessfulAndStartHandling:
                        devCashier.Cashier.SuccessfulHandling();

                        item          = devCashier.Cashier.StartHandling();
                        writeProvider = new Server2CashierWriteDataProvider {
                            InputData = item
                        };
                        await port.DataExchangeAsync(_timeRespone, writeProvider, ct);

                        if (writeProvider.IsOutDataValid)                    //завершение транзакции ( успешная передача билета кассиру)
                        {
                            devCashier.Cashier.SuccessfulStartHandling();
                        }
                        break;

                    case CashierHandling.IsErrorAndStartHandling:
                        devCashier.Cashier.ErrorHandling();

                        item          = devCashier.Cashier.StartHandling();
                        writeProvider = new Server2CashierWriteDataProvider {
                            InputData = item
                        };
                        await port.DataExchangeAsync(_timeRespone, writeProvider, ct);

                        if (writeProvider.IsOutDataValid)                    //завершение транзакции ( успешная передача билета кассиру)
                        {
                            devCashier.Cashier.SuccessfulStartHandling();
                        }
                        break;

                    default:
                        item = null;
                        break;
                    }
                }
            }

            //Отправка запроса синхронизации времени раз в час
            if (_lastSyncLabel != DateTime.Now.Hour)
            {
                _lastSyncLabel = DateTime.Now.Hour;

                var syncTimeProvider = new Server2CashierSyncTimeDataProvider();
                await port.DataExchangeAsync(_timeRespone, syncTimeProvider, ct);
            }
        }
示例#5
0
        public async Task ExchangeService(MasterSerialPort port, CancellationToken ct)
        {
            if (port == null)
            {
                return;
            }

            try
            {
                foreach (var devCashier in _deviceCashiers)                                                                                                                                                                                                                                                                        //Запуск опроса кассиров
                {
                    _loggerCashierInfo.Info($"---------------------------КАССИР: Id= {devCashier.Cashier.Id}   CurrentTicket= {(devCashier.Cashier.CurrentTicket != null ? devCashier.Cashier.CurrentTicket.Prefix + devCashier.Cashier.CurrentTicket.NumberElement.ToString("000") : "НЕТ")}----------------------------------"); //LOG;

                    var readProvider = new Server2CashierReadDataProvider(devCashier.AddresDevice, _logName);
                    devCashier.DataExchangeSuccess = await port.DataExchangeAsync(_timeRespone, readProvider, ct);

                    if (!devCashier.IsConnect)
                    {
                        _loggerCashierInfo.Info($"кассир НЕ на связи: Id= {devCashier.Cashier.Id}");//LOG;
                        devCashier.LastSyncLabel = 0;
                        continue;
                    }

                    if (readProvider.IsOutDataValid)
                    {
                        TicketItem item;
                        var        cashierInfo = readProvider.OutputData;

                        //Если устойство было не на связи, то Отправка запроса синхронизации времени раз в час, будет произведенна мгновенно.
                        if (devCashier.LastSyncLabel != DateTime.Now.Hour)
                        {
                            devCashier.LastSyncLabel = DateTime.Now.Hour;
                            var syncTimeProvider = new Server2CashierSyncTimeDataProvider(_logName);
                            await port.DataExchangeAsync(_timeRespone, syncTimeProvider, ct);
                        }

                        //TODO: проверить
                        if (!cashierInfo.IsWork)
                        {
                            //Если кассир быстро закрыла сессию (до того как опрос порта дошел до нее), то билет из обработки надо убрать.
                            if (devCashier.Cashier.CurrentTicket != null)
                            {
                                _loggerCashierInfo.Info($"Команда от кассира: Id= {devCashier.Cashier.Id}   Handling=\"Если кассир быстро закрыла сессию(до того как опрос порта дошел до нее). НО У НЕЕ БЫЛ ТЕКУЩИЙ ОБРАБАТЫВАЕМЫЙ БИЛЕТ\"    NameTicket= {cashierInfo.NameTicket}");//LOG;
                                //devCashier.Cashier.SuccessfulHandling();
                            }
                            continue;
                        }

                        switch (cashierInfo.Handling)
                        {
                        case CashierHandling.IsSuccessfulHandling:
                            if (!devCashier.Cashier.CanHandling)
                            {
                                break;
                            }
                            devCashier.Cashier.SuccessfulHandling();
                            break;


                        case CashierHandling.IsErrorHandling:
                            if (!devCashier.Cashier.CanHandling)
                            {
                                break;
                            }
                            devCashier.Cashier.ErrorHandling();
                            break;


                        case CashierHandling.IsStartHandling:
                            await WriteTicketTransaction(devCashier, cashierInfo.Handling, port, ct);

                            break;


                        case CashierHandling.IsSuccessfulAndStartHandling:
                            devCashier.Cashier.SuccessfulHandling();
                            await WriteTicketTransaction(devCashier, cashierInfo.Handling, port, ct);

                            break;


                        case CashierHandling.IsRedirectAndStartHandling:
                            if (_adminCashier != null)
                            {
                                var redirectTicket = devCashier.Cashier.CurrentTicket;
                                if (redirectTicket != null)
                                {
                                    _adminCashier.Cashier.AddRedirectedTicket(redirectTicket);
                                }

                                devCashier.Cashier.SuccessfulHandling();
                                await WriteTicketTransaction(devCashier, cashierInfo.Handling, port, ct);
                            }
                            break;


                        case CashierHandling.IsErrorAndStartHandling:
                            devCashier.Cashier.ErrorHandling();
                            await WriteTicketTransaction(devCashier, cashierInfo.Handling, port, ct);

                            break;


                        case CashierHandling.IsRedirectHandling:
                            if (_adminCashier != null)
                            {
                                if (!devCashier.Cashier.CanHandling)
                                {
                                    break;
                                }
                                var redirectTicket = devCashier.Cashier.CurrentTicket;
                                if (redirectTicket != null)
                                {
                                    _adminCashier.Cashier.AddRedirectedTicket(redirectTicket);
                                }
                                devCashier.Cashier.SuccessfulHandling();
                            }
                            break;

                        default:
                            item = null;
                            break;
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                _loggerCashierInfo.Info($"EXCEPTION CashierExchangeService:   {ex.ToString()}");
            }
        }
示例#6
0
        /// <summary>
        /// Транзакция на передачу билета кассиру.
        /// </summary>
        private async Task <bool> WriteTicketTransaction(DeviceCashier devCashier, CashierHandling handling, MasterSerialPort port, CancellationToken ct)
        {
            var item = devCashier.Cashier.StartHandling();

            if (item == null)                         //БЛОКИРОВКА ТРАНЗАКЦИИ (билет уже используетсяв транзакции)
            {
                return(false);
            }

            var writeProvider = new Server2CashierWriteDataProvider(devCashier.AddresDevice, _logName)
            {
                InputData = item
            };
            await port.DataExchangeAsync(_timeRespone, writeProvider, ct);

            if (writeProvider.IsOutDataValid)        //ТРАНЗАКЦИЯ ЗАВЕРШЕНА УСПЕШНО  (извлечем билет из очереди и присвоим кассиру)
            {
                devCashier.Cashier.StartHandlingSuccessful();
            }
            else                                     //ТРАНЗАКЦИЯ ЗАВЕРШЕНА С ОШИБКОЙ (снимем блокировку)
            {
                _loggerCashierInfo.Info($"НЕ УДАЧНАЯ ТРАНЗАКЦИЯ ПЕРЕДАЧИ БИЛЕТА КАССИРУ: Id= {devCashier.Cashier.Id}   НА КОМАНДУ={handling}");
                devCashier.Cashier.StartHandlingFaild();
                return(false);
            }
            return(true);
        }
        public void LoadSetting()
        {
            //ЗАГРУЗКА НАСТРОЕК----------------------------------------------------------------
            XmlListenerSettings       xmlListener;
            IList <XmlSerialSettings> xmlSerials;
            List <XmlCashierSettings> xmlCashier;
            List <XmlQueuesSettings>  xmlQueues;

            try
            {
                var xmlFile = XmlWorker.LoadXmlFile("Settings", "Setting.xml"); //все настройки в одном файле
                if (xmlFile == null)
                {
                    return;
                }

                xmlListener = XmlListenerSettings.LoadXmlSetting(xmlFile);
                xmlSerials  = XmlSerialSettings.LoadXmlSetting(xmlFile).ToList();
                xmlCashier  = XmlCashierSettings.LoadXmlSetting(xmlFile);
                xmlQueues   = XmlQueuesSettings.LoadXmlSetting(xmlFile);
            }
            catch (FileNotFoundException ex)
            {
                ErrorString = ex.ToString();
                return;
            }
            catch (Exception ex)
            {
                ErrorString = "ОШИБКА в узлах дерева XML файла настроек:  " + ex;
                return;
            }

            //РАЗРЕШИТЬ ЛОГГИРОВАНИЕ-----------------------------------------------------------
            Log.EnableLogging(true);

            //СОЗДАНИЕ ОЧЕРЕДИ-----------------------------------------------------------------------
            foreach (var xmlQueue in xmlQueues)
            {
                var queue = new QueuePriority(xmlQueue.Name, xmlQueue.Prefixes);
                QueuePriorities.Add(queue);
            }


            //СОЗДАНИЕ СЛУШАТЕЛЯ ДЛЯ ТЕРМИНАЛОВ-------------------------------------------------------
            Listener         = new ListenerTcpIp(xmlListener);
            ProviderTerminal = new Server2TerminalExchangeDataProvider(isSynchronized: true);
            ProviderTerminal.PropertyChanged += (o, e) =>
            {
                var provider = o as Server2TerminalExchangeDataProvider;
                if (provider != null)
                {
                    if (e.PropertyName == "InputData")
                    {
                        try
                        {
                            provider.OutputData = provider.OutputData ?? new TerminalOutData();

                            //Найдем очередь к которой обращен запрос
                            var prefixQueue = provider.InputData.PrefixQueue;
                            var nameQueue   = provider.InputData.NameQueue;
                            var queue       = QueuePriorities.FirstOrDefault(q => string.Equals(q.Name, nameQueue, StringComparison.InvariantCultureIgnoreCase));

                            if (queue == null)
                            {
                                return;
                            }

                            switch (provider.InputData.Action)
                            {
                            //ИНФОРМАЦИЯ ОБ ОЧЕРЕДИ
                            case TerminalAction.Info:
                                provider.OutputData.PrefixQueue   = provider.InputData.PrefixQueue;
                                provider.OutputData.CountElement  = (ushort)queue.GetInseartPlace(prefixQueue);
                                provider.OutputData.NumberElement = (ushort)(queue.GetCurrentTicketNumber + 1);
                                provider.OutputData.AddedTime     = DateTime.Now;
                                break;

                            //ДОБАВИТЬ БИЛЕТ В ОЧЕРЕДЬ
                            case TerminalAction.Add:
                                var ticket = queue.CreateTicket(prefixQueue);

                                provider.OutputData.PrefixQueue   = provider.InputData.PrefixQueue;
                                provider.OutputData.CountElement  = ticket.CountElement;
                                provider.OutputData.NumberElement = (ushort)ticket.NumberElement;
                                provider.OutputData.AddedTime     = ticket.AddedTime;
                                queue.Enqueue(ticket);
                                var logMessage = $"ДОБАВИТЬ БИЛЕТ В ОЧЕРЕДЬ (команда от терминала): {ticket.ToString()}   ";
                                _logQueueInput.Info(logMessage);
                                break;
                            }
                        }
                        catch (Exception ex)
                        {
                            _logQueueInput.Error($"Server2TerminalExchangeDataProvider:   {ex.ToString()}");
                        }
                    }
                }
            };

            //DEBUG------ИНИЦИАЛИЗАЦИЯ ОЧЕРЕДИ---------------------
            //Обязательно коментировать  _model.LoadStates(); иначе состояние очереди затрется
            //var queueTemp = QueuePriorities.FirstOrDefault(q => string.Equals(q.Name, "Main", StringComparison.InvariantCultureIgnoreCase));
            //var queueAdmin = QueuePriorities.FirstOrDefault(q => string.Equals(q.Name, "Admin", StringComparison.InvariantCultureIgnoreCase));
            //for (int i = 0; i < 200; i++)
            //{
            //    var ticketAdmin = queueTemp.CreateTicket("А");
            //    queueAdmin.Enqueue(ticketAdmin);

            //    var ticket = queueTemp.CreateTicket("К");
            //    queueTemp.Enqueue(ticket);

            //    ticket = queueTemp.CreateTicket("К");
            //    queueTemp.Enqueue(ticket);

            //    ticket = queueTemp.CreateTicket("Г");
            //    queueTemp.Enqueue(ticket);

            //    ticket = queueTemp.CreateTicket("И");
            //    queueTemp.Enqueue(ticket);

            //    ticket = queueTemp.CreateTicket("С");
            //    queueTemp.Enqueue(ticket);
            //}
            //DEBUG----------------------------------------------


            //СОЗДАНИЕ КАССИРОВ------------------------------------------------------------------------------------------------
            foreach (var xmlCash in xmlCashier)
            {
                var queue = QueuePriorities.FirstOrDefault(q => q.Name == xmlCash.NameQueue);
                if (queue != null)
                {
                    var logName = "Server.CashierInfo_" + xmlCash.Port;
                    var casher  = new Сashier(xmlCash.Id, xmlCash.Prefixs, queue, xmlCash.MaxCountTryHanding, logName);
                    DeviceCashiers.Add(new DeviceCashier(xmlCash.AddressDevice, casher, xmlCash.Port));
                }
            }
            AdminCasher = DeviceCashiers.FirstOrDefault(d => d.Cashier.Prefixes.Contains("А"));


            //СОЗДАНИЕ ПОСЛЕД. ПОРТА ДЛЯ ОПРОСА КАССИРОВ-----------------------------------------------------------------------
            var cashersGroup = DeviceCashiers.GroupBy(d => d.Port).ToDictionary(group => group.Key, group => group.ToList());  //принадлежность кассира к порту

            foreach (var xmlSerial in xmlSerials)
            {
                var logName     = "Server.CashierInfo_" + xmlSerial.Port;
                var sp          = new MasterSerialPort(xmlSerial, logName);
                var cashiers    = cashersGroup[xmlSerial.Port];
                var cashierExch = new CashierExchangeService(cashiers, AdminCasher, xmlSerial.TimeRespoune, logName);
                sp.AddFunc(cashierExch.ExchangeService);
                //sp.PropertyChanged += (o, e) =>
                // {
                //     var port = o as MasterSerialPort;
                //     if (port != null)
                //     {
                //         if (e.PropertyName == "StatusString")
                //         {
                //             ErrorString = port.StatusString;                     //TODO: РАЗДЕЛЯЕМЫЙ РЕСУРС возможно нужна блокировка
                //        }
                //     }
                // };
                MasterSerialPorts.Add(sp);
                CashierExchangeServices.Add(cashierExch);
            }
        }