Skip to content

Commit cfc3602

Browse files
committed
Implement command GetAllPINCodes in ZPC
This is a contribution per the CLA Signed-off-by: Nenad Kljajic <[email protected]>
1 parent 0e0dcc8 commit cfc3602

File tree

3 files changed

+215
-0
lines changed

3 files changed

+215
-0
lines changed

applications/zpc/components/dotdot_mapper/rules/DoorLock_to_DoorLockCC.uam

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,34 @@
44
def zwDOOR_LOCK_OPERATION_DOOR_LOCK_MODE 0x6207
55
def zwDOOR_LOCK_CAPABILITIES_SUPPORTED_DOOR_COMPONENTS 0x6217
66

7+
def zwDOOR_LOCK_CONFIGURATION_OPERATION_TYPE 0x6202
8+
def zwDOOR_LOCK_CONFIGURATION_INSIDE_DOOR_HANDLES_STATE 0x6203
9+
def zwDOOR_LOCK_CONFIGURATION_OUTSIDE_DOOR_HANDLES_STATE 0x6204
10+
def zwDOOR_LOCK_CONFIGURATION_LOCK_TIMEOUT_MINUTES 0x6205
11+
def zwDOOR_LOCK_CONFIGURATION_LOCK_TIMEOUT_SECONDS 0x6206
12+
13+
def zwDOOR_LOCK_OPERATION_INSIDE_DOOR_HANDLES_MODE 0x6208
14+
def zwDOOR_LOCK_OPERATION_OUTSIDE_DOOR_HANDLES_MODE 0x6209
15+
def zwDOOR_LOCK_OPERATION_DOOR_CONDITION 0x620A
16+
def zwDOOR_LOCK_OPERATION_LOCK_TIMEOUT_MINUTES 0x620B
17+
def zwDOOR_LOCK_OPERATION_LOCK_TIMEOUT_SECONDS 0x620C
18+
19+
// UserCode Zwave attributes
20+
def zwUSER_CODE_DATA 0x6302
21+
def zwUSER_CODE_NUMBER_OF_USERS 0x6303
22+
def zwUSER_CODE_CAPABILITIES 0x6309
23+
def zwUSER_CODE_SUPPORTED_FLAGS 0x630A
24+
def zwUSER_CODE_SUPPORTED_USER_ID_STATUS_BITMASK 0x630B
25+
def zwUSER_CODE_SUPPORTED_KEYPAD_MODES_BITMASK 0x630C
26+
def zwUSER_CODE_SUPPORTED_KEYS_BITMASK 0x630D
27+
28+
def zwUSER_CODE_KEYPAD_MODE 0x630F
29+
730
// ZigBee DoorLock attributes
831
def zbDOOR_LOCK_CLUSTER_LOCK_STATE 0x01010000
932
def zbDOOR_LOCK_CLUSTER_LOCK_TYPE 0x01010001
1033
def zbDOOR_LOCK_ACTUATOR_ENABLED 0x01010002
34+
def zbDOOR_LOCK_NUMBER_OF_PIN_USERS 0x01010012
1135
// --------
1236

1337
// Zwave lock types
@@ -35,6 +59,8 @@ def zbDOOR_UNDEFINED 0xFF
3559

