From 82891d56d87d3029c9a3d47424e1c4895c60fd6a Mon Sep 17 00:00:00 2001 From: gbakeman Date: Mon, 1 Jul 2024 15:26:17 -0400 Subject: [PATCH 1/7] VS automatic changes to .resx files --- WinNUT_V2/WinNUT-Client/About_Gui.zh-CN.resx | 14 ---- .../My Project/Resources.zh-CN.resx | 22 ++++-- WinNUT_V2/WinNUT-Client/Pref_Gui.zh-CN.resx | 20 ++---- .../UpgradePrefsDialog.zh-CN.resx | 68 +++++++++---------- WinNUT_V2/WinNUT-Client/WinNUT.zh-CN.resx | 9 --- 5 files changed, 56 insertions(+), 77 deletions(-) diff --git a/WinNUT_V2/WinNUT-Client/About_Gui.zh-CN.resx b/WinNUT_V2/WinNUT-Client/About_Gui.zh-CN.resx index d2c71ca..a3df4f0 100644 --- a/WinNUT_V2/WinNUT-Client/About_Gui.zh-CN.resx +++ b/WinNUT_V2/WinNUT-Client/About_Gui.zh-CN.resx @@ -12,18 +12,4 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - This program is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published -by the Free Software Foundation, either version 3 of the License, or -any later version. - -This program is distributed in the hope that it will be useful, but -WITHOUT ANY WARRANTY; without even the implied warranty -of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program. If not, see https://www.gnu.org/licenses/. - \ No newline at end of file diff --git a/WinNUT_V2/WinNUT-Client/My Project/Resources.zh-CN.resx b/WinNUT_V2/WinNUT-Client/My Project/Resources.zh-CN.resx index debcdbb..2fea80c 100644 --- a/WinNUT_V2/WinNUT-Client/My Project/Resources.zh-CN.resx +++ b/WinNUT_V2/WinNUT-Client/My Project/Resources.zh-CN.resx @@ -121,32 +121,33 @@ Ini 文件重命名为 {0}.old ..\Resources\XP_Information.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - ..\Resources\regedit.exe_14_100-0.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - - https://github.com/nutdotnet/WinNUT-Client - 在注册表中检测到以前的设置数据。 + Notify the user that preferences data from the old system was detected in the Registry hive. 旧设置已经被导入。 + Notify the user that the import procedure has completed. 有 {0} 个未知的设置。请查看日志获取更多详细信息。 + Alert the user to how many unmatched preferences there were {0}. 旧设置已经从您的注册表中删除。 + Notify the user that the old preferences have been removed from their Registry. 升级过程已取消:使用默认设置。 + Notify the user that the upgrade dialog was cancelled, and that default settings will be used instead. 保存 WinNUT 注册表 + Title of the SaveFileDialog that prompts the user to select the file and location they would like to save their WinNUT Registry preferences to. 旧设置已备份到 {0} + Notify the user that the old preferences have been exported to a file, and give the full path with {0}. 升级过程中发生错误: @@ -154,20 +155,29 @@ Ini 文件重命名为 {0}.old {0} 请修复错误,或取消升级对话框以继续使用默认设置。 + Alert the user that an error occurred during the upgrade procedure, attempt to give a brief summary of the error, and prompt them to take the next step. + + + ..\Resources\regedit.exe_14_100-0.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a 没有检测到设置 + A brief caption for the error message. 您的系统中未检测到设置。无法继续操作。 + Alert the user that the dialog is unable to continue, since no preferences are detected in the Registry. 您的系统中未检测到旧设置。 + Similar to _Enabled tooltip, except that the preferences were not detected. 检测到旧设置。点击运行导入向导。 + Tooltip of the "manage old prefs" menu item, explaining that the old preferences were detected and that clicking will open the wizard dialog. 参数无效 + Indicate that a variable is unavailable \ No newline at end of file diff --git a/WinNUT_V2/WinNUT-Client/Pref_Gui.zh-CN.resx b/WinNUT_V2/WinNUT-Client/Pref_Gui.zh-CN.resx index 509deb8..3cdf9a3 100644 --- a/WinNUT_V2/WinNUT-Client/Pref_Gui.zh-CN.resx +++ b/WinNUT_V2/WinNUT-Client/Pref_Gui.zh-CN.resx @@ -101,6 +101,10 @@ 登录 + + 从NUT服务器更新数据时间间隔(单位:毫秒)。 +最小值: 100, 最大值: 60 000。 + 监控的 UPS 名称。 允许值:在 UPS 的 Nut 服务端所配置的名称。 @@ -161,6 +165,9 @@ 创建日志文件 + + 将日志事件写入文件。 + 随 Windows 启动当前应用 @@ -316,17 +323,4 @@ Microsoft Sans Serif, 8.25pt, style=Italic - - 50 - - - 60 - - - 从NUT服务器更新数据时间间隔(单位:毫秒)。 -最小值: 100, 最大值: 60 000。 - - - 将日志事件写入文件。 - \ No newline at end of file diff --git a/WinNUT_V2/WinNUT-Client/UpgradePrefsDialog.zh-CN.resx b/WinNUT_V2/WinNUT-Client/UpgradePrefsDialog.zh-CN.resx index a0b1a0b..344f56f 100644 --- a/WinNUT_V2/WinNUT-Client/UpgradePrefsDialog.zh-CN.resx +++ b/WinNUT_V2/WinNUT-Client/UpgradePrefsDialog.zh-CN.resx @@ -42,6 +42,9 @@ 2 + + WinNUT已经升级到一个新的设置和设置系统,并且必须继续使用它。在注册表中检测到了一些旧程序的设置。请从下面选择您希望对旧设置进行的操作。如果您不希望采取任何操作,请选择取消,将使用默认设置。只要新的程序数据保持完整,将不会再显示此消息。 + Right @@ -57,6 +60,9 @@ 0 + + 确认 + Right @@ -72,6 +78,9 @@ 1 + + 取消 + True @@ -87,6 +96,12 @@ 5 + + 导入 + + + 旧设置将从注册表导入到新的设置系统中。 + True @@ -102,6 +117,12 @@ 6 + + 删除 + + + 在注册表中检测到旧设置数据。 + Top, Left, Right @@ -120,6 +141,12 @@ 7 + + 备份 + + + 旧设置将被导出到文件中。 + 6, 122 @@ -132,6 +159,9 @@ 7 + + 以前的设置 + Bottom @@ -180,6 +210,9 @@ CenterParent + + 迁移到新设置格式 + 488, 17 @@ -195,39 +228,4 @@ 44 - - WinNUT已经升级到一个新的设置和设置系统,并且必须继续使用它。在注册表中检测到了一些旧程序的设置。请从下面选择您希望对旧设置进行的操作。如果您不希望采取任何操作,请选择取消,将使用默认设置。只要新的程序数据保持完整,将不会再显示此消息。 - - - - - 确认 - - - 取消 - - - 导入 - - - 旧设置将从注册表导入到新的设置系统中。 - - - 删除 - - - 在注册表中检测到旧设置数据。 - - - 备份 - - - 旧设置将被导出到文件中。 - - - 以前的设置 - - - 迁移到新设置格式 - \ No newline at end of file diff --git a/WinNUT_V2/WinNUT-Client/WinNUT.zh-CN.resx b/WinNUT_V2/WinNUT-Client/WinNUT.zh-CN.resx index f965560..93b9b17 100644 --- a/WinNUT_V2/WinNUT-Client/WinNUT.zh-CN.resx +++ b/WinNUT_V2/WinNUT-Client/WinNUT.zh-CN.resx @@ -102,15 +102,6 @@ False - - NotifyIcon1 - - - MenuStrip1 - - - WinNUT Client - 管理旧设置... From f7418914f691b016ecc8da4b40b72fd7fa13b841 Mon Sep 17 00:00:00 2001 From: gbakeman Date: Mon, 1 Jul 2024 15:48:05 -0400 Subject: [PATCH 2/7] Support Suspend power mode change We previously didn't support the Suspend power mode change, which meant WinNUT would be paused in the middle of execution (and with an open socket) if the system goes to sleep. Now WinNUT has the chance to close down operations and connections, which seems to at least help with errors while changing power states. It looks like WinNUT still tries to reconnect too quickly after the system resumes from sleep (before networking is fully restored?) In the interest of reducing notification spam, it may be best to have WinNUT wait a few seconds before reconnecting. --- WinNUT_V2/WinNUT-Client/WinNUT.vb | 3 +++ 1 file changed, 3 insertions(+) diff --git a/WinNUT_V2/WinNUT-Client/WinNUT.vb b/WinNUT_V2/WinNUT-Client/WinNUT.vb index 894c05d..955d6fc 100644 --- a/WinNUT_V2/WinNUT-Client/WinNUT.vb +++ b/WinNUT_V2/WinNUT-Client/WinNUT.vb @@ -345,6 +345,9 @@ Public Class WinNUT Private Sub SystemEvents_PowerModeChanged(sender As Object, e As Microsoft.Win32.PowerModeChangedEventArgs) LogFile.LogTracing("PowerModeChangedEvent: " & [Enum].GetName(GetType(Microsoft.Win32.PowerModes), e.Mode), LogLvl.LOG_NOTICE, Me) Select Case e.Mode + Case Microsoft.Win32.PowerModes.Suspend + LogFile.LogTracing("Suspending WinNUT operations...", LogLvl.LOG_NOTICE, Me, StrLog.Item(AppResxStr.STR_MAIN_GOTOSLEEP)) + UPSDisconnect() Case Microsoft.Win32.PowerModes.Resume LogFile.LogTracing("Restarting WinNUT after waking up from Windows", LogLvl.LOG_NOTICE, Me, StrLog.Item(AppResxStr.STR_MAIN_EXITSLEEP)) If My.Settings.NUT_AutoReconnect Then From 47b803e9f25d608c0eee31ab9e585e49b68d78d6 Mon Sep 17 00:00:00 2001 From: gbakeman Date: Tue, 2 Jul 2024 12:47:25 -0400 Subject: [PATCH 3/7] Removing Form-wide manual update variable Variable was essentially unused except for within the Update GUI trigger function, when it's predetermined anyways. --- WinNUT_V2/WinNUT-Client/WinNUT.vb | 24 ++++-------------------- 1 file changed, 4 insertions(+), 20 deletions(-) diff --git a/WinNUT_V2/WinNUT-Client/WinNUT.vb b/WinNUT_V2/WinNUT-Client/WinNUT.vb index 955d6fc..46f6815 100644 --- a/WinNUT_V2/WinNUT-Client/WinNUT.vb +++ b/WinNUT_V2/WinNUT-Client/WinNUT.vb @@ -12,20 +12,6 @@ Imports WinNUT_Client_Common Public Class WinNUT #Region "Properties" - Public Property UpdateMethod() As String - Get - If mUpdate Then - mUpdate = False - Return True - Else - Return False - End If - End Get - Set(Value As String) - mUpdate = Value - End Set - End Property - Public WriteOnly Property HasCrashed() As Boolean Set(Value As Boolean) WinNUT_Crashed = Value @@ -78,7 +64,6 @@ Public Class WinNUT Public UPS_InputA As Double Private HasFocus As Boolean = True - Private mUpdate As Boolean = False Private FormText As String Private WinNUT_Crashed As Boolean = False @@ -349,10 +334,10 @@ Public Class WinNUT LogFile.LogTracing("Suspending WinNUT operations...", LogLvl.LOG_NOTICE, Me, StrLog.Item(AppResxStr.STR_MAIN_GOTOSLEEP)) UPSDisconnect() Case Microsoft.Win32.PowerModes.Resume - LogFile.LogTracing("Restarting WinNUT after waking up from Windows", LogLvl.LOG_NOTICE, Me, StrLog.Item(AppResxStr.STR_MAIN_EXITSLEEP)) If My.Settings.NUT_AutoReconnect Then - UPS_Connect(True) - End If + LogFile.LogTracing("Reconnecting after system resume.", LogLvl.LOG_NOTICE, Me, StrLog.Item(AppResxStr.STR_MAIN_EXITSLEEP)) + UPS_Connect(True) + End If End Select End Sub @@ -1048,12 +1033,11 @@ Public Class WinNUT End Sub Private Sub Menu_Update_Click(sender As Object, e As EventArgs) Handles Menu_Update.Click - mUpdate = True 'Dim th As System.Threading.Thread = New Threading.Thread(New System.Threading.ParameterizedThreadStart(AddressOf Run_Update)) 'th.SetApartmentState(System.Threading.ApartmentState.STA) 'th.Start(Me.UpdateMethod) LogFile.LogTracing("Open About Gui From Menu", LogLvl.LOG_DEBUG, Me) - Dim Update_Frm = New Update_Gui(mUpdate) + Dim Update_Frm = New Update_Gui(True) Update_Frm.Activate() Update_Frm.Visible = True HasFocus = False From ef93c30a7d3bb1518870993b0a7627139bab2ea9 Mon Sep 17 00:00:00 2001 From: gbakeman Date: Tue, 2 Jul 2024 13:10:41 -0400 Subject: [PATCH 4/7] Small socket, power mode changes - Socket Disconnect method now calls the Close_Socket method and raises the SocketDisconnected event in more cases - System Resume event now tries to disconnect the UPS if it's still considered connected. --- WinNUT_V2/WinNUT-Client/WinNUT.vb | 11 ++++++++--- WinNUT_V2/WinNUT-Client_Common/Nut_Socket.vb | 12 +++++------- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/WinNUT_V2/WinNUT-Client/WinNUT.vb b/WinNUT_V2/WinNUT-Client/WinNUT.vb index 46f6815..24ab84f 100644 --- a/WinNUT_V2/WinNUT-Client/WinNUT.vb +++ b/WinNUT_V2/WinNUT-Client/WinNUT.vb @@ -330,14 +330,19 @@ Public Class WinNUT Private Sub SystemEvents_PowerModeChanged(sender As Object, e As Microsoft.Win32.PowerModeChangedEventArgs) LogFile.LogTracing("PowerModeChangedEvent: " & [Enum].GetName(GetType(Microsoft.Win32.PowerModes), e.Mode), LogLvl.LOG_NOTICE, Me) Select Case e.Mode + ' Note: Windows does not wait for applications to handle a Suspend event. Case Microsoft.Win32.PowerModes.Suspend LogFile.LogTracing("Suspending WinNUT operations...", LogLvl.LOG_NOTICE, Me, StrLog.Item(AppResxStr.STR_MAIN_GOTOSLEEP)) UPSDisconnect() Case Microsoft.Win32.PowerModes.Resume + If UPS_Device IsNot Nothing AndAlso UPS_Device.IsConnected Then + LogFile.LogTracing("Trying to disconnect connected UPS after system resume...", LogLvl.LOG_NOTICE, Me) + UPSDisconnect() + End If If My.Settings.NUT_AutoReconnect Then - LogFile.LogTracing("Reconnecting after system resume.", LogLvl.LOG_NOTICE, Me, StrLog.Item(AppResxStr.STR_MAIN_EXITSLEEP)) - UPS_Connect(True) - End If + LogFile.LogTracing("Reconnecting after system resume.", LogLvl.LOG_NOTICE, Me, StrLog.Item(AppResxStr.STR_MAIN_EXITSLEEP)) + UPS_Connect(True) + End If End Select End Sub diff --git a/WinNUT_V2/WinNUT-Client_Common/Nut_Socket.vb b/WinNUT_V2/WinNUT-Client_Common/Nut_Socket.vb index 3669aa7..3efff26 100644 --- a/WinNUT_V2/WinNUT-Client_Common/Nut_Socket.vb +++ b/WinNUT_V2/WinNUT-Client_Common/Nut_Socket.vb @@ -161,16 +161,14 @@ Public Class Nut_Socket ''' ''' Perform various functions necessary to disconnect the socket from the NUT server. ''' - ''' Skip sending the LOGOUT command to the NUT server. Unknown effects. + ''' Skip sending the LOGOUT command to the NUT server. Unknown effects. Public Sub Disconnect(Optional forceful = False) If Not forceful AndAlso IsConnected AndAlso IsLoggedIn Then - Try - Query_Data("LOGOUT") - Finally - Close_Socket() - RaiseEvent SocketDisconnected() - End Try + Query_Data("LOGOUT") End If + + Close_Socket() + RaiseEvent SocketDisconnected() End Sub ''' From 031bee46a691b0b1ff784c7a90ba96701e7b7e58 Mon Sep 17 00:00:00 2001 From: gbakeman Date: Tue, 2 Jul 2024 17:04:17 -0400 Subject: [PATCH 5/7] Login, socket improvements Nut_Socket.vb - Removed Socket object and any relating code since TcpClient is already providing the functionality. - Remove Disconnected event since this will be provided through exceptions or intentional commands. - Fixed use of LOGIN protocol command - Simplify Disconnect method UPS_Device.vb - Created dedicated Login method that interfaces with the socket layer. WinNUT.vb - Calls Login method only when a username is provided. Fixes forced/unintended logins. --- WinNUT_V2/WinNUT-Client/WinNUT.vb | 8 +- WinNUT_V2/WinNUT-Client_Common/Nut_Socket.vb | 131 +++++++------------ WinNUT_V2/WinNUT-Client_Common/UPS_Device.vb | 32 +++-- 3 files changed, 78 insertions(+), 93 deletions(-) diff --git a/WinNUT_V2/WinNUT-Client/WinNUT.vb b/WinNUT_V2/WinNUT-Client/WinNUT.vb index 24ab84f..e1f42a6 100644 --- a/WinNUT_V2/WinNUT-Client/WinNUT.vb +++ b/WinNUT_V2/WinNUT-Client/WinNUT.vb @@ -383,6 +383,10 @@ Public Class WinNUT UPS_Device = New UPS_Device(Nut_Config, LogFile, My.Settings.NUT_PollIntervalMsec, My.Settings.CAL_FreqInNom) AddHandler UPS_Device.EncounteredNUTException, AddressOf HandleNUTException UPS_Device.Connect_UPS(retryOnConnFailure) + + If Not String.IsNullOrEmpty(Nut_Config.Login) Then + UPS_Device.Login() + End If End Sub ''' @@ -409,8 +413,8 @@ Public Class WinNUT End Sub Private Sub ConnectionError(sender As UPS_Device, ex As Exception) Handles UPS_Device.ConnectionError - LogFile.LogTracing(String.Format("Something went wrong connecting to UPS {0}. IsConnected: {1}, IsAuthenticated: {2}", - sender.Name, sender.IsConnected, sender.IsAuthenticated), LogLvl.LOG_ERROR, Me, + LogFile.LogTracing(String.Format("Something went wrong connecting to UPS {0}. IsConnected: {1}, IsLoggedIn: {2}", + sender.Name, sender.IsConnected, sender.IsLoggedIn), LogLvl.LOG_ERROR, Me, String.Format(StrLog.Item(AppResxStr.STR_LOG_CON_FAILED), sender.Nut_Config.Host, sender.Nut_Config.Port, ex.Message)) End Sub diff --git a/WinNUT_V2/WinNUT-Client_Common/Nut_Socket.vb b/WinNUT_V2/WinNUT-Client_Common/Nut_Socket.vb index 3efff26..afeb05a 100644 --- a/WinNUT_V2/WinNUT-Client_Common/Nut_Socket.vb +++ b/WinNUT_V2/WinNUT-Client_Common/Nut_Socket.vb @@ -11,6 +11,7 @@ ' Class dealing only with the management of the communication socket with the Nut server Imports System.IO +Imports System.Net Imports System.Net.Sockets Public Class Nut_Socket @@ -18,11 +19,7 @@ Public Class Nut_Socket #Region "Properties" Public ReadOnly Property ConnectionStatus As Boolean Get - If NutSocket IsNot Nothing Then - Return NutSocket.Connected - Else - Return False - End If + Return client.Connected End Get End Property @@ -58,8 +55,7 @@ Public Class Nut_Socket Private NutConfig As Nut_Parameter 'Socket Variables - Private NutSocket As Socket - Private NutTCP As TcpClient + Private client As New TcpClient Private NutStream As NetworkStream Private ReaderStream As StreamReader Private WriterStream As StreamWriter @@ -71,11 +67,6 @@ Public Class Nut_Socket Public Event Socket_Broken(ex As NutException) - ''' - ''' Socket was disconnected as a part of normal operations. - ''' - Public Event SocketDisconnected() - Public Sub New(Nut_Config As Nut_Parameter, ByRef logger As Logger) LogFile = logger NutConfig = Nut_Config @@ -93,67 +84,53 @@ Public Class Nut_Socket End If Try - ' NutSocket = New Socket(AddressFamily.InterNetwork, ProtocolType.IP) - NutSocket = New Socket(SocketType.Stream, ProtocolType.IP) LogFile.LogTracing(String.Format("Attempting TCP socket connection to {0}:{1}...", Host, Port), LogLvl.LOG_NOTICE, Me) - NutSocket.Connect(Host, Port) - NutTCP = New TcpClient(Host, Port) - NutStream = NutTCP.GetStream + + client.Connect(Host, Port) + NutStream = client.GetStream() ReaderStream = New StreamReader(NutStream) WriterStream = New StreamWriter(NutStream) - LogFile.LogTracing(String.Format("Connection established and streams ready for {0}:{1}", Host, Port), LogLvl.LOG_NOTICE, Me) - ' Something went wrong - cleanup and pass along error. + LogFile.LogTracing("Connection established and streams ready.", LogLvl.LOG_NOTICE, Me) + Catch Excep As Exception Disconnect(True) Throw ' Pass exception on up to UPS End Try - If ConnectionStatus Then - Try - AuthLogin(Login, Password) - Catch ex As NutException - ' TODO: Make friendly message string for user. - LogFile.LogTracing("Error while attempting to log in: " & ex.Message, LogLvl.LOG_ERROR, Me) - End Try + Dim Nut_Query = Query_Data("VER") - Dim Nut_Query = Query_Data("VER") - - If Nut_Query.ResponseType = NUTResponse.OK Then - Nut_Ver = (Nut_Query.RawResponse.Split(" "c))(4) - End If - Nut_Query = Query_Data("NETVER") - - If Nut_Query.ResponseType = NUTResponse.OK Then - Net_Ver = Nut_Query.RawResponse - End If + If Nut_Query.ResponseType = NUTResponse.OK Then + Nut_Ver = (Nut_Query.RawResponse.Split(" "c))(4) + End If + Nut_Query = Query_Data("NETVER") - LogFile.LogTracing(String.Format("NUT server reports VER: {0} NETVER: {1}", Nut_Ver, Net_Ver), LogLvl.LOG_NOTICE, Me) + If Nut_Query.ResponseType = NUTResponse.OK Then + Net_Ver = Nut_Query.RawResponse End If + + LogFile.LogTracing(String.Format("NUT server reports VER: {0} NETVER: {1}", Nut_Ver, Net_Ver), LogLvl.LOG_NOTICE, Me) End Sub - ''' - ''' Register with the UPSd server as being dependant on it for power. - ''' - ''' - ''' - ''' A protocol error was encountered while trying to authenticate. - Private Sub AuthLogin(Login As String, Password As String) + Public Sub Login() If _isLoggedIn Then Throw New InvalidOperationException("Attempted to login when already logged in.") End If - LogFile.LogTracing("Attempting authentication...", LogLvl.LOG_NOTICE, Me) + LogFile.LogTracing(String.Format("Logging in to UPS [{0}] as user [{1}] ({2})...", + NutConfig.UPSName, NutConfig.Login, + If(String.IsNullOrEmpty(NutConfig.Password), + "NO Password", "Password provided")), LogLvl.LOG_NOTICE, Me) - If Not String.IsNullOrEmpty(Login) Then - Query_Data("USERNAME " & Login) + If Not String.IsNullOrEmpty(NutConfig.Login) Then + Query_Data("USERNAME " & NutConfig.Login) - If Not String.IsNullOrEmpty(Password) Then - Query_Data("PASSWORD " & Password) + If Not String.IsNullOrEmpty(NutConfig.Password) Then + Query_Data("PASSWORD " & NutConfig.Password) End If End If - Query_Data("LOGIN") + Query_Data("LOGIN " & NutConfig.UPSName) _isLoggedIn = True LogFile.LogTracing("Authenticated successfully.", LogLvl.LOG_NOTICE, Me) End Sub @@ -163,12 +140,29 @@ Public Class Nut_Socket ''' ''' Skip sending the LOGOUT command to the NUT server. Unknown effects. Public Sub Disconnect(Optional forceful = False) - If Not forceful AndAlso IsConnected AndAlso IsLoggedIn Then - Query_Data("LOGOUT") - End If + If IsConnected Then + If IsLoggedIn AndAlso Not forceful Then + Query_Data("LOGOUT") + End If - Close_Socket() - RaiseEvent SocketDisconnected() + If WriterStream IsNot Nothing Then + WriterStream.Close() + End If + + If ReaderStream IsNot Nothing Then + ReaderStream.Close() + End If + + If NutStream IsNot Nothing Then + NutStream.Close() + End If + + If client IsNot Nothing Then + client.Close() + End If + Else + Throw New InvalidOperationException("NUT Socket is already disconnected.") + End If End Sub ''' @@ -383,31 +377,4 @@ Public Class Nut_Socket RaiseEvent Socket_Broken(New NutException(Nut_Query)) End If End Sub - - Private Sub Close_Socket() - Try - If WriterStream IsNot Nothing Then - WriterStream.Close() - End If - - If ReaderStream IsNot Nothing Then - ReaderStream.Close() - End If - - If NutStream IsNot Nothing Then - NutStream.Close() - End If - - If NutTCP IsNot Nothing Then - NutTCP.Close() - End If - - If NutSocket IsNot Nothing Then - NutSocket.Close() - End If - Catch Excep As Exception - LogFile.LogTracing("Error encountered while shutting down socket: " & vbNewLine & Excep.ToString(), - LogLvl.LOG_ERROR, Me) - End Try - End Sub End Class diff --git a/WinNUT_V2/WinNUT-Client_Common/UPS_Device.vb b/WinNUT_V2/WinNUT-Client_Common/UPS_Device.vb index 67c8da6..f4065c4 100644 --- a/WinNUT_V2/WinNUT-Client_Common/UPS_Device.vb +++ b/WinNUT_V2/WinNUT-Client_Common/UPS_Device.vb @@ -37,8 +37,7 @@ Public Class UPS_Device Return (Nut_Socket.IsConnected) End Get End Property - - Public ReadOnly Property IsAuthenticated As Boolean + Public ReadOnly Property IsLoggedIn As Boolean Get Return Nut_Socket.IsLoggedIn End Get @@ -154,6 +153,7 @@ Public Class UPS_Device UPS_Datas = GetUPSProductInfo() Update_Data.Start() RaiseEvent Connected(Me) + Catch ex As NutException ' This is how we determine if we have a valid UPS name entered, among other errors. RaiseEvent EncounteredNUTException(Me, ex) @@ -168,6 +168,21 @@ Public Class UPS_Device End Try End Sub + Public Sub Login() + If Not IsConnected OrElse IsLoggedIn Then + Throw New InvalidOperationException("UPS is in an invalid state to login.") + End If + + If Not String.IsNullOrEmpty(Nut_Config.Login) Then + Try + Nut_Socket.Login() + Catch ex As NutException + LogFile.LogTracing("Error while attempting to log in.", LogLvl.LOG_ERROR, Me) + RaiseEvent EncounteredNUTException(Me, ex) + End Try + End If + End Sub + Public Sub Disconnect(Optional cancelReconnect As Boolean = True, Optional forceful As Boolean = False) LogFile.LogTracing("Processing request to disconnect...", LogLvl.LOG_DEBUG, Me) @@ -179,7 +194,7 @@ Public Class UPS_Device Retry = 0 Try - Nut_Socket.Disconnect(forceful) + Catch nutEx As NutException RaiseEvent EncounteredNUTException(Me, nutEx) Finally @@ -189,12 +204,6 @@ Public Class UPS_Device #Region "Socket Interaction" - Private Sub SocketDisconnected() Handles Nut_Socket.SocketDisconnected - LogFile.LogTracing("NutSocket raised Disconnected event.", LogLvl.LOG_DEBUG, Me) - - RaiseEvent Disconnected() - End Sub - Private Sub Socket_Broken() Handles Nut_Socket.Socket_Broken LogFile.LogTracing("Socket has reported a Broken event.", LogLvl.LOG_WARNING, Me) RaiseEvent Lost_Connect() @@ -215,6 +224,11 @@ Public Class UPS_Device LogFile.LogTracing("Nut Host Reconnected", LogLvl.LOG_DEBUG, Me) Reconnect_Nut.Stop() Retry = 0 + + If Not String.IsNullOrEmpty(Nut_Config.Login) Then + Login() + End If + RaiseEvent ReConnected(Me) End If Else From ef6ce51ef4fe79f14c69596bafdf5ca8fe1eaec2 Mon Sep 17 00:00:00 2001 From: gbakeman Date: Wed, 3 Jul 2024 13:29:17 -0400 Subject: [PATCH 6/7] More smaller networking bugfixes Nut_Socket.vb - ConnectionStatus property checks for null client object before checking .Connected property - TcpClient object is left null at construction, and only instantiated during a Connection subroutine. - Disconnect subroutine doesn't explicitly check for connection status on the TcpClient object before running anymore. This allows it to dispose/close all objects regardless. UPS_Device.vb - Fixed polling interval not being applied to timer. Associated property is now read only, and the interval is set directly on the timer during construction. - Fixed missing call to socket's Disconnect subroutine, and added a general exception catch-all. - Removed Login code from Reconnect subroutine, leaving that to external code. - Removed ReConnected event since it seems to duplicate the Connected event's calls. WinNUT.vb - Moved Login call to connection finalization subroutine. - Added LogException call during protocol error handling. --- WinNUT_V2/WinNUT-Client/WinNUT.vb | 15 +++--- WinNUT_V2/WinNUT-Client_Common/Nut_Socket.vb | 53 +++++++------------- WinNUT_V2/WinNUT-Client_Common/UPS_Device.vb | 31 +++--------- 3 files changed, 33 insertions(+), 66 deletions(-) diff --git a/WinNUT_V2/WinNUT-Client/WinNUT.vb b/WinNUT_V2/WinNUT-Client/WinNUT.vb index e1f42a6..783747c 100644 --- a/WinNUT_V2/WinNUT-Client/WinNUT.vb +++ b/WinNUT_V2/WinNUT-Client/WinNUT.vb @@ -383,16 +383,12 @@ Public Class WinNUT UPS_Device = New UPS_Device(Nut_Config, LogFile, My.Settings.NUT_PollIntervalMsec, My.Settings.CAL_FreqInNom) AddHandler UPS_Device.EncounteredNUTException, AddressOf HandleNUTException UPS_Device.Connect_UPS(retryOnConnFailure) - - If Not String.IsNullOrEmpty(Nut_Config.Login) Then - UPS_Device.Login() - End If End Sub ''' ''' Prepare the form to begin receiving data from a connected UPS. ''' - Private Sub UPSReady(nutUps As UPS_Device) Handles UPS_Device.Connected, UPS_Device.ReConnected + Private Sub UPSReady(nutUps As UPS_Device) Handles UPS_Device.Connected Dim upsConf = nutUps.Nut_Config LogFile.LogTracing(upsConf.UPSName & " has indicated it's ready to start sending data.", LogLvl.LOG_DEBUG, Me) @@ -410,6 +406,10 @@ Public Class WinNUT LogFile.LogTracing("Connection to Nut Host Established", LogLvl.LOG_NOTICE, Me, String.Format(StrLog.Item(AppResxStr.STR_LOG_CONNECTED), upsConf.Host, upsConf.Port)) + + If Not String.IsNullOrEmpty(upsConf.Login) Then + UPS_Device.Login() + End If End Sub Private Sub ConnectionError(sender As UPS_Device, ex As Exception) Handles UPS_Device.ConnectionError @@ -596,7 +596,8 @@ Public Class WinNUT Event_Unknown_UPS() End If - LogFile.LogTracing("NUT protocol error encoutnered:" + vbNewLine + ex.ToString(), LogLvl.LOG_NOTICE, sender) + LogFile.LogTracing("NUT protocol error encoutnered:", LogLvl.LOG_NOTICE, sender) + LogFile.LogException(ex, Me) End Sub Public Sub Event_Unknown_UPS() ' Handles UPS_Device.Unknown_UPS @@ -623,7 +624,7 @@ Public Class WinNUT End Sub Public Shared Sub Event_ChangeStatus() Handles Me.On_Battery, Me.On_Line, - UPS_Device.Lost_Connect, UPS_Device.Connected, UPS_Device.Disconnected, UPS_Device.New_Retry, UPS_Device.ReConnected + UPS_Device.Lost_Connect, UPS_Device.Connected, UPS_Device.Disconnected, UPS_Device.New_Retry ', UPS_Device.Unknown_UPS ', UPS_Device.InvalidLogin diff --git a/WinNUT_V2/WinNUT-Client_Common/Nut_Socket.vb b/WinNUT_V2/WinNUT-Client_Common/Nut_Socket.vb index afeb05a..a85a260 100644 --- a/WinNUT_V2/WinNUT-Client_Common/Nut_Socket.vb +++ b/WinNUT_V2/WinNUT-Client_Common/Nut_Socket.vb @@ -1,17 +1,4 @@ -' WinNUT-Client is a NUT windows client for monitoring your ups hooked up to your favorite linux server. -' Copyright (C) 2019-2021 Gawindx (Decaux Nicolas) -' -' This program is free software: you can redistribute it and/or modify it under the terms of the -' GNU General Public License as published by the Free Software Foundation, either version 3 of the -' License, or any later version. -' -' This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY - - - -' Class dealing only with the management of the communication socket with the Nut server -Imports System.IO -Imports System.Net +Imports System.IO Imports System.Net.Sockets Public Class Nut_Socket @@ -19,7 +6,7 @@ Public Class Nut_Socket #Region "Properties" Public ReadOnly Property ConnectionStatus As Boolean Get - Return client.Connected + Return If(client IsNot Nothing, client.Connected, False) End Get End Property @@ -55,7 +42,7 @@ Public Class Nut_Socket Private NutConfig As Nut_Parameter 'Socket Variables - Private client As New TcpClient + Private client As TcpClient Private NutStream As NetworkStream Private ReaderStream As StreamReader Private WriterStream As StreamWriter @@ -86,7 +73,7 @@ Public Class Nut_Socket Try LogFile.LogTracing(String.Format("Attempting TCP socket connection to {0}:{1}...", Host, Port), LogLvl.LOG_NOTICE, Me) - client.Connect(Host, Port) + client = New TcpClient(Host, Port) NutStream = client.GetStream() ReaderStream = New StreamReader(NutStream) WriterStream = New StreamWriter(NutStream) @@ -140,28 +127,24 @@ Public Class Nut_Socket ''' ''' Skip sending the LOGOUT command to the NUT server. Unknown effects. Public Sub Disconnect(Optional forceful = False) - If IsConnected Then - If IsLoggedIn AndAlso Not forceful Then - Query_Data("LOGOUT") - End If + If IsLoggedIn AndAlso Not forceful Then + Query_Data("LOGOUT") + End If - If WriterStream IsNot Nothing Then - WriterStream.Close() - End If + If WriterStream IsNot Nothing Then + WriterStream.Dispose() + End If - If ReaderStream IsNot Nothing Then - ReaderStream.Close() - End If + If ReaderStream IsNot Nothing Then + ReaderStream.Dispose() + End If - If NutStream IsNot Nothing Then - NutStream.Close() - End If + If NutStream IsNot Nothing Then + NutStream.Dispose() + End If - If client IsNot Nothing Then - client.Close() - End If - Else - Throw New InvalidOperationException("NUT Socket is already disconnected.") + If client IsNot Nothing Then + client.Close() End If End Sub diff --git a/WinNUT_V2/WinNUT-Client_Common/UPS_Device.vb b/WinNUT_V2/WinNUT-Client_Common/UPS_Device.vb index f4065c4..600be14 100644 --- a/WinNUT_V2/WinNUT-Client_Common/UPS_Device.vb +++ b/WinNUT_V2/WinNUT-Client_Common/UPS_Device.vb @@ -1,13 +1,4 @@ -' WinNUT-Client is a NUT windows client for monitoring your ups hooked up to your favorite linux server. -' Copyright (C) 2019-2021 Gawindx (Decaux Nicolas) -' -' This program is free software: you can redistribute it and/or modify it under the terms of the -' GNU General Public License as published by the Free Software Foundation, either version 3 of the -' License, or any later version. -' -' This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY - -Imports System.Globalization +Imports System.Globalization Imports System.Windows.Forms Public Class UPS_Device @@ -47,13 +38,10 @@ Public Class UPS_Device ''' How often UPS data is updated, in milliseconds. ''' ''' - Public Property PollingInterval As Integer + Public ReadOnly Property PollingInterval As Integer Get Return Update_Data.Interval End Get - Set(value As Integer) - Update_Data.Interval = value - End Set End Property Public Property IsUpdatingData As Boolean @@ -89,7 +77,6 @@ Public Class UPS_Device #Region "Events" Public Event DataUpdated() Public Event Connected(sender As UPS_Device) - Public Event ReConnected(sender As UPS_Device) ' Notify that the connection was closed gracefully. Public Event Disconnected() ' Notify of an unexpectedly lost connection (??) @@ -127,7 +114,6 @@ Public Class UPS_Device Public Sub New(ByRef Nut_Config As Nut_Parameter, ByRef LogFile As Logger, pollInterval As Integer, defaultFrequency As Integer) Me.LogFile = LogFile Me.Nut_Config = Nut_Config - PollingInterval = pollInterval Freq_Fallback = defaultFrequency Nut_Socket = New Nut_Socket(Me.Nut_Config, LogFile) @@ -138,7 +124,7 @@ Public Class UPS_Device End With With Update_Data - .Interval = DEFAULT_UPDATE_INTERVAL_MS + .Interval = pollInterval .Enabled = False AddHandler .Tick, AddressOf Retrieve_UPS_Datas End With @@ -194,9 +180,12 @@ Public Class UPS_Device Retry = 0 Try - + Nut_Socket.Disconnect(forceful) Catch nutEx As NutException RaiseEvent EncounteredNUTException(Me, nutEx) + Catch ex As Exception + LogFile.LogTracing("Unexpected exception while Disconnecting.", LogLvl.LOG_ERROR, Me) + LogFile.LogException(ex, Me) Finally RaiseEvent Disconnected() End Try @@ -224,12 +213,6 @@ Public Class UPS_Device LogFile.LogTracing("Nut Host Reconnected", LogLvl.LOG_DEBUG, Me) Reconnect_Nut.Stop() Retry = 0 - - If Not String.IsNullOrEmpty(Nut_Config.Login) Then - Login() - End If - - RaiseEvent ReConnected(Me) End If Else LogFile.LogTracing("Max Retry reached. Stop Process Autoreconnect and wait for manual Reconnection", LogLvl.LOG_ERROR, Me, StrLog.Item(AppResxStr.STR_LOG_STOP_RETRY)) From 4d58c43b5d221f866869612841bf4e1e1032eaa3 Mon Sep 17 00:00:00 2001 From: gbakeman Date: Mon, 15 Jul 2024 16:02:57 -0400 Subject: [PATCH 7/7] Smaller socket updates - Removed redundant IsConnected property in favor of ConnectionStatus - Renamed Nut and Net version properties and converted them to auto-implemented properties. - Wrapped version query statements in try-catch blocks in case servers that throw an error for these queries (Synology in particular) may not have further problems with other queries. - Added support for Net version 1.3 --- WinNUT_V2/WinNUT-Client_Common/Nut_Socket.vb | 63 ++++++++++---------- WinNUT_V2/WinNUT-Client_Common/UPS_Device.vb | 2 +- 2 files changed, 31 insertions(+), 34 deletions(-) diff --git a/WinNUT_V2/WinNUT-Client_Common/Nut_Socket.vb b/WinNUT_V2/WinNUT-Client_Common/Nut_Socket.vb index a85a260..2a578fe 100644 --- a/WinNUT_V2/WinNUT-Client_Common/Nut_Socket.vb +++ b/WinNUT_V2/WinNUT-Client_Common/Nut_Socket.vb @@ -10,12 +10,6 @@ Public Class Nut_Socket End Get End Property - Public ReadOnly Property IsConnected() As Boolean - Get - Return ConnectionStatus - End Get - End Property - Private _isLoggedIn As Boolean = False Public ReadOnly Property IsLoggedIn() As Boolean Get @@ -23,19 +17,8 @@ Public Class Nut_Socket End Get End Property - Private Nut_Ver As String - Public ReadOnly Property Nut_Version() As String - Get - Return Nut_Ver - End Get - End Property - - Private Net_Ver As String - Public ReadOnly Property Net_Version() As String - Get - Return Net_Ver - End Get - End Property + Public ReadOnly Property NUTVersion As String + Public ReadOnly Property NetVersion As String #End Region Private LogFile As Logger @@ -80,23 +63,37 @@ Public Class Nut_Socket LogFile.LogTracing("Connection established and streams ready.", LogLvl.LOG_NOTICE, Me) + LogFile.LogTracing("Gathering basic info about the NUT server...", LogLvl.LOG_DEBUG, Me) + + Try + Dim Nut_Query = Query_Data("VER") + + If Nut_Query.ResponseType = NUTResponse.OK Then + _NUTVersion = (Nut_Query.RawResponse.Split(" "c))(4) + LogFile.LogTracing("Server version: " & NUTVersion, LogLvl.LOG_NOTICE, Me) + End If + Catch nutEx As NutException + LogFile.LogTracing("Error retrieving server version.", LogLvl.LOG_WARNING, Me) + LogFile.LogException(nutEx, Me) + End Try + + Try + Dim Nut_Query = Query_Data("NETVER") + + If Nut_Query.ResponseType = NUTResponse.OK Then + _NetVersion = Nut_Query.RawResponse + LogFile.LogTracing("Protocol version: " & NetVersion, LogLvl.LOG_NOTICE, Me) + End If + Catch nutEx As NutException + LogFile.LogTracing("Error retrieving protocol version.", LogLvl.LOG_WARNING, Me) + LogFile.LogException(nutEx, Me) + End Try + + LogFile.LogTracing("Completed gathering basic info about NUT server.", LogLvl.LOG_DEBUG, Me) Catch Excep As Exception Disconnect(True) Throw ' Pass exception on up to UPS End Try - - Dim Nut_Query = Query_Data("VER") - - If Nut_Query.ResponseType = NUTResponse.OK Then - Nut_Ver = (Nut_Query.RawResponse.Split(" "c))(4) - End If - Nut_Query = Query_Data("NETVER") - - If Nut_Query.ResponseType = NUTResponse.OK Then - Net_Ver = Nut_Query.RawResponse - End If - - LogFile.LogTracing(String.Format("NUT server reports VER: {0} NETVER: {1}", Nut_Ver, Net_Ver), LogLvl.LOG_NOTICE, Me) End Sub Public Sub Login() @@ -169,7 +166,7 @@ Public Class Nut_Socket Response = NUTResponse.ENDLIST Case "ERR" Response = DirectCast([Enum].Parse(GetType(NUTResponse), SplitString(1)), NUTResponse) - Case "NETWORK", "1.0", "1.1", "1.2" + Case "NETWORK", "1.0", "1.1", "1.2", "1.3" 'In case of "VER" or "NETVER" Query Response = NUTResponse.OK Case Else diff --git a/WinNUT_V2/WinNUT-Client_Common/UPS_Device.vb b/WinNUT_V2/WinNUT-Client_Common/UPS_Device.vb index 600be14..f428dee 100644 --- a/WinNUT_V2/WinNUT-Client_Common/UPS_Device.vb +++ b/WinNUT_V2/WinNUT-Client_Common/UPS_Device.vb @@ -25,7 +25,7 @@ Public Class UPS_Device Public ReadOnly Property IsConnected As Boolean Get - Return (Nut_Socket.IsConnected) + Return (Nut_Socket.ConnectionStatus) End Get End Property Public ReadOnly Property IsLoggedIn As Boolean