main.cpp 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680
  1. /*
  2. *
  3. * Copyright (c) 2021 Project CHIP Authors
  4. * All rights reserved.
  5. *
  6. * Licensed under the Apache License, Version 2.0 (the "License");
  7. * you may not use this file except in compliance with the License.
  8. * You may obtain a copy of the License at
  9. *
  10. * http://www.apache.org/licenses/LICENSE-2.0
  11. *
  12. * Unless required by applicable law or agreed to in writing, software
  13. * distributed under the License is distributed on an "AS IS" BASIS,
  14. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  15. * See the License for the specific language governing permissions and
  16. * limitations under the License.
  17. */
  18. #include <platform/CHIPDeviceLayer.h>
  19. #include <platform/PlatformManager.h>
  20. #include <app-common/zap-generated/af-structs.h>
  21. #include <app-common/zap-generated/attribute-id.h>
  22. #include <app-common/zap-generated/cluster-id.h>
  23. #include <app/chip-zcl-zpro-codec.h>
  24. #include <app/reporting/reporting.h>
  25. #include <app/util/af-types.h>
  26. #include <app/util/af.h>
  27. #include <app/util/attribute-storage.h>
  28. #include <app/util/util.h>
  29. #include <credentials/DeviceAttestationCredsProvider.h>
  30. #include <credentials/examples/DeviceAttestationCredsExample.h>
  31. #include <lib/core/CHIPError.h>
  32. #include <lib/support/CHIPMem.h>
  33. #include <lib/support/ZclString.h>
  34. #include <setup_payload/QRCodeSetupPayloadGenerator.h>
  35. #include <setup_payload/SetupPayload.h>
  36. #include "Device.h"
  37. #include "Options.h"
  38. #include <app/server/Server.h>
  39. #include <cassert>
  40. #include <iostream>
  41. using namespace chip;
  42. using namespace chip::Credentials;
  43. using namespace chip::Inet;
  44. using namespace chip::Transport;
  45. using namespace chip::DeviceLayer;
  46. static const int kNodeLabelSize = 32;
  47. // Current ZCL implementation of Struct uses a max-size array of 254 bytes
  48. static const int kDescriptorAttributeArraySize = 254;
  49. static const int kFixedLabelAttributeArraySize = 254;
  50. // Four attributes in descriptor cluster: DeviceTypeList, ServerList, ClientList, PartsList
  51. static const int kFixedLabelElementsOctetStringSize = 16;
  52. static EndpointId gCurrentEndpointId;
  53. static EndpointId gFirstDynamicEndpointId;
  54. static Device * gDevices[CHIP_DEVICE_CONFIG_DYNAMIC_ENDPOINT_COUNT];
  55. // ENDPOINT DEFINITIONS:
  56. // =================================================================================
  57. //
  58. // Endpoint definitions will be reused across multiple endpoints for every instance of the
  59. // endpoint type.
  60. // There will be no intrinsic storage for the endpoint attributes declared here.
  61. // Instead, all attributes will be treated as EXTERNAL, and therefore all reads
  62. // or writes to the attributes must be handled within the emberAfExternalAttributeWriteCallback
  63. // and emberAfExternalAttributeReadCallback functions declared herein. This fits
  64. // the typical model of a bridge, since a bridge typically maintains its own
  65. // state database representing the devices connected to it.
  66. // Device types for dynamic endpoints: TODO Need a generated file from ZAP to define these!
  67. // (taken from chip-devices.xml)
  68. #define DEVICE_TYPE_CHIP_BRIDGE 0x0a0b
  69. // (taken from lo-devices.xml)
  70. #define DEVICE_TYPE_LO_ON_OFF_LIGHT 0x0100
  71. // (taken from lo-devices.xml)
  72. #define DEVICE_TYPE_LO_ON_OFF_LIGHT_SWITCH 0x0103
  73. // Device Version for dynamic endpoints:
  74. #define DEVICE_VERSION_DEFAULT 1
  75. // ---------------------------------------------------------------------------
  76. //
  77. // LIGHT ENDPOINT: contains the following clusters:
  78. // - On/Off
  79. // - Descriptor
  80. // - Bridged Device Basic
  81. // - Fixed Label
  82. // Declare On/Off cluster attributes
  83. DECLARE_DYNAMIC_ATTRIBUTE_LIST_BEGIN(onOffAttrs)
  84. DECLARE_DYNAMIC_ATTRIBUTE(ZCL_ON_OFF_ATTRIBUTE_ID, BOOLEAN, 1, 0), /* on/off */
  85. DECLARE_DYNAMIC_ATTRIBUTE_LIST_END();
  86. // Declare Descriptor cluster attributes
  87. DECLARE_DYNAMIC_ATTRIBUTE_LIST_BEGIN(descriptorAttrs)
  88. DECLARE_DYNAMIC_ATTRIBUTE(ZCL_DEVICE_LIST_ATTRIBUTE_ID, ARRAY, kDescriptorAttributeArraySize, 0), /* device list */
  89. DECLARE_DYNAMIC_ATTRIBUTE(ZCL_SERVER_LIST_ATTRIBUTE_ID, ARRAY, kDescriptorAttributeArraySize, 0), /* server list */
  90. DECLARE_DYNAMIC_ATTRIBUTE(ZCL_CLIENT_LIST_ATTRIBUTE_ID, ARRAY, kDescriptorAttributeArraySize, 0), /* client list */
  91. DECLARE_DYNAMIC_ATTRIBUTE(ZCL_PARTS_LIST_ATTRIBUTE_ID, ARRAY, kDescriptorAttributeArraySize, 0), /* parts list */
  92. DECLARE_DYNAMIC_ATTRIBUTE_LIST_END();
  93. // Declare Bridged Device Basic information cluster attributes
  94. DECLARE_DYNAMIC_ATTRIBUTE_LIST_BEGIN(bridgedDeviceBasicAttrs)
  95. DECLARE_DYNAMIC_ATTRIBUTE(ZCL_NODE_LABEL_ATTRIBUTE_ID, CHAR_STRING, kNodeLabelSize, 0), /* NodeLabel */
  96. DECLARE_DYNAMIC_ATTRIBUTE(ZCL_REACHABLE_ATTRIBUTE_ID, BOOLEAN, 1, 0), /* Reachable */
  97. DECLARE_DYNAMIC_ATTRIBUTE_LIST_END();
  98. // Declare Fixed Label cluster attributes
  99. DECLARE_DYNAMIC_ATTRIBUTE_LIST_BEGIN(fixedLabelAttrs)
  100. DECLARE_DYNAMIC_ATTRIBUTE(ZCL_LABEL_LIST_ATTRIBUTE_ID, ARRAY, kFixedLabelAttributeArraySize, 0), /* label list */
  101. DECLARE_DYNAMIC_ATTRIBUTE_LIST_END();
  102. // Declare Cluster List for Bridged Light endpoint
  103. DECLARE_DYNAMIC_CLUSTER_LIST_BEGIN(bridgedLightClusters)
  104. DECLARE_DYNAMIC_CLUSTER(ZCL_ON_OFF_CLUSTER_ID, onOffAttrs), DECLARE_DYNAMIC_CLUSTER(ZCL_DESCRIPTOR_CLUSTER_ID, descriptorAttrs),
  105. DECLARE_DYNAMIC_CLUSTER(ZCL_BRIDGED_DEVICE_BASIC_CLUSTER_ID, bridgedDeviceBasicAttrs),
  106. DECLARE_DYNAMIC_CLUSTER(ZCL_FIXED_LABEL_CLUSTER_ID, fixedLabelAttrs) DECLARE_DYNAMIC_CLUSTER_LIST_END;
  107. // Declare Bridged Light endpoint
  108. DECLARE_DYNAMIC_ENDPOINT(bridgedLightEndpoint, bridgedLightClusters);
  109. // ---------------------------------------------------------------------------
  110. //
  111. // SWITCH ENDPOINT: contains the following clusters:
  112. // - Switch
  113. // - Descriptor
  114. // - Bridged Device Basic
  115. // - Fixed Label
  116. // Declare Switch cluster attributes
  117. DECLARE_DYNAMIC_ATTRIBUTE_LIST_BEGIN(switchAttrs)
  118. DECLARE_DYNAMIC_ATTRIBUTE(ZCL_NUMBER_OF_POSITIONS_ATTRIBUTE_ID, INT8U, 1, 0), /* NumberOfPositions */
  119. DECLARE_DYNAMIC_ATTRIBUTE(ZCL_CURRENT_POSITION_ATTRIBUTE_ID, INT8U, 1, 0), /* CurrentPosition */
  120. DECLARE_DYNAMIC_ATTRIBUTE(ZCL_MULTI_PRESS_MAX_ATTRIBUTE_ID, INT8U, 1, 0), /* MultiPressMax */
  121. DECLARE_DYNAMIC_ATTRIBUTE(ZCL_FEATURE_MAP_SERVER_ATTRIBUTE_ID, BITMAP32, 4, 0), /* FeatureMap */
  122. DECLARE_DYNAMIC_ATTRIBUTE_LIST_END();
  123. // Declare Descriptor cluster attributes
  124. DECLARE_DYNAMIC_ATTRIBUTE_LIST_BEGIN(switchDescriptorAttrs)
  125. DECLARE_DYNAMIC_ATTRIBUTE(ZCL_DEVICE_LIST_ATTRIBUTE_ID, ARRAY, kDescriptorAttributeArraySize, 0), /* device list */
  126. DECLARE_DYNAMIC_ATTRIBUTE(ZCL_SERVER_LIST_ATTRIBUTE_ID, ARRAY, kDescriptorAttributeArraySize, 0), /* server list */
  127. DECLARE_DYNAMIC_ATTRIBUTE(ZCL_CLIENT_LIST_ATTRIBUTE_ID, ARRAY, kDescriptorAttributeArraySize, 0), /* client list */
  128. DECLARE_DYNAMIC_ATTRIBUTE(ZCL_PARTS_LIST_ATTRIBUTE_ID, ARRAY, kDescriptorAttributeArraySize, 0), /* parts list */
  129. DECLARE_DYNAMIC_ATTRIBUTE_LIST_END();
  130. // Declare Bridged Device Basic information cluster attributes
  131. DECLARE_DYNAMIC_ATTRIBUTE_LIST_BEGIN(switchBridgedDeviceBasicAttrs)
  132. DECLARE_DYNAMIC_ATTRIBUTE(ZCL_NODE_LABEL_ATTRIBUTE_ID, CHAR_STRING, kNodeLabelSize, 0), /* NodeLabel */
  133. DECLARE_DYNAMIC_ATTRIBUTE(ZCL_REACHABLE_ATTRIBUTE_ID, BOOLEAN, 1, 0), /* Reachable */
  134. DECLARE_DYNAMIC_ATTRIBUTE_LIST_END();
  135. // Declare Fixed Label cluster attributes
  136. DECLARE_DYNAMIC_ATTRIBUTE_LIST_BEGIN(switchFixedLabelAttrs)
  137. DECLARE_DYNAMIC_ATTRIBUTE(ZCL_LABEL_LIST_ATTRIBUTE_ID, ARRAY, kFixedLabelAttributeArraySize, 0), /* label list */
  138. DECLARE_DYNAMIC_ATTRIBUTE_LIST_END();
  139. // Declare Cluster List for Bridged Switch endpoint
  140. DECLARE_DYNAMIC_CLUSTER_LIST_BEGIN(bridgedSwitchClusters)
  141. DECLARE_DYNAMIC_CLUSTER(ZCL_SWITCH_CLUSTER_ID, switchAttrs),
  142. DECLARE_DYNAMIC_CLUSTER(ZCL_DESCRIPTOR_CLUSTER_ID, switchDescriptorAttrs),
  143. DECLARE_DYNAMIC_CLUSTER(ZCL_BRIDGED_DEVICE_BASIC_CLUSTER_ID, switchBridgedDeviceBasicAttrs),
  144. DECLARE_DYNAMIC_CLUSTER(ZCL_FIXED_LABEL_CLUSTER_ID, switchFixedLabelAttrs) DECLARE_DYNAMIC_CLUSTER_LIST_END;
  145. // Declare Bridged Switch endpoint
  146. DECLARE_DYNAMIC_ENDPOINT(bridgedSwitchEndpoint, bridgedSwitchClusters);
  147. // REVISION DEFINITIONS:
  148. // =================================================================================
  149. #define ZCL_DESCRIPTOR_CLUSTER_REVISION (1u)
  150. #define ZCL_BRIDGED_DEVICE_BASIC_CLUSTER_REVISION (1u)
  151. #define ZCL_FIXED_LABEL_CLUSTER_REVISION (1u)
  152. #define ZCL_ON_OFF_CLUSTER_REVISION (4u)
  153. #define ZCL_SWITCH_CLUSTER_REVISION (1u)
  154. // ---------------------------------------------------------------------------
  155. int AddDeviceEndpoint(Device * dev, EmberAfEndpointType * ep, uint16_t deviceType)
  156. {
  157. uint8_t index = 0;
  158. while (index < CHIP_DEVICE_CONFIG_DYNAMIC_ENDPOINT_COUNT)
  159. {
  160. if (NULL == gDevices[index])
  161. {
  162. gDevices[index] = dev;
  163. EmberAfStatus ret;
  164. while (1)
  165. {
  166. ret = emberAfSetDynamicEndpoint(index, gCurrentEndpointId, ep, deviceType, DEVICE_VERSION_DEFAULT);
  167. if (ret == EMBER_ZCL_STATUS_SUCCESS)
  168. {
  169. ChipLogProgress(DeviceLayer, "Added device %s to dynamic endpoint %d (index=%d)", dev->GetName(),
  170. gCurrentEndpointId, index);
  171. return index;
  172. }
  173. else if (ret != EMBER_ZCL_STATUS_DUPLICATE_EXISTS)
  174. {
  175. return -1;
  176. }
  177. // Handle wrap condition
  178. if (++gCurrentEndpointId < gFirstDynamicEndpointId)
  179. {
  180. gCurrentEndpointId = gFirstDynamicEndpointId;
  181. }
  182. }
  183. }
  184. index++;
  185. }
  186. ChipLogProgress(DeviceLayer, "Failed to add dynamic endpoint: No endpoints available!");
  187. return -1;
  188. }
  189. int RemoveDeviceEndpoint(Device * dev)
  190. {
  191. uint8_t index = 0;
  192. while (index < CHIP_DEVICE_CONFIG_DYNAMIC_ENDPOINT_COUNT)
  193. {
  194. if (gDevices[index] == dev)
  195. {
  196. EndpointId ep = emberAfClearDynamicEndpoint(index);
  197. gDevices[index] = NULL;
  198. ChipLogProgress(DeviceLayer, "Removed device %s from dynamic endpoint %d (index=%d)", dev->GetName(), ep, index);
  199. // Silence complaints about unused ep when progress logging
  200. // disabled.
  201. UNUSED_VAR(ep);
  202. return index;
  203. }
  204. index++;
  205. }
  206. return -1;
  207. }
  208. void EncodeFixedLabel(const char * label, const char * value, uint8_t * buffer, uint16_t length,
  209. const EmberAfAttributeMetadata * am)
  210. {
  211. char zclOctetStrBuf[kFixedLabelElementsOctetStringSize];
  212. _LabelStruct labelStruct;
  213. // TODO: This size is obviously wrong. See
  214. // https://github.com/project-chip/connectedhomeip/issues/10743
  215. labelStruct.label = CharSpan(label, kFixedLabelElementsOctetStringSize);
  216. strncpy(zclOctetStrBuf, value, sizeof(zclOctetStrBuf));
  217. // TODO: This size is obviously wrong. See
  218. // https://github.com/project-chip/connectedhomeip/issues/10743
  219. labelStruct.value = CharSpan(&zclOctetStrBuf[0], sizeof(zclOctetStrBuf));
  220. // TODO: Need to set up an AttributeAccessInterface to handle the lists here.
  221. }
  222. void HandleDeviceStatusChanged(Device * dev, Device::Changed_t itemChangedMask)
  223. {
  224. if (itemChangedMask & Device::kChanged_Reachable)
  225. {
  226. uint8_t reachable = dev->IsReachable() ? 1 : 0;
  227. MatterReportingAttributeChangeCallback(dev->GetEndpointId(), ZCL_BRIDGED_DEVICE_BASIC_CLUSTER_ID,
  228. ZCL_REACHABLE_ATTRIBUTE_ID, CLUSTER_MASK_SERVER, ZCL_BOOLEAN_ATTRIBUTE_TYPE,
  229. &reachable);
  230. }
  231. if (itemChangedMask & Device::kChanged_Name)
  232. {
  233. uint8_t zclName[kNodeLabelSize];
  234. MutableByteSpan zclNameSpan(zclName);
  235. MakeZclCharString(zclNameSpan, dev->GetName());
  236. MatterReportingAttributeChangeCallback(dev->GetEndpointId(), ZCL_BRIDGED_DEVICE_BASIC_CLUSTER_ID,
  237. ZCL_NODE_LABEL_ATTRIBUTE_ID, CLUSTER_MASK_SERVER, ZCL_CHAR_STRING_ATTRIBUTE_TYPE,
  238. zclNameSpan.data());
  239. }
  240. if (itemChangedMask & Device::kChanged_Location)
  241. {
  242. uint8_t buffer[kFixedLabelAttributeArraySize];
  243. EmberAfAttributeMetadata am = { .attributeId = ZCL_LABEL_LIST_ATTRIBUTE_ID,
  244. .size = kFixedLabelAttributeArraySize,
  245. .defaultValue = static_cast<uint16_t>(0) };
  246. EncodeFixedLabel("room", dev->GetLocation(), buffer, sizeof(buffer), &am);
  247. MatterReportingAttributeChangeCallback(dev->GetEndpointId(), ZCL_FIXED_LABEL_CLUSTER_ID, ZCL_LABEL_LIST_ATTRIBUTE_ID,
  248. CLUSTER_MASK_SERVER, ZCL_ARRAY_ATTRIBUTE_TYPE, buffer);
  249. }
  250. }
  251. void HandleDeviceOnOffStatusChanged(DeviceOnOff * dev, DeviceOnOff::Changed_t itemChangedMask)
  252. {
  253. if (itemChangedMask & (DeviceOnOff::kChanged_Reachable | DeviceOnOff::kChanged_Name | DeviceOnOff::kChanged_Location))
  254. {
  255. HandleDeviceStatusChanged(static_cast<Device *>(dev), (Device::Changed_t) itemChangedMask);
  256. }
  257. if (itemChangedMask & DeviceOnOff::kChanged_OnOff)
  258. {
  259. uint8_t isOn = dev->IsOn() ? 1 : 0;
  260. MatterReportingAttributeChangeCallback(dev->GetEndpointId(), ZCL_ON_OFF_CLUSTER_ID, ZCL_ON_OFF_ATTRIBUTE_ID,
  261. CLUSTER_MASK_SERVER, ZCL_BOOLEAN_ATTRIBUTE_TYPE, &isOn);
  262. }
  263. }
  264. void HandleDeviceSwitchStatusChanged(DeviceSwitch * dev, DeviceSwitch::Changed_t itemChangedMask)
  265. {
  266. if (itemChangedMask & (DeviceSwitch::kChanged_Reachable | DeviceSwitch::kChanged_Name | DeviceSwitch::kChanged_Location))
  267. {
  268. HandleDeviceStatusChanged(static_cast<Device *>(dev), (Device::Changed_t) itemChangedMask);
  269. }
  270. if (itemChangedMask & DeviceSwitch::kChanged_NumberOfPositions)
  271. {
  272. uint8_t numberOfPositions = dev->GetNumberOfPositions();
  273. MatterReportingAttributeChangeCallback(dev->GetEndpointId(), ZCL_SWITCH_CLUSTER_ID, ZCL_NUMBER_OF_POSITIONS_ATTRIBUTE_ID,
  274. CLUSTER_MASK_SERVER, ZCL_INT8U_ATTRIBUTE_TYPE, &numberOfPositions);
  275. }
  276. if (itemChangedMask & DeviceSwitch::kChanged_CurrentPosition)
  277. {
  278. uint8_t currentPosition = dev->GetCurrentPosition();
  279. MatterReportingAttributeChangeCallback(dev->GetEndpointId(), ZCL_SWITCH_CLUSTER_ID, ZCL_CURRENT_POSITION_ATTRIBUTE_ID,
  280. CLUSTER_MASK_SERVER, ZCL_INT8U_ATTRIBUTE_TYPE, &currentPosition);
  281. }
  282. if (itemChangedMask & DeviceSwitch::kChanged_MultiPressMax)
  283. {
  284. uint8_t multiPressMax = dev->GetMultiPressMax();
  285. MatterReportingAttributeChangeCallback(dev->GetEndpointId(), ZCL_SWITCH_CLUSTER_ID, ZCL_MULTI_PRESS_MAX_ATTRIBUTE_ID,
  286. CLUSTER_MASK_SERVER, ZCL_INT8U_ATTRIBUTE_TYPE, &multiPressMax);
  287. }
  288. }
  289. EmberAfStatus HandleReadBridgedDeviceBasicAttribute(Device * dev, chip::AttributeId attributeId, uint8_t * buffer,
  290. uint16_t maxReadLength)
  291. {
  292. ChipLogProgress(DeviceLayer, "HandleReadBridgedDeviceBasicAttribute: attrId=%d, maxReadLength=%d", attributeId, maxReadLength);
  293. if ((attributeId == ZCL_REACHABLE_ATTRIBUTE_ID) && (maxReadLength == 1))
  294. {
  295. *buffer = dev->IsReachable() ? 1 : 0;
  296. }
  297. else if ((attributeId == ZCL_NODE_LABEL_ATTRIBUTE_ID) && (maxReadLength == 32))
  298. {
  299. uint8_t bufferMemory[254];
  300. MutableByteSpan zclString(bufferMemory);
  301. MakeZclCharString(zclString, dev->GetName());
  302. buffer = zclString.data();
  303. }
  304. else if ((attributeId == ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID) && (maxReadLength == 2))
  305. {
  306. *buffer = (uint16_t) ZCL_BRIDGED_DEVICE_BASIC_CLUSTER_REVISION;
  307. }
  308. else
  309. {
  310. return EMBER_ZCL_STATUS_FAILURE;
  311. }
  312. return EMBER_ZCL_STATUS_SUCCESS;
  313. }
  314. EmberAfStatus HandleReadOnOffAttribute(DeviceOnOff * dev, chip::AttributeId attributeId, uint8_t * buffer, uint16_t maxReadLength)
  315. {
  316. ChipLogProgress(DeviceLayer, "HandleReadOnOffAttribute: attrId=%d, maxReadLength=%d", attributeId, maxReadLength);
  317. if ((attributeId == ZCL_ON_OFF_ATTRIBUTE_ID) && (maxReadLength == 1))
  318. {
  319. *buffer = dev->IsOn() ? 1 : 0;
  320. }
  321. else if ((attributeId == ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID) && (maxReadLength == 2))
  322. {
  323. *buffer = (uint16_t) ZCL_ON_OFF_CLUSTER_REVISION;
  324. }
  325. else
  326. {
  327. return EMBER_ZCL_STATUS_FAILURE;
  328. }
  329. return EMBER_ZCL_STATUS_SUCCESS;
  330. }
  331. EmberAfStatus HandleWriteOnOffAttribute(DeviceOnOff * dev, chip::AttributeId attributeId, uint8_t * buffer)
  332. {
  333. ChipLogProgress(DeviceLayer, "HandleWriteOnOffAttribute: attrId=%d", attributeId);
  334. if ((attributeId == ZCL_ON_OFF_ATTRIBUTE_ID) && (dev->IsReachable()))
  335. {
  336. if (*buffer)
  337. {
  338. dev->SetOnOff(true);
  339. }
  340. else
  341. {
  342. dev->SetOnOff(false);
  343. }
  344. }
  345. else
  346. {
  347. return EMBER_ZCL_STATUS_FAILURE;
  348. }
  349. return EMBER_ZCL_STATUS_SUCCESS;
  350. }
  351. EmberAfStatus HandleReadFixedLabelAttribute(Device * dev, const EmberAfAttributeMetadata * am, uint8_t * buffer,
  352. uint16_t maxReadLength)
  353. {
  354. if ((am->attributeId == ZCL_LABEL_LIST_ATTRIBUTE_ID) && (maxReadLength <= kFixedLabelAttributeArraySize))
  355. {
  356. EncodeFixedLabel("room", dev->GetLocation(), buffer, maxReadLength, am);
  357. }
  358. else if ((am->attributeId == ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID) && (maxReadLength == 2))
  359. {
  360. *buffer = (uint16_t) ZCL_FIXED_LABEL_CLUSTER_REVISION;
  361. }
  362. else
  363. {
  364. return EMBER_ZCL_STATUS_FAILURE;
  365. }
  366. return EMBER_ZCL_STATUS_SUCCESS;
  367. }
  368. EmberAfStatus HandleReadSwitchAttribute(DeviceSwitch * dev, chip::AttributeId attributeId, uint8_t * buffer, uint16_t maxReadLength)
  369. {
  370. if ((attributeId == ZCL_NUMBER_OF_POSITIONS_ATTRIBUTE_ID) && (maxReadLength == 1))
  371. {
  372. *buffer = dev->GetNumberOfPositions();
  373. }
  374. else if ((attributeId == ZCL_CURRENT_POSITION_ATTRIBUTE_ID) && (maxReadLength == 1))
  375. {
  376. *buffer = dev->GetCurrentPosition();
  377. }
  378. else if ((attributeId == ZCL_MULTI_PRESS_MAX_ATTRIBUTE_ID) && (maxReadLength == 1))
  379. {
  380. *buffer = dev->GetMultiPressMax();
  381. }
  382. else if ((attributeId == ZCL_FEATURE_MAP_SERVER_ATTRIBUTE_ID) && (maxReadLength == 4))
  383. {
  384. *(uint32_t *) buffer = dev->GetFeatureMap();
  385. }
  386. else if ((attributeId == ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID) && (maxReadLength == 2))
  387. {
  388. *buffer = (uint16_t) ZCL_SWITCH_CLUSTER_REVISION;
  389. }
  390. else
  391. {
  392. return EMBER_ZCL_STATUS_FAILURE;
  393. }
  394. return EMBER_ZCL_STATUS_SUCCESS;
  395. }
  396. EmberAfStatus emberAfExternalAttributeReadCallback(EndpointId endpoint, ClusterId clusterId,
  397. const EmberAfAttributeMetadata * attributeMetadata, uint8_t * buffer,
  398. uint16_t maxReadLength)
  399. {
  400. uint16_t endpointIndex = emberAfGetDynamicIndexFromEndpoint(endpoint);
  401. EmberAfStatus ret = EMBER_ZCL_STATUS_FAILURE;
  402. if ((endpointIndex < CHIP_DEVICE_CONFIG_DYNAMIC_ENDPOINT_COUNT) && (gDevices[endpointIndex] != NULL))
  403. {
  404. Device * dev = gDevices[endpointIndex];
  405. if (clusterId == ZCL_BRIDGED_DEVICE_BASIC_CLUSTER_ID)
  406. {
  407. ret = HandleReadBridgedDeviceBasicAttribute(dev, attributeMetadata->attributeId, buffer, maxReadLength);
  408. }
  409. else if (clusterId == ZCL_FIXED_LABEL_CLUSTER_ID)
  410. {
  411. ret = HandleReadFixedLabelAttribute(dev, attributeMetadata, buffer, maxReadLength);
  412. }
  413. else if (clusterId == ZCL_ON_OFF_CLUSTER_ID)
  414. {
  415. ret = HandleReadOnOffAttribute(static_cast<DeviceOnOff *>(dev), attributeMetadata->attributeId, buffer, maxReadLength);
  416. }
  417. else if (clusterId == ZCL_SWITCH_CLUSTER_ID)
  418. {
  419. ret =
  420. HandleReadSwitchAttribute(static_cast<DeviceSwitch *>(dev), attributeMetadata->attributeId, buffer, maxReadLength);
  421. }
  422. }
  423. return ret;
  424. }
  425. EmberAfStatus emberAfExternalAttributeWriteCallback(EndpointId endpoint, ClusterId clusterId,
  426. const EmberAfAttributeMetadata * attributeMetadata, uint8_t * buffer)
  427. {
  428. uint16_t endpointIndex = emberAfGetDynamicIndexFromEndpoint(endpoint);
  429. EmberAfStatus ret = EMBER_ZCL_STATUS_FAILURE;
  430. // ChipLogProgress(DeviceLayer, "emberAfExternalAttributeWriteCallback: ep=%d", endpoint);
  431. if (endpointIndex < CHIP_DEVICE_CONFIG_DYNAMIC_ENDPOINT_COUNT)
  432. {
  433. Device * dev = gDevices[endpointIndex];
  434. if ((dev->IsReachable()) && (clusterId == ZCL_ON_OFF_CLUSTER_ID))
  435. {
  436. ret = HandleWriteOnOffAttribute(static_cast<DeviceOnOff *>(dev), attributeMetadata->attributeId, buffer);
  437. }
  438. }
  439. return ret;
  440. }
  441. namespace {
  442. void EventHandler(const chip::DeviceLayer::ChipDeviceEvent * event, intptr_t arg)
  443. {
  444. (void) arg;
  445. if (event->Type == chip::DeviceLayer::DeviceEventType::kCHIPoBLEConnectionEstablished)
  446. {
  447. ChipLogProgress(DeviceLayer, "Receive kCHIPoBLEConnectionEstablished");
  448. }
  449. }
  450. CHIP_ERROR PrintQRCodeContent()
  451. {
  452. CHIP_ERROR err = CHIP_NO_ERROR;
  453. // If we do not have a discriminator, generate one
  454. chip::SetupPayload payload;
  455. uint32_t setUpPINCode;
  456. uint16_t setUpDiscriminator;
  457. uint16_t vendorId;
  458. uint16_t productId;
  459. std::string result;
  460. err = ConfigurationMgr().GetSetupPinCode(setUpPINCode);
  461. SuccessOrExit(err);
  462. err = ConfigurationMgr().GetSetupDiscriminator(setUpDiscriminator);
  463. SuccessOrExit(err);
  464. err = ConfigurationMgr().GetVendorId(vendorId);
  465. SuccessOrExit(err);
  466. err = ConfigurationMgr().GetProductId(productId);
  467. SuccessOrExit(err);
  468. payload.version = 0;
  469. payload.vendorID = vendorId;
  470. payload.productID = productId;
  471. payload.setUpPINCode = setUpPINCode;
  472. payload.discriminator = setUpDiscriminator;
  473. // Wrap it so SuccessOrExit can work
  474. {
  475. chip::QRCodeSetupPayloadGenerator generator(payload);
  476. err = generator.payloadBase38Representation(result);
  477. SuccessOrExit(err);
  478. }
  479. std::cout << "SetupPINCode: [" << setUpPINCode << "]" << std::endl;
  480. // There might be whitespace in setup QRCode, add brackets to make it clearer.
  481. std::cout << "SetupQRCode: [" << result << "]" << std::endl;
  482. exit:
  483. if (err != CHIP_NO_ERROR)
  484. {
  485. std::cerr << "Failed to generate QR Code: " << ErrorStr(err) << std::endl;
  486. }
  487. return err;
  488. }
  489. } // namespace
  490. void ApplicationInit() {}
  491. int main(int argc, char * argv[])
  492. {
  493. CHIP_ERROR err = CHIP_NO_ERROR;
  494. // Clear out the device database
  495. memset(gDevices, 0, sizeof(gDevices));
  496. // Create Mock Devices
  497. // Define 4 lights
  498. DeviceOnOff Light1("Light 1", "Office");
  499. DeviceOnOff Light2("Light 2", "Office");
  500. DeviceOnOff Light3("Light 3", "Office");
  501. DeviceOnOff Light4("Light 4", "Den");
  502. Light1.SetChangeCallback(&HandleDeviceOnOffStatusChanged);
  503. Light2.SetChangeCallback(&HandleDeviceOnOffStatusChanged);
  504. Light3.SetChangeCallback(&HandleDeviceOnOffStatusChanged);
  505. Light4.SetChangeCallback(&HandleDeviceOnOffStatusChanged);
  506. Light1.SetReachable(true);
  507. Light2.SetReachable(true);
  508. Light3.SetReachable(true);
  509. Light4.SetReachable(true);
  510. // Define 2 switches
  511. DeviceSwitch Switch1("Switch 1", "Office", EMBER_AF_SWITCH_FEATURE_LATCHING_SWITCH);
  512. DeviceSwitch Switch2("Switch 2", "Office",
  513. EMBER_AF_SWITCH_FEATURE_MOMENTARY_SWITCH | EMBER_AF_SWITCH_FEATURE_MOMENTARY_SWITCH_RELEASE |
  514. EMBER_AF_SWITCH_FEATURE_MOMENTARY_SWITCH_LONG_PRESS |
  515. EMBER_AF_SWITCH_FEATURE_MOMENTARY_SWITCH_MULTI_PRESS);
  516. Switch1.SetChangeCallback(&HandleDeviceSwitchStatusChanged);
  517. Switch2.SetChangeCallback(&HandleDeviceSwitchStatusChanged);
  518. Switch1.SetReachable(true);
  519. Switch2.SetReachable(true);
  520. // Initialize CHIP
  521. err = chip::Platform::MemoryInit();
  522. SuccessOrExit(err);
  523. err = ParseArguments(argc, argv);
  524. SuccessOrExit(err);
  525. err = chip::DeviceLayer::PlatformMgr().InitChipStack();
  526. SuccessOrExit(err);
  527. err = PrintQRCodeContent();
  528. SuccessOrExit(err);
  529. chip::DeviceLayer::PlatformMgrImpl().AddEventHandler(EventHandler, 0);
  530. chip::DeviceLayer::ConnectivityMgr().SetBLEDeviceName(nullptr); // Use default device name (CHIP-XXXX)
  531. #if CONFIG_NETWORK_LAYER_BLE
  532. chip::DeviceLayer::Internal::BLEMgrImpl().ConfigureBle(LinuxDeviceOptions::GetInstance().mBleDevice, false);
  533. #endif
  534. chip::DeviceLayer::ConnectivityMgr().SetBLEAdvertisingEnabled(true);
  535. // Init ZCL Data Model and CHIP App Server
  536. chip::Server::GetInstance().Init();
  537. // Initialize device attestation config
  538. SetDeviceAttestationCredentialsProvider(Examples::GetExampleDACProvider());
  539. // Set starting endpoint id where dynamic endpoints will be assigned, which
  540. // will be the next consecutive endpoint id after the last fixed endpoint.
  541. gFirstDynamicEndpointId = static_cast<chip::EndpointId>(
  542. static_cast<int>(emberAfEndpointFromIndex(static_cast<uint16_t>(emberAfFixedEndpointCount() - 1))) + 1);
  543. gCurrentEndpointId = gFirstDynamicEndpointId;
  544. // Disable last fixed endpoint, which is used as a placeholder for all of the
  545. // supported clusters so that ZAP will generated the requisite code.
  546. emberAfEndpointEnableDisable(emberAfEndpointFromIndex(static_cast<uint16_t>(emberAfFixedEndpointCount() - 1)), false);
  547. // Add lights 1..3 --> will be mapped to ZCL endpoints 2, 3, 4
  548. AddDeviceEndpoint(&Light1, &bridgedLightEndpoint, DEVICE_TYPE_LO_ON_OFF_LIGHT);
  549. AddDeviceEndpoint(&Light2, &bridgedLightEndpoint, DEVICE_TYPE_LO_ON_OFF_LIGHT);
  550. AddDeviceEndpoint(&Light3, &bridgedLightEndpoint, DEVICE_TYPE_LO_ON_OFF_LIGHT);
  551. // Remove Light 2 -- Lights 1 & 3 will remain mapped to endpoints 2 & 4
  552. RemoveDeviceEndpoint(&Light2);
  553. // Add Light 4 -- > will be mapped to ZCL endpoint 5
  554. AddDeviceEndpoint(&Light4, &bridgedLightEndpoint, DEVICE_TYPE_LO_ON_OFF_LIGHT);
  555. // Re-add Light 2 -- > will be mapped to ZCL endpoint 6
  556. AddDeviceEndpoint(&Light2, &bridgedLightEndpoint, DEVICE_TYPE_LO_ON_OFF_LIGHT);
  557. // Add switch 1..2 --> will be mapped to ZCL endpoints 7,8
  558. AddDeviceEndpoint(&Switch1, &bridgedSwitchEndpoint, DEVICE_TYPE_LO_ON_OFF_LIGHT_SWITCH);
  559. AddDeviceEndpoint(&Switch2, &bridgedSwitchEndpoint, DEVICE_TYPE_LO_ON_OFF_LIGHT_SWITCH);
  560. // Run CHIP
  561. chip::DeviceLayer::PlatformMgr().RunEventLoop();
  562. exit:
  563. if (err != CHIP_NO_ERROR)
  564. {
  565. std::cerr << "Failed to run Linux Bridge App: " << ErrorStr(err) << std::endl;
  566. // End the program with non zero error code to indicate a error.
  567. return 1;
  568. }
  569. return 0;
  570. }