Commit Graph

548 Commits

Author SHA1 Message Date
Peter Johanson 80173f8ea3 fix: Improve startup time with proper settings loading.
* Avoid doing duplicate calls to setings_load_subtree, which iterates
  NVS fully each time under the hood, and instead use on settings_load
  later in the lifecycle.
2024-07-03 16:24:17 -06:00
Peter Johanson f18974e8c4 fix: Adjust hid indicator listeners for event refactor
* Avoid static listener to prevent subscription
  issue.
2024-07-01 12:32:04 -06:00
Peter Johanson 96e55c8be6 fix: BLE refactor mouse keys fix. 2024-06-28 17:48:45 -06:00
Peter Johanson 483a4930e9 feat(behaviors): Add local ID system for behaviors
* Add a new feature for tracking a given behavior by a new concept
  of a "behavior local ID" which is a stable 16-bit identifier for
  a given behavior, that is resilient to new behaviors being added
  and requires no additional work on the part of the behavior
  authors.
* Add implementations for either settings lookup table, or CRC16
  hashing of behavior device names for generating behavior local
  IDs.
2024-06-28 15:10:32 -06:00
Peter Johanson f7c34c70ba refactor(ble): Extract API to get active profile connection.
* Add `struct bt_conn *zmk_ble_active_profile_conn(void)` function for
  fetching a connection for the current profile.
2024-06-28 14:43:17 -06:00
Peter Johanson 49f7275beb fix: Add metadata to missed behaviors. 2024-06-25 12:11:32 -06:00
Timoyoungster 10d03ca46c fix: adding option to separate implicit mod release from key release
This adds a new config value `ZMK_HID_SEPARATE_MOD_RELEASE_REPORT`
where, if enabled, the report for a key release is sent separately to
the accompanying modifier release signals, which are then sent in a
second report.

This fixes an issue where certain applications are unable to work with
implicitly modified keys (e.g. colon) due to them registering the
modifier release prior to the actual key release.

Have tested this on my personal keyboard and `wev` now shows the signals
in the correct order.

=> **Previously:** ```LSHIFT (pressed) -> colon (pressed) -> LSHIFT
(released) -> **semi**colon (released)```

=> **Now:** ```LSHIFT (pressed) -> colon (pressed) -> colon (released)
-> LSHIFT (released)```

(This time without accidental files)
2024-06-24 14:26:14 -06:00
Peter Johanson 03099b04b6 feat(behaviors): Add behavior metadata information.
* For upcoming ZMK studio work, make a set of rich metadata available
  to provide a friendly name for a behavior, and allow super flexible
  descriptions of the parameters the behaviors take.
* Add ability to validate a zmk_behavior_binding against
  the behavior metadata available.
2024-06-24 11:08:00 -06:00
Peter Johanson 7be955ff72 fix(usb): Ensure USB init is last
* To avoid USB init issues due to other initialization disrupting
  USB setup, move USB setup to a lower priority.
2024-06-21 13:29:12 -06:00
German Gutierrez 2ee76be6fe
fix(soft_off): central waits 100ms in split if hold_time enabled 2024-05-13 17:43:35 -04:00
Horu 7d1f84e3eb
chore: fix typos in various places 2024-05-13 16:47:33 -04:00
Peter Johanson af908826cd fix: Initialize sideband kscan in APPLICATION.
* In order to be sure the rest of the system is fully ready before
  intializing, because init may result in immediate events being
  triggered when used with toggle direct kscan inner devices.
2024-05-01 11:35:54 -07:00
Jarryd Tilbrook 0d3a4b7bbb
fix(underglow): Correctly set underglow state
This fixes a bug introduced in #2244
2024-04-25 07:26:26 -07:00
Pablo Martínez 4d566853af
fix(rgb): auto-off logic 2024-04-25 04:55:42 -04:00
Peter Johanson 16e92cf665 fix(behaviors): Add multiple soft-off instances properly.
* Properly pass the node id for the unique
  soft-off behavior instance when defining it.
2024-04-17 23:53:12 -07:00
Keeley Hoek e22bc7620c fix(hid): Correct off-by-one buffer overflow with NKRO 2024-04-09 23:20:20 -07:00
Xudong Zheng 849eca7228 refactor(underglow): fix uninitialized variable warning 2024-04-09 15:57:34 -07:00
Peter Johanson 7e7110d85f fix(pm): Fixes for dedicated on/off on peripherals.
* Add new flag to differentiate soft off on peripherals that
  is invoked by split GATT svc and dedicated additional ones
  tied to GPIO pin.
