Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

time synchronization cluster #26082

Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
75 commits
Select commit Hold shift + click to select a range
c843519
update time sync cluster XML based on updated spec
fessehaeve May 2, 2023
4c54583
update time sync cluster XML based on updated spec
fessehaeve May 2, 2023
0691f54
added attribute access interface handled attributes
fessehaeve May 2, 2023
fdd9a4c
GNSS
fessehaeve May 3, 2023
c311d21
TrustedTimeSource is optional with TSC feature
fessehaeve May 3, 2023
182aecf
SetUTCTime
fessehaeve May 3, 2023
808d7b3
SetTrustedTimeSource is optional
fessehaeve May 3, 2023
e1b4578
UTCTime
fessehaeve May 3, 2023
652bcb0
TimeZoneDatabase default 2 (None)
fessehaeve May 3, 2023
80ccd23
regenerate code
fessehaeve May 3, 2023
844783e
update default values
fessehaeve May 3, 2023
1367a2f
updated time-synchronization cluster definition based on PR #6352
fessehaeve Mar 22, 2023
df786be
added SupportsDNSResolve attribute and corrected featuremap value
fessehaeve May 4, 2023
7d089a0
code improvements
fessehaeve May 4, 2023
48633d1
truncate span size to actual data when retreiving defaultNTP
fessehaeve May 5, 2023
8c59a50
bring back section removed by rebase
fessehaeve May 8, 2023
2b87054
Merge branch 'pull-request/time-synchronization-xml' into pull-reques…
fessehaeve May 8, 2023
a843dd5
fix CI error do not use 'else' after 'return'
fessehaeve May 8, 2023
4b19983
updated descriptor cluster test to include time sync server
fessehaeve May 8, 2023
f0c5943
added mechanisms to get local time and set utc time from application
fessehaeve May 9, 2023
19cf4f7
Merge remote-tracking branch 'origin/master' into pull-request/time-s…
fessehaeve May 9, 2023
113a7cf
regenerate after merge to master and fix missed server implementation…
fessehaeve May 9, 2023
1c57991
added CI test for time sync cluster
fessehaeve May 11, 2023
6a856d4
improved time zone and dst offset attributes validation,
fessehaeve May 11, 2023
a01af6d
logic to purge expired time zone and dst offset
fessehaeve May 12, 2023
c410517
set default value for time zone attribute
fessehaeve May 17, 2023
627d921
use AttributeAccessInterface for Granularity attribute
fessehaeve May 19, 2023
eb26f18
UTCTime is in chipepoch and not unixepoch
fessehaeve May 23, 2023
f799c32
localtime should be null if dstoffset is empty
fessehaeve May 23, 2023
5d12183
Merge remote-tracking branch 'origin/master' into pull-request/time-s…
fessehaeve May 24, 2023
3c27a07
regen after merge to master
fessehaeve May 24, 2023
561a32d
update feature map attribute name
fessehaeve May 24, 2023
f166702
use static_cast instead
fessehaeve May 24, 2023
80e0e58
cast the whole thing since the operator is causing int usage
fessehaeve May 24, 2023
31a6ab7
timezone always has a default UTC zone
fessehaeve May 24, 2023
db7e060
improved handling of setting empty lists
fessehaeve May 25, 2023
6b580c7
run restyler
fessehaeve May 25, 2023
ff4c60f
Merge remote-tracking branch 'origin/master' into pull-request/time-s…
fessehaeve May 25, 2023
6133fe0
update external hanlded attributes in ZAP files
fessehaeve May 25, 2023
d7468e3
update tests and remove dstoffset sorting on server side
fessehaeve May 25, 2023
06823c0
update yaml test and generate code
fessehaeve May 25, 2023
69065c8
use TLV size estimator
fessehaeve May 26, 2023
462cb33
Merge remote-tracking branch 'origin/master' into pull-request/time-s…
fessehaeve May 26, 2023
ae9b95e
addressed a bunch of PR comments
fessehaeve May 30, 2023
092843a
declare attributes handled by AAI
fessehaeve May 30, 2023
96121b9
Update src/app/clusters/time-synchronization-server/TimeSyncDataProvi…
fessehaeve Jun 1, 2023
df139ef
added mechanism to better track when events shall be emitted
fessehaeve Jun 1, 2023
e2a2f10
address PR comments
fessehaeve Jun 2, 2023
72ade1c
Merge remote-tracking branch 'origin/master' into pull-request/time-s…
fessehaeve Jun 5, 2023
664766e
typo changes
fessehaeve Jun 5, 2023
8dceb9f
Revert parts of "address PR comments"
fessehaeve Jun 5, 2023
1aa9151
clean up time sync persistent storage interface
fessehaeve Jun 5, 2023
43464d7
error if list sizes are not correct
fessehaeve Jun 5, 2023
ed54358
addressed PR comments
fessehaeve Jun 13, 2023
726626e
rename default delegate implementation
fessehaeve Jun 14, 2023
b3d81b7
few more improvements based on PR comments
fessehaeve Jun 14, 2023
5446531
changed time zone stuct, improved tests, fixed local time calculation…
fessehaeve Jun 16, 2023
1c6175d
restyle, use DSTOffsetobj with size element, improved error response …
fessehaeve Jun 20, 2023
a00499d
replace list with span, not sure if it is needed
fessehaeve Jun 20, 2023
f6a6b92
Merge remote-tracking branch 'origin/master' into pull-request/time-s…
fessehaeve Jun 20, 2023
90eefcc
update dstoffset NL test
fessehaeve Jun 20, 2023
a2c6169
cleaned up for loop indexes, catch dst validUntil expiring, nullable …
fessehaeve Jun 22, 2023
aca64c6
disabled darwin time sync SDK test
fessehaeve Jun 23, 2023
f3b4600
change indexer to size_t type
fessehaeve Jun 23, 2023
5b1a0d7
validate NTP addresses in default delegate and few more improvements
fessehaeve Jun 26, 2023
12e9232
fixed few overflow potentials, lots of minor improvements
fessehaeve Jun 27, 2023
98db550
fix uninitialized corner case and update NL tests
fessehaeve Jun 27, 2023
1579179
apply restyle patch
fessehaeve Jun 27, 2023
ab106b8
another restyle patch
fessehaeve Jun 27, 2023
87f9098
return tz and dst lists by reference, fixed based on TC_TIMESYNC results
fessehaeve Jun 28, 2023
c0d7ad7
apply restyler patch
fessehaeve Jun 28, 2023
80afe93
fix readability-else-after-return
fessehaeve Jun 29, 2023
23dd47e
Merge remote-tracking branch 'origin/master' into pull-request/time-s…
fessehaeve Jun 29, 2023
e57c01e
kickout all DST items if they are all in the past
fessehaeve Jun 29, 2023
abb7a80
use const and reference whenever possible
fessehaeve Jun 30, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
added mechanisms to get local time and set utc time from application
  • Loading branch information
