|
33 | 33 | #import "MTRError_Internal.h"
|
34 | 34 | #import "MTREventTLVValueDecoder_Internal.h"
|
35 | 35 | #import "MTRLogging_Internal.h"
|
| 36 | +#import "MTRTimeUtils.h" |
36 | 37 | #import "MTRUnfairLock.h"
|
37 | 38 | #import "zap-generated/MTRCommandPayloads_Internal.h"
|
38 | 39 |
|
@@ -270,41 +271,50 @@ - (void)_setTimeOnDevice
|
270 | 271 | return;
|
271 | 272 | }
|
272 | 273 |
|
273 |
| - NSTimeZone * localTimeZone = [NSTimeZone localTimeZone]; |
274 |
| - BOOL setDST = TRUE; |
275 |
| - if (!localTimeZone) { |
276 |
| - MTR_LOG_ERROR("%@ Could not retrieve local time zone. Unable to setDSTOffset on endpoints.", self); |
277 |
| - setDST = FALSE; |
278 |
| - } |
279 |
| - |
280 | 274 | uint64_t matterEpochTimeMicroseconds = 0;
|
281 |
| - uint64_t nextDSTInMatterEpochTimeMicroseconds = 0; |
282 | 275 | if (!DateToMatterEpochMicroseconds(now, matterEpochTimeMicroseconds)) {
|
283 | 276 | MTR_LOG_ERROR("%@ Could not convert NSDate (%@) to Matter Epoch Time. Unable to setUTCTime on endpoints.", self, now);
|
284 | 277 | return;
|
285 | 278 | }
|
286 | 279 |
|
287 |
| - int32_t dstOffset = 0; |
288 |
| - if (setDST) { |
289 |
| - NSTimeInterval dstOffsetAsInterval = [localTimeZone daylightSavingTimeOffsetForDate:now]; |
290 |
| - dstOffset = int32_t(dstOffsetAsInterval); |
291 |
| - |
292 |
| - // Calculate time to next DST. This is needed when we set the current DST. |
293 |
| - NSDate * nextDSTTransitionDate = [localTimeZone nextDaylightSavingTimeTransition]; |
294 |
| - if (!DateToMatterEpochMicroseconds(nextDSTTransitionDate, nextDSTInMatterEpochTimeMicroseconds)) { |
295 |
| - MTR_LOG_ERROR("%@ Could not convert NSDate (%@) to Matter Epoch Time. Unable to setDSTOffset on endpoints.", self, nextDSTTransitionDate); |
296 |
| - setDST = FALSE; |
297 |
| - } |
298 |
| - } |
299 |
| - |
300 | 280 | // Set Time on each Endpoint with a Time Synchronization Cluster Server
|
301 | 281 | NSArray<NSNumber *> * endpointsToSync = [self _endpointsWithTimeSyncClusterServer];
|
302 | 282 | for (NSNumber * endpoint in endpointsToSync) {
|
303 | 283 | MTR_LOG_DEBUG("%@ Setting Time on Endpoint %@", self, endpoint);
|
304 | 284 | [self _setUTCTime:matterEpochTimeMicroseconds withGranularity:MTRTimeSynchronizationGranularityMicrosecondsGranularity forEndpoint:endpoint];
|
305 |
| - if (setDST) { |
306 |
| - [self _setDSTOffset:dstOffset validStarting:0 validUntil:nextDSTInMatterEpochTimeMicroseconds forEndpoint:endpoint]; |
| 285 | + |
| 286 | + // Check how many DST offsets this endpoint supports. |
| 287 | + auto dstOffsetsMaxSizePath = [MTRAttributePath attributePathWithEndpointID:endpoint clusterID:@(MTRClusterIDTypeTimeSynchronizationID) attributeID:@(MTRAttributeIDTypeClusterTimeSynchronizationAttributeDSTOffsetListMaxSizeID)]; |
| 288 | + auto dstOffsetsMaxSize = [self readAttributeWithEndpointID:dstOffsetsMaxSizePath.endpoint clusterID:dstOffsetsMaxSizePath.cluster attributeID:dstOffsetsMaxSizePath.attribute params:nil]; |
| 289 | + if (dstOffsetsMaxSize == nil) { |
| 290 | + // This endpoint does not support TZ, so won't support SetDSTOffset. |
| 291 | + MTR_LOG_DEFAULT("%@ Unable to SetDSTOffset on endpoint %@, since it does not support the TZ feature", self, endpoint); |
| 292 | + continue; |
307 | 293 | }
|
| 294 | + auto attrReport = [[MTRAttributeReport alloc] initWithResponseValue:@{ |
| 295 | + MTRAttributePathKey : dstOffsetsMaxSizePath, |
| 296 | + MTRDataKey : dstOffsetsMaxSize, |
| 297 | + } |
| 298 | + error:nil]; |
| 299 | + uint8_t maxOffsetCount; |
| 300 | + if (attrReport == nil) { |
| 301 | + MTR_LOG_ERROR("%@ DSTOffsetListMaxSize value on endpoint %@ is invalid. Defaulting to 1.", self, endpoint); |
| 302 | + maxOffsetCount = 1; |
| 303 | + } else { |
| 304 | + NSNumber * maxOffsetCountAsNumber = attrReport.value; |
| 305 | + maxOffsetCount = maxOffsetCountAsNumber.unsignedCharValue; |
| 306 | + if (maxOffsetCount == 0) { |
| 307 | + MTR_LOG_ERROR("%@ DSTOffsetListMaxSize value on endpoint %@ is 0, which is not allowed. Defaulting to 1.", self, endpoint); |
| 308 | + maxOffsetCount = 1; |
| 309 | + } |
| 310 | + } |
| 311 | + auto * dstOffsets = MTRComputeDSTOffsets(maxOffsetCount); |
| 312 | + if (dstOffsets == nil) { |
| 313 | + MTR_LOG_ERROR("%@ Could not retrieve DST offset information. Unable to setDSTOffset on endpoint %@.", self, endpoint); |
| 314 | + continue; |
| 315 | + } |
| 316 | + |
| 317 | + [self _setDSTOffsets:dstOffsets forEndpoint:endpoint]; |
308 | 318 | }
|
309 | 319 | }
|
310 | 320 |
|
@@ -410,23 +420,18 @@ - (void)_setUTCTime:(UInt64)matterEpochTime withGranularity:(uint8_t)granularity
|
410 | 420 | completion:setUTCTimeResponseHandler];
|
411 | 421 | }
|
412 | 422 |
|
413 |
| -- (void)_setDSTOffset:(int32_t)dstOffset validStarting:(uint64_t)validStarting validUntil:(uint64_t)validUntil forEndpoint:(NSNumber *)endpoint |
| 423 | +- (void)_setDSTOffsets:(NSArray<MTRTimeSynchronizationClusterDSTOffsetStruct *> *)dstOffsets forEndpoint:(NSNumber *)endpoint |
414 | 424 | {
|
415 |
| - MTR_LOG_DEBUG("%@ _setDSTOffset with offset: %d, validStarting: %llu, validUntil: %llu, endpoint %@", |
416 |
| - self, |
417 |
| - dstOffset, validStarting, validUntil, endpoint); |
| 425 | + MTR_LOG_DEBUG("%@ _setDSTOffsets with offsets: %@, endpoint %@", |
| 426 | + self, dstOffsets, endpoint); |
418 | 427 |
|
419 | 428 | MTRTimeSynchronizationClusterSetDSTOffsetParams * params = [[MTRTimeSynchronizationClusterSetDSTOffsetParams
|
420 | 429 | alloc] init];
|
421 |
| - MTRTimeSynchronizationClusterDSTOffsetStruct * dstOffsetStruct = [[MTRTimeSynchronizationClusterDSTOffsetStruct alloc] init]; |
422 |
| - dstOffsetStruct.offset = @(dstOffset); |
423 |
| - dstOffsetStruct.validStarting = @(validStarting); |
424 |
| - dstOffsetStruct.validUntil = @(validUntil); |
425 |
| - params.dstOffset = @[ dstOffsetStruct ]; |
| 430 | + params.dstOffset = dstOffsets; |
426 | 431 |
|
427 | 432 | auto setDSTOffsetResponseHandler = ^(id _Nullable response, NSError * _Nullable error) {
|
428 | 433 | if (error) {
|
429 |
| - MTR_LOG_ERROR("%@ _setDSTOffset failed on endpoint %@, with parameters %@, error: %@", self, endpoint, params, error); |
| 434 | + MTR_LOG_ERROR("%@ _setDSTOffsets failed on endpoint %@, with parameters %@, error: %@", self, endpoint, params, error); |
430 | 435 | }
|
431 | 436 | };
|
432 | 437 |
|
|
0 commit comments