2024-03-27 20:59:26 -07:00
Peter Johanson 41d81801ed fix(pm): Use Zephyr created device slots.
* Avoid overwriting random memory by using
  iterable section created by Zephyr PM.
2024-03-27 20:59:26 -07:00
Peter Johanson 2df6dcd973 feat(behaviors): More logging in soft off. 2024-03-27 20:59:26 -07:00
Peter Johanson 8d54e287f0 fix: Adjustments for Zephyr 3.5. 2024-03-27 20:59:26 -07:00
Peter Johanson bd21f41412 refactor: Fixes for review feedback. 2024-03-27 20:59:26 -07:00
Peter Johanson 5d960a758f fix: Cleanups of sideband and direct kscan from review.
* Add dedicated init priority for the sideband kscan.
* Refactor sideband code for clarity.
* Tweaks to direct kscan for clarity.
* Make sideband behavior row optional for brevity.
* Allow overriding ZMK Uno sideband behaviors.
2024-03-27 20:59:26 -07:00
Peter Johanson 4198fac90f fix(pm): Fix deep sleep with sideband behaviors.
* Properly implement the PM hook needed for sideband behavior
  kscan device to have wakeup source enabled on it.
2024-03-27 20:59:26 -07:00
Peter Johanson 09111f1cf3 fix: Sleep after clearing endpoints to wait for send.
* Add a small sleep to allow other threads to send data for the
  endpoint clearing before sleep.
2024-03-27 20:59:26 -07:00
Peter Johanson a0ad1d4c94 refactor: Add kscan sideband behavior driver
* Instead of gpio key behavior trigger, add new kscan driver that
  decorates/wraps a given kscan driver and will invoke basic system
  behavior assigned to a given row + column, without the need for keymap
  mapping in the matrix transform, bypassing keymaps entirely.
2024-03-27 20:59:26 -07:00
Pete Johanson 933fdcd364 refactor(pm): Remove scanned behavior trigger.
* Remove the painful scanned behavior trigger for now, future enhancement
  will restore this high level functionality using kscan directly.
2024-03-27 20:59:26 -07:00
Pete Johanson 5ebe924e94 chore: Various soft-off review fixes
* Code style to avoid goto.
* Enable pm.c compilation via dedicated Kconfig flag.
* Comment wakeup trigger PM behavior.
2024-03-27 20:59:26 -07:00
Peter Johanson fceb0351a5 refactor: Fixes for soft-off based on review.
* Better naming for gpio-key behavior triggers.
* Tweaks to scanned behavior trigger to avoid bad semaphore use,
  and reduce chance of issues with slowly scanned matrixes.
* Various code cleanups of style issues.
2024-03-27 20:59:26 -07:00
Peter Johanson 0d4d4fb2b5 feat(pm): Clear HID data before soft off.
* Make sure the connected host has no held HID usages before we sleep.
2024-03-27 20:59:26 -07:00
Peter Johanson 860e53b33a refactor: Promote new endpoints API
* Add ability for external callers to clear the current endpoint.
2024-03-27 20:59:26 -07:00
Peter Johanson b19df0cbf0 feat(behaviors): Add soft off behavior.
* New soft-off behavior that can be used to force the device
  into  soft-off state with only certain configured wakeup
  devices.
2024-03-27 20:59:26 -07:00
Peter Johanson adb3a13dc5 feat: Add soft on/off support.
Initial work on a soft on/off support for ZMK. Triggering soft off
puts the device into deep sleep with only a specific GPIO pin
configured to wake the device, avoiding waking from other key
presses in the matrix like the normal deep sleep.

Co-authored-by: Cem Aksoylar <caksoylar@users.noreply.github.com>
2024-03-27 20:59:26 -07:00
Thomas Huber 58ccc5970d fix(build): Modify function return type
Change return type of `sticky_key_timeout` function to `void` given it
does not return any value to remove compiler warnings.
2024-03-27 14:52:42 -07:00
Peter Johanson 44358798d3 feat: Add ability to fetch battery voltage.
* To be able to use the Zephyr `voltage-divider` driver,
  add a mode for fetching raw voltage from the sensor
 and do state of charge calculation outside of the driver.
