Skip to content

Commit

Permalink
Allow Thermostat delegate to provide timeout for atomic requests
Browse files Browse the repository at this point in the history
  • Loading branch information
hasty committed Aug 6, 2024
1 parent bdc747e commit 2f9a711
Show file tree
Hide file tree
Showing 4 changed files with 60 additions and 6 deletions.
3 changes: 3 additions & 0 deletions examples/thermostat/linux/include/thermostat-delegate-impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,9 @@ class ThermostatDelegate : public Delegate
public:
static inline ThermostatDelegate & GetInstance() { return sInstance; }

System::Clock::Milliseconds16 GetAtomicWriteTimeout(DataModel::DecodableList<chip::AttributeId> attributeRequests,
System::Clock::Milliseconds16 timeoutRequest) override;

CHIP_ERROR GetPresetTypeAtIndex(size_t index, Structs::PresetTypeStruct::Type & presetType) override;

uint8_t GetNumberOfPresets() override;
Expand Down
38 changes: 38 additions & 0 deletions examples/thermostat/linux/thermostat-delegate-impl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,44 @@ CHIP_ERROR ThermostatDelegate::SetActivePresetHandle(const DataModel::Nullable<B
return CHIP_NO_ERROR;
}

System::Clock::Milliseconds16
ThermostatDelegate::GetAtomicWriteTimeout(DataModel::DecodableList<chip::AttributeId> attributeRequests,
System::Clock::Milliseconds16 timeoutRequest)
{
auto attributeIdsIter = attributeRequests.begin();
bool requestedPresets = false, requestedSchedules = false;
while (attributeIdsIter.Next())
{
auto & attributeId = attributeIdsIter.GetValue();

switch (attributeId)
{
case Attributes::Presets::Id:
requestedPresets = true;
break;
case Attributes::Schedules::Id:
requestedSchedules = true;
break;
default:
return System::Clock::Milliseconds16(0);
}
}
if (attributeIdsIter.GetStatus() != CHIP_NO_ERROR)
{
return System::Clock::Milliseconds16(0);
}
auto timeout = System::Clock::Milliseconds16(0);
if (requestedPresets)
{
timeout += std::chrono::milliseconds(1000);
}
if (requestedSchedules)
{
timeout += std::chrono::milliseconds(3000);
}
return std::min(timeoutRequest, timeout);
}

void ThermostatDelegate::InitializePendingPresets()
{
mNextFreeIndexInPendingPresetsList = 0;
Expand Down
10 changes: 10 additions & 0 deletions src/app/clusters/thermostat-server/thermostat-delegate.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,16 @@ class Delegate

virtual ~Delegate() = default;

/**
* @brief Get the maximum timeout for atomically writing to a set of attributes
*
* @param[in] attributeRequests The list of attributes to write to.
* @param[out] timeoutRequest The timeout proposed by the client.
* @return The maximum allowed timeout; zero if the request is invalid.
*/
virtual System::Clock::Milliseconds16 GetAtomicWriteTimeout(DataModel::DecodableList<chip::AttributeId> attributeRequests,
System::Clock::Milliseconds16 timeoutRequest) = 0;

/**
* @brief Get the preset type at a given index in the PresetTypes attribute
*
Expand Down
15 changes: 9 additions & 6 deletions src/app/clusters/thermostat-server/thermostat-server.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1402,8 +1402,6 @@ void handleAtomicBegin(CommandHandler * commandObj, const ConcreteCommandPath &
return;
}

auto timeout = commandData.timeout.Value();

if (!validAtomicAttributes(commandData, false))
{
commandObj->AddStatus(commandPath, imcode::InvalidCommand);
Expand All @@ -1420,12 +1418,17 @@ void handleAtomicBegin(CommandHandler * commandObj, const ConcreteCommandPath &
// needs to keep track of a pending preset list now.
delegate->InitializePendingPresets();

uint16_t maxTimeout = 5000;
timeout = std::min(timeout, maxTimeout);
System::Clock::Milliseconds16 timeout =
delegate->GetAtomicWriteTimeout(commandData.attributeRequests, System::Clock::Milliseconds16(commandData.timeout.Value()));

ScheduleTimer(endpoint, System::Clock::Milliseconds16(timeout));
if (timeout == System::Clock::Milliseconds16(0))
{
commandObj->AddStatus(commandPath, imcode::InvalidCommand);
return;
}
ScheduleTimer(endpoint, timeout);
gThermostatAttrAccess.SetAtomicWrite(endpoint, GetSourceScopedNodeId(commandObj), true);
sendAtomicResponse(commandObj, commandPath, imcode::Success, imcode::Success, imcode::Success, MakeOptional(timeout));
sendAtomicResponse(commandObj, commandPath, imcode::Success, imcode::Success, imcode::Success, MakeOptional(timeout.count()));
}

imcode commitPresets(Delegate * delegate, EndpointId endpoint)
Expand Down

0 comments on commit 2f9a711

Please sign in to comment.