From 4df8f282a24e71aa7ce9ad3113c851a7f3c9077c Mon Sep 17 00:00:00 2001 From: Anodynous Date: Sun, 21 Mar 2021 18:43:41 +0200 Subject: [PATCH 01/17] Add DS3231 RTC module wiring and integration guide --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index c064f3e..988c05c 100644 --- a/README.md +++ b/README.md @@ -144,7 +144,7 @@ All commands should be executed as root. The installation process can be complet CONFIG_CHECK_DIETPI_UPDATES=0 CONFIG_CHECK_APT_UPDATES=0 - * Disable waiting for network and time sync at boot. Doing this you should be aware that the RPI0w does not have a hardware clock. It will lose track of real world time as soon it is powered off, making log timestamps or any time based action you may set up unreliable. None of this is important for the core functionality of the Stenogotchi and disabling time-sync at boot can shave up to a minute off the boot process. By adding a cheap I2C hardware clock you can completely remove the need for network sync. Many modules are small enough to fit in the empty space of the UPS-Lite or under the eINK screen [and are easy to wire](https://www.pishop.us/product/ds3231-real-time-clock-module-for-raspberry-pi/) and [set up](https://learn.adafruit.com/adding-a-real-time-clock-to-raspberry-pi/set-rtc-time). Just don't forget to isolate it with some tape. + * Disable waiting for network and time sync at boot. Doing this you should be aware that the RPI0w does not have a hardware clock. It will lose track of real world time as soon it is powered off, making log timestamps or any time based action you may set up unreliable. None of this is important for the core functionality of the Stenogotchi and disabling time-sync at boot can shave up to a minute off the boot process. By adding a cheap I2C hardware clock you can completely remove the need for network sync. Many modules are small enough to fit in the empty space of the UPS-Lite or under the eINK screen [and are easy to wire](https://www.pishop.us/product/ds3231-real-time-clock-module-for-raspberry-pi/) and [set up](https://learn.adafruit.com/adding-a-real-time-clock-to-raspberry-pi/set-rtc-time). Just don't forget to isolate it with some tape. You can see [how to wire and fit the DS3231 module in the Stenogotchi here](https://user-images.githubusercontent.com/17461433/111912767-cff8e700-8a73-11eb-9bd0-a406bd7241ef.jpg). nano /boot/dietpi.txt From 5cee3f18f668635539d5175741307f4558488373 Mon Sep 17 00:00:00 2001 From: Anodynous Date: Sun, 21 Mar 2021 18:58:15 +0200 Subject: [PATCH 02/17] DS3231 info update --- CHANGELOG.md | 2 ++ README.md | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 025a830..461f298 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] ### Added +- Add DS3231 real time clock module wiring and positioning reference picture to README. + ### Changed ### Fixed ### Removed diff --git a/README.md b/README.md index 988c05c..72a5057 100644 --- a/README.md +++ b/README.md @@ -144,7 +144,7 @@ All commands should be executed as root. The installation process can be complet CONFIG_CHECK_DIETPI_UPDATES=0 CONFIG_CHECK_APT_UPDATES=0 - * Disable waiting for network and time sync at boot. Doing this you should be aware that the RPI0w does not have a hardware clock. It will lose track of real world time as soon it is powered off, making log timestamps or any time based action you may set up unreliable. None of this is important for the core functionality of the Stenogotchi and disabling time-sync at boot can shave up to a minute off the boot process. By adding a cheap I2C hardware clock you can completely remove the need for network sync. Many modules are small enough to fit in the empty space of the UPS-Lite or under the eINK screen [and are easy to wire](https://www.pishop.us/product/ds3231-real-time-clock-module-for-raspberry-pi/) and [set up](https://learn.adafruit.com/adding-a-real-time-clock-to-raspberry-pi/set-rtc-time). Just don't forget to isolate it with some tape. You can see [how to wire and fit the DS3231 module in the Stenogotchi here](https://user-images.githubusercontent.com/17461433/111912767-cff8e700-8a73-11eb-9bd0-a406bd7241ef.jpg). + * Disable waiting for network and time sync at boot. Doing this you should be aware that the RPI0w does not have a hardware clock. It will lose track of real world time as soon it is powered off, making log timestamps or any time based action you may set up unreliable. None of this is important for the core functionality of the Stenogotchi and disabling time-sync at boot can shave up to a minute off the boot process. By adding a cheap I2C hardware clock you can completely remove the need for network sync. Many modules are small enough to fit in the empty space of the UPS-Lite or under the eINK screen [and are easy to wire](https://www.pishop.us/product/ds3231-real-time-clock-module-for-raspberry-pi/) and [set up](https://learn.adafruit.com/adding-a-real-time-clock-to-raspberry-pi/set-rtc-time). Just don't forget to isolate it with some tape. Here you can see [how to wire and fit the DS3231 module in the Stenogotchi](https://user-images.githubusercontent.com/17461433/111912767-cff8e700-8a73-11eb-9bd0-a406bd7241ef.jpg). nano /boot/dietpi.txt From 773bcb2e72358b07ef2bf221eff9a9a42b601044 Mon Sep 17 00:00:00 2001 From: Anodynous Date: Mon, 22 Mar 2021 22:11:42 +0200 Subject: [PATCH 03/17] Align on_events with Stenogotchi functionality --- stenogotchi/defaults.toml | 34 ++++++--- stenogotchi/plugins/default/example.py | 84 +++++++++++++++++----- stenogotchi/plugins/default/led.py | 97 ++++++++++++++------------ 3 files changed, 143 insertions(+), 72 deletions(-) diff --git a/stenogotchi/defaults.toml b/stenogotchi/defaults.toml index 0cd2b9c..4360f2b 100644 --- a/stenogotchi/defaults.toml +++ b/stenogotchi/defaults.toml @@ -87,7 +87,7 @@ main.plugins.plover_link.wpm_timeout = '60' main.plugins.evdevkb.enabled = true main.plugins.upslite.enabled = false -main.plugins.upslite.shutdown_level = 4 +main.plugins.upslite.shutdown_level = 5 main.plugins.memtemp.enabled = false main.plugins.memtemp.scale = "celsius" @@ -96,16 +96,28 @@ main.plugins.memtemp.orientation = "horizontal" main.plugins.led.enabled = false main.plugins.led.led = 0 main.plugins.led.delay = 200 -main.plugins.led.patterns.loaded = "oo oo oo oo oo oo oo" -main.plugins.led.patterns.updating = "oo oo oo oo oo oo oo" -main.plugins.led.patterns.ready = "oo oo oo oo oo oo oo" -main.plugins.led.patterns.bored = "oo oo oo oo oo oo oo" -main.plugins.led.patterns.sad = "oo oo oo oo oo oo oo" -main.plugins.led.patterns.excited = "oo oo oo oo oo oo oo" -main.plugins.led.patterns.lonely = "oo oo oo oo oo oo oo" -main.plugins.led.patterns.rebooting = "oo oo oo oo oo oo oo" -main.plugins.led.patterns.wait = "oo oo oo oo oo oo oo" -main.plugins.led.patterns.sleep = "oo oo oo oo oo oo oo" +main.plugins.led.patterns.loaded = "" +main.plugins.led.patterns.updating = "" +main.plugins.led.patterns.ready = "" +main.plugins.led.patterns.grateful = "" +main.plugins.led.patterns.lonely = "" +main.plugins.led.patterns.bored = "" +main.plugins.led.patterns.sad = "" +main.plugins.led.patterns.angry = "" +main.plugins.led.patterns.excited = "" +main.plugins.led.patterns.rebooting = "oo oo oo oo oo" +main.plugins.led.patterns.wait = "" +main.plugins.led.patterns.sleep = "" +main.plugins.led.patterns.epoch = "" +main.plugins.led.patterns.bt_connected = "oo oo oo oo oo" +main.plugins.led.patterns.bt_disconnected = "oo oo oo oo oo" +main.plugins.led.patterns.plover_boot = "" +main.plugins.led.patterns.plover_ready = "oo oo oo oo oo" +main.plugins.led.patterns.plover_quit = "oo oo oo oo oo" +main.plugins.led.patterns.wifi_connected = "oo oo oo oo oo" +main.plugins.led.patterns.wifi_disconnected = "oo oo oo oo oo" +main.plugins.led.patterns.wpm_set = "" +main.plugins.led.patterns.strokes_set = "" main.plugins.logtail.enabled = false main.plugins.logtail.max-lines = 10000 diff --git a/stenogotchi/plugins/default/example.py b/stenogotchi/plugins/default/example.py index 8601677..2a3af81 100644 --- a/stenogotchi/plugins/default/example.py +++ b/stenogotchi/plugins/default/example.py @@ -1,3 +1,11 @@ +# ############################################################### +# Based on: https://github.com/evilsocket/pwnagotchi/blob/master/pwnagotchi/plugins/default/example.py +# +# Changed 22-03-2021 by Anodynous +# - Changed to fit Stenogotchi events +# +################################################################ + import logging import stenogotchi.plugins as plugins @@ -7,7 +15,7 @@ class Example(plugins.Plugin): - __author__ = 'evilsocket@gmail.com' + __author__ = 'evilsocket@gmail.com, Anodynous' __version__ = '1.0.0' __license__ = 'GPL3' __description__ = 'An example plugin for pwnagotchi that implements all the available callbacks.' @@ -19,7 +27,7 @@ def __init__(self): # must return a html page # IMPORTANT: If you use "POST"s, add a csrf-token (via csrf_token() and render_template_string) def on_webhook(self, path, request): - pass + logging.info("[example] webhook established") # called when the plugin is loaded def on_loaded(self): @@ -27,11 +35,11 @@ def on_loaded(self): # called before the plugin is unloaded def on_unload(self, ui): - pass + logging.info("[example] is unloaded") # called hen there's internet connectivity def on_internet_available(self, agent): - pass + logging.info("[example] unit has internet connection") # called to setup the ui elements def on_ui_setup(self, ui): @@ -48,7 +56,7 @@ def on_ui_update(self, ui): # called when the hardware display setup is done, display is an hardware specific object def on_display_setup(self, display): - pass + logging.info("[example] unit has set up display") # called when everything is ready and the main loop is about to start def on_ready(self, agent): @@ -58,34 +66,78 @@ def on_ready(self, agent): # or set a custom state # agent.set_bored() + # called when the status is set to grateful + def on_grateful(self, agent): + logging.info("[example] unit is grateful") + + # called when the status is set to lonely + def on_lonely(self, agent): + logging.info("[example] unit is lonely") + # called when the status is set to bored def on_bored(self, agent): - pass + logging.info("[example] unit is bored") # called when the status is set to sad def on_sad(self, agent): - pass + logging.info("[example] unit is sad") + + # called when the status is set to angry + def on_angry(self, agent): + logging.info("[example] unit is angry") # called when the status is set to excited def on_excited(self, agent): - pass - - # called when the status is set to lonely - def on_lonely(self, agent): - pass + logging.info("[example] unit is excited") # called when the agent is rebooting the board def on_rebooting(self, agent): - pass + logging.info("[example] unit is rebooting") # called when the agent is waiting for t seconds def on_wait(self, agent, t): - pass + logging.info(f"[example] unit is waiting {t} seconds") # called when the agent is sleeping for t seconds def on_sleep(self, agent, t): - pass + logging.info(f"[example] unit is sleeping {t} seconds") # called when an epoch is over (where an epoch is a single loop of the main algorithm) def on_epoch(self, agent, epoch, epoch_data): - pass + logging.info(f"[example] epoch is over") + + # called when successfully connected to a bluetooth host + def on_bt_connected(self, agent, bthost_name): + logging.info(f"[example] unit connected to bluetooth host '{bthost_name}'") + + # called when disconnected from bluetooth host + def on_bt_disconnected(self, agent): + logging.info("[example] unit disconnected from bluetooth host") + + # called when plover boots + def on_plover_boot(self, agent): + logging.info("[example] Plover is starting up") + + # called when plover is ready + def on_plover_ready(self, agent): + logging.info("[example] Plover is ready") + + # called when plover quits + def on_plover_quit(self, agent): + logging.info("[example] Plover has quit") + + # called when wifi is connected + def on_wifi_connected(self, agent, ssid, ip): + logging.info(f"[example] unit is connected to wifi '{ssid}' using ip '{ip}'") + + # called when wifi is disconnected + def on_wifi_disconnected(self, agent): + logging.info("[example] unit is disconnected from wifi") + + # called when wpm stats are updated + def on_wpm_stats(self, agent): + logging.info("[example] unit received new WPM stats") + + # called when wpm-strokes stats are updated + def on_strokes_stats(self, agent): + logging.info("[example] unit received new WPM-strokes stats") \ No newline at end of file diff --git a/stenogotchi/plugins/default/led.py b/stenogotchi/plugins/default/led.py index 44f6dfa..c2002ef 100644 --- a/stenogotchi/plugins/default/led.py +++ b/stenogotchi/plugins/default/led.py @@ -1,3 +1,11 @@ +# ############################################################### +# Based on: https://github.com/evilsocket/pwnagotchi/blob/master/pwnagotchi/plugins/default/led.py +# +# Changed 22-03-2021 by Anodynous +# - Changed to fit Stenogotchi events +# +################################################################ + from threading import Event import _thread import logging @@ -7,7 +15,7 @@ class Led(plugins.Plugin): - __author__ = 'evilsocket@gmail.com' + __author__ = 'evilsocket@gmail.com, Anodynous' __version__ = '1.0.0' __license__ = 'GPL3' __description__ = 'This plugin blinks the PWR led with different patterns depending on the event.' @@ -73,10 +81,6 @@ def _worker(self): def on_updating(self): self._on_event('updating') - # called when there's one or more unread pwnmail messages - def on_unread_inbox(self, num_unread): - self._on_event('unread_inbox') - # called when there's internet connectivity def on_internet_available(self, agent): self._on_event('internet_available') @@ -85,21 +89,13 @@ def on_internet_available(self, agent): def on_ready(self, agent): self._on_event('ready') - # called when the AI finished loading - def on_ai_ready(self, agent): - self._on_event('ai_ready') - - # called when the AI starts training for a given number of epochs - def on_ai_training_start(self, agent, epochs): - self._on_event('ai_training_start') + # called when the status is set to grateful + def on_grateful(self, agent): + self._on_event('grateful') - # called when the AI got the best reward so far - def on_ai_best_reward(self, agent, reward): - self._on_event('ai_best_reward') - - # called when the AI got the worst reward so far - def on_ai_worst_reward(self, agent, reward): - self._on_event('ai_worst_reward') + # called when the status is set to lonely + def on_lonely(self, agent): + self._on_event('lonely') # called when the status is set to bored def on_bored(self, agent): @@ -109,14 +105,14 @@ def on_bored(self, agent): def on_sad(self, agent): self._on_event('sad') + # called when the status is set to angry + def on_angry(self, agent): + self._on_event('angry') + # called when the status is set to excited def on_excited(self, agent): self._on_event('excited') - # called when the status is set to lonely - def on_lonely(self, agent): - self._on_event('lonely') - # called when the agent is rebooting the board def on_rebooting(self, agent): self._on_event('rebooting') @@ -129,31 +125,42 @@ def on_wait(self, agent, t): def on_sleep(self, agent, t): self._on_event('sleep') - # called when the agent refreshed its access points list - def on_wifi_update(self, agent, access_points): - self._on_event('wifi_update') + # called when an epoch is over (where an epoch is a single loop of the main algorithm) + def on_epoch(self, agent, epoch, epoch_data): + self._on_event('epoch') - # called when the agent is sending an association frame - def on_association(self, agent, access_point): - self._on_event('association') + # called when successfully connected to a bluetooth host + def on_bt_connected(self, agent, bthost_name): + self._on_event('bt_connected') - # called when the agent is deauthenticating a client station from an AP - def on_deauthentication(self, agent, access_point, client_station): - self._on_event('deauthentication') + # called when disconnected from bluetooth host + def on_bt_disconnected(self, agent): + self._on_event('bt_disconnected') - # called when a new handshake is captured, access_point and client_station are json objects - # if the agent could match the BSSIDs to the current list, otherwise they are just the strings of the BSSIDs - def on_handshake(self, agent, filename, access_point, client_station): - self._on_event('handshake') + # called when plover boots + def on_plover_boot(self, agent): + self._on_event('plover_boot') - # called when an epoch is over (where an epoch is a single loop of the main algorithm) - def on_epoch(self, agent, epoch, epoch_data): - self._on_event('epoch') + # called when plover is ready + def on_plover_ready(self, agent): + self._on_event('plover_ready') + + # called when plover quits + def on_plover_quit(self, agent): + self._on_event('plover_quit') + + # called when wifi is connected + def on_wifi_connected(self, agent, ssid, ip): + self._on_event('wifi_connected') + + # called when wifi is disconnected + def on_wifi_disconnected(self, agent): + self._on_event('wifi_disconnected') - # called when a new peer is detected - def on_peer_detected(self, agent, peer): - self._on_event('peer_detected') + # called when wpm stats are updated + def on_wpm_stats(self, agent): + self._on_event('wpm_set') - # called when a known peer is lost - def on_peer_lost(self, agent, peer): - self._on_event('peer_lost') + # called when wpm-strokes stats are updated + def on_strokes_stats(self, agent): + self._on_event('strokes_set') \ No newline at end of file From 7994a3cceef00f58f0fd40fed78fbf56b5568db0 Mon Sep 17 00:00:00 2001 From: Anodynous Date: Mon, 22 Mar 2021 22:12:29 +0200 Subject: [PATCH 04/17] Add original author of plugin --- stenogotchi/plugins/default/buttonshim.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stenogotchi/plugins/default/buttonshim.py b/stenogotchi/plugins/default/buttonshim.py index 9f82756..0331b9f 100644 --- a/stenogotchi/plugins/default/buttonshim.py +++ b/stenogotchi/plugins/default/buttonshim.py @@ -98,7 +98,7 @@ def __init__(self, plugin): class Buttonshim(plugins.Plugin): - __author__ = 'Anodynous' + __author__ = 'gon@o2online.de, Anodynous' __version__ = '0.0.2' __license__ = 'GPL3' __description__ = 'Pimoroni Button Shim GPIO Button and RGB LED support plugin based on the pimoroni-buttonshim-lib and the pwnagotchi-gpio-buttons-plugin' From 79e77e42dd21cc5dc606eed3bf78de116f019230 Mon Sep 17 00:00:00 2001 From: Anodynous Date: Mon, 22 Mar 2021 22:28:27 +0200 Subject: [PATCH 05/17] Add three new faces to indicate processing status. Idea taken from https://github.com/evilsocket/pwnagotchi/pull/969 --- CHANGELOG.md | 3 +++ stenogotchi/defaults.toml | 3 +++ stenogotchi/ui/faces.py | 3 +++ 3 files changed, 9 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 461f298..4db631f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,8 +7,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] ### Added - Add DS3231 real time clock module wiring and positioning reference picture to README. +- Add three new faces to indicate processing status. ### Changed +- Change led plugin and default patterns to better indicate noteworthy events. + ### Fixed ### Removed diff --git a/stenogotchi/defaults.toml b/stenogotchi/defaults.toml index 4360f2b..932f151 100644 --- a/stenogotchi/defaults.toml +++ b/stenogotchi/defaults.toml @@ -54,6 +54,9 @@ ui.faces.angry = "(-_-')" ui.faces.friend = "(♥‿‿♥)" ui.faces.broken = "(☓‿‿☓)" ui.faces.debug = "(#__#)" +ui.faces.process_1 = '(1__0)' +ui.faces.process_2 = '(1__1)' +ui.faces.process_3 = '(0__1)' ui.web.enabled = false ui.web.address = "192.168.1.111" diff --git a/stenogotchi/ui/faces.py b/stenogotchi/ui/faces.py index 27a3266..09e2722 100644 --- a/stenogotchi/ui/faces.py +++ b/stenogotchi/ui/faces.py @@ -20,6 +20,9 @@ FRIEND = '(♥‿‿♥)' BROKEN = '(☓‿‿☓)' DEBUG = '(#__#)' +PROCESS_1 = '(1__0)' +PROCESS_2 = '(1__1)' +PROCESS_3 = '(0__1)' def load_from_config(config): From 9eb501e4bcb4cc250be6176bf8b09ea6399e1c5b Mon Sep 17 00:00:00 2001 From: Anodynous Date: Mon, 22 Mar 2021 22:44:38 +0200 Subject: [PATCH 06/17] Add 4th processing face to complete animation --- stenogotchi/defaults.toml | 1 + stenogotchi/ui/faces.py | 1 + 2 files changed, 2 insertions(+) diff --git a/stenogotchi/defaults.toml b/stenogotchi/defaults.toml index 932f151..d0f5f26 100644 --- a/stenogotchi/defaults.toml +++ b/stenogotchi/defaults.toml @@ -57,6 +57,7 @@ ui.faces.debug = "(#__#)" ui.faces.process_1 = '(1__0)' ui.faces.process_2 = '(1__1)' ui.faces.process_3 = '(0__1)' +ui.faces.process_4 = '(0__0)' ui.web.enabled = false ui.web.address = "192.168.1.111" diff --git a/stenogotchi/ui/faces.py b/stenogotchi/ui/faces.py index 09e2722..bcb2a7e 100644 --- a/stenogotchi/ui/faces.py +++ b/stenogotchi/ui/faces.py @@ -23,6 +23,7 @@ PROCESS_1 = '(1__0)' PROCESS_2 = '(1__1)' PROCESS_3 = '(0__1)' +PROCESS_4 = '(0__0)' def load_from_config(config): From 3ebac88ba29df01b235c356ee6459e3211e0c680 Mon Sep 17 00:00:00 2001 From: Anodynous Date: Mon, 22 Mar 2021 23:17:42 +0200 Subject: [PATCH 07/17] Version bump --- stenogotchi/_version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stenogotchi/_version.py b/stenogotchi/_version.py index cba8e59..a55ccd2 100644 --- a/stenogotchi/_version.py +++ b/stenogotchi/_version.py @@ -1 +1 @@ -__version__ = '0.0.4' \ No newline at end of file +__version__ = '0.0.5' \ No newline at end of file From 7b0a525f72197c26274466b7c21a59435d27dcdb Mon Sep 17 00:00:00 2001 From: Anodynous Date: Mon, 22 Mar 2021 23:48:24 +0200 Subject: [PATCH 08/17] Add processing animation --- CHANGELOG.md | 4 ++-- stenogotchi/automata.py | 4 ++++ stenogotchi/ui/view.py | 15 +++++++++++---- 3 files changed, 17 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4db631f..d199251 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,8 +6,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] ### Added -- Add DS3231 real time clock module wiring and positioning reference picture to README. -- Add three new faces to indicate processing status. +- DS3231 real time clock module wiring and positioning reference picture to README. +- Four new faces, producing processing animation when combined. ### Changed - Change led plugin and default patterns to better indicate noteworthy events. diff --git a/stenogotchi/automata.py b/stenogotchi/automata.py index 9aaf645..6fe58d3 100644 --- a/stenogotchi/automata.py +++ b/stenogotchi/automata.py @@ -43,6 +43,10 @@ def set_excited(self): self._view.on_excited() plugins.on('excited', self) + def set_processing(self): + self._view.on_processing() + plugins.on('processing', self) + def set_rebooting(self): self._view.on_rebooting() plugins.on('rebooting', self) diff --git a/stenogotchi/ui/view.py b/stenogotchi/ui/view.py index 0416825..d5b560d 100644 --- a/stenogotchi/ui/view.py +++ b/stenogotchi/ui/view.py @@ -264,6 +264,16 @@ def on_lonely(self): self.set('status', self._voice.on_lonely()) self.update() + def on_processing(self): + start_face = self._state.get('face') + processing_faces = [faces.PROCESS_1, faces.PROCESS_2, faces.PROCESS_3, faces.PROCESS_4] + for face in processing_faces: + self.set('face', face) + self.update() + time.sleep(2) + self.set('face', start_face) + self.update() + def on_rebooting(self): self.set('face', faces.BROKEN) self.set('status', self._voice.on_rebooting()) @@ -281,7 +291,7 @@ def on_plover_boot(self): self.update() def on_plover_ready(self): - face = random.choice((faces.AWAKE, faces.LOOK_R_HAPPY, faces.HAPPY, faces.EXCITED, faces.GRATEFUL, faces.MOTIVATED)) + face = random.choice((faces.AWAKE, faces.LOOK_R_HAPPY, faces.HAPPY, faces.EXCITED, faces.GRATEFUL)) self.set('face', face) self.set('status', self._voice.on_plover_ready()) if self._state.get('mode') == 'NONE': @@ -297,10 +307,7 @@ def on_plover_quit(self): self.update() def on_set_wpm(self, wpm): - # Implement check for strokes data and show in () after wpm. Or show top session wpm in this - # Add option to reset top session stat with button self.set('wpm', wpm) - # set face if new top wpm reached, with reaction text self.update() def on_set_strokes(self, strokes): From a6b991f377eb11bee3b225d7c92ad34c08ec218f Mon Sep 17 00:00:00 2001 From: Anodynous Date: Wed, 24 Mar 2021 00:10:52 +0200 Subject: [PATCH 09/17] Fix endless while-loop breaking qwerty mode --- stenogotchi/plugins/default/evdevkb.py | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/stenogotchi/plugins/default/evdevkb.py b/stenogotchi/plugins/default/evdevkb.py index 76c94b4..7c79d08 100644 --- a/stenogotchi/plugins/default/evdevkb.py +++ b/stenogotchi/plugins/default/evdevkb.py @@ -265,15 +265,14 @@ def get_keyboards(self): def set_keyboards(self): # Sets all keyboards as device to listen for key-inputs from - while self.do_capture: - while not self.have_kb: - keyboards = self.get_keyboards() - if keyboards: - self.devs = keyboards - self.have_kb = True - else: - logging.debug('[evdevkb] Keyboard not found, waiting 3 seconds and retrying') - sleep(3) + while not self.have_kb: + keyboards = self.get_keyboards() + if keyboards: + self.devs = keyboards + self.have_kb = True + else: + logging.debug('[evdevkb] Keyboard not found, waiting 3 seconds and retrying') + sleep(3) def update_mod_keys(self, mod_key, value): """ From fdfa88b8fb79a87d02cbb743db330a15ec5bde20 Mon Sep 17 00:00:00 2001 From: Anodynous Date: Wed, 24 Mar 2021 00:13:42 +0200 Subject: [PATCH 10/17] Fix shift-modifier key --- CHANGELOG.md | 5 ++++- plover_plugin/stenogotchi_link/clients.py | 10 +++++----- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d199251..d1ad01d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,9 +10,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Four new faces, producing processing animation when combined. ### Changed -- Change led plugin and default patterns to better indicate noteworthy events. +- Led plugin and default patterns to better indicate noteworthy events. ### Fixed +- Issues with letter capitalization and special characters due to flawed shift modifier-key execution. +- QWERTY-mode breaking bug. + ### Removed ## [0.0.4] - 2021-03-21 diff --git a/plover_plugin/stenogotchi_link/clients.py b/plover_plugin/stenogotchi_link/clients.py index ee9b457..8e8600d 100644 --- a/plover_plugin/stenogotchi_link/clients.py +++ b/plover_plugin/stenogotchi_link/clients.py @@ -16,7 +16,7 @@ SERVER_SRVC = '/com/github/stenogotchi' ERROR_NO_SERVER: str = 'A server is not currently running' ERROR_SERVER_RUNNING: str = 'A server is already running' -TIME_SLEEP = 0.001 +TIME_SLEEP = 0 class StenogotchiClient: @@ -171,12 +171,12 @@ def send_plover_keycode(self, keycode, modifiers=0): # for n in range(8) # if (modifiers & (1 << n)) #] - if modifiers > 1: - logging.debug("[stenogotchi_link] Modifier received: " + str(modifiers) +" keycode" + str(keycode)) + #if modifiers > 1: + # logging.debug("[stenogotchi_link] Modifier received: " + str(modifiers) +" keycode" + str(keycode)) # Update modifier keys #for mod_keycode in modifiers_list: # self.update_mod_keys(plover_modkey(mod_keycode), 1) - if modifiers > 1: # Should update this to handle multiple modifier keys like plover does + if modifiers > 0: # Should look at handling multiple modifiers in combination, but only shift seems to be needed in default plover keymap. self.update_mod_keys(plover_modkey(modifiers), 1) # Press and release the base key. @@ -186,7 +186,7 @@ def send_plover_keycode(self, keycode, modifiers=0): self.update_keys(plover_convert(keycode), 0) self.send_keys() # Release modifiers - if modifiers == 1: + if modifiers > 0: self.update_mod_keys(plover_modkey(modifiers), 0) #for mod_keycode in reversed(modifiers_list): # self.update_mod_keys(plover_modkey(mod_keycode), 0) From df0ef49494198fdd5013cc16f2270cf579c16d4c Mon Sep 17 00:00:00 2001 From: Anodynous Date: Wed, 24 Mar 2021 01:37:57 +0200 Subject: [PATCH 11/17] Add handling for return-key and few special chars --- CHANGELOG.md | 4 +- plover_plugin/stenogotchi_link/clients.py | 19 ++- plover_plugin/stenogotchi_link/keymap.py | 120 +++++++++++++++++- .../stenogotchi_link/stenogotchi_link.py | 4 +- 4 files changed, 140 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d1ad01d..64e8703 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,8 +13,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Led plugin and default patterns to better indicate noteworthy events. ### Fixed -- Issues with letter capitalization and special characters due to flawed shift modifier-key execution. -- QWERTY-mode breaking bug. +- QWERTY-mode breaking bug introduced in v0.0.4. +- Letter capitalization, symbol characters and return key in STENO-mode. ### Removed diff --git a/plover_plugin/stenogotchi_link/clients.py b/plover_plugin/stenogotchi_link/clients.py index 8e8600d..d7d2408 100644 --- a/plover_plugin/stenogotchi_link/clients.py +++ b/plover_plugin/stenogotchi_link/clients.py @@ -192,10 +192,27 @@ def send_plover_keycode(self, keycode, modifiers=0): # self.update_mod_keys(plover_modkey(mod_keycode), 0) def send_string(self, s): + special_cases = ['<', '(', ')'] for char in s: + if char in special_cases: + if char == '<': + self.send_plover_keycode(59,1) # shift(,) + elif char == '(': + self.send_plover_keycode(18,1) # shift(9) + elif char == ')': + self.send_plover_keycode(19,1) # shift(0) keysym = uchr_to_keysym(char) mapping = self.ke._get_mapping(keysym) if mapping is None: continue self.send_plover_keycode(mapping.keycode, - mapping.modifiers) \ No newline at end of file + mapping.modifiers) + + def send_key_combination(self, combination: str): + """ + TODO: handle properly all combinations, like Control_L(BackSpace) + """ + if combination == 'Return': + self.send_plover_keycode(36) + else: + print(f"Received unknown key_combination from Plover: {combination}") diff --git a/plover_plugin/stenogotchi_link/keymap.py b/plover_plugin/stenogotchi_link/keymap.py index 7c7361f..fd9d674 100644 --- a/plover_plugin/stenogotchi_link/keymap.py +++ b/plover_plugin/stenogotchi_link/keymap.py @@ -1,3 +1,6 @@ +# Find HID keycode mapping here: https://www.usb.org/sites/default/files/documents/hut1_12v2.pdf +# Linux keycode : HID keycode + plover_keytable = { # Function row. 67: 58, #"F1", @@ -79,6 +82,11 @@ 23 : 43, #"Tab", 111: 82, #"Up", 65 : 44, #"space", + # Keypad keys mapped by Plover + 94 : 197, # "Keypad <" # not working, shift(,) should work instead. Added as special case for send_string(). + 126 : 215, # "Keypad ±" # tested ok + 187 : 182, # "Keypad (" # not working, shift(9) should work instead. Added as special case for send_string(). + 188 : 183, # "Keypad )" # not working, shift(0) should work instead. Added as special case for send_string(). } # Map modifier keys to array element in the bit array @@ -100,4 +108,114 @@ def plover_modkey(plover_keycode): if plover_keycode in plover_modkeys: return plover_modkeys[plover_keycode] else: - return -1 # Return an invalid array element \ No newline at end of file + return -1 # Return an invalid array element + +""" Plover keymap debug +TODO make modular instead of hardcoded translation to HID. + +keymap: +linux keycode:shift modifier + +9:0=ff1b[] # Escape +10:0=31[1] +10:1=21[!] +11:0=32[2] +11:1=40[@] +12:0=33[3] +12:1=23[#] +13:0=34[4] +13:1=24[$] +14:0=35[5] +14:1=25[%] +15:0=36[6] +15:1=5e[^] +16:0=37[7] +16:1=26[&] +17:0=38[8] +17:1=2a[*] +18:0=39[9] +19:0=30[0] +20:0=2d[-] +20:1=5f[_] +21:0=3d[=] +21:1=2b[+] +22:0=ff08[] # Backspace +23:0=ff09[ ] # Tab +23:1=fe20[] # Backtab +24:0=71[q] +24:1=51[Q] +25:0=77[w] +25:1=57[W] +26:0=65[e] +26:1=45[E] +27:0=72[r] +27:1=52[R] +28:0=74[t] +28:1=54[T] +29:0=79[y] +29:1=59[Y] +30:0=75[u] +30:1=55[U] +31:0=69[i] +31:1=49[I] +32:0=6f[o] +32:1=4f[O] +33:0=70[p] +33:1=50[P] +34:0=5b[[] +34:1=7b[{] +35:0=5d[]] +35:1=7d[}] +]36:0=ff0d[ # Return +37:0=ffe3[] # Caps Lock ? +38:0=61[a] +38:1=41[A] +39:0=73[s] +39:1=53[S] +40:0=64[d] +40:1=44[D] +41:0=66[f] +41:1=46[F] +42:0=67[g] +42:1=47[G] +43:0=68[h] +43:1=48[H] +44:0=6a[j] +44:1=4a[J] +45:0=6b[k] +45:1=4b[K] +46:0=6c[l] +46:1=4c[L] +47:0=3b[;] +47:1=3a[:] +48:0=27['] +48:1=22["] +49:0=60[`] +49:1=7e[~] +50:0=ffe1[] # Shift ? +51:0=5c[\] +51:1=7c[|] +52:0=7a[z] +52:1=5a[Z] +53:0=78[x] +53:1=58[X] +54:0=63[c] +54:1=43[C] +55:0=76[v] +55:1=56[V] +56:0=62[b] +56:1=42[B] +57:0=6e[n] +57:1=4e[N] +58:0=6d[m] +58:1=4d[M] +59:0=2c[,] +60:0=2e[.] +60:1=3e[>] +61:0=2f[/] +61:1=3f[?] +94:0=3c[<] +126:0=b1[±] +187:0=28[(] +188:0=29[)] +""" \ No newline at end of file diff --git a/plover_plugin/stenogotchi_link/stenogotchi_link.py b/plover_plugin/stenogotchi_link/stenogotchi_link.py index 64288c9..3e3124e 100644 --- a/plover_plugin/stenogotchi_link/stenogotchi_link.py +++ b/plover_plugin/stenogotchi_link/stenogotchi_link.py @@ -185,9 +185,7 @@ def _on_send_key_combination(self, combination: str): Keys are represented by their names based on the OS-specific keyboard implementations in plover.oslayer. """ - - data = {'send_key_combination': combination} - logging.debug(f'[stenogotchi_link] _on_send_key_combination data: {data}') + self._btclient.send_key_combination(combination) def _on_add_translation(self): """Broadcasts when the add translation tool is opened via a command.""" From 4a86efb74b8948a3ac6293bf702f5c0657c5b5b8 Mon Sep 17 00:00:00 2001 From: Anodynous Date: Wed, 24 Mar 2021 01:41:05 +0200 Subject: [PATCH 12/17] Version bump --- plover_plugin/setup.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plover_plugin/setup.cfg b/plover_plugin/setup.cfg index 98a6f53..f0efa59 100644 --- a/plover_plugin/setup.cfg +++ b/plover_plugin/setup.cfg @@ -1,6 +1,6 @@ [metadata] name = stenogotchi_link -version = 0.0.4 +version = 0.0.5 description = A plugin for exposing Plover events and communicating with Stenogotchi over D-Bus long_description = author = Anodynous From a2def3786672897c615c0dc20b7d52a8e180abb2 Mon Sep 17 00:00:00 2001 From: Anodynous Date: Wed, 24 Mar 2021 01:59:36 +0200 Subject: [PATCH 13/17] Fix endlessly looking for keyboard if n/a --- stenogotchi/plugins/default/evdevkb.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/stenogotchi/plugins/default/evdevkb.py b/stenogotchi/plugins/default/evdevkb.py index 7c79d08..506680b 100644 --- a/stenogotchi/plugins/default/evdevkb.py +++ b/stenogotchi/plugins/default/evdevkb.py @@ -266,6 +266,8 @@ def get_keyboards(self): def set_keyboards(self): # Sets all keyboards as device to listen for key-inputs from while not self.have_kb: + if not self.do_capture: + break keyboards = self.get_keyboards() if keyboards: self.devs = keyboards From ab99b0b465a1a625340693374f08e126690c960a Mon Sep 17 00:00:00 2001 From: Anodynous Date: Wed, 24 Mar 2021 20:26:14 +0200 Subject: [PATCH 14/17] Refactor: clean up plugins a bit --- stenogotchi/plugins/default/buttonshim.py | 8 +++++--- stenogotchi/plugins/default/evdevkb.py | 7 +++++-- stenogotchi/plugins/default/led.py | 3 +++ stenogotchi/plugins/default/memtemp.py | 3 +++ stenogotchi/plugins/default/plover_link.py | 15 +++++++++------ stenogotchi/plugins/default/upslite.py | 3 +++ 6 files changed, 28 insertions(+), 11 deletions(-) diff --git a/stenogotchi/plugins/default/buttonshim.py b/stenogotchi/plugins/default/buttonshim.py index 0331b9f..f77006a 100644 --- a/stenogotchi/plugins/default/buttonshim.py +++ b/stenogotchi/plugins/default/buttonshim.py @@ -121,7 +121,6 @@ def __init__(self): self._states = 0b00011111 self._handlers = [None,None,None,None,None] self._button_was_held = False - def on_loaded(self): logging.info("[buttonshim] GPIO Button plugin loaded.") @@ -131,6 +130,9 @@ def on_loaded(self): self.on_hold([BUTTON_A, BUTTON_B, BUTTON_C, BUTTON_D, BUTTON_E], self.hold_handler) self.on_release([BUTTON_A, BUTTON_B, BUTTON_C, BUTTON_D, BUTTON_E], self.release_handler) + def on_config_changed(self, config): + self.config = config + def on_ready(self, agent): self._agent = agent @@ -472,8 +474,8 @@ def toggle_qwerty_steno(): def toggle_wpm_meters(): command = {} try: - wpm_method = self._agent._config['main']['plugins']['plover_link']['wpm_method'] - wpm_timeout = self._agent._config['main']['plugins']['plover_link']['wpm_timeout'] + wpm_method = plugins.loaded['plover_link'].options['wpm_method'] + wpm_timeout = plugins.loaded['plover_link'].options['wpm_timeout'] except Exception as ex: logging.exception(f"[buttonshim] Check that wpm_method and wpm_timeout is configured. Falling back to defaults. Exception: {str(ex)}") wpm_method = 'ncra' diff --git a/stenogotchi/plugins/default/evdevkb.py b/stenogotchi/plugins/default/evdevkb.py index 506680b..8ecc0cc 100644 --- a/stenogotchi/plugins/default/evdevkb.py +++ b/stenogotchi/plugins/default/evdevkb.py @@ -311,10 +311,10 @@ def state(self): return [0xA1, 0x01, self.mod_keys, 0, *self.pressed_keys] def send_keys(self): - # If we have self._skip_dbus, use plugin function directly + # If ran as part of Stenogotchi, communicate directly with plugin if self._skip_dbus: plugins.loaded['plover_link']._stenogotchiservice.send_keys(self.state) - # If we lack self._skip_dbus assume we need to use dbus to access send_keys() + # If ran as stand-alone, assume dbus is needed to access send_keys() function else: self.btk_service.send_keys(self.state) @@ -358,6 +358,9 @@ def __init__(self): def on_ready(self, agent): self._agent = agent + def on_config_changed(self, config): + self.config = config + def trigger_ui_update(self, input_mode): self._agent.view().set('mode', input_mode) self._agent.view().update() diff --git a/stenogotchi/plugins/default/led.py b/stenogotchi/plugins/default/led.py index c2002ef..ae7dc0d 100644 --- a/stenogotchi/plugins/default/led.py +++ b/stenogotchi/plugins/default/led.py @@ -36,6 +36,9 @@ def on_loaded(self): self._on_event('loaded') _thread.start_new_thread(self._worker, ()) + def on_config_changed(self, config): + self.config = config + def _on_event(self, event): if not self._is_busy: self._event_name = event diff --git a/stenogotchi/plugins/default/memtemp.py b/stenogotchi/plugins/default/memtemp.py index afedbdf..6a6f7d0 100644 --- a/stenogotchi/plugins/default/memtemp.py +++ b/stenogotchi/plugins/default/memtemp.py @@ -45,6 +45,9 @@ def on_loaded(self): logging.info("[memtemp] memtemp plugin loaded.") _thread.start_new_thread(self._cpu_poller(), ()) + def on_config_changed(self, config): + self.config = config + def mem_usage(self): return int(stenogotchi.mem_usage() * 100) diff --git a/stenogotchi/plugins/default/plover_link.py b/stenogotchi/plugins/default/plover_link.py index 473fd30..589aeef 100644 --- a/stenogotchi/plugins/default/plover_link.py +++ b/stenogotchi/plugins/default/plover_link.py @@ -66,9 +66,9 @@ class BTKbDevice: """ create a bluetooth device to emulate a HID keyboard """ - # Service port - must match port configured in SDP record + # Service control port - must match port configured in SDP record P_CTRL = 17 - # Service port - must match port configured in SDP record#Interrrupt port + # Service interrupt port - must match port configured in SDP record P_INTR = 19 # BlueZ dbus PROFILE_DBUS_PATH = '/bluez/yaptb/btkb_profile' @@ -117,7 +117,7 @@ def __init__(self, hci=0): # set the Bluetooth device configuration try: - self.alias = plugins.loaded['plover_link']._agent._config['main']['plugins']['plover_link']['bt_device_name'] + self.alias = plugins.loaded['plover_link'].options['bt_device_name'] except: self.alias = 'Bluetooth Keyboard' self.discoverabletimeout = 0 @@ -272,7 +272,7 @@ def listen(self): self._agent.set_bt_connected(self.bthost_name) def auto_connect(self): - bt_autoconnect_mac = plugins.loaded['plover_link']._agent._config['main']['plugins']['plover_link']['bt_autoconnect_mac'] + bt_autoconnect_mac = plugins.loaded['plover_link'].options['bt_autoconnect_mac'] if not bt_autoconnect_mac: logging.info('[plover_link] No bt_autoconnect_mac set in config. Listening for incoming connections instead...') @@ -392,14 +392,14 @@ class PloverLink(ObjectClass): __description__ = 'This plugin enables connectivity to Plover through D-Bus. Note that it needs root permissions due to using sockets' def __init__(self): - self._agent = None # only added to be able to do callbacks ot agent events + self._agent = None self.running = False self._stenogotchiservice = None self.mainloop = None # called when everything is ready and the main loop is about to start def on_ready(self, agent): - self._agent = agent + self._agent = agent # used for agent/automata functionsadded to be able to do callbacks to agent events DBusGMainLoop(set_as_default=True) self._stenogotchiservice = StenogotchiService() @@ -411,6 +411,9 @@ def on_ready(self, agent): logging.info("[plover_link] PloverLink is up") except: logging.error("[plover_link] Could not start PloverLink") + + def on_config_changed(self, config): + self.config = config def on_unload(self, ui): self.mainloop.quit() diff --git a/stenogotchi/plugins/default/upslite.py b/stenogotchi/plugins/default/upslite.py index e889543..666f37b 100644 --- a/stenogotchi/plugins/default/upslite.py +++ b/stenogotchi/plugins/default/upslite.py @@ -51,6 +51,9 @@ def on_loaded(self): self._quickstart() except: logging.error("[upslite] Could not start UPS-Lite plugin") + + def on_config_changed(self, config): + self.config = config # Called when the ui is updated def on_ui_update(self, ui): From 8ebbd641e41432bf359ba60e75154f6f7d44e720 Mon Sep 17 00:00:00 2001 From: Anodynous Date: Wed, 24 Mar 2021 20:53:09 +0200 Subject: [PATCH 15/17] Docs: add updating process --- README.md | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 72a5057..41b5103 100644 --- a/README.md +++ b/README.md @@ -152,12 +152,11 @@ All commands should be executed as root. The installation process can be complet CONFIG_BOOT_WAIT_FOR_NETWORK=0 CONFIG_NTP_MODE=0 - ## Configuration -* Configuration files are placed in /etc/stenogotchi/ - * Create a file called config.toml with overrides to the defaults. Don't edit default.toml directly as it is overwritten on version updates. -* Define your bluetooth devices in main.plugins.plover_link.bt_autoconnect_mac for auto-connect upon boot. Multiple comma separated devices in order of preference can be given. If no connection attempts are successful, the device will fall back to listening for incoming connection attempts. - * Issues with pairing or connecting after changes in bluetooth configurations can usually be fixed by unpairing the devices and re-pairing. On the Stenogotchi this is handled through bluetoothctl. +* Configuration files are placed in /etc/stenogotchi/. Create a separate file named config.toml containing overrides to the defaults. Don't edit default.toml directly as it will be overwritten on Stenogotchi version updates. + +* Define your bluetooth devices in main.plugins.plover_link.bt_autoconnect_mac to auto-connect on boot. Multiple comma separated devices in order of priority can be given. If no connection attempts are successful, the device will fall back to listening for incoming connection attempts. + * Issues with pairing or connecting after changes in bluetooth configurations can usually be fixed through unpairing and re-pairing. On the Stenogotchi side this is best handled through bluetoothctl. bluetoothctl [bluetooth]# paired-devices @@ -165,12 +164,17 @@ All commands should be executed as root. The installation process can be complet [bluetooth]# remove 00:DE:AD:BE:EF:00 [bluetooth]# exit +## Updating + cd ~/stenogotchi + git pull + pip3 install ./stenogotchi/plover_plugin/ ## Usage ![stenogotchi_2](https://user-images.githubusercontent.com/17461433/107883149-d5539680-6ef5-11eb-86fe-41f0b6293eed.jpg) ### Buttonshim Below long-press (1s) actions are pre-defined. Short-press triggers user configurable terminal commands. + * Button A - toggle QWERTY / STENO mode * Button B - toggle wpm readings (60s NCRA) From 9f1d4b2ec83cc0bb775bfe5583dd864b08706029 Mon Sep 17 00:00:00 2001 From: Anodynous Date: Wed, 24 Mar 2021 23:17:17 +0200 Subject: [PATCH 16/17] Feat: track session top wpm result --- CHANGELOG.md | 1 + stenogotchi/plugins/default/buttonshim.py | 7 ++--- stenogotchi/plugins/default/plover_link.py | 10 ++++++- stenogotchi/ui/hw/waveshare2.py | 20 ++++++++++--- stenogotchi/ui/view.py | 34 +++++++++++----------- 5 files changed, 46 insertions(+), 26 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 64e8703..58d4e17 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added - DS3231 real time clock module wiring and positioning reference picture to README. - Four new faces, producing processing animation when combined. +- WPM stats now track and display top result for session. ### Changed - Led plugin and default patterns to better indicate noteworthy events. diff --git a/stenogotchi/plugins/default/buttonshim.py b/stenogotchi/plugins/default/buttonshim.py index f77006a..3daa487 100644 --- a/stenogotchi/plugins/default/buttonshim.py +++ b/stenogotchi/plugins/default/buttonshim.py @@ -487,15 +487,14 @@ def toggle_wpm_meters(): self.set_ui_update('strokes', '') self.trigger_ui_update() logging.info(f"[buttonshim] Disabled WPM readings") + elif not self._plover_wpm_meters_enabled: command = {'start_wpm_meter': 'wpm and strokes', 'wpm_method' : wpm_method, 'wpm_timeout' : wpm_timeout} - wpm_method_ui = wpm_method[0:6] - wpm_timeout_ui = wpm_timeout + 's' - self.set_ui_update('wpm', wpm_method_ui) - self.set_ui_update('strokes', wpm_timeout_ui) + self.set_ui_update('wpm', wpm_method) + self.set_ui_update('strokes', f"{wpm_timeout}s") self.trigger_ui_update() logging.info(f"[buttonshim] Enabled WPM readings using method {wpm_method} and timeout {wpm_timeout}") diff --git a/stenogotchi/plugins/default/plover_link.py b/stenogotchi/plugins/default/plover_link.py index 589aeef..abfebbb 100644 --- a/stenogotchi/plugins/default/plover_link.py +++ b/stenogotchi/plugins/default/plover_link.py @@ -344,6 +344,7 @@ def __init__(self): self._agent = plugins.loaded['plover_link']._agent self.device = BTKbDevice() # create and setup our BTKbDevice self.device.auto_connect() # connect to preferred bt_mac. If unspecified or unavailable fall back to awaiting incoming connections + self.wpm_top = None @dbus.service.method('com.github.stenogotchi', in_signature='ay') # bytearray def send_keys(self, cmd): @@ -373,7 +374,14 @@ def plover_output_enabled(self, b): @dbus.service.method('com.github.stenogotchi', in_signature='s') # string def plover_wpm_stats(self, s): logging.debug('[plover_link] plover_wpm_stats = ' + s) - self._agent.set_wpm_stats(s) + if not self.wpm_top: + self.wpm_top = int(s) + else: + if int(s) > self.wpm_top: + self.wpm_top = int(s) + stats = '{:3s} {:5s}'.format(s, f"({self.wpm_top})") + + self._agent.set_wpm_stats(stats) @dbus.service.method('com.github.stenogotchi', in_signature='s') # string def plover_strokes_stats(self, s): diff --git a/stenogotchi/ui/hw/waveshare2.py b/stenogotchi/ui/hw/waveshare2.py index 40c6e54..582aa00 100644 --- a/stenogotchi/ui/hw/waveshare2.py +++ b/stenogotchi/ui/hw/waveshare2.py @@ -17,8 +17,14 @@ def layout(self): self._layout['face'] = (0, 40) self._layout['name'] = (5, 20) self._layout['ups'] = (0, 0) - self._layout['wpm'] = (52, 0) - self._layout['strokes'] = (112, 0) + self._layout['wpm'] = { + 'pos': (50, 0), + 'max': 9 + } + self._layout['strokes'] = { + 'pos': (128, 0), + 'max': 5 + } self._layout['uptime'] = (185, 0) self._layout['line1'] = [0, 14, 250, 14] self._layout['line2'] = [0, 108, 250, 108] @@ -45,8 +51,14 @@ def layout(self): self._layout['face'] = (0, 26) self._layout['name'] = (5, 15) self._layout['ups'] = (0, 0) - self._layout['wpm'] = (52, 0) - self._layout['strokes'] = (112, 0) + self._layout['wpm'] = { + 'pos': (50, 0), + 'max': 9 + } + self._layout['strokes'] = { + 'pos': (128, 0), + 'max': 5 + } self._layout['status'] = (91, 15) self._layout['uptime'] = (147, 0) self._layout['line1'] = [0, 12, 212, 12] diff --git a/stenogotchi/ui/view.py b/stenogotchi/ui/view.py index d5b560d..7cfb828 100644 --- a/stenogotchi/ui/view.py +++ b/stenogotchi/ui/view.py @@ -41,31 +41,29 @@ def __init__(self, config, impl, state=None): self._height = self._layout['height'] self._state = State(state={ 'ups': LabeledValue(color=BLACK, label='BAT', value='', position=self._layout['ups'], - label_font=fonts.Bold, - text_font=fonts.Medium), - 'wpm': LabeledValue(color=BLACK, label='WPM', value='', position=self._layout['wpm'], - label_font=fonts.Bold, - text_font=fonts.Medium), + label_font=fonts.Bold,text_font=fonts.Medium), - 'strokes': LabeledValue(color=BLACK, label='STR', value='', position=self._layout['strokes'], - label_font=fonts.Bold, - text_font=fonts.Medium), + 'wpm': LabeledValue(color=BLACK, label='WPM', value='', position=self._layout['wpm']['pos'], + label_font=fonts.Bold, text_font=fonts.Medium, max_length=self._layout['wpm']['max']), - 'uptime': LabeledValue(color=BLACK, label='UP', value='00:00:00', position=self._layout['uptime'], - label_font=fonts.Bold, - text_font=fonts.Medium), + 'strokes': LabeledValue(color=BLACK, label='STR', value='', position=self._layout['strokes']['pos'], + label_font=fonts.Bold, text_font=fonts.Medium, max_length=self._layout['strokes']['max']), + + 'uptime': LabeledValue(color=BLACK, label='UP', value='', position=self._layout['uptime'], + label_font=fonts.Bold, text_font=fonts.Medium), 'line1': Line(self._layout['line1'], color=BLACK), + 'line2': Line(self._layout['line2'], color=BLACK), - + 'face': Text(value=faces.SLEEP, position=self._layout['face'], color=BLACK, font=fonts.Huge), - + 'friend_face': Text(value=None, position=self._layout['friend_face'], font=fonts.Bold, color=BLACK), - 'friend_name': Text(value=None, position=self._layout['friend_name'], font=fonts.BoldSmall, - color=BLACK), - + + 'friend_name': Text(value=None, position=self._layout['friend_name'], font=fonts.BoldSmall, color=BLACK), + 'name': Text(value='%s>' % 'stenogotchi', position=self._layout['name'], color=BLACK, font=fonts.Bold), - + 'status': Text(value=self._voice.default(), position=self._layout['status']['pos'], color=BLACK, @@ -77,9 +75,11 @@ def __init__(self, config, impl, state=None): 'bthost': LabeledValue(label='BT', value='', color=BLACK, position=self._layout['bthost']['pos'], label_font=fonts.Bold, text_font=fonts.Medium, max_length=self._layout['bthost']['max']), + 'wifi': LabeledValue(label='WIFI', value='', color=BLACK, position=self._layout['wifi']['pos'], label_font=fonts.Bold, text_font=fonts.Medium, max_length=self._layout['wifi']['max']), + 'mode': Text(value='NONE', position=self._layout['mode'], font=fonts.Bold, color=BLACK), }) From 79bee6d4b402a85aab9e5737bbd1295b32238d97 Mon Sep 17 00:00:00 2001 From: Anodynous Date: Wed, 24 Mar 2021 23:28:37 +0200 Subject: [PATCH 17/17] Chore: prepare for release v0.0.5 --- CHANGELOG.md | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 58d4e17..8822eaf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] ### Added +### Changed +### Fixed +### Removed + +## [0.0.5] - 2021-03-24 +### Added - DS3231 real time clock module wiring and positioning reference picture to README. - Four new faces, producing processing animation when combined. - WPM stats now track and display top result for session. @@ -17,8 +23,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - QWERTY-mode breaking bug introduced in v0.0.4. - Letter capitalization, symbol characters and return key in STENO-mode. -### Removed - ## [0.0.4] - 2021-03-21 ### Added - This CHANGELOG file. @@ -52,6 +56,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - README now includes basic configuration and usage documentation. - LICENSE file. -[Unreleased]: https://github.com/Anodynous/stenogotchi/compare/v0.0.4...dev +[Unreleased]: https://github.com/Anodynous/stenogotchi/compare/v0.0.5...dev +[0.0.5]: https://github.com/Anodynous/stenogotchi/compare/v0.0.4...v0.0.5 [0.0.4]: https://github.com/Anodynous/stenogotchi/compare/v0.0.3...v0.0.4 [0.0.3]: https://github.com/Anodynous/stenogotchi/releases/tag/v0.0.3 \ No newline at end of file