3660
scope 0 {
3761

62+
r'zbDOOR_LOCK_NUMBER_OF_PIN_USERS = r'zwUSER_CODE_DATA.zwUSER_CODE_NUMBER_OF_USERS
63+
3864
// Linking Zigbee Lock State to mapped ZWave Lock State
3965
r'zbDOOR_LOCK_CLUSTER_LOCK_STATE =
4066
if ( r'zwDOOR_LOCK_OPERATION_DOOR_LOCK_MODE == zwDOOR_UNSECURE_FOR_OUTSIDE ) zbDOOR_NOT_FULLY_LOCKED

applications/zpc/components/zcl_cluster_servers/src/user_code_cluster_server.cpp

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,22 @@ static sl_status_t
195195
(uint8_t *)&user_id,
196196
sizeof(uint16_t),
197197
0);
198+
uint16_t number_of_users = 0;
199+
attribute_store_get_child_reported(user_code_data,
200+
ATTRIBUTE(NUMBER_OF_USERS),
201+
&number_of_users,
202+
sizeof(number_of_users));
203+
204+
if ((user_id > 0) && (user_id <= number_of_users)) {
205+
if (user_id_node == ATTRIBUTE_STORE_INVALID_NODE) {
206+
user_id_node = attribute_store_emplace(user_code_data,
207+
ATTRIBUTE(USER_ID),
208+
&user_id,
209+
sizeof(user_id));
210+
}
211+
} else {
212+
return SL_STATUS_FAIL;
213+
}
198214

199215
attribute_store_node_t user_code_node
200216
= attribute_store_get_first_child_by_type(user_id_node, ATTRIBUTE(CODE));
@@ -205,6 +221,82 @@ static sl_status_t
205221
: SL_STATUS_FAIL;
206222
}
207223

