diff --git a/src/app/zap-templates/zcl/data-model/chip/chip-ota.xml b/src/app/zap-templates/zcl/data-model/chip/chip-ota.xml
index 9d311bd50beed1..aaf38d4fdea1a4 100644
--- a/src/app/zap-templates/zcl/data-model/chip/chip-ota.xml
+++ b/src/app/zap-templates/zcl/data-model/chip/chip-ota.xml
@@ -87,6 +87,26 @@ limitations under the License.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
OTA Software Update Requestor
CHIP
@@ -104,5 +124,24 @@ limitations under the License.
+
+ This event SHALL be generated when a change of the UpdateState attribute occurs due to an OTA Requestor moving through the states necessary to query for updates.
+
+
+
+
+
+
+ This event SHALL be generated whenever a new version starts executing after being applied due to a software update.
+
+
+
+
+ This event SHALL be generated whenever an error occurs during OTA Requestor download operation.
+
+
+
+
+
diff --git a/src/controller/python/chip/clusters/Objects.py b/src/controller/python/chip/clusters/Objects.py
index bada758b2f187a..951f9c92fad9a9 100644
--- a/src/controller/python/chip/clusters/Objects.py
+++ b/src/controller/python/chip/clusters/Objects.py
@@ -5794,11 +5794,29 @@ class OtaSoftwareUpdateRequestor(Cluster):
id: typing.ClassVar[int] = 0x002A
class Enums:
+ class ChangeReasonEnum(IntEnum):
+ kUnknown = 0x00
+ kSuccess = 0x01
+ kFailure = 0x02
+ kTimeOut = 0x03
+ kDelayByProvider = 0x04
+
class OTAAnnouncementReason(IntEnum):
kSimpleAnnouncement = 0x00
kUpdateAvailable = 0x01
kUrgentUpdateAvailable = 0x02
+ class UpdateStateEnum(IntEnum):
+ kUnknown = 0x00
+ kIdle = 0x01
+ kQuerying = 0x02
+ kDelayedOnQuery = 0x03
+ kDownloading = 0x04
+ kApplying = 0x05
+ kDelayedOnApply = 0x06
+ kRollingBack = 0x07
+ kDelayedOnUserConsent = 0x08
+
class Commands:
@dataclass
class AnnounceOtaProvider(ClusterCommand):
@@ -5890,6 +5908,73 @@ def attribute_type(cls) -> ClusterObjectFieldDescriptor:
value: 'uint' = None
+ class Events:
+ @dataclass
+ class StateTransition(ClusterEventDescriptor):
+ cluster_id: typing.ClassVar[int] = 0x002A
+ event_id: typing.ClassVar[int] = 0x00000000
+
+ @ChipUtility.classproperty
+ def descriptor(cls) -> ClusterObjectDescriptor:
+ return ClusterObjectDescriptor(
+ Fields=[
+ ClusterObjectFieldDescriptor(
+ Label="previousState", Tag=0, Type=OtaSoftwareUpdateRequestor.Enums.UpdateStateEnum),
+ ClusterObjectFieldDescriptor(
+ Label="newState", Tag=1, Type=OtaSoftwareUpdateRequestor.Enums.UpdateStateEnum),
+ ClusterObjectFieldDescriptor(
+ Label="reason", Tag=2, Type=OtaSoftwareUpdateRequestor.Enums.ChangeReasonEnum),
+ ClusterObjectFieldDescriptor(
+ Label="targetSoftwareVersion", Tag=3, Type=uint),
+ ])
+
+ previousState: 'OtaSoftwareUpdateRequestor.Enums.UpdateStateEnum' = None
+ newState: 'OtaSoftwareUpdateRequestor.Enums.UpdateStateEnum' = None
+ reason: 'OtaSoftwareUpdateRequestor.Enums.ChangeReasonEnum' = None
+ targetSoftwareVersion: 'uint' = None
+
+ @dataclass
+ class VersionApplied(ClusterEventDescriptor):
+ cluster_id: typing.ClassVar[int] = 0x002A
+ event_id: typing.ClassVar[int] = 0x00000001
+
+ @ChipUtility.classproperty
+ def descriptor(cls) -> ClusterObjectDescriptor:
+ return ClusterObjectDescriptor(
+ Fields=[
+ ClusterObjectFieldDescriptor(
+ Label="softwareVersion", Tag=0, Type=uint),
+ ClusterObjectFieldDescriptor(
+ Label="productID", Tag=1, Type=uint),
+ ])
+
+ softwareVersion: 'uint' = None
+ productID: 'uint' = None
+
+ @dataclass
+ class DownloadError(ClusterEventDescriptor):
+ cluster_id: typing.ClassVar[int] = 0x002A
+ event_id: typing.ClassVar[int] = 0x00000002
+
+ @ChipUtility.classproperty
+ def descriptor(cls) -> ClusterObjectDescriptor:
+ return ClusterObjectDescriptor(
+ Fields=[
+ ClusterObjectFieldDescriptor(
+ Label="softwareVersion", Tag=0, Type=uint),
+ ClusterObjectFieldDescriptor(
+ Label="bytesDownloaded", Tag=1, Type=uint),
+ ClusterObjectFieldDescriptor(
+ Label="progressPercent", Tag=2, Type=uint),
+ ClusterObjectFieldDescriptor(
+ Label="platformCode", Tag=3, Type=int),
+ ])
+
+ softwareVersion: 'uint' = None
+ bytesDownloaded: 'uint' = None
+ progressPercent: 'uint' = None
+ platformCode: 'int' = None
+
@dataclass
class LocalizationConfiguration(Cluster):
diff --git a/zzz_generated/app-common/app-common/zap-generated/cluster-objects.cpp b/zzz_generated/app-common/app-common/zap-generated/cluster-objects.cpp
index 7363482a5eb8da..b0366d390e2266 100644
--- a/zzz_generated/app-common/app-common/zap-generated/cluster-objects.cpp
+++ b/zzz_generated/app-common/app-common/zap-generated/cluster-objects.cpp
@@ -5059,6 +5059,137 @@ CHIP_ERROR DecodableType::Decode(TLV::TLVReader & reader)
} // namespace Commands
namespace Events {
+namespace StateTransition {
+CHIP_ERROR Type::Encode(TLV::TLVWriter & writer, TLV::Tag tag) const
+{
+ TLV::TLVType outer;
+ ReturnErrorOnFailure(writer.StartContainer(tag, TLV::kTLVType_Structure, outer));
+ ReturnErrorOnFailure(DataModel::Encode(writer, TLV::ContextTag(to_underlying(Fields::kPreviousState)), previousState));
+ ReturnErrorOnFailure(DataModel::Encode(writer, TLV::ContextTag(to_underlying(Fields::kNewState)), newState));
+ ReturnErrorOnFailure(DataModel::Encode(writer, TLV::ContextTag(to_underlying(Fields::kReason)), reason));
+ ReturnErrorOnFailure(
+ DataModel::Encode(writer, TLV::ContextTag(to_underlying(Fields::kTargetSoftwareVersion)), targetSoftwareVersion));
+ ReturnErrorOnFailure(writer.EndContainer(outer));
+ return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR DecodableType::Decode(TLV::TLVReader & reader)
+{
+ CHIP_ERROR err = CHIP_NO_ERROR;
+ TLV::TLVType outer;
+ VerifyOrReturnError(TLV::kTLVType_Structure == reader.GetType(), CHIP_ERROR_WRONG_TLV_TYPE);
+ ReturnErrorOnFailure(reader.EnterContainer(outer));
+ while ((err = reader.Next()) == CHIP_NO_ERROR)
+ {
+ VerifyOrReturnError(TLV::IsContextTag(reader.GetTag()), CHIP_ERROR_INVALID_TLV_TAG);
+ switch (TLV::TagNumFromTag(reader.GetTag()))
+ {
+ case to_underlying(Fields::kPreviousState):
+ ReturnErrorOnFailure(DataModel::Decode(reader, previousState));
+ break;
+ case to_underlying(Fields::kNewState):
+ ReturnErrorOnFailure(DataModel::Decode(reader, newState));
+ break;
+ case to_underlying(Fields::kReason):
+ ReturnErrorOnFailure(DataModel::Decode(reader, reason));
+ break;
+ case to_underlying(Fields::kTargetSoftwareVersion):
+ ReturnErrorOnFailure(DataModel::Decode(reader, targetSoftwareVersion));
+ break;
+ default:
+ break;
+ }
+ }
+
+ VerifyOrReturnError(err == CHIP_END_OF_TLV, err);
+ ReturnErrorOnFailure(reader.ExitContainer(outer));
+ return CHIP_NO_ERROR;
+}
+} // namespace StateTransition.
+namespace VersionApplied {
+CHIP_ERROR Type::Encode(TLV::TLVWriter & writer, TLV::Tag tag) const
+{
+ TLV::TLVType outer;
+ ReturnErrorOnFailure(writer.StartContainer(tag, TLV::kTLVType_Structure, outer));
+ ReturnErrorOnFailure(DataModel::Encode(writer, TLV::ContextTag(to_underlying(Fields::kSoftwareVersion)), softwareVersion));
+ ReturnErrorOnFailure(DataModel::Encode(writer, TLV::ContextTag(to_underlying(Fields::kProductID)), productID));
+ ReturnErrorOnFailure(writer.EndContainer(outer));
+ return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR DecodableType::Decode(TLV::TLVReader & reader)
+{
+ CHIP_ERROR err = CHIP_NO_ERROR;
+ TLV::TLVType outer;
+ VerifyOrReturnError(TLV::kTLVType_Structure == reader.GetType(), CHIP_ERROR_WRONG_TLV_TYPE);
+ ReturnErrorOnFailure(reader.EnterContainer(outer));
+ while ((err = reader.Next()) == CHIP_NO_ERROR)
+ {
+ VerifyOrReturnError(TLV::IsContextTag(reader.GetTag()), CHIP_ERROR_INVALID_TLV_TAG);
+ switch (TLV::TagNumFromTag(reader.GetTag()))
+ {
+ case to_underlying(Fields::kSoftwareVersion):
+ ReturnErrorOnFailure(DataModel::Decode(reader, softwareVersion));
+ break;
+ case to_underlying(Fields::kProductID):
+ ReturnErrorOnFailure(DataModel::Decode(reader, productID));
+ break;
+ default:
+ break;
+ }
+ }
+
+ VerifyOrReturnError(err == CHIP_END_OF_TLV, err);
+ ReturnErrorOnFailure(reader.ExitContainer(outer));
+ return CHIP_NO_ERROR;
+}
+} // namespace VersionApplied.
+namespace DownloadError {
+CHIP_ERROR Type::Encode(TLV::TLVWriter & writer, TLV::Tag tag) const
+{
+ TLV::TLVType outer;
+ ReturnErrorOnFailure(writer.StartContainer(tag, TLV::kTLVType_Structure, outer));
+ ReturnErrorOnFailure(DataModel::Encode(writer, TLV::ContextTag(to_underlying(Fields::kSoftwareVersion)), softwareVersion));
+ ReturnErrorOnFailure(DataModel::Encode(writer, TLV::ContextTag(to_underlying(Fields::kBytesDownloaded)), bytesDownloaded));
+ ReturnErrorOnFailure(DataModel::Encode(writer, TLV::ContextTag(to_underlying(Fields::kProgressPercent)), progressPercent));
+ ReturnErrorOnFailure(DataModel::Encode(writer, TLV::ContextTag(to_underlying(Fields::kPlatformCode)), platformCode));
+ ReturnErrorOnFailure(writer.EndContainer(outer));
+ return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR DecodableType::Decode(TLV::TLVReader & reader)
+{
+ CHIP_ERROR err = CHIP_NO_ERROR;
+ TLV::TLVType outer;
+ VerifyOrReturnError(TLV::kTLVType_Structure == reader.GetType(), CHIP_ERROR_WRONG_TLV_TYPE);
+ ReturnErrorOnFailure(reader.EnterContainer(outer));
+ while ((err = reader.Next()) == CHIP_NO_ERROR)
+ {
+ VerifyOrReturnError(TLV::IsContextTag(reader.GetTag()), CHIP_ERROR_INVALID_TLV_TAG);
+ switch (TLV::TagNumFromTag(reader.GetTag()))
+ {
+ case to_underlying(Fields::kSoftwareVersion):
+ ReturnErrorOnFailure(DataModel::Decode(reader, softwareVersion));
+ break;
+ case to_underlying(Fields::kBytesDownloaded):
+ ReturnErrorOnFailure(DataModel::Decode(reader, bytesDownloaded));
+ break;
+ case to_underlying(Fields::kProgressPercent):
+ ReturnErrorOnFailure(DataModel::Decode(reader, progressPercent));
+ break;
+ case to_underlying(Fields::kPlatformCode):
+ ReturnErrorOnFailure(DataModel::Decode(reader, platformCode));
+ break;
+ default:
+ break;
+ }
+ }
+
+ VerifyOrReturnError(err == CHIP_END_OF_TLV, err);
+ ReturnErrorOnFailure(reader.ExitContainer(outer));
+ return CHIP_NO_ERROR;
+}
+} // namespace DownloadError.
} // namespace Events
} // namespace OtaSoftwareUpdateRequestor
diff --git a/zzz_generated/app-common/app-common/zap-generated/cluster-objects.h b/zzz_generated/app-common/app-common/zap-generated/cluster-objects.h
index 83e93260d04dc1..ef1425c5bc5a1e 100644
--- a/zzz_generated/app-common/app-common/zap-generated/cluster-objects.h
+++ b/zzz_generated/app-common/app-common/zap-generated/cluster-objects.h
@@ -7294,6 +7294,21 @@ namespace OtaSoftwareUpdateRequestor {
// Need to convert consumers to using the new enum classes, so we
// don't just have casts all over.
#ifdef CHIP_USE_ENUM_CLASS_FOR_IM_ENUM
+// Enum for ChangeReasonEnum
+enum class ChangeReasonEnum : uint8_t
+{
+ kUnknown = 0x00,
+ kSuccess = 0x01,
+ kFailure = 0x02,
+ kTimeOut = 0x03,
+ kDelayByProvider = 0x04,
+};
+#else // CHIP_USE_ENUM_CLASS_FOR_IM_ENUM
+using ChangeReasonEnum = EmberAfChangeReasonEnum;
+#endif
+// Need to convert consumers to using the new enum classes, so we
+// don't just have casts all over.
+#ifdef CHIP_USE_ENUM_CLASS_FOR_IM_ENUM
// Enum for OTAAnnouncementReason
enum class OTAAnnouncementReason : uint8_t
{
@@ -7304,6 +7319,25 @@ enum class OTAAnnouncementReason : uint8_t
#else // CHIP_USE_ENUM_CLASS_FOR_IM_ENUM
using OTAAnnouncementReason = EmberAfOTAAnnouncementReason;
#endif
+// Need to convert consumers to using the new enum classes, so we
+// don't just have casts all over.
+#ifdef CHIP_USE_ENUM_CLASS_FOR_IM_ENUM
+// Enum for UpdateStateEnum
+enum class UpdateStateEnum : uint8_t
+{
+ kUnknown = 0x00,
+ kIdle = 0x01,
+ kQuerying = 0x02,
+ kDelayedOnQuery = 0x03,
+ kDownloading = 0x04,
+ kApplying = 0x05,
+ kDelayedOnApply = 0x06,
+ kRollingBack = 0x07,
+ kDelayedOnUserConsent = 0x08,
+};
+#else // CHIP_USE_ENUM_CLASS_FOR_IM_ENUM
+using UpdateStateEnum = EmberAfUpdateStateEnum;
+#endif
namespace Commands {
// Forward-declarations so we can reference these later.
@@ -7403,6 +7437,128 @@ struct TypeInfo
};
} // namespace ClusterRevision
} // namespace Attributes
+namespace Events {
+namespace StateTransition {
+static constexpr PriorityLevel kPriorityLevel = PriorityLevel::Info;
+static constexpr EventId kEventId = 0x00000000;
+
+enum class Fields
+{
+ kPreviousState = 0,
+ kNewState = 1,
+ kReason = 2,
+ kTargetSoftwareVersion = 3,
+};
+
+struct Type
+{
+public:
+ static constexpr PriorityLevel GetPriorityLevel() { return kPriorityLevel; }
+ static constexpr EventId GetEventId() { return kEventId; }
+ static constexpr ClusterId GetClusterId() { return Clusters::OtaSoftwareUpdateRequestor::Id; }
+
+ UpdateStateEnum previousState;
+ UpdateStateEnum newState;
+ ChangeReasonEnum reason;
+ uint32_t targetSoftwareVersion;
+
+ CHIP_ERROR Encode(TLV::TLVWriter & writer, TLV::Tag tag) const;
+};
+
+struct DecodableType
+{
+public:
+ static constexpr PriorityLevel GetPriorityLevel() { return kPriorityLevel; }
+ static constexpr EventId GetEventId() { return kEventId; }
+ static constexpr ClusterId GetClusterId() { return Clusters::OtaSoftwareUpdateRequestor::Id; }
+
+ UpdateStateEnum previousState;
+ UpdateStateEnum newState;
+ ChangeReasonEnum reason;
+ uint32_t targetSoftwareVersion;
+
+ CHIP_ERROR Decode(TLV::TLVReader & reader);
+};
+} // namespace StateTransition
+namespace VersionApplied {
+static constexpr PriorityLevel kPriorityLevel = PriorityLevel::Critical;
+static constexpr EventId kEventId = 0x00000001;
+
+enum class Fields
+{
+ kSoftwareVersion = 0,
+ kProductID = 1,
+};
+
+struct Type
+{
+public:
+ static constexpr PriorityLevel GetPriorityLevel() { return kPriorityLevel; }
+ static constexpr EventId GetEventId() { return kEventId; }
+ static constexpr ClusterId GetClusterId() { return Clusters::OtaSoftwareUpdateRequestor::Id; }
+
+ uint32_t softwareVersion;
+ uint16_t productID;
+
+ CHIP_ERROR Encode(TLV::TLVWriter & writer, TLV::Tag tag) const;
+};
+
+struct DecodableType
+{
+public:
+ static constexpr PriorityLevel GetPriorityLevel() { return kPriorityLevel; }
+ static constexpr EventId GetEventId() { return kEventId; }
+ static constexpr ClusterId GetClusterId() { return Clusters::OtaSoftwareUpdateRequestor::Id; }
+
+ uint32_t softwareVersion;
+ uint16_t productID;
+
+ CHIP_ERROR Decode(TLV::TLVReader & reader);
+};
+} // namespace VersionApplied
+namespace DownloadError {
+static constexpr PriorityLevel kPriorityLevel = PriorityLevel::Info;
+static constexpr EventId kEventId = 0x00000002;
+
+enum class Fields
+{
+ kSoftwareVersion = 0,
+ kBytesDownloaded = 1,
+ kProgressPercent = 2,
+ kPlatformCode = 3,
+};
+
+struct Type
+{
+public:
+ static constexpr PriorityLevel GetPriorityLevel() { return kPriorityLevel; }
+ static constexpr EventId GetEventId() { return kEventId; }
+ static constexpr ClusterId GetClusterId() { return Clusters::OtaSoftwareUpdateRequestor::Id; }
+
+ uint32_t softwareVersion;
+ uint64_t bytesDownloaded;
+ uint8_t progressPercent;
+ int64_t platformCode;
+
+ CHIP_ERROR Encode(TLV::TLVWriter & writer, TLV::Tag tag) const;
+};
+
+struct DecodableType
+{
+public:
+ static constexpr PriorityLevel GetPriorityLevel() { return kPriorityLevel; }
+ static constexpr EventId GetEventId() { return kEventId; }
+ static constexpr ClusterId GetClusterId() { return Clusters::OtaSoftwareUpdateRequestor::Id; }
+
+ uint32_t softwareVersion;
+ uint64_t bytesDownloaded;
+ uint8_t progressPercent;
+ int64_t platformCode;
+
+ CHIP_ERROR Decode(TLV::TLVReader & reader);
+};
+} // namespace DownloadError
+} // namespace Events
} // namespace OtaSoftwareUpdateRequestor
namespace LocalizationConfiguration {
diff --git a/zzz_generated/app-common/app-common/zap-generated/enums.h b/zzz_generated/app-common/app-common/zap-generated/enums.h
index 95f498d1503ef4..cd60e8cea362e8 100644
--- a/zzz_generated/app-common/app-common/zap-generated/enums.h
+++ b/zzz_generated/app-common/app-common/zap-generated/enums.h
@@ -259,6 +259,16 @@ enum EmberAfCecedSpecificationVersion : uint8_t
EMBER_ZCL_CECED_SPECIFICATION_VERSION_COMPLIANT_WITH_V10_CERTIFIED = 26,
};
+// Enum for ChangeReasonEnum
+enum EmberAfChangeReasonEnum : uint8_t
+{
+ EMBER_ZCL_CHANGE_REASON_ENUM_UNKNOWN = 0,
+ EMBER_ZCL_CHANGE_REASON_ENUM_SUCCESS = 1,
+ EMBER_ZCL_CHANGE_REASON_ENUM_FAILURE = 2,
+ EMBER_ZCL_CHANGE_REASON_ENUM_TIME_OUT = 3,
+ EMBER_ZCL_CHANGE_REASON_ENUM_DELAY_BY_PROVIDER = 4,
+};
+
// Enum for ColorControlOptions
enum EmberAfColorControlOptions : uint8_t
{
@@ -1597,6 +1607,20 @@ enum EmberAfTvChannelLineupInfoType : uint8_t
EMBER_ZCL_TV_CHANNEL_LINEUP_INFO_TYPE_MSO = 0,
};
+// Enum for UpdateStateEnum
+enum EmberAfUpdateStateEnum : uint8_t
+{
+ EMBER_ZCL_UPDATE_STATE_ENUM_UNKNOWN = 0,
+ EMBER_ZCL_UPDATE_STATE_ENUM_IDLE = 1,
+ EMBER_ZCL_UPDATE_STATE_ENUM_QUERYING = 2,
+ EMBER_ZCL_UPDATE_STATE_ENUM_DELAYED_ON_QUERY = 3,
+ EMBER_ZCL_UPDATE_STATE_ENUM_DOWNLOADING = 4,
+ EMBER_ZCL_UPDATE_STATE_ENUM_APPLYING = 5,
+ EMBER_ZCL_UPDATE_STATE_ENUM_DELAYED_ON_APPLY = 6,
+ EMBER_ZCL_UPDATE_STATE_ENUM_ROLLING_BACK = 7,
+ EMBER_ZCL_UPDATE_STATE_ENUM_DELAYED_ON_USER_CONSENT = 8,
+};
+
// Enum for WarningEvent
enum EmberAfWarningEvent : uint8_t
{