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

Add web UI notification for under voltage/throttling events #1203

Merged
merged 16 commits into from
Sep 1, 2023
Merged
Show file tree
Hide file tree
Changes from 7 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
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ Please check out the full story with much more detail on the [wiki](https://gith
# How do I contribute?
PiSCSI is using the <a href="https://datasift.github.io/gitflow/IntroducingGitFlow.html">Gitflow Workflow</a>. A quick overview:

- The *master* branch should always reflect the contents of the last stable release
- The *main* branch should always reflect the contents of the last stable release
- The *develop* branch should contain the latest tested & approved updates. Pull requests should be used to merge changes into develop.
- The rest of the feature branches are for developing new features
- A tag will be created for each "release". The releases will be named <year>.<month>.<release number> where the release number is incremented for each subsequent release tagged in the same calendar month. The first release of the month of January 2021 is called "21.01.01", the second one in the same month "21.01.02" and so on.
Expand Down
1 change: 1 addition & 0 deletions python/common/requirements.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
protobuf==3.19.5
requests==2.31.0
vcgencmd==0.1.1
8 changes: 8 additions & 0 deletions python/common/src/piscsi/return_codes.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,11 @@ class ReturnCodes:
EXTRACTIMAGE_NO_FILES_SPECIFIED = 91
EXTRACTIMAGE_NO_FILES_EXTRACTED = 92
EXTRACTIMAGE_COMMAND_ERROR = 93
UNDER_VOLTAGE_DETECTED = 100
ARM_FREQUENCY_CAPPED = 101
CURRENTLY_THROTTLED = 102
SOFT_TEMPERATURE_LIMIT_ACTIVE = 103
UNDER_VOLTAGE_HAS_OCCURED = 116
Copy link
Member

Choose a reason for hiding this comment

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

Nitpick: Spelling of "OCCURRED"

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

This was misspelled in a few places. They should all be fixed now.

ARM_FREQUENCY_CAPPING_HAS_OCCURRED = 117
THROTTLING_HAS_OCCURRED = 118
SOFT_TEMPERATURE_LIMIT_HAS_OCCURRED = 119
36 changes: 36 additions & 0 deletions python/common/src/piscsi/sys_cmds.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@
from socket import socket, gethostname, AF_INET, SOCK_DGRAM
from pathlib import Path
from platform import uname
from vcgencmd import Vcgencmd

from piscsi.return_codes import ReturnCodes
from piscsi.common_settings import SHELL_ERROR


Expand Down Expand Up @@ -263,3 +265,37 @@ def shutdown_system():
return process.returncode, process.stdout.decode("utf-8")

return process.returncode, process.stderr.decode("utf-8")

@staticmethod
def get_throttled(enabled_modes, test_modes):
"""
Takes (list) enabled_modes & (list) test_modes parameters & returns a
tuple of (str) category & (str) message.

enabled_modes is a list of modes that will be enabled for display if
they're triggered. test_modes works similarly to enabled_mode but will
ALWAYS display the modes listed for troubleshooting styling.
"""
vcgcmd = Vcgencmd()
t_states = vcgcmd.get_throttled()['breakdown']
matched_states = []

state_msgs = {
"0": ("error", ReturnCodes.UNDER_VOLTAGE_DETECTED),
"1": ("warning", ReturnCodes.ARM_FREQUENCY_CAPPED),
"2": ("error", ReturnCodes.CURRENTLY_THROTTLED),
"3": ("warning", ReturnCodes.SOFT_TEMPERATURE_LIMIT_ACTIVE),
"16": ("warning", ReturnCodes.UNDER_VOLTAGE_HAS_OCCURED),
"17": ("warning", ReturnCodes.ARM_FREQUENCY_CAPPING_HAS_OCCURRED),
"18": ("warning", ReturnCodes.THROTTLING_HAS_OCCURRED),
"19": ("warning", ReturnCodes.SOFT_TEMPERATURE_LIMIT_HAS_OCCURRED),
}

for k in t_states:
if t_states[k] and k in enabled_modes:
matched_states.append(state_msgs[k])

for t in test_modes:
matched_states.append(state_msgs[t])

return matched_states
23 changes: 23 additions & 0 deletions python/web/mock/bin/vcgencmd
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#!/usr/bin/env bash

# Info: https://www.raspberrypi.com/documentation/computers/os.html#vcgencmd
#
# Bit Hex value Meaning
# ----- ----------- ------------------------
# 0 0x1 Under-voltage detected
# 1 0x2 Arm frequency capped
# 2 0x4 Currently throttled
# 3 0x8 Soft temperature limit active
# 16 0x10000 Under-voltage has occurred
# 17 0x20000 Arm frequency capping has occurred
# 18 0x40000 Throttling has occurred
# 19 0x80000 Soft temperature limit has occurred

if [[ "$1" == "get_throttled" ]]
then
# Return 'Under-voltage detected' & 'Under-voltage has occurred'
echo "throttled=0x10001"
fi

echo "Mock does not recognize: $0 $@"
exit 1
16 changes: 16 additions & 0 deletions python/web/src/return_code_mapper.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,22 @@ class ReturnCodeMapper:
_("No files were extracted (existing files are skipped)"),
ReturnCodes.EXTRACTIMAGE_COMMAND_ERROR:
_("Unable to extract archive: %(error)s"),
ReturnCodes.UNDER_VOLTAGE_DETECTED:
_("Under voltage detected"),
ReturnCodes.ARM_FREQUENCY_CAPPED:
_("Arm frequency capped"),
Copy link
Member

Choose a reason for hiding this comment

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

Should "Arm" be all uppercase?

ReturnCodes.CURRENTLY_THROTTLED:
_("Currently throttled"),
ReturnCodes.SOFT_TEMPERATURE_LIMIT_ACTIVE:
_("Soft-temperature limit active"),
ReturnCodes.UNDER_VOLTAGE_HAS_OCCURED:
_("Under voltage has occured"),
Copy link
Member

Choose a reason for hiding this comment

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

One remaining typo here! (should say "occurred")

ReturnCodes.ARM_FREQUENCY_CAPPING_HAS_OCCURRED:
_("Arm frequency capping has occurred"),
ReturnCodes.THROTTLING_HAS_OCCURRED:
_("Throttling has occurred"),
ReturnCodes.SOFT_TEMPERATURE_LIMIT_HAS_OCCURRED:
_("Soft temperature limit has occurred")
}
# fmt: on