224+
/**
225+
* @brief Checks if the User ID node matches what we expect and undefines
226+
* the User Code data underneath.
227+
*
228+
* @param user_id_node Attribute Store node for the User ID.
229+
*/
230+
static void undefine_user_code(attribute_store_node_t user_id_node)
231+
{
232+
if (attribute_store_get_node_type(user_id_node) != ATTRIBUTE(USER_ID)) {
233+
return;
234+
}
235+
236+
// Set the user code to nothing:
237+
attribute_store_node_t user_code_node
238+
= attribute_store_get_first_child_by_type(user_id_node, ATTRIBUTE(CODE));
239+
240+
attribute_store_undefine_desired(user_code_node);
241+
attribute_store_undefine_reported(user_code_node);
242+
243+
attribute_store_node_t user_id_status_node
244+
= attribute_store_get_first_child_by_type(user_id_node,
245+
ATTRIBUTE(USER_ID_STATUS));
246+
247+
attribute_store_undefine_desired(user_id_status_node);
248+
attribute_store_undefine_reported(user_id_status_node);
249+
}
250+
251+
/**
252+
* @brief Navigates under the endpoint node and undefines all the
253+
* known user code data.
254+
*
255+
* @param node Attribute Store node for the Endpoint.
256+
*/
257+
static void undefine_all_user_codes(attribute_store_node_t endpoint_node)
258+
{
259+
attribute_store_node_t data_node
260+
= attribute_store_get_first_child_by_type(endpoint_node, ATTRIBUTE(DATA));
261+
262+
attribute_store_walk_tree(data_node, &undefine_user_code);
263+
}
264+
265+
sl_status_t get_all_pin_codes_command(dotdot_unid_t unid,
266+
dotdot_endpoint_id_t endpoint,
267+
uic_mqtt_dotdot_callback_call_type_t call_type)
268+
{
269+
attribute_store_node_t user_code_data
270+
= get_user_code_data_node(unid, endpoint);
271+
272+
// Now that we know that the command is supported, return here if it is
273+
// a support check type of call.
274+
if (UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK == call_type) {
275+
return attribute_store_node_exists(user_code_data) ? SL_STATUS_OK
276+
: SL_STATUS_FAIL;
277+
}
278+
279+
attribute_store_node_t endpoint_node
280+
= attribute_store_network_helper_get_endpoint_node(unid, endpoint);
281+
282+
attribute_store_node_t data_node
283+
= attribute_store_get_first_child_by_type(endpoint_node, ATTRIBUTE(DATA));
284+
285+
uint16_t number_of_users = 0;
286+
attribute_store_get_child_reported(user_code_data,
287+
ATTRIBUTE(NUMBER_OF_USERS),
288+
&number_of_users,
289+
sizeof(number_of_users));
290+
291+
for (uint16_t i = 1; (i <= number_of_users) && (i != 0); i++) {
292+
attribute_store_emplace(data_node, ATTRIBUTE(USER_ID), &i, sizeof(i));
293+
}
294+
295+
undefine_all_user_codes(endpoint_node);
296+
297+
return SL_STATUS_OK;
298+
}
299+
208300
static sl_status_t
209301
set_user_status_command(dotdot_unid_t unid,
210302
dotdot_endpoint_id_t endpoint,
@@ -291,6 +383,7 @@ sl_status_t user_code_cluster_server_init()
291383
// Register the callback for handling commands from IoT service
292384
uic_mqtt_dotdot_door_lock_setpin_code_callback_set(&set_pin_code_command);
293385
uic_mqtt_dotdot_door_lock_getpin_code_callback_set(&get_pin_code_command);
386+
uic_mqtt_dotdot_door_lock_get_allpin_codes_callback_set(&get_all_pin_codes_command);
294387
uic_mqtt_dotdot_door_lock_clearpin_code_callback_set(&clear_pin_code_command);
295388
uic_mqtt_dotdot_door_lock_clear_allpin_codes_callback_set(
296389
&clear_all_pin_codes_command);

applications/zpc/components/zwave_command_classes/src/zwave_command_class_user_code.c

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,11 @@
2424
#include "zwave_controller_utils.h"
2525
#include "zpc_attribute_store_network_helper.h"
2626
#include "zpc_attribute_resolver.h"
27+
#include "zwave_command_class_user_code_types.h"
2728

2829
// Includes from Unify Components
30+
#include "dotdot_mqtt.h"
31+
#include "dotdot_mqtt_generated_commands.h"
2932
#include "attribute_store.h"
3033
#include "attribute_store_helper.h"
3134
#include "attribute_resolver.h"
@@ -875,6 +878,19 @@ static void zwave_command_class_user_code_on_number_of_users_update(
875878
attribute_store_node_t endpoint_node
876879
= attribute_store_get_first_parent_with_type(updated_node,
877880
ATTRIBUTE_ENDPOINT_ID);
881+
attribute_store_node_t version_node
882+
= attribute_store_get_first_child_by_type(endpoint_node,
883+
ATTRIBUTE(VERSION));
884+
// We need to check the version of the supporting node:
885+
zwave_cc_version_t supporting_node_version = 0;
886+
attribute_store_get_reported(version_node,
887+
&supporting_node_version,
888+
sizeof(supporting_node_version));
889+
if (supporting_node_version == 1) {
890+
sl_log_debug(LOG_TAG, "Skip creating User ID nodes for CC UserCode V1.");
891+
return;
892+
}
893+
878894
attribute_store_node_t data_node
879895
= attribute_store_get_first_child_by_type(endpoint_node, ATTRIBUTE(DATA));
880896

@@ -905,6 +921,78 @@ static void zwave_command_class_user_code_on_capabilities_created(
905921
COUNT_OF(capabilities_attributes));
906922
}
907923

924+
static void zwave_command_class_user_code_on_code_update(
925+
attribute_store_node_t updated_node, attribute_store_change_t change)
926+
{
927+
if (change != ATTRIBUTE_UPDATED) {
928+
return;
929+
}
930+
931+
// Get pin code value
932+
char pin_code [ATTRIBUTE_STORE_MAXIMUM_VALUE_LENGTH] = {0};
933+
attribute_store_get_reported_string(updated_node,
934+
pin_code,
935+
ATTRIBUTE_STORE_MAXIMUM_VALUE_LENGTH);
936+
attribute_store_node_t user_id_node
937+
= attribute_store_get_first_parent_with_type(updated_node,
938+
ATTRIBUTE(USER_ID));
939+
// get user id value
940+
uint16_t user_id = 0;
941+
attribute_store_get_reported(user_id_node, &user_id, sizeof(user_id));
942+
943+
attribute_store_node_t endpoint_id_node
944+
= attribute_store_get_first_parent_with_type(user_id_node,
945+
ATTRIBUTE_ENDPOINT_ID);
946+
zwave_endpoint_id_t endpoint_id = 0;
947+
attribute_store_get_reported(endpoint_id_node, &endpoint_id, sizeof(endpoint_id));
948+
949+
attribute_store_node_t node_id_node
950+
= attribute_store_get_first_parent_with_type(endpoint_id_node,
951+
ATTRIBUTE_NODE_ID);
952+
zwave_node_id_t node_id = 0;
953+
attribute_store_get_reported(node_id_node, &node_id, sizeof(node_id));
954+
955+
unid_t node_unid;
956+
zwave_unid_from_node_id(node_id, node_unid);
957+
958+
attribute_store_node_t status_node
959+
= attribute_store_get_first_child_by_type(user_id_node,
960+
ATTRIBUTE(USER_ID_STATUS));
961+
uint8_t ustatus = 0;
962+
attribute_store_get_reported(status_node, &ustatus, sizeof(ustatus));
963+
DrlkUserStatus user_status = 0;
964+
switch (ustatus) {
965+
case USER_STATUS_AVAILABLE:
966+
user_status = ZCL_DRLK_USER_STATUS_AVAILABLE;
967+
break;
968+
case USER_STATUS_ENABLED:
969+
user_status = ZCL_DRLK_USER_STATUS_OCCUPIED_ENABLED;
970+
break;
971+
case USER_STATUS_DISABLED:
972+
user_status = ZCL_DRLK_USER_STATUS_OCCUPIED_DISABLED;
973+
break;
974+
case USER_STATUS_MESSAGING:
975+
user_status = ZCL_DRLK_USER_STATUS_OCCUPIED_ENABLED;
976+
break;
977+
case USER_STATUS_PASSAGE_MODE:
978+
user_status = ZCL_DRLK_USER_STATUS_OCCUPIED_DISABLED;
979+
break;
980+
}
981+
982+
if (attribute_store_is_desired_defined(updated_node) == false) {
983+
uic_mqtt_dotdot_door_lock_command_getpin_code_response_fields_t fields =
984+
{
985+
.userid = (DrlkPINUserID) user_id,
986+
.user_status = (DrlkUserStatus) user_status,
987+
.user_type = (DrlkUserType) ZCL_DRLK_USER_TYPE_UNRESTRICTED_USER,
988+
.code = pin_code
989+
};
990+
991+
uic_mqtt_dotdot_door_lock_publish_generated_getpin_code_response_command(
992+
node_unid, endpoint_id, &fields);
993+
}
994+
}
995+
908996
///////////////////////////////////////////////////////////////////////////////
909997
// Attribute Resolver callback functions
910998
///////////////////////////////////////////////////////////////////////////////
@@ -1067,6 +1155,10 @@ static sl_status_t
10671155
memcpy(user_code, &frame[4], user_code_length);
10681156
user_code[user_code_length] = '\0';
10691157
attribute_store_set_reported_string(user_code_node, user_code);
1158+
if (user_code_node != ATTRIBUTE_STORE_INVALID_NODE) {
1159+
zwave_command_class_user_code_on_code_update(user_code_node,
1160+
ATTRIBUTE_UPDATED);
1161+
}
10701162
attribute_store_undefine_desired(user_code_node);
10711163

10721164
return SL_STATUS_OK;
@@ -1167,6 +1259,10 @@ static sl_status_t handle_extended_user_code_report(
11671259
}
11681260

11691261
attribute_store_set_reported_string(user_code_node, user_code);
1262+
if (user_code_node != ATTRIBUTE_STORE_INVALID_NODE) {
1263+
zwave_command_class_user_code_on_code_update(user_code_node,
1264+
ATTRIBUTE_UPDATED);
1265+
}
11701266
attribute_store_undefine_desired(user_code_node);
11711267

11721268
j += 4 + user_code_length;

0 commit comments

Comments
 (0)