From 30c179dd3848ebf972aac240ec8f9534cfa9ac7b Mon Sep 17 00:00:00 2001 From: Burathar Date: Thu, 11 Jun 2020 20:01:36 +0200 Subject: [PATCH] Add first working version --- .gitignore | 140 +++++++++++++++++++++++++++++++++++++++++ create_keyboard_map.py | 70 +++++++++++++++++++++ main.py | 80 +++++++++++++++++++++++ test_keyboard_map.py | 65 +++++++++++++++++++ 4 files changed, 355 insertions(+) create mode 100644 .gitignore create mode 100755 create_keyboard_map.py create mode 100755 main.py create mode 100755 test_keyboard_map.py diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..24a1300 --- /dev/null +++ b/.gitignore @@ -0,0 +1,140 @@ +# Source: https://github.com/github/gitignore/blob/master/Python.gitignore + +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ +cover/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +.pybuilder/ +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# IPython +profile_default/ +ipython_config.py + +# pyenv +# For a library or package, you might want to ignore these files since the code is +# intended to run in multiple environments; otherwise, check them in: +# .python-version + +# pipenv +# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. +# However, in case of collaboration, if having platform-specific dependencies or dependencies +# having no cross-platform support, pipenv may install dependencies that don't work, or not +# install all needed dependencies. +#Pipfile.lock + +# PEP 582; used by e.g. github.com/David-OConnor/pyflow +__pypackages__/ + +# Celery stuff +celerybeat-schedule +celerybeat.pid + +# SageMath parsed files +*.sage.py + +# Environments +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + +# Pyre type checker +.pyre/ + +# pytype static type analyzer +.pytype/ + +# Cython debug symbols +cython_debug/ diff --git a/create_keyboard_map.py b/create_keyboard_map.py new file mode 100755 index 0000000..636c0bc --- /dev/null +++ b/create_keyboard_map.py @@ -0,0 +1,70 @@ +#! /bin/python3 + +import openrazer.client +import json +from pathlib import Path +from pynput import keyboard + +def get_keyboard(): + devman = openrazer.client.DeviceManager() + + for device in devman.devices: + if (device.name == "Razer BlackWidow Chroma V2"): + return device + + return None + +def clear_all(kbd): + # Set full keyboard to green + for row in range(0,kbd_rows): + for column in range(0, kbd_columns): + kbd.fx.advanced.matrix[row,column] = [0, 0, 0] + + +kbd = get_keyboard() +if (kbd == None): + print("No Razer device with devicename 'Razer Blackwidow Chroma V2' found.") + exit() + +kbd_rows, kbd_columns = kbd.fx.advanced.rows, kbd.fx.advanced.cols + + +last_key_pressed = None +def on_press(key): + global last_key_pressed + last_key_pressed = key + return False + +def get_key(): + with keyboard.Listener(on_press=on_press) as listener: + listener.join() + +def set_key_columns(keymap, column_range, prefix=""): + for row in range(0,kbd_rows): + for column in column_range: + clear_all(kbd) + kbd.fx.advanced.matrix[row,column] = [255, 255, 255] + kbd.fx.advanced.draw() + get_key() + print('{} was pressed'.format(last_key_pressed)) + keymap[prefix + str(last_key_pressed)] = row * kbd_columns + column + +def iter_keys(): + keymap = dict() + print("Make sure caps lock and numpad are disabled, if not, do it now and restart the script") + print("This script will iterate over all keys, row by row. When a key lights up white, press it, and use the mouse to cancel any F-key effects. First, we'll skip the numpad. If no key lights up, press the bottom-right most key, excluding the numpad().") + set_key_columns(keymap, range(0,18)) + print("Now we'll iterate over the numpad, if no key lights up, press the bottom right key(enter)") + set_key_columns(keymap, range(18,kbd_columns), "num_") + return keymap + +def write_keymap_file(dictionary): + keymap_json = json.dumps(keymap) + path = Path.home() / '.config/openrazer_scripter/keymap.json' + Path(path.parent).mkdir(parents=True, exist_ok=True) + with open(path,'w') as keymap_file: + keymap_file.write(keymap_json) + +keymap = iter_keys() +write_keymap_file(keymap) +print('Saved keymap to file (.config/openrazer_scripter/keymap.json)') diff --git a/main.py b/main.py new file mode 100755 index 0000000..400654f --- /dev/null +++ b/main.py @@ -0,0 +1,80 @@ +import openrazer.client +import json +from pathlib import Path +import math + +def get_keyboard(): + devman = openrazer.client.DeviceManager() + for device in devman.devices: + if (device.name == 'Razer BlackWidow Chroma V2'): + return device + return None + +def read_keymap_file(path = ''): + if path == '': + path = Path.home() / '.config/openrazer_scripter/keymap.json' + keymap = None + with open(path,'r') as keymap_file: + keymap = json.load(keymap_file) + return keymap + +kbd = get_keyboard() +if (kbd == None): + print("No Razer device with devicename 'Razer Blackwidow Chroma V2' found.") + exit() +keymap = read_keymap_file() + +def set_static(kbd, color): + color = get_rgb(color) + if color is None: + print(f"Color set_static() was incorrect, skipping.") + return + for row in range(0,6): + for column in range(0, 22): + kbd.fx.advanced.matrix[row,column] = [color[0], color[1], color[2]] + +def check_color_value(value): + if not isinstance(value, int): + print(f"Colorvalue '{value}' is not a number") + return False + if value < 0 or value > 255: + print(f"Color value '{value}' is out of bounds (0-255)") + return False + return True + +def get_rgb(color): + r, g, b = None, None, None + if isinstance(color, str): + if len(color) == 6: + color = tuple(int(color[i:i+2], 16) for i in (0, 2, 4)) + if len(color) == 3: + r = color[0] + g = color[1] + b = color[2] + else: + print(f"Could not interpert color '{color}'") + return None + if check_color_value(r) and check_color_value(g) and check_color_value(b): + return r, g, b + else: + print(f"Color '{color}' is out of range") + return None + +def get_row_column(index): + row = math.floor(index / 22) + column = index % 22 + return row, column + +def set_keys(kbd, color, *keys): + color = get_rgb(color) + if color is None: + print(f"Color for key(s) '{keys}' was incorrect, skipping.") + return + for key in keys: + if key in keymap: + position = get_row_column(keymap[key]) + kbd.fx.advanced.matrix[position[0], position[1]] = [color[0], color[1], color[2]] + +set_static(kbd, (255,255,255)) +set_keys(kbd, 'ff0000', 'enter') +kbd.fx.advanced.draw() diff --git a/test_keyboard_map.py b/test_keyboard_map.py new file mode 100755 index 0000000..8da9b75 --- /dev/null +++ b/test_keyboard_map.py @@ -0,0 +1,65 @@ +#! /bin/python3 + +import openrazer.client +import json +from pathlib import Path +import math + +def get_keyboard(): + devman = openrazer.client.DeviceManager() + + for device in devman.devices: + if (device.name == "Razer BlackWidow Chroma V2"): + return device + + return None + +def clear_all(kbd): + # Set full keyboard to green + for row in range(0, 6): + for column in range(0, 22): + kbd.fx.advanced.matrix[row,column] = [0, 0, 0] + + +kbd = get_keyboard() +if (kbd == None): + print("No Razer device with devicename 'Razer Blackwidow Chroma V2' found.") + exit() + +def read_keymap_file(): + path = Path.home() / '.config/openrazer_scripter/keymap.json' + keymap = None + with open(path,'r') as keymap_file: + keymap = json.load(keymap_file) + return keymap + +def get_row_column(index): + row = math.floor(index / 22) + column = index % 22 + return row, column + +def set_all_white(kbd, keymap): + clear_all(kbd) + for key, value in keymap.items(): + position = get_row_column(value) + kbd.fx.advanced.matrix[position[0], position[1]] = [255,255,255] + kbd.fx.advanced.draw() + +def sort_dict(dictionary): + return {k: v for k, v in sorted(dictionary.items(), key=lambda item: item[1])} + +def iter_keys(kbd, keymap): + keymap = sort_dict(keymap) + for key, value in keymap.items(): + clear_all(kbd) + position = get_row_column(value) + print(f'key: {key}') + kbd.fx.advanced.matrix[position[0], position[1]] = [255,255,255] + kbd.fx.advanced.draw() + input() + +keymap = read_keymap_file() +while True: + set_all_white(kbd, keymap) + input("Press Enter to continue...") + iter_keys(kbd, keymap)