fessehaeve committed May 9, 2023
commit f0c59435ea50fdd352982f8ab4636dd899d68f10
Original file line number Diff line number Diff line change
Expand Up @@ -93,9 +93,9 @@ CHIP_ERROR TimeSyncDataProvider::StoreTimeZone(const TimeZone & timeZoneList)
writer.Init(buffer);
ReturnErrorOnFailure(writer.StartContainer(TLV::AnonymousTag(), TLV::kTLVType_Array, outerType));

for (auto const & timeZoneIter : timeZoneList)
for (auto const & timeZone : timeZoneList)
{
ReturnErrorOnFailure(timeZoneIter.Encode(writer, TLV::AnonymousTag()));
ReturnErrorOnFailure(timeZone.Encode(writer, TLV::AnonymousTag()));
}

ReturnErrorOnFailure(writer.EndContainer(outerType));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,21 @@ Delegate * GetDefaultDelegate()
} // namespace app
} // namespace chip

static CHIP_ERROR utcTimeChanged(uint64_t utcTime)
{
System::Clock::Seconds32 lastKnownGoodChipEpoch;
uint32_t utcTimeInChipEpoch;

ReturnErrorOnFailure(Server::GetInstance().GetFabricTable().GetLastKnownGoodChipEpochTime(lastKnownGoodChipEpoch));
chip::UnixEpochToChipEpochTime((uint32_t)(utcTime / chip::kMicrosecondsPerSecond), utcTimeInChipEpoch);
// if ( lastKnownGoodChipEpoch > utcTimeInChipEpoch) return CHIP_ERROR_INVALID_TIME;
ReturnErrorOnFailure(
Server::GetInstance().GetFabricTable().SetLastKnownGoodChipEpochTime(System::Clock::Seconds32(utcTimeInChipEpoch)));
ReturnErrorOnFailure(System::SystemClock().SetClock_RealTime(System::Clock::Microseconds64(utcTime)));

return CHIP_NO_ERROR;
}

