|
@@ -0,0 +1,395 @@
|
|
|
+using Aitex.Core.RT.Log;
|
|
|
+using Aitex.Core.Util;
|
|
|
+using DocumentFormat.OpenXml.InkML;
|
|
|
+using MECF.Framework.Common.CommonData.PowerSupplier;
|
|
|
+using MECF.Framework.Common.Communications;
|
|
|
+using MECF.Framework.Common.Net;
|
|
|
+using System;
|
|
|
+using System.Collections.Concurrent;
|
|
|
+using System.Collections.Generic;
|
|
|
+using System.Linq;
|
|
|
+using System.Text;
|
|
|
+using System.Threading.Tasks;
|
|
|
+
|
|
|
+namespace MECF.Framework.Common.Device.PowerSupplier
|
|
|
+{
|
|
|
+ public class PowerSupplierGoldModbusDevice : JetMessageTcpClient<PowerSupplierTcpGoldModbusMessage, PowerSupplierCommand>,IPowerSupplierDevice
|
|
|
+ {
|
|
|
+ #region 常量
|
|
|
+ private const short CURRENT_SETTING_ADDRESS = 0x6102;
|
|
|
+ private const short OUTPUT_CONTROL_ADDRESS = 0x0110;
|
|
|
+ private const short STEP_PERIOD_ADDRESS = 0x77D0;
|
|
|
+ private const short STEP_PERIOD_START_ADDRESS = 0x7C50;
|
|
|
+ private const short VOLTAGE_OUTPUT_ADDRESS = 0x0201;
|
|
|
+ private const short POWER_CONTROL_ADDRESS = 0x0113;
|
|
|
+ private const short POWER_RUN_MODEL_ADDRESS = 0x0111;
|
|
|
+ /// <summary>
|
|
|
+ /// 电源状态(00-cv输出,01-cc输出)
|
|
|
+ /// </summary>
|
|
|
+ private const short POWER_STATUS_ADDRESS = 0x0200;
|
|
|
+ private const string SET_POINT = "SetPoint";
|
|
|
+ private const string CURRENT = "Current";
|
|
|
+ private const string VOLTAGE = "Voltage";
|
|
|
+ private const string ENABLED = "Enabled";
|
|
|
+ private const string POWER_STATUS = "PowerStatus";
|
|
|
+ private const string POWER_CONTROL = "PowerControl";
|
|
|
+ private const string POWER_RUN_MODEL = "PowerRunModel";
|
|
|
+ /// <summary>
|
|
|
+ /// 步阶数据数量
|
|
|
+ /// </summary>
|
|
|
+ private const int STEP_PERIOD_LENGTH = 12;
|
|
|
+ #endregion
|
|
|
+ #region 内部变量
|
|
|
+ private string _name;
|
|
|
+ private string _lastErrorMsg = "";
|
|
|
+ private bool _isFirstConnected = false;
|
|
|
+ #endregion
|
|
|
+ /// <summary>
|
|
|
+ /// 构造函数
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="ip"></param>
|
|
|
+ /// <param name="port"></param>
|
|
|
+ public PowerSupplierGoldModbusDevice(string name, string ip, int port,int receiveTimeout,int sendTimeout) : base(ip, port)
|
|
|
+ {
|
|
|
+ ReceiveTimeout = receiveTimeout;
|
|
|
+ SendTimeout = sendTimeout;
|
|
|
+ ReconnectInterval = 3000;
|
|
|
+ ConnectTimeout = 1000;
|
|
|
+ _name = name;
|
|
|
+ }
|
|
|
+ /// <summary>
|
|
|
+ /// 连接
|
|
|
+ /// </summary>
|
|
|
+ /// <returns></returns>
|
|
|
+ public void Start()
|
|
|
+ {
|
|
|
+ Connect();
|
|
|
+ if (!_isFirstConnected)
|
|
|
+ {
|
|
|
+ _isFirstConnected = true;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ /// <summary>
|
|
|
+ /// 设置通道输出开关控制
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="channel"></param>
|
|
|
+ /// <param name="currentValue"></param>
|
|
|
+ /// <returns></returns>
|
|
|
+ public bool SetChannelOutputSwitchControl(byte channel, bool enabled)
|
|
|
+ {
|
|
|
+ PowerSupplierCommand command = new PowerSupplierCommand();
|
|
|
+ command.Channel = channel;
|
|
|
+ command.CommandCode = 0x06;
|
|
|
+ command.Address = (ushort)(OUTPUT_CONTROL_ADDRESS);
|
|
|
+ command.Datas = new ushort[] { enabled ? (ushort)01 : (ushort)00 };
|
|
|
+ return SetOperation(command);
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 设置电源控制
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="channel"></param>
|
|
|
+ /// <param name="currentValue"></param>
|
|
|
+ /// <returns></returns>
|
|
|
+ public bool SetChannelPowerControl(byte channel, byte remoteControl)
|
|
|
+ {
|
|
|
+ PowerSupplierCommand command = new PowerSupplierCommand();
|
|
|
+ command.Channel = channel;
|
|
|
+ command.CommandCode = 0x06;
|
|
|
+ command.Address = (ushort)(POWER_CONTROL_ADDRESS);
|
|
|
+ command.Datas = new ushort[] { remoteControl };
|
|
|
+ return SetOperation(command);
|
|
|
+ }
|
|
|
+ /// <summary>
|
|
|
+ /// 设置电源运行模式
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="channel"></param>
|
|
|
+ /// <param name="currentValue"></param>
|
|
|
+ /// <returns></returns>
|
|
|
+ public bool SetChannelPowerRunmodelControl(byte channel, byte model)
|
|
|
+ {
|
|
|
+ PowerSupplierCommand command = new PowerSupplierCommand();
|
|
|
+ command.Channel = channel;
|
|
|
+ command.CommandCode = 0x06;
|
|
|
+ command.Address = (ushort)(POWER_RUN_MODEL_ADDRESS);
|
|
|
+ command.Datas = new ushort[] { model };
|
|
|
+ return SetOperation(command);
|
|
|
+ }
|
|
|
+ /// <summary>
|
|
|
+ /// 设置步阶数据
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="channel"></param>
|
|
|
+ /// <param name="stepDatas"></param>
|
|
|
+ public bool SetStepPeriod(byte channel, List<PowerSupplierStepPeriodData> stepDatas, int voltageScale,int currentScale)
|
|
|
+ {
|
|
|
+ PowerSupplierCommand command = new PowerSupplierCommand();
|
|
|
+ command.Channel = channel;
|
|
|
+ command.CommandCode = 0x10;
|
|
|
+ command.Address = (ushort)STEP_PERIOD_ADDRESS;
|
|
|
+ command.RegisterCount = (ushort)(STEP_PERIOD_LENGTH * stepDatas.Count);
|
|
|
+ command.Datas = new ushort[STEP_PERIOD_LENGTH * stepDatas.Count];
|
|
|
+ for (int i = 0; i < stepDatas.Count; i++)
|
|
|
+ {
|
|
|
+ PowerSupplierStepPeriodData data = stepDatas[i];
|
|
|
+ command.Datas[0 + STEP_PERIOD_LENGTH * i] = (ushort)(data.Voltage * voltageScale/0xffff);
|
|
|
+ command.Datas[1 + STEP_PERIOD_LENGTH * i] = (ushort)(data.Voltage * voltageScale %0xffff);
|
|
|
+ command.Datas[2 + STEP_PERIOD_LENGTH * i] = (ushort)(Math.Round(stepDatas[i].Current * currentScale, 0)/0xffff);
|
|
|
+ command.Datas[3 + STEP_PERIOD_LENGTH * i] = (ushort)(Math.Round(stepDatas[i].Current * currentScale, 0) % 0xffff);
|
|
|
+ command.Datas[4 + STEP_PERIOD_LENGTH * i] = 0;
|
|
|
+ command.Datas[5 + STEP_PERIOD_LENGTH * i] = stepDatas[i].Hour;
|
|
|
+ command.Datas[6 + STEP_PERIOD_LENGTH * i] = 0;
|
|
|
+ command.Datas[7 + STEP_PERIOD_LENGTH * i] = stepDatas[i].Minute;
|
|
|
+ command.Datas[8 + STEP_PERIOD_LENGTH * i] = 0;
|
|
|
+ command.Datas[9 + STEP_PERIOD_LENGTH * i] = stepDatas[i].Second;
|
|
|
+ command.Datas[10 + STEP_PERIOD_LENGTH * i] = 0;
|
|
|
+ command.Datas[11 + STEP_PERIOD_LENGTH * i] = stepDatas[i].Microsecond;
|
|
|
+ }
|
|
|
+ return SetOperation(command);
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 启动步阶
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="channel"></param>
|
|
|
+ /// <param name="startStep"></param>
|
|
|
+ /// <param name="endStep"></param>
|
|
|
+ /// <param name="cycle"></param>
|
|
|
+ public bool StartStepPeriod(byte channel, ushort startStep, ushort endStep, ushort cycle)
|
|
|
+ {
|
|
|
+ PowerSupplierCommand command = new PowerSupplierCommand();
|
|
|
+ command.Channel = channel;
|
|
|
+ command.CommandCode = 0x10;
|
|
|
+ command.Address = (ushort)STEP_PERIOD_START_ADDRESS;
|
|
|
+ command.RegisterCount = 6;
|
|
|
+ command.Datas = new ushort[6] {0,startStep, 0,endStep,0,cycle };
|
|
|
+ return SetOperation(command);
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 设置电流
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="channel"></param>
|
|
|
+ /// <param name="currentValue"></param>
|
|
|
+ /// <returns></returns>
|
|
|
+ public bool SetCurrentValue(byte channel, int currentValue)
|
|
|
+ {
|
|
|
+ PowerSupplierCommand command = new PowerSupplierCommand();
|
|
|
+ command.Channel = channel;
|
|
|
+ command.CommandCode = 0x10;
|
|
|
+ command.Address = (ushort)(CURRENT_SETTING_ADDRESS);
|
|
|
+ command.RegisterCount = 4;//2N N-寄存器地址数据
|
|
|
+ ushort[] ushorts = new ushort[2];
|
|
|
+ ushorts[0] = (ushort)(currentValue / 0xFFFF);//高位
|
|
|
+ ushorts[1] = (ushort)(currentValue % 0xFFFF);//低位
|
|
|
+ command.Datas = ushorts;
|
|
|
+ return SetOperation(command);
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 设置电源状态
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="channel"></param>
|
|
|
+ /// <param name="currentValue"></param>
|
|
|
+ /// <returns></returns>
|
|
|
+ public bool SetChannelPowerStatus(byte channel, byte powerStatus)
|
|
|
+ {
|
|
|
+ PowerSupplierCommand command = new PowerSupplierCommand();
|
|
|
+ command.Channel = channel;
|
|
|
+ command.CommandCode = 0x06;
|
|
|
+ command.Address = (ushort)(POWER_STATUS_ADDRESS);
|
|
|
+ command.Datas = new ushort[] { powerStatus };
|
|
|
+ return SetOperation(command);
|
|
|
+ }
|
|
|
+ /// <summary>
|
|
|
+ /// 获取通道输出开关控制
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="channel"></param>
|
|
|
+ /// <returns></returns>
|
|
|
+ public void GetChannelOutput(byte channel)
|
|
|
+ {
|
|
|
+ PowerSupplierCommand applyCommand = new PowerSupplierCommand();
|
|
|
+ applyCommand.Channel = channel;
|
|
|
+ applyCommand.CommandCode = 0x03;
|
|
|
+ applyCommand.Address = (ushort)(OUTPUT_CONTROL_ADDRESS);
|
|
|
+ applyCommand.RegisterCount = 1;
|
|
|
+ applyCommand.Variables.Add(ENABLED, (0, 1));
|
|
|
+ ApplyDataOperation(applyCommand);
|
|
|
+ }
|
|
|
+ /// <summary>
|
|
|
+ /// 获取通道电源控制
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="channel"></param>
|
|
|
+ /// <returns></returns>
|
|
|
+ public void GetChannelPowerControl(byte channel)
|
|
|
+ {
|
|
|
+ PowerSupplierCommand applyCommand = new PowerSupplierCommand();
|
|
|
+ applyCommand.Channel = channel;
|
|
|
+ applyCommand.CommandCode = 0x03;
|
|
|
+ applyCommand.Address = (ushort)(POWER_CONTROL_ADDRESS);
|
|
|
+ applyCommand.RegisterCount = 1;
|
|
|
+ applyCommand.Variables.Add(POWER_CONTROL, (0, 1));
|
|
|
+ ApplyDataOperation(applyCommand);
|
|
|
+ }
|
|
|
+ /// <summary>
|
|
|
+ /// 获取通道电流设置数值
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="channel"></param>
|
|
|
+ /// <returns></returns>
|
|
|
+ public void GetChannelCurrentSetting(byte channel)
|
|
|
+ {
|
|
|
+ PowerSupplierCommand applyCommand = new PowerSupplierCommand();
|
|
|
+ applyCommand.Channel = channel;
|
|
|
+ applyCommand.CommandCode = 0x03;
|
|
|
+ applyCommand.Address = (ushort)(CURRENT_SETTING_ADDRESS);
|
|
|
+ applyCommand.RegisterCount = 2;
|
|
|
+ applyCommand.Variables.Add(SET_POINT, (0, 2));
|
|
|
+ ApplyDataOperation(applyCommand);
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 获取电源状态设置数值
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="channel"></param>
|
|
|
+ /// <returns></returns>
|
|
|
+ public void GetChannelPowerStatus(byte channel)
|
|
|
+ {
|
|
|
+ PowerSupplierCommand applyCommand = new PowerSupplierCommand();
|
|
|
+ applyCommand.Channel = channel;
|
|
|
+ applyCommand.CommandCode = 0x03;
|
|
|
+ applyCommand.Address = (ushort)(POWER_STATUS_ADDRESS);
|
|
|
+ applyCommand.RegisterCount = 1;
|
|
|
+ applyCommand.Variables.Add(POWER_STATUS, (0, 1));
|
|
|
+ ApplyDataOperation(applyCommand);
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 获取电源运行模式
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="channel"></param>
|
|
|
+ /// <returns></returns>
|
|
|
+ public void GetChannelPowerRunModel(byte channel)
|
|
|
+ {
|
|
|
+ PowerSupplierCommand applyCommand = new PowerSupplierCommand();
|
|
|
+ applyCommand.Channel = channel;
|
|
|
+ applyCommand.CommandCode = 0x03;
|
|
|
+ applyCommand.Address = (ushort)(POWER_RUN_MODEL_ADDRESS);
|
|
|
+ applyCommand.RegisterCount = 1;
|
|
|
+ applyCommand.Variables.Add(POWER_RUN_MODEL, (0, 1));
|
|
|
+ ApplyDataOperation(applyCommand);
|
|
|
+ }
|
|
|
+ /// <summary>
|
|
|
+ /// 申请电压和电流数值
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="channel"></param>
|
|
|
+ /// <returns></returns>
|
|
|
+ public void GetChannelVoltageAndCurrent(byte channel)
|
|
|
+ {
|
|
|
+ PowerSupplierCommand applyCommand = new PowerSupplierCommand();
|
|
|
+ applyCommand.Channel = channel;
|
|
|
+ applyCommand.CommandCode = 0x03;
|
|
|
+ applyCommand.Address = (ushort)(VOLTAGE_OUTPUT_ADDRESS);
|
|
|
+ applyCommand.RegisterCount = 4;
|
|
|
+ applyCommand.Variables.Add(VOLTAGE, (0, 2));
|
|
|
+ applyCommand.Variables.Add(CURRENT, (2, 2));
|
|
|
+ ApplyDataOperation(applyCommand);
|
|
|
+ }
|
|
|
+ /// <summary>
|
|
|
+ /// 设置操作
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="command"></param>
|
|
|
+ /// <returns></returns>
|
|
|
+ private bool SetOperation(PowerSupplierCommand command)
|
|
|
+ {
|
|
|
+ if (Connected)
|
|
|
+ {
|
|
|
+ NetResult netResult = SetData(command);
|
|
|
+ if (!netResult.IsSuccess)
|
|
|
+ {
|
|
|
+ WriteErrMsg($"write write {command.Address.ToString("X2")} value {command.Datas[0]} failed,{netResult.Message}");
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ NetResult netResult = Connect();
|
|
|
+ if (netResult.IsSuccess)
|
|
|
+ {
|
|
|
+ netResult = SetData(command);
|
|
|
+ if (!netResult.IsSuccess)
|
|
|
+ {
|
|
|
+ WriteErrMsg($"write {command.Address.ToString("X2")} value {command.Datas[0]} failed,{netResult.Message}");
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ WriteErrMsg("connect failed");
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ /// <summary>
|
|
|
+ /// 申请数据操作
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="command"></param>
|
|
|
+ private void ApplyDataOperation(PowerSupplierCommand command)
|
|
|
+ {
|
|
|
+ if (!Connected)
|
|
|
+ {
|
|
|
+ NetResult connectResult = Connect();
|
|
|
+ if (!connectResult.IsSuccess)
|
|
|
+ {
|
|
|
+ WriteErrMsg("connect failed");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ NetResult<PowerSupplierCommand> netResult = ApplyData(command);
|
|
|
+ if (!netResult.IsSuccess)
|
|
|
+ {
|
|
|
+ WriteErrMsg($"apply {command.Address.ToString("X2")} failed,{netResult.Message}");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ if (netResult.Data.Datas != null)
|
|
|
+ {
|
|
|
+ Dictionary<string, (int, int)> dictionary = command.Variables;
|
|
|
+ List<string> keys = dictionary.Keys.ToList();
|
|
|
+ foreach (string item in keys)
|
|
|
+ {
|
|
|
+ var result = dictionary[item];
|
|
|
+ if (item == ENABLED)
|
|
|
+ {
|
|
|
+ PowerSupplierDeviceConfigManager.Instance.UpdateModuleVariable(_name, command.Channel, ENABLED, netResult.Data.Datas[result.Item1] == 0x01);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ if (result.Item2 == 1)
|
|
|
+ {
|
|
|
+ PowerSupplierDeviceConfigManager.Instance.UpdateModuleVariable(_name, command.Channel, item, netResult.Data.Datas[result.Item1]);
|
|
|
+ }
|
|
|
+ else if (result.Item2 == 2)
|
|
|
+ {
|
|
|
+ int value = netResult.Data.Datas[result.Item1] * 0xFFFF + netResult.Data.Datas[result.Item1 + 1];
|
|
|
+ PowerSupplierDeviceConfigManager.Instance.UpdateModuleVariable(_name, command.Channel, item, value);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ /// <summary>
|
|
|
+ /// 写错误日志
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="msg"></param>
|
|
|
+ private void WriteErrMsg(string msg)
|
|
|
+ {
|
|
|
+ if (msg != _lastErrorMsg)
|
|
|
+ {
|
|
|
+ _lastErrorMsg = msg;
|
|
|
+
|
|
|
+ LOG.WriteLog(eEvent.ERR_POWERSUPPLIER, _name, msg);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|