Files
JP_KDDI_LFPS_48100/LFP_Manager/Function/CsSerialCommFunctionDelta.cs
2025-12-19 13:59:34 +09:00

1008 lines
45 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using LFP_Manager.DataStructure;
using LFP_Manager.Utils;
using LFP_Manager.Controls;
using System.Web.Services.Description;
using DevExpress.XtraTreeList;
using SnmpSharpNet;
using DevExpress.XtraGrid.Views.BandedGrid.Handler;
using static DevExpress.Xpo.Helpers.AssociatedCollectionCriteriaHelper;
namespace LFP_Manager.Function
{
class CsSerialCommFunctionDelta
{
public const byte READ_COIL_STATUS = 0x01;
public const byte READ_HOLDING_REG = 0x03;
public const byte READ_INPUT_REG = 0x04; //Byul 구문 추가 필요
public const byte FORCE_SINGLE_COIL = 0x05;
public const byte PRESET_SINGLE_REG = 0x06;
public const byte PRESET_MULTI_REG = 0x10;
public const byte WRITE_COIL_REG = 0x0F;
public const byte ERROR_REG = 0x90;
public const byte READ_WRITE_REG = 0x17;
public const byte SPECIAL_REG_02 = 0x19;
public const byte READ_DEV_ID = 0x2B;
public const byte FW_FLASH_ERASE_CMD = 0x43;
public const byte FW_FLASH_WRITE_CMD = 0x31;
public const byte NO_CMD = 0xFF;
public static byte[] GetCRC(byte[] pby, int nSize)
{
ushort uIndex, i;
ushort crc;
byte uchCRCHi = 0xff;
byte uchCRCLo = 0xff;
byte[] result = new byte[2];
for (i = 0; i < nSize; i++)
{
uIndex = (ushort)((int)uchCRCLo ^ (int)pby[i]);
uchCRCLo = (byte)(uchCRCHi ^ csConstData.CRC_Data.auchCRCHi[uIndex]);
uchCRCHi = csConstData.CRC_Data.auchCRCLo[uIndex];
}
crc = (ushort)((uchCRCHi << 8) | uchCRCLo);
result[0] = (byte)(crc >> 8);
result[1] = (byte)(crc >> 0);
return result;
}
static public byte[] MakeReadRegisterData(ushort DevID, ushort cmd, ushort ReadAddr, ushort Size)
{
byte[] result = new byte[8];
byte[] crc;
result[0] = (byte)DevID; // Device ID
result[1] = (byte)cmd; // Command
result[2] = (byte)(ReadAddr >> 8); // Register Address MSB
result[3] = (byte)(ReadAddr >> 0); // Register Address LSB
result[4] = (byte)(Size >> 8); // Count of Register MSB
result[5] = (byte)(Size >> 0); // Count of Register LSB
crc = GetCRC(result, 6);
result[6] = crc[1]; // CRCH
result[7] = crc[0]; // CRCL
return result;
}
static public byte[] MakeWriteCoilData(ushort DevID, ushort WriteAddr, short WriteData)
{
byte[] result = new byte[7 + (1 * 1) + 2];
byte[] crc;
ushort i = 0;
result[i++] = (byte)DevID; // Device ID
result[i++] = (byte)WRITE_COIL_REG; // Command
result[i++] = (byte)(WriteAddr >> 8); // Register Address MSB
result[i++] = (byte)(WriteAddr >> 0); // Register Address LSB
result[i++] = (byte)(1 >> 8); // Count of Register MSB
result[i++] = (byte)(1 >> 0); // Count of Register LSB
result[i++] = (byte)(1 * 1); // Byte Count - [2 * (Num of register)]
result[i++] = (byte)(WriteData >> 0);
crc = GetCRC(result, i);
result[i++] = crc[1]; // CRCH
result[i++] = crc[0]; // CRCL
return result;
}
static public byte[] MakeWriteRegisterData(ushort devId, ushort writeAddr, short[] writeData)
{
if (writeData == null || writeData.Length == 0)
return Array.Empty<byte>();
// 부호 확장 없이 캐스팅 (2s complement 그대로 0..65535 범위로 들어갑니다)
Span<ushort> regs = writeData.Length <= 16
? stackalloc ushort[writeData.Length]
: new ushort[writeData.Length]; // 길면 힙 사용
for (int k = 0; k < writeData.Length; k++)
regs[k] = unchecked((ushort)writeData[k]);
return MakeWriteRegisterData(devId, writeAddr, regs);
}
static private byte[] MakeWriteRegisterData(ushort devId, ushort writeAddr, ReadOnlySpan<ushort> writeData)
{
if (writeData.Length <= 0)
return Array.Empty<byte>();
const byte Func = 0x10; // PRESET_MULTI_REG
int regCount = writeData.Length;
int payloadLen = 7 + regCount * 2; // CRC 제외 길이
byte[] frame = new byte[payloadLen + 2];
int i = 0;
frame[i++] = (byte)devId; // Device ID
frame[i++] = Func; // Function Code (0x10)
frame[i++] = (byte)(writeAddr >> 8); // Addr Hi
frame[i++] = (byte)writeAddr; // Addr Lo
frame[i++] = (byte)(regCount >> 8); // Count Hi
frame[i++] = (byte)regCount; // Count Lo
frame[i++] = (byte)(regCount * 2); // ByteCount
// 데이터: 각 레지스터를 Hi → Lo 바이트로
for (int j = 0; j < regCount; j++)
{
ushort v = writeData[j];
frame[i++] = (byte)(v >> 8);
frame[i++] = (byte)v;
}
// CRC (CRCL → CRCH) 부착
if (!CsCRC16.TryAppendCrcLowHigh(frame, payloadLen, 0))
return Array.Empty<byte>();
return frame;
}
static public byte[] MakeWriteRegisterData(ushort DevID, ushort WriteAddr, short WriteData)
{
byte[] result = new byte[9 + (1 * 2)];
byte[] crc;
ushort i = 0;
result[i++] = (byte)DevID; // Device ID
result[i++] = (byte)PRESET_MULTI_REG; // Command
result[i++] = (byte)(WriteAddr >> 8); // Register Address MSB
result[i++] = (byte)(WriteAddr >> 0); // Register Address LSB
result[i++] = (byte)(1 >> 8); // Count of Register MSB
result[i++] = (byte)(1 >> 0); // Count of Register LSB
result[i++] = (byte)(1 * 2); // Byte Count - [2 * (Num of register)]
result[i++] = (byte)(WriteData >> 8);
result[i++] = (byte)(WriteData >> 0);
crc = GetCRC(result, i);
result[i++] = crc[1]; // CRCH
result[i++] = crc[0]; // CRCL
return result;
}
static public byte[] MakeReadDevIdRegReqData(ushort DevID, ushort cmd, ushort ReadAddr)
{
byte[] result = new byte[7];
byte[] crc;
result[0] = (byte)DevID; // Device ID
result[1] = (byte)cmd; // Command
result[2] = (byte)0x0E; // MEI Type
result[3] = (byte)0x02; // Read Dev Id code
result[4] = (byte)ReadAddr; // Object Id
crc = GetCRC(result, 5);
result[5] = crc[1]; // CRCH
result[6] = crc[0]; // CRCL
return result;
}
static short GetRegister(ushort reg_addr, ref DeviceParamData aParam)
{
short result = 0;
switch (reg_addr)
{
//case 19: result = (short)(0 >> 16); break; // 0021 : UTC TimeStamp MSB
//case 20: result = (short)(58 >> 0); break; // 0022 : UTC TimeStamp LSB
//case 21: result = (short)0x1000; break; // 0023 : Cell Balancing Flag
//case 22: result = (short)0x0000; break; // 0024 : Cell Balancing Voltage
//case 23: result = (short)15; break; // 0024 : Cell Balancing Time
case 0x4002: result = (short)aParam.CellUnderVoltageWarning; break; // 0061 : Low cell voltage warning data
//case 33: result = (short)param.sf1.voltage.CUV_Threshold; break; // 0062 : Low cell voltage protection data
//case 34: result = (short)param.sf1.voltage.CUV_Recovery; break; // 0063 : Low cell voltage recovery data
//case 35: result = (short)param.sf1.voltage.SUV_Warning; break; // 0064 : Low voltage warning data
//case 36: result = (short)param.sf1.voltage.SUV_Threshold; break; // 0065 : Low voltage protection data
//case 37: result = (short)param.sf1.voltage.SUV_Recovery; break; // 0066 : Low voltage recovery data
//case 38: result = (short)param.sf1.voltage.COV_Warning; break; // 0067 : Over cell voltage warning data
//case 39: result = (short)param.sf1.voltage.COV_Threshold; break; // 0068 : Over cell voltage protection data
//case 40: result = (short)param.sf1.voltage.COV_Recovery; break; // 0069 : Over cell voltage recovery data
//case 41: result = (short)param.sf1.voltage.SOV_Warning; break; // 0070 : Over voltage warning data
//case 42: result = (short)param.sf1.voltage.SOV_Threshold; break; // 0071 : Over voltage protection data
//case 43: result = (short)param.sf1.voltage.SOV_Recovery; break; // 0072 : Over voltage recovery data
//case 44: result = (short)param.sf1.temperature.OT_Chg_Warning; break; // 0044 : Charge over temperature warning data
//case 45: result = (short)param.sf1.temperature.OT_Chg_Threshold; break; // 0045 : Charge over temperature protection data
//case 46: result = (short)param.sf1.temperature.OT_Chg_Recovery; break; // 0046 : Charge over temperature recovery data
//case 47: result = (short)param.sf1.temperature.OT_Chg_Time; break; // 0047 : Charge over temperature time
//case 48: result = (short)param.sf1.temperature.OT_Dsg_Warning; break; // 0048 : Discharge over temperature warning data
//case 49: result = (short)param.sf1.temperature.OT_Dsg_Threshold; break; // 0049 : Discharge over temperature protection data
//case 50: result = (short)param.sf1.temperature.OT_Dsg_Recovery; break; // 0050 : Discharge over temperature recovery data
//case 51: result = (short)param.sf1.temperature.OT_Dsg_Time; break; // 0051 : Discharge over temperature time
}
return result;
}
static byte[] ModBusGetRegWordToBytes(ushort addr, ref DeviceParamData aParam)
{
short data;
byte[] result = new byte[2];
data = GetRegister(addr, ref aParam);
result[0] = (byte)(data >> 8);
result[1] = (byte)(data >> 0);
return result;
}
static public byte[] MakeWriteRegisterData(ushort DevID, ushort WriteAddr, ushort reg_len, ref DeviceParamData aParam)
{
int tlen = (reg_len * 2) + 7 + 2;
byte[] result = new byte[tlen];
byte[] tmp;
byte[] crc;
result[0] = (byte)DevID; // Device ID
result[1] = (byte)PRESET_MULTI_REG; // Command
result[2] = (byte)(WriteAddr >> 8); // Register Address MSB
result[3] = (byte)(WriteAddr >> 0); // Register Address LSB
result[4] = (byte)(reg_len >> 8); // Count of Register MSB
result[5] = (byte)(reg_len >> 0); // Count of Register LSB
result[6] = (byte)(reg_len * 2); ; // Current Value MSB
for (int i = 0; i < reg_len; i++)
{
tmp = ModBusGetRegWordToBytes((ushort)(WriteAddr + i), ref aParam);
result[7 + (i * 2) + 0] = tmp[0];
result[7 + (i * 2) + 1] = tmp[1];
}
crc = GetCRC(result, 8);
result[tlen - 2] = crc[0]; // CRCH
result[tlen - 1] = crc[1]; // CRCL
return result;
}
static public byte[] MakeReadWriteRegisterData(ushort DevID, ushort WriteAddr, short WriteData)
{
byte[] result = new byte[15];
byte[] crc;
ushort i = 0;
result[i++] = (byte)DevID; // Device ID
result[i++] = (byte)READ_WRITE_REG; // Command
result[i++] = (byte)(WriteAddr >> 8); // Read Register Address MSB
result[i++] = (byte)(WriteAddr >> 0); // Read Register Address LSB
result[i++] = (byte)(0 >> 8); // Read Count of Register MSB
result[i++] = (byte)(0 >> 0); // Read Count of Register LSB
result[i++] = (byte)(WriteAddr >> 8); // Write Register Address MSB
result[i++] = (byte)(WriteAddr >> 0); // Write Register Address LSB
result[i++] = (byte)(1 >> 8); // Write Count of Register MSB
result[i++] = (byte)(1 >> 0); // Write Count of Register LSB
result[i++] = (byte)(1 * 2); // Byte Count - [2 * (Num of register)]
result[i++] = (byte)(WriteData >> 8);
result[i++] = (byte)(WriteData >> 0);
crc = GetCRC(result, i);
result[i++] = crc[0]; // CRCH
result[i++] = crc[1]; // CRCL
return result;
}
public static byte[] MakeCheckSum(byte[] sData, int offset, int len, bool flag)
{
byte[] result = new byte[2];
int checksum = 0;
for (int i = 0; i < len; i++)
{
checksum += sData[i + offset];
}
checksum = ~checksum + 1;
result[0] = (byte)(checksum >> 8);
result[1] = (byte)checksum;
return result;
}
private static byte[] MakeTxPacket(byte[] sData, int len)
{
string str = "";
byte[] result;
char[] chrArray;
int checksum = 0;
string checksumStr = "";
char[] checksumChr;
str = "~";
for (int i = 0; i < len; i++)
{
str += sData[i].ToString("X2");
}
str += "\r";
chrArray = str.ToCharArray();
for (int i = 0; i < (chrArray.Length - 6); i++)
{
checksum += chrArray[i + 1];
}
checksum = ~checksum + 1;
checksumStr = String.Format("{0:X2}{1:X2}", (byte)(checksum >> 8), (byte)checksum);
checksumChr = checksumStr.ToCharArray();
for (int i = 0; i < 4; i++)
{
chrArray[chrArray.Length - 5 + i] = checksumChr[i];
}
result = new byte[chrArray.Length];
for (int i = 0; i < chrArray.Length; i++)
{
result[i] = (byte)chrArray[i];
}
return result;
}
public static byte[] LengthLchk(int sLen)
{
byte[] result = new byte[2];
int lchksum = 0;
lchksum = (~(((sLen >> 8) & 0xF) +
((sLen >> 4) & 0xF) +
((sLen >> 0) & 0xF)) + 1) % 16;
lchksum = ((lchksum << 12) | sLen);
result[0] = (byte)(lchksum >> 8);
result[1] = (byte)(lchksum >> 0);
return result;
}
public static byte[] MakeTxData(byte addr, byte cmd, int sLen)
{
int buffCh = 0;
byte[] sData;
byte[] lenId;
byte[] checksum;
sData = new byte[((sLen > 0) ? 11 : 10)];
sData[buffCh] = 0x7E; buffCh++; // SOI
sData[buffCh] = 0x25; buffCh++; // VER
sData[buffCh] = addr; buffCh++; // ADDR
sData[buffCh] = 0x46; buffCh++; // CID1
sData[buffCh] = cmd; buffCh++; // CID2 (CMD)
lenId = LengthLchk(sLen); // LENID
sData[buffCh] = lenId[0]; buffCh++; // LENID MSB
sData[buffCh] = lenId[1]; buffCh++; // LENID LSB
if (sLen > 0)
{
sData[buffCh] = (byte)(sLen / 2); buffCh++; // INFO
}
checksum = csSerialCommFunction.MakeCheckSum(sData, 1, sData.Length - 4, false);
sData[buffCh] = checksum[1]; buffCh++;
sData[buffCh] = checksum[0]; buffCh++;
sData[buffCh] = 0x0D; buffCh++; // EOI
return MakeTxPacket(sData, sData.Length);
}
public static int TbPacketCheck(byte[] rdata, int rlen)
{
int result = 0;
byte[] cdata;
byte[] checksum;
byte[] checksum1;
checksum = MakeCheckSum(rdata, 1, rlen - 6, false);
checksum1 = new byte[2];
checksum1[0] = csUtils.StrByte2toByte(rdata[rlen - 4], rdata[rlen - 5]);
checksum1[1] = csUtils.StrByte2toByte(rdata[rlen - 2], rdata[rlen - 3]);
if ((checksum[0] == checksum1[0]) && (checksum[1] == checksum1[1]))
{
cdata = csUtils.StrToByteArray(rdata, 0, rlen);
result = 1;
}
return result;
}
static public int ModbusPacketFromSlaveCheck(byte[] rdata, ushort rlen)
{
int result = 0;
byte[] cdata, crc;
ushort clen, bytecount;
if (rlen > 2)
{
cdata = rdata;
switch (cdata[1])
{
case READ_DEV_ID:
if (rlen < 10) break;
if (rdata[7] == 0) break;
int tmp = 0;
int cPos = 7;
int alen = 0;
for (int i = 0; i < cdata[7]; i++)
{
alen = cdata[cPos + 2];
cPos += alen + 2;
if (rlen < (cPos + 3))
{
tmp = 1;
break;
}
}
if (tmp == 1) break;
crc = GetCRC(cdata, (ushort)(rlen - 2));
if ((crc[1] == cdata[rlen - 2]) && (crc[0] == cdata[rlen - 1])) result = 1;
else result = -1;
break;
case READ_COIL_STATUS:
case READ_HOLDING_REG:
case READ_INPUT_REG:
case READ_WRITE_REG:
bytecount = cdata[2];
clen = (ushort)(bytecount + 5); // header 3, tail 2
if (rlen >= clen)
{
crc = GetCRC(cdata, (ushort)(rlen - 2));
if ((crc[1] == cdata[rlen - 2]) && (crc[0] == cdata[rlen - 1])) result = 1;
else result = -1;
}
break;
case PRESET_MULTI_REG:
case FORCE_SINGLE_COIL:
case PRESET_SINGLE_REG:
clen = 8;
if (rlen >= clen)
{
crc = GetCRC(cdata, (ushort)(rlen - 2));
if ((crc[0] == cdata[rlen - 1]) && (crc[1] == cdata[rlen - 2])) result = 1;
else result = -1;
}
break;
case ERROR_REG:
clen = 6;
if (rlen >= clen)
{
crc = GetCRC(cdata, (ushort)(rlen - 2));
if ((crc[0] == cdata[rlen - 1]) && (crc[1] == cdata[rlen - 2])) result = 1;
else result = -1;
}
break;
case FW_FLASH_ERASE_CMD:
clen = 5;
if (rlen >= clen)
{
crc = GetCRC(cdata, (ushort)(rlen - 2));
if ((crc[0] == cdata[rlen - 1]) && (crc[1] == cdata[rlen - 2])) result = 2;
else result = -1;
}
break;
case FW_FLASH_WRITE_CMD:
clen = 5;
if (rlen >= clen)
{
crc = GetCRC(cdata, (ushort)(rlen - 2));
if ((crc[0] == cdata[rlen - 1]) && (crc[1] == cdata[rlen - 2])) result = 2;
else result = -1;
}
break;
default:
result = -1;
break;
}
}
return result;
}
public static short[] SerialRxProcess(byte[] rData, ushort rRegAddr, ushort rLen, ref CsDeviceData.DeviceModuleData aModuleData)
{
short[] result = new short[2];
switch (rData[1])
{
case READ_INPUT_REG: // 0x04
ReadInputRegisterProcess(rData, rRegAddr, rLen, ref aModuleData);
break;
case READ_WRITE_REG: // 0x17
//ReadSP1RegisterProcess(rData, rRegAddr, rLen, ref rSystemData);
break;
case SPECIAL_REG_02: // 0x19
//ReadInputRegisterProcess(rData, rRegAddr, rLen, ref rSystemData);
break;
case READ_DEV_ID: // 0x2B
ReadDevIdRegisterProcess(rData, rRegAddr, rLen, ref aModuleData);
break;
case PRESET_MULTI_REG:
// read_holding_reg_process(reverse16(rsp->start_addr, true), reverse16(rsp->qty_reg, true));
//result[0] = 1;
//result[1] = 1;
break;
case ERROR_REG:
result[0] = 2;
result[1] = (short)((rData[0] << 8) | rData[1]);
break;
}
return result;
}
private static void ReadCoilRegisterProcess(byte[] rData, ushort rRegAddr, ushort rLen, ref CsDeviceData.DeviceModuleData aModuleData)
{
int i, j;
short reg_count;
short reg_value;
i = 2;
reg_count = rData[i];
i++;
for (j = 0; j < reg_count; j++)
{
reg_value = (short)(rData[i + j]);
SetCoilRegister((short)(rRegAddr + j), reg_value, ref aModuleData);
i++;
}
}
private static void ReadInputRegisterProcess(byte[] rData, ushort rRegAddr, ushort rLen, ref CsDeviceData.DeviceModuleData aModuleData)
{
int i, j;
short reg_count;
short reg_value;
i = 2;
reg_count = (short)(rData[i] / 2); i += 1;
for (j = 0; j < reg_count; j++)
{
reg_value = (short)(rData[i] << 8 | rData[i + 1]);
SetInputRegister((short)(rRegAddr + j), reg_value, ref aModuleData);
i += 2;
}
}
private static void ReadDevIdRegisterProcess(byte[] rData, ushort rRegAddr, ushort rLen, ref CsDeviceData.DeviceModuleData aModuleData)
{
int cPos = 7;
int alen = 0;
int regCount = rData[7];
int oID = 0;
for (int i = 0; i < regCount; i++)
{
oID = rData[cPos + 1];
alen = rData[cPos + 2];
byte[] tmp = new byte[alen];
for (int j = 0; j < alen; j++) { tmp[j] = rData[cPos + 3 + j]; }
switch (oID)
{
case 0x00: aModuleData.Information.VendorName = Encoding.ASCII.GetString(tmp).Trim('\0'); break;
case 0x01: aModuleData.Information.ProductCode = Encoding.ASCII.GetString(tmp).Trim('\0'); break;
case 0x02: aModuleData.Information.MajorMinorRev = Encoding.ASCII.GetString(tmp).Trim('\0'); break;
case 0x05: aModuleData.Information.ModelName = Encoding.ASCII.GetString(tmp).Trim('\0'); break;
case 0x82: aModuleData.Information.HwSerialNumber = Encoding.ASCII.GetString(tmp).Trim('\0'); break;
case 0x83: aModuleData.Information.HwProductRev = Encoding.ASCII.GetString(tmp).Trim('\0'); break;
case 0x84: aModuleData.Information.ManufacturingDate = Encoding.ASCII.GetString(tmp).Trim('\0'); break;
case 0x86: aModuleData.Information.SwProductRev = Encoding.ASCII.GetString(tmp).Trim('\0'); break;
}
cPos += alen + 2;
if (rLen < (cPos + 3))
{
break;
}
}
}
private static void ReadSP2RegisterProcess(byte[] rData, ushort rRegAddr, ushort rLen, ref DeviceSystemData rSystemData)
{
int i, j;
short reg_count;
short reg_value;
i = 2;
reg_count = (short)(rData[i] / 2); i += 1;
for (j = 0; j < reg_count; j++)
{
reg_value = (short)(rData[i] << 8 | rData[i + 1]);
SetSP2Register((short)(rRegAddr + j), reg_value, ref rSystemData);
i += 2;
}
}
private static void ReadSP1RegisterProcess(byte[] rData, ushort rRegAddr, ushort rLen, ref DeviceSystemData rSystemData)
{
int i, j;
short reg_count;
short reg_value;
i = 2;
reg_count = (short)(rData[i] / 2); i += 1;
for (j = 0; j < reg_count; j++)
{
reg_value = (short)(rData[i] << 8 | rData[i + 1]);
SetSP1Register((short)(rRegAddr + j), reg_value, ref rSystemData);
i += 2;
}
}
private static readonly int CURRENT_OFFSET = 10000;
private static readonly int TEMP_OFFSET = 400;
private static short MakeWarningData_AMG(short reg_value)
{
byte[] reg_byte = new byte[2];
ushort result = 0;
reg_byte[1] = (byte)(reg_value >> 8);
reg_byte[0] = (byte)(reg_value >> 0);
if (((reg_byte[0] >> 0) & 0x01) == 0x01) result |= (ushort)(1 << 4); // Cell Over Voltage
if (((reg_byte[0] >> 1) & 0x01) == 0x01) result |= (ushort)(1 << 5); // Cell Under Voltage
if (((reg_byte[0] >> 2) & 0x01) == 0x01) result |= (ushort)(1 << 2); // Pack Over Voltage
if (((reg_byte[0] >> 3) & 0x01) == 0x01) result |= (ushort)(1 << 3); // Pack Under Voltage
if (((reg_byte[0] >> 4) & 0x01) == 0x01) result |= (ushort)(1 << 6); // Charge Over Current
if (((reg_byte[0] >> 5) & 0x01) == 0x01) result |= (ushort)(1 << 7); // Discharge Over Current
if (((reg_byte[0] >> 6) & 0x01) == 0x01) result |= (ushort)(1 << 14); // ENV Over Temperature
if (((reg_byte[0] >> 7) & 0x01) == 0x01) result |= (ushort)(1 << 15); // ENV Under Temperature
if (((reg_byte[1] >> 0) & 0x01) == 0x01) result |= (ushort)(1 << 0); // Chg Over Temperature
if (((reg_byte[1] >> 1) & 0x01) == 0x01) result |= (ushort)(1 << 1); // Chg Under Temperature
if (((reg_byte[1] >> 2) & 0x01) == 0x01) result |= (ushort)(1 << 0); // Dch Over Temperature
if (((reg_byte[1] >> 3) & 0x01) == 0x01) result |= (ushort)(1 << 1); // Dch Under Temperature
if (((reg_byte[1] >> 4) & 0x01) == 0x01) result |= (ushort)(1 << 11); // SOC Low Alarm
if (((reg_byte[1] >> 5) & 0x01) == 0x01) result |= (ushort)(1 << 9); // Diff Voltage Alarm
if (((reg_byte[1] >> 6) & 0x01) == 0x01) result |= (ushort)(1 << 13); // CB On/OFF (1: OFF, 0: ON)
if (((reg_byte[1] >> 7) & 0x01) == 0x01) result |= (ushort)(1 << 12); // reserved
return (short)result;
}
private static short MakeProtectData_AMG(short reg_value)
{
byte[] reg_byte = new byte[2];
ushort result = 0;
reg_byte[1] = (byte)(reg_value >> 8);
reg_byte[0] = (byte)(reg_value >> 0);
if (((reg_byte[0] >> 0) & 0x01) == 0x01) result |= (ushort)(1 << 4); // Cell Over Voltage
if (((reg_byte[0] >> 1) & 0x01) == 0x01) result |= (ushort)(1 << 2); // Pack Over Voltage
if (((reg_byte[0] >> 2) & 0x01) == 0x01) result |= (ushort)(1 << 5); // Cell Under Voltage
if (((reg_byte[0] >> 3) & 0x01) == 0x01) result |= (ushort)(1 << 3); // Pack Under Voltage
if (((reg_byte[0] >> 4) & 0x01) == 0x01) result |= (ushort)(1 << 6); // Cha Over Current 1
if (((reg_byte[0] >> 5) & 0x01) == 0x01) result |= (ushort)(1 << 6); // Cha Over Current 2
if (((reg_byte[0] >> 6) & 0x01) == 0x01) result |= (ushort)(1 << 7); // Dch Over Current 1
if (((reg_byte[0] >> 7) & 0x01) == 0x01) result |= (ushort)(1 << 7); // Dch Over Current 2
if (((reg_byte[1] >> 0) & 0x01) == 0x01) result |= (ushort)(1 << 8); // SC Protect / CB off
if (((reg_byte[1] >> 1) & 0x01) == 0x01) result |= (ushort)(1 << 0); // Chg Over Temperature
if (((reg_byte[1] >> 2) & 0x01) == 0x01) result |= (ushort)(1 << 1); // Chg Under Temperature
if (((reg_byte[1] >> 3) & 0x01) == 0x01) result |= (ushort)(1 << 0); // Dch Over Temperature
if (((reg_byte[1] >> 4) & 0x01) == 0x01) result |= (ushort)(1 << 1); // Dch Under Temperature
return (short)result;
}
private static void MakeAlarm(ref CsDeviceData.DeviceModuleData mData)
{
if (((mData.StatusData.faultstatus >> 14) & 0x0001) == 0x0001)
{
mData.StatusData.batteryStatus = 4; // Anti-theft Gyroscope
}
else if (((mData.StatusData.faultstatus >> 15) & 0x0001) == 0x0001)
{
mData.StatusData.batteryStatus = 5; // Anti-theft Comm.
}
else if (mData.StatusData.protect != 0x0000)
{
mData.StatusData.batteryStatus = 2;
}
else if (mData.StatusData.warning != 0x0000)
{
mData.StatusData.batteryStatus = 1;
}
else
{
mData.StatusData.batteryStatus = 0;
}
}
private static void SetInputRegister(short reg_addr, short reg_value, ref CsDeviceData.DeviceModuleData aModuleData)
{
switch (reg_addr)
{
case 0x0FFF:
aModuleData.ValueData.voltage = (short)(reg_value / 10);
aModuleData.active = true;
break; // 48.00V = 4800
case 0x1000: aModuleData.ValueData.current = (short)(reg_value - CURRENT_OFFSET); break; // 100.0A = 1000 -10000 = 0;
case 0x1001: aModuleData.ValueData.remainingCapacity = (short)(reg_value / 1); break; // 100.0Ah = 1000
case 0x1002: aModuleData.ValueData.MosTemperature = (short)(reg_value - TEMP_OFFSET); break; // 10.0C = 100
case 0x1003: aModuleData.ValueData.AmbTemperature = (short)(reg_value - TEMP_OFFSET); break; // 10.0C = 100
case 0x1004: aModuleData.StatusData.warning = (ushort)CsAlarmDefine.DevWarningToGui(reg_value); break; // Warning Status
case 0x1005: aModuleData.StatusData.protect = (ushort)CsAlarmDefine.DevProtectToGui(reg_value); break; // Protection Status
case 0x1006: // Fault Status
aModuleData.StatusData.faultstatus = (ushort)(reg_value / 1);
aModuleData.StatusData.status = (ushort)((reg_value >> 8) & 0x00FF);
MakeAlarm(ref aModuleData);
break; // Fault Status
case 0x1007: aModuleData.ValueData.SOC = (short)(reg_value / 10); break; // 100.00% = 10000
case 0x1008: aModuleData.ValueData.SOH = (short)(reg_value / 10); break; // 100.00% = 10000
case 0x1009: aModuleData.ValueData.fullChgCapacity_Ah = (ushort)(reg_value / 1); break; // 100.0Ah = 1000
case 0x100A: aModuleData.ValueData.cycleCount = (ushort)(reg_value / 1); break; // 100 cycles = 100
case 0x100B: aModuleData.ValueData.NumOfCells = (short)(reg_value / 1); break; // 15 cells = 15
case 0x100C:
case 0x100D:
case 0x100E:
case 0x100F:
case 0x1010:
case 0x1011:
case 0x1012:
case 0x1013:
case 0x1014:
case 0x1015:
case 0x1016:
case 0x1017:
case 0x1018:
case 0x1019:
case 0x101A:
case 0x101B: // 3.256V = 3256
int cNo = reg_addr - 0x100C;
if (cNo < 15)
{ aModuleData.ValueData.CellVoltage[cNo] = (ushort)(reg_value / 1); }
MakeMaxAvgMinCellVoltage(ref aModuleData);
break; // 100.00% = 10000
case 0x101C: aModuleData.ValueData.NumOfTemps = (short)(reg_value / 1); break; // 5 temps = 5
case 0x101D:
case 0x101E:
case 0x101F:
case 0x1020: // 25.3C = 253 - 400 = -147 (Offset -400)
int tNo = reg_addr - 0x101D;
aModuleData.ValueData.CellTemperature[tNo] = (short)(reg_value - TEMP_OFFSET);
MakeMaxAvgMinTemperature(ref aModuleData);
break; // 100.00% = 10000
case 0x1021: aModuleData.MaxValue.MaxChgCurrent = (short)(reg_value); break; // Max. Charge Current
case 0x1022: aModuleData.MaxValue.MaxChgTemperature = (short)(reg_value - TEMP_OFFSET); break; // Max. Charge Temperature
case 0x1023: aModuleData.MaxValue.MinChgTemperature = (short)(reg_value - TEMP_OFFSET); break; // Min. Charge Temperature
case 0x1024: aModuleData.MaxValue.FloatChgVolt = (short)(reg_value / 10); break; // Float Charge Current
case 0x1025: aModuleData.MaxValue.BoostChgVolt = (short)(reg_value / 10); break; // Boost Charge Current
case 0x3000: aModuleData.CalibrationData.AntiTheftComm.TimeOut = (short)(reg_value / 1); break;
case 0x3002: aModuleData.CalibrationData.AntiTheftComm.FuncSwitch = (short)(reg_value / 1); break;
case 0x4000: aModuleData.CalibrationData.AntiTheftGyro.XAxis = (short)(reg_value / 1); break;
case 0x4001: aModuleData.CalibrationData.AntiTheftGyro.YAxis = (short)(reg_value / 1); break;
case 0x4002: aModuleData.CalibrationData.AntiTheftGyro.ZAxis = (short)(reg_value / 1); break;
case 0x4003: aModuleData.CalibrationData.AntiTheftGyro.GyroPolicySel = (short)(reg_value / 1); break;
case 0x4004: aModuleData.CalibrationData.AntiTheftGyro.GyroFuncSwitch = (short)(reg_value / 1); break;
case 0x4006: aModuleData.CalibrationData.AntiTheftGyro.GyroState = (short)(reg_value / 1); break;
default:
break;
}
}
private static void SetSP1Register(short reg_addr, short reg_value, ref DeviceSystemData rSystemData)
{
switch (reg_addr)
{
case 0x4000: rSystemData.GyroValue.X_axis = (short)(reg_value); break; //
case 0x4001: rSystemData.GyroValue.Y_axis = (short)(reg_value); break; //
case 0x4002: rSystemData.GyroValue.Z_axis = (short)(reg_value); break; //
case 0x4003: rSystemData.GyroValue.Gyro_policy_sel = (short)(reg_value); break; //
case 0x4004: rSystemData.GyroValue.Gyro_func_sw = (short)(reg_value); break; //
case 0x4006: rSystemData.GyroValue.Gyro_state = (short)(reg_value); break; //
default:
break;
}
}
private static void SetSP2Register(short reg_addr, short reg_value, ref DeviceSystemData rSystemData)
{
switch (reg_addr)
{
case 0x3000: rSystemData.GyroValue.X_axis = (short)(reg_value); break; //
case 0x3002: rSystemData.GyroValue.Y_axis = (short)(reg_value); break; //
default:
break;
}
}
private static void SetReadIdRegister(short reg_addr, short reg_value, ref DeviceSystemData rSystemData)
{
switch (reg_addr)
{
case 0x4000: rSystemData.GyroValue.X_axis = (short)(reg_value); break; //
case 0x4001: rSystemData.GyroValue.Y_axis = (short)(reg_value); break; //
case 0x4002: rSystemData.GyroValue.Z_axis = (short)(reg_value); break; //
case 0x4003: rSystemData.GyroValue.Gyro_policy_sel = (short)(reg_value); break; //
case 0x4004: rSystemData.GyroValue.Gyro_func_sw = (short)(reg_value); break; //
case 0x4006: rSystemData.GyroValue.Gyro_state = (short)(reg_value); break; //
default:
break;
}
}
private static void SetCoilRegister(short reg_addr, short reg_value, ref CsDeviceData.DeviceModuleData mData)
{
switch (reg_addr)
{
case 0x3078:
mData.StatusData.relayStatus = (ushort)reg_value;
mData.CalibrationData.FetCalib.FetStatus = reg_value;
break;
case 0x502E:
mData.CalibrationData.Current.ChargeOption = reg_value;
break;
}
}
private static void MakeMaxAvgMinCellVoltage(ref CsDeviceData.DeviceModuleData mData)
{
int Max, Avg, Min, Sum;
int MaxNo, MinNo;
Max = Avg = Min = Sum = 0;
MaxNo = MinNo = 0;
for (int i = 0; i < mData.cellQty; i++)
{
if (i == 0)
{
Max = Min = mData.ValueData.CellVoltage[i];
}
Sum += mData.ValueData.CellVoltage[i];
if (Max < mData.ValueData.CellVoltage[i])
{
Max = mData.ValueData.CellVoltage[i];
MaxNo = i;
}
if (Min > mData.ValueData.CellVoltage[i])
{
Min = mData.ValueData.CellVoltage[i];
MinNo = i;
}
}
Avg = Sum / mData.cellQty;
mData.AvgData.avgCellVoltage = (short)Avg;
mData.AvgData.maxCellVoltage = (short)Max;
mData.AvgData.maxCellNum = (short)(MaxNo + 1);
mData.AvgData.minCellVoltage = (short)Min;
mData.AvgData.minCellNum = (short)(MinNo + 1);
mData.AvgData.diffCellVoltage = (short)(Max - Min);
}
private static void MakeMaxAvgMinTemperature(ref CsDeviceData.DeviceModuleData mData)
{
int Max, Avg, Min, Sum;
int MaxNo, MinNo;
Max = Avg = Min = Sum = 0;
MaxNo = MinNo = 0;
for (int i = 0; i < mData.tempQty; i++)
{
if (i == 0)
{
Max = Min = mData.ValueData.CellTemperature[i];
}
Sum += mData.ValueData.CellTemperature[i];
if (Max < mData.ValueData.CellTemperature[i])
{
Max = mData.ValueData.CellTemperature[i];
MaxNo = i;
}
if (Min > mData.ValueData.CellTemperature[i])
{
Min = mData.ValueData.CellTemperature[i];
MinNo = i;
}
}
Avg = Sum / mData.tempQty;
mData.AvgData.avgTemp = (short)Avg;
mData.AvgData.maxTemp = (short)Max;
mData.AvgData.maxTempNum = (short)(MaxNo + 1);
mData.AvgData.minTemp = (short)Min;
mData.AvgData.minTempNum = (short)(MinNo + 1);
mData.AvgData.diffTemp = (short)(Max - Min);
}
private static short MakeUartWarningData(short rdata)
{
short result = 0;
bool[] bAlarm = csUtils.Int16ToBitArray(rdata);
if (bAlarm[0] == true) result |= (short)(1 << 2); // 0x0001Pack OV
if (bAlarm[1] == true) result |= (short)(1 << 4); // 0x0002Cell OV
if (bAlarm[2] == true) result |= (short)(1 << 3); // 0x0004Pack UV
if (bAlarm[3] == true) result |= (short)(1 << 5); // 0x0008Cell UV
if (bAlarm[4] == true) result |= (short)(1 << 6); // 0x0010Charging OC
if (bAlarm[5] == true) result |= (short)(1 << 7); // 0x0020Discharging OC
if (bAlarm[8] == true) result |= (short)(1 << 0); // 0x0080: Charging Over Tempratuer
if (bAlarm[9] == true) result |= (short)(1 << 0); // 0x0080: Discharging Over Tempratuer
if (bAlarm[10] == true) result |= (short)(1 << 1); // 0x0040: Charging Under Tempratuer
if (bAlarm[11] == true) result |= (short)(1 << 1); // 0x0040: Discharging Under Tempratuer
if (bAlarm[12] == true) result |= (short)(1 << 11); // 0x0200SOC Low
return result;
}
private static short MakeUartTripData(short rdata)
{
short result = 0;
bool[] bAlarm = csUtils.Int16ToBitArray(rdata);
if (bAlarm[0] == true) result |= (short)(1 << 2); // 0x0001Pack OV
if (bAlarm[1] == true) result |= (short)(1 << 4); // 0x0002Cell OV
if (bAlarm[2] == true) result |= (short)(1 << 3); // 0x0004Pack UV
if (bAlarm[3] == true) result |= (short)(1 << 5); // 0x0008Cell UV
if (bAlarm[4] == true) result |= (short)(1 << 6); // 0x0010Charging OC
if (bAlarm[5] == true) result |= (short)(1 << 7); // 0x0020Discharging OC
if (bAlarm[8] == true) result |= (short)(1 << 0); // 0x0080: Charging Over Temprature
if (bAlarm[9] == true) result |= (short)(1 << 0); // 0x0080: Discharging Over Temprature
if (bAlarm[10] == true) result |= (short)(1 << 1); // 0x0040: Charging Under Temprature
if (bAlarm[11] == true) result |= (short)(1 << 1); // 0x0040: Discharging Under Temprature
if (bAlarm[13] == true) result |= (short)(1 << 9); // 0x0200Short Circuit Protection
return result;
}
private static short MakeUartErrorData(short rdata, short cdata)
{
short result = cdata;
bool[] bAlarm = csUtils.Int16ToBitArray(rdata);
if (bAlarm[0] == true) result |= (short)(1 << 9); // 0x0001Voltage error
if (bAlarm[1] == true) result |= (short)(1 << 9); // 0x0002Temperature error
if (bAlarm[2] == true) result |= (short)(1 << 9); // 0x0004: 电流检测Error
if (bAlarm[3] == true) result |= (short)(1 << 9); // 0x0010Cell unbalance
return result;
}
}
}