更改初版
This commit is contained in:
@@ -1,6 +1,7 @@
|
|||||||
using Example;
|
using Example;
|
||||||
using FreeSql;
|
using FreeSql;
|
||||||
using OrpaonEMS.App.Services;
|
using OrpaonEMS.App.Services;
|
||||||
|
using OrpaonEMS.App.CANDrive;
|
||||||
using OrpaonEMS.App.ViewModels;
|
using OrpaonEMS.App.ViewModels;
|
||||||
using OrpaonEMS.App.Views;
|
using OrpaonEMS.App.Views;
|
||||||
using OrpaonEMS.Core;
|
using OrpaonEMS.Core;
|
||||||
@@ -115,7 +116,8 @@ namespace OrpaonEMS.App
|
|||||||
services.RegisterForNavigation<ACView, ACViewModel>();
|
services.RegisterForNavigation<ACView, ACViewModel>();
|
||||||
services.RegisterForNavigation<FFView, FFViewModel>();
|
services.RegisterForNavigation<FFView, FFViewModel>();
|
||||||
services.RegisterForNavigation<SysConfigView, SysConfigViewModel>();
|
services.RegisterForNavigation<SysConfigView, SysConfigViewModel>();
|
||||||
|
services.RegisterForNavigation<ControlConfigView, ControlConfigViewModel>();
|
||||||
|
|
||||||
services.RegisterForNavigation<YuPuHandView, YuPuHandViewModel>();
|
services.RegisterForNavigation<YuPuHandView, YuPuHandViewModel>();
|
||||||
services.RegisterForNavigation<AutoHandView, AutoHandViewModel>();
|
services.RegisterForNavigation<AutoHandView, AutoHandViewModel>();
|
||||||
services.RegisterForNavigation<YuPuDashBoardView, YuPuDashBoardViewModel>();
|
services.RegisterForNavigation<YuPuDashBoardView, YuPuDashBoardViewModel>();
|
||||||
@@ -193,6 +195,9 @@ namespace OrpaonEMS.App
|
|||||||
ContainerLocator.Container.Resolve<EnergyStorageService>().WebSocketThreadEnable = false;
|
ContainerLocator.Container.Resolve<EnergyStorageService>().WebSocketThreadEnable = false;
|
||||||
ContainerLocator.Container.Resolve<EMSService>().ThreadEnable = false;
|
ContainerLocator.Container.Resolve<EMSService>().ThreadEnable = false;
|
||||||
|
|
||||||
|
// 确保停止 CAN 接收线程,避免前台线程阻塞进程退出
|
||||||
|
CAN.Stop();
|
||||||
|
|
||||||
energyStorageService.EnergyStorageStateMachine.Fire(Core.Enums.EnergyStorageStateTrig.HandTrig);
|
energyStorageService.EnergyStorageStateMachine.Fire(Core.Enums.EnergyStorageStateTrig.HandTrig);
|
||||||
base.OnExit(e);
|
base.OnExit(e);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -274,6 +274,21 @@ namespace OrpaonEMS.App.CANDrive
|
|||||||
Console.WriteLine("\nEMUC reveice start ...\n");
|
Console.WriteLine("\nEMUC reveice start ...\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 停止接收线程并关闭设备
|
||||||
|
/// </summary>
|
||||||
|
public static void Stop()
|
||||||
|
{
|
||||||
|
try { Global.StopRequested = true; } catch { }
|
||||||
|
try {
|
||||||
|
if (Global.TRDRecv != null && Global.TRDRecv.IsAlive)
|
||||||
|
{
|
||||||
|
Global.TRDRecv.Join(500);
|
||||||
|
}
|
||||||
|
} catch { }
|
||||||
|
try { if (Global.com_port >= 0) EMUCCloseDevice(Global.com_port); } catch { }
|
||||||
|
}
|
||||||
|
|
||||||
public void StartTest()
|
public void StartTest()
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
@@ -550,7 +565,7 @@ namespace OrpaonEMS.App.CANDrive
|
|||||||
int i;
|
int i;
|
||||||
int rtn;
|
int rtn;
|
||||||
|
|
||||||
while (true)
|
while (!Global.StopRequested)
|
||||||
{
|
{
|
||||||
rtn = EMUCReceive(Global.com_port, ref Global.frame_recv);
|
rtn = EMUCReceive(Global.com_port, ref Global.frame_recv);
|
||||||
|
|
||||||
@@ -677,6 +692,10 @@ namespace OrpaonEMS.App.CANDrive
|
|||||||
public static uint recv_cnt1 = 0;
|
public static uint recv_cnt1 = 0;
|
||||||
public static uint recv_cnt2 = 0;
|
public static uint recv_cnt2 = 0;
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
/// 停止标志
|
||||||
|
/// </summary>
|
||||||
|
public static volatile bool StopRequested = false;
|
||||||
|
/// <summary>
|
||||||
/// 版本信息
|
/// 版本信息
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static VER_INFO ver_info = new VER_INFO();
|
public static VER_INFO ver_info = new VER_INFO();
|
||||||
@@ -688,7 +707,7 @@ namespace OrpaonEMS.App.CANDrive
|
|||||||
public static CAN_FRAME_INFO frame_send = new CAN_FRAME_INFO();
|
public static CAN_FRAME_INFO frame_send = new CAN_FRAME_INFO();
|
||||||
public static CAN_FRAME_INFO frame_recv = new CAN_FRAME_INFO();
|
public static CAN_FRAME_INFO frame_recv = new CAN_FRAME_INFO();
|
||||||
|
|
||||||
public static Thread TRDRecv = new Thread(TRDRecvFx);
|
public static Thread TRDRecv = new Thread(TRDRecvFx) { IsBackground = true };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
24
OrpaonEMS.App/Config/ControlConfigValue.json
Normal file
24
OrpaonEMS.App/Config/ControlConfigValue.json
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
{
|
||||||
|
"SolarToEsAsFullSoc": 97,
|
||||||
|
"Master_ToSlaveByMasterSoc" : 5,
|
||||||
|
"Master_ToSlaveBySlaveSoc": 15,
|
||||||
|
"Master_SolarToSlaveEsFullByMasterSoc": 95,
|
||||||
|
"Slave_ToMasterBySlaveSoc": 5,
|
||||||
|
"Slave_ToMasterByMasterSoc": 15,
|
||||||
|
"Slave_SolarToMasterEsFullBySlaverSoc": 95,
|
||||||
|
"NightMaster_ToMasterFullSoc": 98,
|
||||||
|
"NightSlave_ToSlaveFullSoc": 80,
|
||||||
|
|
||||||
|
"DisChargeModel": [
|
||||||
|
{
|
||||||
|
"Model": 1,
|
||||||
|
"DisChargeTime": "08:00"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Model": 2,
|
||||||
|
"DisChargeTime": "11:00"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
|
||||||
|
"SelectedDisChargeModel ": 1
|
||||||
|
}
|
||||||
145
OrpaonEMS.App/Models/ControlConfigValue.cs
Normal file
145
OrpaonEMS.App/Models/ControlConfigValue.cs
Normal file
@@ -0,0 +1,145 @@
|
|||||||
|
using Prism.Mvvm;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace OrpaonEMS.App.Models
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 控制参数配置值
|
||||||
|
/// </summary>
|
||||||
|
public class ControlConfigValue : BindableBase
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 实例化函数
|
||||||
|
/// </summary>
|
||||||
|
public ControlConfigValue()
|
||||||
|
{
|
||||||
|
SolarToEsAsFullSoc = 97;
|
||||||
|
Master_ToSlaveByMasterSoc = 5;
|
||||||
|
Master_ToSlaveBySlaveSoc = 15;
|
||||||
|
Master_SolarToSlaveEsFullByMasterSoc = 95;
|
||||||
|
Slave_ToMasterBySlaveSoc = 5;
|
||||||
|
Slave_ToMasterByMasterSoc = 15;
|
||||||
|
Slave_SolarToMasterEsFullBySlaverSoc = 95;
|
||||||
|
NightMaster_ToMasterFullSoc = 98;
|
||||||
|
NightSlave_ToSlaveFullSoc = 98;
|
||||||
|
DisChargeModel = new List<DisChargeModelItem>();
|
||||||
|
SelectedDisChargeModel = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
private double _SolarToEsAsFullSoc;
|
||||||
|
/// <summary>
|
||||||
|
/// 光伏给储能充电 作为满的比值
|
||||||
|
/// 90-97
|
||||||
|
/// </summary>
|
||||||
|
public double SolarToEsAsFullSoc
|
||||||
|
{
|
||||||
|
get { return _SolarToEsAsFullSoc; }
|
||||||
|
set { _SolarToEsAsFullSoc = value; RaisePropertyChanged(); }
|
||||||
|
}
|
||||||
|
|
||||||
|
private double _Master_ToSlaveByMasterSoc;
|
||||||
|
/// <summary>
|
||||||
|
/// Master模式,切换到Slave模式时MasterSOC的阈值
|
||||||
|
/// </summary>
|
||||||
|
public double Master_ToSlaveByMasterSoc
|
||||||
|
{
|
||||||
|
get { return _Master_ToSlaveByMasterSoc; }
|
||||||
|
set { _Master_ToSlaveByMasterSoc = value; RaisePropertyChanged(); }
|
||||||
|
}
|
||||||
|
|
||||||
|
private double _Master_ToSlaveBySlaveSoc;
|
||||||
|
/// <summary>
|
||||||
|
/// Master模式,切换到Slave模式时Slave SOC的阀值
|
||||||
|
/// 两个同时考虑
|
||||||
|
/// </summary>
|
||||||
|
public double Master_ToSlaveBySlaveSoc
|
||||||
|
{
|
||||||
|
get { return _Master_ToSlaveBySlaveSoc; }
|
||||||
|
set { _Master_ToSlaveBySlaveSoc = value; RaisePropertyChanged(); }
|
||||||
|
}
|
||||||
|
|
||||||
|
private double _Master_SolarToSlaveEsFullByMasterSoc;
|
||||||
|
/// <summary>
|
||||||
|
/// Master模式,光伏给从储能充满了,是否切换到Slave模式,但是此时需要判断主储能MasterSOC是否满了(主储能也满的话,也无法接收光伏的电),否则不切换
|
||||||
|
/// 主要考虑尽可能的不浪费光伏的电,主从储能只要有余量就要接受光伏的电,也要防止频繁的切换
|
||||||
|
/// < SolarToEsAsFullSoc
|
||||||
|
/// </summary>
|
||||||
|
public double Master_SolarToSlaveEsFullByMasterSoc
|
||||||
|
{
|
||||||
|
get { return _Master_SolarToSlaveEsFullByMasterSoc; }
|
||||||
|
set { _Master_SolarToSlaveEsFullByMasterSoc = value; RaisePropertyChanged(); }
|
||||||
|
}
|
||||||
|
|
||||||
|
private double _Slave_ToMasterBySlaveSoc;
|
||||||
|
/// <summary>
|
||||||
|
/// Slave模式,切换到Master模式时SOC的阀值
|
||||||
|
/// 两个同时考虑
|
||||||
|
/// </summary>
|
||||||
|
public double Slave_ToMasterBySlaveSoc
|
||||||
|
{
|
||||||
|
get { return _Slave_ToMasterBySlaveSoc; }
|
||||||
|
set { _Slave_ToMasterBySlaveSoc = value; RaisePropertyChanged(); }
|
||||||
|
}
|
||||||
|
|
||||||
|
private double _Slave_ToMasterByMasterSoc;
|
||||||
|
/// <summary>
|
||||||
|
/// Slave模式,切换到Master模式时SOC的阀值
|
||||||
|
/// 两个同时考虑
|
||||||
|
/// </summary>
|
||||||
|
public double Slave_ToMasterByMasterSoc
|
||||||
|
{
|
||||||
|
get { return _Slave_ToMasterByMasterSoc; }
|
||||||
|
set { _Slave_ToMasterByMasterSoc = value; RaisePropertyChanged(); }
|
||||||
|
}
|
||||||
|
|
||||||
|
private double _Slave_SolarToMasterEsFullBySlaverSoc;
|
||||||
|
/// <summary>
|
||||||
|
/// Slave模式,光伏给主储能充满了,是否切换到Master模式,但是此时需要判断从储能SOC是否满了(从储能也满的话,也无法接收光伏的电),否则不切换
|
||||||
|
/// 主要考虑尽可能的不浪费光伏的电,主从储能只要有余量就要接受光伏的电,也要防止频繁的切换
|
||||||
|
/// < SolarToEsAsFullSoc
|
||||||
|
/// </summary>
|
||||||
|
public double Slave_SolarToMasterEsFullBySlaverSoc
|
||||||
|
{
|
||||||
|
get { return _Slave_SolarToMasterEsFullBySlaverSoc; }
|
||||||
|
set { _Slave_SolarToMasterEsFullBySlaverSoc = value; RaisePropertyChanged(); }
|
||||||
|
}
|
||||||
|
|
||||||
|
private double _NightMaster_ToMasterFullSoc;
|
||||||
|
/// <summary>
|
||||||
|
/// 晚上,主储能充满的标志,也是切换到从储能的控制标志
|
||||||
|
/// </summary>
|
||||||
|
public double NightMaster_ToMasterFullSoc
|
||||||
|
{
|
||||||
|
get { return _NightMaster_ToMasterFullSoc; }
|
||||||
|
set { _NightMaster_ToMasterFullSoc = value; RaisePropertyChanged(); }
|
||||||
|
}
|
||||||
|
|
||||||
|
private double _NightSlave_ToSlaveFullSoc;
|
||||||
|
/// <summary>
|
||||||
|
/// 晚上,从储能充满的标志,也是切换到主储能的控制标志
|
||||||
|
/// </summary>
|
||||||
|
public double NightSlave_ToSlaveFullSoc
|
||||||
|
{
|
||||||
|
get { return _NightSlave_ToSlaveFullSoc; }
|
||||||
|
set { _NightSlave_ToSlaveFullSoc = value; RaisePropertyChanged(); }
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<DisChargeModelItem> _DisChargeModel;
|
||||||
|
public List<DisChargeModelItem> DisChargeModel
|
||||||
|
{
|
||||||
|
get { return _DisChargeModel; }
|
||||||
|
set { _DisChargeModel = value; RaisePropertyChanged(); }
|
||||||
|
}
|
||||||
|
|
||||||
|
private int _SelectedDisChargeModel;
|
||||||
|
public int SelectedDisChargeModel
|
||||||
|
{
|
||||||
|
get { return _SelectedDisChargeModel; }
|
||||||
|
set { _SelectedDisChargeModel = value; RaisePropertyChanged(); }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
10
OrpaonEMS.App/Models/DisChargeModelItem.cs
Normal file
10
OrpaonEMS.App/Models/DisChargeModelItem.cs
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace OrpaonEMS.App.Models
|
||||||
|
{
|
||||||
|
public class DisChargeModelItem
|
||||||
|
{
|
||||||
|
public int Model { get; set; }
|
||||||
|
public string DisChargeTime { get; set; } = string.Empty;
|
||||||
|
}
|
||||||
|
}
|
||||||
80
OrpaonEMS.App/Models/DischargeTimeModel.cs
Normal file
80
OrpaonEMS.App/Models/DischargeTimeModel.cs
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Windows.System.Power;
|
||||||
|
|
||||||
|
namespace OrpaonEMS.App.Models
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 放电时间模型
|
||||||
|
/// 7、8月份11点放电
|
||||||
|
/// 其他月份8点开始放点
|
||||||
|
/// </summary>
|
||||||
|
public class DischargeTimeModel
|
||||||
|
{
|
||||||
|
public DischargeTimeModel(DisChargeType disChargeType)
|
||||||
|
{
|
||||||
|
|
||||||
|
CurDisChargeType = disChargeType;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 当前放电时间
|
||||||
|
/// </summary>
|
||||||
|
public DateTime CurDischargeTime { get; set; } = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day, 8, 0, 0);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 可以放电吗?
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
public bool IsCanDischarge()
|
||||||
|
{
|
||||||
|
DateTime currentTime = DateTime.Now;
|
||||||
|
DateTime curDischargeTime = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day, CurDischargeTime.Hour, 0, 0);
|
||||||
|
|
||||||
|
// Check if current time is after the configured discharge time
|
||||||
|
if (currentTime.TimeOfDay >= curDischargeTime.TimeOfDay)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Not yet time to discharge
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private DisChargeType _CurDisChargeType;
|
||||||
|
/// <summary>
|
||||||
|
/// 当前放电模式
|
||||||
|
/// </summary>
|
||||||
|
public DisChargeType CurDisChargeType
|
||||||
|
{
|
||||||
|
get { return _CurDisChargeType; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_CurDisChargeType = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 放电类型
|
||||||
|
/// </summary>
|
||||||
|
public enum DisChargeType
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 放电模式A
|
||||||
|
/// </summary>
|
||||||
|
DischargeA = 1,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 放电模式B
|
||||||
|
/// </summary>
|
||||||
|
DischargeB = 2,
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -417,6 +417,7 @@ namespace OrpaonEMS.App.Services
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public void CloseDrive()
|
public void CloseDrive()
|
||||||
{
|
{
|
||||||
|
ThreadEnable = false;
|
||||||
ModbusTcpNetDrive.ConnectClose();
|
ModbusTcpNetDrive.ConnectClose();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -11,8 +11,10 @@ using Prism.Mvvm;
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using System.Text.Json;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using System.Windows.Documents;
|
using System.Windows.Documents;
|
||||||
|
|
||||||
@@ -68,6 +70,9 @@ namespace OrpaonEMS.App.Services
|
|||||||
ListEnergyStoragePeakValleyTimeConfig = FreeSql.Select<PeakValleyConfig>().ToList();
|
ListEnergyStoragePeakValleyTimeConfig = FreeSql.Select<PeakValleyConfig>().ToList();
|
||||||
//削峰填谷模式的时间监视线程
|
//削峰填谷模式的时间监视线程
|
||||||
var ListenPeakValleyTimeTaskInfo = Task.Run(() => ListenPeakValleyTimeCycle());
|
var ListenPeakValleyTimeTaskInfo = Task.Run(() => ListenPeakValleyTimeCycle());
|
||||||
|
|
||||||
|
//加载控制参数配置
|
||||||
|
LoadControlConfigValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -427,5 +432,421 @@ namespace OrpaonEMS.App.Services
|
|||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
#region 控制参数配置
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 控制参数配置文件路径
|
||||||
|
/// </summary>
|
||||||
|
private readonly string _controlConfigFilePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Config", "ControlConfigValue.json");
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 控制参数配置值
|
||||||
|
/// </summary>
|
||||||
|
public ControlConfigValue ControlConfigValue { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 加载控制参数配置
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>返回加载结果,true表示成功,false表示失败</returns>
|
||||||
|
public bool LoadControlConfigValue()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// 确保目录存在
|
||||||
|
string directory = Path.GetDirectoryName(_controlConfigFilePath);
|
||||||
|
if (!Directory.Exists(directory))
|
||||||
|
{
|
||||||
|
Directory.CreateDirectory(directory);
|
||||||
|
LogService.Info($"创建配置目录: {directory}");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查文件是否存在
|
||||||
|
if (File.Exists(_controlConfigFilePath))
|
||||||
|
{
|
||||||
|
// 读取JSON文件内容
|
||||||
|
string jsonContent = File.ReadAllText(_controlConfigFilePath, Encoding.UTF8);
|
||||||
|
|
||||||
|
// 检查文件是否为空或只包含空对象
|
||||||
|
if (string.IsNullOrWhiteSpace(jsonContent) || jsonContent.Trim() == "{}" || jsonContent.Trim() == "{\r\n \r\n}")
|
||||||
|
{
|
||||||
|
// 文件为空,创建默认配置
|
||||||
|
LogService.Info("控制参数配置文件为空,创建默认配置");
|
||||||
|
ControlConfigValue = new ControlConfigValue();
|
||||||
|
SaveControlConfigValue();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// 反序列化JSON到对象
|
||||||
|
var options = new JsonSerializerOptions
|
||||||
|
{
|
||||||
|
PropertyNameCaseInsensitive = true,
|
||||||
|
WriteIndented = true,
|
||||||
|
Encoder = System.Text.Encodings.Web.JavaScriptEncoder.UnsafeRelaxedJsonEscaping
|
||||||
|
};
|
||||||
|
|
||||||
|
ControlConfigValue = JsonSerializer.Deserialize<ControlConfigValue>(jsonContent, options);
|
||||||
|
|
||||||
|
// 验证反序列化结果
|
||||||
|
if (ControlConfigValue == null)
|
||||||
|
{
|
||||||
|
LogService.Warn("控制参数配置反序列化失败,使用默认配置");
|
||||||
|
ControlConfigValue = new ControlConfigValue();
|
||||||
|
SaveControlConfigValue();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LogService.Info("成功加载控制参数配置");
|
||||||
|
|
||||||
|
// 兼容键名末尾带空格的 SelectedDisChargeModel
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using (var doc = JsonDocument.Parse(jsonContent))
|
||||||
|
{
|
||||||
|
var root = doc.RootElement;
|
||||||
|
if (root.TryGetProperty("SelectedDisChargeModel ", out var selectedProp))
|
||||||
|
{
|
||||||
|
if (selectedProp.ValueKind == JsonValueKind.Number)
|
||||||
|
{
|
||||||
|
ControlConfigValue.SelectedDisChargeModel = selectedProp.GetInt32();
|
||||||
|
}
|
||||||
|
else if (selectedProp.ValueKind == JsonValueKind.String && int.TryParse(selectedProp.GetString(), out var selInt))
|
||||||
|
{
|
||||||
|
ControlConfigValue.SelectedDisChargeModel = selInt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
LogService.Warn($"SelectedDisChargeModel(带空格) 兼容解析失败: {ex.Message}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// 文件不存在,创建默认配置
|
||||||
|
LogService.Info($"控制参数配置文件不存在,创建默认配置: {_controlConfigFilePath}");
|
||||||
|
ControlConfigValue = new ControlConfigValue();
|
||||||
|
SaveControlConfigValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 兼容旧配置:确保 DisChargeModel 非空,并在为空列表时注入默认项
|
||||||
|
if (ControlConfigValue != null)
|
||||||
|
{
|
||||||
|
if (ControlConfigValue.DisChargeModel == null)
|
||||||
|
{
|
||||||
|
ControlConfigValue.DisChargeModel = new List<DisChargeModelItem>();
|
||||||
|
}
|
||||||
|
if (ControlConfigValue.DisChargeModel.Count == 0)
|
||||||
|
{
|
||||||
|
ControlConfigValue.DisChargeModel.Add(new DisChargeModelItem { Model = 1, DisChargeTime = "08:00" });
|
||||||
|
ControlConfigValue.DisChargeModel.Add(new DisChargeModelItem { Model = 2, DisChargeTime = "11:00" });
|
||||||
|
if (ControlConfigValue.SelectedDisChargeModel <= 0)
|
||||||
|
{
|
||||||
|
ControlConfigValue.SelectedDisChargeModel = 1;
|
||||||
|
}
|
||||||
|
// 保存注入的默认配置
|
||||||
|
SaveControlConfigValue();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch (JsonException jsonEx)
|
||||||
|
{
|
||||||
|
// JSON解析错误
|
||||||
|
LogService.Error($"控制参数配置JSON解析错误: {jsonEx.Message}");
|
||||||
|
LogService.Error($"异常堆栈: {jsonEx.StackTrace}");
|
||||||
|
|
||||||
|
// 使用默认配置
|
||||||
|
ControlConfigValue = new ControlConfigValue();
|
||||||
|
|
||||||
|
// 尝试备份损坏的文件
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (File.Exists(_controlConfigFilePath))
|
||||||
|
{
|
||||||
|
string backupPath = $"{_controlConfigFilePath}.backup_{DateTime.Now:yyyyMMddHHmmss}";
|
||||||
|
File.Copy(_controlConfigFilePath, backupPath, true);
|
||||||
|
LogService.Info($"已备份损坏的配置文件到: {backupPath}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception backupEx)
|
||||||
|
{
|
||||||
|
LogService.Error($"备份损坏的配置文件失败: {backupEx.Message}");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 保存默认配置
|
||||||
|
SaveControlConfigValue();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
// 其他异常
|
||||||
|
LogService.Error($"加载控制参数配置时发生异常: {ex.Message}");
|
||||||
|
LogService.Error($"异常类型: {ex.GetType().Name}");
|
||||||
|
LogService.Error($"异常堆栈: {ex.StackTrace}");
|
||||||
|
|
||||||
|
// 使用默认配置
|
||||||
|
ControlConfigValue = new ControlConfigValue();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 保存控制参数配置
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>返回保存结果,true表示成功,false表示失败</returns>
|
||||||
|
public bool SaveControlConfigValue()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// 验证配置对象
|
||||||
|
if (ControlConfigValue == null)
|
||||||
|
{
|
||||||
|
LogService.Error("控制参数配置对象为空,无法保存");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 确保目录存在
|
||||||
|
string directory = Path.GetDirectoryName(_controlConfigFilePath);
|
||||||
|
if (!Directory.Exists(directory))
|
||||||
|
{
|
||||||
|
Directory.CreateDirectory(directory);
|
||||||
|
LogService.Info($"创建配置目录: {directory}");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 序列化对象到JSON
|
||||||
|
var options = new JsonSerializerOptions
|
||||||
|
{
|
||||||
|
WriteIndented = true,
|
||||||
|
Encoder = System.Text.Encodings.Web.JavaScriptEncoder.UnsafeRelaxedJsonEscaping
|
||||||
|
};
|
||||||
|
|
||||||
|
string jsonContent = JsonSerializer.Serialize(ControlConfigValue, options);
|
||||||
|
|
||||||
|
// 写入文件前先写入临时文件
|
||||||
|
string tempFilePath = $"{_controlConfigFilePath}.tmp";
|
||||||
|
File.WriteAllText(tempFilePath, jsonContent, Encoding.UTF8);
|
||||||
|
|
||||||
|
// 验证临时文件是否写入成功
|
||||||
|
if (File.Exists(tempFilePath))
|
||||||
|
{
|
||||||
|
// 备份原文件(如果存在)
|
||||||
|
if (File.Exists(_controlConfigFilePath))
|
||||||
|
{
|
||||||
|
string backupPath = $"{_controlConfigFilePath}.bak";
|
||||||
|
File.Copy(_controlConfigFilePath, backupPath, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 用临时文件替换原文件
|
||||||
|
File.Copy(tempFilePath, _controlConfigFilePath, true);
|
||||||
|
File.Delete(tempFilePath);
|
||||||
|
|
||||||
|
LogService.Info($"成功保存控制参数配置到: {_controlConfigFilePath}");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LogService.Error("临时配置文件写入失败");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (IOException ioEx)
|
||||||
|
{
|
||||||
|
// 文件IO异常
|
||||||
|
LogService.Error($"保存控制参数配置时发生IO异常: {ioEx.Message}");
|
||||||
|
LogService.Error($"异常堆栈: {ioEx.StackTrace}");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
catch (JsonException jsonEx)
|
||||||
|
{
|
||||||
|
// JSON序列化异常
|
||||||
|
LogService.Error($"控制参数配置JSON序列化错误: {jsonEx.Message}");
|
||||||
|
LogService.Error($"异常堆栈: {jsonEx.StackTrace}");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
// 其他异常
|
||||||
|
LogService.Error($"保存控制参数配置时发生异常: {ex.Message}");
|
||||||
|
LogService.Error($"异常类型: {ex.GetType().Name}");
|
||||||
|
LogService.Error($"异常堆栈: {ex.StackTrace}");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 更新控制参数配置的值并保存
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="configValue">要更新的控制参数配置对象</param>
|
||||||
|
/// <returns>返回更新结果,true表示成功,false表示失败</returns>
|
||||||
|
public bool UpdateControlConfigValue(ControlConfigValue configValue)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (configValue == null)
|
||||||
|
{
|
||||||
|
LogService.Error("传入的控制参数配置对象为空");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 更新配置值
|
||||||
|
ControlConfigValue.SolarToEsAsFullSoc = configValue.SolarToEsAsFullSoc;
|
||||||
|
ControlConfigValue.Master_ToSlaveByMasterSoc = configValue.Master_ToSlaveByMasterSoc;
|
||||||
|
ControlConfigValue.Master_ToSlaveBySlaveSoc = configValue.Master_ToSlaveBySlaveSoc;
|
||||||
|
ControlConfigValue.Master_SolarToSlaveEsFullByMasterSoc = configValue.Master_SolarToSlaveEsFullByMasterSoc;
|
||||||
|
ControlConfigValue.Slave_ToMasterBySlaveSoc = configValue.Slave_ToMasterBySlaveSoc;
|
||||||
|
ControlConfigValue.Slave_ToMasterByMasterSoc = configValue.Slave_ToMasterByMasterSoc;
|
||||||
|
ControlConfigValue.Slave_SolarToMasterEsFullBySlaverSoc = configValue.Slave_SolarToMasterEsFullBySlaverSoc;
|
||||||
|
ControlConfigValue.NightMaster_ToMasterFullSoc = configValue.NightMaster_ToMasterFullSoc;
|
||||||
|
ControlConfigValue.NightSlave_ToSlaveFullSoc = configValue.NightSlave_ToSlaveFullSoc;
|
||||||
|
|
||||||
|
// 保存到文件
|
||||||
|
bool saveResult = SaveControlConfigValue();
|
||||||
|
|
||||||
|
if (saveResult)
|
||||||
|
{
|
||||||
|
LogService.Info("成功更新并保存控制参数配置");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LogService.Error("更新控制参数配置后保存失败");
|
||||||
|
}
|
||||||
|
|
||||||
|
return saveResult;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
LogService.Error($"更新控制参数配置时发生异常: {ex.Message}");
|
||||||
|
LogService.Error($"异常堆栈: {ex.StackTrace}");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取放电时间配置集合
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>放电时间配置列表(永不返回 null)</returns>
|
||||||
|
public List<DisChargeModelItem> GetDisChargeModel()
|
||||||
|
{
|
||||||
|
if (ControlConfigValue == null)
|
||||||
|
{
|
||||||
|
ControlConfigValue = new ControlConfigValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ControlConfigValue.DisChargeModel == null)
|
||||||
|
{
|
||||||
|
ControlConfigValue.DisChargeModel = new List<DisChargeModelItem>();
|
||||||
|
}
|
||||||
|
|
||||||
|
return ControlConfigValue.DisChargeModel;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 保存放电时间配置集合
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="items">放电时间配置列表</param>
|
||||||
|
/// <returns>保存结果</returns>
|
||||||
|
public bool SaveDisChargeModel(List<DisChargeModelItem> items)
|
||||||
|
{
|
||||||
|
if (ControlConfigValue == null)
|
||||||
|
{
|
||||||
|
ControlConfigValue = new ControlConfigValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 基础校验
|
||||||
|
var list = items ?? new List<DisChargeModelItem>();
|
||||||
|
foreach (var it in list)
|
||||||
|
{
|
||||||
|
if (it == null)
|
||||||
|
{
|
||||||
|
LogService.Error("DisChargeModel 中存在空项");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (string.IsNullOrWhiteSpace(it.DisChargeTime))
|
||||||
|
{
|
||||||
|
LogService.Error("DisChargeModel.DisChargeTime 为空");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!TimeSpan.TryParse(it.DisChargeTime, out _))
|
||||||
|
{
|
||||||
|
LogService.Error($"DisChargeModel.DisChargeTime 格式非法: {it.DisChargeTime},期望 HH:mm");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ControlConfigValue.DisChargeModel = list;
|
||||||
|
return SaveControlConfigValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 时间上是否可以放电
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
public bool IsTimeCanDischarge()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// 确保配置加载
|
||||||
|
if (ControlConfigValue == null)
|
||||||
|
{
|
||||||
|
LoadControlConfigValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取放电时间集合(内部已保证非 null)
|
||||||
|
var list = GetDisChargeModel();
|
||||||
|
|
||||||
|
// 选中模式 Id(缺省=1)
|
||||||
|
int selectedId = 1;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
selectedId = ControlConfigValue?.SelectedDisChargeModel ?? 1;
|
||||||
|
}
|
||||||
|
catch { selectedId = 1; }
|
||||||
|
|
||||||
|
// 查找选中项,找不到回退第一项
|
||||||
|
DisChargeModelItem selected = null;
|
||||||
|
if (list != null && list.Count > 0)
|
||||||
|
{
|
||||||
|
foreach (var it in list)
|
||||||
|
{
|
||||||
|
if (it != null && it.Model == selectedId)
|
||||||
|
{
|
||||||
|
selected = it;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (selected == null)
|
||||||
|
{
|
||||||
|
selected = list[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 解析时间(HH:mm),失败回退 08:00
|
||||||
|
TimeSpan target;
|
||||||
|
if (selected != null && !string.IsNullOrWhiteSpace(selected.DisChargeTime) && TimeSpan.TryParse(selected.DisChargeTime, out target))
|
||||||
|
{
|
||||||
|
return DateTime.Now.TimeOfDay >= target;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LogService.Warn("IsTimeCanDischarge: 配置时间缺失或格式非法,使用默认 08:00 进行比较");
|
||||||
|
target = new TimeSpan(8, 0, 0);
|
||||||
|
return DateTime.Now.TimeOfDay >= target;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
LogService.Error($"IsTimeCanDischarge 执行失败: {ex.Message}");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -166,6 +166,16 @@ namespace OrpaonEMS.App.Services
|
|||||||
set { _LinkStateMsg = value; RaisePropertyChanged(); }
|
set { _LinkStateMsg = value; RaisePropertyChanged(); }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 关闭连接
|
||||||
|
/// </summary>
|
||||||
|
public void CloseDrive()
|
||||||
|
{
|
||||||
|
ThreadEnable=false;
|
||||||
|
if (ModbusRtuDrive!=null) ModbusRtuDrive!.Close();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
#region 消防数据
|
#region 消防数据
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -91,7 +91,7 @@ namespace OrpaonEMS.App.Services
|
|||||||
MessageBox.Show("PCS 连接失败");
|
MessageBox.Show("PCS 连接失败");
|
||||||
}
|
}
|
||||||
|
|
||||||
PwTranceCmdValues = new TranceCmdValue(0.7);
|
PwTranceCmdValues = new TranceCmdValue(2);
|
||||||
PwTranceCmdValues.CmdValueChanged += PwTranceCmdValues_CmdValueChanged;
|
PwTranceCmdValues.CmdValueChanged += PwTranceCmdValues_CmdValueChanged;
|
||||||
|
|
||||||
//CurPcsAlarmModel = new PcsAlarmModel();
|
//CurPcsAlarmModel = new PcsAlarmModel();
|
||||||
@@ -768,6 +768,7 @@ namespace OrpaonEMS.App.Services
|
|||||||
public void CloseModbusRtu()
|
public void CloseModbusRtu()
|
||||||
{
|
{
|
||||||
ThreadEnable = false;
|
ThreadEnable = false;
|
||||||
|
CurTimer.Stop();
|
||||||
ModbusTcpNetDrive.ConnectClose();
|
ModbusTcpNetDrive.ConnectClose();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -65,6 +65,7 @@ namespace OrpaonEMS.App.Services
|
|||||||
MenuItems.Add(new NavigationItem("FireExtinguisher", "消防", "FFView"));
|
MenuItems.Add(new NavigationItem("FireExtinguisher", "消防", "FFView"));
|
||||||
MenuItems.Add(new NavigationItem("CogRefreshOutline", "配置", "SysConfigView"));
|
MenuItems.Add(new NavigationItem("CogRefreshOutline", "配置", "SysConfigView"));
|
||||||
MenuItems.Add(new NavigationItem("RefreshAuto", "手自动", "AutoHandView"));
|
MenuItems.Add(new NavigationItem("RefreshAuto", "手自动", "AutoHandView"));
|
||||||
|
MenuItems.Add(new NavigationItem("ControlConfigView", "控制设置", "ControlConfigView"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,10 +26,13 @@ namespace OrpaonEMS.App.Services
|
|||||||
{
|
{
|
||||||
///////
|
///////
|
||||||
/////怎么认定为晚上,光伏发电功率低于一个阈值时可认为是晚上
|
/////怎么认定为晚上,光伏发电功率低于一个阈值时可认为是晚上
|
||||||
public YuePuRunModelService(ILogService logService, ConfigDataService configDataService,
|
public YuePuRunModelService(ILogService logService, ConfigDataService configDataService,BmsDataService bmsDataService,FFService fFService, InPowerPCSDataService inPowerPCSDataService,
|
||||||
IEventAggregator eventAggregator)
|
IEventAggregator eventAggregator)
|
||||||
{
|
{
|
||||||
ConfigDataService = configDataService;
|
ConfigDataService = configDataService;
|
||||||
|
BmsDataService = bmsDataService;
|
||||||
|
FFService = fFService;
|
||||||
|
InPowerPCSDataService = inPowerPCSDataService;
|
||||||
LogService = logService;
|
LogService = logService;
|
||||||
|
|
||||||
//CurNightChargEleModel = new NightChargEleModel(ConfigDataService);
|
//CurNightChargEleModel = new NightChargEleModel(ConfigDataService);
|
||||||
@@ -131,6 +134,64 @@ namespace OrpaonEMS.App.Services
|
|||||||
//QFSwitch2.SetRtSwitch(SwitchEm.Off);
|
//QFSwitch2.SetRtSwitch(SwitchEm.Off);
|
||||||
//QFSwitch1.SetRtSwitch(SwitchEm.On);
|
//QFSwitch1.SetRtSwitch(SwitchEm.On);
|
||||||
|
|
||||||
|
// 放电时间模型初始化:基于配置的 DisChargeModel 列表与 SelectedDisChargeModel
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var list = ConfigDataService.GetDisChargeModel();
|
||||||
|
int selectedId = 1;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
selectedId = ConfigDataService.ControlConfigValue?.SelectedDisChargeModel ?? 1;
|
||||||
|
}
|
||||||
|
catch { selectedId = 1; }
|
||||||
|
|
||||||
|
DisChargeModelItem? selected = null;
|
||||||
|
if (list != null && list.Count > 0)
|
||||||
|
{
|
||||||
|
foreach (var it in list)
|
||||||
|
{
|
||||||
|
if (it != null && it.Model == selectedId)
|
||||||
|
{
|
||||||
|
selected = it;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (selected == null)
|
||||||
|
{
|
||||||
|
selected = list[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 映射到旧的枚举(如可用),否则回退到 DischargeA
|
||||||
|
var enumValue = DisChargeType.DischargeA;
|
||||||
|
if (selected != null && System.Enum.IsDefined(typeof(DisChargeType), selected.Model))
|
||||||
|
{
|
||||||
|
enumValue = (DisChargeType)selected.Model;
|
||||||
|
}
|
||||||
|
|
||||||
|
CurDischargeTimeModel = new DischargeTimeModel(enumValue);
|
||||||
|
|
||||||
|
// 设置具体时间(优先使用配置时间),格式期望 HH:mm
|
||||||
|
if (selected != null && !string.IsNullOrWhiteSpace(selected.DisChargeTime) && TimeSpan.TryParse(selected.DisChargeTime, out var ts))
|
||||||
|
{
|
||||||
|
CurDischargeTimeModel.CurDischargeTime = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day, ts.Hours, ts.Minutes, 0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// 解析失败使用默认 08:00
|
||||||
|
CurDischargeTimeModel.CurDischargeTime = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day, 8, 0, 0);
|
||||||
|
LogService.Warn("DisChargeModel 配置时间缺失或格式非法,已使用默认 08:00");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (System.Exception ex)
|
||||||
|
{
|
||||||
|
// 失败时初始化为默认模式与时间
|
||||||
|
CurDischargeTimeModel = new DischargeTimeModel(DisChargeType.DischargeA)
|
||||||
|
{
|
||||||
|
CurDischargeTime = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day, 8, 0, 0)
|
||||||
|
};
|
||||||
|
LogService.Error($"初始化放电时间模型失败: {ex.Message}");
|
||||||
|
}
|
||||||
|
|
||||||
StateMachineInitial();
|
StateMachineInitial();
|
||||||
LogicScan();
|
LogicScan();
|
||||||
@@ -169,6 +230,11 @@ namespace OrpaonEMS.App.Services
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 当前的放电时间模型
|
||||||
|
/// </summary>
|
||||||
|
public DischargeTimeModel CurDischargeTimeModel { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 税务大楼光伏逆流触发模型
|
/// 税务大楼光伏逆流触发模型
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -911,7 +977,8 @@ namespace OrpaonEMS.App.Services
|
|||||||
//循环执行方法
|
//循环执行方法
|
||||||
|
|
||||||
//在峰的时候放电
|
//在峰的时候放电
|
||||||
if (PeakValleySglModel == ElePVEnum.TopPeak || PeakValleySglModel == ElePVEnum.Peak)
|
//if (PeakValleySglModel == ElePVEnum.TopPeak || PeakValleySglModel == ElePVEnum.Peak)
|
||||||
|
if (ConfigDataService.IsTimeCanDischarge())
|
||||||
{
|
{
|
||||||
///////////////////Slave从控制柜给管理大楼供电
|
///////////////////Slave从控制柜给管理大楼供电
|
||||||
//注意方向
|
//注意方向
|
||||||
@@ -1118,9 +1185,9 @@ namespace OrpaonEMS.App.Services
|
|||||||
//循环执行方法
|
//循环执行方法
|
||||||
|
|
||||||
//在峰的时候放电
|
//在峰的时候放电
|
||||||
if (PeakValleySglModel == ElePVEnum.TopPeak || PeakValleySglModel == ElePVEnum.Peak)
|
//if (PeakValleySglModel == ElePVEnum.TopPeak || PeakValleySglModel == ElePVEnum.Peak)
|
||||||
|
if (ConfigDataService.IsTimeCanDischarge())
|
||||||
{
|
{
|
||||||
|
|
||||||
///////////////////Master主控制柜给管理大楼供电
|
///////////////////Master主控制柜给管理大楼供电
|
||||||
//注意方向
|
//注意方向
|
||||||
//主储能箱体放电的控制
|
//主储能箱体放电的控制
|
||||||
@@ -1251,7 +1318,6 @@ namespace OrpaonEMS.App.Services
|
|||||||
|
|
||||||
SlaveControlMsg = "【从储能】充电吸收【光伏】电能:税务大楼负载小5,【从储能】最大功率充电吸收光伏电能,存在【逆流】可能性";
|
SlaveControlMsg = "【从储能】充电吸收【光伏】电能:税务大楼负载小5,【从储能】最大功率充电吸收光伏电能,存在【逆流】可能性";
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -1261,11 +1327,7 @@ namespace OrpaonEMS.App.Services
|
|||||||
|
|
||||||
SlaveControlMsg = "【从储能】充电吸收【光伏】电能:【从储能】无法充电,【从储能】停止工作";
|
SlaveControlMsg = "【从储能】充电吸收【光伏】电能:【从储能】无法充电,【从储能】停止工作";
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
@@ -1497,6 +1559,33 @@ namespace OrpaonEMS.App.Services
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private CancellationTokenSource NoSolarTokenSource { get; set; }
|
private CancellationTokenSource NoSolarTokenSource { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 关闭系统:停止线程循环并断开所有通信连接
|
||||||
|
/// </summary>
|
||||||
|
public void CloseSystem()
|
||||||
|
{
|
||||||
|
// 先关闭扫描线程使能,令 while(ThreadEnable) 循环尽快退出
|
||||||
|
try { ThreadEnable = false; } catch { }
|
||||||
|
try { MasterTokenSource?.Cancel(); } catch { }
|
||||||
|
try { SlaveTokenSource?.Cancel(); } catch { }
|
||||||
|
try { Night_MasterTokenSource?.Cancel(); } catch { }
|
||||||
|
try { Night_SlaveTokenSource?.Cancel(); } catch { }
|
||||||
|
try { WaitTokenSource?.Cancel(); } catch { }
|
||||||
|
try { NoSolarTokenSource?.Cancel(); } catch { }
|
||||||
|
|
||||||
|
// 停止输出,置零功率
|
||||||
|
try { if (SlaveClient != null) { SlaveClient.ServerCmd.CmdPw = 0; } } catch { }
|
||||||
|
try { if (MasterClient != null) { MasterClient.ServerCmd.CmdPw = 0; } } catch { }
|
||||||
|
|
||||||
|
// 断开设备通信
|
||||||
|
try { SolarMdDrive?.Close(); } catch { }
|
||||||
|
try { MeterMdDrive?.Close(); } catch { }
|
||||||
|
try { ModbusTcpNetDrive?.ConnectClose(); } catch { }
|
||||||
|
try { BmsDataService.CloseDrive(); } catch { }
|
||||||
|
try { FFService.CloseDrive(); } catch { }
|
||||||
|
try { InPowerPCSDataService.CloseModbusRtu(); } catch { }
|
||||||
|
|
||||||
|
}
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 预先状态
|
/// 预先状态
|
||||||
/// 就是确定目标状态,先进入准备状态时这个预先的状态信息,等条件具备后再进行操作
|
/// 就是确定目标状态,先进入准备状态时这个预先的状态信息,等条件具备后再进行操作
|
||||||
@@ -3173,7 +3262,7 @@ namespace OrpaonEMS.App.Services
|
|||||||
|
|
||||||
//用Soc小的吸收光伏能量
|
//用Soc小的吸收光伏能量
|
||||||
|
|
||||||
if (SlaveClient.ClientInfo!.SOC <= (SolarToEsAsFullSoc-10))
|
if (SlaveClient.ClientInfo!.SOC <= (SolarToEsAsFullSoc - 10))
|
||||||
{
|
{
|
||||||
LogService.Info($"时间:{DateTime.Now.ToString()}-【动作】-当前是【NoSolar】-从储能箱体SOC:{SlaveClient.ClientInfo!.SOC},主储能箱体SOC:{MasterClient.ClientInfo!.SOC},切换到Master");
|
LogService.Info($"时间:{DateTime.Now.ToString()}-【动作】-当前是【NoSolar】-从储能箱体SOC:{SlaveClient.ClientInfo!.SOC},主储能箱体SOC:{MasterClient.ClientInfo!.SOC},切换到Master");
|
||||||
|
|
||||||
@@ -3711,6 +3800,9 @@ namespace OrpaonEMS.App.Services
|
|||||||
/// 配置服务信息
|
/// 配置服务信息
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public ConfigDataService ConfigDataService { get; }
|
public ConfigDataService ConfigDataService { get; }
|
||||||
|
public BmsDataService BmsDataService { get; }
|
||||||
|
public FFService FFService { get; }
|
||||||
|
public InPowerPCSDataService InPowerPCSDataService { get; }
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
347
OrpaonEMS.App/ViewModels/ControlConfigViewModel.cs
Normal file
347
OrpaonEMS.App/ViewModels/ControlConfigViewModel.cs
Normal file
@@ -0,0 +1,347 @@
|
|||||||
|
using OrpaonEMS.App.Models;
|
||||||
|
using OrpaonEMS.App.Services;
|
||||||
|
using OrpaonEMS.Core;
|
||||||
|
using Prism.Commands;
|
||||||
|
using System;
|
||||||
|
using System.Collections.ObjectModel;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
namespace OrpaonEMS.App.ViewModels
|
||||||
|
{
|
||||||
|
public class ControlConfigViewModel : NavigationViewModel
|
||||||
|
{
|
||||||
|
public ControlConfigViewModel(YuePuRunModelService yuePuRunModelService, ConfigDataService configDataService)
|
||||||
|
{
|
||||||
|
YuePuRunModelService = yuePuRunModelService;
|
||||||
|
ConfigDataService = configDataService;
|
||||||
|
|
||||||
|
// 从配置文件加载参数
|
||||||
|
if (ConfigDataService.ControlConfigValue != null)
|
||||||
|
{
|
||||||
|
SolarToEsAsFullSoc = ConfigDataService.ControlConfigValue.SolarToEsAsFullSoc;
|
||||||
|
Master_ToSlaveByMasterSoc = ConfigDataService.ControlConfigValue.Master_ToSlaveByMasterSoc;
|
||||||
|
Master_ToSlaveBySlaveSoc = ConfigDataService.ControlConfigValue.Master_ToSlaveBySlaveSoc;
|
||||||
|
Master_SolarToSlaveEsFullByMasterSoc = ConfigDataService.ControlConfigValue.Master_SolarToSlaveEsFullByMasterSoc;
|
||||||
|
Slave_ToMasterBySlaveSoc = ConfigDataService.ControlConfigValue.Slave_ToMasterBySlaveSoc;
|
||||||
|
Slave_ToMasterByMasterSoc = ConfigDataService.ControlConfigValue.Slave_ToMasterByMasterSoc;
|
||||||
|
Slave_SolarToMasterEsFullBySlaverSoc = ConfigDataService.ControlConfigValue.Slave_SolarToMasterEsFullBySlaverSoc;
|
||||||
|
NightMaster_ToMasterFullSoc = ConfigDataService.ControlConfigValue.NightMaster_ToMasterFullSoc;
|
||||||
|
NightSlave_ToSlaveFullSoc = ConfigDataService.ControlConfigValue.NightSlave_ToSlaveFullSoc;
|
||||||
|
|
||||||
|
// 加载放电模式列表与已选项
|
||||||
|
var list = ConfigDataService.GetDisChargeModel();
|
||||||
|
DisChargeModels = new ObservableCollection<DisChargeModelItem>(list);
|
||||||
|
var sel = ConfigDataService.ControlConfigValue.SelectedDisChargeModel;
|
||||||
|
if (DisChargeModels != null && DisChargeModels.Count > 0)
|
||||||
|
{
|
||||||
|
// 若配置中无效则回落到第一个项
|
||||||
|
if (DisChargeModels.Any(m => m.Model == sel))
|
||||||
|
SelectedDisChargeModelId = sel;
|
||||||
|
else
|
||||||
|
SelectedDisChargeModelId = DisChargeModels[0].Model;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SelectedDisChargeModelId = 1;
|
||||||
|
}
|
||||||
|
// 与旧逻辑保持同步(可选)
|
||||||
|
if (System.Enum.IsDefined(typeof(DisChargeType), SelectedDisChargeModelId))
|
||||||
|
SelectedDisChargeType = (DisChargeType)SelectedDisChargeModelId;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 同步到运行模式服务
|
||||||
|
YuePuRunModelService.SolarToEsAsFullSoc = SolarToEsAsFullSoc;
|
||||||
|
YuePuRunModelService.Master_ToSlaveByMasterSoc = Master_ToSlaveByMasterSoc;
|
||||||
|
YuePuRunModelService.Master_ToSlaveBySlaveSoc = Master_ToSlaveBySlaveSoc;
|
||||||
|
YuePuRunModelService.Master_SolarToSlaveEsFullByMasterSoc = Master_SolarToSlaveEsFullByMasterSoc;
|
||||||
|
YuePuRunModelService.Slave_ToMasterBySlaveSoc = Slave_ToMasterBySlaveSoc;
|
||||||
|
YuePuRunModelService.Slave_ToMasterByMasterSoc = Slave_ToMasterByMasterSoc;
|
||||||
|
YuePuRunModelService.Slave_SolarToMasterEsFullBySlaverSoc = Slave_SolarToMasterEsFullBySlaverSoc;
|
||||||
|
YuePuRunModelService.NightMaster_ToMasterFullSoc = NightMaster_ToMasterFullSoc;
|
||||||
|
YuePuRunModelService.NightSlave_ToSlaveFullSoc = NightSlave_ToSlaveFullSoc;
|
||||||
|
|
||||||
|
|
||||||
|
//SelectedDisChargeType=
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private DelegateCommand<string> _BtnConfigSave;
|
||||||
|
/// <summary>
|
||||||
|
/// 运行模式操作
|
||||||
|
/// </summary>
|
||||||
|
public DelegateCommand<string> BtnConfigSave
|
||||||
|
{
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_BtnConfigSave = value;
|
||||||
|
}
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (_BtnConfigSave == null)
|
||||||
|
{
|
||||||
|
_BtnConfigSave = new DelegateCommand<string>((par) => BtnConfigSaveCall(par));
|
||||||
|
}
|
||||||
|
return _BtnConfigSave;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private DelegateCommand _BtnCloseSys;
|
||||||
|
/// <summary>
|
||||||
|
/// 关闭系统
|
||||||
|
/// </summary>
|
||||||
|
public DelegateCommand BtnCloseSys
|
||||||
|
{
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_BtnCloseSys = value;
|
||||||
|
}
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (_BtnCloseSys == null)
|
||||||
|
{
|
||||||
|
_BtnCloseSys = new DelegateCommand(() => BtnCloseSysCall());
|
||||||
|
}
|
||||||
|
return _BtnCloseSys;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// 关闭系统的执行方法
|
||||||
|
/// </summary>
|
||||||
|
private void BtnCloseSysCall()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// 停止后台监听线程(例如削峰填谷时间监听)
|
||||||
|
if (ConfigDataService != null)
|
||||||
|
{
|
||||||
|
ConfigDataService.ThreadEnable = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 关闭运行服务中的状态循环与通信连接
|
||||||
|
YuePuRunModelService?.CloseSystem();
|
||||||
|
}
|
||||||
|
catch (System.Exception ex)
|
||||||
|
{
|
||||||
|
System.Windows.MessageBox.Show($"关闭系统时发生异常: {ex.Message}", "错误", System.Windows.MessageBoxButton.OK, System.Windows.MessageBoxImage.Error);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// 退出应用程序
|
||||||
|
System.Windows.Application.Current.Shutdown();
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
System.Environment.Exit(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void BtnConfigSaveCall(string par)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// 同步到运行模式服务
|
||||||
|
YuePuRunModelService.SolarToEsAsFullSoc = SolarToEsAsFullSoc;
|
||||||
|
YuePuRunModelService.Master_ToSlaveBySlaveSoc = Master_ToSlaveBySlaveSoc;
|
||||||
|
YuePuRunModelService.Master_SolarToSlaveEsFullByMasterSoc = Master_SolarToSlaveEsFullByMasterSoc;
|
||||||
|
YuePuRunModelService.Slave_ToMasterBySlaveSoc = Slave_ToMasterBySlaveSoc;
|
||||||
|
YuePuRunModelService.Slave_ToMasterByMasterSoc = Slave_ToMasterByMasterSoc;
|
||||||
|
YuePuRunModelService.Slave_SolarToMasterEsFullBySlaverSoc = Slave_SolarToMasterEsFullBySlaverSoc;
|
||||||
|
YuePuRunModelService.NightMaster_ToMasterFullSoc = NightMaster_ToMasterFullSoc;
|
||||||
|
YuePuRunModelService.NightSlave_ToSlaveFullSoc = NightSlave_ToSlaveFullSoc;
|
||||||
|
|
||||||
|
// 保存到配置文件
|
||||||
|
if (ConfigDataService.ControlConfigValue != null)
|
||||||
|
{
|
||||||
|
ConfigDataService.ControlConfigValue.SolarToEsAsFullSoc = SolarToEsAsFullSoc;
|
||||||
|
ConfigDataService.ControlConfigValue.Master_ToSlaveByMasterSoc = Master_ToSlaveByMasterSoc;
|
||||||
|
ConfigDataService.ControlConfigValue.Master_ToSlaveBySlaveSoc = Master_ToSlaveBySlaveSoc;
|
||||||
|
ConfigDataService.ControlConfigValue.Master_SolarToSlaveEsFullByMasterSoc = Master_SolarToSlaveEsFullByMasterSoc;
|
||||||
|
ConfigDataService.ControlConfigValue.Slave_ToMasterBySlaveSoc = Slave_ToMasterBySlaveSoc;
|
||||||
|
ConfigDataService.ControlConfigValue.Slave_ToMasterByMasterSoc = Slave_ToMasterByMasterSoc;
|
||||||
|
ConfigDataService.ControlConfigValue.Slave_SolarToMasterEsFullBySlaverSoc = Slave_SolarToMasterEsFullBySlaverSoc;
|
||||||
|
ConfigDataService.ControlConfigValue.NightMaster_ToMasterFullSoc = NightMaster_ToMasterFullSoc;
|
||||||
|
ConfigDataService.ControlConfigValue.NightSlave_ToSlaveFullSoc = NightSlave_ToSlaveFullSoc;
|
||||||
|
|
||||||
|
// 保存选择的放电模式(以 Model Id 为准)
|
||||||
|
ConfigDataService.ControlConfigValue.SelectedDisChargeModel = SelectedDisChargeModelId;
|
||||||
|
// 同步旧字段
|
||||||
|
if (System.Enum.IsDefined(typeof(DisChargeType), SelectedDisChargeModelId))
|
||||||
|
SelectedDisChargeType = (DisChargeType)SelectedDisChargeModelId;
|
||||||
|
|
||||||
|
// 调用保存方法
|
||||||
|
bool saveResult = ConfigDataService.SaveControlConfigValue();
|
||||||
|
|
||||||
|
if (saveResult)
|
||||||
|
{
|
||||||
|
System.Windows.MessageBox.Show("控制参数配置保存成功!", "提示", System.Windows.MessageBoxButton.OK, System.Windows.MessageBoxImage.Information);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
System.Windows.MessageBox.Show("控制参数配置保存失败,请查看日志!", "错误", System.Windows.MessageBoxButton.OK, System.Windows.MessageBoxImage.Error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
System.Windows.MessageBox.Show("控制参数配置对象为空!", "错误", System.Windows.MessageBoxButton.OK, System.Windows.MessageBoxImage.Error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (System.Exception ex)
|
||||||
|
{
|
||||||
|
System.Windows.MessageBox.Show($"保存控制参数配置时发生异常: {ex.Message}", "错误", System.Windows.MessageBoxButton.OK, System.Windows.MessageBoxImage.Error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private double _SolarToEsAsFullSoc = 97;
|
||||||
|
/// <summary>
|
||||||
|
/// 光伏给储能充电 作为满的比值
|
||||||
|
/// 90-97
|
||||||
|
/// </summary>
|
||||||
|
public double SolarToEsAsFullSoc
|
||||||
|
{
|
||||||
|
get { return _SolarToEsAsFullSoc; }
|
||||||
|
set { _SolarToEsAsFullSoc = value; RaisePropertyChanged(); }
|
||||||
|
}
|
||||||
|
|
||||||
|
private double _Master_ToSlaveByMasterSoc = 5;
|
||||||
|
/// <summary>
|
||||||
|
/// Master模式,切换到Slave模式时MasterSOC的阀值
|
||||||
|
/// 两个同时考虑
|
||||||
|
/// </summary>
|
||||||
|
public double Master_ToSlaveByMasterSoc
|
||||||
|
{
|
||||||
|
get { return _Master_ToSlaveByMasterSoc; }
|
||||||
|
set { _Master_ToSlaveByMasterSoc = value; RaisePropertyChanged(); }
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private double _Master_ToSlaveBySlaveSoc = 15;
|
||||||
|
/// <summary>
|
||||||
|
/// Master模式,切换到Slave模式时Slave SOC的阀值
|
||||||
|
/// 两个同时考虑
|
||||||
|
/// </summary>
|
||||||
|
public double Master_ToSlaveBySlaveSoc
|
||||||
|
{
|
||||||
|
get { return _Master_ToSlaveBySlaveSoc; }
|
||||||
|
set { _Master_ToSlaveBySlaveSoc = value; RaisePropertyChanged(); }
|
||||||
|
}
|
||||||
|
|
||||||
|
private double _Master_SolarToSlaveEsFullByMasterSoc = 95;
|
||||||
|
/// <summary>
|
||||||
|
/// Master模式,光伏给从储能充满了,是否切换到Slave模式,但是此时需要判断主储能MasterSOC是否满了(主储能也满的话,也无法接收光伏的电),否则不切换
|
||||||
|
/// 主要考虑尽可能的不浪费光伏的电,主从储能只要有余量就要接受光伏的电,也要防止频繁的切换
|
||||||
|
/// < SolarToEsAsFullSoc
|
||||||
|
/// </summary>
|
||||||
|
public double Master_SolarToSlaveEsFullByMasterSoc
|
||||||
|
{
|
||||||
|
get { return _Master_SolarToSlaveEsFullByMasterSoc; }
|
||||||
|
set { _Master_SolarToSlaveEsFullByMasterSoc = value; RaisePropertyChanged(); }
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private double _Slave_ToMasterBySlaveSoc = 5;
|
||||||
|
/// <summary>
|
||||||
|
/// Slave模式,切换到Master模式时SOC的阀值
|
||||||
|
/// 两个同时考虑
|
||||||
|
/// </summary>
|
||||||
|
public double Slave_ToMasterBySlaveSoc
|
||||||
|
{
|
||||||
|
get { return _Slave_ToMasterBySlaveSoc; }
|
||||||
|
set { _Slave_ToMasterBySlaveSoc = value; RaisePropertyChanged(); }
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private double _Slave_ToMasterByMasterSoc = 15;
|
||||||
|
/// <summary>
|
||||||
|
/// Slave模式,切换到Master模式时SOC的阀值
|
||||||
|
/// 两个同时考虑
|
||||||
|
/// </summary>
|
||||||
|
public double Slave_ToMasterByMasterSoc
|
||||||
|
{
|
||||||
|
get { return _Slave_ToMasterByMasterSoc; }
|
||||||
|
set { _Slave_ToMasterByMasterSoc = value; RaisePropertyChanged(); }
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private double _Slave_SolarToMasterEsFullBySlaverSoc = 95;
|
||||||
|
/// <summary>
|
||||||
|
/// Slave模式,光伏给主储能充满了,是否切换到Master模式,但是此时需要判断从储能SOC是否满了(从储能也满的话,也无法接收光伏的电),否则不切换
|
||||||
|
/// 主要考虑尽可能的不浪费光伏的电,主从储能只要有余量就要接受光伏的电,也要防止频繁的切换
|
||||||
|
/// < SolarToEsAsFullSoc
|
||||||
|
/// </summary>
|
||||||
|
public double Slave_SolarToMasterEsFullBySlaverSoc
|
||||||
|
{
|
||||||
|
get { return _Slave_SolarToMasterEsFullBySlaverSoc; }
|
||||||
|
set { _Slave_SolarToMasterEsFullBySlaverSoc = value; RaisePropertyChanged(); }
|
||||||
|
}
|
||||||
|
|
||||||
|
private double _NightMaster_ToMasterFullSoc = 98;
|
||||||
|
/// <summary>
|
||||||
|
/// 晚上,主储能充满的标志,也是切换到从储能的控制标志
|
||||||
|
/// </summary>
|
||||||
|
public double NightMaster_ToMasterFullSoc
|
||||||
|
{
|
||||||
|
get { return _NightMaster_ToMasterFullSoc; }
|
||||||
|
set { _NightMaster_ToMasterFullSoc = value; RaisePropertyChanged(); }
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private double _NightSlave_ToSlaveFullSoc = 98;
|
||||||
|
/// <summary>
|
||||||
|
/// 晚上,从储能充满的标志,也是切换到主储能的控制标志
|
||||||
|
/// </summary>
|
||||||
|
public double NightSlave_ToSlaveFullSoc
|
||||||
|
{
|
||||||
|
get { return _NightSlave_ToSlaveFullSoc; }
|
||||||
|
set { _NightSlave_ToSlaveFullSoc = value; RaisePropertyChanged(); }
|
||||||
|
}
|
||||||
|
|
||||||
|
public YuePuRunModelService YuePuRunModelService { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 配置数据服务
|
||||||
|
/// </summary>
|
||||||
|
public ConfigDataService ConfigDataService { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 选中的放电模式
|
||||||
|
/// </summary>
|
||||||
|
private DisChargeType _SelectedDisChargeType;
|
||||||
|
public DisChargeType SelectedDisChargeType
|
||||||
|
{
|
||||||
|
get { return _SelectedDisChargeType; }
|
||||||
|
set { _SelectedDisChargeType = value; RaisePropertyChanged(); }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 放电模式列表
|
||||||
|
/// </summary>
|
||||||
|
private ObservableCollection<DisChargeModelItem> _DisChargeModels;
|
||||||
|
public ObservableCollection<DisChargeModelItem> DisChargeModels
|
||||||
|
{
|
||||||
|
get { return _DisChargeModels; }
|
||||||
|
set { _DisChargeModels = value; RaisePropertyChanged(); }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 选中的放电模式(列表项的 Model Id)
|
||||||
|
/// </summary>
|
||||||
|
private int _SelectedDisChargeModelId;
|
||||||
|
public int SelectedDisChargeModelId
|
||||||
|
{
|
||||||
|
get { return _SelectedDisChargeModelId; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_SelectedDisChargeModelId = value;
|
||||||
|
// 同步枚举值(若兼容)
|
||||||
|
if (System.Enum.IsDefined(typeof(DisChargeType), _SelectedDisChargeModelId))
|
||||||
|
SelectedDisChargeType = (DisChargeType)_SelectedDisChargeModelId;
|
||||||
|
RaisePropertyChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -687,6 +687,10 @@
|
|||||||
FontSize="16"
|
FontSize="16"
|
||||||
Text="{Binding YuePuRunModelService.EsSoc2}" />
|
Text="{Binding YuePuRunModelService.EsSoc2}" />
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
|
|
||||||
|
<StackPanel Grid.RowSpan="2" Grid.Column="2">
|
||||||
|
<TextBlock Text="{Binding YuePuRunModelService.LogicMsg}" TextWrapping="Wrap" />
|
||||||
|
</StackPanel>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|||||||
@@ -14,15 +14,18 @@
|
|||||||
prism:ViewModelLocator.AutoWireViewModel="True"
|
prism:ViewModelLocator.AutoWireViewModel="True"
|
||||||
mc:Ignorable="d">
|
mc:Ignorable="d">
|
||||||
<Grid>
|
<Grid>
|
||||||
<Grid.RowDefinitions>
|
<!--<Grid.RowDefinitions>
|
||||||
<RowDefinition />
|
<RowDefinition />
|
||||||
<RowDefinition />
|
<RowDefinition />
|
||||||
</Grid.RowDefinitions>
|
</Grid.RowDefinitions>
|
||||||
<Grid.ColumnDefinitions>
|
<Grid.ColumnDefinitions>
|
||||||
<ColumnDefinition />
|
<ColumnDefinition />
|
||||||
<ColumnDefinition />
|
<ColumnDefinition />
|
||||||
</Grid.ColumnDefinitions>
|
<ColumnDefinition />
|
||||||
|
</Grid.ColumnDefinitions>-->
|
||||||
<Border
|
<Border
|
||||||
|
Grid.RowSpan="2"
|
||||||
|
Grid.ColumnSpan="2"
|
||||||
Margin="5,5,5,5"
|
Margin="5,5,5,5"
|
||||||
Background="White"
|
Background="White"
|
||||||
CornerRadius="10">
|
CornerRadius="10">
|
||||||
@@ -41,20 +44,44 @@
|
|||||||
<RowDefinition />
|
<RowDefinition />
|
||||||
<RowDefinition />
|
<RowDefinition />
|
||||||
<RowDefinition />
|
<RowDefinition />
|
||||||
|
<RowDefinition />
|
||||||
|
<RowDefinition />
|
||||||
|
<RowDefinition />
|
||||||
|
<RowDefinition />
|
||||||
|
<RowDefinition />
|
||||||
|
<RowDefinition />
|
||||||
|
<RowDefinition />
|
||||||
|
<RowDefinition />
|
||||||
|
<RowDefinition />
|
||||||
|
<RowDefinition />
|
||||||
|
<RowDefinition />
|
||||||
|
<RowDefinition />
|
||||||
|
<RowDefinition />
|
||||||
|
<RowDefinition />
|
||||||
|
|
||||||
</Grid.RowDefinitions>
|
</Grid.RowDefinitions>
|
||||||
<Grid.ColumnDefinitions>
|
|
||||||
<ColumnDefinition />
|
|
||||||
<ColumnDefinition />
|
|
||||||
</Grid.ColumnDefinitions>
|
|
||||||
<Grid.Resources>
|
<Grid.Resources>
|
||||||
<Style x:Key="TextIco" TargetType="TextBlock">
|
<Style x:Key="TextIco" TargetType="TextBlock">
|
||||||
<Setter Property="Margin" Value="0,2,10,2" />
|
<Setter Property="Margin" Value="0,2,5,2" />
|
||||||
<Setter Property="FontSize" Value="20" />
|
<Setter Property="FontSize" Value="20" />
|
||||||
<Setter Property="VerticalAlignment" Value="Bottom" />
|
<Setter Property="VerticalAlignment" Value="Bottom" />
|
||||||
<Setter Property="FontFamily" Value="../Assets/Fonts/#iconfont" />
|
<Setter Property="FontFamily" Value="../Assets/Fonts/#iconfont" />
|
||||||
<Setter Property="Foreground" Value="Black" />
|
<Setter Property="Foreground" Value="Black" />
|
||||||
</Style>
|
</Style>
|
||||||
|
<Style x:Key="TextTitle" TargetType="TextBlock">
|
||||||
|
<Setter Property="Margin" Value="5,0,10,0" />
|
||||||
|
<Setter Property="FontSize" Value="20" />
|
||||||
|
<Setter Property="VerticalAlignment" Value="Center" />
|
||||||
|
<Setter Property="HorizontalAlignment" Value="Center" />
|
||||||
|
<Setter Property="Foreground" Value="Black" />
|
||||||
|
</Style>
|
||||||
|
<Style x:Key="TextValue" TargetType="TextBlock">
|
||||||
|
<Setter Property="Margin" Value="10,0,5,0" />
|
||||||
|
<Setter Property="FontSize" Value="20" />
|
||||||
|
<Setter Property="VerticalAlignment" Value="Center" />
|
||||||
|
<Setter Property="HorizontalAlignment" Value="Center" />
|
||||||
|
<Setter Property="Foreground" Value="Black" />
|
||||||
|
</Style>
|
||||||
<Style x:Key="StackPanelText" TargetType="StackPanel">
|
<Style x:Key="StackPanelText" TargetType="StackPanel">
|
||||||
<Setter Property="HorizontalAlignment" Value="Center" />
|
<Setter Property="HorizontalAlignment" Value="Center" />
|
||||||
<Setter Property="VerticalAlignment" Value="Center" />
|
<Setter Property="VerticalAlignment" Value="Center" />
|
||||||
@@ -74,98 +101,261 @@
|
|||||||
VerticalAlignment="Center"
|
VerticalAlignment="Center"
|
||||||
FontSize="20"
|
FontSize="20"
|
||||||
Foreground="#596B75"
|
Foreground="#596B75"
|
||||||
Text="Mqtt配置" />
|
Text="控制参数配置" />
|
||||||
</StackPanel>
|
|
||||||
<StackPanel Grid.Row="1" Style="{StaticResource StackPanelText}">
|
|
||||||
<TextBlock Style="{StaticResource TextIco}" Text="" />
|
|
||||||
<TextBox
|
|
||||||
Width="100"
|
|
||||||
VerticalAlignment="Center"
|
|
||||||
materialDesign:HintAssist.Hint="IP地址"
|
|
||||||
FontSize="14"
|
|
||||||
Style="{StaticResource MaterialDesignFloatingHintTextBox}"
|
|
||||||
Text="{Binding ConfigDataService.MqttServerUrl}">
|
|
||||||
<i:Interaction.Behaviors>
|
|
||||||
<keyboard:NumericKeyboardBehavior />
|
|
||||||
</i:Interaction.Behaviors>
|
|
||||||
</TextBox>
|
|
||||||
</StackPanel>
|
|
||||||
<StackPanel
|
|
||||||
Grid.Row="1"
|
|
||||||
Grid.Column="1"
|
|
||||||
Style="{StaticResource StackPanelText}">
|
|
||||||
<TextBlock Style="{StaticResource TextIco}" Text="" />
|
|
||||||
<TextBox
|
|
||||||
Width="100"
|
|
||||||
VerticalAlignment="Center"
|
|
||||||
materialDesign:HintAssist.Hint="端口号"
|
|
||||||
FontSize="14"
|
|
||||||
Style="{StaticResource MaterialDesignFloatingHintTextBox}"
|
|
||||||
Text="{Binding ConfigDataService.MqttServerPort}">
|
|
||||||
<i:Interaction.Behaviors>
|
|
||||||
<keyboard:NumericKeyboardBehavior />
|
|
||||||
</i:Interaction.Behaviors>
|
|
||||||
</TextBox>
|
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
|
|
||||||
<StackPanel
|
|
||||||
Grid.Row="2"
|
|
||||||
Grid.Column="0"
|
<StackPanel Grid.Row="1" Style="{StaticResource StackPanelText}">
|
||||||
Style="{StaticResource StackPanelText}">
|
|
||||||
<TextBlock Style="{StaticResource TextIco}" Text="" />
|
|
||||||
<TextBox
|
|
||||||
Width="100"
|
|
||||||
VerticalAlignment="Center"
|
|
||||||
materialDesign:HintAssist.Hint="用户名"
|
|
||||||
FontSize="14"
|
|
||||||
Style="{StaticResource MaterialDesignFloatingHintTextBox}"
|
|
||||||
Text="{Binding ConfigDataService.MqttUser}">
|
|
||||||
<i:Interaction.Behaviors>
|
|
||||||
<keyboard:KeyboardBehavior />
|
|
||||||
</i:Interaction.Behaviors>
|
|
||||||
</TextBox>
|
|
||||||
</StackPanel>
|
|
||||||
<StackPanel
|
|
||||||
Grid.Row="2"
|
|
||||||
Grid.Column="1"
|
|
||||||
Style="{StaticResource StackPanelText}">
|
|
||||||
<TextBlock Style="{StaticResource TextIco}" Text="" />
|
|
||||||
<TextBox
|
|
||||||
Width="100"
|
|
||||||
VerticalAlignment="Center"
|
|
||||||
materialDesign:HintAssist.Hint="密码"
|
|
||||||
FontSize="14"
|
|
||||||
Style="{StaticResource MaterialDesignFloatingHintTextBox}"
|
|
||||||
Text="{Binding ConfigDataService.MqttPwd}">
|
|
||||||
<i:Interaction.Behaviors>
|
|
||||||
<keyboard:KeyboardBehavior />
|
|
||||||
</i:Interaction.Behaviors>
|
|
||||||
</TextBox>
|
|
||||||
</StackPanel>
|
|
||||||
<StackPanel
|
|
||||||
Grid.Row="3"
|
|
||||||
Grid.ColumnSpan="2"
|
|
||||||
Style="{StaticResource StackPanelText}">
|
|
||||||
<TextBlock Style="{StaticResource TextIco}" Text="" />
|
<TextBlock Style="{StaticResource TextIco}" Text="" />
|
||||||
<TextBox
|
<TextBlock Style="{StaticResource TextTitle}" Text="1-光伏充电储能上限(95-99):" />
|
||||||
Width="260"
|
<Slider
|
||||||
|
x:Name="Slider1"
|
||||||
|
Width="280"
|
||||||
|
IsSelectionRangeEnabled="True"
|
||||||
|
Maximum="100"
|
||||||
|
Minimum="50"
|
||||||
|
Orientation="Horizontal"
|
||||||
|
SelectionEnd="99"
|
||||||
|
SelectionStart="95"
|
||||||
|
TickFrequency="5"
|
||||||
|
TickPlacement="BottomRight"
|
||||||
|
Value="{Binding SolarToEsAsFullSoc}" />
|
||||||
|
<TextBlock
|
||||||
|
Margin="5,0"
|
||||||
|
Style="{StaticResource TextValue}"
|
||||||
|
Text="{Binding ElementName=Slider1, Path=Value, Mode=OneWay, StringFormat=0}" />
|
||||||
|
<!--<TextBox
|
||||||
|
Width="180"
|
||||||
VerticalAlignment="Center"
|
VerticalAlignment="Center"
|
||||||
materialDesign:HintAssist.Hint="客户端标识"
|
materialDesign:HintAssist.Hint="建议数据:【90-99】"
|
||||||
FontSize="14"
|
FontSize="14"
|
||||||
Style="{StaticResource MaterialDesignFloatingHintTextBox}"
|
Style="{StaticResource MaterialDesignFloatingHintTextBox}"
|
||||||
Text="{Binding ConfigDataService.MqttClientId}">
|
Text="145">
|
||||||
<i:Interaction.Behaviors>
|
<i:Interaction.Behaviors>
|
||||||
<keyboard:KeyboardBehavior />
|
<keyboard:NumericKeyboardBehavior />
|
||||||
</i:Interaction.Behaviors>
|
</i:Interaction.Behaviors>
|
||||||
</TextBox>
|
</TextBox>-->
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
|
<StackPanel Grid.Row="2" Style="{StaticResource StackPanelText}">
|
||||||
|
<TextBlock Style="{StaticResource TextIco}" Text="" />
|
||||||
|
<TextBlock Style="{StaticResource TextTitle}" Text="2-主模式:切换从模式时主储能Soc下限(0-20):" />
|
||||||
|
<Slider
|
||||||
|
x:Name="Slider2"
|
||||||
|
Width="280"
|
||||||
|
IsSelectionRangeEnabled="True"
|
||||||
|
Maximum="50"
|
||||||
|
Minimum="0"
|
||||||
|
Orientation="Horizontal"
|
||||||
|
SelectionEnd="10"
|
||||||
|
SelectionStart="1"
|
||||||
|
TickFrequency="5"
|
||||||
|
TickPlacement="BottomRight"
|
||||||
|
Value="{Binding Master_ToSlaveByMasterSoc}" />
|
||||||
|
<TextBlock
|
||||||
|
Margin="5,0"
|
||||||
|
Style="{StaticResource TextValue}"
|
||||||
|
Text="{Binding ElementName=Slider2, Path=Value, Mode=OneWay, StringFormat=0}" />
|
||||||
|
</StackPanel>
|
||||||
|
<StackPanel Grid.Row="3" Style="{StaticResource StackPanelText}">
|
||||||
|
<TextBlock Style="{StaticResource TextIco}" Text="" />
|
||||||
|
<TextBlock Style="{StaticResource TextTitle}" Text="3-主模式:切换从模式时从储能Soc下限(0-20):" />
|
||||||
|
<Slider
|
||||||
|
x:Name="Slider3"
|
||||||
|
Width="280"
|
||||||
|
IsSelectionRangeEnabled="True"
|
||||||
|
Maximum="50"
|
||||||
|
Minimum="0"
|
||||||
|
Orientation="Horizontal"
|
||||||
|
SelectionEnd="10"
|
||||||
|
SelectionStart="1"
|
||||||
|
TickFrequency="5"
|
||||||
|
TickPlacement="BottomRight"
|
||||||
|
Value="{Binding Master_ToSlaveBySlaveSoc}" />
|
||||||
|
<TextBlock
|
||||||
|
Margin="5,0"
|
||||||
|
Style="{StaticResource TextValue}"
|
||||||
|
Text="{Binding ElementName=Slider3, Path=Value, Mode=OneWay, StringFormat=0}" />
|
||||||
|
<!--<TextBox
|
||||||
|
Width="180"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
materialDesign:HintAssist.Hint="建议数据:【90-99】"
|
||||||
|
FontSize="14"
|
||||||
|
Style="{StaticResource MaterialDesignFloatingHintTextBox}"
|
||||||
|
Text="145">
|
||||||
|
<i:Interaction.Behaviors>
|
||||||
|
<keyboard:NumericKeyboardBehavior />
|
||||||
|
</i:Interaction.Behaviors>
|
||||||
|
</TextBox>-->
|
||||||
|
</StackPanel>
|
||||||
|
<StackPanel Grid.Row="4" Style="{StaticResource StackPanelText}">
|
||||||
|
<TextBlock Style="{StaticResource TextIco}" Text="" />
|
||||||
|
<TextBlock Style="{StaticResource TextTitle}" Text="4-主模式:光伏到从储能已充满,主储能Soc阀值(80-99):" />
|
||||||
|
<Slider
|
||||||
|
x:Name="Slider4"
|
||||||
|
Width="280"
|
||||||
|
IsSelectionRangeEnabled="True"
|
||||||
|
Maximum="100"
|
||||||
|
Minimum="50"
|
||||||
|
Orientation="Horizontal"
|
||||||
|
SelectionEnd="100"
|
||||||
|
SelectionStart="90"
|
||||||
|
TickFrequency="5"
|
||||||
|
TickPlacement="BottomRight"
|
||||||
|
Value="{Binding Master_SolarToSlaveEsFullByMasterSoc}" />
|
||||||
|
<TextBlock
|
||||||
|
Margin="5,0"
|
||||||
|
Style="{StaticResource TextValue}"
|
||||||
|
Text="{Binding ElementName=Slider4, Path=Value, Mode=OneWay, StringFormat=0}" />
|
||||||
|
<!--<TextBox
|
||||||
|
Width="180"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
materialDesign:HintAssist.Hint="建议数据:【90-99】"
|
||||||
|
FontSize="14"
|
||||||
|
Style="{StaticResource MaterialDesignFloatingHintTextBox}"
|
||||||
|
Text="145">
|
||||||
|
<i:Interaction.Behaviors>
|
||||||
|
<keyboard:NumericKeyboardBehavior />
|
||||||
|
</i:Interaction.Behaviors>
|
||||||
|
</TextBox>-->
|
||||||
|
</StackPanel>
|
||||||
|
|
||||||
|
|
||||||
|
<StackPanel Grid.Row="6" Style="{StaticResource StackPanelText}">
|
||||||
|
<TextBlock Style="{StaticResource TextIco}" Text="" />
|
||||||
|
<TextBlock Style="{StaticResource TextTitle}" Text="5-从模式:切换主模式时从储能Soc下限(0-20):" />
|
||||||
|
<Slider
|
||||||
|
x:Name="Slider6"
|
||||||
|
Width="280"
|
||||||
|
IsSelectionRangeEnabled="True"
|
||||||
|
Maximum="50"
|
||||||
|
Minimum="0"
|
||||||
|
Orientation="Horizontal"
|
||||||
|
SelectionEnd="10"
|
||||||
|
SelectionStart="1"
|
||||||
|
TickFrequency="5"
|
||||||
|
TickPlacement="BottomRight"
|
||||||
|
Value="{Binding Slave_ToMasterBySlaveSoc}" />
|
||||||
|
<TextBlock
|
||||||
|
Margin="5,0"
|
||||||
|
Style="{StaticResource TextValue}"
|
||||||
|
Text="{Binding ElementName=Slider6, Path=Value, Mode=OneWay, StringFormat=0}" />
|
||||||
|
</StackPanel>
|
||||||
|
<StackPanel Grid.Row="7" Style="{StaticResource StackPanelText}">
|
||||||
|
<TextBlock Style="{StaticResource TextIco}" Text="" />
|
||||||
|
<TextBlock Style="{StaticResource TextTitle}" Text="6-从模式:切换主模式时主储能Soc下限(0-20):" />
|
||||||
|
<Slider
|
||||||
|
x:Name="Slider7"
|
||||||
|
Width="280"
|
||||||
|
IsSelectionRangeEnabled="True"
|
||||||
|
Maximum="50"
|
||||||
|
Minimum="0"
|
||||||
|
Orientation="Horizontal"
|
||||||
|
SelectionEnd="10"
|
||||||
|
SelectionStart="1"
|
||||||
|
TickFrequency="5"
|
||||||
|
TickPlacement="BottomRight"
|
||||||
|
Value="{Binding Slave_ToMasterByMasterSoc}" />
|
||||||
|
<TextBlock
|
||||||
|
Margin="5,0"
|
||||||
|
Style="{StaticResource TextValue}"
|
||||||
|
Text="{Binding ElementName=Slider7, Path=Value, Mode=OneWay, StringFormat=0}" />
|
||||||
|
|
||||||
|
</StackPanel>
|
||||||
|
<StackPanel Grid.Row="8" Style="{StaticResource StackPanelText}">
|
||||||
|
<TextBlock Style="{StaticResource TextIco}" Text="" />
|
||||||
|
<TextBlock Style="{StaticResource TextTitle}" Text="7-从模式:光伏到主储能已充满,从储能Soc阀值(80-99):" />
|
||||||
|
<Slider
|
||||||
|
x:Name="Slider8"
|
||||||
|
Width="280"
|
||||||
|
IsSelectionRangeEnabled="True"
|
||||||
|
Maximum="100"
|
||||||
|
Minimum="50"
|
||||||
|
Orientation="Horizontal"
|
||||||
|
SelectionEnd="100"
|
||||||
|
SelectionStart="90"
|
||||||
|
TickFrequency="5"
|
||||||
|
TickPlacement="BottomRight"
|
||||||
|
Value="{Binding Slave_SolarToMasterEsFullBySlaverSoc}" />
|
||||||
|
<TextBlock
|
||||||
|
Margin="5,0"
|
||||||
|
Style="{StaticResource TextValue}"
|
||||||
|
Text="{Binding ElementName=Slider8, Path=Value, Mode=OneWay, StringFormat=0}" />
|
||||||
|
|
||||||
|
</StackPanel>
|
||||||
|
|
||||||
|
|
||||||
|
<StackPanel Grid.Row="10" Style="{StaticResource StackPanelText}">
|
||||||
|
<TextBlock Style="{StaticResource TextIco}" Text="" />
|
||||||
|
<TextBlock Style="{StaticResource TextTitle}" Text="8-晚上充电:主储能充满Soc上限(建议90-99):" />
|
||||||
|
<Slider
|
||||||
|
x:Name="Slider10"
|
||||||
|
Width="280"
|
||||||
|
IsSelectionRangeEnabled="True"
|
||||||
|
Maximum="100"
|
||||||
|
Minimum="50"
|
||||||
|
Orientation="Horizontal"
|
||||||
|
SelectionEnd="99"
|
||||||
|
SelectionStart="90"
|
||||||
|
TickFrequency="5"
|
||||||
|
TickPlacement="BottomRight"
|
||||||
|
Value="{Binding NightMaster_ToMasterFullSoc}" />
|
||||||
|
<TextBlock
|
||||||
|
Margin="5,0"
|
||||||
|
Style="{StaticResource TextValue}"
|
||||||
|
Text="{Binding ElementName=Slider10, Path=Value, Mode=OneWay, StringFormat=0}" />
|
||||||
|
|
||||||
|
</StackPanel>
|
||||||
|
|
||||||
|
<StackPanel Grid.Row="11" Style="{StaticResource StackPanelText}">
|
||||||
|
<TextBlock Style="{StaticResource TextIco}" Text="" />
|
||||||
|
<TextBlock Style="{StaticResource TextTitle}" Text="9-晚上充电:从储能充满Soc上限(建议50-90):" />
|
||||||
|
<Slider
|
||||||
|
x:Name="Slider11"
|
||||||
|
Width="280"
|
||||||
|
IsSelectionRangeEnabled="True"
|
||||||
|
Maximum="100"
|
||||||
|
Minimum="0"
|
||||||
|
Orientation="Horizontal"
|
||||||
|
SelectionEnd="90"
|
||||||
|
SelectionStart="50"
|
||||||
|
TickFrequency="5"
|
||||||
|
TickPlacement="BottomRight"
|
||||||
|
Value="{Binding NightSlave_ToSlaveFullSoc}" />
|
||||||
|
<TextBlock
|
||||||
|
Margin="5,0"
|
||||||
|
Style="{StaticResource TextValue}"
|
||||||
|
Text="{Binding ElementName=Slider11, Path=Value, Mode=OneWay, StringFormat=0}" />
|
||||||
|
|
||||||
|
</StackPanel>
|
||||||
|
|
||||||
|
<StackPanel Grid.Row="13" Style="{StaticResource StackPanelText}">
|
||||||
|
<TextBlock Style="{StaticResource TextIco}" Text="" />
|
||||||
|
<TextBlock Style="{StaticResource TextTitle}" Text="放电模式时间:" />
|
||||||
|
<ComboBox
|
||||||
|
Width="240"
|
||||||
|
DisplayMemberPath="DisChargeTime"
|
||||||
|
ItemsSource="{Binding DisChargeModels}"
|
||||||
|
SelectedValue="{Binding SelectedDisChargeModelId, Mode=TwoWay}"
|
||||||
|
SelectedValuePath="Model" />
|
||||||
|
</StackPanel>
|
||||||
|
|
||||||
|
|
||||||
<StackPanel
|
<StackPanel
|
||||||
Grid.Row="4"
|
Grid.Row="18"
|
||||||
Grid.ColumnSpan="2"
|
Grid.ColumnSpan="2"
|
||||||
Margin="0,0,20,0"
|
Margin="0,0,20,5"
|
||||||
HorizontalAlignment="Right"
|
HorizontalAlignment="Right"
|
||||||
VerticalAlignment="Center">
|
VerticalAlignment="Center">
|
||||||
<Button Command="{Binding BtnMqttConfigSave}" Content="保存配置" />
|
<Button Command="{Binding BtnConfigSave}" Content="使用并保存配置" />
|
||||||
|
</StackPanel>
|
||||||
|
<StackPanel
|
||||||
|
Grid.Row="18"
|
||||||
|
Grid.ColumnSpan="2"
|
||||||
|
Margin="20,0,20,5"
|
||||||
|
HorizontalAlignment="Left"
|
||||||
|
VerticalAlignment="Center">
|
||||||
|
<Button Command="{Binding BtnCloseSys}" Content="关闭系统" />
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Border>
|
</Border>
|
||||||
|
|||||||
Reference in New Issue
Block a user