/* * * Copyright (c) 2024 Project CHIP Authors * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "electrical-power-measurement-server.h" #include #include #include #include #include #include using namespace chip; using namespace chip::app; using namespace chip::app::DataModel; using namespace chip::app::Clusters; using namespace chip::app::Clusters::ElectricalPowerMeasurement; using namespace chip::app::Clusters::ElectricalPowerMeasurement::Attributes; using namespace chip::app::Clusters::ElectricalPowerMeasurement::Structs; using chip::Protocols::InteractionModel::Status; namespace chip { namespace app { namespace Clusters { namespace ElectricalPowerMeasurement { CHIP_ERROR Instance::Init() { VerifyOrReturnError(AttributeAccessInterfaceRegistry::Instance().Register(this), CHIP_ERROR_INCORRECT_STATE); return CHIP_NO_ERROR; } void Instance::Shutdown() { AttributeAccessInterfaceRegistry::Instance().Unregister(this); } bool Instance::HasFeature(Feature aFeature) const { return mFeature.Has(aFeature); } bool Instance::SupportsOptAttr(OptionalAttributes aOptionalAttrs) const { return mOptionalAttrs.Has(aOptionalAttrs); } // AttributeAccessInterface CHIP_ERROR Instance::Read(const ConcreteReadAttributePath & aPath, AttributeValueEncoder & aEncoder) { switch (aPath.mAttributeId) { case FeatureMap::Id: ReturnErrorOnFailure(aEncoder.Encode(mFeature)); break; case PowerMode::Id: ReturnErrorOnFailure(aEncoder.Encode(mDelegate.GetPowerMode())); break; case NumberOfMeasurementTypes::Id: ReturnErrorOnFailure(aEncoder.Encode(mDelegate.GetNumberOfMeasurementTypes())); break; case Accuracy::Id: ReturnErrorOnFailure( aEncoder.EncodeList([this](const auto & encoder) -> CHIP_ERROR { return this->EncodeAccuracy(encoder); })); break; case Ranges::Id: if (!SupportsOptAttr(OptionalAttributes::kOptionalAttributeRanges)) { return CHIP_IM_GLOBAL_STATUS(UnsupportedAttribute); } ReturnErrorOnFailure( aEncoder.EncodeList([this](const auto & encoder) -> CHIP_ERROR { return this->EncodeRanges(encoder); })); break; case Voltage::Id: if (!SupportsOptAttr(OptionalAttributes::kOptionalAttributeVoltage)) { return CHIP_IM_GLOBAL_STATUS(UnsupportedAttribute); } ReturnErrorOnFailure(aEncoder.Encode(mDelegate.GetVoltage())); break; case ActiveCurrent::Id: if (!SupportsOptAttr(OptionalAttributes::kOptionalAttributeActiveCurrent)) { return CHIP_IM_GLOBAL_STATUS(UnsupportedAttribute); } ReturnErrorOnFailure(aEncoder.Encode(mDelegate.GetActiveCurrent())); break; case ReactiveCurrent::Id: if (!SupportsOptAttr(OptionalAttributes::kOptionalAttributeReactiveCurrent)) { return CHIP_IM_GLOBAL_STATUS(UnsupportedAttribute); } VerifyOrReturnError( HasFeature(ElectricalPowerMeasurement::Feature::kAlternatingCurrent), CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE, ChipLogError(Zcl, "Electrical Power Measurement: can not get ReactiveCurrent, feature is not supported")); ReturnErrorOnFailure(aEncoder.Encode(mDelegate.GetReactiveCurrent())); break; case ApparentCurrent::Id: if (!SupportsOptAttr(OptionalAttributes::kOptionalAttributeApparentCurrent)) { return CHIP_IM_GLOBAL_STATUS(UnsupportedAttribute); } VerifyOrReturnError( HasFeature(ElectricalPowerMeasurement::Feature::kAlternatingCurrent), CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE, ChipLogError(Zcl, "Electrical Power Measurement: can not get ApparentCurrent, feature is not supported")); ReturnErrorOnFailure(aEncoder.Encode(mDelegate.GetApparentCurrent())); break; case ActivePower::Id: ReturnErrorOnFailure(aEncoder.Encode(mDelegate.GetActivePower())); break; case ReactivePower::Id: if (!SupportsOptAttr(OptionalAttributes::kOptionalAttributeReactivePower)) { return CHIP_IM_GLOBAL_STATUS(UnsupportedAttribute); } VerifyOrReturnError(HasFeature(ElectricalPowerMeasurement::Feature::kAlternatingCurrent), CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE, ChipLogError(Zcl, "Electrical Power Measurement: can not get ReactivePower, feature is not supported")); ReturnErrorOnFailure(aEncoder.Encode(mDelegate.GetReactivePower())); break; case ApparentPower::Id: if (!SupportsOptAttr(OptionalAttributes::kOptionalAttributeApparentPower)) { return CHIP_IM_GLOBAL_STATUS(UnsupportedAttribute); } VerifyOrReturnError(HasFeature(ElectricalPowerMeasurement::Feature::kAlternatingCurrent), CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE, ChipLogError(Zcl, "Electrical Power Measurement: can not get ApparentPower, feature is not supported")); ReturnErrorOnFailure(aEncoder.Encode(mDelegate.GetApparentPower())); break; case RMSVoltage::Id: if (!SupportsOptAttr(OptionalAttributes::kOptionalAttributeRMSVoltage)) { return CHIP_IM_GLOBAL_STATUS(UnsupportedAttribute); } VerifyOrReturnError(HasFeature(ElectricalPowerMeasurement::Feature::kAlternatingCurrent), CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE, ChipLogError(Zcl, "Electrical Power Measurement: can not get RMSVoltage, feature is not supported")); ReturnErrorOnFailure(aEncoder.Encode(mDelegate.GetRMSVoltage())); break; case RMSCurrent::Id: if (!SupportsOptAttr(OptionalAttributes::kOptionalAttributeRMSCurrent)) { return CHIP_IM_GLOBAL_STATUS(UnsupportedAttribute); } VerifyOrReturnError(HasFeature(ElectricalPowerMeasurement::Feature::kAlternatingCurrent), CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE, ChipLogError(Zcl, "Electrical Power Measurement: can not get RMSCurrent, feature is not supported")); ReturnErrorOnFailure(aEncoder.Encode(mDelegate.GetRMSCurrent())); break; case RMSPower::Id: if (!SupportsOptAttr(OptionalAttributes::kOptionalAttributeRMSPower)) { return CHIP_IM_GLOBAL_STATUS(UnsupportedAttribute); } VerifyOrReturnError(HasFeature(ElectricalPowerMeasurement::Feature::kAlternatingCurrent), CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE, ChipLogError(Zcl, "Electrical Power Measurement: can not get RMSPower, feature is not supported")); ReturnErrorOnFailure(aEncoder.Encode(mDelegate.GetRMSPower())); break; case Frequency::Id: if (!SupportsOptAttr(OptionalAttributes::kOptionalAttributeFrequency)) { return CHIP_IM_GLOBAL_STATUS(UnsupportedAttribute); } VerifyOrReturnError(HasFeature(ElectricalPowerMeasurement::Feature::kAlternatingCurrent), CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE, ChipLogError(Zcl, "Electrical Power Measurement: can not get Frequency, feature is not supported")); ReturnErrorOnFailure(aEncoder.Encode(mDelegate.GetFrequency())); break; case HarmonicCurrents::Id: VerifyOrReturnError( HasFeature(ElectricalPowerMeasurement::Feature::kHarmonics), CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE, ChipLogError(Zcl, "Electrical Power Measurement: can not get HarmonicCurrents, feature is not supported")); ReturnErrorOnFailure( aEncoder.EncodeList([this](const auto & encoder) -> CHIP_ERROR { return this->EncodeHarmonicCurrents(encoder); })); break; case HarmonicPhases::Id: VerifyOrReturnError( HasFeature(ElectricalPowerMeasurement::Feature::kPowerQuality), CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE, ChipLogError(Zcl, "Electrical Power Measurement: can not get HarmonicPhases, feature is not supported")); ReturnErrorOnFailure( aEncoder.EncodeList([this](const auto & encoder) -> CHIP_ERROR { return this->EncodeHarmonicPhases(encoder); })); break; case PowerFactor::Id: if (!SupportsOptAttr(OptionalAttributes::kOptionalAttributePowerFactor)) { return CHIP_IM_GLOBAL_STATUS(UnsupportedAttribute); } VerifyOrReturnError(HasFeature(ElectricalPowerMeasurement::Feature::kAlternatingCurrent), CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE, ChipLogError(Zcl, "Electrical Power Measurement: can not get PowerFactor, feature is not supported")); ReturnErrorOnFailure(aEncoder.Encode(mDelegate.GetPowerFactor())); break; case NeutralCurrent::Id: if (!SupportsOptAttr(OptionalAttributes::kOptionalAttributeNeutralCurrent)) { return CHIP_IM_GLOBAL_STATUS(UnsupportedAttribute); } VerifyOrReturnError( HasFeature(ElectricalPowerMeasurement::Feature::kPolyphasePower), CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE, ChipLogError(Zcl, "Electrical Power Measurement: can not get NeutralCurrent, feature is not supported")); ReturnErrorOnFailure(aEncoder.Encode(mDelegate.GetNeutralCurrent())); break; } return CHIP_NO_ERROR; } CHIP_ERROR Instance::EncodeAccuracy(const AttributeValueEncoder::ListEncodeHelper & encoder) { CHIP_ERROR err = CHIP_NO_ERROR; ReturnErrorOnFailure(mDelegate.StartAccuracyRead()); for (uint8_t i = 0; true; i++) { Structs::MeasurementAccuracyStruct::Type accuracy; err = mDelegate.GetAccuracyByIndex(i, accuracy); if (err == CHIP_ERROR_PROVIDER_LIST_EXHAUSTED) { // Convert end of list to CHIP_NO_ERROR err = CHIP_NO_ERROR; goto exit; } // Check if another error occurred before trying to encode SuccessOrExit(err); err = encoder.Encode(accuracy); SuccessOrExit(err); } exit: // Tell the delegate the read is complete mDelegate.EndAccuracyRead(); return err; } CHIP_ERROR Instance::EncodeRanges(const AttributeValueEncoder::ListEncodeHelper & encoder) { CHIP_ERROR err = CHIP_NO_ERROR; ReturnErrorOnFailure(mDelegate.StartRangesRead()); for (uint8_t i = 0; true; i++) { Structs::MeasurementRangeStruct::Type range; err = mDelegate.GetRangeByIndex(i, range); if (err == CHIP_ERROR_PROVIDER_LIST_EXHAUSTED) { // Convert end of list to CHIP_NO_ERROR err = CHIP_NO_ERROR; goto exit; } // Check if another error occurred before trying to encode SuccessOrExit(err); err = encoder.Encode(range); SuccessOrExit(err); } exit: // Tell the delegate the read is complete err = mDelegate.EndRangesRead(); return err; } CHIP_ERROR Instance::EncodeHarmonicCurrents(const AttributeValueEncoder::ListEncodeHelper & encoder) { CHIP_ERROR err = CHIP_NO_ERROR; ReturnErrorOnFailure(mDelegate.StartHarmonicCurrentsRead()); for (uint8_t i = 0; true; i++) { Structs::HarmonicMeasurementStruct::Type current; err = mDelegate.GetHarmonicCurrentsByIndex(i, current); if (err == CHIP_ERROR_PROVIDER_LIST_EXHAUSTED) { // Convert end of list to CHIP_NO_ERROR err = CHIP_NO_ERROR; goto exit; } // Check if another error occurred before trying to encode SuccessOrExit(err); err = encoder.Encode(current); SuccessOrExit(err); } exit: // Tell the delegate the read is complete err = mDelegate.EndHarmonicCurrentsRead(); return err; } CHIP_ERROR Instance::EncodeHarmonicPhases(const AttributeValueEncoder::ListEncodeHelper & encoder) { CHIP_ERROR err = CHIP_NO_ERROR; ReturnErrorOnFailure(mDelegate.StartHarmonicPhasesRead()); for (uint8_t i = 0; true; i++) { Structs::HarmonicMeasurementStruct::Type phase; err = mDelegate.GetHarmonicPhasesByIndex(i, phase); if (err == CHIP_ERROR_PROVIDER_LIST_EXHAUSTED) { // Convert end of list to CHIP_NO_ERROR err = CHIP_NO_ERROR; goto exit; } // Check if another error occurred before trying to encode SuccessOrExit(err); err = encoder.Encode(phase); SuccessOrExit(err); } exit: // Tell the delegate the read is complete err = mDelegate.EndHarmonicPhasesRead(); return err; } } // namespace ElectricalPowerMeasurement } // namespace Clusters } // namespace app } // namespace chip