Last active
July 22, 2024 21:00
-
-
Save ranisalt/d83db5ecda9c6738e182ad34e259f7ef to your computer and use it in GitHub Desktop.
Cerberus, a Hades Canyon companion
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import logging | |
import sys | |
from argparse import ArgumentParser, ArgumentTypeError | |
from string import hexdigits | |
from typing import Tuple | |
# CSS3 COLORS | |
COLOR_NAMES = { | |
'aliceblue': '#f0f8ff', | |
'antiquewhite': '#faebd7', | |
'aqua': '#00ffff', | |
'aquamarine': '#7fffd4', | |
'azure': '#f0ffff', | |
'beige': '#f5f5dc', | |
'bisque': '#ffe4c4', | |
'black': '#000000', | |
'blanchedalmond': '#ffebcd', | |
'blue': '#0000ff', | |
'blueviolet': '#8a2be2', | |
'brown': '#a52a2a', | |
'burlywood': '#deb887', | |
'cadetblue': '#5f9ea0', | |
'chartreuse': '#7fff00', | |
'chocolate': '#d2691e', | |
'coral': '#ff7f50', | |
'cornflowerblue': '#6495ed', | |
'cornsilk': '#fff8dc', | |
'crimson': '#dc143c', | |
'cyan': '#00ffff', | |
'darkblue': '#00008b', | |
'darkcyan': '#008b8b', | |
'darkgoldenrod': '#b8860b', | |
'darkgray': '#a9a9a9', | |
'darkgrey': '#a9a9a9', | |
'darkgreen': '#006400', | |
'darkkhaki': '#bdb76b', | |
'darkmagenta': '#8b008b', | |
'darkolivegreen': '#556b2f', | |
'darkorange': '#ff8c00', | |
'darkorchid': '#9932cc', | |
'darkred': '#8b0000', | |
'darksalmon': '#e9967a', | |
'darkseagreen': '#8fbc8f', | |
'darkslateblue': '#483d8b', | |
'darkslategray': '#2f4f4f', | |
'darkslategrey': '#2f4f4f', | |
'darkturquoise': '#00ced1', | |
'darkviolet': '#9400d3', | |
'deeppink': '#ff1493', | |
'deepskyblue': '#00bfff', | |
'dimgray': '#696969', | |
'dimgrey': '#696969', | |
'dodgerblue': '#1e90ff', | |
'firebrick': '#b22222', | |
'floralwhite': '#fffaf0', | |
'forestgreen': '#228b22', | |
'fuchsia': '#ff00ff', | |
'gainsboro': '#dcdcdc', | |
'ghostwhite': '#f8f8ff', | |
'gold': '#ffd700', | |
'goldenrod': '#daa520', | |
'gray': '#808080', | |
'grey': '#808080', | |
'green': '#008000', | |
'greenyellow': '#adff2f', | |
'honeydew': '#f0fff0', | |
'hotpink': '#ff69b4', | |
'indianred': '#cd5c5c', | |
'indigo': '#4b0082', | |
'ivory': '#fffff0', | |
'khaki': '#f0e68c', | |
'lavender': '#e6e6fa', | |
'lavenderblush': '#fff0f5', | |
'lawngreen': '#7cfc00', | |
'lemonchiffon': '#fffacd', | |
'lightblue': '#add8e6', | |
'lightcoral': '#f08080', | |
'lightcyan': '#e0ffff', | |
'lightgoldenrodyellow': '#fafad2', | |
'lightgray': '#d3d3d3', | |
'lightgrey': '#d3d3d3', | |
'lightgreen': '#90ee90', | |
'lightpink': '#ffb6c1', | |
'lightsalmon': '#ffa07a', | |
'lightseagreen': '#20b2aa', | |
'lightskyblue': '#87cefa', | |
'lightslategray': '#778899', | |
'lightslategrey': '#778899', | |
'lightsteelblue': '#b0c4de', | |
'lightyellow': '#ffffe0', | |
'lime': '#00ff00', | |
'limegreen': '#32cd32', | |
'linen': '#faf0e6', | |
'magenta': '#ff00ff', | |
'maroon': '#800000', | |
'mediumaquamarine': '#66cdaa', | |
'mediumblue': '#0000cd', | |
'mediumorchid': '#ba55d3', | |
'mediumpurple': '#9370db', | |
'mediumseagreen': '#3cb371', | |
'mediumslateblue': '#7b68ee', | |
'mediumspringgreen': '#00fa9a', | |
'mediumturquoise': '#48d1cc', | |
'mediumvioletred': '#c71585', | |
'midnightblue': '#191970', | |
'mintcream': '#f5fffa', | |
'mistyrose': '#ffe4e1', | |
'moccasin': '#ffe4b5', | |
'navajowhite': '#ffdead', | |
'navy': '#000080', | |
'oldlace': '#fdf5e6', | |
'olive': '#808000', | |
'olivedrab': '#6b8e23', | |
'orange': '#ffa500', | |
'orangered': '#ff4500', | |
'orchid': '#da70d6', | |
'palegoldenrod': '#eee8aa', | |
'palegreen': '#98fb98', | |
'paleturquoise': '#afeeee', | |
'palevioletred': '#db7093', | |
'papayawhip': '#ffefd5', | |
'peachpuff': '#ffdab9', | |
'per': '#cd853f', | |
'pink': '#ffc0cb', | |
'plum': '#dda0dd', | |
'powderblue': '#b0e0e6', | |
'purple': '#800080', | |
'red': '#ff0000', | |
'rosybrown': '#bc8f8f', | |
'royalblue': '#4169e1', | |
'saddlebrown': '#8b4513', | |
'salmon': '#fa8072', | |
'sandybrown': '#f4a460', | |
'seagreen': '#2e8b57', | |
'seashell': '#fff5ee', | |
'sienna': '#a0522d', | |
'silver': '#c0c0c0', | |
'skyblue': '#87ceeb', | |
'slateblue': '#6a5acd', | |
'slategray': '#708090', | |
'slategrey': '#708090', | |
'snow': '#fffafa', | |
'springgreen': '#00ff7f', | |
'steelblue': '#4682b4', | |
'tan': '#d2b48c', | |
'teal': '#008080', | |
'thistle': '#d8bfd8', | |
'tomato': '#ff6347', | |
'turquoise': '#40e0d0', | |
'violet': '#ee82ee', | |
'wheat': '#f5deb3', | |
'white': '#ffffff', | |
'whitesmoke': '#f5f5f5', | |
'yellow': '#ffff00', | |
'yellowgreen': '#9acd32', | |
} | |
def hex2rgb(value: str) -> Tuple[int, int, int]: | |
value = COLOR_NAMES.get(value, value).lstrip('#') | |
if len(value) == 3: | |
value = ''.join(s * 2 for s in value) | |
if len(value) != 6 or any(c not in hexdigits for c in value): | |
raise ArgumentTypeError(f'{value} is not a valid hex color value') | |
rgb = int(value, 16) | |
return (rgb >> 16, rgb >> 8 & 0xff, rgb & 0xff) | |
PROCFILE = '/proc/acpi/nuc_led' | |
HDD_BEHAVIORS = { | |
'off': 0, | |
'on': 1, | |
} | |
INDICATION_SCHEMES = { | |
'gradient': 0, | |
'fixed': 1, | |
} | |
BLINKING_BEHAVIORS = { | |
'solid': 0, | |
'breathing': 1, | |
'pulsing': 2, | |
'strobing': 3, | |
} | |
INDICATORS = { | |
'power', | |
'hdd', | |
'ethernet', | |
'wifi', | |
'software', | |
'powerlimit', | |
# 'disable', | |
} | |
POWER_STATES = { | |
's0': 0, | |
's3': 1, | |
's4': 2, | |
's5': 3, | |
} | |
TYPES = { | |
'power': 0, | |
'hdd': 1, | |
'skull': 2, | |
'eyes': 3, | |
'front1': 4, | |
'front2': 5, | |
'front3': 6, | |
} | |
def main(): | |
parser = ArgumentParser() | |
parser.add_argument('-d', '--dry-run', action='store_true') | |
parser.add_argument('--indicator', choices=INDICATORS, required=True) | |
parser.add_argument('--power-state', choices=POWER_STATES, default='s0') | |
parser.add_argument('--type', choices=TYPES, required=True) | |
power = parser.add_mutually_exclusive_group() | |
power.add_argument('--brightness', choices=range(100), | |
type=int, metavar='[0-100]') | |
power.add_argument('--behavior', choices=[ | |
*HDD_BEHAVIORS.keys(), *BLINKING_BEHAVIORS.keys(), | |
]) | |
power.add_argument('--frequency', choices=range(10), | |
type=int, metavar='[1-10]') | |
power.add_argument( | |
'--color', metavar='#rrggbb or color name', type=hex2rgb) | |
power.add_argument('--scheme', choices=INDICATION_SCHEMES) | |
args = parser.parse_args() | |
type_ = TYPES[args.type] | |
with sys.stdout if args.dry_run else open(PROCFILE, 'w', 1) as proc: | |
def set_indicator_value(indicator: int, control: int, value: int): | |
cmd = f'set_indicator_value,{type_},{indicator},{control},{value}\n' | |
proc.write(cmd) | |
if args.indicator == 'power': | |
offset = POWER_STATES[args.power_state] * 6 | |
if args.brightness is not None: | |
set_indicator_value(0, offset, args.brightness) | |
elif args.behavior: | |
set_indicator_value( | |
0, offset + 1, BLINKING_BEHAVIORS[args.behavior]) | |
elif args.frequency is not None: | |
set_indicator_value(0, offset + 2, args.frequency) | |
elif args.color is not None: | |
red, green, blue = args.color | |
set_indicator_value(0, offset + 3, red) | |
set_indicator_value(0, offset + 4, green) | |
set_indicator_value(0, offset + 5, blue) | |
else: | |
logging.warning('No valid action for power indicator!') | |
elif args.indicator == 'hdd': | |
if args.brightness is not None: | |
set_indicator_value(1, 0, args.brightness) | |
elif args.color: | |
red, green, blue = args.color | |
set_indicator_value(1, 1, red) | |
set_indicator_value(1, 2, green) | |
set_indicator_value(1, 3, blue) | |
elif args.behavior: | |
set_indicator_value(1, 4, HDD_BEHAVIORS[args.behavior]) | |
else: | |
logging.warning('No valid action for hdd indicator!') | |
elif args.indicator == 'ethernet': | |
if args.brightness is not None: | |
set_indicator_value(2, 0, args.brightness) | |
elif args.color: | |
red, green, blue = args.color | |
set_indicator_value(2, 1, red) | |
set_indicator_value(2, 2, green) | |
set_indicator_value(2, 3, blue) | |
elif args.behavior: | |
set_indicator_value(2, 4, HDD_BEHAVIORS[args.behavior]) | |
else: | |
logging.warning('No valid action for ethernet indicator!') | |
elif args.indicator == 'wifi': | |
if args.brightness is not None: | |
set_indicator_value(3, 0, args.brightness) | |
elif args.color: | |
red, green, blue = args.color | |
set_indicator_value(3, 1, red) | |
set_indicator_value(3, 2, green) | |
set_indicator_value(3, 3, blue) | |
else: | |
logging.warning('No valid action for wifi indicator!') | |
elif args.indicator == 'software': | |
if args.brightness is not None: | |
set_indicator_value(4, 0, args.brightness) | |
elif args.behavior: | |
set_indicator_value(4, 1, BLINKING_BEHAVIORS[args.behavior]) | |
elif args.frequency is not None: | |
set_indicator_value(4, 2, args.frequency) | |
elif args.color: | |
red, green, blue = args.color | |
set_indicator_value(4, 3, red) | |
set_indicator_value(4, 4, green) | |
set_indicator_value(4, 5, blue) | |
else: | |
logging.warning('No valid action for software indicator!') | |
elif args.indicator == 'powerlimit': | |
if args.scheme: | |
set_indicator_value(5, 0, INDICATION_SCHEMES[args.scheme]) | |
elif args.brightness is not None: | |
set_indicator_value(5, 1, args.brightness) | |
elif args.color: | |
red, green, blue = args.color | |
set_indicator_value(5, 2, red) | |
set_indicator_value(5, 3, green) | |
set_indicator_value(5, 4, blue) | |
else: | |
logging.warning('No valid action for powerlimit indicator!') | |
# elif args.indicator == 'disable': | |
# set_indicator_value(6, 0, 1) | |
if __name__ == '__main__': | |
main() |
@docop I don't have the device for 4+ years now, but you should be able to get usage information by running python <script.py> --help
It can control all the leds, including the skull on top
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Hi i would like some info on your script.. As was it made to control the led on top ? And so.. how can it be used.. if you may have an how to run or so..
Thanks, appreciated