TimeSynchronizationServer TimeSynchronizationServer::mTimeSyncInstance;

TimeSynchronizationServer & TimeSynchronizationServer::Instance()
Expand Down Expand Up @@ -145,6 +160,14 @@ CHIP_ERROR TimeSynchronizationServer::SetDefaultNtp(DataModel::Nullable<chip::Ch

CHIP_ERROR TimeSynchronizationServer::SetTimeZone(DataModel::DecodableList<TimeSynchronization::Structs::TimeZoneStruct::Type> tz)
{
size_t items;
ReturnErrorOnFailure(tz.ComputeSize(&items));

if (items > CHIP_CONFIG_TIME_ZONE_LIST_MAX_SIZE)
{
return CHIP_ERROR_BUFFER_TOO_SMALL;
}

auto tzL = mTimeZoneList.begin();
auto newTzL = tz.begin();
uint8_t i = 0;
Expand All @@ -171,6 +194,14 @@ CHIP_ERROR TimeSynchronizationServer::SetTimeZone(DataModel::DecodableList<TimeS
CHIP_ERROR
TimeSynchronizationServer::SetDSTOffset(DataModel::DecodableList<TimeSynchronization::Structs::DSTOffsetStruct::Type> dst)
{
size_t items;
ReturnErrorOnFailure(dst.ComputeSize(&items));

if (items > CHIP_CONFIG_DST_OFFSET_LIST_MAX_SIZE)
{
return CHIP_ERROR_BUFFER_TOO_SMALL;
}

auto dstL = mDstOffsetList.begin();
auto newDstL = dst.begin();
uint8_t i = 0;
Expand Down Expand Up @@ -223,13 +254,21 @@ void TimeSynchronizationServer::ScheduleDelayedAction(System::Clock::Seconds32 d
CHIP_NO_ERROR);
}

namespace {
CHIP_ERROR TimeSynchronizationServer::SetUTCTime(chip::EndpointId ep, uint64_t utcTime,
TimeSynchronization::GranularityEnum granularity,
TimeSynchronization::TimeSourceEnum source)
{
ReturnErrorOnFailure(utcTimeChanged(utcTime));
Granularity::Set(ep, granularity);
TimeSource::Set(ep, source);
return CHIP_NO_ERROR;
}

static bool computeLocalTime(chip::EndpointId ep, uint64_t & localTime)
CHIP_ERROR TimeSynchronizationServer::GetLocalTime(chip::EndpointId ep, uint64_t & localTime)
{
int32_t timeZoneOffset = 0, dstOffset = 0;
System::Clock::Microseconds64 utcTime;
VerifyOrReturnValue(System::SystemClock().GetClock_RealTime(utcTime) == CHIP_NO_ERROR, false);
ReturnErrorOnFailure(System::SystemClock().GetClock_RealTime(utcTime));
auto tz = TimeSynchronizationServer::Instance().GetTimeZone().begin();
auto dst = TimeSynchronizationServer::Instance().GetDSTOffset().begin();
if (tz->validAt <= utcTime.count())
Expand All @@ -241,9 +280,11 @@ static bool computeLocalTime(chip::EndpointId ep, uint64_t & localTime)
dstOffset = dst->offset;
}
localTime = (utcTime.count() + static_cast<uint64_t>(timeZoneOffset) + static_cast<uint64_t>(dstOffset));
return true;
return CHIP_NO_ERROR;
}

namespace {

class TimeSynchronizationAttrAccess : public AttributeAccessInterface
{
public:
Expand All @@ -257,6 +298,7 @@ class TimeSynchronizationAttrAccess : public AttributeAccessInterface
CHIP_ERROR ReadDefaultNtp(EndpointId endpoint, AttributeValueEncoder & aEncoder);
CHIP_ERROR ReadTimeZone(EndpointId endpoint, AttributeValueEncoder & aEncoder);
CHIP_ERROR ReadDSTOffset(EndpointId endpoint, AttributeValueEncoder & aEncoder);
CHIP_ERROR ReadLocalTime(EndpointId endpoint, AttributeValueEncoder & aEncoder);
};

TimeSynchronizationAttrAccess gAttrAccess;
Expand Down Expand Up @@ -314,6 +356,21 @@ CHIP_ERROR TimeSynchronizationAttrAccess::ReadDSTOffset(EndpointId endpoint, Att
return err;
}

CHIP_ERROR TimeSynchronizationAttrAccess::ReadLocalTime(EndpointId endpoint, AttributeValueEncoder & aEncoder)
{
uint64_t localTime = 0;
CHIP_ERROR err = TimeSynchronizationServer::Instance().GetLocalTime(endpoint, localTime);
if (err != CHIP_NO_ERROR)
{
err = aEncoder.EncodeNull();
}
else
{
err = aEncoder.Encode(localTime);
}
return err;
}

CHIP_ERROR TimeSynchronizationAttrAccess::Read(const ConcreteReadAttributePath & aPath, AttributeValueEncoder & aEncoder)
{
CHIP_ERROR err = CHIP_NO_ERROR;
Expand Down Expand Up @@ -342,7 +399,7 @@ CHIP_ERROR TimeSynchronizationAttrAccess::Read(const ConcreteReadAttributePath &
case DSTOffset::Id: {
return ReadDSTOffset(aPath.mEndpointId, aEncoder);
}
case TimeZoneListMaxSize::Id: { // can't find a way to initialize default value for F quality
case TimeZoneListMaxSize::Id: {
uint8_t max = CHIP_CONFIG_TIME_ZONE_LIST_MAX_SIZE;
return aEncoder.Encode(max);
}
Expand All @@ -351,9 +408,7 @@ CHIP_ERROR TimeSynchronizationAttrAccess::Read(const ConcreteReadAttributePath &
return aEncoder.Encode(max);
}
case LocalTime::Id: {
uint64_t localTime = 0;
VerifyOrReturnError(computeLocalTime(aPath.mEndpointId, localTime), aEncoder.EncodeNull());
return aEncoder.Encode(localTime);
return ReadLocalTime(aPath.mEndpointId, aEncoder);
}
default: {
break;
Expand Down Expand Up @@ -460,26 +515,6 @@ static bool sendMissingTrustedTimeSource(chip::EndpointId endpointId)
return true;
}

static bool utcTimeChanged(uint64_t utcTime)
{
System::Clock::Seconds32 lastKnownGoodChipEpoch;
System::Clock::Microseconds64 realTime;
uint32_t utcTimetoChipEpoch;

Server::GetInstance().GetFabricTable().GetLastKnownGoodChipEpochTime(lastKnownGoodChipEpoch);
System::SystemClock().GetClock_RealTime(realTime);
chip::UnixEpochToChipEpochTime((uint32_t)(utcTime / chip::kMicrosecondsPerSecond), utcTimetoChipEpoch);

VerifyOrReturnValue(Server::GetInstance().GetFabricTable().SetLastKnownGoodChipEpochTime(
System::Clock::Seconds32(utcTimetoChipEpoch)) == CHIP_NO_ERROR,
false);
VerifyOrReturnValue(System::SystemClock().SetClock_RealTime(System::Clock::Microseconds64(utcTime)) == CHIP_NO_ERROR, false);

Server::GetInstance().GetFabricTable().GetLastKnownGoodChipEpochTime(lastKnownGoodChipEpoch);
System::SystemClock().GetClock_RealTime(realTime);
return true;
}

bool emberAfTimeSynchronizationClusterSetUTCTimeCallback(
chip::app::CommandHandler * commandObj, const chip::app::ConcreteCommandPath & commandPath,
const chip::app::Clusters::TimeSynchronization::Commands::SetUTCTime::DecodableType & commandData)
Expand All @@ -491,10 +526,10 @@ bool emberAfTimeSynchronizationClusterSetUTCTimeCallback(
Granularity::Get(commandPath.mEndpointId, &currentGranularity);

if ((currentGranularity == TimeSynchronization::GranularityEnum::kNoTimeGranularity || granularity >= currentGranularity) &&
utcTimeChanged(utcTime))
CHIP_NO_ERROR ==
TimeSynchronizationServer::Instance().SetUTCTime(commandPath.mEndpointId, utcTime, granularity,
TimeSynchronization::TimeSourceEnum::kAdmin))
{
Granularity::Set(commandPath.mEndpointId, granularity);
TimeSource::Set(commandPath.mEndpointId, TimeSynchronization::TimeSourceEnum::kAdmin);
commandObj->AddStatus(commandPath, Status::Success);
}
else
Expand Down Expand Up @@ -535,23 +570,21 @@ bool emberAfTimeSynchronizationClusterSetTimeZoneCallback(
const chip::app::Clusters::TimeSynchronization::Commands::SetTimeZone::DecodableType & commandData)
{
const auto & timeZone = commandData.timeZone;
size_t items;
uint8_t maxSize = 0;
uint64_t localTime;
VerifyOrReturnValue(timeZone.ComputeSize(&items) == CHIP_NO_ERROR, false);
TimeZoneListMaxSize::Get(commandPath.mEndpointId, &maxSize);

if (items > maxSize || items > CHIP_CONFIG_TIME_ZONE_LIST_MAX_SIZE)
{
commandObj->AddStatus(commandPath, Status::ResourceExhausted);
return true;
}
// first element shall have validAt entry of 0
// if second element, it shall have validAt entry of non-0

if (CHIP_NO_ERROR != TimeSynchronizationServer::Instance().SetTimeZone(timeZone))
CHIP_ERROR err = TimeSynchronizationServer::Instance().SetTimeZone(timeZone);
if (err != CHIP_NO_ERROR)
{
commandObj->AddStatus(commandPath, Status::ConstraintError);
if (err == CHIP_ERROR_BUFFER_TOO_SMALL)
{
commandObj->AddStatus(commandPath, Status::ResourceExhausted);
}
else
{
commandObj->AddStatus(commandPath, Status::ConstraintError);
}
return true;
}
sendTimeZoneStatus(commandPath.mEndpointId, 0);
Expand Down Expand Up @@ -579,7 +612,7 @@ bool emberAfTimeSynchronizationClusterSetTimeZoneCallback(
sendDSTStatus(commandPath.mEndpointId, false);
}
}
computeLocalTime(commandPath.mEndpointId, localTime);
TimeSynchronizationServer::Instance().GetLocalTime(commandPath.mEndpointId, localTime);
response.DSTOffsetRequired = true;
commandObj->AddResponse(commandPath, response);
return true;
Expand All @@ -590,25 +623,23 @@ bool emberAfTimeSynchronizationClusterSetDSTOffsetCallback(
const chip::app::Clusters::TimeSynchronization::Commands::SetDSTOffset::DecodableType & commandData)
{
const auto & dstOffset = commandData.DSTOffset;
size_t items;
uint8_t maxSize = 0;
VerifyOrReturnValue(dstOffset.ComputeSize(&items) == CHIP_NO_ERROR, false);
DSTOffsetListMaxSize::Get(commandPath.mEndpointId, &maxSize);

if (items > maxSize && items > CHIP_CONFIG_DST_OFFSET_LIST_MAX_SIZE)
{
commandObj->AddStatus(commandPath, Status::ResourceExhausted);
return true;
}

// sorted by ValidStarting time
// ValidStartingTime shall not be smaller than ValidUntil time of previous entry
// only 1 validuntil null value and shall be last in the list
// remove entries which are no longer active
// if offset == 0 && ValidUntil == null then no DST is used
if (CHIP_NO_ERROR != TimeSynchronizationServer::Instance().SetDSTOffset(dstOffset))
CHIP_ERROR err = TimeSynchronizationServer::Instance().SetDSTOffset(dstOffset);
if (err != CHIP_NO_ERROR)
{
commandObj->AddStatus(commandPath, Status::ConstraintError);
if (err == CHIP_ERROR_BUFFER_TOO_SMALL)
{
commandObj->AddStatus(commandPath, Status::ResourceExhausted);
}
else
{
commandObj->AddStatus(commandPath, Status::ConstraintError);
}
return true;
}
// if DST state changes, generate DSTStatus event
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,10 @@ class TimeSynchronizationServer
DataModel::List<TimeSynchronization::Structs::TimeZoneStruct::Type> & GetTimeZone(void);
DataModel::List<TimeSynchronization::Structs::DSTOffsetStruct::Type> & GetDSTOffset(void);

CHIP_ERROR SetUTCTime(chip::EndpointId ep, uint64_t utcTime, TimeSynchronization::GranularityEnum granularity,
TimeSynchronization::TimeSourceEnum source);
CHIP_ERROR GetLocalTime(chip::EndpointId ep, uint64_t & localTime);

void ScheduleDelayedAction(System::Clock::Seconds32 delay, System::TimerCompleteCallback action, void * aAppState);

private:
Expand Down