Skip to content

Commit

Permalink
Fix display of current + voltage for single-phase pvinverters
Browse files Browse the repository at this point in the history
The /Ac/Current and /Ac/Voltage paths for pvinverters are
deprecated / no longer valid.

Instead, determine whether there is a single valid phase
available for a given pvinverter, and if so, export that
phase's current and voltage as properties.

(If multiple valid phases exist, we cannot export valid
aggregate values for current or voltage, so return NaN.)

Contributes to issue #1883

Contributes to issue #1713 in the case where only a
single valid phase exists in the pvinverter device.
  • Loading branch information
chriadam committed Feb 17, 2025
1 parent 8ae46fc commit 2fe5693
Show file tree
Hide file tree
Showing 3 changed files with 98 additions and 14 deletions.
44 changes: 30 additions & 14 deletions data/common/PvInverter.qml
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@ Device {
readonly property int errorCode: _errorCode.isValid ? _errorCode.value : -1

readonly property real energy: _energy.isValid ? _energy.value : NaN
readonly property real current: _current.isValid ? _current.value : NaN
readonly property real power: _power.isValid ? _power.value : NaN
readonly property real voltage: _voltage.isValid ? _voltage.value : NaN
readonly property real current: pvInverter.phases.singlePhaseCurrent
readonly property real voltage: pvInverter.phases.singlePhaseVoltage

readonly property PhaseModel phases: PhaseModel {
function updateCount(maxPhaseCount) {
Expand All @@ -42,22 +42,46 @@ Device {

readonly property VeQuickItem _phaseEnergy: VeQuickItem {
uid: phaseUid + "/Energy/Forward"
onIsValidChanged: if (isValid) phases.updateCount(index + 1)
onIsValidChanged: {
if (isValid) {
phases.updateCount(index + 1)
} else if (phases.count > index) {
phases.setValue(index, PhaseModel.EnergyRole, NaN)
}
}
onValueChanged: phases.setValue(index, PhaseModel.EnergyRole, value)
}
readonly property VeQuickItem _phasePower: VeQuickItem {
uid: phaseUid + "/Power"
onIsValidChanged: if (isValid) phases.updateCount(index + 1)
onIsValidChanged: {
if (isValid) {
phases.updateCount(index + 1)
} else if (phases.count > index) {
phases.setValue(index, PhaseModel.PowerRole, NaN)
}
}
onValueChanged: phases.setValue(index, PhaseModel.PowerRole, value)
}
readonly property VeQuickItem _phaseCurrent: VeQuickItem {
uid: phaseUid + "/Current"
onIsValidChanged: if (isValid) phases.updateCount(index + 1)
onIsValidChanged: {
if (isValid) {
phases.updateCount(index + 1)
} else if (phases.count > index) {
phases.setValue(index, PhaseModel.CurrentRole, NaN)
}
}
onValueChanged: phases.setValue(index, PhaseModel.CurrentRole, value)
}
readonly property VeQuickItem _phaseVoltage: VeQuickItem {
uid: phaseUid + "/Voltage"
onIsValidChanged: if (isValid) phases.updateCount(index + 1)
onIsValidChanged: {
if (isValid) {
phases.updateCount(index + 1)
} else if (phases.count > index) {
phases.setValue(index, PhaseModel.VoltageRole, NaN)
}
}
onValueChanged: phases.setValue(index, PhaseModel.VoltageRole, value)
}
}
Expand All @@ -80,14 +104,6 @@ Device {
uid: pvInverter.serviceUid + "/Ac/Power"
}

readonly property VeQuickItem _current: VeQuickItem {
uid: pvInverter.serviceUid + "/Ac/Current"
}

readonly property VeQuickItem _voltage: VeQuickItem {
uid: pvInverter.serviceUid + "/Ac/Voltage"
}

onValidChanged: {
if (!!Global.pvInverters) {
if (valid) {
Expand Down
58 changes: 58 additions & 0 deletions src/phasemodel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,62 @@ void PhaseModel::setL2AndL1OutSummed(bool l2AndL1OutSummed)
}
}

qreal PhaseModel::singlePhaseCurrent() const
{
return m_singlePhaseCurrent;
}

qreal PhaseModel::singlePhaseVoltage() const
{
return m_singlePhaseVoltage;
}

// If we have ONLY a single phase with valid data,
// expose its current+voltage via separate properties.
void PhaseModel::updateSinglePhaseData()
{
qreal current = qQNaN();
qreal voltage = qQNaN();
for (const Phase &phase : std::as_const(m_phases)) {
if (!qIsNaN(phase.current) || !qIsNaN(phase.voltage)) {
// have valid current and/or voltage data for this phase.
if (qIsNaN(current) && qIsNaN(voltage)) {
// we found a phase with valid data, and no prior
// phases had valid data. Possibly expose this
// phase's data as the singlePhase data properties
// (unless we later find another phase also with data).
current = phase.current;
voltage = phase.voltage;
} else {
// we already found a phase with valid data,
// so we do NOT have valid single-phase data
// (as we cannot sum multiple phases of current/voltage).
current = qQNaN();
voltage = qQNaN();
break;
}
}
}

if (qIsNaN(current) || qIsNaN(voltage)) {
if (!qIsNaN(m_singlePhaseCurrent) || !qIsNaN(m_singlePhaseVoltage)) {
m_singlePhaseCurrent = qQNaN();
m_singlePhaseVoltage = qQNaN();
emit singlePhaseCurrentChanged();
emit singlePhaseVoltageChanged();
}
} else {
if (m_singlePhaseCurrent != current) {
m_singlePhaseCurrent = current;
emit singlePhaseCurrentChanged();
}
if (m_singlePhaseVoltage != voltage) {
m_singlePhaseVoltage = voltage;
emit singlePhaseVoltageChanged();
}
}
}

void PhaseModel::setValue(int index, Role role, const qreal value)
{
if (index < 0) {
Expand All @@ -64,10 +120,12 @@ void PhaseModel::setValue(int index, Role role, const qreal value)
break;
case CurrentRole:
phase.current = value;
updateSinglePhaseData();
emit dataChanged(createIndex(index, 0), createIndex(index, 0), { CurrentRole });
break;
case VoltageRole:
phase.voltage = value;
updateSinglePhaseData();
emit dataChanged(createIndex(index, 0), createIndex(index, 0), { VoltageRole });
break;
case EnergyRole:
Expand Down
10 changes: 10 additions & 0 deletions src/phasemodel.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ class PhaseModel : public QAbstractListModel
Q_PROPERTY(int count READ count NOTIFY countChanged)
Q_PROPERTY(int phaseCount READ phaseCount WRITE setPhaseCount NOTIFY phaseCountChanged)
Q_PROPERTY(bool l2AndL1OutSummed READ l2AndL1OutSummed WRITE setL2AndL1OutSummed NOTIFY l2AndL1OutSummedChanged)
Q_PROPERTY(qreal singlePhaseCurrent READ singlePhaseCurrent NOTIFY singlePhaseCurrentChanged)
Q_PROPERTY(qreal singlePhaseVoltage READ singlePhaseVoltage NOTIFY singlePhaseVoltageChanged)

public:
enum Role {
Expand All @@ -42,6 +44,9 @@ class PhaseModel : public QAbstractListModel
bool l2AndL1OutSummed() const;
void setL2AndL1OutSummed(bool l2AndL1OutSummed);

qreal singlePhaseCurrent() const;
qreal singlePhaseVoltage() const;

int rowCount(const QModelIndex &parent) const override;
QVariant data(const QModelIndex& index, int role) const override;

Expand All @@ -52,11 +57,14 @@ class PhaseModel : public QAbstractListModel
void countChanged();
void phaseCountChanged();
void l2AndL1OutSummedChanged();
void singlePhaseCurrentChanged();
void singlePhaseVoltageChanged();

protected:
QHash<int, QByteArray> roleNames() const override;

private:
void updateSinglePhaseData();
struct Phase {
qreal power = qQNaN();
qreal current = qQNaN();
Expand All @@ -71,6 +79,8 @@ class PhaseModel : public QAbstractListModel
int m_phaseCount = 0;
int m_modelCount = 0;
bool m_l2AndL1OutSummed = false;
qreal m_singlePhaseCurrent = qQNaN();
qreal m_singlePhaseVoltage = qQNaN();
};

} /* VenusOS */
Expand Down

0 comments on commit 2fe5693

Please sign in to comment.