2024-03-24 13:28:55 -07:00
Peter Johanson 3a3eed2960 fix: Add settings reset on start init priority.
* Add a dedicated settings reset on start init priority and default
  it to lower priority (high number) than default FLASH_INIT_PRIORITY
  to be sure flash is initialized before we open the area.
2024-03-20 11:18:43 -07:00
Theo Lemay 94d9d837e3 refactor: extract duplicate logic 2024-03-18 10:30:14 -07:00
Theo Lemay 341534aa15 feat(behaviors): lazy sticky keys 2024-03-18 10:30:14 -07:00
ReFil 388ad71385
feat(build): Explicit missing keymap node error
* Explicit error if zmk,keymap not set
* Document keymap error

---------

Co-authored-by: Cem Aksoylar <caksoylar@users.noreply.github.com>
2024-03-18 12:54:47 -04:00
Joel Spadin a77288f527 fix: Update settings reset for Zephyr 3.5 2024-03-18 09:48:19 -07:00
Joel Spadin 1dfcfc7d3f feat(shields): Make settings_reset shield reset all settings
Added a new CONFIG_ZMK_SETTINGS_RESET_ON_START option which enables init
code to call zmk_settings_erase(), and changed the settings_reset shield
to use it instead of CONFIG_ZMK_BLE_CLEAR_BONDS_ON_START, so it now
resets all settings instead of just clearing BLE bonds.

CONFIG_ZMK_BLE_CLEAR_BONDS_ON_START is left in place for now in case
someone still needs it. It may be replaced in the future once we find a
better way to repair a broken split connection.
2024-03-18 09:48:19 -07:00
Joel Spadin 610a806c84 feat: Add function to erase all settings
Added a zmk_settings_erase() function to clear all saved settings. This
does not go through Zephyr's settings subsystem, but instead directly
clears the data from the setting storage backend, so a reboot is needed
for it to take effect.
2024-03-18 09:48:19 -07:00
Theo Lemay c9c620d19f fix: inline initialise 2024-02-20 00:25:53 -08:00
Theo Lemay c007d60357 feat(behaviors): hold while undecided 2024-02-20 00:25:53 -08:00
Xudong Zheng 104c73d303 refactor: address transport switch enumeration warning
When building without USB or Bluetooth, the compiler emits a warning due to
ZMK_TRANSPORT_USB or ZMK_TRANSPORT_BLE not being handled.
2024-02-19 21:41:52 -08:00
honorless ccf0380179 refactor: remove redundant Kconfig defaults
bool symbols implicitly default to n.
2024-02-19 16:39:31 -08:00
zhiayang a9ae6796a0
fix(display): Proper initial display of battery status
* fix initial display of battery status on displays, and also fix a null deref
2024-02-19 19:15:19 -05:00
ctranstrum 0f49fa9ae4
fix(behavior): Proper init priority for ext_power. 2024-02-14 20:29:19 -05:00
Peter Johanson 50a303b8bb fix(pm): Restore sleep suspension of devices.
* After the move to `sys_poweroff`, restore the behavior of
  suspending devices before entering sleep state.
2024-02-09 14:32:46 -08:00
Peter Johanson b2a0a357e1 fix(display): Set a default mem size for built-in
* Set a reasonable default LVGL mem pool size for our built-in
  status screen.
2024-02-09 14:32:46 -08:00
Peter Johanson f4e6d70465 fix: Proper use of CONTAINER_OF with delayable work. 2024-02-09 14:32:46 -08:00
Peter Johanson 98e3b8b435 refactor: Move to new sys_poweroff API.
* Move to new `sys_poweroff` API for our deep sleep functionality.
2024-02-09 14:32:46 -08:00
Peter Johanson b6d9f3c911 fix(ble): Ensure large enough string for setting name.
* Fix warning related to potentially large number of profiles
  causing overflow of allocated string for the setting name.
