using HslCommunication.ModBus;
using NLog;
using OrpaonEMS.App.Models;
using OrpaonEMS.Core.DbModel;
using OrpaonEMS.Core.Enums;
using OrpaonEMS.Core;
using Stateless;
using System;
using System.Collections.Generic;
using System.Diagnostics.Metrics;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Prism.Mvvm;
using OrpaonEMS.Model;
using OrpaonEMS.Model.Enums;
using Prism.Events;
using OrpaonEMS.App.PrismEvent;
using OrpaonEMS.App.Com;
using NLog.Targets;
using System.Diagnostics.Eventing.Reader;
using HslCommunication.WebSocket;
using HslCommunication;
using OrpaonEMS.Model.MasterSlave;
using System.Text.Json;
using Windows.ApplicationModel.Contacts;
namespace OrpaonEMS.App.Services
{
///
/// 储能服务
/// https://blog.csdn.net/zwcslj/article/details/136363261
///
public class EnergyStorageService : BindableBase
{
/////
///// 负载仪表数据
/// 伊顿客户提供的仪表
/////
//public KEMeter kEMeter { get; set; } = new KEMeter();
///
/// 安科瑞仪表数据
/// 储能本身的计量数据
///
public AcrelMeterDataService AcrelMeters { get; set; }
public PwAnalyzeService PwAnalyzeService { get; }
/////
///// 分布式控制
///// 主从站通信
/////
//public EMSService MasterSlave { get; set; }
///
/// NLog服务集合
///
public ILogService LogService { get; }
///
/// 储能统计分析
///
public PwAnalyzeService pwAnalyze { get; set; }
///
/// 是否为主站
///
public bool IsMaster { get; set; }
///
/// 实例化
///
public EnergyStorageService(ILogService logService,
BmsDataService bmsDataService,
SolarEnergyService solarEnergyService,
InPowerPCSDataService inPowerPCSDataService,
IFreeSql freeSql,
ACService aCService,
AcrelMeterDataService acrelMeterDataService,
PwAnalyzeService pwAnalyzeService,
ConfigDataService configDataService)
{
//Log服务实例赋值
LogService = logService;
AcrelMeters = acrelMeterDataService;
//获取Bms服务实例
BmsDataService = bmsDataService;
//获取太阳储能的服务
SolarEnergyService = solarEnergyService;
//获取英博PCS服务实例
InPowerPCSDataService = inPowerPCSDataService;
//FreeSQL实例
FreeSql = freeSql;
ACService = aCService;
//ListEnergyStoragePeakValleyTimeConfig = new List();
//获取配置服务实例
ConfigDataService = configDataService;
WebUrl = ConfigDataService.ServerUrl;
IsMaster = ConfigDataService.IsMaster;
if (IsMaster)
{
//作为服务时,站号是固定的
ClientStation = 0;
}
else
{
ClientStation = ConfigDataService.Station;
}
CurClientInfo.Station = ClientStation;
//PCS的追踪模型,初始值设置为0
InPowerPCSDataService.PwTranceCmdValues.CmdValue = 0;
//伊顿电表服务 特制
//PwMeters = new PwMeter();
//状态机初始化参数配置
StateMachineInitial();
//注入当前的实例
TrigModuleStartRunActions = new TrigModuleStartRunAction(this);
//云服务实例化
////服务实例化
//esModbusTcpServer = new EsModbusTcpServer();
//esModbusTcpServer.StartServer();
//ModbusTcpServerTask = Task.Run(() => ModbusTcpServerCycle());
//mqttClientDrive = new MqttClientDrive("139.224.230.213", "1883", "b1955190-d471-11ee-a961-354c6e00783a", "ter354uyQbK81JF6xWH9", "", "v1/devices/me/telemetry");
//mqttClientDrive.CurMsg = "{\r\n \"stringKey\": \"value1\",\r\n \"booleanKey\": true,\r\n \"doubleKey\": 42.0,\r\n \"longKey\": 73,\r\n \"jsonKey\": {\r\n \"someNumber\": 42,\r\n \"someArray\": [1,2,3],\r\n \"someNestedObject\": {\"key\": \"value\"}\r\n }\r\n}";
//实例化能耗统计分析模型
PwAnalyzeService = pwAnalyzeService;
//pwAnalyze = new PwAnalyze(this, LogService, FreeSql, ConfigDataService);
//MasterSlave = new EMSService(LogService, InPowerPCSDataService, BmsDataService, ConfigDataService, this);
WebSocketClientInit();
}
#region ModbusTcpServer
/////
///// ModbusTcp服务
/////
//public EsModbusTcpServer esModbusTcpServer { get; set; } = null;
//public MqttClientDrive mqttClientDrive { get; set; }
/////
///// ModbusTcp 的服务周期
/////
//public Task ModbusTcpServerTask = null;
/////
///// 循环赋值
/////
/////
//private async Task ModbusTcpServerCycle()
//{
// Thread.Sleep(10000);
// while (ThreadEnable)
// {
// try
// {
// if (esModbusTcpServer.IsOpenServer())
// {
// //BMS
// esModbusTcpServer.busTcpServer.Write("x=4;1", BmsDataService.ListBMSRoCell.Find(a => a.Name == "电池簇总SOC").SrRtValue);
// esModbusTcpServer.busTcpServer.Write("x=4;2", BmsDataService.ListBMSRoCell.Find(a => a.Name == "电池簇总SOH").SrRtValue);
// esModbusTcpServer.busTcpServer.Write("x=4;3", BmsDataService.ListBMSRoCell.Find(a => a.Name == "电池最高温度").SrRtValue);
// esModbusTcpServer.busTcpServer.Write("x=4;4", BmsDataService.ListBMSRoCell.Find(a => a.Name == "电池最高温度所在模块号").SrRtValue);
// esModbusTcpServer.busTcpServer.Write("x=4;5", BmsDataService.ListBMSRoCell.Find(a => a.Name == "电池最低温度").SrRtValue);
// esModbusTcpServer.busTcpServer.Write("x=4;6", BmsDataService.ListBMSRoCell.Find(a => a.Name == "电池最低温度所在模块号").SrRtValue);
// //PCS
// esModbusTcpServer.busTcpServer.Write("x=4;7", esModbusTcpServer.busTcpServer.ByteTransform.TransUInt16(InPowerPCSDataService.OperateResultBytes1.Content, 0));
// esModbusTcpServer.busTcpServer.Write("x=4;8", esModbusTcpServer.busTcpServer.ByteTransform.TransUInt16(InPowerPCSDataService.OperateResultBytes1.Content, 2));
// esModbusTcpServer.busTcpServer.Write("x=4;9", esModbusTcpServer.busTcpServer.ByteTransform.TransUInt16(InPowerPCSDataService.OperateResultBytes1.Content, 4));
// esModbusTcpServer.busTcpServer.Write("x=4;10", esModbusTcpServer.busTcpServer.ByteTransform.TransInt16(InPowerPCSDataService.OperateResultBytes1.Content, 6));
// esModbusTcpServer.busTcpServer.Write("x=4;11", esModbusTcpServer.busTcpServer.ByteTransform.TransInt16(InPowerPCSDataService.OperateResultBytes1.Content, 8));
// esModbusTcpServer.busTcpServer.Write("x=4;12", esModbusTcpServer.busTcpServer.ByteTransform.TransInt16(InPowerPCSDataService.OperateResultBytes1.Content, 10));
// esModbusTcpServer.busTcpServer.Write("x=4;13", esModbusTcpServer.busTcpServer.ByteTransform.TransUInt16(InPowerPCSDataService.OperateResultBytes1.Content, 12));
// esModbusTcpServer.busTcpServer.Write("x=4;14", esModbusTcpServer.busTcpServer.ByteTransform.TransInt16(InPowerPCSDataService.OperateResultBytes1.Content, 20));
// esModbusTcpServer.busTcpServer.Write("x=4;15", esModbusTcpServer.busTcpServer.ByteTransform.TransUInt16(InPowerPCSDataService.OperateResultBytes1.Content, 36));
// esModbusTcpServer.busTcpServer.Write("x=4;16", esModbusTcpServer.busTcpServer.ByteTransform.TransInt16(InPowerPCSDataService.OperateResultBytes1.Content, 28));
// esModbusTcpServer.busTcpServer.Write("x=4;17", esModbusTcpServer.busTcpServer.ByteTransform.TransUInt16(InPowerPCSDataService.OperateResultBytes1.Content, 44));
// esModbusTcpServer.busTcpServer.Write("x=4;18", esModbusTcpServer.busTcpServer.ByteTransform.TransInt16(InPowerPCSDataService.OperateResultBytes1.Content, 52));
// //电表数据
// esModbusTcpServer.busTcpServer.Write("x=4;20", esModbusTcpServer.busTcpServer.ByteTransform.TransSingle(AcrelMeters.OperateResultBytes1.Content, 52));
// esModbusTcpServer.busTcpServer.Write("x=4;22", esModbusTcpServer.busTcpServer.ByteTransform.TransSingle(AcrelMeters.OperateResultBytes1.Content, 68));
// esModbusTcpServer.busTcpServer.Write("x=4;24", esModbusTcpServer.busTcpServer.ByteTransform.TransSingle(AcrelMeters.OperateResultBytes1.Content, 0));
// esModbusTcpServer.busTcpServer.Write("x=4;26", esModbusTcpServer.busTcpServer.ByteTransform.TransSingle(AcrelMeters.OperateResultBytes1.Content, 4));
// esModbusTcpServer.busTcpServer.Write("x=4;28", esModbusTcpServer.busTcpServer.ByteTransform.TransSingle(AcrelMeters.OperateResultBytes1.Content, 8));
// esModbusTcpServer.busTcpServer.Write("x=4;30", esModbusTcpServer.busTcpServer.ByteTransform.TransSingle(AcrelMeters.OperateResultBytes1.Content, 24));
// esModbusTcpServer.busTcpServer.Write("x=4;32", esModbusTcpServer.busTcpServer.ByteTransform.TransSingle(AcrelMeters.OperateResultBytes1.Content, 28));
// esModbusTcpServer.busTcpServer.Write("x=4;34", esModbusTcpServer.busTcpServer.ByteTransform.TransSingle(AcrelMeters.OperateResultBytes1.Content, 32));
// esModbusTcpServer.busTcpServer.Write("x=4;36", esModbusTcpServer.busTcpServer.ByteTransform.TransUInt32(AcrelMeters.OperateResultBytes3.Content, 0));
// esModbusTcpServer.busTcpServer.Write("x=4;38", esModbusTcpServer.busTcpServer.ByteTransform.TransUInt32(AcrelMeters.OperateResultBytes3.Content, 72));
// esModbusTcpServer.busTcpServer.Write("x=4;40", esModbusTcpServer.busTcpServer.ByteTransform.TransSingle(AcrelMeters.OperateResultBytes1.Content, 100));
// esModbusTcpServer.busTcpServer.Write("x=4;42", esModbusTcpServer.busTcpServer.ByteTransform.TransUInt16(AcrelMeters.OperateResultBytes2.Content, 0));
// esModbusTcpServer.busTcpServer.Write("x=4;43", esModbusTcpServer.busTcpServer.ByteTransform.TransUInt16(AcrelMeters.OperateResultBytes2.Content, 2));
// esModbusTcpServer.busTcpServer.Write("x=4;44", esModbusTcpServer.busTcpServer.ByteTransform.TransUInt16(AcrelMeters.OperateResultBytes2.Content, 4));
// esModbusTcpServer.busTcpServer.Write("x=4;45", esModbusTcpServer.busTcpServer.ByteTransform.TransUInt16(AcrelMeters.OperateResultBytes2.Content, 6));
// esModbusTcpServer.busTcpServer.Write("x=4;46", esModbusTcpServer.busTcpServer.ByteTransform.TransUInt16(AcrelMeters.OperateResultBytes2.Content, 8));
// esModbusTcpServer.busTcpServer.Write("x=4;47", esModbusTcpServer.busTcpServer.ByteTransform.TransUInt16(AcrelMeters.OperateResultBytes2.Content, 10));
// esModbusTcpServer.busTcpServer.Write("x=4;50", esModbusTcpServer.busTcpServer.ByteTransform.TransUInt32(AcrelMeters.OperateResultBytes3.Content, 8));
// esModbusTcpServer.busTcpServer.Write("x=4;52", esModbusTcpServer.busTcpServer.ByteTransform.TransUInt32(AcrelMeters.OperateResultBytes3.Content, 16));
// esModbusTcpServer.busTcpServer.Write("x=4;54", esModbusTcpServer.busTcpServer.ByteTransform.TransUInt32(AcrelMeters.OperateResultBytes3.Content, 24));
// esModbusTcpServer.busTcpServer.Write("x=4;56", esModbusTcpServer.busTcpServer.ByteTransform.TransUInt32(AcrelMeters.OperateResultBytes3.Content, 32));
// esModbusTcpServer.busTcpServer.Write("x=4;58", esModbusTcpServer.busTcpServer.ByteTransform.TransUInt32(AcrelMeters.OperateResultBytes3.Content, 0));
// esModbusTcpServer.busTcpServer.Write("x=4;60", esModbusTcpServer.busTcpServer.ByteTransform.TransUInt32(AcrelMeters.OperateResultBytes3.Content, 88));
// esModbusTcpServer.busTcpServer.Write("x=4;62", esModbusTcpServer.busTcpServer.ByteTransform.TransUInt32(AcrelMeters.OperateResultBytes3.Content, 96));
// esModbusTcpServer.busTcpServer.Write("x=4;64", esModbusTcpServer.busTcpServer.ByteTransform.TransUInt32(AcrelMeters.OperateResultBytes3.Content, 104));
// }
// }
// catch (Exception ex)
// {
// LogService.Info($"时间:{DateTime.Now.ToString()}-【ExitPeakValley】-{ex.Message}");
// }
// await Task.Delay(2000);
// }
//}
#endregion
///
/// 线程启用的标志位
/// 退出关闭标志位
///
public bool ThreadEnable { get; set; } = true;
///
/// 当前系统报警消息内容
/// 不是来自设备实际报警
/// 来自软件判断
///
public string CurSysAlarmMsg { get; set; }
#region 储能指令函数
//MasterSlave
///
/// 储能充电指令
/// 可实时调用这个方法
/// 英博PCS 正从电网充电
/// 可实时给值
///
///
public void ChargPwCmd(double targetpw)
{
//指令状态
//EsSysCmdState = EnergyStoryageCmdState.ChargeValue;
if (BmsDataService.MaxChargePowerCell.RtValue * ConfigDataService.energyStorageRunConfig.MaxBatChargRatio < Math.Abs(targetpw))//超过了限值
{
//超过了限值就按照最大的限值发送
InPowerPCSDataService.PwTranceCmdValues.CmdValue = Math.Abs(BmsDataService.MaxChargePowerCell.RtValue * ConfigDataService.energyStorageRunConfig.MaxBatChargRatio) + 0;
return;
}
//实时写入到追踪模型中,变化大于阀值则发数据给PCS 让总关口电表为正不能为0
InPowerPCSDataService.PwTranceCmdValues.CmdValue = Math.Abs(targetpw) / 1.0 + ConfigDataService.energyStorageRunConfig.PcsChargOffset;
////指令状态 没有分布式之前
//EsSysCmdState = EnergyStoryageCmdState.ChargeValue;
//if (BmsDataService.MaxChargePowerCell.RtValue * ConfigDataService.energyStorageRunConfig.MaxBatChargRatio < Math.Abs(targetpw))//超过了限值
//{
// //超过了限值就按照最大的限值发送
// InPowerPCSDataService.PwTranceCmdValues.CmdValue = Math.Abs(BmsDataService.MaxChargePowerCell.RtValue * ConfigDataService.energyStorageRunConfig.MaxBatChargRatio) + 0;
// return;
//}
////实时写入到追踪模型中,变化大于阀值则发数据给PCS 让总关口电表为正不能为0
//InPowerPCSDataService.PwTranceCmdValues.CmdValue = Math.Abs(targetpw) / 1.0 + ConfigDataService.energyStorageRunConfig.PcsChargOffset;
}
/////
///// 计算或者获取Pcs的目标指令值
/////
//private double PcsTargetPw { get; set; }
///
/// 储能放电指令
/// 英博PCS 负给电网放电
/// 可实时给值
///
///
public void DisChargPwCmd(double targetpw)
{
//指令状态
//EsSysCmdState = EnergyStoryageCmdState.DischargeValue;
if (BmsDataService.MaxDisChargePowerCell.RtValue * ConfigDataService.energyStorageRunConfig.MaxBatDisChargRatio < Math.Abs(targetpw))//超过了限值
{
//超过了限值就按照最大的限值发送
InPowerPCSDataService.PwTranceCmdValues.CmdValue = -(Math.Abs(BmsDataService.MaxDisChargePowerCell.RtValue * ConfigDataService.energyStorageRunConfig.MaxBatDisChargRatio) + 0);
return;
}
//实时写入到追踪模型中,变化大于阀值则发数据给PCS
InPowerPCSDataService.PwTranceCmdValues.CmdValue = -(Math.Abs(targetpw) / 1.0 + ConfigDataService.energyStorageRunConfig.PcsDisChargOffset);
////指令状态 没有分布式之前
//EsSysCmdState = EnergyStoryageCmdState.DischargeValue;
//if (BmsDataService.MaxDisChargePowerCell.RtValue * ConfigDataService.energyStorageRunConfig.MaxBatDisChargRatio < Math.Abs(targetpw))//超过了限值
//{
// //超过了限值就按照最大的限值发送
// InPowerPCSDataService.PwTranceCmdValues.CmdValue = -(Math.Abs(BmsDataService.MaxDisChargePowerCell.RtValue * ConfigDataService.energyStorageRunConfig.MaxBatDisChargRatio) + 0);
// return;
//}
////实时写入到追踪模型中,变化大于阀值则发数据给PCS
//InPowerPCSDataService.PwTranceCmdValues.CmdValue = -(Math.Abs(targetpw) / 1.0 + ConfigDataService.energyStorageRunConfig.PcsDisChargOffset);
}
///
/// 发送全功率放电
/// 可实时给值
///
public void SendFullDisChargePwValueCmd(double cmdValue)
{
//指令状态 这里只是标记状态
//EsSysCmdState = EnergyStoryageCmdState.FullDischarge;
//发送全功率的功率值给Pcs
InPowerPCSDataService.PwTranceCmdValues.CmdValue = -Math.Abs(cmdValue) / 1.0;
}
///
/// 发送全功率充电
/// 可实时给值
///
public void SendFullChargePwCmd(double cmdValue)
{
//指令状态 这里只是标记状态
//EsSysCmdState = EnergyStoryageCmdState.FullCharge;
//发送全功率的功率值给Pcs
InPowerPCSDataService.PwTranceCmdValues.CmdValue = Math.Abs(cmdValue) / 1.0 + 0;
}
///
/// 待机指令
/// 其实给PCS发送0的功率值则就是待机指令
/// 可实时给值
///
public void SendStandby()
{
//指令状态 无指令的状态,PCS待机状态 为0的功率值
//EsSysCmdState = EnergyStoryageCmdState.Standby;
InPowerPCSDataService.PwTranceCmdValues.CmdValue = 0;
}
#endregion
#region 储能的状态机
///
/// 储能状态机初始化配置
///
private void StateMachineInitial()
{
//初始状态是这个状态,不然同一个状态会重复进入导致状态机报错
_EsSysRunState = EnergyStorageState.Inital;
EnergyStorageStateMachine = new StateMachine(EnergyStorageState.Inital);
//初始状态
EnergyStorageStateMachine.Configure(EnergyStorageState.Inital)
.Permit(EnergyStorageStateTrig.HandTrig, EnergyStorageState.Hand)
.Permit(EnergyStorageStateTrig.StandbyTrig, EnergyStorageState.Standby)
.Permit(EnergyStorageStateTrig.ReadyCmdTrig, EnergyStorageState.ReadyCmd)
.Permit(EnergyStorageStateTrig.AlarmTrig, EnergyStorageState.Alarm)
.Ignore(EnergyStorageStateTrig.InitalTrig);
//待机状态
EnergyStorageStateMachine.Configure(EnergyStorageState.Standby)
.Permit(EnergyStorageStateTrig.HandTrig, EnergyStorageState.Hand)
.Permit(EnergyStorageStateTrig.AlarmTrig, EnergyStorageState.Alarm)
.Permit(EnergyStorageStateTrig.ReadyCmdTrig, EnergyStorageState.ReadyCmd)
.Ignore(EnergyStorageStateTrig.StandbyTrig)
.OnEntry(() => EntryStandby())
.OnExit(() => ExitStandby());
//峰谷模式/命令等待 状态
EnergyStorageStateMachine.Configure(EnergyStorageState.ReadyCmd)
.Permit(EnergyStorageStateTrig.HandTrig, EnergyStorageState.Hand)
.Permit(EnergyStorageStateTrig.StandbyTrig, EnergyStorageState.Standby)
.Permit(EnergyStorageStateTrig.AlarmTrig, EnergyStorageState.Alarm)
.Ignore(EnergyStorageStateTrig.ReadyCmdTrig)
.OnEntry(() => EntryReadyCmd())
.OnExit(() => ExitReadyCmd());
//报警状态
EnergyStorageStateMachine.Configure(EnergyStorageState.Alarm)
.Permit(EnergyStorageStateTrig.HandTrig, EnergyStorageState.Hand)
.Permit(EnergyStorageStateTrig.StandbyTrig, EnergyStorageState.Standby)
.Permit(EnergyStorageStateTrig.ReadyCmdTrig, EnergyStorageState.ReadyCmd)
.Ignore(EnergyStorageStateTrig.AlarmTrig)
.OnEntry(() => EntryAlarm())
.OnExit(() => ExitAlarm());
//手动状态
EnergyStorageStateMachine.Configure(EnergyStorageState.Hand)
.Permit(EnergyStorageStateTrig.AlarmTrig, EnergyStorageState.Alarm)
.Permit(EnergyStorageStateTrig.StandbyTrig, EnergyStorageState.Standby)
.Permit(EnergyStorageStateTrig.ReadyCmdTrig, EnergyStorageState.ReadyCmd)
.Ignore(EnergyStorageStateTrig.HandTrig)
.OnEntry(() => EntryHand())
.OnExit(() => ExitHand());
//初始的储能检查
EnergyStorageCheck();
}
public TrigModuleStartRunAction TrigModuleStartRunActions { get; set; }
///
/// 削峰填谷的线程取消操作
///
private CancellationTokenSource ReadyCmdTokenSource { get; set; }
///
/// 报警的线程取消操作
///
private CancellationTokenSource AlarmTokenSource;
///
/// 待机的线程取消操作
///
private CancellationTokenSource StandbyTokenSource;
///
/// 进入手动模式
/// 手动模式的优先级比较高,在当前模式下,即使报警了,也不自动跳转。其跳转由人工手动触发,
/// 手动模式和自动模式,手动模式是一个确定的模式,没有确定和具体的自动模式,自动模式是跳转到包括报警和待机和等待指令的任何一个模式(具体要看当时的情况)
///
///
private void EntryHand()
{
HandAutoState = "手动模式";
EsSysRunState = EnergyStorageState.Hand;
CurClientInfo.SysState = "Hand";
AutoHandValue = false;
Console.WriteLine($"时间:{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss fff")}:储能进入【手动】模式 ");
}
private bool _AutoHandValue = true;
///
/// 手自动值
/// 手动为False
/// 自动为True
///
public bool AutoHandValue
{
get { return _AutoHandValue; }
set { _AutoHandValue = value; RaisePropertyChanged(); }
}
///
/// 退出手动模式
///
///
private void ExitHand()
{
HandAutoState = "自动模式";
AutoHandValue = true;
Console.WriteLine($"时间:{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss fff")}:储能离开【手动】模式 ");
}
///
/// 离开命令等待的模式
///
///
private void ExitReadyCmd()
{
try
{
//线程取消,防止一直运行和后面的冲突
ReadyCmdTokenSource.Cancel();
//离开命令等待,之前可能有遗漏的指令,防止其他的状态残留,那么需要发送PCS待机指令 可能退出之前还是大功率充电
SendStandby();
Console.WriteLine($"时间:{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss fff")}:储能离开【命令等待】模式 ");
}
catch (Exception ex)
{
LogService.Info($"时间:{DateTime.Now.ToString()}-【ExitPeakValley】-{ex.Message}");
}
}
///
/// 进入储能的等待指令的状态
/// 则此时需要接受通信的数据
/// 如果和EMS通信的状态是OK的话,直接执行EMS的指令
///
private void EntryReadyCmd()
{
try
{
Console.WriteLine($"时间:{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss fff")}:储能进入【等待指令】模式 ");
//EsSysRunStateMsg = "峰谷状态";
EsSysRunState = EnergyStorageState.ReadyCmd;
CurClientInfo.SysState = "ReadyCmd";
ReadyCmdTokenSource = new CancellationTokenSource();
//等待EMS指令的状态
Task.Run(() =>
{
//判断储能的状态是否正确
while (EsSysRunState == EnergyStorageState.ReadyCmd)
{
try
{
Thread.Sleep(200);
//检查储能的状态
if (!CheckEnergyStorageModuleLink().Result || !CheckEnergyStorageModuleAlarm().Result)//产生报警
{
//产生报警,把自动触发PCS运行关闭掉
//可能运行自动触发PCS运行的循环,先关闭循环,没触发也可以关闭
TrigModuleStartRunActions.PcsAutoTrigClose();
//EsSysRunState=EnergyStorageState.Alarm;
//产生报警
Console.WriteLine($"时间:{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss fff")}:储能待机状态判断 产生报警 跳转-开始进入重新策略分配 ");
StrategyAllocate(EnergyStorageState.Alarm);
break;
}
else if (!CheckEnergyStorageModuleRunState().Result)
{
//储能的状态出现问题,跳转到待机状态
//可能运行自动触发PCS运行的循环,先关闭循环,没触发也可以关闭
TrigModuleStartRunActions.PcsAutoTrigClose();
Console.WriteLine($"时间:{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss fff")}:储能的状态出现问题,-开始进入待机状态 ");
StrategyAllocate(EnergyStorageState.Standby);
break;
}
else//依旧存在未正常运行状态,维持当前状态机
{
//当处于待机状态时,主要组件没有运行,那么可以通过自动执行指令进行运行指令的操作
if (true)
{
}
}
if (ReadyCmdTokenSource.IsCancellationRequested)
{
break;
}
//先检查跟服务器的状态,服务器的状态没有跟储能本体的状态绑定,分开,方便拆分状态逻辑
if (EMSSocketClientConState.ConResult)
{
switch (CurServerCmd.CmdType)
{
case "Charg"://充电
ChargPwCmd(CurServerCmd.CmdPw);
break;
case "DisCharg"://放电
DisChargPwCmd(CurServerCmd.CmdPw);
break;
default:
break;
}
//液冷控制
if (CurServerCmd.CoolOnOffCmd)
{
ACService.SetCoolCtrModel(CoolState.Auto);
}
else
{
ACService.SetCoolCtrModel(CoolState.Stop);
}
}
else//和服务器的通信状态失败,那么指令就没有意义了,防止之前的指令残留,设置为0
{
switch (CurServerCmd.CmdType)
{
case "Charg"://充电
ChargPwCmd(0);
break;
case "DisCharg"://放电
DisChargPwCmd(0);
break;
default:
break;
}
}
}
catch (Exception ex)
{
LogService.Info($"时间:{DateTime.Now.ToString()}-【EntryAlarm】-{ex.Message}");
}
}
}, ReadyCmdTokenSource.Token);
}
catch (Exception ex)
{
LogService.Info($"时间:{DateTime.Now.ToString()}-【EntryReadyCmd】-{ex.Message}");
}
}
///
/// 进入初始化状态
/// 开始检查各个系统的状态
/// 确保连接成功和没有报警
///
///
private void EnergyStorageCheck()
{
try
{
//确保通信连接正常 BMS和PCS 电表
var LinkData = CheckEnergyStorageModuleLink();
if (!LinkData.Result)
{
//触发报警
//if (EnergyStorageStateMachine.State != EnergyStorageState.Alarm)
//{
EnergyStorageStateMachine.Fire(EnergyStorageStateTrig.AlarmTrig);
//}
Console.WriteLine($"时间:{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss fff")}:储能初始检查【通信连接失败】");
CurSysAlarmMsg = LinkData.Msg;
return;
}
var AlarmData = CheckEnergyStorageModuleAlarm();
if (!AlarmData.Result)
{
//if (EnergyStorageStateMachine.State != EnergyStorageState.Alarm)
//{
//触发报警
EnergyStorageStateMachine.Fire(EnergyStorageStateTrig.AlarmTrig);
//}
Console.WriteLine($"时间:{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss fff")}:储能初始检查【报警发生】");
CurSysAlarmMsg = AlarmData.Msg;
}
if (ConfigDataService.IsStartAuto)
{
//如果到这里的话 没有问题的话则进入待机模式
EnergyStorageStateMachine.Fire(EnergyStorageStateTrig.StandbyTrig);
}
else
{
EnergyStorageStateMachine.Fire(EnergyStorageStateTrig.HandTrig);
}
}
catch (Exception ex)
{
LogService.Info($"时间:{DateTime.Now.ToString()}-【PeakValleyCycle】-{ex.Message}");
}
}
#region 储能检查
///////////////////////////////////////////////////////////////
///进入储能的削峰填谷的状态模式,需要具备
///1)模块连接正常
///2)模块没有报警
///3)模块运行状态符合要求
///////////////////////////////////////////////////////////////
///
/// 检查模块通信状态
///
///
private ResultInfo CheckEnergyStorageModuleLink()
{
try
{
////Test
if (ConfigDataService.IsDebug)
{
return new ResultInfo() { Result = true, Msg = "" };
}
//检查BMS通信
if (!BmsDataService.LinkStateModels.LinkState)
{
//Console.WriteLine($"时间:{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss fff")}:储能检查【BMS通信失败】");
return new ResultInfo() { Result = false, Msg = "BMS通信失败" };
}
//检查PCS通信
if (InPowerPCSDataService.PcsRunState.PcsLinkState == LinkState.LinkNG)
{
//Console.WriteLine($"时间:{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss fff")}:储能检查【PCS通信失败】");
return new ResultInfo() { Result = false, Msg = "PCS通信失败" };
}
//检查电表通信
if (!AcrelMeters.MeterLinkState)
{
//Console.WriteLine($"时间:{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss fff")}:储能检查【电表通信失败】");
return new ResultInfo() { Result = false, Msg = "电表通信失败" };
}
//通信成功
return new ResultInfo() { Result = true, Msg = null };
}
catch (Exception ex)
{
//LogService.Info($"时间:{DateTime.Now.ToString()}-【CheckEnergyStorageModuleLink】-{ex.Message}");
//通信成功
return new ResultInfo() { Result = false, Msg = null };
}
}
///
/// 检查模块的报警状态
///
///
private ResultInfo CheckEnergyStorageModuleAlarm()
{
try
{
////Test
if (ConfigDataService.IsDebug)
{
return new ResultInfo() { Result = true, Msg = "" };
}
//return new ResultInfo() { Result = true, Msg = "BMS通信失败" };
//检查BMS报警
if (BmsDataService.BMSAlarmState == BMSAlarmStateEnum.Alarm)
{
//Console.WriteLine($"时间:{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss fff")}:储能检查【BMS报警】");
return new ResultInfo() { Result = false, Msg = "BMS报警" };
}
//检查PCS报警
if (InPowerPCSDataService.PcsRunState.PcsSysAlarmState == PcsAlarmState.Alarm)
{
//Console.WriteLine($"时间:{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss fff")}:储能检查【PCS报警】");
return new ResultInfo() { Result = false, Msg = "PCS报警" };
}
//检查PCS故障
if (InPowerPCSDataService.PcsRunState.PcsSysFaultState == PcsFaultState.Fault)
{
//Console.WriteLine($"时间:{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss fff")}:储能检查【PCS故障】");
return new ResultInfo() { Result = false, Msg = "PCS故障" };
}
////检查液冷故障
//if (BmsDataService.CoolAlarmState)
//{
// Console.WriteLine($"时间:{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss fff")}:储能检查【液冷报警】");
// return new ResultInfo() { Result = false, Msg = "液冷报警" };
//}
//没有故障发生
return new ResultInfo() { Result = true, Msg = "" };
}
catch (Exception ex)
{
LogService.Info($"时间:{DateTime.Now.ToString()}-【CheckEnergyStorageModuleAlarm】-{ex.Message}");
//没有故障发生
return new ResultInfo() { Result = true, Msg = "" };
}
}
///
/// 检查储能的运行状态
/// 报警的优先级更高
///
///
private ResultInfo CheckEnergyStorageModuleRunState()
{
try
{
////Test
if (ConfigDataService.IsDebug)
{
return new ResultInfo() { Result = true, Msg = "" };
}
//检查BMS运行状态
if (!BmsDataService.BmsTotalState)
{
//Console.WriteLine($"时间:{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss fff")}:储能检查【BMS未正常运行】");
return new ResultInfo() { Result = false, Msg = "BMS未正常运行" };
}
//检查PCS运行状态
if (InPowerPCSDataService.PcsRunState.PcsStateInfo == PCSState.Stop)
{
//Console.WriteLine($"时间:{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss fff")}:储能检查【PCS未运行】");
return new ResultInfo() { Result = false, Msg = "PCS未运行" };
}
//检查液冷运行状态
//液冷并不总是运行,根据温度进行逻辑判断,并且液冷不直接影响削峰填谷的执行,报警状态已经能概括液冷的运行状态了
//if (xxx)
//{
// Console.WriteLine($"时间:{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss fff")}:储能检查【PCS未运行】");
// return new ResultInfo() { Result = false, Msg = "PCS未运行" };
//}
//检查消防运行状态
//消防没有运行与否负状态,并且液冷不直接影响削峰填谷的执行,报警状态已经能概括消防的运行状态了
//if (xxx)
//{
// Console.WriteLine($"时间:{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss fff")}:储能检查【PCS未运行】");
// return new ResultInfo() { Result = false, Msg = "PCS未运行" };
//}
//正常运行
return new ResultInfo() { Result = true, Msg = null };
}
catch (Exception ex)
{
LogService.Info($"时间:{DateTime.Now.ToString()}-【PeakValleyCycle】-{ex.Message}");
//正常运行
return new ResultInfo() { Result = true, Msg = null };
}
}
#endregion
///
/// 进入储能待机状态
///
///
private void EntryStandby()
{
Console.WriteLine($"时间:{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss fff")}:储能进入【待机】模式 ");
//EsSysRunStateMsg = "待机状态";
EsSysRunState = EnergyStorageState.Standby;
CurClientInfo.SysState = "Standby";
StandbyTokenSource = new CancellationTokenSource();
//报警任务循环
Task.Run(() =>
{
//待机状态时,如果是PCS的停止了,那么需要自动触发PCS运行
if (InPowerPCSDataService.PcsRunState.PcsStateInfo == PCSState.Stop)
{
TrigModuleStartRunActions.PcsAutoTrigRun();
}
//判断储能的状态是否正确
while (EsSysRunState == EnergyStorageState.Standby)
{
try
{
Thread.Sleep(100);
if (StandbyTokenSource.IsCancellationRequested)
{
break;
}
//待机状态,可能转到报警,可能转到削峰填谷 报警优先判断
//循环获取系统的状态
if (!CheckEnergyStorageModuleLink().Result || !CheckEnergyStorageModuleAlarm().Result)//产生报警
{
//可能运行自动触发PCS运行的循环,先关闭循环,没触发也可以关闭
TrigModuleStartRunActions.PcsAutoTrigClose();
//EsSysRunState=EnergyStorageState.Alarm;
//产生报警
Console.WriteLine($"时间:{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss fff")}:储能待机状态判断 产生报警 跳转-开始进入重新策略分配 ");
StrategyAllocate(EnergyStorageState.Alarm);
break;
}
else if (CheckEnergyStorageModuleRunState().Result)
{
//可能运行自动触发PCS运行的循环,先关闭循环,没触发也可以关闭
TrigModuleStartRunActions.PcsAutoTrigClose();
Console.WriteLine($"时间:{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss fff")}:未正常运行状态消失-储能待机状态判断,-开始进入重新策略分配 ");
StrategyAllocate(EnergyStorageState.ReadyCmd);
break;
}
else//依旧存在未正常运行状态,维持当前状态机
{
//当处于待机状态时,主要组件没有运行,那么可以通过自动执行指令进行运行指令的操作
}
}
catch (Exception ex)
{
LogService.Info($"时间:{DateTime.Now.ToString()}-【EntryStandby】-{ex.Message}");
}
}
}, StandbyTokenSource.Token);
}
///
/// 退出待机状态
///
///
private void ExitStandby()
{
StandbyTokenSource.Cancel();
Console.WriteLine($"时间:{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss fff")}:储能离开【待机】模式 ");
}
///
/// 进入储能的报警状态
///
///
private void EntryAlarm()
{
Console.WriteLine($"时间:{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss fff")}:储能进入【报警】模式 ");
//EsSysRunStateMsg = "报警状态";
EsSysRunState = EnergyStorageState.Alarm;
CurClientInfo.SysState = "Alarm";
AlarmTokenSource = new CancellationTokenSource();
//报警任务循环
var AlarmTask = Task.Run(() =>
{
//判断储能的状态是否正确
while (EsSysRunState == EnergyStorageState.Alarm)
{
try
{
Thread.Sleep(100);
if (AlarmTokenSource.IsCancellationRequested)
{
break;
}
//循环获取系统的状态
//State = CheckEnergyStorageAlarmState();
if (CheckEnergyStorageModuleLink().Result && CheckEnergyStorageModuleAlarm().Result)//没有报警状态
{
//报警消失,再判断模块的运行状态是否正常
if (CheckEnergyStorageModuleRunState().Result)
{
//报警消失
Console.WriteLine($"时间:{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss fff")}:储能报警消失-判断到削峰填谷-开始进入重新策略分配 ");
StrategyAllocate(EnergyStorageState.ReadyCmd);
break;
}
else
{
//报警消失
Console.WriteLine($"时间:{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss fff")}:储能报警消失-判断到待机状态-开始进入重新策略分配 ");
StrategyAllocate(EnergyStorageState.Standby);
break;
}
}
else//依旧存在报警状态,维持状态机
{
}
}
catch (Exception ex)
{
LogService.Info($"时间:{DateTime.Now.ToString()}-【EntryAlarm】-{ex.Message}");
}
}
}, AlarmTokenSource.Token);
}
///
/// 储能离开报警
///
///
private void ExitAlarm()
{
AlarmTokenSource.Cancel();
Console.WriteLine($"时间:{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss fff")}:储能离开【报警】模式 ");
}
///
/// 其他状态退出后暂时还没有状态分配
/// 这里进行状态分配一下
/// 策略分配
///
private void StrategyAllocate(EnergyStorageState newState)
{
//如果有切换到手自动的话,则进入到待机状态,否则进入削峰填谷的模式
//当然报警的等级是最高的,报警出来后才能接受外面的最新的状态
Console.WriteLine($"时间:{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss fff")}:储能开始【策略分配】 新判断:{newState.ToString()}");
try
{
// 【newState】是新的判断后的状态
switch (newState)
{
case EnergyStorageState.Inital:
break;
case EnergyStorageState.Standby:
EnergyStorageStateMachine.Fire(EnergyStorageStateTrig.StandbyTrig);
break;
case EnergyStorageState.Alarm:
EnergyStorageStateMachine.Fire(EnergyStorageStateTrig.AlarmTrig);
break;
case EnergyStorageState.ReadyCmd:
EnergyStorageStateMachine.Fire(EnergyStorageStateTrig.ReadyCmdTrig);
break;
default:
break;
}
}
catch (Exception ex)
{
LogService.Error($"错误信息,策略分配处的状态机出现错误 {ex.Message}");
StrategyAllocate(newState);
}
}
#endregion
#region 光伏的开关和电能逻辑
///
/// 是否可以充电
/// 1) 电池状态允许
/// 2) 电池Soc允许
/// 3)PCS运行状态
///
///
public bool IsCanCharg()
{
//电池
if (BmsDataService.BmsAlarmStateMsg == "禁充标志")
{
IsCanChargMsg = "禁止";
return false;
}
if (BmsDataService.BmsAlarmStateMsg == "充满状态")
{
IsCanChargMsg = "禁止";
return false;
}
if (BmsDataService.BmsAlarmStateMsg == "告警状态")
{
IsCanChargMsg = "禁止";
return false;
}
//模式判断 模式不是命令等待模式时,给Server状态不进行充放电
if (EsSysRunState != EnergyStorageState.ReadyCmd)
{
IsCanChargMsg = "禁止";
return false;
}
//PCS
if (InPowerPCSDataService.PcsRunState.PcsStateMsg == "停止")
{
IsCanChargMsg = "禁止";
return false;
}
//SOC处于运行的范围之内
if (BmsDataService.BmsSOC.RtValue <= ConfigDataService.energyStorageRunConfig.BMSSocUpSignLimitValue)
{
IsCanChargMsg = "允许";
return true;
}
else
{
IsCanChargMsg = "禁止";
return false;
}
//IsCanChargMsg = "禁止";
//return false;
}
private string _IsCanChargMsg;
///
/// 是否可以充电文本
///
public string IsCanChargMsg
{
get { return _IsCanChargMsg; }
set { _IsCanChargMsg = value; RaisePropertyChanged(); }
}
private string _IsCanDisChargMsg;
///
/// 是否可以放电文本
///
public string IsCanDisChargMsg
{
get { return _IsCanDisChargMsg; }
set { _IsCanDisChargMsg = value; RaisePropertyChanged(); }
}
///
/// 是否可以放电
/// 1) 电池状态允许
/// 2) 电池Soc允许
/// 3)PCS运行状态
///
///
public bool IsCanDisCharg()
{
//电池
if (BmsDataService.BmsAlarmStateMsg == "禁放标志")
{
IsCanDisChargMsg = "禁止";
return false;
}
if (BmsDataService.BmsAlarmStateMsg == "放空状态")
{
IsCanDisChargMsg = "禁止";
return false;
}
if (BmsDataService.BmsAlarmStateMsg == "告警状态")
{
IsCanDisChargMsg = "禁止";
return false;
}
//PCS
if (InPowerPCSDataService.PcsRunState.PcsStateMsg == "停止")
{
IsCanDisChargMsg = "禁止";
return false;
}
//模式判断 模式不是命令等待模式时,给Server状态不进行充放电
if (EsSysRunState != EnergyStorageState.ReadyCmd)
{
IsCanChargMsg = "禁止";
return false;
}
if (BmsDataService.BmsSOC.RtValue >= ConfigDataService.energyStorageRunConfig.BMSSocDownSignLimitValue)
{
IsCanDisChargMsg = "允许";
return true;
}
else
{
IsCanDisChargMsg = "禁止";
return false;
}
//IsCanDisChargMsg = "禁止";
//return false;
}
///
/// 最大允许充电功率
///
///
public double GetMaxChargPw()
{
return BmsDataService.MaxChargePowerCell.RtValue;
}
///
/// 最大允许放电电功率
///
///
public double GetMaxDisChargPw()
{
return BmsDataService.MaxDisChargePowerCell.RtValue;
}
#endregion
///
/// 切换到手动模式 手动模式等于待机模式 暂时这么定义
/// 进度待机模式
///
public string HandModel()
{
//
if (EsSysRunState == EnergyStorageState.Alarm)
{
return "当前处于报警状态,无法切换到手动模式,请报警结束后再重试";
}
else
{
EnergyStorageStateMachine.Fire(EnergyStorageStateTrig.StandbyTrig);
return "OK";
}
}
///
/// 英博PCS实例
///
public InPowerPCSDataService InPowerPCSDataService { get; set; }
public IFreeSql FreeSql { get; }
public ACService ACService { get; }
///
/// 系统的配置服务实例
///
public ConfigDataService ConfigDataService { get; }
///
/// BMS模型实例
///
public BmsDataService BmsDataService { get; set; }
///
/// 光伏的数据服务
///
public SolarEnergyService SolarEnergyService { get; }
/////
///// 电表数据
/////
//public PwMeter PwMeters { get; set; }
///
/// 储能系统的状态机
///
public StateMachine EnergyStorageStateMachine { get; set; }
private string _HandAutoState = "自动模式";
///
/// 手自动模式
///
public string HandAutoState
{
get { return _HandAutoState; }
set { _HandAutoState = value; RaisePropertyChanged(); }
}
private string _EsSysRunStateMsg = "待机状态";
///
/// 储能系统运行状态
///
public string EsSysRunStateMsg
{
get { return _EsSysRunStateMsg; }
set { _EsSysRunStateMsg = value; RaisePropertyChanged(); }
}
private EnergyStorageState _EsSysRunState;
///
/// 储能当前的状态
///
public EnergyStorageState EsSysRunState
{
get { return _EsSysRunState; }
set
{
if (_EsSysRunState != value)//储能的状态改变了
{
switch (value)
{
case EnergyStorageState.Inital:
EsSysRunStateMsg = "初始化";
break;
case EnergyStorageState.Standby:
EsSysRunStateMsg = "待机";
break;
case EnergyStorageState.Alarm:
EsSysRunStateMsg = "报警";
break;
case EnergyStorageState.ReadyCmd:
EsSysRunStateMsg = "命令等待";
break;
case EnergyStorageState.Hand:
EsSysRunStateMsg = "手动";
break;
default:
break;
}
_EsSysRunState = value;
}
}
}
/////
///// 储能系统的指令状态
/////
//public StateMachine EnergyStoryageCmdStateMachine { get; set; }
///
/// 获取储能系统的状态
///
///
public EnergyStorageState GetEnergyStorageState()
{
//return EnergyStorageState.Charge;
return EsSysRunState;
}
#region Slave Client 本站
///
/// 驱动扫描线程
///
static Task mainTask = null;
///
/// 线程使能
///
public bool WebSocketThreadEnable { get; set; } = true;
///
/// 当前的客户端状态指令内容
///
private ClientInfo CurClientInfo { get; set; } = new ClientInfo();
///
/// 当前站号
///
public ushort ClientStation { get; set; }
//客户端考虑是否可以充放电的时候,除了状态,把SOC的情况放进去
private EnergyStoryageCmdState _EsSysCmdState;
///
/// 储能的指令状态
/// 只是监视全功率的指令的变化 这个有问题,就是全功率实时发送一次,但是全功率的功率值根据SOC是改变的,可能需要监视全功率值,然后多次触发全功率数据????
///
public EnergyStoryageCmdState EsSysCmdState
{
get { return _EsSysCmdState; }
set
{
if (value != _EsSysCmdState)
{
switch (value)
{
case EnergyStoryageCmdState.NoCmd://指令是实时的值
EsSysCmdStateMsg = "无指令";
Console.WriteLine($"时间:{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss fff")}:进入平衡阶段,不需要调整[维持上一个指令] ");
break;
case EnergyStoryageCmdState.Standby://指令是实时的值
EsSysCmdStateMsg = "待机指令";
Console.WriteLine($"时间:{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss fff")}:储能PCS待机指令 ");
//InPowerPCSDataService.StandbyPwCmd();
break;
case EnergyStoryageCmdState.ChargeValue://指令是实时的值
EsSysCmdStateMsg = "充电指令";
break;
case EnergyStoryageCmdState.DischargeValue://指令是实时的值
EsSysCmdStateMsg = "放电指令";
break;
case EnergyStoryageCmdState.FullCharge://全功率充电 变化时发送一次数据
EsSysCmdStateMsg = "全功率充电指令";
//这里只是标记状态,因为最大功率是变化的,这里只能执行一次,那么在赋值的时候做一个处理
break;
case EnergyStoryageCmdState.FullDischarge://全功率放电 变化时发送一次数据
EsSysCmdStateMsg = "全功率放电指令";
//这里只是标记状态,因为最大功率是变化的,这里只能执行一次,那么在赋值的时候做一个处理
Console.WriteLine($"时间:{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss fff")}:全功率放电指令 ");
break;
default:
break;
}
_EsSysCmdState = value;
}
}
}
private string _EsSysCmdStateMsg;
///
/// 储能的指令状态
/// 只是监视全功率的指令的变化 这个有问题,就是全功率实时发送一次,但是全功率的功率值根据SOC是改变的,可能需要监视全功率值,然后多次触发全功率数据????
///
public string EsSysCmdStateMsg
{
get { return _EsSysCmdStateMsg; }
set { _EsSysCmdStateMsg = value; RaisePropertyChanged(); }
}
///
/// WebSocketClient
///
private WebSocketClient wsClient { get; set; }
///
/// WebSocketClient 的状态
///
public EMSClientConState EMSSocketClientConState { get; set; } = new EMSClientConState();
///
/// WebSocket Url
///
public string WebUrl { get; set; } = "ws://127.0.0.1:1883";
///
/// 当前服务侧发送给客户端的指令
///
public ServerCmd CurServerCmd { get; set; } = new ServerCmd();
///
/// WebSocketClient初始化函数
///
private void WebSocketClientInit()
{
EMSSocketClientConState = new EMSClientConState();
EMSSocketClientConState.EMSClientConErrEventHandler += EMSSocketClientConState_EMSClientConErrEventHandler;
wsClient?.ConnectClose();
//ws://183.6.55.87:8036/dev-api/mesWebSocket
//wsClient = new WebSocketClient( textBox1.Text, int.Parse( textBox2.Text ), textBox5.Text );//( textBox1.Text, int.Parse(textBox2.Text), textBox5.Text );
//wsClient = new WebSocketClient("ws://183.6.55.87:8036/dev-api/mesWebSocket");//( textBox1.Text, int.Parse(textBox2.Text), textBox5.Text );
wsClient = new WebSocketClient(WebUrl);//( textBox1.Text, int.Parse(textBox2.Text), textBox5.Text );
//wsClient.LogNet = new HslCommunication.LogNet.LogNetSingle(string.Empty);
//wsClient.LogNet.BeforeSaveToFile += LogNet_BeforeSaveToFile;
wsClient.OnClientApplicationMessageReceive += WebSocket_OnWebSocketMessageReceived;
wsClient.OnNetworkError += WsClient_OnNetworkError; // 这里使用内置的处理方式,一般也就够用了。
wsClient.OnClientConnected += WsClient_OnClientConnected;
//connect = wsClient.ConnectServer();
//if (string.IsNullOrEmpty(textBox3.Text))
ConnectResult = wsClient.ConnectServer();
if (ConnectResult.IsSuccess)
{
EMSSocketClientConState.ClientSendState = true;
EMSSocketClientConState.ClientRecvState = true;
}
else
{
EMSSocketClientConState.ClientSendState = false;
EMSSocketClientConState.ClientRecvState = false;
}
//扫描开始
WebSocketScanStart();
}
///
/// 判定跟EMS通信失败触发的事件
/// 因为状态机里面有实时获取状态判断了
/// 这里不需要事件触发纸执行,暂时舍弃
///
///
///
///
private void EMSSocketClientConState_EMSClientConErrEventHandler(object? sender, EMSConErrEventArgs data)
{
if (data.Result)//
{
}
else//连接失败
{
////跟EMS通信失败后,立刻进入待机状态,如果当前处于待机状态也要先给PCS指令为0
//if (EnergyStorageStateMachine.State != EnergyStorageState.Standby)
//{
// SendStandby();//防止其他的状态残留,先给0功率
// EnergyStorageStateMachine.Fire(EnergyStorageStateTrig.StandbyTrig);
//}
}
}
///
/// 连接服务的结果
///
private OperateResult ConnectResult { get; set; }
///
/// 实时客户端的状态消息
///
///
private void WebSocketScanStart()
{
mainTask = Task.Run(async () =>
{
while (WebSocketThreadEnable)
{
await Task.Delay(100);
//定期发送数据,需要连接状态OK,否则实时主动连接Server直到成功
if (EMSSocketClientConState.ClientState)
{
CurClientInfo.MaxChargPw = BmsDataService.MaxChargePowerCell.RtValue;
CurClientInfo.MaxDisChargPw = BmsDataService.MaxDisChargePowerCell.RtValue;
CurClientInfo.SOC = BmsDataService.BmsSOC.RtValue;
CurClientInfo.CurActionCmdPw = InPowerPCSDataService.CurCmdPw;
CurClientInfo.IsCharg = IsCanCharg();
CurClientInfo.IsDisCharg = IsCanDisCharg();
CurClientInfo.CoolState=ACService.CapState== "开启"?true:false;
CurClientInfo.SOE = BmsDataService.BmsSOE.RtValue;
CurClientInfo.SOH = BmsDataService.BmsSOH.RtValue;
//开始发送数据
//发送数据成功,则代表发送状态OK
EMSSocketClientConState.ClientSendState = ClientSendMsg(CurClientInfo);
}
else
{
ConnectResult = wsClient.ConnectServer();
if (ConnectResult.IsSuccess)
{
if (ConnectResult.IsSuccess)
{
EMSSocketClientConState.ClientState = true;
}
else
{
EMSSocketClientConState.ClientState = false;
}
}
}
}
});
}
///
/// 客户端连接成功触发事件,重新连接也会触发
///
///
private void WsClient_OnClientConnected()
{
EMSSocketClientConState.ClientState = true;
LogService.Info($"时间:{DateTime.Now.ToString()}-【WebSocket客户端连接成功】");
}
///
/// 发送消息数据
///
///
///
public bool ClientSendMsg(ClientInfo msg)
{
return wsClient.SendServer(JsonSerializer.Serialize(msg)).IsSuccess;
}
///
/// 关闭连接
///
public void ClientCloseLink()
{
LogService.Info($"时间:{DateTime.Now.ToString()}-【WebSocket关闭连接】");
EMSSocketClientConState.ClientState = false;
wsClient?.ConnectClose();
}
///
/// 网络通信失败
///
///
///
///
private void WsClient_OnNetworkError(object? sender, EventArgs e)
{
LogService.Info($"时间:{DateTime.Now.ToString()}-【WebSocket网络通信失败】");
EMSSocketClientConState.ClientState = false;
}
///
/// WebSoketClient 接收到数据
///
///
private void WebSocket_OnWebSocketMessageReceived(WebSocketMessage message)
{
try
{
//if (EsSysRunState == EnergyStorageState.ReadyCmd)
//{
EMSSocketClientConState.ClientRecvState = true;
//反序列化数据
var data = JsonSerializer.Deserialize>(Encoding.UTF8.GetString(message.Payload)).Find(a => a.Station == ClientStation);
//充放电的指令
CurServerCmd.CmdPw = data!.CmdPw;
CurServerCmd.CmdType = data.CmdType;
//液冷的开关
CurServerCmd.CoolOnOffCmd = data!.CoolOnOffCmd;
//Pcs的开关
CurServerCmd.PcsOnOffCmd = data!.PcsOnOffCmd;
}
catch (Exception Ex)
{
LogService.Error($"时间:{DateTime.Now.ToString()}-【WebSocket接收到数据】ErrMessage{Ex.Message}");
}
}
#endregion
}
}