/// <summary> /// Task which is used for listening to incoming connection. /// </summary> private void ListenIncomingConnection() { while (true) { if (!_isTaskRunning) { continue; } if (_tcpListener == null) { continue; } // Wait the thread for signal. _manualResetListenerEvent.WaitOne(); try { // Accept one connection at one time. using (var tcpClient = _tcpListener.AcceptTcpClient()) using (var stream = tcpClient.GetStream()) { // Read buffer from stream. var buffer = new byte[64]; var rb = stream.Read(buffer, 0, buffer.Length); if (rb != 64) { continue; } // Read commands sent from external. var content = Encoding.UTF8.GetString(buffer, 0, buffer.Length); content = content.Trim(); if (string.IsNullOrEmpty(content)) { continue; } var information = $"(Port: {_terminalSetting.Value.Incoming.Port}) Received message: {content} from external component - {rb} bytes received"; Message.InitiateMessage(DateTime.Now, MessageType.Receive, "Received message", content); Log.Info(information); // Parse terminal message obtained from external terminal. var terminalMessage = TerminalMessage.Parse(content, false); if (terminalMessage == null) { Message.InitiateMessage(DateTime.Now, MessageType.Information, $"Incoming message is incorrect. Restart listener in {Setting.CommandScanTaskInterval} millisecs."); Thread.Sleep(Setting.CommandScanTaskInterval); continue; } if ("5000".Equals(terminalMessage.CommandIndex)) { continue; } // Display message to screen. Log.Info("Command sending process is blocked for analyzing listening process."); //Message.InitiateMessage(DateTime.Now, MessageType.Information, "Command sending process is blocked for analyzing listening process."); try { // ProceedIncommingCommand incoming automated warehouse controller command if (TerminalName.Material.Equals(_terminalSetting.Key)) { MaterialAutoWarehouseController.ProceedIncommingCommand(terminalMessage, AutoController.MaterialAutoWarehouseDeviceCode); // Remove command from cache MaterialAutoWarehouseController.RemoveCommand(x => x.IsAck && x.CommandIndex.Equals(terminalMessage.CommandIndex, StringComparison.InvariantCultureIgnoreCase) && x.CommandSequence.Equals(terminalMessage.CommandSequence, StringComparison.InvariantCultureIgnoreCase)); } else if (TerminalName.PreProduct.Equals(_terminalSetting.Key)) { if ("0100".Equals(terminalMessage.Command) || "0101".Equals(terminalMessage.Command)) { PreProductAutoWarehouseController.ProceedIncommingCommand(terminalMessage, AutoController.PreProductAutoWarehouseDeviceCode); } // Remove command from cache PreProductAutoWarehouseController.RemoveCommand(x => x.IsAck && x.CommandIndex.Equals(terminalMessage.CommandIndex, StringComparison.InvariantCultureIgnoreCase) && x.CommandSequence.Equals(terminalMessage.CommandSequence, StringComparison.InvariantCultureIgnoreCase)); } else if (TerminalName.Product.Equals(_terminalSetting.Key)) { ProductAutoWarehouseController.ProceedIncommingCommand(terminalMessage, AutoController.ProductAutoWarehouseDeviceCode); // Remove command from cache ProductAutoWarehouseController.RemoveCommand(x => x.IsAck && x.CommandIndex.Equals(terminalMessage.CommandIndex, StringComparison.InvariantCultureIgnoreCase) && x.CommandSequence.Equals(terminalMessage.CommandSequence, StringComparison.InvariantCultureIgnoreCase)); } Message.InitiateMessage(DateTime.Now, MessageType.Information, $"Command: {content} has been proceeded. Restart listener in {Setting.CommandScanTaskInterval} millisecs."); Thread.Sleep(Setting.CommandScanTaskInterval); } catch (Exception exception) { Log.Error(exception.Message, exception); Message.InitiateMessage(DateTime.Now, MessageType.Error, $"Command: {content} hasn't been proceeded. Restart listener in {Setting.CommandScanTaskInterval} millisecs."); Thread.Sleep(Setting.CommandScanTaskInterval); } } } catch (Exception exception) { Log.Error(exception.Message, exception); } Message.InitiateMessage(DateTime.Now, MessageType.Information, "Command sending process is unblocked."); } }
/// <summary> /// Task which is used for scanning pending commands and broadcast to external terminals. /// </summary> private void SearchWarehousePendingCommands() { while (true) { // Task is not allowed to run. if (!_isTaskRunning) { Thread.Sleep(Setting.CommandScanTaskInterval); continue; } // Wait for signal from another thread to start this one. _manualResetScannerEvent.WaitOne(); try { // Message will be built base on the being activated automated warehouse controller. var message = ""; #region Message construction // Operating warehouse controller is material. if (TerminalName.Material.Equals(_terminalSetting.Key)) { #region Automated warehouse status validation. // No material warehouse controller has been configured in application setting file. if (string.IsNullOrEmpty(AutoController.MaterialAutoWarehouseDeviceCode)) { Message.InitiateMessage(DateTime.Now, MessageType.Information, $"No material warehouse controller device code has been configured into application setting file. Restart in {Setting.CommandScanTaskInterval} milliseconds."); // Sleep the thread for 3 secs. Thread.Sleep(Setting.CommandScanTaskInterval); continue; } // Material auto warehouse controller is offline. if (!MaterialAutoWarehouseController.IsAutoWarehouseOnline(AutoController.MaterialAutoWarehouseDeviceCode)) { Message.InitiateMessage(DateTime.Now, MessageType.Information, $"Material automated warehouse is offline. Restart in {Setting.CommandScanTaskInterval} milliseconds."); // Sleep the thread for awhile. Thread.Sleep(Setting.CommandScanTaskInterval); continue; } #endregion #region Message initialization try { // Find pending material command in database. var commands = AutoController.FindPendingMaterialCommands(); // Command is not valid. if (commands == null || commands.Count < 1) { //Message.InitiateMessage(DateTime.Now, MessageType.Information, //$"No pending command has been found. Broadcaster will be restarted in {Setting.CommandScanTaskInterval} milliseconds."); Thread.Sleep(Setting.CommandScanTaskInterval); continue; } // ProceedIncommingCommand database records. MaterialAutoWarehouseController.ProcessDataBase(commands, AutoController.MaterialAutoWarehouseDeviceCode, _terminalSetting.Value.Outgoing); Thread.Sleep(Setting.CommandScanTaskInterval); continue; } catch (Exception exception) { Log.Error(exception.Message, exception); Message.InitiateMessage(DateTime.Now, MessageType.Error, exception.Message); Thread.Sleep(Setting.CommandScanTaskInterval); continue; } #endregion } else if (TerminalName.PreProduct.Equals(_terminalSetting.Key)) { using (var context = new KCSGDbContext()) using (var unitOfWork = new UnitOfWork(context)) { // delete off empty command var preProduct = unitOfWork.PreProductWarehouseCommandRepository.GetMany( i => i.F50_From.Trim().Equals("")) .FirstOrDefault(); if (preProduct != null) { unitOfWork.PreProductWarehouseCommandRepository.Delete(preProduct); unitOfWork.Commit(); } } #region Automated warehouse status validation. // No material warehouse controller has been configured in application setting file. if (string.IsNullOrEmpty(AutoController.PreProductAutoWarehouseDeviceCode)) { Message.InitiateMessage(DateTime.Now, MessageType.Information, $"No pre-product warehouse controller device code has been configured into application setting file. Restart in {Setting.CommandScanTaskInterval} milliseconds."); // Sleep the thread for 3 secs. Thread.Sleep(3000); continue; } // Material auto warehouse controller is offline. if (!PreProductAutoWarehouseController.IsAutoWarehouseOnline(AutoController.PreProductAutoWarehouseDeviceCode)) { Message.InitiateMessage(DateTime.Now, MessageType.Information, $"Pre-product automated warehouse is offline. Restart in {Setting.CommandScanTaskInterval} milliseconds."); // Sleep the thread for awhile. Thread.Sleep(Setting.CommandScanTaskInterval); continue; } #endregion #region Pre-product initialization try { var commands = AutoController.FindPendingPreProductCommands(); if (commands == null || commands.Count < 1) { //Message.InitiateMessage(DateTime.Now, MessageType.Information, //$"No pending command has been found. Listener will be restarted in {Setting.CommandScanTaskInterval} milliseconds."); Thread.Sleep(Setting.CommandScanTaskInterval); continue; } // ProceedIncommingCommand messages list. PreProductAutoWarehouseController.ProceedMessages(commands, AutoController.PreProductAutoWarehouseDeviceCode, _terminalSetting.Value.Outgoing); Thread.Sleep(Setting.CommandScanTaskInterval); } catch (Exception exception) { Log.Error(exception.Message, exception); Message.InitiateMessage(DateTime.Now, MessageType.Error, exception.Message); } #endregion } else if (TerminalName.Product.Equals(_terminalSetting.Key)) { #region Automated warehouse status validation. // No material warehouse controller has been configured in application setting file. if (string.IsNullOrEmpty(AutoController.ProductAutoWarehouseDeviceCode)) { Message.InitiateMessage(DateTime.Now, MessageType.Information, $"No product warehouse controller device code has been configured into application setting file. Restart in {Setting.CommandScanTaskInterval} milliseconds."); // Sleep the thread for 3 secs. Thread.Sleep(3000); continue; } // Material auto warehouse controller is offline. if (!ProductAutoWarehouseController.IsAutoWarehouseOnline(AutoController.ProductAutoWarehouseDeviceCode)) { Message.InitiateMessage(DateTime.Now, MessageType.Information, $"Product automated warehouse is offline. Restart in {Setting.CommandScanTaskInterval} milliseconds."); // Sleep the thread for awhile. Thread.Sleep(Setting.CommandScanTaskInterval); continue; } #endregion #region Products initialization try { // TODO: Disabled it at 2017-05-17 (Consider enable it back) //var commands = AutoController.FindPendingProductCommands(); //if (commands == null || commands.Count < 1) //{ // //Message.InitiateMessage(DateTime.Now, MessageType.Information, // //$"No pending command has been found. Listener will be restarted in {Setting.CommandScanTaskInterval} milliseconds."); // Thread.Sleep(Setting.CommandScanTaskInterval); // continue; //} //ProductAutoWarehouseController.ProcessDataList(commands, // AutoController.ProductAutoWarehouseDeviceCode, _terminalSetting.Value.Outgoing); //Thread.Sleep(Setting.CommandScanTaskInterval); var command = AutoController.FindPendingProductCommands().FirstOrDefault(); if (command == null) { Thread.Sleep(Setting.CommandScanTaskInterval); continue; } ProductAutoWarehouseController.ProcessDataList(new[] { command }, AutoController.ProductAutoWarehouseDeviceCode, _terminalSetting.Value.Outgoing); Thread.Sleep(Setting.CommandScanTaskInterval); } catch (Exception exception) { Log.Error(exception.Message, exception); Message.InitiateMessage(DateTime.Now, MessageType.Error, exception.Message); } #endregion } else { Message.InitiateMessage(DateTime.Now, MessageType.Error, $"Material, Pre-Product, Product should be selected to broadcast message. Restart message broadcaster in {Setting.CommandScanTaskInterval} milliseconds."); Thread.Sleep(Setting.CommandScanTaskInterval); continue; } #endregion } catch (EntityException entityException) { Log.Error(entityException.Message, entityException); Message.ShowMessageBox(View.FindView(), "There is something wrong with database. Please check database configuration in configuration file.", "System Message", MessageBoxButton.OK, MessageBoxImage.Error, MessageBoxResult.OK); Application.Current.Dispatcher.Invoke(() => { IsTaskRunning = false; }); } catch (Exception exception) { Log.Error(exception.Message, exception); } } }
/// <summary> /// Callback which is fired when start button is clicked. /// </summary> /// <param name="owner"></param> public void ExecuteClickToggle(Window owner) { // Listening progress is not running. if (!_isTaskRunning) { var terminalSetting = _terminalSetting.Value; var incoming = terminalSetting.Incoming; var outgoing = terminalSetting.Outgoing; // Update IP Endpoint. IPEndPoint endPoint; try { endPoint = new IPEndPoint(IPAddress.Any, incoming.Port); } catch (Exception exception) { Log.Error(exception.Message, exception); Message.ShowMessageBox(owner, "Incoming message IP Endpoint is not valid.", "System Message", MessageBoxButton.OK, MessageBoxImage.Error, MessageBoxResult.OK); return; } try { // Tcp listener has been initialized. if (_tcpListener != null) { _tcpListener.Stop(); } // Initiate tcp listener. _tcpListener = new TcpListener(terminalSetting.Incoming.Port); // Start the listener. _tcpListener.Start(); } catch (Exception exception) { Log.Error(exception.Message, exception); Message.ShowMessageBox(owner, "Something is wrong while listener opens.", "System Message", MessageBoxButton.OK, MessageBoxImage.Error, MessageBoxResult.OK); return; } // Clear all caches and messages. Message.ClearMessages(); PreProductAutoWarehouseController.ClearQueue(); MaterialAutoWarehouseController.ClearQueue(); ProductAutoWarehouseController.ClearQueue(); // Update window state. IsTaskRunning = true; // Signal threads. _manualResetListenerEvent.Set(); _manualResetScannerEvent.Set(); _manualResetStatusRequest.Set(); // Display message to UI. Message.InitiateMessage(DateTime.Now, MessageType.Information, $"Listener has been opened at {incoming.Address}:{incoming.Port}."); Message.InitiateMessage(DateTime.Now, MessageType.Information, $"Pending commands scanner has been initialized at port {outgoing.Address}:{outgoing.Port}."); return; } //UninitiateIncomingMessageListeningTask(); _manualResetListenerEvent.Reset(); Message.InitiateMessage(DateTime.Now, MessageType.Information, "Listener has been manually stopped."); //UninitiatePendingCommandScanningTask(); _manualResetScannerEvent.Reset(); Message.InitiateMessage(DateTime.Now, MessageType.Information, "Scanning pending command task was manually stopped."); _manualResetStatusRequest.Reset(); IsTaskRunning = false; }