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

samples: matter: Introduce Timed Schedule Access in Lock #15485

Merged
merged 2 commits into from
May 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
Original file line number Diff line number Diff line change
Expand Up @@ -594,8 +594,9 @@ Matter samples
* :ref:`matter_lock_sample` sample:

* Added support for emulation of the nRF7001 Wi-Fi companion IC on the nRF7002 DK.
* Added a door lock credentials manager module.
* Added a door lock access manager module.
The module is used to implement support for refined handling and persistent storage of PIN codes.
* Added the ::ref::`matter_lock_scheduled_timed_access` feature.

Multicore samples
-----------------
Expand Down
13 changes: 11 additions & 2 deletions samples/matter/lock/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -28,14 +28,23 @@ target_include_directories(app PRIVATE
src
)

FILE(GLOB cred_srcs src/credentials/*.cpp)
SET(access_srcs src/access/access_data_types.cpp
src/access/access_manager_credentials.cpp
src/access/access_manager_users.cpp
src/access/access_manager.cpp
src/access/access_storage.cpp
)

if(CONFIG_LOCK_SCHEDULES)
LIST(APPEND access_srcs src/access/access_manager_schedules.cpp)
endif()

target_sources(app PRIVATE
src/app_task.cpp
src/bolt_lock_manager.cpp
src/main.cpp
src/zcl_callbacks.cpp
${cred_srcs}
${access_srcs}
)

if(CONFIG_THREAD_WIFI_SWITCHING)
Expand Down
33 changes: 33 additions & 0 deletions samples/matter/lock/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,30 @@ config LOCK_MAX_CREDENTIAL_LENGTH
int "Maximum length of the single credential supported by the lock"
default 10

config LOCK_SCHEDULES
bool "Support for WeekDay, YearDay and Holiday schedules in lock"
help
This option adds support for an optional Timed Schedule Access Lock feature.
You can use Week Day, Year Day and Holiday schedules to restrict access for a
specific user for a defined time window. For example, use it to
give the user access only for three days in week.

if LOCK_SCHEDULES

config LOCK_MAX_WEEKDAY_SCHEDULES_PER_USER
int "Maximum number of WeekDay schedules per one user supported by the lock"
default 5

config LOCK_MAX_YEARDAY_SCHEDULES_PER_USER
int "Maximum number of YearDay schedules per one user supported by the lock"
default 5

config LOCK_MAX_HOLIDAY_SCHEDULES
int "Maximum number of Holiday schedules supported by the lock"
default 5

endif

config LOCK_ENABLE_DEBUG
bool "Enable debug features to print users and credentials"
depends on SHELL
Expand All @@ -32,6 +56,15 @@ config LOCK_ENABLE_DEBUG

if LOCK_ENABLE_DEBUG

config LOCK_PRINT_STORAGE_STATUS
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it used anywhere? I can't find it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is used in the credentials_storage.cpp please check one more time. Previously it was used but never defined in Kconfig. It is a fix for that.

bool "Print storage status after each store call"
help
Debug feature to print the debug-level log that contains information of the entry being stored
to persistent storage and how many bytes are left to store the new entry. It can be used to verify
whether credential, schedule or user entries are written properly to persistent storage.
This option should be disabled in production firmware
version.

# This should be deterined based on the maximum possible command length that depends on the LOCK_MAX_CREDENTIAL_LENGTH
config SHELL_CMD_BUFF_SIZE
default 300
Expand Down
259 changes: 258 additions & 1 deletion samples/matter/lock/README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ For details, see the `Commissioning the device`_ section.
Door lock credentials
=====================

By default, the application supports only PIN code credentials, but it is possible to implement support for other door lock credential types by using the ``CredentialsManager`` module.
By default, the application supports only PIN code credentials, but it is possible to implement support for other door lock credential types by using the ``AccessManager`` module.
The credentials can be used to control remote access to the bolt lock.
The PIN code assigned by the Matter controller is stored persistently, which means that it can survive a device reboot.
Depending on the IPv6 network technology in use, the following storage backends are supported by default to store the PIN code credential:
Expand Down Expand Up @@ -481,6 +481,150 @@ Upgrading the device firmware

To upgrade the device firmware, complete the steps listed for the selected method in the :doc:`matter:nrfconnect_examples_software_update` tutorial of the Matter documentation.

.. _matter_lock_scheduled_timed_access:

Scheduled timed access
======================

The scheduled timed access feature is an optional Matter lock feature that can be applicable to all available lock users.
You can use the scheduled timed access feature to allow guest users of the home to access the lock at the specific scheduled times.
To use this feature, you need to create at least one user on the lock device, and assign credentials.
For more information about setting user credentials, see the Saving users and credentials on door lock devices section of the :doc:`matter:chip_tool_guide` page in the :doc:`Matter documentation set <matter:index>`, and the :ref:`matter_lock_sample_remote_access_with_pin` section of this sample.

You can schedule the following types of timed access:

- ``Week-day`` - Restricts access to a specified time window on certain days of the week for a specific user.
This schedule grants repeated access each week.
When the schedule is cleared, the user is granted unrestricted access.

- ``Year-day`` - Restricts access to a specified time window on a specific date window.
This schedule grants access only once, and does not repeat.
When the schedule is cleared, the user is granted unrestricted access.

- ``Holiday`` - Sets up a holiday operating mode in the lock device.
You can choose one of the following operating modes:

- ``Normal`` - The lock operates normally.
- ``Vacation`` - Only remote operations are enabled.
- ``Privacy`` - All external interactions with the lock are disabled.
Can only be used if the lock is in the locked state.
Manually unlocking the lock changes the mode to ``Normal``.
- ``NoRemoteLockUnlock`` - All remote operations with the lock are disabled.
- ``Passage`` - The lock can be operated without providing a PIN.
This option can be used, for example, for employees during working hours.

To enable the scheduled timed access feature, complete the following steps:

1. Enable all needed scheduled timed access types in the ZAP file:

a. Open the :file:`lock.zap` file using the following west command:

.. code-block:: console

west zap-gui

#. Select the endpoint that contains the Matter Door Lock cluster.
By default, this is `Endpoint-1`.

#. Click the :guilabel:`Configure` symbol for the ``Door Lock`` cluster entry.
#. In the **Door Lock** context window, go to the **Attributes** tab and enable all required attributes:

* ``NumberOfWeekDaySchedulesSupportedPerUser`` for the ``Week-day`` schedule support.
* ``NumberOfYearDaySchedulesSupportedPerUser`` for the ``Year-day`` schedule support.
* ``NumberOfHolidaySchedulesSupported`` for the ``Holiday`` schedule support.

#. In the **Door Lock** context window, go to the **Attribute Reporting** page and enable all required attribute reporting entries:

* ``NumberOfWeekDaySchedulesSupportedPerUser`` for the ``Week-day`` schedule support.
* ``NumberOfYearDaySchedulesSupportedPerUser`` for the ``Year-day`` schedule support.
* ``NumberOfHolidaySchedulesSupported`` for the ``Holiday`` schedule support.

#. In the **Door Lock** context window, go to the **Commands** page and enable all required command entries:

* For the ``Week-day`` schedule support:

* ``SetWeekDaySchedule``
* ``GetWeekDaySchedule``
* ``GetWeekDayScheduleResponse``
* ``ClearWeekDaySchedule``

* For the ``Year-day`` schedule support:

* ``SetYearDaySchedule``
* ``GetYearDaySchedule``
* ``GetYearDayScheduleResponse``
* ``ClearYearDaySchedule``

* For the ``Holiday`` schedule support:

* ``SetHolidaySchedule``
* ``GetHolidaySchedule``
* ``GetHolidayScheduleResponse``
* ``ClearHolidaySchedule``

#. In the **Door Lock** context window, go to the **Attributes** tab and set the proper bits for the ``FeatureMap`` attribute:

* For the ``Week-day`` schedule support set the ``5th`` bit of the feature map bit map.
* For the ``Year-day`` schedule support set the ``11th`` bit of the feature map bit map.
* For the ``Holiday`` schedule support set the ``12th`` bit of the feature map bit map.

#. Enable Time Synchronization cluster with all needed types in the ZAP file:

#. In ZAP Tool GUI, select the endpoint 0 and enable the ``Time Synchronization`` cluster, with both server and client roles, for that endpoint.

#. Click the :guilabel:`Configure` symbol for the ``Time Synchronization`` cluster entry.
#. In the **Time Synchronization** context window, go to the **Attributes** tab and enable all required attributes:

* ``UTCTime``.
* ``Granularity``.
* ``TimeZone``.
* ``DSTOffset``.
* ``LocalTime``.
* ``TimeZoneDatabase``.
* ``TimeZoneListMaxSize``.
* ``DSTOffsetListMaxSize``.
* ``TrustedTimeSource``.

#. In the **Time Synchronization** context window, go to the **Attribute Reporting** page and enable all available attribute reporting entries.

#. In the **Time Synchronization** context window, go to the **Commands** page and enable all required command entries:

* ``SetUTCTime``.
* ``SetTimeZone``.
* ``SetTimeZoneResponse``.
* ``SetDSTOffset``.
* ``SetTrustedTimeSource``.

#. In the **Time Synchronization** context window, go to the **Attributes** tab and set the proper bits for the ``FeatureMap`` attribute:

* For the ``TimeZone`` support, set the ``0th`` bit of the feature map bit map.
* For the ``TimeSyncClient`` support, set the ``3rd`` bit of the feature map bit map.

As a result, the default decimal value of the ``FeatureMap`` should be `9`.

#. Save the :file:`lock.zap` file, and close ZAP-tool.
#. Generate new ZAP files with the changes in the Door Lock cluster using the following west command:

.. code-block:: console

west zap-generate

#. Enable the Lock Schedules feature in the |NCS| Matter Lock sample by setting the :kconfig:option:`CONFIG_LOCK_SCHEDULES` Kconfig option to ``y``.
#. Enable the Read Client support in the |NCS| Matter Lock sample by setting the :kconfig:option:`CONFIG_CHIP_ENABLE_READ_CLIENT` Kconfig option to ``y``.
#. Use the following Kconfig options to modify the maximum number of specific schedule types:

- :kconfig:option:`CONFIG_LOCK_MAX_WEEKDAY_SCHEDULES_PER_USER` to define the maximum number of ``Week-day`` schedules for one user.
- :kconfig:option:`CONFIG_LOCK_MAX_YEARDAY_SCHEDULES_PER_USER` to define the maximum number of ``Year-day`` schedules for one user.
- :kconfig:option:`CONFIG_LOCK_MAX_HOLIDAY_SCHEDULES` to define the maximum number of ``Holiday`` schedules.

To learn more about configuring the Matter clusters, see the :ref:`ug_matter_creating_accessory` user guide.

All scheduled timed access entries are saved to non-volatile memory and loaded automatically after device reboot.
ArekBalysNordic marked this conversation as resolved.
Show resolved Hide resolved
To disable the feature, you need to revert all changes in the :file:`lock.zap` file, re-generate the ZAP files and set the :kconfig:option:`CONFIG_LOCK_SCHEDULES` Kconfig option to ``n``.

.. note::
Adding a single schedule for a user contributes to the settings partition memory occupancy increase.

.. _matter_lock_sample_remote_access_with_pin:

Testing remote access with PIN code credential
Expand Down Expand Up @@ -536,6 +680,119 @@ After building the sample and programming it to your development kit, complete t
.. note::
Accessing the door lock remotely without a valid PIN code credential will fail.

.. _matter_lock_sample_schedule_testing:

Testing scheduled timed access
==============================

.. note::
You can test :ref:`matter_lock_scheduled_timed_access` using any Matter compatible controller.
The following steps use the CHIP Tool controller as an example.

After building the sample with the feature enabled and programming it to your development kit, complete the following steps to test scheduled timed access:

1. |connect_kit|
#. |connect_terminal_ANSI|
#. Wait until the device boots.
#. Commission an accessory with node ID equal to 10 to the Matter network by following the steps described in the `Commissioning the device`_ section.
#. Add the example ``Home`` door lock user:

.. code-block:: console

./chip-tool doorlock set-user 0 2 Home 123 1 0 0 10 1 --timedInteractionTimeoutMs 5000

This command creates a ``Home`` user with a unique ID of ``123`` and an index of ``2``.
The new user's status is set to ``1``, and both its type and credential rule to ``0``.
The user is assigned to the door lock cluster residing on endpoint ``1`` of the node with ID ``10``.

#. Set the example ``Week-day`` schedule using the following command:

.. parsed-literal::
:class: highlight

./chip-tool doorlock set-week-day-schedule *weekday-index* *user-index* *days-mask* *start-hour* *start-minute* *end-hour* *end-minute* *destination-id* *endpoint-id*

* *weekday-index* is the index of the new schedule, starting from ``1``.
The maximum value is defined by the :kconfig:option:`CONFIG_LOCK_MAX_WEEKDAY_SCHEDULES_PER_USER` Kconfig option.
* *user-index* is the user index defined for the user created in the previous step.
* *days-mask* is a bitmap of numbers of the week days starting from ``0`` as a Sunday and finishing at ``6`` as a Saturday.
For example, to assign this schedule to Tuesday, Thursday and Saturday you need to provide ``84`` because it is equivalent to the ``01010100`` bitmap.
* *start-hour* is the starting hour for the week day schedule.
* *start-minute* is the starting minute for the week day schedule.
* *end-hour* is the ending hour for the week day schedule.
* *end-minute* is the ending hour for the week day schedule.
* *destination-id* is the device node ID.
* *endpoint-id* is the Matter door lock endpoint, in this sample assigned to ``1``.

For example, use the following command to set a ``Week-day`` schedule with index ``1`` for Tuesday, Thursday and Saturday to start at 7:30 AM and finish at 10:30 AM, dedicated for user with ID ``2``:

.. code-block:: console

./chip-tool doorlock set-week-day-schedule 1 2 84 7 30 10 30 1 1


#. Set the example ``Year-day`` schedule using the following command:

.. parsed-literal::
:class: highlight

./chip-tool doorlock set-year-day-schedule *yearday-index* *user-index* *localtime-start* *localtime-end* *destination-id* *endpoint-id*


* *yearday-index* is the index of the new schedule, starting from ``1``.
The maximum value is defined by the :kconfig:option:`CONFIG_LOCK_MAX_YEARDAY_SCHEDULES_PER_USER` kconfig option.
* *user-index* is the user index defined for the user created in the previous step.
* *localtime-start* is the starting time in Epoch Time.
* *localtime-end* is the ending time in Epoch Time.
* *destination-id* is the device node ID.
* *endpoint-id* is the Matter door lock endpoint, in this sample assigned to ``1``.

Both ``localtime-start`` and ``localtime-end`` are in seconds with the local time offset based on the local timezone and DST offset on the day represented by the value.

For example, use the following command to set a ``Year-day`` schedule with index ``1`` to start on Monday, May 27, 2024, at 7:00:00 AM GMT+02:00 DST and finish on Thursday, May 30, 2024, at 7:00:00 AM GMT+02:00 DST dedicated for user with ID ``2``::

.. code-block:: console

./chip-tool doorlock set-year-day-schedule 1 2 1716786000 1717045200 1 1

#. Set the example ``Holiday`` schedule using the following command:

.. parsed-literal::
:class: highlight

./chip-tool doorlock set-holiday-schedule *holiday-index* *localtime-start* *localtime-end* *operating-mode* *destination-id* *endpoint-id*

* *holiday-index* is the index of the new schedule, starting from ``1``.
* *localtime-start* is the starting time in Epoch Time.
* *localtime-end* is the ending time in Epoch Time.
* *operating-mode* is the operating mode described in the :ref:`matter_lock_scheduled_timed_access` section of this guide.
* *destination-id* is the device node ID.
* *endpoint-id* is the Matter door lock endpoint, in this sample assigned to ``1``.

For example, use the following command to setup a ``Holiday`` schedule with the operating mode ``Vacation`` to start on Monday, May 27, 2024, at 7:00:00 AM GMT+02:00 DST and finish on Thursday, May 30, 2024, at 7:00:00 AM GMT+02:00 DST:

.. parsed-literal::
:class: highlight

./chip-tool doorlock set-holiday-schedule 1 1716786000 1717045200 1 1 1

#. Read saved schedules using the following commands and providing the same arguments you used in the earlier steps:

.. parsed-literal::
:class: highlight

./chip-tool doorlock get-week-day-schedule *weekday-index* *user-index* *destination-id* *endpoint-id*

.. parsed-literal::
:class: highlight

./chip-tool doorlock get-year-day-schedule *yearday-index* *user-index* *destination-id* *endpoint-id*

.. parsed-literal::
:class: highlight

./chip-tool doorlock get-holiday-schedule *holiday-index* *destination-id* *endpoint-id*
markaj-nordic marked this conversation as resolved.
Show resolved Hide resolved

.. _matter_lock_sample_switching_thread_wifi:

Testing switching between Thread and Wi-Fi
Expand Down
Loading
Loading