From ac0c20ee899f9f5c2dbb4230503f599e9a1173ec Mon Sep 17 00:00:00 2001 From: "CMS3762\\carminatini" Date: Thu, 11 Jan 2018 16:53:04 +0100 Subject: [PATCH 1/2] Added Client feature: reading configuration from Server in startup form --- Client.Config/ClientValidator.xsd | 7 +- Client.Config/Config.xml | 5 +- Client.Config/ConfigController.cs | 62 +++++----- Client.Config/SubModels/Connection.cs | 8 +- Client.Config/SubModels/VendorHmi.cs | 1 + Client.Utils/Constants.cs | 5 +- Client/Program.cs | 7 +- Client/View/MainForm.cs | 2 +- Client/View/NcWindow.cs | 163 +++++++++++++++++++------- Client/View/OpeningForm.cs | 85 +++++++++++++- 10 files changed, 249 insertions(+), 96 deletions(-) diff --git a/Client.Config/ClientValidator.xsd b/Client.Config/ClientValidator.xsd index b9d6143d..7720e05e 100644 --- a/Client.Config/ClientValidator.xsd +++ b/Client.Config/ClientValidator.xsd @@ -15,9 +15,10 @@ - + + + - @@ -25,7 +26,7 @@ - + diff --git a/Client.Config/Config.xml b/Client.Config/Config.xml index 50019c19..e0900b77 100644 --- a/Client.Config/Config.xml +++ b/Client.Config/Config.xml @@ -7,12 +7,13 @@ true - http://localhost:9000/index.html + localhost + 9000 1 false - OSAI + True diff --git a/Client.Config/ConfigController.cs b/Client.Config/ConfigController.cs index 7134a890..88fdb861 100644 --- a/Client.Config/ConfigController.cs +++ b/Client.Config/ConfigController.cs @@ -47,7 +47,8 @@ namespace Client.Config .Descendants(Constants.CONNECTION_CONFIG_KEY) .Select(x => new SubModels.Connection() { - Url = ValidateUrl(x.Element("Url").Value), + ServerUrl = ValidateServerUrl(x.Element("ServerUrl").Value), + ServerPort = ValidateServerPort(x.Element("ServerPort").Value), Id = ValidateClientID(x.Element("Id").Value), DeleteCahceFolderOnStartup = ValidateDelCache(x.Element("DeleteCahceFolderOnStartup").Value), }).FirstOrDefault(); @@ -56,8 +57,7 @@ namespace Client.Config .Descendants(Constants.VENDORHMI_CONFIG_KEY) .Select(x => new SubModels.VendorHmi() { - Enabled = ValidateOpenHmi(x.Element("Type").Value), - Type = ValidateNcType(x.Element("Type").Value) + FollowNcWindow = ValidateFollowNcWin(x.Element("FollowNcWindow").Value) }).FirstOrDefault(); Config.ExtSoftwaresConfig = xmlConfigFile @@ -72,8 +72,12 @@ namespace Client.Config IconBase64 = ExtractBase64Icon(x.Element("Path").Value), Id = SoftwareId++.ToString() } - ).ToArray(); - + ).ToArray(); + + //ReadConfig Url compositing + Config.ConnectionConfig.ReadConfigUrl = "http://" + Config.ConnectionConfig.ServerUrl + ":" + Config.ConnectionConfig.ServerPort + "/" + Constants.ConfigPage; + Config.ConnectionConfig.StartingUrl = "http://" + Config.ConnectionConfig.ServerUrl + ":" + Config.ConnectionConfig.ServerPort + "/" + Constants.StartingPage; + } private static void ValidationHandler(object sender, ValidationEventArgs e) @@ -85,13 +89,22 @@ namespace Client.Config /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// #region PROPERTIES_VALIDATOR - private static String ValidateUrl(String value) + private static String ValidateServerUrl(String value) { - Uri NewUrl; - if (Uri.TryCreate(value, UriKind.Absolute, out NewUrl) && (NewUrl.Scheme == Uri.UriSchemeHttp || NewUrl.Scheme == Uri.UriSchemeHttps || NewUrl.Scheme == Uri.UriSchemeFile || NewUrl.Scheme == ChromeScheme)) + if (!String.IsNullOrWhiteSpace(value)) return value; else - throw new Exception(@"Configuration Error: ""Connection - Url"" is not a valid URL"); + throw new Exception(@"Configuration Error: ""Connection - ServerUrl"" is not a valid URL"); + } + + + private static ushort ValidateServerPort(String value) + { + ushort Port; + if (ushort.TryParse(value, out Port)) + return Port; + else + throw new Exception(@"Configuration Error: ""Connection - ServerPort"" is not a valid Id of CMS-Client"); } @@ -155,36 +168,15 @@ namespace Client.Config throw new Exception(@"Configuration Error: ""Client - DeveloperMode"" is not a valid Boolean Type"); } - - private static Boolean ValidateOpenHmi(String value) + private static Boolean ValidateFollowNcWin(String value) { - String Nc = value.ToUpper(); - - if (Nc.Equals("NO_NC")) - return false; + Boolean FollowNc; + if (Boolean.TryParse(value, out FollowNc)) + return FollowNc; else - return true; - - } - - - - private static ushort ValidateNcType(String value) - { - String Nc = value.ToUpper(); - - if (Nc.Equals("NO_NC") || Nc.Equals("DEMO")) - return 0; - else if(Nc.Equals("FANUC")) - return 1; - else if (Nc.Equals("SIEMENS")) - return 2; - else if (Nc.Equals("OSAI")) - return 3; - else - throw new Exception(@"Configuration Error: ""VendorHmi - Type"" is not a valid NC Type"); + throw new Exception(@"Configuration Error: ""VendorHmi - FollowNcWindow"" is not a valid Boolean Type"); } diff --git a/Client.Config/SubModels/Connection.cs b/Client.Config/SubModels/Connection.cs index 51fb1cf3..e48c1964 100644 --- a/Client.Config/SubModels/Connection.cs +++ b/Client.Config/SubModels/Connection.cs @@ -8,9 +8,13 @@ namespace Client.Config.SubModels { public class Connection { - public string Url { get; set; } + public string ServerUrl { get; set; } + public ushort ServerPort { get; set; } public ushort Id { get; set; } + public string StartingUrl { get; set; } + public string ReadConfigUrl { get; set; } public Boolean DeleteCahceFolderOnStartup { get; set; } - + public Boolean BypassReadConfiguration { get; set; } + } } diff --git a/Client.Config/SubModels/VendorHmi.cs b/Client.Config/SubModels/VendorHmi.cs index 69a4302f..226ab1a4 100644 --- a/Client.Config/SubModels/VendorHmi.cs +++ b/Client.Config/SubModels/VendorHmi.cs @@ -9,6 +9,7 @@ namespace Client.Config.SubModels public class VendorHmi { public Boolean Enabled { get; set; } + public Boolean FollowNcWindow { get; set; } public ushort Type { get; set; } /* 0: Demo - 1: Fanuc - 2: Siemens - 3: Osai */ } diff --git a/Client.Utils/Constants.cs b/Client.Utils/Constants.cs index 0874e8c3..b4ea3fc5 100644 --- a/Client.Utils/Constants.cs +++ b/Client.Utils/Constants.cs @@ -21,7 +21,6 @@ namespace Client.Utils //Config Names - public const string CONFIG_KEY = "Config"; public const string CLIENT_CONFIG_KEY = "Client"; public const string CONNECTION_CONFIG_KEY = "Connection"; @@ -39,6 +38,8 @@ namespace Client.Utils //Nc States public enum NcState { HIDE = 0, SHOW = 1,READONLY = 2 }; - + public const string StartingPage = "index.html"; + public const string ConfigPage = "api/configuration/client"; + } } diff --git a/Client/Program.cs b/Client/Program.cs index 875232d8..e23538d1 100644 --- a/Client/Program.cs +++ b/Client/Program.cs @@ -41,7 +41,12 @@ namespace CMS_Client { // Read ARGS Config if (!String.IsNullOrWhiteSpace(args[0])) - Config.ConnectionConfig.Url = args[0]; + { + Config.ConnectionConfig.BypassReadConfiguration = true; + Config.ConnectionConfig.StartingUrl = args[0]; + } + else + Config.ConnectionConfig.BypassReadConfiguration = false; } diff --git a/Client/View/MainForm.cs b/Client/View/MainForm.cs index ea1a56db..749e6a7b 100644 --- a/Client/View/MainForm.cs +++ b/Client/View/MainForm.cs @@ -63,7 +63,7 @@ namespace CMS_Client.View Cursor.Current = Cursors.WaitCursor; //Load the page - Browser.LoadUrl(Config.ConnectionConfig.Url); + Browser.LoadUrl(Config.ConnectionConfig.StartingUrl); //Set the title of the window in "Loading" SetWindowTitle("Loading..."); diff --git a/Client/View/NcWindow.cs b/Client/View/NcWindow.cs index 969d38dc..b3f2384b 100644 --- a/Client/View/NcWindow.cs +++ b/Client/View/NcWindow.cs @@ -71,7 +71,8 @@ namespace CMS_Client.View private static IntPtr LastHookedHND; private static IntPtr NcHND; private static Thread CaptureThread; - + private static Thread FollowNCThread; + public static NcState State { get { return state; } } private static NcState state; @@ -210,16 +211,25 @@ namespace CMS_Client.View public static void CloseNcWindow() { Process[] processes; + int style; //Stop Following Nc StopNcFollowing(); - //If the NC is Siemens Exit from Function and let the HMI continue his life (To Be validated) + //If the NC is Siemens Exit from Function and lets the HMI to continue his life if (IsNcSiemens) { HideNcWindow(); return; } + //If FollowNcWindow is OFF, set the Border and lets the HMI to continue his life + else if (!Config.VendorHmiConfig.FollowNcWindow) + { + ShowNcWindow(); + style = GetWindowLong(ncprocess.MainWindowHandle, GWL_STYLE); + SetWindowLong(ncprocess.MainWindowHandle, GWL_STYLE, (style | WS_CAPTION | WS_THICKFRAME)); + return; + } //Kill the Process if (ncprocess != null && !ncprocess.HasExited) @@ -375,8 +385,17 @@ namespace CMS_Client.View if (CaptureThread != null) CaptureThread.Abort(); CaptureThread = new Thread(new ThreadStart(CaptureCycle)); - CaptureThread.Start(); + + //Start the new Thread of Follow-NC-Window + if (Config.VendorHmiConfig.FollowNcWindow) + { + if (FollowNCThread != null) + FollowNCThread.Abort(); + FollowNCThread = new Thread(new ThreadStart(FollowNcBehaviour)); + FollowNCThread.Start(); + } + } } @@ -386,14 +405,22 @@ namespace CMS_Client.View public static void StopNcFollowing() { //Un-parent the window - SetParent(ncprocess.MainWindowHandle, IntPtr.Zero); + if(ncprocess.MainWindowHandle != IntPtr.Zero) + SetParent(ncprocess.MainWindowHandle, IntPtr.Zero); //Detach the hook if (hhook != IntPtr.Zero) UnhookWinEvent(hhook); + //Stop the Image-Capture Thread if (CaptureThread != null) CaptureThread.Abort(); + + + //Stop the Follow-Nc Thread + if (Config.VendorHmiConfig.FollowNcWindow && FollowNCThread != null) + FollowNCThread.Abort(); + } #endregion @@ -641,6 +668,93 @@ namespace CMS_Client.View #endregion + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + #region THREAD_CYCLE_METHODS + + + //Image Capture Method + public static void CaptureCycle() + { + RECT rc = new RECT(); + Graphics gr; + bool success = false; + Bitmap bmp; + MemoryStream m = new MemoryStream(); + + try + { + while (true) + { + if (state == NcState.READONLY) + { + Thread.BeginThreadAffinity(); + m = new MemoryStream(); + String Base64Capture; + if (ncprocess != null && ncprocess.MainWindowHandle != IntPtr.Zero) + { + GetWindowRect(ncprocess.MainWindowHandle, out rc); + bmp = new Bitmap(rc.Right - rc.Left, rc.Bottom - rc.Top); + gr = Graphics.FromImage(bmp); + success = PrintWindow(ncprocess.MainWindowHandle, gr.GetHdc(), 0); + gr.ReleaseHdc(); + if (success && bmp != null) + { + bmp.Save(m, ImageFormat.Png); + Base64Capture = Convert.ToBase64String(m.ToArray()); + ncCapture = "data:image/png;base64," + Base64Capture; + } + m.Dispose(); + bmp.Dispose(); + gr.Dispose(); + } + else + ncCapture = "data:image/png;base64,"; + + Thread.EndThreadAffinity(); + } + Thread.Sleep(500); + } + } + catch (ThreadAbortException) { } + } + + + //NC Following Method + public static void FollowNcBehaviour() + { + try + { + while (true) + { + if (Process.GetProcessesByName(processname).Length == 0) + { + //Un-parent the window + if (ncprocess.MainWindowHandle != IntPtr.Zero) + SetParent(ncprocess.MainWindowHandle, IntPtr.Zero); + + //Detach the hook + if (hhook != IntPtr.Zero) + UnhookWinEvent(hhook); + + //Stop the Image-Capture Thread + if (CaptureThread != null) + CaptureThread.Abort(); + + //Show Task Bar + ShowTaskBar(); + + //Exit from Application + Environment.Exit(0); + } + + Thread.Sleep(1000); + } + } + catch (ThreadAbortException) { } + } + + #endregion + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// #region WIN32_METHODS @@ -810,47 +924,8 @@ namespace CMS_Client.View public int Right; public int Bottom; } - - public static void CaptureCycle() - { - RECT rc = new RECT(); - Graphics gr; - bool success=false; - Bitmap bmp; - MemoryStream m = new MemoryStream(); - - - while (true) - { - if(state == NcState.READONLY) - { - Thread.BeginThreadAffinity(); - m = new MemoryStream(); - String Base64Capture; - if (ncprocess != null && ncprocess.MainWindowHandle != IntPtr.Zero) - { - GetWindowRect(ncprocess.MainWindowHandle, out rc); - bmp = new Bitmap(rc.Right - rc.Left, rc.Bottom - rc.Top); - gr = Graphics.FromImage(bmp); - success = PrintWindow(ncprocess.MainWindowHandle, gr.GetHdc(), 0); - gr.ReleaseHdc(); - if (success && bmp != null) - { - bmp.Save(m, ImageFormat.Png); - Base64Capture = Convert.ToBase64String(m.ToArray()); - ncCapture = "data:image/png;base64," + Base64Capture; - } - m.Dispose(); - bmp.Dispose(); - gr.Dispose(); - } - Thread.EndThreadAffinity(); - } - Thread.Sleep(500); - } - } - #endregion + #endregion } } diff --git a/Client/View/OpeningForm.cs b/Client/View/OpeningForm.cs index 4f208fbc..87613261 100644 --- a/Client/View/OpeningForm.cs +++ b/Client/View/OpeningForm.cs @@ -15,6 +15,7 @@ using System.Windows.Forms; using Client.Utils; using System.IO; using MetroFramework; +using Newtonsoft.Json; namespace CMS_Client.View { @@ -25,6 +26,7 @@ namespace CMS_Client.View private HttpWebResponse ConnTestResponse; private String ConnTestError; private Task ConnTask; + private ushort WaitDot=1; /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// #region WINDOW_START_&_BEHAVIOUR_METHOD @@ -116,8 +118,17 @@ namespace CMS_Client.View this.Invoke((MethodInvoker)delegate () {TaskbarManager.Instance.SetProgressState(TaskbarProgressBarState.Indeterminate, this.Handle); }); //try to Request - setStatus("Connecting to " + Config.ConnectionConfig.Url + "...", ""); - do { } while (!testConnection(new Uri(Config.ConnectionConfig.Url))) ; + if(!Config.ConnectionConfig.BypassReadConfiguration) + { + setStatus("Connecting to \n" + Config.ConnectionConfig.ServerUrl + ":" + Config.ConnectionConfig.ServerPort + "\n", ""); + + Boolean error=false; + do { + if (error == true) + return; + } while (!testConnection(new Uri(Config.ConnectionConfig.ReadConfigUrl),out error)); + + } //Set App Opacity (Only Siemens) if(Config.VendorHmiConfig.Type == 2) @@ -167,12 +178,13 @@ namespace CMS_Client.View //Sub-Method used to test the connection - private bool testConnection(Uri url) + private bool testConnection(Uri url,out Boolean error) { Boolean Connected = false; + error = false; //Try to connect - if(url.Scheme == Uri.UriSchemeHttps || url.Scheme == Uri.UriSchemeHttp) + if (url.Scheme == Uri.UriSchemeHttps || url.Scheme == Uri.UriSchemeHttp) { try { @@ -196,12 +208,73 @@ namespace CMS_Client.View //Check if it's connected if (Connected) { + var jsonDefinition = new { ncVendor = "", showHMI = "" }; setStatus("Connected!", ""); - return true; + + //Read the configuration from Server + try + { + using (var reader = new StreamReader(ConnTestResponse.GetResponseStream())) + { + var ConfigResponse = JsonConvert.DeserializeAnonymousType(reader.ReadToEnd(), jsonDefinition); + + if(!String.IsNullOrWhiteSpace(ConfigResponse.ncVendor) && !String.IsNullOrWhiteSpace(ConfigResponse.showHMI)) + { + String ncVendorName = ConfigResponse.ncVendor.ToUpper(); + String ncVendorHMI = ConfigResponse.showHMI.ToUpper(); + + + //Read the Server Type + if (ncVendorName.Equals("DEMO")) + Config.VendorHmiConfig.Type = 0; + else if (ncVendorName.Equals("FANUC")) + Config.VendorHmiConfig.Type = 1; + else if (ncVendorName.Equals("SIEMENS")) + Config.VendorHmiConfig.Type = 2; + else if (ncVendorName.Equals("OSAI")) + Config.VendorHmiConfig.Type = 3; + else + { + setStatus("Close the application!", "Errror in configuration, from server"); + error = true; + return false; + } + + //Read if the HMI must be visible + if (ncVendorHMI.Equals("TRUE")) + Config.VendorHmiConfig.Enabled = true; + else + Config.VendorHmiConfig.Enabled = false; + + return true; + } + + } + return true; + } + catch (Exception e) + { + + return false; + } + } else { - setStatus("Retry connection to: " + Config.ConnectionConfig.Url, "Server not found (Error:" + ConnTestError + ")"); + //Set the Dot string + String dot = ""; + for (int i = 0; i < WaitDot; i++) dot += "."; + + //Set the status + setStatus("Retry connection to \n" + Config.ConnectionConfig.ServerUrl + ":" + Config.ConnectionConfig.ServerPort + "\n" + dot, "Server not found (Error: " + ConnTestError + ")"); + if (WaitDot < 3) + WaitDot++; + else + WaitDot = 0; + + //Wait 500 ms + Thread.Sleep(500); + return false; } } From 899919ae2b646baeafa81b46fee44d94ee44f705 Mon Sep 17 00:00:00 2001 From: Lucio Maranta Date: Thu, 11 Jan 2018 17:19:59 +0100 Subject: [PATCH 2/2] Refactor WIP self hosted server url --- Step.Model/DTOModels/DTOClientConfigurationModel.cs | 2 +- Step/Controllers/WebApi/ConfigurationController.cs | 4 ++-- Step/Controllers/WebApi/NcApiController.cs | 2 +- Step/program.cs | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Step.Model/DTOModels/DTOClientConfigurationModel.cs b/Step.Model/DTOModels/DTOClientConfigurationModel.cs index a9fd1edc..59ed44ed 100644 --- a/Step.Model/DTOModels/DTOClientConfigurationModel.cs +++ b/Step.Model/DTOModels/DTOClientConfigurationModel.cs @@ -9,6 +9,6 @@ namespace Step.Model.DTOModels public class DTOClientConfigurationModel { public string NcVendor; - public bool showHMI; + public bool ShowHMI; } } diff --git a/Step/Controllers/WebApi/ConfigurationController.cs b/Step/Controllers/WebApi/ConfigurationController.cs index db2b3372..4230736b 100644 --- a/Step/Controllers/WebApi/ConfigurationController.cs +++ b/Step/Controllers/WebApi/ConfigurationController.cs @@ -7,7 +7,7 @@ namespace Step.Controllers.WebApi [RoutePrefix("api/configuration")] public class ConfigurationController : ApiController { - [Route("base"), HttpGet] + [Route("areas"), HttpGet] public IHttpActionResult GetStartupConfiguration() { DTOStartupConfigurationModel startupConfiguration = new DTOStartupConfigurationModel() @@ -30,7 +30,7 @@ namespace Step.Controllers.WebApi DTOClientConfigurationModel clientConfiguration = new DTOClientConfigurationModel() { NcVendor = NcConfig.NcVendor, - showHMI = NcConfig.showNcHMI + ShowHMI = NcConfig.showNcHMI }; return Ok(clientConfiguration); diff --git a/Step/Controllers/WebApi/NcApiController.cs b/Step/Controllers/WebApi/NcApiController.cs index 20ef7512..3ad0375b 100644 --- a/Step/Controllers/WebApi/NcApiController.cs +++ b/Step/Controllers/WebApi/NcApiController.cs @@ -29,7 +29,7 @@ namespace Step.Controllers.WebApi ncHandler.Connect(); CmsError libraryError = ncHandler.GetNcGenericData(out DTONcGenericDataModel genericData); if (libraryError.errorCode != 0) - Console.WriteLine(libraryError.message); + return Ok(libraryError.message); return Ok(genericData); } diff --git a/Step/program.cs b/Step/program.cs index 6eb707c6..29f022ab 100644 --- a/Step/program.cs +++ b/Step/program.cs @@ -28,7 +28,7 @@ namespace Step DatabaseContext.TestDatabaseConnection(); // Start self host application - string configuredUri = "http://*:" + ServerConfig.ServerPort.ToString(); + string configuredUri = "http://localhost:" + ServerConfig.ServerPort.ToString(); // Register listener to "close application" messages MessageServices.Current.Subscribe(STOP_SERVER, (a, b) =>