Expand Down
16 changes: 16 additions & 0 deletions python/web/src/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,19 @@

# Fallback theme for older browsers
TEMPLATE_THEME_LEGACY = "classic"

# Enable throttle notifications
#
# Available modes:
# "0": "Under-voltage detected"
# "1": "Arm frequency capped"
# "2": "Currently throttled"
# "3": "Soft temperature limit active"
# "16": "Under-voltage has occurred"
# "17": "Arm frequency capping has occurred"
# "18": "Throttling has occurred"
# "19": "Soft temperature limit has occurred"
THROTTLE_NOTIFY_MODES = ["0", "16"]
# Include a list of modes to be shown ALL THE TIME to be used for styling
# and formatting.
THROTTLE_TEST_MODES = []
33 changes: 33 additions & 0 deletions python/web/src/static/themes/classic/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -172,3 +172,36 @@ summary.filename {
left: 50%;
margin-left: -27px;
}

div.throttle_notice > div {
display: grid;
align-items: center;
background-color: #efefef;
background-repeat: no-repeat;
background-position: 1rem center;
background-size: 1rem;
font-size: x-small;
font-weight: bold;
justify-content: center;
}

div.throttle_notice > div.error {
background-color: #dc3545;
align-items: center;
}

div.throttle_notice > div.warning {
background-color: #ffc107;
align-items: center;
}

div.throttle_notice > div a {
color: black;
text-decoration: none;
}

div.throttle_notice > div a:hover {
text-decoration: underline;
}


43 changes: 43 additions & 0 deletions python/web/src/static/themes/modern/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -470,6 +470,49 @@ div.footer div.theme-change-hint a {
color: yellow;
}

/*
------------------------------------------------------------------------------
Throttle messages
------------------------------------------------------------------------------
*/

div.throttle_notice > div {
display: grid;
align-items: center;
background-color: #efefef;
background-repeat: no-repeat;
background-position: 1rem center;
background-size: 1rem;
font-size: x-small;
font-weight: bold;
}

div.throttle_notice > div.error {
background-color: var(--danger);
background-image: url("icons/error.svg");
color: #fff;
align-items: center;
}

div.throttle_notice > div.warning {
background-color: var(--warning);
background-image: url("icons/warning.svg");
align-items: center;
}

div.throttle_notice > div > span.message {
padding-left: 3rem;
}

div.throttle_notice > div a {
color: black;
text-decoration: none;
}

div.throttle_notice > div a:hover {
text-decoration: underline;
}

/*
------------------------------------------------------------------------------
Flash messages
Expand Down
10 changes: 10 additions & 0 deletions python/web/src/templates/base.html
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,16 @@ <h1>
</div>
</div>

<div class="throttle_notice">
{% if (env["throttle_status"]|length > 0) %}
{% for category, response in env["throttle_status"] %}
<div class="{{ category }}">
<span class="message" title="{{ response['msg'] }}"><a href="https://www.raspberrypi.com/documentation/computers/configuration.html#undervoltage-warning">{{ response['msg'] }}</a></span>
</div>
{% endfor %}
{% endif %}
</div>

<div class="flash" id="flash">
{% if get_flashed_messages(): %}
{% for category, message in get_flashed_messages(with_categories=true) %}
Expand Down
Loading