From 81e7279a9e76bd6d3e314f9defd496fa22a26d8a Mon Sep 17 00:00:00 2001 From: Tom Kent Date: Fri, 15 Jan 2021 20:02:08 -0600 Subject: [PATCH 1/4] Remove extra self syntax error Typo that causes a crash if called. --- vcgencmd/vcgencmd.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vcgencmd/vcgencmd.py b/vcgencmd/vcgencmd.py index d8881b7..a74bda8 100644 --- a/vcgencmd/vcgencmd.py +++ b/vcgencmd/vcgencmd.py @@ -32,7 +32,7 @@ def get_sources(self, typ): return self.__sources.get(typ) def vcos_version(self): - out = self.self.__verify_command("vcos version", "", [""]) + out = self.__verify_command("vcos version", "", [""]) return str(out) def vcos_log_status(self): From a49624b3d6f1400338f1f0b8064af4db1a040be9 Mon Sep 17 00:00:00 2001 From: Thomas Kent Date: Fri, 15 Jan 2021 21:06:25 -0600 Subject: [PATCH 2/4] Must be lower to pass the check In __verify_command the source.lower() is used, so everything in the sources must also be lower or it will never match. --- vcgencmd/vcgencmd.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vcgencmd/vcgencmd.py b/vcgencmd/vcgencmd.py index d8881b7..0fe632d 100644 --- a/vcgencmd/vcgencmd.py +++ b/vcgencmd/vcgencmd.py @@ -4,7 +4,7 @@ class Vcgencmd: __sources = { - "clock": ["arm", "core","H264", "isp", "v3d", "uart", "pwm", "emmc", "pixel", "vec", "hdmi", "dpi"], + "clock": ["arm", "core","h264", "isp", "v3d", "uart", "pwm", "emmc", "pixel", "vec", "hdmi", "dpi"], "volts": ["core", "sdram_c", "sdram_i", "sdram_p"], "mem": ["arm", "gpu"], "codec": ["agif", "flac", "h263", "h264", "mjpa", "mjpb", "mjpg", "mpg2", "mpg4", "mvc0", "pcm", "thra", "vorb", "vp6", "vp8", "wmv9", "wvc1"], From 74c60de821ae7ddd357715655f521e8414d8b71f Mon Sep 17 00:00:00 2001 From: Thomas Kent Date: Sat, 16 Jan 2021 05:59:25 -0600 Subject: [PATCH 3/4] Descriptive output from throttling call In addition to the existing method that returns the bit field, return a dictionary with descriptive values, similar to mem_oom() and mem_reloc_stats(). --- README.md | 18 +++++++++++++++++- vcgencmd/vcgencmd.py | 20 ++++++++++++++++++++ 2 files changed, 37 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 14cdc31..370349d 100644 --- a/README.md +++ b/README.md @@ -82,7 +82,7 @@ Returns the enabled and detected state of the official camera in JSON format. 1 #### get_throttled() -Returns the throttled state of the system in JSON format. This is a bit pattern - a bit being set indicates the following meanings: +Returns the throttled state of the system in dictionaries (similar to JSON format). This is a bit pattern - a bit being set indicates the following meanings: | Bit | Meaning | |:---:|---------| @@ -110,6 +110,22 @@ Adding the bit numbers along the top we get: From this we can see that bits 18 and 16 are set, indicating that the Pi has previously been throttled due to under-voltage, but is not currently throttled for any reason. +#### get_throttled_flags() + +Returns a dictionary of the same results as `get_throttled()` but with the descriptive names as the keys. + +```python +>>> pprint.pp(out.get_throttled_flags()) +{'Under-voltage detected': False, + 'Arm frequency capped': False, + 'Currently throttled': False, + 'Soft temperature limit active': False, + 'Under-voltage has occurred': False, + 'Arm frequency capping has occurred': True, + 'Throttling has occurred': False, + 'Soft temperature limit has occurred': False} +``` + #### measure_temp() Returns the temperature of the SoC as measured by the on-board temperature sensor. diff --git a/vcgencmd/vcgencmd.py b/vcgencmd/vcgencmd.py index b16a262..4e2713d 100644 --- a/vcgencmd/vcgencmd.py +++ b/vcgencmd/vcgencmd.py @@ -79,6 +79,26 @@ def get_throttled(self): response["breakdown"]["19"] = state(binary_val[0:4][0]) return response + def get_throttled_flags(self): + bits = self.get_throttled()['breakdown'] + + mapping = { + "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" + } + + desc = {} + for bit, value in bits.items(): + desc[mapping[bit]] = value + + return desc + def measure_temp(self): out = self.__verify_command("measure_temp", "", [""]) return float(re.sub("[^\d\.]", "",out)) From fbe7412946566ca06ea23c55522e79919005ee69 Mon Sep 17 00:00:00 2001 From: Thomas Kent Date: Sat, 16 Jan 2021 07:31:30 -0600 Subject: [PATCH 4/4] Printable overview of all stats Added a simple helper function that prints out all the relevant details. Set it to be what runs from main with a `python3 -m vcgencmd` call. --- README.md | 53 +++++++++++++++++++++++++++++++ vcgencmd/__main__.py | 5 ++- vcgencmd/vcgencmd.py | 74 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 129 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 370349d..823f2a2 100644 --- a/README.md +++ b/README.md @@ -56,6 +56,59 @@ print(output) ``` +## Overview Output +See status from all fields on the command line. + +```text +$ sudo python3 -m vcgencmd +Binary Version +Nov 30 2020 22:12:08 +Copyright (c) 2012 Broadcom +version ab1181cc0cb6df52bfae3b1d3fef0ce7c325166c (clean) (release) (start) + + +Clock Frequencies (Hz) +arm : 1500398464 +core : 500000992 +h264 : 0 +isp : 0 +v3d : 500000992 +uart : 48001464 +pwm : 0 +emmc : 250000496 +pixel : 75001464 +vec : 0 +hdmi : 0 +dpi : 0 + +Voltages (V) +core : 0.8375 +sdram_c : 1.1 +sdram_i : 1.1 +sdram_p : 1.1 + +Memory (MB) (Not accurate on rpi4) +arm : 948 +gpu : 76 + +Temperatures (C) +core : 75.9 + +Video Core Log Status +mmal : opaque +gencmd_file : info +wdog : warn + + + +Display Status +display 0 : off +display 1 : off +display 2 : off +display 3 : off +display 7 : off +``` + ## Commands #### get_sources(src) diff --git a/vcgencmd/__main__.py b/vcgencmd/__main__.py index 16fe952..be09a29 100644 --- a/vcgencmd/__main__.py +++ b/vcgencmd/__main__.py @@ -1,10 +1,9 @@ -from .vcgencmd import Vcgencmd +from .vcgencmd import print_overview import sys def main(): - out = Vcgencmd().version() - print(out) + print_overview() if __name__ == "__main__": sys.exit(main()) diff --git a/vcgencmd/vcgencmd.py b/vcgencmd/vcgencmd.py index 4e2713d..a7ea18e 100644 --- a/vcgencmd/vcgencmd.py +++ b/vcgencmd/vcgencmd.py @@ -237,3 +237,77 @@ def display_power_state(self, display=0): return "off" elif out.split("=")[1].strip() == "1": return "on" + +def _print_dict(input_dict): + mm_fmt = "{:35s} : {}" + for key, val in input_dict.items(): + print(mm_fmt.format(key, val)) + +def print_overview(): + mm_fmt = "{:35s} : {}" + + stats = Vcgencmd() + print("Binary Version") + print(stats.version()) + + print("\nClock Frequencies (Hz)") + for clock in stats.get_sources("clock"): + val = stats.measure_clock(clock) + print(mm_fmt.format(clock, val)) + + print("\nVoltages (V)") + for volt in stats.get_sources("volts"): + val = stats.measure_volts(volt) + print(mm_fmt.format(volt, val)) + + print("\nMemory (MB) (Not accurate on rpi4)") + for mem in stats.get_sources("mem"): + val = stats.get_mem(mem) + print(mm_fmt.format(mem, val)) + + print("\nTemperatures (C)") + val = stats.measure_temp() + print(mm_fmt.format("core", val)) + + print("\nVideo Core Log Status") + _print_dict(stats.vcos_log_status()) + + print("\nCamera") + status = stats.get_camera() + print(mm_fmt.format("supported", status["supported"])) + print(mm_fmt.format("detected", status["detected"])) + + print("\nThrottling") + _print_dict(stats.get_throttled_flags()) + + print("\nOne Time Programmable Memory") + _print_dict(stats.otp_dump()) + + print("\nCodecs Enabled") + for codec in stats.get_sources("codec"): + val = stats.codec_enabled(codec) + print(mm_fmt.format(codec, val)) + + print("\nBoot Config Values (config.txt effective values)") + _print_dict(stats.get_config("str")) + _print_dict(stats.get_config("int")) + + print("\nLCD (px)") + _print_dict(stats.get_lcd_info()) + + print("\nstats Of Memory Events") + _print_dict(stats.mem_oom()) + + print("\nRelocatable Memory") + _print_dict(stats.mem_reloc_stats()) + + print("\nRing Oscillator") + _print_dict(stats.read_ring_osc()) + + print("\nHDMI Timings") + _print_dict(stats.hdmi_timings()["breakdown"]) + + print("\nDisplay Status") + for disp in stats.get_sources("display_id"): + val = stats.display_power_state(disp) + print(mm_fmt.format("display " + str(disp), val))