|
74 | 74 | NSString * const MTRNullValueType = @"Null";
|
75 | 75 | NSString * const MTRStructureValueType = @"Structure";
|
76 | 76 | NSString * const MTRArrayValueType = @"Array";
|
| 77 | +NSString * const MTREventNumberKey = @"eventNumber"; |
| 78 | +NSString * const MTREventPriorityKey = @"eventPriority"; |
| 79 | +NSString * const MTREventTimeTypeKey = @"eventTimeType"; |
| 80 | +NSString * const MTREventSystemUpTimeKey = @"eventSystemUpTime"; |
| 81 | +NSString * const MTREventTimestampDateKey = @"eventTimestampDate"; |
77 | 82 |
|
78 | 83 | class MTRDataValueDictionaryCallbackBridge;
|
79 | 84 |
|
@@ -752,7 +757,7 @@ CHIP_ERROR Encode(chip::TLV::TLVWriter & writer, chip::TLV::Tag tag) const
|
752 | 757 | public:
|
753 | 758 | using OnSuccessAttributeCallbackType
|
754 | 759 | = std::function<void(const ConcreteAttributePath & aPath, const DecodableValueType & aData)>;
|
755 |
| - using OnSuccessEventCallbackType = std::function<void(const ConcreteEventPath & aPath, const DecodableValueType & aData)>; |
| 760 | + using OnSuccessEventCallbackType = std::function<void(const EventHeader & aEventHeader, const DecodableValueType & aData)>; |
756 | 761 | using OnErrorCallbackType = std::function<void(
|
757 | 762 | const app::ConcreteAttributePath * attributePath, const app::ConcreteEventPath * eventPath, CHIP_ERROR aError)>;
|
758 | 763 | using OnDoneCallbackType = std::function<void(BufferedReadClientCallback * callback)>;
|
@@ -844,7 +849,7 @@ void OnEventData(const EventHeader & aEventHeader, TLV::TLVReader * apData, cons
|
844 | 849 |
|
845 | 850 | SuccessOrExit(err = app::DataModel::Decode(*apData, value));
|
846 | 851 |
|
847 |
| - mOnEventSuccess(aEventHeader.mPath, value); |
| 852 | + mOnEventSuccess(aEventHeader, value); |
848 | 853 |
|
849 | 854 | exit:
|
850 | 855 | if (err != CHIP_NO_ERROR) {
|
@@ -944,31 +949,28 @@ - (void)readAttributePaths:(NSArray<MTRAttributeRequestPath *> * _Nullable)attri
|
944 | 949 |
|
945 | 950 | auto resultArray = [[NSMutableArray alloc] init];
|
946 | 951 | auto onAttributeSuccessCb
|
947 |
| - = [resultArray](const ConcreteAttributePath & attributePath, const MTRDataValueDictionaryDecodableType & aData) { |
| 952 | + = [resultArray](const ConcreteAttributePath & aAttributePath, const MTRDataValueDictionaryDecodableType & aData) { |
948 | 953 | [resultArray addObject:@ {
|
949 |
| - MTRAttributePathKey : [[MTRAttributePath alloc] initWithPath:attributePath], |
| 954 | + MTRAttributePathKey : [[MTRAttributePath alloc] initWithPath:aAttributePath], |
950 | 955 | MTRDataKey : aData.GetDecodedObject()
|
951 | 956 | }];
|
952 | 957 | };
|
953 | 958 |
|
954 | 959 | auto onEventSuccessCb
|
955 |
| - = [resultArray](const ConcreteEventPath & eventPath, const MTRDataValueDictionaryDecodableType & aData) { |
956 |
| - [resultArray addObject:@ { |
957 |
| - MTREventPathKey : [[MTREventPath alloc] initWithPath:eventPath], |
958 |
| - MTRDataKey : aData.GetDecodedObject() |
959 |
| - }]; |
| 960 | + = [resultArray](const EventHeader & aEventHeader, const MTRDataValueDictionaryDecodableType & aData) { |
| 961 | + [resultArray addObject:[MTRBaseDevice eventReportForHeader:aEventHeader andData:aData.GetDecodedObject()]]; |
960 | 962 | };
|
961 | 963 |
|
962 |
| - auto onFailureCb = [resultArray, interactionStatus](const app::ConcreteAttributePath * attributePath, |
963 |
| - const app::ConcreteEventPath * eventPath, CHIP_ERROR aError) { |
964 |
| - if (attributePath != nullptr) { |
| 964 | + auto onFailureCb = [resultArray, interactionStatus](const app::ConcreteAttributePath * aAttributePath, |
| 965 | + const app::ConcreteEventPath * aEventPath, CHIP_ERROR aError) { |
| 966 | + if (aAttributePath != nullptr) { |
965 | 967 | [resultArray addObject:@ {
|
966 |
| - MTRAttributePathKey : [[MTRAttributePath alloc] initWithPath:*attributePath], |
| 968 | + MTRAttributePathKey : [[MTRAttributePath alloc] initWithPath:*aAttributePath], |
967 | 969 | MTRErrorKey : [MTRError errorForCHIPErrorCode:aError]
|
968 | 970 | }];
|
969 |
| - } else if (eventPath != nullptr) { |
| 971 | + } else if (aEventPath != nullptr) { |
970 | 972 | [resultArray addObject:@ {
|
971 |
| - MTREventPathKey : [[MTREventPath alloc] initWithPath:*eventPath], |
| 973 | + MTREventPathKey : [[MTREventPath alloc] initWithPath:*aEventPath], |
972 | 974 | MTRErrorKey : [MTRError errorForCHIPErrorCode:aError]
|
973 | 975 | }];
|
974 | 976 | } else {
|
@@ -1343,14 +1345,11 @@ - (void)subscribeToAttributePaths:(NSArray<MTRAttributeRequestPath *> * _Nullabl
|
1343 | 1345 | });
|
1344 | 1346 | };
|
1345 | 1347 |
|
1346 |
| - auto onEventReportCb = [queue, reportHandler](const ConcreteEventPath & eventPath, |
1347 |
| - const MTRDataValueDictionaryDecodableType & data) { |
1348 |
| - id valueObject = data.GetDecodedObject(); |
1349 |
| - ConcreteEventPath pathCopy(eventPath); |
| 1348 | + auto onEventReportCb = [queue, reportHandler]( |
| 1349 | + const EventHeader & eventHeader, const MTRDataValueDictionaryDecodableType & data) { |
| 1350 | + NSDictionary * report = [MTRBaseDevice eventReportForHeader:eventHeader andData:data.GetDecodedObject()]; |
1350 | 1351 | dispatch_async(queue, ^{
|
1351 |
| - reportHandler( |
1352 |
| - @[ @ { MTREventPathKey : [[MTREventPath alloc] initWithPath:pathCopy], MTRDataKey : valueObject } ], |
1353 |
| - nil); |
| 1352 | + reportHandler(@[ report ], nil); |
1354 | 1353 | });
|
1355 | 1354 | };
|
1356 | 1355 |
|
@@ -1540,6 +1539,43 @@ static CHIP_ERROR OpenCommissioningWindow(Controller::DeviceController * control
|
1540 | 1539 | delete self;
|
1541 | 1540 | }
|
1542 | 1541 |
|
| 1542 | +#pragma mark - Utility for time conversion |
| 1543 | +NSTimeInterval MTRTimeIntervalForEventTimestampValue(uint64_t timeValue) |
| 1544 | +{ |
| 1545 | + // Note: The event timestamp value as written in the spec is in microseconds, but the released 1.0 SDK implemented it in |
| 1546 | + // milliseconds. The following issue was filed to address the inconsistency: |
| 1547 | + // https://github.com/CHIP-Specifications/connectedhomeip-spec/issues/6236 |
| 1548 | + // For consistency with the released behavior, calculations here will be done in milliseconds. |
| 1549 | + |
| 1550 | + // First convert the event timestamp value (in milliseconds) to NSTimeInterval - to minimize potential loss of precision |
| 1551 | + // of uint64 => NSTimeInterval (double), convert whole seconds and remainder separately and then combine |
| 1552 | + uint64_t eventTimestampValueSeconds = timeValue / chip::kMillisecondsPerSecond; |
| 1553 | + uint64_t eventTimestampValueRemainderMilliseconds = timeValue % chip::kMillisecondsPerSecond; |
| 1554 | + NSTimeInterval eventTimestampValueRemainder |
| 1555 | + = NSTimeInterval(eventTimestampValueRemainderMilliseconds) / chip::kMillisecondsPerSecond; |
| 1556 | + NSTimeInterval eventTimestampValue = eventTimestampValueSeconds + eventTimestampValueRemainder; |
| 1557 | + |
| 1558 | + return eventTimestampValue; |
| 1559 | +} |
| 1560 | + |
| 1561 | +#pragma mark - Utility for event priority conversion |
| 1562 | +BOOL MTRPriorityLevelIsValid(chip::app::PriorityLevel priorityLevel) |
| 1563 | +{ |
| 1564 | + return (priorityLevel >= chip::app::PriorityLevel::Debug) && (priorityLevel <= chip::app::PriorityLevel::Critical); |
| 1565 | +} |
| 1566 | + |
| 1567 | +MTREventPriority MTREventPriorityForValidPriorityLevel(chip::app::PriorityLevel priorityLevel) |
| 1568 | +{ |
| 1569 | + switch (priorityLevel) { |
| 1570 | + case chip::app::PriorityLevel::Debug: |
| 1571 | + return MTREventPriorityDebug; |
| 1572 | + case chip::app::PriorityLevel::Info: |
| 1573 | + return MTREventPriorityInfo; |
| 1574 | + default: |
| 1575 | + return MTREventPriorityCritical; |
| 1576 | + } |
| 1577 | +} |
| 1578 | + |
1543 | 1579 | } // anonymous namespace
|
1544 | 1580 |
|
1545 | 1581 | - (void)_openCommissioningWindowWithSetupPasscode:(nullable NSNumber *)setupPasscode
|
@@ -1738,6 +1774,46 @@ - (void)subscribeToEventsWithEndpointID:(NSNumber * _Nullable)endpointID
|
1738 | 1774 | subscriptionEstablished:subscriptionEstablished
|
1739 | 1775 | resubscriptionScheduled:nil];
|
1740 | 1776 | }
|
| 1777 | + |
| 1778 | ++ (NSDictionary *)eventReportForHeader:(const chip::app::EventHeader &)header andData:(id _Nullable)data |
| 1779 | +{ |
| 1780 | + MTREventPath * eventPath = [[MTREventPath alloc] initWithPath:header.mPath]; |
| 1781 | + if (data == nil) { |
| 1782 | + MTR_LOG_ERROR("%@ could not decode event data", eventPath); |
| 1783 | + return @{ MTREventPathKey : eventPath, MTRErrorKey : [MTRError errorForCHIPErrorCode:CHIP_ERROR_INVALID_ARGUMENT] }; |
| 1784 | + } |
| 1785 | + |
| 1786 | + // Construct the right type, and key/value depending on the type |
| 1787 | + NSNumber * eventTimeType; |
| 1788 | + NSString * timestampKey; |
| 1789 | + id timestampValue; |
| 1790 | + if (header.mTimestamp.mType == Timestamp::Type::kSystem) { |
| 1791 | + eventTimeType = @(MTREventTimeTypeSystemUpTime); |
| 1792 | + timestampKey = MTREventSystemUpTimeKey; |
| 1793 | + timestampValue = @(MTRTimeIntervalForEventTimestampValue(header.mTimestamp.mValue)); |
| 1794 | + } else if (header.mTimestamp.mType == Timestamp::Type::kEpoch) { |
| 1795 | + eventTimeType = @(MTREventTimeTypeTimestampDate); |
| 1796 | + timestampKey = MTREventTimestampDateKey; |
| 1797 | + timestampValue = [NSDate dateWithTimeIntervalSince1970:MTRTimeIntervalForEventTimestampValue(header.mTimestamp.mValue)]; |
| 1798 | + } else { |
| 1799 | + MTR_LOG_ERROR("%@ Unsupported event timestamp type %u - ignoring", eventPath, (unsigned int) header.mTimestamp.mType); |
| 1800 | + return @{ MTREventPathKey : eventPath, MTRErrorKey : [MTRError errorForCHIPErrorCode:CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE] }; |
| 1801 | + } |
| 1802 | + |
| 1803 | + if (!MTRPriorityLevelIsValid(header.mPriorityLevel)) { |
| 1804 | + MTR_LOG_ERROR("%@ Unsupported event priority %u - ignoring", eventPath, (unsigned int) header.mPriorityLevel); |
| 1805 | + return @{ MTREventPathKey : eventPath, MTRErrorKey : [MTRError errorForCHIPErrorCode:CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE] }; |
| 1806 | + } |
| 1807 | + |
| 1808 | + return @{ |
| 1809 | + MTREventPathKey : eventPath, |
| 1810 | + MTRDataKey : data, |
| 1811 | + MTREventNumberKey : @(header.mEventNumber), |
| 1812 | + MTREventPriorityKey : @(MTREventPriorityForValidPriorityLevel(header.mPriorityLevel)), |
| 1813 | + MTREventTimeTypeKey : eventTimeType, |
| 1814 | + timestampKey : timestampValue |
| 1815 | + }; |
| 1816 | +} |
1741 | 1817 | @end
|
1742 | 1818 |
|
1743 | 1819 | @implementation MTRBaseDevice (Deprecated)
|
|
0 commit comments