2024-02-09 14:32:46 -08:00
Peter Johanson d6de8a3acc refactor: Move to POST_KERNEL phase for behavior inits. 2024-02-09 14:32:46 -08:00
Peter Johanson ba1a6c08ad refactor: Return int from main function. 2024-02-09 14:32:46 -08:00
Peter Johanson 0b5afbf9c0 refacter(bluetooth): Proper HCI header include. 2024-02-09 14:32:46 -08:00
Peter Johanson bf4008da02 refactor: All SYS_INIT functions are void args. 2024-02-09 14:32:46 -08:00
Peter Johanson f4fce9e158 refactor(display): Move new LVGL DPI Kconfig setting. 2024-02-09 14:32:46 -08:00
Cem Aksoylar b8846cf635 refactor(display): Remove unused BAS includes 2024-02-06 01:09:07 -08:00
Peter Johanson 331915f989 fix: Fix missed event manager usages from refactor. 2024-01-14 11:31:05 -08:00
Peter Johanson 644feeb40d fix(core): Address review comments from Joel.
* Fix up some lingering events API tweaks for heap-less event manager.
2024-01-14 11:13:57 -08:00
Peter Johanson 33209dee1d refactor(core): Move to stack allocated events.
* Move to local/stack allocated event API that doesn't require
  dynamic allocation/freeing.
* Disable heap, we no longer use alloc/free unless using LVGL.
* Tons of refactors all over to account for the new event approach.
2024-01-14 11:13:57 -08:00
Xudong Zheng 6bf4870704 fix(battery): prevent bus fault when battery does not exist
zmk_battery_start_reporting() may be called from battery_event_listener(), which
will result in a bus fault when attempting to read a battery that does not exist
such as on a dongle.
2024-01-08 17:39:05 -08:00
Peter Johanson 12bc8b0402 fix: Fix function signatures for WPM.
* Recent refactor accidentally used the wrong signatures for a few
  WPM function definitions.
2024-01-05 16:09:34 -08:00
Peter Johanson 395ffaa790 fix(ble): Properly send mouse HoG using worker.
* Properly send mouse HoG reports using our worker to avoid thread issues.
2024-01-05 12:17:59 -08:00
Peter Johanson 74875314f8 feat(ble): Request encryption if notifying fails
* If attempting to notify and getting an EPERM return value, request
  upgrading the security of the connection at that moment, since it
  likely means we got a connection to a bonded host but the connection
  hasn't been upgraded to encrypted yet.
2024-01-05 12:17:59 -08:00
Pete Johanson 69f962fab2 feat(ble): Add security related tests.
* Add security related tests to verify behavior when trying to read
  a GATT characteristic from our peripheral with and without client
  auto security request/retry.
2024-01-05 12:17:59 -08:00
Peter Johanson bc7b4b56bd fix(ble): Disable Auto Sec Req again.
* Auto security request actually makes macOS worse, so disable it,
  and remove our early request in favor of using GATT enforcement
 to ensure connections are secured.
2024-01-05 12:17:59 -08:00
Chris Andreae 194a9790eb fixup! use wider type for loop iterator 2024-01-05 12:16:38 -08:00
Chris Andreae b813f34e34 fixup! bt: add BT_CLR_ALL behaviour 2024-01-05 12:16:38 -08:00
Chris Andreae f4fe7fa40f Extract common behaviour of clearing a bond 2024-01-05 12:16:38 -08:00
Chris Andreae 604c95118e Remove error reporting from ble utility functions that never error 2024-01-05 12:16:38 -08:00
Chris Andreae b8cb407351 lint: use correct type signature for Zephyr callbacks 2024-01-05 12:16:38 -08:00
Chris Andreae 7a5155f36e lint: add (void) parameter to pass -Wstrict-prototypes
Note there was one place where a non-strict prototype was actually being used
with an argument, in `zmk_hog_init`. In this case, the actual argument type was
added instead.
2024-01-05 12:16:38 -08:00
moergo-sc 5257cde1f5 bt: add BT_CLR_ALL behaviour
Defines behaviour to clear all paired Bluetooth profiles
2024-01-05 12:16:38 -08:00
Gabor Hornyak 0e2f94b73b feat(ble): Support perhipheral battery levels.
* Add ability to fetch and report peripheral battery levels
  on split centrals.
* Add additional support for adding a new Battery Level
  service to split centrals that exposes fetched peripheral
  battery levels to connected hosts.

Co-authored-by: Peter Johanson <peter@peterjohanson.com>
2024-01-03 09:26:51 -08:00
Peter Johanson 63c8c5700a feat(bt): Add more experimental tweaks.
* Support auto security upgrade for splits properly.
* Disable 2M and legacy LLCP if the experimental
  Kconfig flag is selected.
