zmk icon indicating copy to clipboard operation
zmk copied to clipboard

feat(split): sync central & peripherals last activity timing

Open angweekiat opened this issue 1 year ago • 1 comments

Sync central last activity timings to all devices, by having the central emit how long it's inactive, and the peripheral(s) using it to adjust the local last activity time. Prior to this change, key presses on a peripheral keep the central awake, but not vice versa.

This is done by:

  1. Adding a new SYNC_ACTIVITY GATT characteristic for central to sync its inactive time to the other peripheral(s).
  2. Central's activity.c broadcasting its inactivity time to its peripherals via 2 options: a. ZMK_SPLIT_SYNC_LAST_ACTIVITY_TIMING_PERIODIC - broadcasting at a regular configurable interval b. ZMK_SPLIT_SYNC_LAST_ACTIVITY_TIMING_ON_EVENT - broadcasting when key press / sensors events are received, with a minimum configurable interval between each broadcast
  3. Peripheral's service.c receiving the inactivity time and sending it as an event to its activity.c
  4. Peripheral's activity.c determining its local activity_last_uptime value using the inactivity time as a relative difference.

Additionally:

  • central.c is updated to sync the timers upon a new BLE connection, so new devices don't need to wait for the full interval to get synced.
  • If a peripheral is in IDLE mode when the central comes online, it'll get synced to ACTIVE as well.

Cons:

  • This solution doesn't handle cases where the peripheral(s) is already in deep sleep (ZMK_ACTIVITY_SLEEP), since BLE is turned off. However, the sync-ing can prevent peripheral(s) from going into deep sleep if the central is used.
  • The original intention of periodic broadcast is to prevent unnecessary deep sleeps, not idle, and the default interval was 5 minutes. However, if the interval is greater than the idle time out (ZMK_IDLE_SLEEP_TIMEOUT), the peripheral(s) may go into IDLE before receiving the next sync from central, which may not be desired. See Test steps - Periodic sync below

Test steps - Periodic sync

  1. Build and flash both sides to the target keyboard, ideally with indicators such as backlight, battery, RGB underglow, displays, to detect when one side has gone to idle/active, and with ZMK_SPLIT_SYNC_LAST_ACTIVITY_TIMING_PERIODIC enabled
  2. Allow the peripheral to go to idle state (default timeout: 30s)
  3. Press any key on the central that causes it to switch to active. The peripheral should go to active state, not immediately, but within 30s.

Test steps - Event-based sync

  1. Build and flash both sides to the target keyboard, ideally with indicators such as backlight, battery, RGB underglow, displays, to detect when one side has gone to idle/active, and with ZMK_SPLIT_SYNC_LAST_ACTIVITY_TIMING_ON_EVENT enabled. (_ON_EVENT, not _PERIODIC)
  2. Allow the peripheral to go to idle state (default timeout: 30s)
  3. Press any key on the central that causes it to switch to active. The peripheral should go to active state immediately.

Local test

I added log lines to check the output, that the values are sent and received correctly on both ends. However, if the sync interval is set to a low value (30 seconds), the log lines would end up spamming the console, so I opt'ed to remove them. Let me know if logs can be introduced more nicely, or if there's a better way to check that the code works for the context of reviewing this pull request!

Raised as an issue in https://github.com/zmkfirmware/zmk/issues/2408

angweekiat avatar Sep 05 '24 15:09 angweekiat

Shifted original comment into PR description

angweekiat avatar Sep 06 '24 13:09 angweekiat

This PR has been automatically marked as stale because it has not had activity in 10 months. It will be closed in 14 days if no further activity occurs. Feel free to give a status update or re-open when it has been rebased and is ready for review (again). Thanks!

github-actions[bot] avatar Jul 24 '25 22:07 github-actions[bot]

This PR was closed because it had no activity for over 10 months. Feel free to give a status update or re-open when it has been rebased and is ready for review (again).

github-actions[bot] avatar Aug 07 '25 22:08 github-actions[bot]

It's a bummer that this never got merged. Been using event based sync for a bit now and it solves my problems when playing a game. Very useful.

kmobs avatar Nov 02 '25 04:11 kmobs