Skip to content

Instantly share code, notes, and snippets.

@ranisalt
Last active September 16, 2019 03:39
Show Gist options
  • Save ranisalt/d83db5ecda9c6738e182ad34e259f7ef to your computer and use it in GitHub Desktop.
Save ranisalt/d83db5ecda9c6738e182ad34e259f7ef to your computer and use it in GitHub Desktop.
Cerberus, a Hades Canyon companion
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