2023-12-08 14:57:23 -08:00
Joel Spadin 23ecf08119 refactor(behaviors)!: Remove labels from behaviors
Removed the label property from built-in behaviors, custom behaviors
defined in a few keymaps, and macros generated with ZMK_MACRO().

Now that node names are used to identify behaviors, and names only need
to be unique within the set of behaviors, the names of all behaviors
have been shortened to be similar to their original labels.

This means that any keymaps which reference behavior nodes by name
instead of by label will need to be updated. Keymaps typically use the
labels though, so most keymaps should be unaffected by this change.
2023-12-04 20:06:54 -06:00
Joel Spadin 36eda571b7 refactor(behaviors): Create a list to lookup behaviors
Added BEHAVIOR_DT_DEFINE() and BEHAVIOR_DT_INST_DEFINE(), which work
exactly like the DEVICE_*_DEFINE() macros, except they also register the
device as a behavior by adding a pointer to it to a memory section.

Added zmk_behavior_get_binding(), which works like device_get_binding()
except that it only searches the devices that have been registered as
behaviors. This ensures that behaviors cannot have name collisions with
other devices defined by the SoC, which will be important when we remove
the label property from behaviors so they are given their node names.

As an added benefit, this is faster since it searches a smaller list.
Some basic benchmark code I wrote indicates it takes 30-70% as long,
depending on where the behavior is in the list and whether the name
string is an exact pointer match.

From now on, behaviors should use BEHAVIOR_*_DEFINe() instead of
DEVICE_*_DEFINE(), and any code that looks up a behavior by name should
use zmk_behavior_get_binding() instead of device_get_binding().
2023-12-04 20:06:54 -06:00
Joel Spadin d4e8dee444 refactor(keymaps): Rename layer label to "display-name"
Changed the property used to define a layer name for displays from
"label" (which affects other things in Zephyr and is deprecated) to
"display-name". (It cannot be named simply "name", because that has
special meaning in newer versions of the devicetree compiler.)

"label" is still supported as a fallback, so no changes need to be made
to existing keymaps.
2023-12-04 20:06:54 -06:00
Joel Spadin 05925c72d7 refactor(ext_power): Remove label property
Changed the label property on zmk,ext-power-generic to be optional and
removed it from existing uses. Renamed the nodes for all non-development
boards to "EXT_POWER" to preserve user settings.

rgb_underglow.c now finds the correct device by finding the first
instance of zmk,ext-power-generic instead of looking for a node named
"EXT_POWER".
2023-12-04 20:06:54 -06:00
Joel Spadin 179bdbc41a refactor(behaviors): Make label property optional
Changed all code (except for layer names) which used the label property
to use DEVICE_DT_NAME() instead, which uses the label if set or falls
back to the full node name. This matches how Zephyr determines the node
names used with device_get_binding() and allows us to start removing the
deprecated label property from things.
2023-12-04 20:06:54 -06:00
ReFil dbe5dfb1d8
feat(split): Add is_bonded function to peripherals
There is already a function to see if the peripheral is connected, a matching one for if it's bonded is a useful addition for displays/indicators. `is_bonded` gets reset to false in the advertising function in preparation for runtime peripheral bond clearing
2023-12-04 18:31:35 -05:00
Peter Johanson da15564d0e feat(bluetooth): Build on ARCH_POSIX. 2023-12-02 17:11:45 -08:00
Peter Johanson 3fad4dba07 fix(bt): Passkey entry pairing fixes.
* Don't propogate any key press events while in the
  middle of passkey entry, avoid funky state on hosts.
* Handle passkey on release, not press, to ensure key *releases*
  are not accidentally sent, especially the Enter release
  at the very end of passkey entry, which can trigger
  cancel in the dialog if the keyboard is connected
  via USB to the same host.
2023-12-01 16:48:46 -08:00
Peter Johanson 329d6474ee feat(ble): Make it possible to use BT_GATT_AUTO_SEC_REQ
* Only upgrade security of new connections if BT_GATT_AUTO_SEC_REQ
  is not enabled.
