Last active
September 16, 2019 03:39
-
-
Save ranisalt/d83db5ecda9c6738e182ad34e259f7ef to your computer and use it in GitHub Desktop.
Cerberus, a Hades Canyon companion
This file contains 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() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment