From 65e766a5b1db8aac6daccae0a273d711f7c73ba0 Mon Sep 17 00:00:00 2001 From: merodahero Date: Tue, 21 Jul 2026 07:50:34 +0000 Subject: [PATCH 1/2] feat(client): editable Power Factor and Nominal VA for watts calculation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds two new settings under the existing CAL namespace: - CAL_PowerFactor (Double, default 0.95) - CAL_ApparentPowerNom (Int32, default 2400) The Schneider Easy UPS SRVSPM3KIL (and many other online-double- conversion units) does not publish ups.realpower through the apcsmart driver, so WinNUT-Client falls back to its computed methods. The hardcoded POWER_FACTOR = 0.8 in UPS_Device.vb under-reads by ~15%. The new settings let users override both: - POWER_FACTOR feeds OutputVACalc and InputNomVALoadPct - CAL_ApparentPowerNom backs up RPNomLoadPct when the unit does not publish ups.realpower.nominal Defaults are tuned for online-double-conversion UPSes. To keep the Common assembly free of My.Settings (which is scoped to the Client project only), the values flow through a public shared UPS_Device.RuntimeConfig class that the Client project populates from My.Settings at UPS_Device instantiation. Wire-frame in Pref_Gui: two new NumericUpDown controls (PF: 0.00–1.00, ApparentNomVA: 0–100000) added to the existing CAL tab. --- .../My Project/Settings.settings | 6 ++++ WinNUT_V2/WinNUT-Client/Pref_Gui.Designer.vb | 18 ++++++++++++ WinNUT_V2/WinNUT-Client/Pref_Gui.vb | 10 +++++++ WinNUT_V2/WinNUT-Client/WinNUT.vb | 7 +++++ WinNUT_V2/WinNUT-Client_Common/UPS_Device.vb | 29 +++++++++++++++++-- 5 files changed, 67 insertions(+), 3 deletions(-) diff --git a/WinNUT_V2/WinNUT-Client/My Project/Settings.settings b/WinNUT_V2/WinNUT-Client/My Project/Settings.settings index 579c341..255d4ae 100644 --- a/WinNUT_V2/WinNUT-Client/My Project/Settings.settings +++ b/WinNUT_V2/WinNUT-Client/My Project/Settings.settings @@ -113,5 +113,11 @@ True + + 0.95 + + + 2400 + \ No newline at end of file diff --git a/WinNUT_V2/WinNUT-Client/Pref_Gui.Designer.vb b/WinNUT_V2/WinNUT-Client/Pref_Gui.Designer.vb index cf76326..4e33c88 100644 --- a/WinNUT_V2/WinNUT-Client/Pref_Gui.Designer.vb +++ b/WinNUT_V2/WinNUT-Client/Pref_Gui.Designer.vb @@ -28,6 +28,16 @@ Partial Class Pref_Gui Me.Tab_Connexion = New System.Windows.Forms.TabPage() Me.pollingIntervalUnitLabel = New System.Windows.Forms.Label() Me.pollingIntervalValue = New System.Windows.Forms.NumericUpDown() + + Me.Tb_Cal_PowerFactor.DecimalPlaces = 2 + Me.Tb_Cal_PowerFactor.Minimum = New Decimal(New Integer() {200, 0, 0, 0}) + Me.Tb_Cal_PowerFactor.Maximum = New Decimal(New Integer() {1, 0, 0, 0}) + Me.Tb_Cal_PowerFactor.Value = New Decimal(New Integer() {950, 0, 0, 131072}) + + Me.Tb_Cal_ApparentPowerNom.DecimalPlaces = 0 + Me.Tb_Cal_ApparentPowerNom.Minimum = New Decimal(New Integer() {0, 0, 0, 0}) + Me.Tb_Cal_ApparentPowerNom.Maximum = New Decimal(New Integer() {100000, 0, 0, 0}) + Me.Tb_Cal_ApparentPowerNom.Value = New Decimal(New Integer() {2400, 0, 0, 0}) Me.Tb_Pwd_Nut = New System.Windows.Forms.TextBox() Me.Tb_Login_Nut = New System.Windows.Forms.TextBox() Me.Label3 = New System.Windows.Forms.Label() @@ -44,6 +54,10 @@ Partial Class Pref_Gui Me.Tab_Calibrage = New System.Windows.Forms.TabPage() Me.Cbx_Freq_Input = New System.Windows.Forms.ComboBox() Me.Tb_BattV_Max = New System.Windows.Forms.TextBox() + Me.Tb_Cal_PowerFactor = New System.Windows.Forms.NumericUpDown() + Me.Tb_Cal_ApparentPowerNom = New System.Windows.Forms.NumericUpDown() + Me.Lbl_PowerFactor = New System.Windows.Forms.Label() + Me.Lbl_ApparentPowerNom = New System.Windows.Forms.Label() Me.Tb_OutV_Max = New System.Windows.Forms.TextBox() Me.Tb_InF_Max = New System.Windows.Forms.TextBox() Me.Tb_BattV_Min = New System.Windows.Forms.TextBox() @@ -236,6 +250,10 @@ Partial Class Pref_Gui Me.Tab_Calibrage.Controls.Add(Me.Tb_InV_Min) Me.Tab_Calibrage.Controls.Add(Me.Lbl_Maxi) Me.Tab_Calibrage.Controls.Add(Me.Lbl_Mini) + Me.Tab_Calibrage.Controls.Add(Me.Lbl_PowerFactor) + Me.Tab_Calibrage.Controls.Add(Me.Tb_Cal_PowerFactor) + Me.Tab_Calibrage.Controls.Add(Me.Lbl_ApparentPowerNom) + Me.Tab_Calibrage.Controls.Add(Me.Tb_Cal_ApparentPowerNom) Me.Tab_Calibrage.Controls.Add(Me.Lbl_BattV) Me.Tab_Calibrage.Controls.Add(Me.Lbl_LoadUPS) Me.Tab_Calibrage.Controls.Add(Me.Lbl_OutputV) diff --git a/WinNUT_V2/WinNUT-Client/Pref_Gui.vb b/WinNUT_V2/WinNUT-Client/Pref_Gui.vb index 965abe2..e29aa81 100644 --- a/WinNUT_V2/WinNUT-Client/Pref_Gui.vb +++ b/WinNUT_V2/WinNUT-Client/Pref_Gui.vb @@ -25,6 +25,8 @@ Public Class Pref_Gui Try LogFile.LogTracing("Save Parameters.", LogLvl.LOG_DEBUG, Me) My.Settings.NUT_ServerAddress = Tb_Server_IP.Text + My.Settings.CAL_PowerFactor = CDbl(Tb_Cal_PowerFactor.Value) + My.Settings.CAL_ApparentPowerNom = CInt(Tb_Cal_ApparentPowerNom.Value) My.Settings.NUT_ServerPort = CInt(Tb_Port.Text) My.Settings.NUT_UPSName = Tb_UPS_Name.Text My.Settings.NUT_PollIntervalMsec = CInt(pollingIntervalValue.Value * 1000D) @@ -303,6 +305,14 @@ Public Class Pref_Gui Private Sub Pref_Gui_Load(sender As Object, e As EventArgs) Handles MyBase.Load Icon = WinNUT.Icon LogFile.LogTracing("Load Pref Gui", LogLvl.LOG_DEBUG, Me) + Try + Tb_Cal_PowerFactor.Value = CDbl(My.Settings.CAL_PowerFactor) + Catch + End Try + Try + Tb_Cal_ApparentPowerNom.Value = CInt(My.Settings.CAL_ApparentPowerNom) + Catch + End Try End Sub ''' diff --git a/WinNUT_V2/WinNUT-Client/WinNUT.vb b/WinNUT_V2/WinNUT-Client/WinNUT.vb index d35e48f..72aae9b 100644 --- a/WinNUT_V2/WinNUT-Client/WinNUT.vb +++ b/WinNUT_V2/WinNUT-Client/WinNUT.vb @@ -369,6 +369,13 @@ Public Class WinNUT My.Settings.NUT_UPSName, My.Settings.NUT_AutoReconnect) + ' Apply user-tunable watt-calculation knobs from My.Settings before + ' instantiating the device. These are shared via UPS_Device.RuntimeConfig + ' because UPS_Device lives in the Common assembly where My.Settings is + ' not available. + UPS_Device.RuntimeConfig.PowerFactor = My.Settings.CAL_PowerFactor + UPS_Device.RuntimeConfig.ApparentPowerNomVA = My.Settings.CAL_ApparentPowerNom + 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) diff --git a/WinNUT_V2/WinNUT-Client_Common/UPS_Device.vb b/WinNUT_V2/WinNUT-Client_Common/UPS_Device.vb index 506f019..623fe74 100644 --- a/WinNUT_V2/WinNUT-Client_Common/UPS_Device.vb +++ b/WinNUT_V2/WinNUT-Client_Common/UPS_Device.vb @@ -8,7 +8,25 @@ Imports System.Windows.Forms Public Class UPS_Device #Region "Statics/Defaults" Private ReadOnly INVARIANT_CULTURE = CultureInfo.InvariantCulture - Private Const POWER_FACTOR = 0.8 + Private Const POWER_FACTOR_DEFAULT = 0.95 + Private Const APPARENT_POWER_DEFAULT = 2400 + + ' Shared configuration holder. The Client project sets this once + ' before instantiating UPS_Device, so the Common assembly does not + ' need to reference My.Settings (which is scoped to the Client + ' project only). + Public NotInheritable Class RuntimeConfig + Public Shared PowerFactor As Double = POWER_FACTOR_DEFAULT + Public Shared ApparentPowerNomVA As Integer = APPARENT_POWER_DEFAULT + End Class + + Private ReadOnly Property POWER_FACTOR As Double + Get + Dim pf = RuntimeConfig.PowerFactor + If pf <= 0.0 OrElse pf > 1.0 Then Return POWER_FACTOR_DEFAULT + Return pf + End Get + End Property ' How many milliseconds to wait before the Reconnect routine tries again. Private Const DEFAULT_RECONNECT_WAIT_MS As Double = 5000 @@ -353,8 +371,13 @@ Public Class UPS_Device parsedValue = Single.Parse(GetUPSVar("output.realpower"), INVARIANT_CULTURE) Case PowerMethod.RPNomLoadPct - parsedValue = Double.Parse(GetUPSVar("ups.realpower.nominal"), INVARIANT_CULTURE) - parsedValue *= UPS_Datas.UPS_Value.Load / 100.0 + Dim rpNom As Double + Try + rpNom = Double.Parse(GetUPSVar("ups.realpower.nominal"), INVARIANT_CULTURE) + Catch + rpNom = Config.ApparentPowerNomVA + End Try + parsedValue = rpNom * UPS_Datas.UPS_Value.Load / 100.0 Case PowerMethod.InputNomVALoadPct Dim nomCurrent = Double.Parse(GetUPSVar("input.current.nominal"), INVARIANT_CULTURE) From b116e158fe65e33111a1d90f2449174816433cc7 Mon Sep 17 00:00:00 2001 From: merodahero Date: Wed, 5 Aug 2026 02:39:20 +0000 Subject: [PATCH 2/2] build: add Microsoft.NETFramework.ReferenceAssemblies 1.0.3 PackageReference Restores NuGet resolution for .NET Framework 4.x targets on modern NuGet clients (5.0+). Both vbproj files were missing the explicit PackageReference, causing intermittent NU1605 'No warning' / NU1701 errors during restore on systems where the legacy GAC fallback isn't available. The 1.0.3 version is the latest stable; matches the locked assembly versions referenced elsewhere in the project. --- WinNUT_V2/WinNUT-Client/WinNUT-client.vbproj | 2 ++ WinNUT_V2/WinNUT-Client_Common/WinNUT-Client_Common.vbproj | 2 ++ 2 files changed, 4 insertions(+) diff --git a/WinNUT_V2/WinNUT-Client/WinNUT-client.vbproj b/WinNUT_V2/WinNUT-Client/WinNUT-client.vbproj index 4ba31a3..6c27b26 100644 --- a/WinNUT_V2/WinNUT-Client/WinNUT-client.vbproj +++ b/WinNUT_V2/WinNUT-Client/WinNUT-client.vbproj @@ -124,6 +124,8 @@ LocalIntranet + + diff --git a/WinNUT_V2/WinNUT-Client_Common/WinNUT-Client_Common.vbproj b/WinNUT_V2/WinNUT-Client_Common/WinNUT-Client_Common.vbproj index 8e31f9d..3c382db 100644 --- a/WinNUT_V2/WinNUT-Client_Common/WinNUT-Client_Common.vbproj +++ b/WinNUT_V2/WinNUT-Client_Common/WinNUT-Client_Common.vbproj @@ -61,6 +61,8 @@ true + +