/// <summary> /// Find the automated pre-product warehouse command with the highest priority. /// </summary> /// <returns></returns> public IList <TX50_PrePdtWhsCmd> FindPendingPreProductCommands() { // Initiate unit of work instance. using (var context = new KCSGDbContext()) using (var unitOfWork = new UnitOfWork(context)) { var autoWarehousePreProduct = PreProductAutoWarehouseDeviceCode; if (autoWarehousePreProduct == null) { return(null); } var autoWarehousePreProductDevice = unitOfWork.DeviceRepository.GetById(autoWarehousePreProduct); if (!"0".Equals(autoWarehousePreProductDevice.F14_DeviceStatus)) { throw new Exception("Automated warehouse pre-product is offline."); } var pendingCommands = unitOfWork.PreProductWarehouseCommandRepository.GetAll(); pendingCommands = pendingCommands.Where(i => i.F50_Status.Trim().Equals("0") || i.F50_Status.Trim().Equals("1") || i.F50_Status.Trim().Equals("2") || i.F50_Status.Trim().Equals("4") || i.F50_Status.Trim().Equals("5")) .OrderByDescending(i => i.F50_Priority) .ThenByDescending(i => i.F50_Status); return(pendingCommands.ToList()); } }
/// <summary> /// Check whether auto warehouse controller is enabled or not. /// </summary> /// <param name="autoWarehouseDevice"></param> /// <returns></returns> public bool IsAutoWarehouseOnline(string autoWarehouseDevice) { using (var context = new KCSGDbContext()) using (var unitOfWork = new UnitOfWork(context)) { var autoWarehouseMaterialDevice = unitOfWork.DeviceRepository.GetById(autoWarehouseDevice); return(AutoControllerStatus.Online.Equals(autoWarehouseMaterialDevice.F14_DeviceStatus)); } }
/// <summary> /// Find the automated material warehouse command with highest priority. /// </summary> /// <returns></returns> public IList <TX34_MtrWhsCmd> FindPendingMaterialCommands() { // Initiate unit of work instance. using (var context = new KCSGDbContext()) using (var unitOfWork = new UnitOfWork(context)) { var pendingCommands = unitOfWork.MaterialWarehouseCommandRepository.GetAll(); pendingCommands = pendingCommands.Where(i => i.F34_Status.Trim().Equals("0") || i.F34_Status.Trim().Equals("1") || i.F34_Status.Trim().Equals("2") || i.F34_Status.Trim().Equals("4") || i.F34_Status.Trim().Equals("5")) .OrderByDescending(i => i.F34_Priority) .ThenByDescending(i => i.F34_Status); return(pendingCommands.ToList()); } }
/// <summary> /// Set automated warehouse to offline mode. /// </summary> /// <param name="deviceCode"></param> public void SetAutoWarehouseOffline(string deviceCode) { using (var context = new KCSGDbContext()) using (var unitOfWork = new UnitOfWork(context)) { var device = unitOfWork.DeviceRepository.GetByDeviceCode(deviceCode); if (device != null) { device.F14_DeviceStatus = "1"; device.F14_UpdateDate = DateTime.Now; unitOfWork.DeviceRepository.Update(device); Message.InitiateMessage(DateTime.Now, MessageType.Error, "Autoware House is at error status.."); } else { Message.InitiateMessage(DateTime.Now, MessageType.Error, "Set Device Status failed"); } unitOfWork.Commit(); } }
/// <summary> /// Check whether screen is locked by another terminal or not. /// </summary> /// <param name="screen"></param> /// <returns></returns> private bool IsAccessLocked(string terminalNo) { // No screen is specified, therefore every terminal can access to 'em at any time. if (_screens == null) { return(false); } using (var context = new KCSGDbContext()) using (var unitOfWork = new UnitOfWork(context)) { // More than one screen is specified. // If one of them is access by another terminal. Block the access of the current one. var terminalStatuses = unitOfWork.TermStatusRepository.GetAll(); var conflictTerminalStatus = terminalStatuses.FirstOrDefault( x => !x.F17_TermNo.Equals(terminalNo) && _screens.Contains(x.F17_InUsePictureNo) && (x.F17_LastRequest != null)); if (conflictTerminalStatus != null && conflictTerminalStatus.F17_LastRequest != null && DateTime.Now.Subtract(conflictTerminalStatus.F17_LastRequest.Value) < TimeSpan.FromSeconds(10)) { return(true); } // Screen is not blocked by any terminals at the request time. var accesses = unitOfWork.AccessRepository.GetAll(); accesses = accesses.Where(x => _screens.Contains(x.F18_LockedPicture)); // Whether screen is locked by another terminal. return((from terminalStatus in terminalStatuses from access in accesses where terminalStatus.F17_InUsePictureNo.Equals(access.F18_LockPicture) && !terminalStatus.F17_TermNo.Equals(terminalNo) select terminalStatus).Any()); } }
/// <summary> /// This function is for parsing cookie, querying database and decide whether user can access the function or not. /// </summary> /// <param name="authorizationContext"></param> public void OnAuthorization(AuthorizationContext authorizationContext) { #if !UNAUTHORIZED_DEBUG using (var context = new KCSGDbContext()) using (var unitOfWork = new UnitOfWork(context)) { try { var loginDomain = new LoginDomain(unitOfWork); // Initiate authentication result. var authenticationResult = new AuthenticationResult(); #region Authentication cookie & ticket validation var formAuthenticationCookie = authorizationContext.RequestContext.HttpContext.Request.Cookies[FormsAuthentication.FormsCookieName]; if (formAuthenticationCookie == null) { if (IsAnonymousAllowed(authorizationContext)) { return; } FormsAuthentication.SignOut(); authorizationContext.Result = new HttpUnauthorizedResult(); Log.Error("Authentication cookie is invalid."); return; } //Cookie value is invalid if (string.IsNullOrWhiteSpace(formAuthenticationCookie.Value)) { if (IsAnonymousAllowed(authorizationContext)) { return; } // Sign the user out to clear the cookie. FormsAuthentication.SignOut(); // Treat the request as unauthorized. authorizationContext.Result = new HttpUnauthorizedResult(); Log.Error("Authentication cookie value is invalid."); return; } // Decrypt the authentication cookie value to authentication ticket instance. var formAuthenticationTicket = FormsAuthentication.Decrypt(formAuthenticationCookie.Value); // Ticket is invalid. if (formAuthenticationTicket == null) { if (IsAnonymousAllowed(authorizationContext)) { return; } // Sign the user out to clear the cookie. FormsAuthentication.SignOut(); // Treat the request as unauthorized. authorizationContext.Result = new HttpUnauthorizedResult(); Log.Error("Authentication ticket is not valid."); return; } // User data is invalid. if (string.IsNullOrWhiteSpace(formAuthenticationTicket.UserData)) { if (IsAnonymousAllowed(authorizationContext)) { return; } // Sign the user out to clear the cookie. FormsAuthentication.SignOut(); // Treat the request as unauthorized. authorizationContext.Result = new HttpUnauthorizedResult(); Log.Error("Authentication ticket's user data is invalid."); return; } #endregion #region IP Address validation // Find the user data in the ticket. var loginViewModel = JsonConvert.DeserializeObject <LoginItem>(formAuthenticationTicket.UserData); // User data is invalid. if (loginViewModel == null) { if (IsAnonymousAllowed(authorizationContext)) { return; } // Sign the user out to clear the cookie. FormsAuthentication.SignOut(); // Treat the request as unauthorized. authorizationContext.Result = new HttpUnauthorizedResult(); Log.Error("Authentication ticket information is invalid."); return; } // Find IP Address of request. var requestIpAddress = loginDomain.FindRequestIpAddress(authorizationContext.HttpContext); // Cookie doesn't come from the same origin. if (string.IsNullOrEmpty(requestIpAddress) || !requestIpAddress.Equals(loginViewModel.IpAddress)) { if (IsAnonymousAllowed(authorizationContext)) { return; } // Sign the user out to clear the cookie. FormsAuthentication.SignOut(); // Treat the request as unauthorized. authorizationContext.Result = new HttpUnauthorizedResult(); Log.Error(string.Format("Cookie doesn't come from the same origin as the request (Source: {0} - Target: {1})", loginViewModel.IpAddress, loginViewModel.Password)); return; } #endregion #region Passsword // No password is included in cookie. if (string.IsNullOrEmpty(loginViewModel.Password)) { if (IsAnonymousAllowed(authorizationContext)) { return; } // Sign the user out to clear the cookie. FormsAuthentication.SignOut(); // Treat the request as unauthorized. authorizationContext.Result = new HttpUnauthorizedResult(); Log.Error("No password is included in the cookie."); return; } // Find password setting. var passwordSetting = loginDomain.FindPasswordSetting(loginViewModel.Password); if (passwordSetting == null) { if (IsAnonymousAllowed(authorizationContext)) { return; } // Sign the user out to clear the cookie. FormsAuthentication.SignOut(); // Treat the request as unauthorized. authorizationContext.Result = new HttpUnauthorizedResult(); Log.Error(string.Format("Password {0}", loginViewModel.Password)); return; } // Find the password level. authenticationResult.PasswordLevel = passwordSetting.F16_PswdLevel; #endregion #region Terminal // Analyze client ip address. var ips = loginDomain.AnalyzeIpAddress(requestIpAddress); // Find terminal by searching ip address. var terminal = loginDomain.FindTerminalFromIpAddress(ips); // No terminal has been found in the request. if (terminal == null) { // Unauthenticated request is allowed to access function. if (IsAnonymousAllowed(authorizationContext)) { return; } // Sign the user out to clear the cookie. FormsAuthentication.SignOut(); // Treat the request as unauthorized. authorizationContext.Result = new HttpUnauthorizedResult(); Log.Error(string.Format("No terminal has been found with IP : {0}", requestIpAddress)); return; } // Update authentication result. authenticationResult.TerminalNo = terminal.F06_TerminalNo; #endregion #region Cookie authentication // Find the current system time on the server. var systemTime = DateTime.Now; // Login is successful, save the information in the cookie for future use. formAuthenticationTicket = new FormsAuthenticationTicket(1, loginDomain.AuthenticationTicketName, systemTime, systemTime.AddMinutes(30), true, JsonConvert.SerializeObject(loginViewModel)); // Initialize cookie contain the authorization ticket. var httpCookie = new HttpCookie(FormsAuthentication.FormsCookieName, FormsAuthentication.Encrypt(formAuthenticationTicket)); authorizationContext.HttpContext.Response.Cookies.Add(httpCookie); // Set credential for the HttpContext. var claimIdentity = new ClaimsIdentity(null, loginDomain.AuthenticationClaimName); claimIdentity.AddClaim(new Claim(ClientIdentities.TerminalNo, authenticationResult.TerminalNo)); claimIdentity.AddClaim(new Claim(ClientIdentities.IpAddress, requestIpAddress)); claimIdentity.AddClaim(new Claim(ClientIdentities.PasswordLevel, authenticationResult.PasswordLevel)); #endregion #region Accessible screens // Find list of accessible screens by using terminal functions & functions management. var availableScreens = loginDomain.FindAccessibleScreens(authenticationResult.TerminalNo, authenticationResult.PasswordLevel); // No screen has been found. if (availableScreens == null || availableScreens.Count < 1) { // Unauthenticated request is allowed to access function. if (IsAnonymousAllowed(authorizationContext)) { return; } // Treat the request as forbidden. authorizationContext.Result = new HttpStatusCodeResult(HttpStatusCode.Forbidden); Log.Error(string.Format("No available screen has been found for terminal {0}", authenticationResult.TerminalNo)); return; } // Update available screens list to the terminal. authenticationResult.AccessibleScreens = availableScreens; // Identity update. claimIdentity.AddClaim(new Claim(ClientIdentities.AccessibleScreens, string.Join(",", authenticationResult.AccessibleScreens))); if (_screens != null) { claimIdentity.AddClaim(new Claim(ClientIdentities.AccessingScreen, string.Join(",", _screens))); } var claimsPrincipal = new ClaimsPrincipal(claimIdentity); authorizationContext.HttpContext.User = claimsPrincipal; // At least one screen has been specified to the target controller/action. if (_screens != null && _screens.Length > 0) { // Check whether terminal can access to screen or not. var isScreenAccessible = availableScreens.Any(x => _screens.Any(y => x.Equals(y))); if (!isScreenAccessible) { // Treat the request as forbidden. authorizationContext.Result = new HttpStatusCodeResult(HttpStatusCode.Forbidden); Log.Error(string.Format("Terminal {0} cannot access to screens : {1}", authenticationResult.TerminalNo, string.Join(",", _screens))); } } // Access of terminal to screen is locked. if (IsAccessLocked(terminal.F06_TerminalNo)) { var urlHelper = new UrlHelper(HttpContext.Current.Request.RequestContext); authorizationContext.Result = new RedirectResult(urlHelper.Action("Index", "Home", new { Area = "", @isLockScreen = true })); } #endregion } catch (UnauthorizedAccessException) { authorizationContext.Result = new HttpStatusCodeResult(HttpStatusCode.Unauthorized); } } #elif UNAUTHORIZED_DEBUG #endif }
/// <summary> /// Task which is used for sending status request to external terminal. /// </summary> private void SendingStatusRequestCommands() { while (true) { // Task is not allowed to run. if (!_isTaskRunning) { Thread.Sleep(Setting.CommandScanTaskInterval); continue; } // Wait for status request. _manualResetStatusRequest.WaitOne(); var terminalMessage = new TerminalMessage(); try { // Maximum command sequence number. var maximumCommandSeq = 1; using (var context = new KCSGDbContext()) using (var unitOfWork = new UnitOfWork(context)) { // Find no manage in database. var noManage = unitOfWork.NoManageRepository.GetAll().FirstOrDefault(); if (noManage == null) { Thread.Sleep(Setting.CommandScanTaskInterval); continue; } if (TerminalName.Material.Equals(_terminalSetting.Key)) { maximumCommandSeq = noManage.F48_MtrWhsCmdNo + 1; if (maximumCommandSeq > 9999) { noManage.F48_MtrWhsCmdNo = 0; maximumCommandSeq = 0; } noManage.F48_MtrWhsCmdNo = maximumCommandSeq; } else if (TerminalName.PreProduct.Equals(_terminalSetting.Key)) { // 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(); } maximumCommandSeq = noManage.F48_PrePdtWhsCmdNo + 1; if (maximumCommandSeq > 9999) { noManage.F48_PrePdtWhsCmdNo = 0; maximumCommandSeq = 0; } noManage.F48_PrePdtWhsCmdNo = maximumCommandSeq; } else if (TerminalName.Product.Equals(_terminalSetting.Key)) { maximumCommandSeq = noManage.F48_PdtWhsCmdNo + 1; if (maximumCommandSeq > 9999) { noManage.F48_PdtWhsCmdNo = 0; maximumCommandSeq = 0; } noManage.F48_PdtWhsCmdNo = maximumCommandSeq; } // Update no manage first. unitOfWork.NoManageRepository.Update(noManage); unitOfWork.Commit(); } terminalMessage.CommandIndex = "5000"; terminalMessage.CommandSequence = maximumCommandSeq.ToString("D4"); using (var tcpClient = new TcpClient()) { var endpoint = new IPEndPoint(IPAddress.Parse(_terminalSetting.Value.Outgoing.Address), _terminalSetting.Value.Outgoing.Port); tcpClient.Connect(endpoint); //using (var stream = tcpClient.GetStream()) //using (var streamWriter = new StreamWriter(stream, new UTF8Encoding())) //{ // streamWriter.AutoFlush = true; // streamWriter.WriteLine(terminalMessage); //} using (var stream = tcpClient.GetStream()) { var bytes = Encoding.UTF8.GetBytes(terminalMessage.ToString()); stream.Write(bytes, 0, bytes.Length); stream.Flush(); } } Message.InitiateMessage(DateTime.Now, MessageType.StatusRequest, "Sent status request", terminalMessage.ToString()); } catch (Exception exception) { Message.InitiateMessage(DateTime.Now, MessageType.Error, $"Failed to send status request: {terminalMessage}"); Log.Debug(exception.Message, exception); } finally { // 2017-05-15: Disabled status request message notification. //Message.InitiateMessage(DateTime.Now, MessageType.Information, $"Status request will be sent after {CommandStatusTime} milliseconds"); Thread.Sleep(CommandStatusTime); } } }
/// <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); } } }