2023-12-01 16:47:49 -08:00
Peter Johanson 744f70c80c feat(bt): Add support for unauth overwrite
* Properly handle the user enabling the
  `CONFIG_BT_SMP_ALLOW_UNAUTH_OVERWRITE`
  Zephyr flag and handle re-pairing to an existing taken
  profile from the same address.
2023-12-01 23:39:31 +00:00
Peter Johanson 817ce8764f refactor: Move to `zmk_hid_indicators_t` type. 2023-11-27 16:03:18 -08:00
Alessandro Bortolin d9bb0d7d0e feat: LED indicators on peripheral side 2023-11-27 16:03:18 -08:00
Alessandro Bortolin 4e55c5f6e9 feat: handle LED indicators report 2023-11-27 16:03:18 -08:00
ReFil 6276e973d5 feat(ble): Only update BAS when active
Subscribes to the activity changing event, will stop the battery work timer when in idle or deep sleep, restart when board goes active
2023-11-27 09:58:20 -08:00
Chris Andreae 0a4b1a6533
feat(ble): add behavior to disconnect from BLE profile
Adds new functionality and a behavior to disconnect an active BLE connection.
The motivation for this is that for some devices like phones, the presence of an
active BLE connection results in the onscreen keyboard being selected.
2023-11-20 15:00:10 -05:00
Alexander Krikun d7d9eed317 feat(mouse): Initial mouse keys support.
* Add HID report/descriptor for a new report with mouse buttons,
  and x/y/wheel deltas.
* New mouse key press behavior for press/release of mouse keys.
* Add constants for HID main item values (e.g. data/array/absolute)
* Define and use constants for our HID report IDs.
2023-11-15 11:16:59 -08:00
ReFil 8776911da5
feat(ble): Allow disabling BLE BAS reporting
The battery reporting has been known to cause macOS computers to wakeup repeatedly. In some cases (e.g. display or custom lighting implementation) one might want to collect battery SOC without broadcasting over BLE

* Update docs/docs/config/battery.md

Co-authored-by: Cem Aksoylar <caksoylar@users.noreply.github.com>
2023-11-15 13:03:30 -05:00
Peter Johanson f6716f869a fix(usb): Build with ZMK_USB_BOOT disabled.
* Invert the logic so `get_keyboard_report` is sane when `ZMK_USB_BOOT`
  is disabled.
2023-11-13 23:56:10 -08:00
Peter Johanson 964c54139d fix(usb): Tweak how ZMK_USB gets enabled.
* Previous version of multiple overrides of the default value of ZMK_USB
  were problematic. Move to using board _defconfig files for the
  defaults for those, along with proper `depends on` for ZMK_USB that
  accounts for split and split roles.
2023-11-13 12:56:23 -08:00
Chris Andreae 91aa3378f3
feat(usb): Add boot protocol support
* USB boot protocol support
* Use a single definition of a boot report, used for regular reports in
  non-6KRO, and for rollover in all branches.
* Handle gaps in the zmk report when producing a boot report in HKRO mode. For
  .example, if it was 8KRO, it would be possible to have the state 0 0 0 0 0 0 0
  17 (by pressing 8 keys, and letting go of the first 7). Copying the first 6
  bytes would not show up the single pressed key.
* Disable usb status change and callback on SOF events:
  SOF events were introduced by the boot protocol changes, and required internally
  by Zephyr's idle support, but are unused within ZMK itself. Ignore them in the
  usb status callback.

---------

Co-authored-by: Andrew Childs <lorne@cons.org.nz>
2023-11-13 13:04:04 -05:00
Peter Johanson c2d220fbdf refactor(hid): Use proper defines for HID values.
* Add report ID defines and use them consistently.
* Add defines for main item value flags to avoid magic constants.
2023-11-08 16:00:19 -08:00
Andrew Rae b85ffa4b6c refactor(behaviors): global-quick-tap -> require-prior-idle
Renaming global-quick-tap-ms to require-prior-idle.
2023-10-03 01:12:47 -07:00
Andrew Rae 77eb44ba9b feat(behaviors): Adding global-quick-tap-ms for combos
This brings the 'global-quick-tap' functionality to combos by filtering
out candidate combos that fell within their own quick tap term.

I also replaced `return 0` with `return ZMK_EV_EVENT_BUBBLE` where appropriate.
(I assume this was done in past as it is similar to errno returning, but
being that this is to signify an event type I find this more clear)
2023-10-03 01:12:47 -07:00