fixed sunspec inverter event state
This commit is contained in:
parent
c112e1e6a0
commit
1020dd90a4
@ -564,6 +564,8 @@ void IntegrationPluginSunSpec::onFoundSunSpecModel(SunSpec::ModelId modelId, int
|
||||
descriptor.setParams(params);
|
||||
emit autoThingsAppeared({descriptor});
|
||||
} break;
|
||||
case SunSpec::ModelIdWyeConnectThreePhaseMeter:
|
||||
case SunSpec::ModelIdDeltaConnectThreePhaseMeter:
|
||||
case SunSpec::ModelIdWyeConnectThreePhaseMeterFloat:
|
||||
case SunSpec::ModelIdDeltaConnectThreePhaseMeterFloat: {
|
||||
ThingDescriptor descriptor(sunspecThreePhaseMeterThingClassId, model+" meter", "", thing->id());
|
||||
@ -617,6 +619,24 @@ void IntegrationPluginSunSpec::onInverterDataReceived(const SunSpecInverter::Inv
|
||||
if(!thing) {
|
||||
return;
|
||||
}
|
||||
|
||||
qCDebug(dcSunSpec()) << "Inverter data received";
|
||||
qCDebug(dcSunSpec()) << " - Total AC Current" << inverterData.acCurrent << "[A]";
|
||||
qCDebug(dcSunSpec()) << " - Phase A Current" << inverterData.phaseACurrent << "[A]";
|
||||
qCDebug(dcSunSpec()) << " - Phase B Current" << inverterData.phaseBCurrent << "[A]";
|
||||
qCDebug(dcSunSpec()) << " - Phase C Current" << inverterData.phaseCCurrent << "[A]";
|
||||
qCDebug(dcSunSpec()) << " - Phase voltage AB" << inverterData.phaseVoltageAB << "[V]";
|
||||
qCDebug(dcSunSpec()) << " - Phase voltage BC" << inverterData.phaseVoltageBC << "[V]";
|
||||
qCDebug(dcSunSpec()) << " - Phase voltage CA" << inverterData.phaseVoltageCA << "[V]";
|
||||
qCDebug(dcSunSpec()) << " - Phase voltage AN" << inverterData.phaseVoltageAN << "[V]";
|
||||
qCDebug(dcSunSpec()) << " - Phase voltage BN" << inverterData.phaseVoltageBN << "[V]";
|
||||
qCDebug(dcSunSpec()) << " - Phase voltage CN" << inverterData.phaseVoltageCN << "[V]";
|
||||
qCDebug(dcSunSpec()) << " - AC Power" << inverterData.acPower << "[W]";
|
||||
qCDebug(dcSunSpec()) << " - Line frequency" << inverterData.lineFrequency << "[Hz]";
|
||||
qCDebug(dcSunSpec()) << " - AC energy" << inverterData.acEnergy << "[Wh]";
|
||||
qCDebug(dcSunSpec()) << " - Cabinet temperature" << inverterData.cabinetTemperature << "[°C]";
|
||||
qCDebug(dcSunSpec()) << " - Operating state" << inverterData.operatingState;
|
||||
|
||||
thing->setStateValue(m_connectedStateTypeIds.value(thing->thingClassId()), true);
|
||||
thing->setStateValue(m_acPowerStateTypeIds.value(thing->thingClassId()), inverterData.acPower/1000.00);
|
||||
thing->setStateValue(m_acEnergyStateTypeIds.value(thing->thingClassId()), inverterData.acEnergy/1000.00);
|
||||
@ -625,7 +645,7 @@ void IntegrationPluginSunSpec::onInverterDataReceived(const SunSpecInverter::Inv
|
||||
thing->setStateValue(sunspecThreePhaseInverterTotalCurrentStateTypeId, inverterData.acCurrent);
|
||||
thing->setStateValue(sunspecThreePhaseInverterCabinetTemperatureStateTypeId, inverterData.cabinetTemperature);
|
||||
|
||||
if (thing->thingClassId() == sunspecSplitPhaseMeterThingClassId) {
|
||||
if (thing->thingClassId() == sunspecSplitPhaseInverterThingClassId) {
|
||||
|
||||
thing->setStateValue(sunspecSplitPhaseInverterPhaseANVoltageStateTypeId, inverterData.phaseVoltageAN);
|
||||
thing->setStateValue(sunspecSplitPhaseInverterPhaseBNVoltageStateTypeId, inverterData.phaseVoltageBN);
|
||||
@ -633,7 +653,7 @@ void IntegrationPluginSunSpec::onInverterDataReceived(const SunSpecInverter::Inv
|
||||
thing->setStateValue(sunspecSplitPhaseInverterPhaseACurrentStateTypeId, inverterData.phaseACurrent);
|
||||
thing->setStateValue(sunspecSplitPhaseInverterPhaseBCurrentStateTypeId, inverterData.phaseBCurrent);
|
||||
|
||||
} else if (thing->thingClassId() == sunspecThreePhaseMeterThingClassId) {
|
||||
} else if (thing->thingClassId() == sunspecThreePhaseInverterThingClassId) {
|
||||
|
||||
thing->setStateValue(sunspecThreePhaseInverterPhaseANVoltageStateTypeId, inverterData.phaseVoltageAN);
|
||||
thing->setStateValue(sunspecThreePhaseInverterPhaseBNVoltageStateTypeId, inverterData.phaseVoltageBN);
|
||||
@ -671,55 +691,41 @@ void IntegrationPluginSunSpec::onInverterDataReceived(const SunSpecInverter::Inv
|
||||
break;
|
||||
}
|
||||
|
||||
switch(inverterData.event) {
|
||||
case SunSpec::SunSpecEvent1::OVER_TEMP:
|
||||
//FIXME: Event1 may have multiple states at once. Only one is stated in nymea
|
||||
if (inverterData.event1.overTemperature) {
|
||||
thing->setStateValue(sunspecThreePhaseInverterErrorStateTypeId, "Over temperature");
|
||||
break;
|
||||
case SunSpec::SunSpecEvent1::UNDER_TEMP:
|
||||
} else if (inverterData.event1.underTemperature) {
|
||||
thing->setStateValue(sunspecThreePhaseInverterErrorStateTypeId, "Under temperature");
|
||||
break;
|
||||
case SunSpec::SunSpecEvent1::GroundFault:
|
||||
} else if (inverterData.event1.groundFault) {
|
||||
thing->setStateValue(sunspecThreePhaseInverterErrorStateTypeId, "Ground fault");
|
||||
break;
|
||||
case SunSpec::SunSpecEvent1::MEMORY_LOSS:
|
||||
} else if (inverterData.event1.memoryLoss) {
|
||||
thing->setStateValue(sunspecThreePhaseInverterErrorStateTypeId, "Memory loss");
|
||||
break;
|
||||
case SunSpec::SunSpecEvent1::AC_OVER_VOLT:
|
||||
} else if (inverterData.event1.acOverVolt) {
|
||||
thing->setStateValue(sunspecThreePhaseInverterErrorStateTypeId, "AC voltage above limit");
|
||||
break;
|
||||
case SunSpec::SunSpecEvent1::CABINET_OPEN:
|
||||
} else if (inverterData.event1.cabinetOpen) {
|
||||
thing->setStateValue(sunspecThreePhaseInverterErrorStateTypeId, "Cabinet open");
|
||||
break;
|
||||
case SunSpec::SunSpecEvent1::AC_DISCONNECT:
|
||||
} else if (inverterData.event1.acDisconnect) {
|
||||
thing->setStateValue(sunspecThreePhaseInverterErrorStateTypeId, "AC disconnect open");
|
||||
break;
|
||||
case SunSpec::SunSpecEvent1::AC_UNDER_VOLT:
|
||||
} else if (inverterData.event1.acUnderVolt) {
|
||||
thing->setStateValue(sunspecThreePhaseInverterErrorStateTypeId, "AC voltage under limit");
|
||||
break;
|
||||
case SunSpec::SunSpecEvent1::DC_DISCONNECT:
|
||||
} else if (inverterData.event1.dcDicconnect) {
|
||||
thing->setStateValue(sunspecThreePhaseInverterErrorStateTypeId, "DC disconnect open");
|
||||
break;
|
||||
case SunSpec::SunSpecEvent1::DcOverVolatage:
|
||||
} else if (inverterData.event1.dcOverVoltage) {
|
||||
thing->setStateValue(sunspecThreePhaseInverterErrorStateTypeId, "DC over voltage");
|
||||
break;
|
||||
case SunSpec::SunSpecEvent1::OVER_FREQUENCY:
|
||||
} else if (inverterData.event1.overFrequency) {
|
||||
thing->setStateValue(sunspecThreePhaseInverterErrorStateTypeId, "Frequency above limit");
|
||||
break;
|
||||
case SunSpec::SunSpecEvent1::GRID_DISCONNECT:
|
||||
} else if (inverterData.event1.gridDisconnect) {
|
||||
thing->setStateValue(sunspecThreePhaseInverterErrorStateTypeId, "Grid disconnect");
|
||||
break;
|
||||
case SunSpec::SunSpecEvent1::HW_TEST_FAILURE:
|
||||
} else if (inverterData.event1.hwTestFailure) {
|
||||
thing->setStateValue(sunspecThreePhaseInverterErrorStateTypeId, "Hardware test failure");
|
||||
break;
|
||||
case SunSpec::SunSpecEvent1::MANUAL_SHUTDOWN:
|
||||
} else if (inverterData.event1.manualShutdown) {
|
||||
thing->setStateValue(sunspecThreePhaseInverterErrorStateTypeId, "Manual shutdown");
|
||||
break;
|
||||
case SunSpec::SunSpecEvent1::UNDER_FREQUENCY:
|
||||
} else if (inverterData.event1.underFrequency) {
|
||||
thing->setStateValue(sunspecThreePhaseInverterErrorStateTypeId, "Frequency under limit");
|
||||
break;
|
||||
case SunSpec::SunSpecEvent1::BLOWN_STRING_FUSE:
|
||||
} else if (inverterData.event1.blownStringFuse) {
|
||||
thing->setStateValue(sunspecThreePhaseInverterErrorStateTypeId, "Blown string fuse on input");
|
||||
break;
|
||||
} else {
|
||||
thing->setStateValue(sunspecThreePhaseInverterErrorStateTypeId, "None");
|
||||
}
|
||||
}
|
||||
|
||||
@ -774,5 +780,34 @@ void IntegrationPluginSunSpec::onMeterDataReceived(const SunSpecMeter::MeterData
|
||||
if (!thing) {
|
||||
return;
|
||||
}
|
||||
|
||||
thing->setStateValue(m_connectedStateTypeIds.value(thing->thingClassId()), true);
|
||||
|
||||
qCDebug(dcSunSpec()) << "Meter data received";
|
||||
qCDebug(dcSunSpec()) << " - Total AC Current" << meterData.totalAcCurrent << "[A]";
|
||||
qCDebug(dcSunSpec()) << " - Phase A current" << meterData.phaseACurrent << "[A]";
|
||||
qCDebug(dcSunSpec()) << " - Phase B current" << meterData.phaseBCurrent << "[A]";
|
||||
qCDebug(dcSunSpec()) << " - Phase C current" << meterData.phaseCCurrent << "[A]";
|
||||
qCDebug(dcSunSpec()) << " - Voltage LN" << meterData.voltageLN << "[V]";
|
||||
qCDebug(dcSunSpec()) << " - Phase voltage AN" << meterData.phaseVoltageAN << "[V]";
|
||||
qCDebug(dcSunSpec()) << " - Phase voltage BN" << meterData.phaseVoltageBN << "[V]";
|
||||
qCDebug(dcSunSpec()) << " - Phase voltage CN" << meterData.phaseVoltageCN<< "[V]";
|
||||
qCDebug(dcSunSpec()) << " - Voltage LL" << meterData.voltageLL << "[V]";
|
||||
qCDebug(dcSunSpec()) << " - Phase voltage AB" << meterData.phaseVoltageAB << "[V]";
|
||||
qCDebug(dcSunSpec()) << " - Phase voltage BC" << meterData.phaseVoltageBC << "[V]";
|
||||
qCDebug(dcSunSpec()) << " - Phase voltage CA" << meterData.phaseVoltageCA<< "[V]";
|
||||
qCDebug(dcSunSpec()) << " - Frequency" << meterData.frequency << "[Hz]";
|
||||
qCDebug(dcSunSpec()) << " - Total real power" << meterData.totalRealPower << "[W]";
|
||||
qCDebug(dcSunSpec()) << " - Total real energy exported" << meterData.totalRealEnergyExported<< "[kWH]";
|
||||
qCDebug(dcSunSpec()) << " - Total real energy imported" << meterData.totalRealEnergyImported<< "[kWH]";
|
||||
|
||||
thing->setStateValue(sunspecThreePhaseMeterTotalCurrentStateTypeId, meterData.totalAcCurrent);
|
||||
thing->setStateValue(sunspecThreePhaseMeterPhaseACurrentStateTypeId, meterData.phaseACurrent);
|
||||
thing->setStateValue(sunspecThreePhaseMeterPhaseBCurrentStateTypeId, meterData.phaseBCurrent);
|
||||
thing->setStateValue(sunspecThreePhaseMeterPhaseCCurrentStateTypeId, meterData.phaseCCurrent);
|
||||
thing->setStateValue(sunspecThreePhaseMeterLnACVoltageStateTypeId, meterData.voltageLN);
|
||||
thing->setStateValue(sunspecThreePhaseMeterTotalRealPowerEventTypeId, meterData.totalRealPower);
|
||||
thing->setStateValue(sunspecThreePhaseMeterEnergyExportedStateTypeId, meterData.totalRealEnergyExported);
|
||||
thing->setStateValue(sunspecThreePhaseMeterEnergyImportedStateTypeId, meterData.totalRealEnergyImported);
|
||||
thing->setStateValue(m_frequencyStateTypeIds.value(thing->thingClassId()), meterData.frequency);
|
||||
}
|
||||
|
||||
@ -39,7 +39,6 @@
|
||||
#include "sunspecinverter.h"
|
||||
#include "sunspecstorage.h"
|
||||
#include "sunspecmeter.h"
|
||||
#include "sunspectracker.h"
|
||||
|
||||
#include <QUuid>
|
||||
|
||||
|
||||
@ -67,25 +67,6 @@ public:
|
||||
};
|
||||
Q_ENUM(SunSpecOperatingState)
|
||||
|
||||
enum SunSpecEvent1 {
|
||||
GroundFault = 0,
|
||||
DcOverVolatage,
|
||||
AC_DISCONNECT,
|
||||
DC_DISCONNECT,
|
||||
GRID_DISCONNECT,
|
||||
CABINET_OPEN,
|
||||
MANUAL_SHUTDOWN,
|
||||
OVER_TEMP,
|
||||
OVER_FREQUENCY,
|
||||
UNDER_FREQUENCY,
|
||||
AC_OVER_VOLT,
|
||||
AC_UNDER_VOLT,
|
||||
BLOWN_STRING_FUSE,
|
||||
UNDER_TEMP,
|
||||
MEMORY_LOSS,
|
||||
HW_TEST_FAILURE
|
||||
};
|
||||
Q_ENUM(SunSpecEvent1)
|
||||
|
||||
enum ModelId {
|
||||
ModelIdCommon = 1,
|
||||
|
||||
@ -73,46 +73,70 @@ void SunSpecInverter::getInverterModelDataBlock()
|
||||
m_connection->readModelDataBlock(m_modelModbusStartRegister, m_modelLength);
|
||||
}
|
||||
|
||||
SunSpecInverter::SunSpecEvent1 SunSpecInverter::bitfieldToSunSpecEvent1(quint16 register1, quint16 register2)
|
||||
{
|
||||
SunSpecEvent1 event1;
|
||||
Q_UNUSED(register2);
|
||||
event1.groundFault = ((register1 & (0x01 << 0)) != 0);
|
||||
event1.dcOverVoltage = ((register1 & (0x01 << 1)) != 0);
|
||||
event1.acDisconnect = ((register1 & (0x01 << 2)) != 0);
|
||||
event1.dcDicconnect = ((register1 & (0x01 << 3)) != 0);
|
||||
event1.gridDisconnect = ((register1 & (0x01 << 4)) != 0);
|
||||
event1.cabinetOpen = ((register1 & (0x01 << 5)) != 0);
|
||||
event1.manualShutdown = ((register1 & (0x01 << 6)) != 0);
|
||||
event1.overTemperature = ((register1 & (0x01 << 7)) != 0);
|
||||
event1.overFrequency = ((register1 & (0x01 << 8)) != 0);
|
||||
event1.underFrequency = ((register1 & (0x01 << 9)) != 0);
|
||||
event1.acOverVolt = ((register1 & (0x01 << 10)) != 0);
|
||||
event1.acUnderVolt = ((register1 & (0x01 << 11)) != 0);
|
||||
event1.blownStringFuse = ((register1 & (0x01 << 12)) != 0);
|
||||
event1.underTemperature = ((register1 & (0x01 << 13)) != 0);
|
||||
event1.memoryLoss = ((register1 & (0x01 << 14)) != 0);
|
||||
event1.hwTestFailure = ((register1 & (0x01 << 15)) != 0);
|
||||
return event1;
|
||||
}
|
||||
|
||||
void SunSpecInverter::getInverterModelHeader()
|
||||
{
|
||||
qCDebug(dcSunSpec()) << "SunSpecInverter: get inverter model header, modbus register" << m_modelModbusStartRegister;
|
||||
m_connection->readModelHeader(m_modelModbusStartRegister);
|
||||
}
|
||||
|
||||
void SunSpecInverter::onModelDataBlockReceived(SunSpec::ModelId mapId, uint mapLength, QVector<quint16> data)
|
||||
void SunSpecInverter::onModelDataBlockReceived(SunSpec::ModelId modelId, uint length, QVector<quint16> data)
|
||||
{
|
||||
Q_UNUSED(mapLength)
|
||||
if (mapId != m_id) {
|
||||
Q_UNUSED(length)
|
||||
if (modelId != m_id) {
|
||||
return;
|
||||
}
|
||||
if (mapLength < m_modelLength) {
|
||||
qCDebug(dcSunSpec()) << "SunSpecInverter: on modbus map received, map length is too short" << mapLength;
|
||||
//return;
|
||||
if (length < m_modelLength) {
|
||||
qCDebug(dcSunSpec()) << "SunSpecInverter: on model data block received, model length is too short" << length;
|
||||
return;
|
||||
}
|
||||
InverterData inverterData;
|
||||
|
||||
switch (mapId) {
|
||||
qCDebug(dcSunSpec()) << "SunSpecInverter: Received" << modelId;
|
||||
switch (modelId) {
|
||||
case SunSpec::ModelIdInverterSinglePhase:
|
||||
case SunSpec::ModelIdInverterSplitPhase:
|
||||
case SunSpec::ModelIdInverterThreePhase: {
|
||||
|
||||
inverterData.acCurrent= m_connection->convertValueWithSSF(data[Model10X::Model10XAcCurrent], data[Model10X::Model10XAmpereScaleFactor]);
|
||||
inverterData.acPower = m_connection->convertValueWithSSF(data[Model10X::Model10XACPower], data[Model10X::Model10XWattScaleFactor]);
|
||||
inverterData.lineFrequency = m_connection->convertValueWithSSF(data[Model10X::Model10XLineFrequency], data[Model10X::Model10XHerzScaleFactor]);
|
||||
|
||||
inverterData.phaseACurrent = m_connection->convertValueWithSSF(data[Model10X::Model10XPhaseACurrent], data[Model10X::Model10XAmpereScaleFactor]);
|
||||
inverterData.phaseBCurrent = m_connection->convertValueWithSSF(data[Model10X::Model10XPhaseBCurrent], data[Model10X::Model10XAmpereScaleFactor]);
|
||||
inverterData.phaseCCurrent = m_connection->convertValueWithSSF(data[Model10X::Model10XPhaseCCurrent], data[Model10X::Model10XAmpereScaleFactor]);
|
||||
|
||||
inverterData.phaseVoltageAN = m_connection->convertValueWithSSF(data[Model10X::Model10XPhaseVoltageAN], data[Model10X::Model10XVoltageScaleFactor]);
|
||||
inverterData.phaseVoltageBN = m_connection->convertValueWithSSF(data[Model10X::Model10XPhaseVoltageBN], data[Model10X::Model10XVoltageScaleFactor]);
|
||||
inverterData.phaseVoltageCN = m_connection->convertValueWithSSF(data[Model10X::Model10XPhaseVoltageCN], data[Model10X::Model10XVoltageScaleFactor]);
|
||||
quint16 ampereScaleFactor = data[Model10X::Model10XAmpereScaleFactor];
|
||||
inverterData.phaseACurrent = m_connection->convertValueWithSSF(data[Model10X::Model10XPhaseACurrent], ampereScaleFactor);
|
||||
inverterData.phaseBCurrent = m_connection->convertValueWithSSF(data[Model10X::Model10XPhaseBCurrent], ampereScaleFactor);
|
||||
inverterData.phaseCCurrent = m_connection->convertValueWithSSF(data[Model10X::Model10XPhaseCCurrent], ampereScaleFactor);
|
||||
quint16 voltageScaleFactor = data[Model10X::Model10XVoltageScaleFactor];
|
||||
inverterData.phaseVoltageAN = m_connection->convertValueWithSSF(data[Model10X::Model10XPhaseVoltageAN], voltageScaleFactor);
|
||||
inverterData.phaseVoltageBN = m_connection->convertValueWithSSF(data[Model10X::Model10XPhaseVoltageBN], voltageScaleFactor);
|
||||
inverterData.phaseVoltageCN = m_connection->convertValueWithSSF(data[Model10X::Model10XPhaseVoltageCN], voltageScaleFactor);
|
||||
|
||||
quint32 acEnergy = ((static_cast<quint32>(data.value(Model10X::Model10XAcEnergy))<<16)|static_cast<quint32>(data.value(Model10X::Model10XAcEnergy+1)));
|
||||
inverterData.acEnergy = m_connection->convertValueWithSSF(acEnergy, data[Model10X::Model10XWattHoursScaleFactor]);
|
||||
|
||||
inverterData.cabinetTemperature = m_connection->convertValueWithSSF(data[Model10X::Model10XCabinetTemperature], data[Model10X::Model10XTemperatureScaleFactor]);
|
||||
inverterData.event = SunSpec::SunSpecEvent1(data[Model10X::Model10XEvent1]);
|
||||
inverterData.event1 = bitfieldToSunSpecEvent1(data[Model10X::Model10XEvent1], data[Model10X::Model10XEvent1+1]);
|
||||
inverterData.operatingState = SunSpec::SunSpecOperatingState(data[Model10X::Model10XOperatingState]);
|
||||
emit inverterDataReceived(inverterData);
|
||||
|
||||
@ -123,21 +147,20 @@ void SunSpecInverter::onModelDataBlockReceived(SunSpec::ModelId mapId, uint mapL
|
||||
|
||||
inverterData.acCurrent = m_connection->convertFloatValues(data[Model11X::Model11XAcCurrent], data[Model11X::Model11XAcCurrent+1]);
|
||||
|
||||
inverterData.phaseCCurrent = m_connection->convertFloatValues(data[Model11X::Model11XPhaseCCurrent], data[Model11X::Model11XPhaseCCurrent+1]);
|
||||
inverterData.phaseVoltageAN = m_connection->convertFloatValues(data[Model11X::Model11XPhaseVoltageAN], data[Model11X::Model11XPhaseVoltageAN+1]);
|
||||
inverterData.phaseVoltageBN = m_connection->convertFloatValues(data[Model11X::Model11XPhaseVoltageBN], data[Model11X::Model11XPhaseVoltageBN+1]);
|
||||
inverterData.phaseVoltageCN = m_connection->convertFloatValues(data[Model11X::Model11XPhaseVoltageCN], data[Model11X::Model11XPhaseVoltageCN+1]);
|
||||
|
||||
inverterData.phaseBCurrent = m_connection->convertFloatValues(data[Model11X::Model11XPhaseBCurrent], data[Model11X::Model11XPhaseBCurrent+1]);
|
||||
inverterData.phaseVoltageBN = m_connection->convertFloatValues(data[Model11X::Model11XPhaseVoltageBN], data[Model11X::Model11XPhaseVoltageBN+1]);
|
||||
inverterData.phaseACurrent = m_connection->convertFloatValues(data[Model11X::Model11XPhaseACurrent], data[Model11X::Model11XPhaseACurrent+1]);
|
||||
inverterData.phaseBCurrent = m_connection->convertFloatValues(data[Model11X::Model11XPhaseBCurrent], data[Model11X::Model11XPhaseBCurrent+1]);
|
||||
inverterData.phaseCCurrent = m_connection->convertFloatValues(data[Model11X::Model11XPhaseCCurrent], data[Model11X::Model11XPhaseCCurrent+1]);
|
||||
|
||||
inverterData.phaseACurrent = m_connection->convertFloatValues(data[Model11X::Model11XPhaseACurrent], data[Model11X::Model11XPhaseACurrent+1]);
|
||||
inverterData.phaseVoltageAN = m_connection->convertFloatValues(data[Model11X::Model11XPhaseVoltageAN], data[Model11X::Model11XPhaseVoltageAN+1]);
|
||||
inverterData.acPower = m_connection->convertFloatValues(data[Model11X::Model11XACPower], data[Model11X::Model11XACPower+1]);
|
||||
inverterData.lineFrequency = m_connection->convertFloatValues(data[Model11X::Model11XLineFrequency], data[Model11X::Model11XLineFrequency+1]);
|
||||
|
||||
inverterData.acPower = m_connection->convertFloatValues(data[Model11X::Model11XACPower], data[Model11X::Model11XACPower+1]);
|
||||
inverterData.lineFrequency = m_connection->convertFloatValues(data[Model11X::Model11XLineFrequency], data[Model11X::Model11XLineFrequency+1]);
|
||||
|
||||
inverterData.acEnergy = m_connection->convertFloatValues(data[Model11X::Model11XAcEnergy], data[Model11X::Model11XAcEnergy+1]);
|
||||
inverterData.cabinetTemperature =m_connection->convertFloatValues(data[Model11X::Model11XCabinetTemperature], data[Model11X::Model11XCabinetTemperature+1]);
|
||||
inverterData.event = SunSpec::SunSpecEvent1(data[Model11X::Model11XEvent1]);
|
||||
inverterData.acEnergy = m_connection->convertFloatValues(data[Model11X::Model11XAcEnergy], data[Model11X::Model11XAcEnergy+1]);
|
||||
inverterData.cabinetTemperature = m_connection->convertFloatValues(data[Model11X::Model11XCabinetTemperature], data[Model11X::Model11XCabinetTemperature+1]);
|
||||
inverterData.event1 = bitfieldToSunSpecEvent1(data[Model11X::Model11XEvent1], data[Model11X::Model11XEvent1+1]);
|
||||
inverterData.operatingState = SunSpec::SunSpecOperatingState(data[Model11X::Model11XOperatingState]);
|
||||
emit inverterDataReceived(inverterData);
|
||||
} break;
|
||||
|
||||
@ -77,6 +77,71 @@ public:
|
||||
Model11XEvent1 = 48
|
||||
};
|
||||
|
||||
enum Model10XOptional { // Optional register
|
||||
Model10XPhaseVoltageAB = 5,
|
||||
Model10XPhaseVoltageBC = 6,
|
||||
Model10XPhaseVoltageCA = 7,
|
||||
Model10XACApparentPower = 16,
|
||||
Model10XACApparentPowerSF = 17,
|
||||
Model10XACReactivePower = 18,
|
||||
Model10XACReactivePowerSF = 19,
|
||||
Model10XACPowerFactor = 20,
|
||||
Model10XACPowerFactorSF = 21,
|
||||
Model10XDCCurrent = 25,
|
||||
Model10XDCCurrentSF = 26,
|
||||
Model10XDCVoltage = 27,
|
||||
Model10XDCVoltageSF = 28,
|
||||
Model10XDCPower = 29,
|
||||
Model10XDCPowerSF = 30,
|
||||
Model10XHeatSinkTemperature = 32,
|
||||
Model10XTransformerTemperature = 33,
|
||||
Model10XOtherTemperature = 34,
|
||||
Model10XVendorOperatingState = 37,
|
||||
Model10XVendorEventBitfield1 = 42,
|
||||
Model10XVendorEventBitfield2 = 44,
|
||||
Model10XVendorEventBitfield3 = 46,
|
||||
Model10XVendorEventBitfield4 = 48
|
||||
};
|
||||
|
||||
enum Model11XOptional { // Optinal registers
|
||||
Model11XPhaseVoltageAB = 8,
|
||||
Model11XPhaseVoltageBC = 10,
|
||||
Model11XPhaseVoltageCA = 12,
|
||||
Model11XACApparentPower = 24,
|
||||
Model11XACReactivePower = 26,
|
||||
Model11XACPowerFactor = 28,
|
||||
Model11XDCCurrent = 32,
|
||||
Model11XDCVoltage = 34,
|
||||
Model11XDCPower = 36,
|
||||
Model11XHeatSinkTemperature = 40,
|
||||
Model11XTransformerTemperature = 42,
|
||||
Model11XOtherTemperature = 44,
|
||||
Model11XVendorOperatingState = 47,
|
||||
Model11XVendorEventBitfield1 = 52,
|
||||
Model11XVendorEventBitfield2 = 54,
|
||||
Model11XVendorEventBitfield3 = 56,
|
||||
Model11XVendorEventBitfield4 = 58
|
||||
};
|
||||
|
||||
struct SunSpecEvent1 {
|
||||
bool groundFault;
|
||||
bool dcOverVoltage;
|
||||
bool acDisconnect;
|
||||
bool dcDicconnect;
|
||||
bool gridDisconnect;
|
||||
bool cabinetOpen;
|
||||
bool manualShutdown;
|
||||
bool overTemperature;
|
||||
bool overFrequency;
|
||||
bool underFrequency;
|
||||
bool acOverVolt;
|
||||
bool acUnderVolt;
|
||||
bool blownStringFuse;
|
||||
bool underTemperature;
|
||||
bool memoryLoss;
|
||||
bool hwTestFailure;
|
||||
};
|
||||
|
||||
struct InverterData {
|
||||
float acCurrent; //in ampere
|
||||
float phaseACurrent;
|
||||
@ -92,7 +157,7 @@ public:
|
||||
float lineFrequency;
|
||||
float acEnergy;
|
||||
float cabinetTemperature; // in degree Celsius
|
||||
SunSpec::SunSpecEvent1 event;
|
||||
SunSpecEvent1 event1;
|
||||
SunSpec::SunSpecOperatingState operatingState;
|
||||
};
|
||||
|
||||
@ -108,6 +173,7 @@ private:
|
||||
uint m_modelModbusStartRegister = 40000;
|
||||
bool m_initFinishedSuccess = false;
|
||||
|
||||
SunSpecEvent1 bitfieldToSunSpecEvent1(quint16 register1, quint16 register2);
|
||||
void getInverterModelHeader();
|
||||
|
||||
private slots:
|
||||
|
||||
@ -83,20 +83,67 @@ void SunSpecMeter::onModelDataBlockReceived(SunSpec::ModelId modelId, uint lengt
|
||||
if (modelId != m_id) {
|
||||
return;
|
||||
}
|
||||
Q_UNUSED(length)
|
||||
Q_UNUSED(data)
|
||||
|
||||
if (length < m_modelLength) {
|
||||
qCDebug(dcSunSpec()) << "SunSpecMeter: on model data block received, model length is too short" << length;
|
||||
return;
|
||||
}
|
||||
|
||||
qCDebug(dcSunSpec()) << "SunSpecMeter: Received" << modelId;
|
||||
switch (modelId) {
|
||||
|
||||
case SunSpec::ModelIdSinglePhaseMeter:
|
||||
case SunSpec::ModelIdSinglePhaseMeterFloat: {
|
||||
|
||||
} break;
|
||||
case SunSpec::ModelIdSplitSinglePhaseMeter:
|
||||
case SunSpec::ModelIdSplitSinglePhaseMeterFloat: {
|
||||
case SunSpec::ModelIdDeltaConnectThreePhaseMeter:
|
||||
case SunSpec::ModelIdWyeConnectThreePhaseMeter: {
|
||||
|
||||
MeterData meterData;
|
||||
quint16 currentScaleFactor = data[Model20XCurrentScaleFactor];
|
||||
meterData.totalAcCurrent = m_connection->convertValueWithSSF(data[Model20XTotalAcCurrent], currentScaleFactor);
|
||||
meterData.phaseACurrent = m_connection->convertValueWithSSF(data[Model20XPhaseACurrent], currentScaleFactor);
|
||||
meterData.phaseBCurrent = m_connection->convertValueWithSSF(data[Model20XPhaseBCurrent], currentScaleFactor);
|
||||
meterData.phaseCCurrent = m_connection->convertValueWithSSF(data[Model20XPhaseCCurrent], currentScaleFactor);
|
||||
quint16 voltageScaleFactor = data[Model20XVoltageScaleFactor];
|
||||
meterData.voltageLN = m_connection->convertValueWithSSF(data[Model20XVoltageLN], voltageScaleFactor);
|
||||
meterData.phaseVoltageAN = m_connection->convertValueWithSSF(data[Model20XPhaseVoltageAN], voltageScaleFactor);
|
||||
meterData.phaseVoltageBN = m_connection->convertValueWithSSF(data[Model20XPhaseVoltageBN], voltageScaleFactor);
|
||||
meterData.phaseVoltageCN = m_connection->convertValueWithSSF(data[Model20XPhaseVoltageCN], voltageScaleFactor);
|
||||
meterData.voltageLL = m_connection->convertValueWithSSF(data[Model20XVoltageLL], voltageScaleFactor);
|
||||
meterData.phaseVoltageAB = m_connection->convertValueWithSSF(data[Model20XPhaseVoltageAB], voltageScaleFactor);
|
||||
meterData.phaseVoltageBC = m_connection->convertValueWithSSF(data[Model20XPhaseVoltageBC], voltageScaleFactor);
|
||||
meterData.phaseVoltageCA = m_connection->convertValueWithSSF(data[Model20XPhaseVoltageCA], voltageScaleFactor);
|
||||
meterData.frequency = m_connection->convertValueWithSSF(data[Model20XFrequency], data[Model20XFrequencyScaleFactor]);
|
||||
meterData.totalRealPower = m_connection->convertValueWithSSF(data[Model20XTotalRealPower], data[Model20XRealPowerScaleFactor]);
|
||||
quint16 energyScaleFactor = data[Model20XRealEnergyScaleFactor];
|
||||
meterData.totalRealEnergyExported = m_connection->convertValueWithSSF(data[Model20XTotalRealEnergyExported], energyScaleFactor);
|
||||
meterData.totalRealEnergyImported = m_connection->convertValueWithSSF(data[Model20XTotalRealEnergyImported], energyScaleFactor);;
|
||||
meterData.meterEventFlags = (static_cast<quint32>(data[Model20XMeterEventFlags]) << 16) | data[Model20XMeterEventFlags+1];
|
||||
emit meterDataReceived(meterData);
|
||||
|
||||
} break;
|
||||
case SunSpec::ModelIdWyeConnectThreePhaseMeterFloat:
|
||||
case SunSpec::ModelIdDeltaConnectThreePhaseMeterFloat: {
|
||||
case SunSpec::ModelIdSinglePhaseMeterFloat:
|
||||
case SunSpec::ModelIdSplitSinglePhaseMeterFloat:
|
||||
case SunSpec::ModelIdDeltaConnectThreePhaseMeterFloat:
|
||||
case SunSpec::ModelIdWyeConnectThreePhaseMeterFloat: {
|
||||
|
||||
MeterData meterData;
|
||||
meterData.totalAcCurrent = m_connection->convertFloatValues(data[Model21XTotalAcCurrent], data[Model21XTotalAcCurrent+1]);
|
||||
meterData.phaseACurrent = m_connection->convertFloatValues(data[Model21XPhaseACurrent], data[Model21XPhaseACurrent+1]);
|
||||
meterData.phaseBCurrent = m_connection->convertFloatValues(data[Model21XPhaseBCurrent], data[Model21XPhaseBCurrent+1]);
|
||||
meterData.phaseCCurrent = m_connection->convertFloatValues(data[Model21XPhaseCCurrent], data[Model21XPhaseCCurrent+1]);
|
||||
meterData.voltageLN = m_connection->convertFloatValues(data[Model21XVoltageLN], data[Model21XVoltageLN+1]);
|
||||
meterData.phaseVoltageAN = m_connection->convertFloatValues(data[Model21XPhaseVoltageAN], data[Model21XPhaseVoltageAN+1]);
|
||||
meterData.phaseVoltageBN = m_connection->convertFloatValues(data[Model21XPhaseVoltageBN], data[Model21XPhaseVoltageBN+1]);
|
||||
meterData.phaseVoltageCN = m_connection->convertFloatValues(data[Model21XPhaseVoltageCN], data[Model21XPhaseVoltageCN+1]);
|
||||
meterData.voltageLL = m_connection->convertFloatValues(data[Model21XVoltageLL], data[Model21XVoltageLL+1]);
|
||||
meterData.phaseVoltageAB = m_connection->convertFloatValues(data[Model21XPhaseVoltageAB], data[Model21XPhaseVoltageAB+1]);
|
||||
meterData.phaseVoltageBC = m_connection->convertFloatValues(data[Model21XPhaseVoltageBC], data[Model21XPhaseVoltageBC+1]);
|
||||
meterData.phaseVoltageCA = m_connection->convertFloatValues(data[Model21XPhaseVoltageCA], data[Model21XPhaseVoltageCA+1]);
|
||||
meterData.frequency = m_connection->convertFloatValues(data[Model21XFrequency], data[Model21XFrequency+1]);
|
||||
meterData.totalRealPower = m_connection->convertFloatValues(data[Model21XTotalRealPower], data[Model21XTotalRealPower+1]);
|
||||
meterData.totalRealEnergyExported = m_connection->convertFloatValues(data[Model21XTotalRealEnergyExported], data[Model21XTotalRealEnergyExported+1]);
|
||||
meterData.totalRealEnergyImported = m_connection->convertFloatValues(data[Model21XTotalRealEnergyImported], data[Model21XTotalRealEnergyImported+1]);
|
||||
meterData.meterEventFlags = ((static_cast<quint32>(data[Model21XMeterEventFlags]) << 16) | data[Model21XMeterEventFlags+1]);
|
||||
emit meterDataReceived(meterData);
|
||||
|
||||
} break;
|
||||
default:
|
||||
|
||||
@ -38,34 +38,109 @@ class SunSpecMeter : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
//Model 203 = Three phase meter
|
||||
enum MandatoryRegistersModel20X {
|
||||
TotalAcCurrent = 2,
|
||||
PhaseACurrent = 3,
|
||||
PhaseBCurrent = 4,
|
||||
PhaseCCurrent = 5,
|
||||
CurrentScaleFactor = 6,
|
||||
VoltageLN = 7,
|
||||
PhaseVoltageAN = 8,
|
||||
PhaseVoltageBN = 9,
|
||||
PhaseVoltageCN = 10,
|
||||
VoltageLL = 11,
|
||||
PhaseVoltageAB = 12,
|
||||
PhaseVoltageBC = 13,
|
||||
PhaseVoltageCA = 14,
|
||||
VoltageScaleFactor = 15,
|
||||
Frequency = 16,
|
||||
TotalRealPower = 18,
|
||||
RealPowerScaleFactor = 22,
|
||||
TotalRealEnergyExported = 38,
|
||||
TotalRealEnergyImported = 46,
|
||||
RealEnergyScaleFactor = 54,
|
||||
MeterEventFlags = 105
|
||||
|
||||
enum MeterEventFlags {
|
||||
MeterEventPowerFailure = 2,
|
||||
MeterEventUnderVoltage,
|
||||
MeterEventLowPF,
|
||||
MeterEventOverCurrent,
|
||||
MeterEventOverVoltage,
|
||||
MeterEventMissing_Sensor,
|
||||
MeterEventReserved1,
|
||||
MeterEventReserved2,
|
||||
MeterEventReserved3,
|
||||
MeterEventReserved4,
|
||||
MeterEventReserved5,
|
||||
MeterEventReserved6,
|
||||
MeterEventReserved7,
|
||||
MeterEventReserved8,
|
||||
MeterEventOEM01,
|
||||
MeterEventOEM02,
|
||||
MeterEventOEM03,
|
||||
MeterEventOEM04,
|
||||
MeterEventOEM05,
|
||||
MeterEventOEM06,
|
||||
MeterEventOEM07,
|
||||
MeterEventOEM08,
|
||||
MeterEventOEM09,
|
||||
MeterEventOEM10,
|
||||
MeterEventOEM11,
|
||||
MeterEventOEM12,
|
||||
MeterEventOEM13,
|
||||
MeterEventOEM14,
|
||||
MeterEventOEM15
|
||||
};
|
||||
|
||||
//Model 201 = Single phase meter SF
|
||||
//Model 202 = Split phase meter SF
|
||||
//Model 203 = Three phase meter SF
|
||||
//Note: For example single phase inverters, Phase B current is optional then.
|
||||
enum Model20X {
|
||||
Model20XTotalAcCurrent = 0,
|
||||
Model20XPhaseACurrent = 1,
|
||||
Model20XPhaseBCurrent = 2,
|
||||
Model20XPhaseCCurrent = 3,
|
||||
Model20XCurrentScaleFactor = 4,
|
||||
Model20XVoltageLN = 5,
|
||||
Model20XPhaseVoltageAN = 6,
|
||||
Model20XPhaseVoltageBN = 7,
|
||||
Model20XPhaseVoltageCN = 8,
|
||||
Model20XVoltageLL = 9,
|
||||
Model20XPhaseVoltageAB = 10,
|
||||
Model20XPhaseVoltageBC = 11,
|
||||
Model20XPhaseVoltageCA = 12,
|
||||
Model20XVoltageScaleFactor = 13,
|
||||
Model20XFrequency = 14,
|
||||
Model20XFrequencyScaleFactor = 15,
|
||||
Model20XTotalRealPower = 16,
|
||||
Model20XRealPowerScaleFactor = 20,
|
||||
Model20XTotalRealEnergyExported = 36,
|
||||
Model20XTotalRealEnergyImported = 44,
|
||||
Model20XRealEnergyScaleFactor = 52,
|
||||
Model20XMeterEventFlags = 103
|
||||
};
|
||||
|
||||
//Model 211 = Single phase meter float
|
||||
//Model 212 = Split phase meter float
|
||||
//Model 213 = Three phase meter float
|
||||
enum Model21X {
|
||||
Model21XTotalAcCurrent = 0,
|
||||
Model21XPhaseACurrent = 2,
|
||||
Model21XPhaseBCurrent = 4,
|
||||
Model21XPhaseCCurrent = 6,
|
||||
Model21XVoltageLN = 8,
|
||||
Model21XPhaseVoltageAN = 10,
|
||||
Model21XPhaseVoltageBN = 12,
|
||||
Model21XPhaseVoltageCN = 14,
|
||||
Model21XVoltageLL = 16,
|
||||
Model21XPhaseVoltageAB = 18,
|
||||
Model21XPhaseVoltageBC = 20,
|
||||
Model21XPhaseVoltageCA = 22,
|
||||
Model21XFrequency = 24,
|
||||
Model21XTotalRealPower = 26,
|
||||
Model21XTotalRealEnergyExported = 58,
|
||||
Model21XTotalRealEnergyImported = 66,
|
||||
Model21XMeterEventFlags = 122
|
||||
};
|
||||
|
||||
struct MeterData {
|
||||
SunSpec::SunSpecEvent1 event;
|
||||
SunSpec::SunSpecOperatingState operatingState;
|
||||
double totalAcCurrent; // [A]
|
||||
double phaseACurrent; // [A]
|
||||
double phaseBCurrent; // [A]
|
||||
double phaseCCurrent; // [A]
|
||||
double voltageLN; // [V]
|
||||
double phaseVoltageAN; // [V]
|
||||
double phaseVoltageBN; // [V]
|
||||
double phaseVoltageCN; // [V]
|
||||
double voltageLL; // [V]
|
||||
double phaseVoltageAB; // [V]
|
||||
double phaseVoltageBC; // [V]
|
||||
double phaseVoltageCA; // [V]
|
||||
double frequency; // [Hz]
|
||||
double totalRealPower; // [W]
|
||||
double totalRealEnergyExported; // [kWh]
|
||||
double totalRealEnergyImported; // [kWh]
|
||||
quint32 meterEventFlags; // MeterEventFlags
|
||||
};
|
||||
|
||||
SunSpecMeter(SunSpec *sunspec, SunSpec::ModelId modelId, int modbusAddress);
|
||||
|
||||
@ -121,15 +121,19 @@ QUuid SunSpecStorage::setDischargingRate(int charging)
|
||||
|
||||
void SunSpecStorage::onModelDataBlockReceived(SunSpec::ModelId modelId, uint length, const QVector<quint16> &data)
|
||||
{
|
||||
Q_UNUSED(length)
|
||||
if (modelId != m_id) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (length < m_modelLength) {
|
||||
qCDebug(dcSunSpec()) << "SunSpecMeter: on model data block received, model length is too short" << length;
|
||||
//return;
|
||||
}
|
||||
|
||||
qCDebug(dcSunSpec()) << "SunSpecStorage: Received" << modelId;
|
||||
switch (modelId) {
|
||||
case SunSpec::ModelIdStorage: {
|
||||
StorageData mandatory;
|
||||
qCDebug(dcSunSpec()) << "SunSpecStorage: Storage model received:";
|
||||
qCDebug(dcSunSpec()) << " - Setpoint maximum charge" << data[Model124SetpointMaximumCharge];
|
||||
qCDebug(dcSunSpec()) << " - Setpoint maximum charging rate" << data[Model124SetpointMaximumChargingRate];
|
||||
qCDebug(dcSunSpec()) << " - Setpoint maximum discharge rate" << data[Model124SetpointMaximumDischargeRate];
|
||||
@ -150,9 +154,6 @@ void SunSpecStorage::onModelDataBlockReceived(SunSpec::ModelId modelId, uint len
|
||||
optional.storageAvailable = m_connection->convertValueWithSSF(data[Model124StorageAvailableAH], data[Model124ScaleFactorMaximumChargingVA]);
|
||||
optional.gridChargingEnabled = (data[Model124ChargeGridSet] == 1);
|
||||
optional.currentlyAvailableEnergy = m_connection->convertValueWithSSF(data[Model124CurrentlyAvailableEnergyPercent], data[Model124ScaleFactorAvailableEnergyPercent]);
|
||||
//qCDebug(dcSunSpec()) << " - Currently available energy" << data[Model124CurrentlyAvailableEnergy];
|
||||
//mandatory.chargingState = ChargingStatus(data[Model124ChargeStatus]);
|
||||
//qCDebug(dcSunSpec()) << " - Charging state" << mandatory.chargingState;
|
||||
|
||||
emit storageDataReceived(mandatory, optional);
|
||||
|
||||
|
||||
@ -1,90 +0,0 @@
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
*
|
||||
* Copyright 2013 - 2020, nymea GmbH
|
||||
* Contact: contact@nymea.io
|
||||
*
|
||||
* This file is part of nymea.
|
||||
* This project including source code and documentation is protected by
|
||||
* copyright law, and remains the property of nymea GmbH. All rights, including
|
||||
* reproduction, publication, editing and translation, are reserved. The use of
|
||||
* this project is subject to the terms of a license agreement to be concluded
|
||||
* with nymea GmbH in accordance with the terms of use of nymea GmbH, available
|
||||
* under https://nymea.io/license
|
||||
*
|
||||
* GNU Lesser General Public License Usage
|
||||
* Alternatively, this project may be redistributed and/or modified under the
|
||||
* terms of the GNU Lesser General Public License as published by the Free
|
||||
* Software Foundation; version 3. This project is distributed in the hope that
|
||||
* it will be useful, but WITHOUT ANY WARRANTY; without even the implied
|
||||
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this project. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* For any further details and any questions please contact us under
|
||||
* contact@nymea.io or see our FAQ/Licensing Information on
|
||||
* https://nymea.io/license/faq
|
||||
*
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
|
||||
#include "sunspecstringcombiner.h"
|
||||
#include "extern-plugininfo.h"
|
||||
|
||||
SunSpecStringCombiner::SunSpecStringCombiner(const QHostAddress &hostAddress, uint port, QObject *parent) : SunSpec(hostAddress, port, parent)
|
||||
{
|
||||
connect(m_modbusTcpClient, &QModbusClient::stateChanged, this, [this] (QModbusDevice::State state) {
|
||||
if (state == QModbusDevice::ConnectedState) {
|
||||
qCDebug(dcSunSpec()) << "String combiner connected successfully";
|
||||
QList<BlockId> mapIds;
|
||||
mapIds.append(BlockIdStringCombiner);
|
||||
mapIds.append(BlockIdStringCombinerCurrent);
|
||||
mapIds.append(BlockIdStringCombinerAdvanced);
|
||||
mapIds.append(BlockIdStringCombinerCurrentAdvanced);
|
||||
findModbusMap(mapIds);
|
||||
}
|
||||
});
|
||||
connect(this, &SunSpec::foundModbusMap, this, [this] (BlockId mapId, uint modbusRegisterAddress) {
|
||||
qCDebug(dcSunSpec()) << "Read map header for mapId" << mapId << "and modbus register" << modbusRegisterAddress;
|
||||
readMapHeader(modbusRegisterAddress);
|
||||
});
|
||||
|
||||
connect(this, &SunSpec::mapHeaderReceived, this, [this] (uint modbusAddress, BlockId mapId, uint mapLength) {
|
||||
m_id = mapId;
|
||||
m_mapLength = mapLength;
|
||||
m_mapModbusStartRegister = modbusAddress;
|
||||
readMap(modbusAddress, mapLength);
|
||||
});
|
||||
|
||||
connect(this, &SunSpec::mapReceived, this, &SunSpecStringCombiner::onModbusMapReceived);
|
||||
}
|
||||
|
||||
void SunSpecStringCombiner::getStringCombinerMap()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void SunSpecStringCombiner::readStringCombinerMapHeader()
|
||||
{
|
||||
readMap(m_mapModbusStartRegister, m_mapLength);
|
||||
}
|
||||
|
||||
void SunSpecStringCombiner::onModbusMapReceived(SunSpec::BlockId mapId, uint mapLength, QVector<quint16> data)
|
||||
{
|
||||
Q_UNUSED(data);
|
||||
|
||||
switch (mapId) {
|
||||
case BlockIdStringCombiner: {
|
||||
int rbCount = (mapLength-14)/8;
|
||||
qCDebug(dcSunSpec()) << "Map" << mapId << "Repeating Block Count" << rbCount;
|
||||
} break;
|
||||
case BlockIdStringCombinerCurrent:
|
||||
case BlockIdStringCombinerAdvanced:
|
||||
case BlockIdStringCombinerCurrentAdvanced: {
|
||||
//StringCombinerData stringCombinerData;
|
||||
//stringCombinerData.acCurrent= convertValueWithSSF(data[Model10X::Model10XAcCurrent], data[Model10X::Model10XAmpereScaleFactor]);
|
||||
} break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -1,128 +0,0 @@
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
*
|
||||
* Copyright 2013 - 2020, nymea GmbH
|
||||
* Contact: contact@nymea.io
|
||||
*
|
||||
* This file is part of nymea.
|
||||
* This project including source code and documentation is protected by
|
||||
* copyright law, and remains the property of nymea GmbH. All rights, including
|
||||
* reproduction, publication, editing and translation, are reserved. The use of
|
||||
* this project is subject to the terms of a license agreement to be concluded
|
||||
* with nymea GmbH in accordance with the terms of use of nymea GmbH, available
|
||||
* under https://nymea.io/license
|
||||
*
|
||||
* GNU Lesser General Public License Usage
|
||||
* Alternatively, this project may be redistributed and/or modified under the
|
||||
* terms of the GNU Lesser General Public License as published by the Free
|
||||
* Software Foundation; version 3. This project is distributed in the hope that
|
||||
* it will be useful, but WITHOUT ANY WARRANTY; without even the implied
|
||||
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this project. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* For any further details and any questions please contact us under
|
||||
* contact@nymea.io or see our FAQ/Licensing Information on
|
||||
* https://nymea.io/license/faq
|
||||
*
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
|
||||
#ifndef SUNSPECSTRINGCOMBINER_H
|
||||
#define SUNSPECSTRINGCOMBINER_H
|
||||
|
||||
#include <QObject>
|
||||
#include "sunspec.h"
|
||||
|
||||
class SunSpecStringCombiner : public SunSpec
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
|
||||
//Map401 length: 14 + (RB Count * 8)
|
||||
//Map403 length: 16 + (RB Count * 8)
|
||||
enum Map401 {
|
||||
Map401CurrentScaleFactor = 0,
|
||||
Map401AmpHourScaleFactor = 1,
|
||||
Map401VoltageScaleFactor = 2,
|
||||
Map401MaximumDCCurrentRating = 3,
|
||||
Map401NumberOfInputs = 4,
|
||||
Map401Events = 5,
|
||||
Map401VendorDefniedEvents = 7,
|
||||
Map401TotalMeasuredCurrent = 9,
|
||||
Map401TotalMeteredAmpHours = 10,
|
||||
Map401OutputVoltage = 12,
|
||||
Map401InternalOperatingTemperature = 13
|
||||
};
|
||||
|
||||
enum Map402 {
|
||||
Map402CurrentScaleFactor,
|
||||
Map402AmpHourScaleFactor,
|
||||
Map402VoltageScaleFactor,
|
||||
Map402PowerScaleFactor,
|
||||
Map402EnergyScaleFactor,
|
||||
Map402MaximumDCCurrentRating,
|
||||
Map402NumberOfInputs,
|
||||
Map402BitmaskValueEvents,
|
||||
Map402BitmaskvalueVendorDefniedEvents,
|
||||
Map402TotalMeasuredCurrent,
|
||||
Map402TotalMeteredAmpHours,
|
||||
Map402OutputVoltage
|
||||
};
|
||||
|
||||
enum Map401RB { //Repeating block
|
||||
ID = 0,
|
||||
Event = 1,
|
||||
VendorEvent = 3,
|
||||
Amps = 5,
|
||||
AmpHours = 6
|
||||
};
|
||||
|
||||
enum StringCombinerEvent {
|
||||
LowVoltage = 0,
|
||||
LowPower,
|
||||
LowEfficiency,
|
||||
Current,
|
||||
Voltage,
|
||||
Power,
|
||||
Pr,
|
||||
Disconnected,
|
||||
FuseFault,
|
||||
CombinerFuseFault,
|
||||
CombinerCabinetOpen,
|
||||
Temp,
|
||||
Groundfault,
|
||||
ReversedPolarity,
|
||||
Incompatible,
|
||||
CommunicationError,
|
||||
InternalError,
|
||||
Theft,
|
||||
ArcDetected
|
||||
};
|
||||
Q_ENUM(StringCombinerEvent)
|
||||
|
||||
struct StringCombinerData {
|
||||
SunSpecEvent1 event;
|
||||
SunSpecOperatingState operatingState;
|
||||
};
|
||||
|
||||
SunSpecStringCombiner(const QHostAddress &hostAddress, uint port = 502, QObject *parent = 0);
|
||||
|
||||
void getStringCombinerMap();
|
||||
|
||||
private:
|
||||
BlockId m_id = BlockIdStringCombiner;
|
||||
uint m_mapLength = 0;
|
||||
uint m_mapModbusStartRegister = 40000;
|
||||
|
||||
void readStringCombinerMapHeader();
|
||||
|
||||
private slots:
|
||||
void onModbusMapReceived(BlockId mapId, uint mapLength, QVector<quint16> data);
|
||||
|
||||
signals:
|
||||
void initFinished();
|
||||
void stringCombinerDataReceived(const StringCombinerData &data);
|
||||
};
|
||||
|
||||
#endif // SUNSPECSTRINGCOMBINER_H
|
||||
@ -1,42 +0,0 @@
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
*
|
||||
* Copyright 2013 - 2020, nymea GmbH
|
||||
* Contact: contact@nymea.io
|
||||
*
|
||||
* This file is part of nymea.
|
||||
* This project including source code and documentation is protected by
|
||||
* copyright law, and remains the property of nymea GmbH. All rights, including
|
||||
* reproduction, publication, editing and translation, are reserved. The use of
|
||||
* this project is subject to the terms of a license agreement to be concluded
|
||||
* with nymea GmbH in accordance with the terms of use of nymea GmbH, available
|
||||
* under https://nymea.io/license
|
||||
*
|
||||
* GNU Lesser General Public License Usage
|
||||
* Alternatively, this project may be redistributed and/or modified under the
|
||||
* terms of the GNU Lesser General Public License as published by the Free
|
||||
* Software Foundation; version 3. This project is distributed in the hope that
|
||||
* it will be useful, but WITHOUT ANY WARRANTY; without even the implied
|
||||
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this project. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* For any further details and any questions please contact us under
|
||||
* contact@nymea.io or see our FAQ/Licensing Information on
|
||||
* https://nymea.io/license/faq
|
||||
*
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
|
||||
#include "sunspectracker.h"
|
||||
#include "extern-plugininfo.h"
|
||||
|
||||
SunSpecTracker::SunSpecTracker(const QHostAddress &hostAddress, uint port, QObject *parent) : SunSpec(hostAddress, port, parent)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void SunSpecTracker::readTrackerBlockHeader()
|
||||
{
|
||||
readMap(m_mapModbusStartRegister, m_mapLength);
|
||||
}
|
||||
@ -1,77 +0,0 @@
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
*
|
||||
* Copyright 2013 - 2020, nymea GmbH
|
||||
* Contact: contact@nymea.io
|
||||
*
|
||||
* This file is part of nymea.
|
||||
* This project including source code and documentation is protected by
|
||||
* copyright law, and remains the property of nymea GmbH. All rights, including
|
||||
* reproduction, publication, editing and translation, are reserved. The use of
|
||||
* this project is subject to the terms of a license agreement to be concluded
|
||||
* with nymea GmbH in accordance with the terms of use of nymea GmbH, available
|
||||
* under https://nymea.io/license
|
||||
*
|
||||
* GNU Lesser General Public License Usage
|
||||
* Alternatively, this project may be redistributed and/or modified under the
|
||||
* terms of the GNU Lesser General Public License as published by the Free
|
||||
* Software Foundation; version 3. This project is distributed in the hope that
|
||||
* it will be useful, but WITHOUT ANY WARRANTY; without even the implied
|
||||
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this project. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* For any further details and any questions please contact us under
|
||||
* contact@nymea.io or see our FAQ/Licensing Information on
|
||||
* https://nymea.io/license/faq
|
||||
*
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
|
||||
#ifndef SUNSPECTRACKER_H
|
||||
#define SUNSPECTRACKER_H
|
||||
|
||||
#include <QObject>
|
||||
#include "sunspec.h"
|
||||
|
||||
class SunSpecTracker : public SunSpec
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
|
||||
enum TrackerType {
|
||||
Unknown = 0,
|
||||
Fixed = 1,
|
||||
Horizontal = 2,
|
||||
Tilted = 3,
|
||||
Azimuth = 4,
|
||||
Dual = 5,
|
||||
Other = 99
|
||||
};
|
||||
Q_ENUM(TrackerType)
|
||||
|
||||
struct TrackerData {
|
||||
SunSpecEvent1 event;
|
||||
SunSpecOperatingState operatingState;
|
||||
};
|
||||
|
||||
SunSpecTracker(const QHostAddress &hostAddress, uint port = 502, QObject *parent = 0);
|
||||
|
||||
void getTrackerMap();
|
||||
|
||||
private:
|
||||
ModelId m_id = ModelIdTrackerController;
|
||||
uint m_mapLength = 0;
|
||||
uint m_mapModbusStartRegister = 40000;
|
||||
|
||||
void readTrackerBlockHeader();
|
||||
|
||||
private slots:
|
||||
//void onModbusMapReceived(BlockId mapId, uint mapLength, QVector<quint16> data);
|
||||
|
||||
signals:
|
||||
void initFinished();
|
||||
void trackerDataReceived(const TrackerData &data);
|
||||
};
|
||||
|
||||
#endif // SUNSPECTRACKER_H
|
||||
Reference in New Issue
Block a user