Delete the unecessary relay lib
This commit is contained in:
parent
5265a332cf
commit
1a47c8884d
|
|
@ -1,211 +0,0 @@
|
||||||
using System.Reflection.Metadata;
|
|
||||||
|
|
||||||
namespace InnovEnergy.App.SodiStoreMax.SaliMaxRelays;
|
|
||||||
#pragma warning disable CS8602 // Dereference of a possibly null reference.
|
|
||||||
|
|
||||||
public class CombinedAdamRelaysRecord : IRelaysRecord
|
|
||||||
{
|
|
||||||
private const UInt16 SlowFreq = 3000;
|
|
||||||
private const UInt16 HighFreq = 1000;
|
|
||||||
|
|
||||||
public CombinedAdamRelaysRecord(RelaysRecordAdam6060? relaysRecordAdam6060, RelaysRecordAdam6360D? relaysRecordAdam6360D)
|
|
||||||
{
|
|
||||||
_recordAdam6060 = relaysRecordAdam6060;
|
|
||||||
_recordAdam6360D = relaysRecordAdam6360D;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static RelaysRecordAdam6060? _recordAdam6060;
|
|
||||||
private static RelaysRecordAdam6360D? _recordAdam6360D;
|
|
||||||
|
|
||||||
public static IRelaysRecord Instance { get; } = new CombinedAdamRelaysRecord(_recordAdam6060, _recordAdam6360D);
|
|
||||||
|
|
||||||
|
|
||||||
public Boolean K1GridBusIsConnectedToGrid => _recordAdam6360D.K1GridBusIsConnectedToGrid;
|
|
||||||
|
|
||||||
public Boolean K2IslandBusIsConnectedToGridBus => _recordAdam6360D.K2IslandBusIsConnectedToGridBus;
|
|
||||||
public Boolean FiWarning => _recordAdam6360D.FiWarning;
|
|
||||||
public Boolean FiError => _recordAdam6360D.FiError;
|
|
||||||
public Boolean K2ConnectIslandBusToGridBus
|
|
||||||
{
|
|
||||||
get => _recordAdam6360D.K2ConnectIslandBusToGridBus;
|
|
||||||
set => _recordAdam6360D.K2ConnectIslandBusToGridBus = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Boolean Inverter1WagoStatus => _recordAdam6360D.Inverter1WagoStatus;
|
|
||||||
public Boolean Inverter2WagoStatus => _recordAdam6360D.Inverter2WagoStatus;
|
|
||||||
public Boolean Inverter3WagoStatus => _recordAdam6360D.Inverter3WagoStatus;
|
|
||||||
public Boolean Inverter4WagoStatus => _recordAdam6360D.Inverter4WagoStatus;
|
|
||||||
|
|
||||||
public Boolean Dc1WagoStatus => _recordAdam6060.Dc1WagoStatus;
|
|
||||||
public Boolean Dc2WagoStatus => _recordAdam6060.Dc2WagoStatus;
|
|
||||||
public Boolean Dc3WagoStatus => _recordAdam6060.Dc3WagoStatus;
|
|
||||||
public Boolean Dc4WagoStatus => _recordAdam6060.Dc4WagoStatus;
|
|
||||||
public Boolean DcSystemControlWagoStatus => _recordAdam6060.DcSystemControlWagoStatus;
|
|
||||||
|
|
||||||
public Boolean LedGreen { get => _recordAdam6360D.LedGreen; set => _recordAdam6360D.LedGreen = value;}
|
|
||||||
public Boolean LedRed { get => _recordAdam6360D.LedRed; set => _recordAdam6360D.LedRed = value;}
|
|
||||||
public Boolean Harvester1Step => _recordAdam6360D.Harvester1Step;
|
|
||||||
public Boolean Harvester2Step => _recordAdam6360D.Harvester2Step;
|
|
||||||
public Boolean Harvester3Step => _recordAdam6360D.Harvester3Step;
|
|
||||||
public Boolean Harvester4Step => _recordAdam6360D.Harvester4Step;
|
|
||||||
|
|
||||||
public UInt16 DigitalOutput0Mode { get => _recordAdam6360D.DigitalOutput0Mode; set => _recordAdam6360D.DigitalOutput0Mode = value; }
|
|
||||||
|
|
||||||
public UInt16 DigitalOutput1Mode
|
|
||||||
{
|
|
||||||
get => _recordAdam6360D.DigitalOutput1Mode;
|
|
||||||
set => _recordAdam6360D.DigitalOutput1Mode = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public UInt16 DigitalOutput2Mode
|
|
||||||
{
|
|
||||||
get => _recordAdam6360D.DigitalOutput2Mode;
|
|
||||||
set => _recordAdam6360D.DigitalOutput2Mode = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public UInt16 DigitalOutput3Mode
|
|
||||||
{
|
|
||||||
get => _recordAdam6360D.DigitalOutput3Mode;
|
|
||||||
set => _recordAdam6360D.DigitalOutput3Mode = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public UInt16 DigitalOutput4Mode
|
|
||||||
{
|
|
||||||
get => _recordAdam6360D.DigitalOutput4Mode;
|
|
||||||
set => _recordAdam6360D.DigitalOutput4Mode = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public UInt16 DigitalOutput5Mode
|
|
||||||
{
|
|
||||||
get => _recordAdam6360D.DigitalOutput5Mode;
|
|
||||||
set => _recordAdam6360D.DigitalOutput5Mode = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Boolean Do0StartPulse { get => _recordAdam6360D.Do0Pulse; set => _recordAdam6360D.Do0Pulse = value; }
|
|
||||||
public Boolean Do1StartPulse { get => _recordAdam6360D.Do1Pulse; set => _recordAdam6360D.Do1Pulse = value; }
|
|
||||||
public Boolean Do2StartPulse { get => _recordAdam6360D.Do2Pulse; set => _recordAdam6360D.Do2Pulse = value; }
|
|
||||||
public Boolean Do3StartPulse { get => _recordAdam6360D.Do3Pulse; set => _recordAdam6360D.Do3Pulse = value; }
|
|
||||||
public Boolean Do4StartPulse { get => _recordAdam6360D.Do4Pulse; set => _recordAdam6360D.Do4Pulse = value; }
|
|
||||||
public Boolean Do5StartPulse { get => _recordAdam6360D.Do5Pulse; set => _recordAdam6360D.Do5Pulse = value; }
|
|
||||||
|
|
||||||
|
|
||||||
public UInt16 PulseOut0LowTime { get => _recordAdam6360D.PulseOut0LowTime; set => _recordAdam6360D.PulseOut0LowTime = value; }
|
|
||||||
public UInt16 PulseOut1LowTime { get => _recordAdam6360D.PulseOut1LowTime; set => _recordAdam6360D.PulseOut1LowTime = value; }
|
|
||||||
public UInt16 PulseOut2LowTime { get => _recordAdam6360D.PulseOut2LowTime; set => _recordAdam6360D.PulseOut2LowTime = value; }
|
|
||||||
public UInt16 PulseOut3LowTime { get => _recordAdam6360D.PulseOut3LowTime; set => _recordAdam6360D.PulseOut3LowTime = value; }
|
|
||||||
public UInt16 PulseOut4LowTime { get => _recordAdam6360D.PulseOut4LowTime; set => _recordAdam6360D.PulseOut4LowTime = value; }
|
|
||||||
public UInt16 PulseOut5LowTime { get => _recordAdam6360D.PulseOut5LowTime; set => _recordAdam6360D.PulseOut5LowTime = value; }
|
|
||||||
|
|
||||||
public UInt16 PulseOut0HighTime { get => _recordAdam6360D.PulseOut0HighTime; set => _recordAdam6360D.PulseOut0HighTime = value; }
|
|
||||||
public UInt16 PulseOut1HighTime { get => _recordAdam6360D.PulseOut1HighTime; set => _recordAdam6360D.PulseOut1HighTime = value; }
|
|
||||||
public UInt16 PulseOut2HighTime { get => _recordAdam6360D.PulseOut2HighTime; set => _recordAdam6360D.PulseOut2HighTime = value; }
|
|
||||||
public UInt16 PulseOut3HighTime { get => _recordAdam6360D.PulseOut3HighTime; set => _recordAdam6360D.PulseOut3HighTime = value; }
|
|
||||||
public UInt16 PulseOut4HighTime { get => _recordAdam6360D.PulseOut4HighTime; set => _recordAdam6360D.PulseOut4HighTime = value; }
|
|
||||||
public UInt16 PulseOut5HighTime { get => _recordAdam6360D.PulseOut5HighTime; set => _recordAdam6360D.PulseOut5HighTime = value; }
|
|
||||||
|
|
||||||
/**************************** Green LED *********************************/
|
|
||||||
|
|
||||||
public void PerformSolidGreenLed()
|
|
||||||
{
|
|
||||||
DigitalOutput0Mode = 0;
|
|
||||||
DigitalOutput1Mode = 0;
|
|
||||||
LedGreen = true;
|
|
||||||
LedRed = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void PerformSlowFlashingGreenLed()
|
|
||||||
{
|
|
||||||
PulseOut0HighTime = SlowFreq;
|
|
||||||
PulseOut0LowTime = SlowFreq;
|
|
||||||
DigitalOutput0Mode = 2;
|
|
||||||
Do0StartPulse = true;
|
|
||||||
Do1StartPulse = false; // make sure the red LED is off
|
|
||||||
|
|
||||||
Console.WriteLine("Green Slow Flashing Starting");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void PerformFastFlashingGreenLed()
|
|
||||||
{
|
|
||||||
PulseOut0HighTime = HighFreq;
|
|
||||||
PulseOut0LowTime = HighFreq;
|
|
||||||
DigitalOutput0Mode = 2;
|
|
||||||
Do0StartPulse = true;
|
|
||||||
Do1StartPulse = false;// make sure the red LED is off
|
|
||||||
|
|
||||||
Console.WriteLine("Green Slow Flashing Starting");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**************************** Orange LED *********************************/
|
|
||||||
|
|
||||||
public void PerformSolidOrangeLed()
|
|
||||||
{
|
|
||||||
DigitalOutput0Mode = 0;
|
|
||||||
DigitalOutput1Mode = 0;
|
|
||||||
LedGreen = true;
|
|
||||||
LedRed = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void PerformSlowFlashingOrangeLed()
|
|
||||||
{
|
|
||||||
PerformSlowFlashingGreenLed();
|
|
||||||
PerformSlowFlashingRedLed();
|
|
||||||
Do0StartPulse = true;
|
|
||||||
Do1StartPulse = true;
|
|
||||||
|
|
||||||
Console.WriteLine("Orange Slow Flashing Starting");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void PerformFastFlashingOrangeLed()
|
|
||||||
{
|
|
||||||
PerformFastFlashingGreenLed();
|
|
||||||
PerformFastFlashingRedLed();
|
|
||||||
Do0StartPulse = true;
|
|
||||||
Do1StartPulse = true;
|
|
||||||
Console.WriteLine("Orange Fast Flashing Starting");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**************************** RED LED *********************************/
|
|
||||||
|
|
||||||
public void PerformSolidRedLed()
|
|
||||||
{
|
|
||||||
DigitalOutput0Mode = 0;
|
|
||||||
DigitalOutput1Mode = 0;
|
|
||||||
LedGreen = false;
|
|
||||||
LedRed = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void PerformSlowFlashingRedLed()
|
|
||||||
{
|
|
||||||
PulseOut1HighTime = SlowFreq;
|
|
||||||
PulseOut1LowTime = SlowFreq;
|
|
||||||
DigitalOutput1Mode = 2;
|
|
||||||
Do0StartPulse = false; // make sure the green LED is off
|
|
||||||
Do1StartPulse = true;
|
|
||||||
|
|
||||||
Console.WriteLine("Red Slow Flashing Starting");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void PerformFastFlashingRedLed()
|
|
||||||
{
|
|
||||||
PulseOut1HighTime = HighFreq;
|
|
||||||
PulseOut1LowTime = HighFreq;
|
|
||||||
DigitalOutput1Mode = 2;
|
|
||||||
Do0StartPulse = false; // make sure the green LED is off
|
|
||||||
Do1StartPulse = true;
|
|
||||||
|
|
||||||
Console.WriteLine("Red Fast Flashing Starting");
|
|
||||||
}
|
|
||||||
|
|
||||||
public RelaysRecordAdam6360D? GetAdam6360DRecord()
|
|
||||||
{
|
|
||||||
return _recordAdam6360D;
|
|
||||||
}
|
|
||||||
|
|
||||||
public RelaysRecordAdam6060? GetAdam6060Record()
|
|
||||||
{
|
|
||||||
return _recordAdam6060;
|
|
||||||
}
|
|
||||||
|
|
||||||
public IEnumerable<Boolean> K3InverterIsConnectedToIslandBus => _recordAdam6360D.K3InverterIsConnectedToIslandBus;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,78 +0,0 @@
|
||||||
namespace InnovEnergy.App.SodiStoreMax.SaliMaxRelays;
|
|
||||||
|
|
||||||
|
|
||||||
public interface IRelaysRecord
|
|
||||||
{
|
|
||||||
Boolean K1GridBusIsConnectedToGrid { get; }
|
|
||||||
Boolean K2IslandBusIsConnectedToGridBus { get; }
|
|
||||||
IEnumerable<Boolean> K3InverterIsConnectedToIslandBus { get; }
|
|
||||||
Boolean FiWarning { get; }
|
|
||||||
Boolean FiError { get; }
|
|
||||||
Boolean K2ConnectIslandBusToGridBus { get; set; }
|
|
||||||
|
|
||||||
// Boolean Inverter1WagoRelay { get; set; } // to add in the future
|
|
||||||
// Boolean Inverter2WagoRelay { get; set; } // to add in the future
|
|
||||||
// Boolean Inverter3WagoRelay { get; set; } // to add in the future
|
|
||||||
// Boolean Inverter4WagoRelay { get; set; } // to add in the future
|
|
||||||
|
|
||||||
Boolean Inverter1WagoStatus { get; }
|
|
||||||
Boolean Inverter2WagoStatus { get; }
|
|
||||||
Boolean Inverter3WagoStatus { get; }
|
|
||||||
Boolean Inverter4WagoStatus { get; }
|
|
||||||
|
|
||||||
Boolean Dc1WagoStatus { get; } // to test
|
|
||||||
Boolean Dc2WagoStatus { get; } // to test
|
|
||||||
Boolean Dc3WagoStatus { get; } // to test
|
|
||||||
Boolean Dc4WagoStatus { get; } // to test
|
|
||||||
|
|
||||||
Boolean DcSystemControlWagoStatus { get; } // to test
|
|
||||||
|
|
||||||
Boolean LedGreen { get; set; }
|
|
||||||
Boolean LedRed { get; }
|
|
||||||
Boolean Harvester1Step { get; }
|
|
||||||
Boolean Harvester2Step { get; }
|
|
||||||
Boolean Harvester3Step { get; }
|
|
||||||
Boolean Harvester4Step { get; }
|
|
||||||
|
|
||||||
Boolean Do0StartPulse { get; set; }
|
|
||||||
Boolean Do1StartPulse { get; set; }
|
|
||||||
Boolean Do2StartPulse { get; set; }
|
|
||||||
Boolean Do3StartPulse { get; set; }
|
|
||||||
Boolean Do4StartPulse { get; set; }
|
|
||||||
Boolean Do5StartPulse { get; set; }
|
|
||||||
|
|
||||||
UInt16 DigitalOutput0Mode { get; set; }
|
|
||||||
UInt16 DigitalOutput1Mode { get; set; }
|
|
||||||
UInt16 DigitalOutput2Mode { get; set; }
|
|
||||||
UInt16 DigitalOutput3Mode { get; set; }
|
|
||||||
UInt16 DigitalOutput4Mode { get; set; }
|
|
||||||
UInt16 DigitalOutput5Mode { get; set; }
|
|
||||||
|
|
||||||
UInt16 PulseOut0LowTime { get; set; }
|
|
||||||
UInt16 PulseOut1LowTime { get; set; }
|
|
||||||
UInt16 PulseOut2LowTime { get; set; }
|
|
||||||
UInt16 PulseOut3LowTime { get; set; }
|
|
||||||
UInt16 PulseOut4LowTime { get; set; }
|
|
||||||
UInt16 PulseOut5LowTime { get; set; }
|
|
||||||
|
|
||||||
UInt16 PulseOut0HighTime { get; set; }
|
|
||||||
UInt16 PulseOut1HighTime { get; set; }
|
|
||||||
UInt16 PulseOut2HighTime { get; set; }
|
|
||||||
UInt16 PulseOut3HighTime { get; set; }
|
|
||||||
UInt16 PulseOut4HighTime { get; set; }
|
|
||||||
UInt16 PulseOut5HighTime { get; set; }
|
|
||||||
|
|
||||||
void PerformSolidGreenLed();
|
|
||||||
void PerformSlowFlashingGreenLed();
|
|
||||||
void PerformFastFlashingGreenLed();
|
|
||||||
|
|
||||||
|
|
||||||
void PerformSolidOrangeLed();
|
|
||||||
void PerformSlowFlashingOrangeLed();
|
|
||||||
void PerformFastFlashingOrangeLed();
|
|
||||||
|
|
||||||
void PerformSolidRedLed();
|
|
||||||
void PerformSlowFlashingRedLed();
|
|
||||||
void PerformFastFlashingRedLed();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,40 +0,0 @@
|
||||||
using InnovEnergy.Lib.Devices.Adam6360D;
|
|
||||||
using InnovEnergy.Lib.Protocols.Modbus.Channels;
|
|
||||||
|
|
||||||
namespace InnovEnergy.App.SodiStoreMax.SaliMaxRelays;
|
|
||||||
|
|
||||||
public class RelaysDeviceAdam6360
|
|
||||||
{
|
|
||||||
private Adam6360DDevice AdamDevice6360D { get; }
|
|
||||||
|
|
||||||
public RelaysDeviceAdam6360(String hostname) => AdamDevice6360D = new Adam6360DDevice(hostname, 2);
|
|
||||||
public RelaysDeviceAdam6360(Channel channel) => AdamDevice6360D = new Adam6360DDevice(channel, 2);
|
|
||||||
|
|
||||||
|
|
||||||
public RelaysRecordAdam6360D? Read()
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
return AdamDevice6360D.Read();
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
$"Failed to read from {nameof(RelaysDeviceAdam6360)}\n{e}".LogError();
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Write(RelaysRecordAdam6360D r)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
AdamDevice6360D.Write(r);
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
$"Failed to write to {nameof(RelaysDeviceAdam6360)}\n{e}".LogError();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1,38 +0,0 @@
|
||||||
using InnovEnergy.Lib.Devices.Adam6060;
|
|
||||||
using InnovEnergy.Lib.Protocols.Modbus.Channels;
|
|
||||||
|
|
||||||
namespace InnovEnergy.App.SodiStoreMax.SaliMaxRelays;
|
|
||||||
|
|
||||||
public class RelaysDeviceAdam6060
|
|
||||||
{
|
|
||||||
private Adam6060Device AdamDevice6060 { get; }
|
|
||||||
|
|
||||||
public RelaysDeviceAdam6060(String hostname) => AdamDevice6060 = new Adam6060Device(hostname, 2);
|
|
||||||
public RelaysDeviceAdam6060(Channel channel) => AdamDevice6060 = new Adam6060Device(channel, 2);
|
|
||||||
|
|
||||||
|
|
||||||
public RelaysRecordAdam6060? Read()
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
return AdamDevice6060.Read();
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
$"Failed to read from {nameof(RelaysDeviceAdam6060)}\n{e}".LogError();
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Write(RelaysRecordAdam6060 r)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
AdamDevice6060.Write(r);
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
$"Failed to write to {nameof(RelaysDeviceAdam6060)}\n{e}".LogError();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,24 +0,0 @@
|
||||||
using InnovEnergy.Lib.Devices.Adam6060;
|
|
||||||
|
|
||||||
|
|
||||||
namespace InnovEnergy.App.SodiStoreMax.SaliMaxRelays;
|
|
||||||
|
|
||||||
public class RelaysRecordAdam6060
|
|
||||||
{
|
|
||||||
private readonly Adam6060Registers _Regs;
|
|
||||||
|
|
||||||
private RelaysRecordAdam6060(Adam6060Registers regs) => _Regs = regs;
|
|
||||||
|
|
||||||
|
|
||||||
public Boolean Dc1WagoStatus => _Regs.DigitalInput0; // to test
|
|
||||||
public Boolean Dc2WagoStatus => _Regs.DigitalInput1; // to test
|
|
||||||
public Boolean Dc3WagoStatus => _Regs.DigitalInput4; // to test
|
|
||||||
public Boolean Dc4WagoStatus => _Regs.DigitalInput5; // to test
|
|
||||||
|
|
||||||
public Boolean DcSystemControlWagoStatus => _Regs.DigitalInput3; // to test
|
|
||||||
|
|
||||||
|
|
||||||
public static implicit operator Adam6060Registers(RelaysRecordAdam6060 d) => d._Regs;
|
|
||||||
public static implicit operator RelaysRecordAdam6060(Adam6060Registers d) => new RelaysRecordAdam6060(d);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,81 +0,0 @@
|
||||||
using InnovEnergy.Lib.Devices.Adam6360D;
|
|
||||||
|
|
||||||
namespace InnovEnergy.App.SodiStoreMax.SaliMaxRelays;
|
|
||||||
|
|
||||||
public class RelaysRecordAdam6360D
|
|
||||||
{
|
|
||||||
private readonly Adam6360DRegisters _Regs;
|
|
||||||
|
|
||||||
private RelaysRecordAdam6360D(Adam6360DRegisters regs) => _Regs = regs;
|
|
||||||
|
|
||||||
public Boolean K1GridBusIsConnectedToGrid => _Regs.DigitalInput6;
|
|
||||||
public Boolean K2IslandBusIsConnectedToGridBus => !_Regs.DigitalInput4;
|
|
||||||
|
|
||||||
public Boolean Inverter1WagoStatus => _Regs.DigitalInput8;
|
|
||||||
public Boolean Inverter2WagoStatus => _Regs.DigitalInput9;
|
|
||||||
public Boolean Inverter3WagoStatus => _Regs.DigitalInput10;
|
|
||||||
public Boolean Inverter4WagoStatus => _Regs.DigitalInput11;
|
|
||||||
|
|
||||||
public IEnumerable<Boolean> K3InverterIsConnectedToIslandBus
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
yield return K3Inverter1IsConnectedToIslandBus;
|
|
||||||
yield return K3Inverter2IsConnectedToIslandBus;
|
|
||||||
yield return K3Inverter3IsConnectedToIslandBus;
|
|
||||||
yield return K3Inverter4IsConnectedToIslandBus;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private Boolean K3Inverter1IsConnectedToIslandBus => !_Regs.DigitalInput0; // change it to private should be ok
|
|
||||||
private Boolean K3Inverter2IsConnectedToIslandBus => !_Regs.DigitalInput1;
|
|
||||||
private Boolean K3Inverter3IsConnectedToIslandBus => !_Regs.DigitalInput2;
|
|
||||||
private Boolean K3Inverter4IsConnectedToIslandBus => !_Regs.DigitalInput3;
|
|
||||||
|
|
||||||
public Boolean FiWarning => !_Regs.DigitalInput5;
|
|
||||||
public Boolean FiError => !_Regs.DigitalInput7;
|
|
||||||
|
|
||||||
public Boolean Harvester1Step =>_Regs.DigitalOutput2;
|
|
||||||
public Boolean Harvester2Step =>_Regs.DigitalOutput3;
|
|
||||||
public Boolean Harvester3Step =>_Regs.DigitalOutput4;
|
|
||||||
public Boolean Harvester4Step =>_Regs.DigitalOutput5;
|
|
||||||
|
|
||||||
public Boolean LedGreen { get =>_Regs.DigitalOutput0; set => _Regs.DigitalOutput0 = value;}
|
|
||||||
public Boolean LedRed { get =>_Regs.DigitalOutput1; set => _Regs.DigitalOutput1 = value;}
|
|
||||||
|
|
||||||
public Boolean Do0Pulse { get => _Regs.Do0Pulse; set => _Regs.Do0Pulse = value;}
|
|
||||||
public Boolean Do1Pulse { get => _Regs.Do1Pulse; set => _Regs.Do1Pulse = value;}
|
|
||||||
public Boolean Do2Pulse { get => _Regs.Do2Pulse; set => _Regs.Do2Pulse = value;}
|
|
||||||
public Boolean Do3Pulse { get => _Regs.Do3Pulse; set => _Regs.Do3Pulse = value;}
|
|
||||||
public Boolean Do4Pulse { get => _Regs.Do4Pulse; set => _Regs.Do4Pulse = value;}
|
|
||||||
public Boolean Do5Pulse { get => _Regs.Do5Pulse; set => _Regs.Do5Pulse = value;}
|
|
||||||
|
|
||||||
public UInt16 PulseOut0LowTime { get => _Regs.PulseOut0LowTime; set => _Regs.PulseOut0LowTime = value;} //in milleseconds
|
|
||||||
public UInt16 PulseOut1LowTime { get => _Regs.PulseOut1LowTime; set => _Regs.PulseOut1LowTime = value;}
|
|
||||||
public UInt16 PulseOut2LowTime { get => _Regs.PulseOut2LowTime; set => _Regs.PulseOut2LowTime = value;}
|
|
||||||
public UInt16 PulseOut3LowTime { get => _Regs.PulseOut3LowTime; set => _Regs.PulseOut3LowTime = value;}
|
|
||||||
public UInt16 PulseOut4LowTime { get => _Regs.PulseOut4LowTime; set => _Regs.PulseOut4LowTime = value;}
|
|
||||||
public UInt16 PulseOut5LowTime { get => _Regs.PulseOut5LowTime; set => _Regs.PulseOut5LowTime = value;}
|
|
||||||
|
|
||||||
public UInt16 PulseOut0HighTime { get => _Regs.PulseOut0HighTime; set => _Regs.PulseOut0HighTime = value;} // in milleseconds
|
|
||||||
public UInt16 PulseOut1HighTime { get => _Regs.PulseOut1HighTime; set => _Regs.PulseOut1HighTime = value;}
|
|
||||||
public UInt16 PulseOut2HighTime { get => _Regs.PulseOut2HighTime; set => _Regs.PulseOut2HighTime = value;}
|
|
||||||
public UInt16 PulseOut3HighTime { get => _Regs.PulseOut3HighTime; set => _Regs.PulseOut3HighTime = value;}
|
|
||||||
public UInt16 PulseOut4HighTime { get => _Regs.PulseOut4HighTime; set => _Regs.PulseOut4HighTime = value;}
|
|
||||||
public UInt16 PulseOut5HighTime { get => _Regs.PulseOut5HighTime; set => _Regs.PulseOut5HighTime = value;}
|
|
||||||
|
|
||||||
public UInt16 DigitalOutput0Mode { get => _Regs.DigitalOutput0Mode; set => _Regs.DigitalOutput0Mode = value;} // To test: 0, 1 or 2
|
|
||||||
public UInt16 DigitalOutput1Mode { get => _Regs.DigitalOutput1Mode; set => _Regs.DigitalOutput1Mode = value;}
|
|
||||||
public UInt16 DigitalOutput2Mode { get => _Regs.DigitalOutput2Mode; set => _Regs.DigitalOutput2Mode = value;}
|
|
||||||
public UInt16 DigitalOutput3Mode { get => _Regs.DigitalOutput3Mode; set => _Regs.DigitalOutput3Mode = value;}
|
|
||||||
public UInt16 DigitalOutput4Mode { get => _Regs.DigitalOutput4Mode; set => _Regs.DigitalOutput4Mode = value;}
|
|
||||||
public UInt16 DigitalOutput5Mode { get => _Regs.DigitalOutput5Mode; set => _Regs.DigitalOutput5Mode = value;}
|
|
||||||
|
|
||||||
public Boolean K2ConnectIslandBusToGridBus { get => _Regs.Relay0; set => _Regs.Relay0 = value;}
|
|
||||||
|
|
||||||
public static implicit operator Adam6360DRegisters(RelaysRecordAdam6360D d) => d._Regs;
|
|
||||||
public static implicit operator RelaysRecordAdam6360D(Adam6360DRegisters d) => new RelaysRecordAdam6360D(d);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1,134 +0,0 @@
|
||||||
using InnovEnergy.Lib.Devices.Amax5070;
|
|
||||||
|
|
||||||
namespace InnovEnergy.App.SodiStoreMax.SaliMaxRelays;
|
|
||||||
|
|
||||||
public class RelaysRecordAmax : IRelaysRecord
|
|
||||||
{
|
|
||||||
private readonly Amax5070Registers _Regs;
|
|
||||||
|
|
||||||
private RelaysRecordAmax(Amax5070Registers regs) => _Regs = regs;
|
|
||||||
|
|
||||||
public Boolean K1GridBusIsConnectedToGrid => _Regs.DigitalInput22;
|
|
||||||
public Boolean K2IslandBusIsConnectedToGridBus => !_Regs.DigitalInput20;
|
|
||||||
|
|
||||||
public Boolean Inverter1WagoStatus => _Regs.DigitalInput0;
|
|
||||||
public Boolean Inverter2WagoStatus => _Regs.DigitalInput1;
|
|
||||||
public Boolean Inverter3WagoStatus => _Regs.DigitalInput2;
|
|
||||||
public Boolean Inverter4WagoStatus => _Regs.DigitalInput3;
|
|
||||||
|
|
||||||
public Boolean Dc1WagoStatus => _Regs.DigitalInput6;
|
|
||||||
public Boolean Dc2WagoStatus => _Regs.DigitalInput7;
|
|
||||||
public Boolean Dc3WagoStatus => _Regs.DigitalInput10;
|
|
||||||
public Boolean Dc4WagoStatus => _Regs.DigitalInput11;
|
|
||||||
public Boolean DcSystemControlWagoStatus => _Regs.DigitalInput9;
|
|
||||||
|
|
||||||
public Boolean LedGreen
|
|
||||||
{
|
|
||||||
get => _Regs.DigitalOutput0;
|
|
||||||
set => _Regs.DigitalOutput0 = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Boolean LedRed => _Regs.DigitalOutput1;
|
|
||||||
public Boolean Harvester1Step => _Regs.DigitalOutput2;
|
|
||||||
public Boolean Harvester2Step => _Regs.DigitalOutput3;
|
|
||||||
public Boolean Harvester3Step => _Regs.DigitalOutput4;
|
|
||||||
public Boolean Harvester4Step => _Regs.DigitalOutput5;
|
|
||||||
public Boolean Do0StartPulse { get; set; }
|
|
||||||
public Boolean Do1StartPulse { get; set; }
|
|
||||||
public Boolean Do2StartPulse { get; set; }
|
|
||||||
public Boolean Do3StartPulse { get; set; }
|
|
||||||
public Boolean Do4StartPulse { get; set; }
|
|
||||||
public Boolean Do5StartPulse { get; set; }
|
|
||||||
public UInt16 DigitalOutput0Mode { get; set; }
|
|
||||||
public UInt16 DigitalOutput1Mode { get; set; }
|
|
||||||
public UInt16 DigitalOutput2Mode { get; set; }
|
|
||||||
public UInt16 DigitalOutput3Mode { get; set; }
|
|
||||||
public UInt16 DigitalOutput4Mode { get; set; }
|
|
||||||
public UInt16 DigitalOutput5Mode { get; set; }
|
|
||||||
public UInt16 PulseOut0LowTime { get; set; }
|
|
||||||
public UInt16 PulseOut1LowTime { get; set; }
|
|
||||||
public UInt16 PulseOut2LowTime { get; set; }
|
|
||||||
public UInt16 PulseOut3LowTime { get; set; }
|
|
||||||
public UInt16 PulseOut4LowTime { get; set; }
|
|
||||||
public UInt16 PulseOut5LowTime { get; set; }
|
|
||||||
public UInt16 PulseOut0HighTime { get; set; }
|
|
||||||
public UInt16 PulseOut1HighTime { get; set; }
|
|
||||||
public UInt16 PulseOut2HighTime { get; set; }
|
|
||||||
public UInt16 PulseOut3HighTime { get; set; }
|
|
||||||
public UInt16 PulseOut4HighTime { get; set; }
|
|
||||||
public UInt16 PulseOut5HighTime { get; set; }
|
|
||||||
|
|
||||||
public void PerformSolidGreenLed()
|
|
||||||
{
|
|
||||||
Console.WriteLine("Solid Green: This is not yet implemented ");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void PerformSlowFlashingGreenLed()
|
|
||||||
{
|
|
||||||
Console.WriteLine("Slow Flashing Green: This is not yet implemented ");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void PerformFastFlashingGreenLed()
|
|
||||||
{
|
|
||||||
Console.WriteLine("Fast Flashing Green: This is not yet implemented ");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void PerformSolidOrangeLed()
|
|
||||||
{
|
|
||||||
Console.WriteLine("Solid Orange: This is not yet implemented ");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void PerformSlowFlashingOrangeLed()
|
|
||||||
{
|
|
||||||
Console.WriteLine("Slow Flashing Orange: This is not yet implemented ");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void PerformFastFlashingOrangeLed()
|
|
||||||
{
|
|
||||||
Console.WriteLine("Fast Flashing Orange: This is not yet implemented ");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void PerformSolidRedLed()
|
|
||||||
{
|
|
||||||
Console.WriteLine("Solid Red: This is not yet implemented ");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void PerformSlowFlashingRedLed()
|
|
||||||
{
|
|
||||||
Console.WriteLine("Slow Flashing Red: This is not yet implemented ");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void PerformFastFlashingRedLed()
|
|
||||||
{
|
|
||||||
Console.WriteLine("Fast Flashing Red: This is not yet implemented ");
|
|
||||||
}
|
|
||||||
|
|
||||||
public IEnumerable<Boolean> K3InverterIsConnectedToIslandBus
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
yield return K3Inverter1IsConnectedToIslandBus;
|
|
||||||
yield return K3Inverter2IsConnectedToIslandBus;
|
|
||||||
yield return K3Inverter3IsConnectedToIslandBus;
|
|
||||||
yield return K3Inverter4IsConnectedToIslandBus;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private Boolean K3Inverter1IsConnectedToIslandBus => !_Regs.DigitalInput16;
|
|
||||||
private Boolean K3Inverter2IsConnectedToIslandBus => !_Regs.DigitalInput17;
|
|
||||||
private Boolean K3Inverter3IsConnectedToIslandBus => !_Regs.DigitalInput18;
|
|
||||||
private Boolean K3Inverter4IsConnectedToIslandBus => !_Regs.DigitalInput19;
|
|
||||||
|
|
||||||
public Boolean FiWarning => !_Regs.DigitalInput21;
|
|
||||||
public Boolean FiError => !_Regs.DigitalInput23;
|
|
||||||
|
|
||||||
public Boolean K2ConnectIslandBusToGridBus
|
|
||||||
{
|
|
||||||
get => _Regs.Relay23;
|
|
||||||
set => _Regs.Relay23 = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static implicit operator Amax5070Registers(RelaysRecordAmax d) => d._Regs;
|
|
||||||
public static implicit operator RelaysRecordAmax(Amax5070Registers d) => new RelaysRecordAmax(d);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,132 +0,0 @@
|
||||||
import serial
|
|
||||||
|
|
||||||
def parse_start_code(frame):
|
|
||||||
soi = frame[0:2]
|
|
||||||
if soi == "~":
|
|
||||||
return "ok!"
|
|
||||||
else:
|
|
||||||
raise ValueError(f"Invalid start identifier! ({soi})")
|
|
||||||
|
|
||||||
def parse_version_code(frame):
|
|
||||||
ver = frame[2:6]
|
|
||||||
return f"Protocol Version V{ver[0]}.{ver[1]}"
|
|
||||||
|
|
||||||
def parse_address_code(frame):
|
|
||||||
adr = frame[6:10]
|
|
||||||
if 0 <= int(adr) <= 15:
|
|
||||||
return adr
|
|
||||||
else:
|
|
||||||
raise ValueError(f"Invalid address: {adr} (out of range 0-15)")
|
|
||||||
|
|
||||||
def parse_device_code(frame):
|
|
||||||
cid1 = frame[10:14]
|
|
||||||
return bms.CID1_DEVICE_CODES.get(cid1, "Unknown!")
|
|
||||||
|
|
||||||
def parse_function_code(frame):
|
|
||||||
cid2 = frame[14:18]
|
|
||||||
if cid2 in bms.CID2_COMMAND_CODES:
|
|
||||||
return f"Command -> {bms.CID2_COMMAND_CODES.get(cid2)}"
|
|
||||||
elif cid2 in bms.CID2_RETURN_CODES:
|
|
||||||
return f"Return -> {bms.CID2_RETURN_CODES.get(cid2)}"
|
|
||||||
else:
|
|
||||||
return f"Unknown CID2: {cid2}"
|
|
||||||
|
|
||||||
def parse_lchksum(length_code):
|
|
||||||
# implements chapter 3.2.2 of the Protocol Specification
|
|
||||||
lchksum = int(length_code[0], 16)
|
|
||||||
# Compute lchksum
|
|
||||||
d11d10d09d08 = int(length_code[1])
|
|
||||||
d07d06d05d04 = int(length_code[2])
|
|
||||||
d03d0ld01d00 = int(length_code[3])
|
|
||||||
sum = d11d10d09d08 + d07d06d05d04 + d03d0ld01d00
|
|
||||||
remainder = sum % 16
|
|
||||||
inverted = ~remainder & 0xF
|
|
||||||
computed_lchksum = (inverted + 1) & 0xF
|
|
||||||
if computed_lchksum == lchksum:
|
|
||||||
return "ok!"
|
|
||||||
else:
|
|
||||||
raise ValueError(f"Invalid LCHKSUM: {lchksum} (computed: {computed_lchksum})")
|
|
||||||
|
|
||||||
|
|
||||||
def parse_lenid(length_code):
|
|
||||||
# implements chapter 3.2.1 of the Protocol Specification
|
|
||||||
d11d10d09d08 = int(length_code[1])
|
|
||||||
d07d06d05d04 = int(length_code[2])
|
|
||||||
d03d0ld01d00 = int(length_code[3])
|
|
||||||
lenid = d11d10d09d08 << 8 | d07d06d05d04 << 4 | d03d0ld01d00
|
|
||||||
return lenid>>1
|
|
||||||
|
|
||||||
def parse_length_code(frame):
|
|
||||||
# implements chapter 3.2 of the Protocol Specification
|
|
||||||
length_code = frame[18:26]
|
|
||||||
lchksum = parse_lchksum(length_code)
|
|
||||||
lenid = parse_lenid(length_code)
|
|
||||||
return { "LCHKSUM": lchksum, "LENID": lenid }
|
|
||||||
|
|
||||||
def parse_info(frame):
|
|
||||||
cid2 = frame[14:18]
|
|
||||||
lenid = parse_lenid(frame[18:26])
|
|
||||||
info = frame[26:26+lenid*2]
|
|
||||||
|
|
||||||
if cid2 == '00' and lenid == 49:
|
|
||||||
return parse_telecommand_return(info)
|
|
||||||
elif cid2 == '00' and lenid == 75:
|
|
||||||
return parse_telemetry_return(info)
|
|
||||||
else:
|
|
||||||
return info
|
|
||||||
|
|
||||||
def parse_telecommand_return(info_raw, info={}, index=0):
|
|
||||||
|
|
||||||
info["DATA FLAG"] = info_raw[index:index+4]
|
|
||||||
index += 4
|
|
||||||
|
|
||||||
info["COMMAND GROUP"] = info_raw[index:index+4]
|
|
||||||
index += 4
|
|
||||||
|
|
||||||
|
|
||||||
def parse_modbus_ascii_frame(frame, parsed_data = {}):
|
|
||||||
frame = bytes.fromhex(frame).decode('ascii')
|
|
||||||
parsed_data["SOI"] = parse_start_code(frame)
|
|
||||||
parsed_data["VER"] = parse_version_code(frame)
|
|
||||||
parsed_data["ADR"] = parse_address_code(frame)
|
|
||||||
parsed_data["CID1"] = parse_device_code(frame)
|
|
||||||
parsed_data["CID2"] = parse_function_code(frame)
|
|
||||||
parsed_data["LENGTH"] = parse_length_code(frame)
|
|
||||||
parsed_data["INFO"] = parse_info(frame)
|
|
||||||
parsed_data["CHKSUM"] = parse_checksum(frame)
|
|
||||||
parsed_data["EOI"] = parse_end_code(frame)
|
|
||||||
return parsed_data
|
|
||||||
|
|
||||||
def send_command():
|
|
||||||
|
|
||||||
# Define the serial port and baud rate
|
|
||||||
port = 'COM9' # Replace with your actual port
|
|
||||||
baudrate = 19200 # Replace with the correct baud rate for your BMS
|
|
||||||
|
|
||||||
# Create the serial connection
|
|
||||||
try:
|
|
||||||
with serial.Serial(port, baudrate, timeout=1) as ser:
|
|
||||||
# Convert the hex string to bytes
|
|
||||||
command = bytes.fromhex("7E3230303034363434453030323030464433350D")
|
|
||||||
|
|
||||||
# Send the command
|
|
||||||
ser.write(command)
|
|
||||||
print("Command sent successfully.")
|
|
||||||
|
|
||||||
# Wait for and read the response
|
|
||||||
response = ser.read(200) # Adjust the number of bytes to read as needed
|
|
||||||
if response:
|
|
||||||
hex_response = response.hex()
|
|
||||||
print("Response received:", hex_response)
|
|
||||||
# Process the response to check details
|
|
||||||
check_starting_byte_and_extract_details(hex_response)
|
|
||||||
else:
|
|
||||||
print("No response received.")
|
|
||||||
except serial.SerialException as e:
|
|
||||||
print(f"Error opening serial port: {e}")
|
|
||||||
except Exception as e:
|
|
||||||
print(f"An unexpected error occurred: {e}")
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
send_command()
|
|
||||||
|
|
@ -1,480 +0,0 @@
|
||||||
import serial
|
|
||||||
import csv
|
|
||||||
|
|
||||||
TELECOMMAND_FILE_PATH = "Telecommand_Return_Record.csv"
|
|
||||||
|
|
||||||
# Table 3
|
|
||||||
CID1_DEVICE_CODES = {
|
|
||||||
"46": "Lithium iron phosphate battery BMS",
|
|
||||||
}
|
|
||||||
|
|
||||||
# Table 4
|
|
||||||
CID2_COMMAND_CODES = {
|
|
||||||
"42": "Acquisition of telemetering information",
|
|
||||||
"44": "Acquisition of telecommand information",
|
|
||||||
"45": "Telecontrol command",
|
|
||||||
"47": "Acquisition of teleregulation information",
|
|
||||||
"49": "Setting of teleregulation information",
|
|
||||||
"4F": "Acquisition of the communication protocol version number",
|
|
||||||
"51": "Acquisition of device vendor information",
|
|
||||||
"4B": "Acquisition of historical data",
|
|
||||||
"4D": "Acquisition time",
|
|
||||||
"4E": "Synchronization time",
|
|
||||||
"A0": "Production calibration",
|
|
||||||
"A1": "Production setting",
|
|
||||||
"A2": "Regular recording"
|
|
||||||
}
|
|
||||||
|
|
||||||
# Table 5
|
|
||||||
CID2_RETURN_CODES = {
|
|
||||||
"00": "Normal",
|
|
||||||
"01": "VER error",
|
|
||||||
"02": "CHKSUM error",
|
|
||||||
"03": "LCHKSUM error",
|
|
||||||
"04": "CID2 invalid",
|
|
||||||
"05": "Command format error",
|
|
||||||
"06": "Data invalid (parameter setting)",
|
|
||||||
"07": "No data (history)",
|
|
||||||
"E1": "CID1 invalid",
|
|
||||||
"E2": "Command execution failure",
|
|
||||||
"E3": "Device fault",
|
|
||||||
"E4": "Invalid permissions"
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
# Table 12
|
|
||||||
BYTE_ALARM_CODES = {
|
|
||||||
"00": "Normal, no alarm",
|
|
||||||
"01": "Alarm that analog quantity reaches the lower limit",
|
|
||||||
"02": "Alarm that analog quantity reaches the upper limit",
|
|
||||||
"F0": "Other alarms"
|
|
||||||
}
|
|
||||||
|
|
||||||
# Table 13
|
|
||||||
BIT_ALARM_CODES = {
|
|
||||||
"Alarm event 1": (
|
|
||||||
"Voltage sensor fault",
|
|
||||||
"Temperature sensor fault",
|
|
||||||
"Current sensor fault",
|
|
||||||
"Key switch fault",
|
|
||||||
"Cell voltage dropout fault",
|
|
||||||
"Charge switch fault",
|
|
||||||
"Discharge switch fault",
|
|
||||||
"Current limit switch fault"
|
|
||||||
),
|
|
||||||
"Alarm event 2": (
|
|
||||||
"Monomer high voltage alarm",
|
|
||||||
"Monomer overvoltage protection",
|
|
||||||
"Monomer low voltage alarm",
|
|
||||||
"Monomer under voltage protection",
|
|
||||||
"High voltage alarm for total voltage",
|
|
||||||
"Overvoltage protection for total voltage",
|
|
||||||
"Low voltage alarm for total voltage",
|
|
||||||
"Under voltage protection for total voltage"
|
|
||||||
),
|
|
||||||
"Alarm event 3": (
|
|
||||||
"Charge high temperature alarm",
|
|
||||||
"Charge over temperature protection",
|
|
||||||
"Charge low temperature alarm",
|
|
||||||
"Charge under temperature protection",
|
|
||||||
"Discharge high temperature alarm",
|
|
||||||
"Discharge over temperature protection",
|
|
||||||
"Discharge low temperature alarm",
|
|
||||||
"Discharge under temperature protection"
|
|
||||||
),
|
|
||||||
"Alarm event 4": (
|
|
||||||
"Environment high temperature alarm",
|
|
||||||
"Environment over temperature protection",
|
|
||||||
"Environment low temperature alarm",
|
|
||||||
"Environment under temperature protection",
|
|
||||||
"Power over temperature protection",
|
|
||||||
"Power high temperature alarm",
|
|
||||||
"Cell low temperature heating",
|
|
||||||
"Reservation bit"
|
|
||||||
),
|
|
||||||
"Alarm event 5": (
|
|
||||||
"Charge over current alarm",
|
|
||||||
"Charge over current protection",
|
|
||||||
"Discharge over current alarm",
|
|
||||||
"Discharge over current protection",
|
|
||||||
"Transient over current protection",
|
|
||||||
"Output short circuit protection",
|
|
||||||
"Transient over current lockout",
|
|
||||||
"Output short circuit lockout"
|
|
||||||
),
|
|
||||||
"Alarm event 6": (
|
|
||||||
"Charge high voltage protection",
|
|
||||||
"Intermittent recharge waiting",
|
|
||||||
"Residual capacity alarm",
|
|
||||||
"Residual capacity protection",
|
|
||||||
"Cell low voltage charging prohibition",
|
|
||||||
"Output reverse polarity protection",
|
|
||||||
"Output connection fault",
|
|
||||||
"Inside bit"
|
|
||||||
),
|
|
||||||
"On-off state": (
|
|
||||||
"Discharge switch state",
|
|
||||||
"Charge switch state",
|
|
||||||
"Current limit switch state",
|
|
||||||
"Heating switch state",
|
|
||||||
"Reservation bit",
|
|
||||||
"Reservation bit",
|
|
||||||
"Reservation bit",
|
|
||||||
"Reservation bit"
|
|
||||||
),
|
|
||||||
"Equilibrium state 1": (
|
|
||||||
"Cell 01 equilibrium",
|
|
||||||
"Cell 02 equilibrium",
|
|
||||||
"Cell 03 equilibrium",
|
|
||||||
"Cell 04 equilibrium",
|
|
||||||
"Cell 05 equilibrium",
|
|
||||||
"Cell 06 equilibrium",
|
|
||||||
"Cell 07 equilibrium",
|
|
||||||
"Cell 08 equilibrium"
|
|
||||||
),
|
|
||||||
"Equilibrium state 2": (
|
|
||||||
"Cell 09 equilibrium",
|
|
||||||
"Cell 10 equilibrium",
|
|
||||||
"Cell 11 equilibrium",
|
|
||||||
"Cell 12 equilibrium",
|
|
||||||
"Cell 13 equilibrium",
|
|
||||||
"Cell 14 equilibrium",
|
|
||||||
"Cell 15 equilibrium",
|
|
||||||
"Cell 16 equilibrium"
|
|
||||||
),
|
|
||||||
"System state": (
|
|
||||||
"Discharge",
|
|
||||||
"Charge",
|
|
||||||
"Floating charge",
|
|
||||||
"Reservation bit",
|
|
||||||
"Standby",
|
|
||||||
"Shutdown",
|
|
||||||
"Reservation bit",
|
|
||||||
"Reservation bit"
|
|
||||||
),
|
|
||||||
"Disconnection state 1": (
|
|
||||||
"Cell 01 disconnection",
|
|
||||||
"Cell 02 disconnection",
|
|
||||||
"Cell 03 disconnection",
|
|
||||||
"Cell 04 disconnection",
|
|
||||||
"Cell 05 disconnection",
|
|
||||||
"Cell 06 disconnection",
|
|
||||||
"Cell 07 disconnection",
|
|
||||||
"Cell 08 disconnection"
|
|
||||||
),
|
|
||||||
"Disconnection state 2": (
|
|
||||||
"Cell 09 disconnection",
|
|
||||||
"Cell 10 disconnection",
|
|
||||||
"Cell 11 disconnection",
|
|
||||||
"Cell 12 disconnection",
|
|
||||||
"Cell 13 disconnection",
|
|
||||||
"Cell 14 disconnection",
|
|
||||||
"Cell 15 disconnection",
|
|
||||||
"Cell 16 disconnection"
|
|
||||||
),
|
|
||||||
"Alarm event 7": (
|
|
||||||
"Inside bit",
|
|
||||||
"Inside bit",
|
|
||||||
"Inside bit",
|
|
||||||
"Inside bit",
|
|
||||||
"Automatic charging waiting",
|
|
||||||
"Manual charging waiting",
|
|
||||||
"Inside bit",
|
|
||||||
"Inside bit"
|
|
||||||
),
|
|
||||||
"Alarm event 3": (
|
|
||||||
"EEP storage fault",
|
|
||||||
"RTC error",
|
|
||||||
"Voltage calibration not performed",
|
|
||||||
"Current calibration not performed",
|
|
||||||
"Zero calibration not performed",
|
|
||||||
"Inside bit",
|
|
||||||
"Inside bit",
|
|
||||||
"Inside bit"
|
|
||||||
),
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
def parse_start_code(frame):
|
|
||||||
soi = frame[0:1]
|
|
||||||
if soi == "~":
|
|
||||||
return "ok!"
|
|
||||||
else:
|
|
||||||
raise ValueError(f"Invalid start identifier! ({soi})")
|
|
||||||
|
|
||||||
def parse_version_code(frame):
|
|
||||||
ver = frame[1:3]
|
|
||||||
return f"Protocol Version V{ver[0]}.{ver[1]}"
|
|
||||||
|
|
||||||
def parse_address_code(frame):
|
|
||||||
adr = frame[3:5]
|
|
||||||
if 0 <= int(adr) <= 15:
|
|
||||||
return adr
|
|
||||||
else:
|
|
||||||
raise ValueError(f"Invalid address: {adr} (out of range 0-15)")
|
|
||||||
|
|
||||||
def parse_device_code(frame):
|
|
||||||
cid1 = frame[5:7]
|
|
||||||
return CID1_DEVICE_CODES.get(cid1, "Unknown!")
|
|
||||||
|
|
||||||
def parse_function_code(frame):
|
|
||||||
cid2 = frame[7:9]
|
|
||||||
if cid2 in CID2_COMMAND_CODES:
|
|
||||||
return f"Command -> {CID2_COMMAND_CODES.get(cid2)}"
|
|
||||||
elif cid2 in CID2_RETURN_CODES:
|
|
||||||
return f"Return -> {CID2_RETURN_CODES.get(cid2)}"
|
|
||||||
else:
|
|
||||||
return f"Unknown CID2: {cid2}"
|
|
||||||
|
|
||||||
def parse_lchksum(length_code):
|
|
||||||
# implements chapter 3.2.2 of the Protocol Specification
|
|
||||||
lchksum = int(length_code[0], 16)
|
|
||||||
# Compute lchksum
|
|
||||||
d11d10d09d08 = int(length_code[1])
|
|
||||||
d07d06d05d04 = int(length_code[2])
|
|
||||||
d03d0ld01d00 = int(length_code[3])
|
|
||||||
sum = d11d10d09d08 + d07d06d05d04 + d03d0ld01d00
|
|
||||||
remainder = sum % 16
|
|
||||||
inverted = ~remainder & 0xF
|
|
||||||
computed_lchksum = (inverted + 1) & 0xF
|
|
||||||
if computed_lchksum == lchksum:
|
|
||||||
return "ok!"
|
|
||||||
else:
|
|
||||||
raise ValueError(f"Invalid LCHKSUM: {lchksum} (computed: {computed_lchksum})")
|
|
||||||
|
|
||||||
def parse_lenid(length_code):
|
|
||||||
# implements chapter 3.2.1 of the Protocol Specification
|
|
||||||
d11d10d09d08 = int(length_code[1])
|
|
||||||
d07d06d05d04 = int(length_code[2])
|
|
||||||
d03d0ld01d00 = int(length_code[3])
|
|
||||||
lenid = d11d10d09d08 << 8 | d07d06d05d04 << 4 | d03d0ld01d00
|
|
||||||
return lenid >> 1
|
|
||||||
|
|
||||||
def parse_length_code(frame):
|
|
||||||
# implements chapter 3.2 of the Protocol Specification
|
|
||||||
length_code = frame[9:13]
|
|
||||||
lchksum = parse_lchksum(length_code)
|
|
||||||
lenid = parse_lenid(length_code)
|
|
||||||
return { "LCHKSUM": lchksum, "LENID": lenid }
|
|
||||||
|
|
||||||
def parse_info(frame):
|
|
||||||
cid2 = frame[7:9]
|
|
||||||
lenid = parse_lenid(frame[9:13])
|
|
||||||
info = frame[13:13+lenid*2]
|
|
||||||
|
|
||||||
if cid2 == '00' and lenid == 49:
|
|
||||||
return parse_telecommand_return(info)
|
|
||||||
elif cid2 == '00' and lenid == 75:
|
|
||||||
return parse_telemetry_return(info)
|
|
||||||
else:
|
|
||||||
return info
|
|
||||||
|
|
||||||
def parse_telecommand_return(info_raw, info={}, index=0):
|
|
||||||
|
|
||||||
info["DATA FLAG"] = info_raw[index:index+2]
|
|
||||||
index += 2
|
|
||||||
|
|
||||||
info["COMMAND GROUP"] = info_raw[index:index+2]
|
|
||||||
index += 2
|
|
||||||
|
|
||||||
num_of_cells = int(info_raw[index:index+2], 16)
|
|
||||||
info["Number of cells"] = num_of_cells
|
|
||||||
index += 2
|
|
||||||
|
|
||||||
for cell in range(info["Number of cells"]):
|
|
||||||
alarm = BYTE_ALARM_CODES.get(info_raw[index:index+2])
|
|
||||||
info[f"Cell {cell +1} alarm"] = alarm
|
|
||||||
index += 2
|
|
||||||
|
|
||||||
num_of_temperatures = int(info_raw[index:index+2], 16)
|
|
||||||
info["Number of temperatures"] = num_of_temperatures
|
|
||||||
index += 2
|
|
||||||
|
|
||||||
for sensor in range(4):
|
|
||||||
alarm = BYTE_ALARM_CODES.get(info_raw[index:index+2])
|
|
||||||
info[f"Cell temperature alarm {sensor}"] = alarm
|
|
||||||
index += 2
|
|
||||||
|
|
||||||
alarm = BYTE_ALARM_CODES.get(info_raw[index:index+2])
|
|
||||||
info["Environment temperature alarm"] = alarm
|
|
||||||
index += 2
|
|
||||||
|
|
||||||
alarm = BYTE_ALARM_CODES.get(info_raw[index:index+2])
|
|
||||||
info["Power temperature alarm 1"] = alarm
|
|
||||||
index += 2
|
|
||||||
|
|
||||||
alarm = BYTE_ALARM_CODES.get(info_raw[index:index+2])
|
|
||||||
info["Charge/discharge current alarm"] = alarm
|
|
||||||
index += 2
|
|
||||||
|
|
||||||
alarm = BYTE_ALARM_CODES.get(info_raw[index:index+2])
|
|
||||||
info["Total battery voltage alarm"] = alarm
|
|
||||||
index += 2
|
|
||||||
|
|
||||||
num_custom = int(info_raw[index:index+2], 16)
|
|
||||||
info["Number of custom alarms"] = num_custom
|
|
||||||
index += 2
|
|
||||||
|
|
||||||
alarm = info_raw[index:index+2]
|
|
||||||
info["Alarm event 1"] = alarm
|
|
||||||
index += 2
|
|
||||||
|
|
||||||
alarm = info_raw[index:index+2]
|
|
||||||
info["Alarm event 2"] = alarm
|
|
||||||
index += 2
|
|
||||||
|
|
||||||
alarm = info_raw[index:index+2]
|
|
||||||
info["Alarm event 3"] = alarm
|
|
||||||
index += 2
|
|
||||||
|
|
||||||
alarm = info_raw[index:index+2]
|
|
||||||
info["Alarm event 4"] = alarm
|
|
||||||
index += 2
|
|
||||||
|
|
||||||
alarm = info_raw[index:index+2]
|
|
||||||
info["Alarm event 5"] = alarm
|
|
||||||
index += 2
|
|
||||||
|
|
||||||
alarm = info_raw[index:index+2]
|
|
||||||
info["Alarm event 6"] = alarm
|
|
||||||
index += 2
|
|
||||||
|
|
||||||
alarm = info_raw[index:index+2]
|
|
||||||
info["On-off state"] = alarm
|
|
||||||
index += 2
|
|
||||||
|
|
||||||
alarm = info_raw[index:index+2]
|
|
||||||
info["Equilibrium state 1"] = alarm
|
|
||||||
index += 2
|
|
||||||
|
|
||||||
alarm = info_raw[index:index+2]
|
|
||||||
info["Equilibrium state 2"] = alarm
|
|
||||||
index += 2
|
|
||||||
|
|
||||||
alarm = info_raw[index:index+2]
|
|
||||||
info["System state"] = alarm
|
|
||||||
index += 2
|
|
||||||
|
|
||||||
alarm = info_raw[index:index+2]
|
|
||||||
info["Disconnection state 1"] = alarm
|
|
||||||
index += 2
|
|
||||||
|
|
||||||
alarm = info_raw[index:index+2]
|
|
||||||
info["Disconnection state 2"] = alarm
|
|
||||||
index += 2
|
|
||||||
|
|
||||||
alarm = info_raw[index:index+2]
|
|
||||||
info["Alarm event 7"] = alarm
|
|
||||||
index += 2
|
|
||||||
|
|
||||||
alarm = info_raw[index:index+2]
|
|
||||||
info["Alarm event 8"] = alarm
|
|
||||||
index += 2
|
|
||||||
|
|
||||||
alarm = info_raw[index:index+2]
|
|
||||||
info["Reservation extention 1"] = alarm
|
|
||||||
index += 2
|
|
||||||
|
|
||||||
alarm = info_raw[index:index+2]
|
|
||||||
info["Reservation extention 2"] = alarm
|
|
||||||
index += 2
|
|
||||||
|
|
||||||
alarm = info_raw[index:index+2]
|
|
||||||
info["Reservation extention 3"] = alarm
|
|
||||||
index += 2
|
|
||||||
|
|
||||||
alarm = info_raw[index:index+2]
|
|
||||||
info["Reservation extention 4"] = alarm
|
|
||||||
index += 2
|
|
||||||
|
|
||||||
alarm = info_raw[index:index+2]
|
|
||||||
info["Reservation extention 5"] = alarm
|
|
||||||
index += 2
|
|
||||||
|
|
||||||
alarm = info_raw[index:index+2]
|
|
||||||
info["Reservation extention 6"] = alarm
|
|
||||||
index += 2
|
|
||||||
|
|
||||||
save_dict_to_csv(TELECOMMAND_FILE_PATH, info)
|
|
||||||
return f"Telecommand Return Data saved in ./{TELECOMMAND_FILE_PATH}"
|
|
||||||
|
|
||||||
|
|
||||||
def save_dict_to_csv(file_path, data):
|
|
||||||
with open(file_path, mode='a+', newline='') as csvfile:
|
|
||||||
csvfile.seek(0)
|
|
||||||
has_header = csvfile.read(1) != ""
|
|
||||||
csvfile.seek(0, 2)
|
|
||||||
writer = csv.DictWriter(csvfile, fieldnames=data.keys())
|
|
||||||
if not has_header:
|
|
||||||
writer.writeheader()
|
|
||||||
writer.writerow(data)
|
|
||||||
|
|
||||||
def parse_checksum(frame):
|
|
||||||
"""implements section 3.3 of the Protocol Specification"""
|
|
||||||
chksum = int(frame[-6:-1], 16)
|
|
||||||
data = frame[1:-5]
|
|
||||||
# Compute chksum
|
|
||||||
ascii_sum = sum(ord(char) for char in data)
|
|
||||||
remainder = ascii_sum % 65536
|
|
||||||
inverted = ~remainder & 0xFFFF
|
|
||||||
computed_chksum = (inverted + 1) & 0xFFFF
|
|
||||||
# Compare with CHKSUM in frame
|
|
||||||
if computed_chksum == chksum:
|
|
||||||
return "ok!"
|
|
||||||
else:
|
|
||||||
raise ValueError(f"Invalid CHKSUM: {chksum} (computed: {computed_chksum})")
|
|
||||||
|
|
||||||
def parse_end_code(frame):
|
|
||||||
eoi = frame[-1]
|
|
||||||
if eoi == "\r":
|
|
||||||
return "ok!"
|
|
||||||
else:
|
|
||||||
raise ValueError(f"Invalid end identifier! ({eoi})")
|
|
||||||
|
|
||||||
def parse_modbus_ascii_frame(frame, parsed_data = {}):
|
|
||||||
frame = bytes.fromhex(frame).decode('ascii')
|
|
||||||
parsed_data["SOI"] = parse_start_code(frame)
|
|
||||||
parsed_data["VER"] = parse_version_code(frame)
|
|
||||||
parsed_data["ADR"] = parse_address_code(frame)
|
|
||||||
parsed_data["CID1"] = parse_device_code(frame)
|
|
||||||
parsed_data["CID2"] = parse_function_code(frame)
|
|
||||||
parsed_data["LENGTH"] = parse_length_code(frame)
|
|
||||||
parsed_data["INFO"] = parse_info(frame)
|
|
||||||
parsed_data["CHKSUM"] = parse_checksum(frame)
|
|
||||||
parsed_data["EOI"] = parse_end_code(frame)
|
|
||||||
return parsed_data
|
|
||||||
|
|
||||||
def send_command():
|
|
||||||
|
|
||||||
# Define the serial port and baud rate
|
|
||||||
port = 'COM9' # Replace with your actual port
|
|
||||||
baudrate = 19200 # Replace with the correct baud rate for your BMS
|
|
||||||
|
|
||||||
# Create the serial connection
|
|
||||||
try:
|
|
||||||
with serial.Serial(port, baudrate, timeout=1) as ser:
|
|
||||||
# Convert the hex string to bytes
|
|
||||||
command = bytes.fromhex("7E3230303034363434453030323030464433350D")
|
|
||||||
|
|
||||||
# Send the command
|
|
||||||
ser.write(command)
|
|
||||||
print("Command sent successfully.")
|
|
||||||
|
|
||||||
# Wait for and read the response
|
|
||||||
response = ser.read(200) # Adjust the number of bytes to read as needed
|
|
||||||
if response:
|
|
||||||
hex_response = response.hex()
|
|
||||||
print("Response received:", hex_response)
|
|
||||||
# Process the response to check details
|
|
||||||
parsed_result = parse_modbus_ascii_frame(hex_response)
|
|
||||||
for key, value in parsed_result.items():
|
|
||||||
print(f"{key}: {value}")
|
|
||||||
else:
|
|
||||||
print("No response received.")
|
|
||||||
except serial.SerialException as e:
|
|
||||||
print(f"Error opening serial port: {e}")
|
|
||||||
except Exception as e:
|
|
||||||
print(f"An unexpected error occurred: {e}")
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
send_command()
|
|
||||||
Loading…
Reference in New Issue