implementing poetry

This commit is contained in:
Florian Kaiser
2024-03-02 23:42:13 +01:00
parent fc60c0fda0
commit 519e667fe9
14 changed files with 417 additions and 112 deletions

View File

@@ -21,11 +21,11 @@ jobs:
- name: Install dependencies - name: Install dependencies
run: | run: |
python -m pip install --upgrade pip python -m pip install --upgrade pip
pip install setuptools wheel twine pip install setuptools wheel twine poetry
- name: Build and publish - name: Build and publish
env: env:
TWINE_USERNAME: __token__ TWINE_USERNAME: __token__
TWINE_PASSWORD: ${{ secrets.PYPI_PASSWORD }} TWINE_PASSWORD: ${{ secrets.PYPI_PASSWORD }}
run: | run: |
python setup.py sdist bdist_wheel poetry build
twine upload dist/* twine upload dist/*

View File

@@ -1,5 +1,5 @@
import sys import sys
import os from pathlib import Path
# Configuration file for the Sphinx documentation builder. # Configuration file for the Sphinx documentation builder.
# #
# For the full list of built-in configuration values, see the documentation: # For the full list of built-in configuration values, see the documentation:
@@ -11,10 +11,10 @@ import os
project = 'pydualsense' project = 'pydualsense'
copyright = '2022, Florian (flok) K' copyright = '2022, Florian (flok) K'
author = 'Florian (flok) K' author = 'Florian (flok) K'
release = '0.6.1' release = '0.7.1'
sys.path.insert(0, os.path.abspath('..'))
sys.path.insert(0, os.path.abspath('../../')) sys.path.append(str(Path(__file__).parents[2]))
# -- General configuration --------------------------------------------------- # -- General configuration ---------------------------------------------------
# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration # https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration

View File

@@ -1,5 +1,5 @@
pydualsense event system classes pydualsense event system classes
========================= ================================
The `Event System` implements the event system used for the button callbacks The `Event System` implements the event system used for the button callbacks

View File

@@ -1,16 +1,18 @@
from pydualsense import * from pydualsense import pydualsense
from pydualsense.enums import PlayerID
import time
# get dualsense instance # get dualsense instance
dualsense = pydualsense() dualsense = pydualsense()
dualsense.init() dualsense.init()
# set color around touchpad to red # set color around touchpad to red
dualsense.light.setColorI(255,0,0) dualsense.light.setColorI(255, 0, 0)
# mute microphone # mute microphone
dualsense.audio.setMicrophoneState(True) dualsense.audio.setMicrophoneState(True)
# set all player 1 indicator on # set all player 1 indicator on
dualsense.light.setPlayerID(PlayerID.PLAYER_1) dualsense.light.setPlayerID(PlayerID.PLAYER_1)
# sleep a little to see the result on the controller # sleep a little to see the result on the controller
# this is not needed in normal usage # this is not needed in normal usage
import time; time.sleep(2) time.sleep(2)
# terminate the thread for message and close the device # terminate the thread for message and close the device
dualsense.close() dualsense.close()

185
poetry.lock generated Normal file
View File

@@ -0,0 +1,185 @@
# This file is automatically @generated by Poetry 1.8.2 and should not be changed by hand.
[[package]]
name = "cffi"
version = "1.15.1"
description = "Foreign Function Interface for Python calling C code."
optional = false
python-versions = "*"
files = [
{file = "cffi-1.15.1-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:a66d3508133af6e8548451b25058d5812812ec3798c886bf38ed24a98216fab2"},
{file = "cffi-1.15.1-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:470c103ae716238bbe698d67ad020e1db9d9dba34fa5a899b5e21577e6d52ed2"},
{file = "cffi-1.15.1-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:9ad5db27f9cabae298d151c85cf2bad1d359a1b9c686a275df03385758e2f914"},
{file = "cffi-1.15.1-cp27-cp27m-win32.whl", hash = "sha256:b3bbeb01c2b273cca1e1e0c5df57f12dce9a4dd331b4fa1635b8bec26350bde3"},
{file = "cffi-1.15.1-cp27-cp27m-win_amd64.whl", hash = "sha256:e00b098126fd45523dd056d2efba6c5a63b71ffe9f2bbe1a4fe1716e1d0c331e"},
{file = "cffi-1.15.1-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:d61f4695e6c866a23a21acab0509af1cdfd2c013cf256bbf5b6b5e2695827162"},
{file = "cffi-1.15.1-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:ed9cb427ba5504c1dc15ede7d516b84757c3e3d7868ccc85121d9310d27eed0b"},
{file = "cffi-1.15.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:39d39875251ca8f612b6f33e6b1195af86d1b3e60086068be9cc053aa4376e21"},
{file = "cffi-1.15.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:285d29981935eb726a4399badae8f0ffdff4f5050eaa6d0cfc3f64b857b77185"},
{file = "cffi-1.15.1-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3eb6971dcff08619f8d91607cfc726518b6fa2a9eba42856be181c6d0d9515fd"},
{file = "cffi-1.15.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:21157295583fe8943475029ed5abdcf71eb3911894724e360acff1d61c1d54bc"},
{file = "cffi-1.15.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5635bd9cb9731e6d4a1132a498dd34f764034a8ce60cef4f5319c0541159392f"},
{file = "cffi-1.15.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2012c72d854c2d03e45d06ae57f40d78e5770d252f195b93f581acf3ba44496e"},
{file = "cffi-1.15.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dd86c085fae2efd48ac91dd7ccffcfc0571387fe1193d33b6394db7ef31fe2a4"},
{file = "cffi-1.15.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:fa6693661a4c91757f4412306191b6dc88c1703f780c8234035eac011922bc01"},
{file = "cffi-1.15.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:59c0b02d0a6c384d453fece7566d1c7e6b7bae4fc5874ef2ef46d56776d61c9e"},
{file = "cffi-1.15.1-cp310-cp310-win32.whl", hash = "sha256:cba9d6b9a7d64d4bd46167096fc9d2f835e25d7e4c121fb2ddfc6528fb0413b2"},
{file = "cffi-1.15.1-cp310-cp310-win_amd64.whl", hash = "sha256:ce4bcc037df4fc5e3d184794f27bdaab018943698f4ca31630bc7f84a7b69c6d"},
{file = "cffi-1.15.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:3d08afd128ddaa624a48cf2b859afef385b720bb4b43df214f85616922e6a5ac"},
{file = "cffi-1.15.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:3799aecf2e17cf585d977b780ce79ff0dc9b78d799fc694221ce814c2c19db83"},
{file = "cffi-1.15.1-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a591fe9e525846e4d154205572a029f653ada1a78b93697f3b5a8f1f2bc055b9"},
{file = "cffi-1.15.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3548db281cd7d2561c9ad9984681c95f7b0e38881201e157833a2342c30d5e8c"},
{file = "cffi-1.15.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:91fc98adde3d7881af9b59ed0294046f3806221863722ba7d8d120c575314325"},
{file = "cffi-1.15.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:94411f22c3985acaec6f83c6df553f2dbe17b698cc7f8ae751ff2237d96b9e3c"},
{file = "cffi-1.15.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:03425bdae262c76aad70202debd780501fabeaca237cdfddc008987c0e0f59ef"},
{file = "cffi-1.15.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:cc4d65aeeaa04136a12677d3dd0b1c0c94dc43abac5860ab33cceb42b801c1e8"},
{file = "cffi-1.15.1-cp311-cp311-win32.whl", hash = "sha256:a0f100c8912c114ff53e1202d0078b425bee3649ae34d7b070e9697f93c5d52d"},
{file = "cffi-1.15.1-cp311-cp311-win_amd64.whl", hash = "sha256:04ed324bda3cda42b9b695d51bb7d54b680b9719cfab04227cdd1e04e5de3104"},
{file = "cffi-1.15.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:50a74364d85fd319352182ef59c5c790484a336f6db772c1a9231f1c3ed0cbd7"},
{file = "cffi-1.15.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e263d77ee3dd201c3a142934a086a4450861778baaeeb45db4591ef65550b0a6"},
{file = "cffi-1.15.1-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:cec7d9412a9102bdc577382c3929b337320c4c4c4849f2c5cdd14d7368c5562d"},
{file = "cffi-1.15.1-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4289fc34b2f5316fbb762d75362931e351941fa95fa18789191b33fc4cf9504a"},
{file = "cffi-1.15.1-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:173379135477dc8cac4bc58f45db08ab45d228b3363adb7af79436135d028405"},
{file = "cffi-1.15.1-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:6975a3fac6bc83c4a65c9f9fcab9e47019a11d3d2cf7f3c0d03431bf145a941e"},
{file = "cffi-1.15.1-cp36-cp36m-win32.whl", hash = "sha256:2470043b93ff09bf8fb1d46d1cb756ce6132c54826661a32d4e4d132e1977adf"},
{file = "cffi-1.15.1-cp36-cp36m-win_amd64.whl", hash = "sha256:30d78fbc8ebf9c92c9b7823ee18eb92f2e6ef79b45ac84db507f52fbe3ec4497"},
{file = "cffi-1.15.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:198caafb44239b60e252492445da556afafc7d1e3ab7a1fb3f0584ef6d742375"},
{file = "cffi-1.15.1-cp37-cp37m-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5ef34d190326c3b1f822a5b7a45f6c4535e2f47ed06fec77d3d799c450b2651e"},
{file = "cffi-1.15.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8102eaf27e1e448db915d08afa8b41d6c7ca7a04b7d73af6514df10a3e74bd82"},
{file = "cffi-1.15.1-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5df2768244d19ab7f60546d0c7c63ce1581f7af8b5de3eb3004b9b6fc8a9f84b"},
{file = "cffi-1.15.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a8c4917bd7ad33e8eb21e9a5bbba979b49d9a97acb3a803092cbc1133e20343c"},
{file = "cffi-1.15.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0e2642fe3142e4cc4af0799748233ad6da94c62a8bec3a6648bf8ee68b1c7426"},
{file = "cffi-1.15.1-cp37-cp37m-win32.whl", hash = "sha256:e229a521186c75c8ad9490854fd8bbdd9a0c9aa3a524326b55be83b54d4e0ad9"},
{file = "cffi-1.15.1-cp37-cp37m-win_amd64.whl", hash = "sha256:a0b71b1b8fbf2b96e41c4d990244165e2c9be83d54962a9a1d118fd8657d2045"},
{file = "cffi-1.15.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:320dab6e7cb2eacdf0e658569d2575c4dad258c0fcc794f46215e1e39f90f2c3"},
{file = "cffi-1.15.1-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1e74c6b51a9ed6589199c787bf5f9875612ca4a8a0785fb2d4a84429badaf22a"},
{file = "cffi-1.15.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a5c84c68147988265e60416b57fc83425a78058853509c1b0629c180094904a5"},
{file = "cffi-1.15.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3b926aa83d1edb5aa5b427b4053dc420ec295a08e40911296b9eb1b6170f6cca"},
{file = "cffi-1.15.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:87c450779d0914f2861b8526e035c5e6da0a3199d8f1add1a665e1cbc6fc6d02"},
{file = "cffi-1.15.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4f2c9f67e9821cad2e5f480bc8d83b8742896f1242dba247911072d4fa94c192"},
{file = "cffi-1.15.1-cp38-cp38-win32.whl", hash = "sha256:8b7ee99e510d7b66cdb6c593f21c043c248537a32e0bedf02e01e9553a172314"},
{file = "cffi-1.15.1-cp38-cp38-win_amd64.whl", hash = "sha256:00a9ed42e88df81ffae7a8ab6d9356b371399b91dbdf0c3cb1e84c03a13aceb5"},
{file = "cffi-1.15.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:54a2db7b78338edd780e7ef7f9f6c442500fb0d41a5a4ea24fff1c929d5af585"},
{file = "cffi-1.15.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:fcd131dd944808b5bdb38e6f5b53013c5aa4f334c5cad0c72742f6eba4b73db0"},
{file = "cffi-1.15.1-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7473e861101c9e72452f9bf8acb984947aa1661a7704553a9f6e4baa5ba64415"},
{file = "cffi-1.15.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6c9a799e985904922a4d207a94eae35c78ebae90e128f0c4e521ce339396be9d"},
{file = "cffi-1.15.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3bcde07039e586f91b45c88f8583ea7cf7a0770df3a1649627bf598332cb6984"},
{file = "cffi-1.15.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:33ab79603146aace82c2427da5ca6e58f2b3f2fb5da893ceac0c42218a40be35"},
{file = "cffi-1.15.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5d598b938678ebf3c67377cdd45e09d431369c3b1a5b331058c338e201f12b27"},
{file = "cffi-1.15.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:db0fbb9c62743ce59a9ff687eb5f4afbe77e5e8403d6697f7446e5f609976f76"},
{file = "cffi-1.15.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:98d85c6a2bef81588d9227dde12db8a7f47f639f4a17c9ae08e773aa9c697bf3"},
{file = "cffi-1.15.1-cp39-cp39-win32.whl", hash = "sha256:40f4774f5a9d4f5e344f31a32b5096977b5d48560c5592e2f3d2c4374bd543ee"},
{file = "cffi-1.15.1-cp39-cp39-win_amd64.whl", hash = "sha256:70df4e3b545a17496c9b3f41f5115e69a4f2e77e94e1d2a8e1070bc0c38c8a3c"},
{file = "cffi-1.15.1.tar.gz", hash = "sha256:d400bfb9a37b1351253cb402671cea7e89bdecc294e8016a707f6d1d8ac934f9"},
]
[package.dependencies]
pycparser = "*"
[[package]]
name = "colorama"
version = "0.4.6"
description = "Cross-platform colored terminal text."
optional = false
python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7"
files = [
{file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"},
{file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"},
]
[[package]]
name = "hidapi-usb"
version = "0.3.1"
description = "CFFI wrapper for hidapi with changes by flok"
optional = false
python-versions = "*"
files = [
{file = "hidapi-usb-0.3.1.tar.gz", hash = "sha256:447ebf44942ab6c4ec2ac355567934b73f688a833266ab0094ea4e10f968cc13"},
{file = "hidapi_usb-0.3.1-py3-none-any.whl", hash = "sha256:b5556ea285e5df02d5f53c2e03b432c87fcc692830279c3f0064040116211679"},
]
[package.dependencies]
cffi = "*"
[[package]]
name = "mslex"
version = "1.1.0"
description = "shlex for windows"
optional = false
python-versions = ">=3.5"
files = [
{file = "mslex-1.1.0-py2.py3-none-any.whl", hash = "sha256:8826f4bb8d8c63402203d921dc8c2df0c7fec0d9c91d020ddf02fc9d0dce81bd"},
{file = "mslex-1.1.0.tar.gz", hash = "sha256:7fe305fbdc9721283875e0b737fdb344374b761338a7f41af91875de278568e4"},
]
[[package]]
name = "psutil"
version = "5.9.8"
description = "Cross-platform lib for process and system monitoring in Python."
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*"
files = [
{file = "psutil-5.9.8-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:26bd09967ae00920df88e0352a91cff1a78f8d69b3ecabbfe733610c0af486c8"},
{file = "psutil-5.9.8-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:05806de88103b25903dff19bb6692bd2e714ccf9e668d050d144012055cbca73"},
{file = "psutil-5.9.8-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:611052c4bc70432ec770d5d54f64206aa7203a101ec273a0cd82418c86503bb7"},
{file = "psutil-5.9.8-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:50187900d73c1381ba1454cf40308c2bf6f34268518b3f36a9b663ca87e65e36"},
{file = "psutil-5.9.8-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:02615ed8c5ea222323408ceba16c60e99c3f91639b07da6373fb7e6539abc56d"},
{file = "psutil-5.9.8-cp27-none-win32.whl", hash = "sha256:36f435891adb138ed3c9e58c6af3e2e6ca9ac2f365efe1f9cfef2794e6c93b4e"},
{file = "psutil-5.9.8-cp27-none-win_amd64.whl", hash = "sha256:bd1184ceb3f87651a67b2708d4c3338e9b10c5df903f2e3776b62303b26cb631"},
{file = "psutil-5.9.8-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:aee678c8720623dc456fa20659af736241f575d79429a0e5e9cf88ae0605cc81"},
{file = "psutil-5.9.8-cp36-abi3-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8cb6403ce6d8e047495a701dc7c5bd788add903f8986d523e3e20b98b733e421"},
{file = "psutil-5.9.8-cp36-abi3-manylinux_2_12_x86_64.manylinux2010_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d06016f7f8625a1825ba3732081d77c94589dca78b7a3fc072194851e88461a4"},
{file = "psutil-5.9.8-cp36-cp36m-win32.whl", hash = "sha256:7d79560ad97af658a0f6adfef8b834b53f64746d45b403f225b85c5c2c140eee"},
{file = "psutil-5.9.8-cp36-cp36m-win_amd64.whl", hash = "sha256:27cc40c3493bb10de1be4b3f07cae4c010ce715290a5be22b98493509c6299e2"},
{file = "psutil-5.9.8-cp37-abi3-win32.whl", hash = "sha256:bc56c2a1b0d15aa3eaa5a60c9f3f8e3e565303b465dbf57a1b730e7a2b9844e0"},
{file = "psutil-5.9.8-cp37-abi3-win_amd64.whl", hash = "sha256:8db4c1b57507eef143a15a6884ca10f7c73876cdf5d51e713151c1236a0e68cf"},
{file = "psutil-5.9.8-cp38-abi3-macosx_11_0_arm64.whl", hash = "sha256:d16bbddf0693323b8c6123dd804100241da461e41d6e332fb0ba6058f630f8c8"},
{file = "psutil-5.9.8.tar.gz", hash = "sha256:6be126e3225486dff286a8fb9a06246a5253f4c7c53b475ea5f5ac934e64194c"},
]
[package.extras]
test = ["enum34", "ipaddress", "mock", "pywin32", "wmi"]
[[package]]
name = "pycparser"
version = "2.21"
description = "C parser in Python"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
files = [
{file = "pycparser-2.21-py2.py3-none-any.whl", hash = "sha256:8ee45429555515e1f6b185e78100aea234072576aa43ab53aefcae078162fca9"},
{file = "pycparser-2.21.tar.gz", hash = "sha256:e644fdec12f7872f86c58ff790da456218b10f863970249516d60a5eaca77206"},
]
[[package]]
name = "taskipy"
version = "1.12.2"
description = "tasks runner for python projects"
optional = false
python-versions = ">=3.6,<4.0"
files = [
{file = "taskipy-1.12.2-py3-none-any.whl", hash = "sha256:ffdbb0bb0db54c0ec5c424610a3a087eea22706d4d1f6e3e8b4f12ebba05f98f"},
{file = "taskipy-1.12.2.tar.gz", hash = "sha256:eadfdc20d6bb94d8018eda32f1dbf584cf4aa6cffb71ba5cc2de20d344f8c4fb"},
]
[package.dependencies]
colorama = ">=0.4.4,<0.5.0"
mslex = {version = ">=1.1.0,<2.0.0", markers = "sys_platform == \"win32\""}
psutil = ">=5.7.2,<6.0.0"
tomli = {version = ">=2.0.1,<3.0.0", markers = "python_version >= \"3.7\" and python_version < \"4.0\""}
[[package]]
name = "tomli"
version = "2.0.1"
description = "A lil' TOML parser"
optional = false
python-versions = ">=3.7"
files = [
{file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"},
{file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"},
]
[metadata]
lock-version = "2.0"
python-versions = "^3.7"
content-hash = "df693da77db69c7bc101566cbef11e351c47e416f881226e88e8d58114b55c41"

View File

@@ -1,3 +1,11 @@
from .enums import LedOptions, Brightness, PlayerID, PulseOptions, TriggerModes import os
from .event_system import Event import sys
from .pydualsense import pydualsense, DSLight, DSState, DSTouchpad, DSTrigger, DSAudio sys.path.append(os.path.dirname(__file__))
from .enums import LedOptions, Brightness, PlayerID, PulseOptions, TriggerModes # noqa : F401
from .event_system import Event # noqa : F401
from .pydualsense import pydualsense, DSLight, DSState, DSTouchpad, DSTrigger, DSAudio # noqa : F401
print(sys.path)
__version__ = "0.7.1"

View File

@@ -1,7 +1,7 @@
import array import array
# from South-River # from South-River
# fmt: off
hashTable = array.array('I', [ hashTable = array.array('I', [
0xd202ef8d, 0xa505df1b, 0x3c0c8ea1, 0x4b0bbe37, 0xd56f2b94, 0xa2681b02, 0x3b614ab8, 0x4c667a2e, 0xd202ef8d, 0xa505df1b, 0x3c0c8ea1, 0x4b0bbe37, 0xd56f2b94, 0xa2681b02, 0x3b614ab8, 0x4c667a2e,
0xdcd967bf, 0xabde5729, 0x32d70693, 0x45d03605, 0xdbb4a3a6, 0xacb39330, 0x35bac28a, 0x42bdf21c, 0xdcd967bf, 0xabde5729, 0x32d70693, 0x45d03605, 0xdbb4a3a6, 0xacb39330, 0x35bac28a, 0x42bdf21c,
@@ -36,12 +36,13 @@ hashTable = array.array('I', [
0x6fbf1d91, 0x18b82d07, 0x81b17cbd, 0xf6b64c2b, 0x68d2d988, 0x1fd5e91e, 0x86dcb8a4, 0xf1db8832, 0x6fbf1d91, 0x18b82d07, 0x81b17cbd, 0xf6b64c2b, 0x68d2d988, 0x1fd5e91e, 0x86dcb8a4, 0xf1db8832,
0x616495a3, 0x1663a535, 0x8f6af48f, 0xf86dc419, 0x660951ba, 0x110e612c, 0x88073096, 0xff000000 0x616495a3, 0x1663a535, 0x8f6af48f, 0xf86dc419, 0x660951ba, 0x110e612c, 0x88073096, 0xff000000
]) ])
# fmt:on
def compute(buffer): def compute(buffer):
result = 0xeada2d49 result = 0xEADA2D49
for i in range(0, 74): for i in range(0, 74):
result = hashTable[(result&0xFF)^(buffer[i]&0xFF)]^(result>>8) result = hashTable[(result & 0xFF) ^ (buffer[i] & 0xFF)] ^ (result >> 8)
return result return result

View File

@@ -50,7 +50,7 @@ class BatteryState(IntFlag):
POWER_SUPPLY_STATUS_DISCHARGING = 0x0 POWER_SUPPLY_STATUS_DISCHARGING = 0x0
POWER_SUPPLY_STATUS_CHARGING = 0x1 POWER_SUPPLY_STATUS_CHARGING = 0x1
POWER_SUPPLY_STATUS_FULL = 0x2 POWER_SUPPLY_STATUS_FULL = 0x2
POWER_SUPPLY_STATUS_NOT_CHARGING = 0xb POWER_SUPPLY_STATUS_NOT_CHARGING = 0xB
POWER_SUPPLY_STATUS_ERROR = 0xf POWER_SUPPLY_STATUS_ERROR = 0xF
POWER_SUPPLY_TEMP_OR_VOLTAGE_OUT_OF_RANGE = 0xa POWER_SUPPLY_TEMP_OR_VOLTAGE_OUT_OF_RANGE = 0xA
POWER_SUPPLY_STATUS_UNKNOWN = 0x0 POWER_SUPPLY_STATUS_UNKNOWN = 0x0

View File

@@ -1,6 +1,3 @@
from collections import defaultdict
class Event(object): class Event(object):
""" """
Base class for the event driven system Base class for the event driven system

BIN
pydualsense/hidapi.dll Normal file

Binary file not shown.

View File

@@ -6,15 +6,20 @@ def check_hide() -> bool:
""" """
check if hidguardian is used and controller is hidden check if hidguardian is used and controller is hidden
""" """
if sys.platform.startswith('win32'): if sys.platform.startswith("win32"):
try: try:
access_reg = winreg.ConnectRegistry(None, winreg.HKEY_LOCAL_MACHINE) access_reg = winreg.ConnectRegistry(None, winreg.HKEY_LOCAL_MACHINE)
access_key = winreg.OpenKey(access_reg, r'SYSTEM\CurrentControlSet\Services\HidGuardian\Parameters', 0, winreg.KEY_READ) access_key = winreg.OpenKey(
affected_devices = winreg.QueryValueEx(access_key, 'AffectedDevices')[0] access_reg,
r"SYSTEM\CurrentControlSet\Services\HidGuardian\Parameters",
0,
winreg.KEY_READ,
)
affected_devices = winreg.QueryValueEx(access_key, "AffectedDevices")[0]
if "054C" in affected_devices and "0CE6" in affected_devices: if "054C" in affected_devices and "0CE6" in affected_devices:
return True return True
return False return False
except OSError as e: except OSError:
pass pass
return False return False

View File

@@ -3,11 +3,20 @@ import os
import sys import sys
from sys import platform from sys import platform
if platform.startswith('Windows') and sys.version_info >= (3, 8): if platform.startswith("win32") and sys.version_info >= (3, 8):
os.add_dll_directory(os.getcwd()) os.environ["PATH"] += os.pathsep + os.path.dirname(__file__)
import hidapi import hidapi
from .enums import (LedOptions, PlayerID, PulseOptions, TriggerModes, Brightness, ConnectionType, BatteryState) # type: ignore from .enums import (
LedOptions,
PlayerID,
PulseOptions,
TriggerModes,
Brightness,
ConnectionType,
BatteryState,
) # type: ignore
import threading import threading
from .event_system import Event from .event_system import Event
from .checksum import compute from .checksum import compute
@@ -15,13 +24,12 @@ from copy import deepcopy
logger = logging.getLogger() logger = logging.getLogger()
FORMAT = '%(asctime)s %(message)s' FORMAT = "%(asctime)s %(message)s"
logging.basicConfig(format=FORMAT) logging.basicConfig(format=FORMAT)
logger.setLevel(logging.INFO) logger.setLevel(logging.INFO)
class pydualsense: class pydualsense:
OUTPUT_REPORT_USB = 0x02 OUTPUT_REPORT_USB = 0x02
OUTPUT_REPORT_BT = 0x31 OUTPUT_REPORT_BT = 0x31
@@ -32,7 +40,7 @@ class pydualsense:
Args: Args:
verbose (bool, optional): display verbose out (debug prints of input and output). Defaults to False. verbose (bool, optional): display verbose out (debug prints of input and output). Defaults to False.
""" """
# TODO: maybe add a init function to not automatically allocate controller when class is declared
self.verbose = verbose self.verbose = verbose
if self.verbose: if self.verbose:
@@ -86,7 +94,7 @@ class pydualsense:
# trackpad touch # trackpad touch
# handles 1 or 2 fingers # handles 1 or 2 fingers
#self.trackpad_frame_reported = Event() # self.trackpad_frame_reported = Event()
# gyrometer events # gyrometer events
self.gyro_changed = Event() self.gyro_changed = Event()
@@ -98,13 +106,13 @@ class pydualsense:
initialize module and device states. Starts the sendReport background thread at the end initialize module and device states. Starts the sendReport background thread at the end
""" """
self.device: hidapi.Device = self.__find_device() self.device: hidapi.Device = self.__find_device()
self.light = DSLight() # control led light of ds self.light = DSLight() # control led light of ds
self.audio = DSAudio() # ds audio setting self.audio = DSAudio() # ds audio setting
self.triggerL = DSTrigger() # left trigger self.triggerL = DSTrigger() # left trigger
self.triggerR = DSTrigger() # right trigger self.triggerR = DSTrigger() # right trigger
self.state = DSState() # controller states self.state = DSState() # controller states
self.battery = DSBattery() self.battery = DSBattery()
self.conType = self.determineConnectionType() # determine USB or BT connection self.conType = self.determineConnectionType() # determine USB or BT connection
self.ds_thread = True self.ds_thread = True
self.report_thread = threading.Thread(target=self.sendReport) self.report_thread = threading.Thread(target=self.sendReport)
self.report_thread.start() self.report_thread.start()
@@ -159,20 +167,25 @@ class pydualsense:
""" """
# TODO: detect connection mode, bluetooth has a bigger write buffer # TODO: detect connection mode, bluetooth has a bigger write buffer
# TODO: implement multiple controllers working # TODO: implement multiple controllers working
if sys.platform.startswith('win32'): if sys.platform.startswith("win32"):
import pydualsense.hidguardian as hidguardian import pydualsense.hidguardian as hidguardian
if hidguardian.check_hide(): if hidguardian.check_hide():
raise Exception('HIDGuardian detected. Delete the controller from HIDGuardian and restart PC to connect to controller') raise Exception(
"HIDGuardian detected. Delete the controller from HIDGuardian and restart PC to connect to controller"
)
detected_device: hidapi.Device = None detected_device: hidapi.Device = None
devices = hidapi.enumerate(vendor_id=0x054c) devices = hidapi.enumerate(vendor_id=0x054C)
for device in devices: for device in devices:
if device.vendor_id == 0x054c and device.product_id == 0x0CE6: if device.vendor_id == 0x054C and device.product_id == 0x0CE6:
detected_device = device detected_device = device
if detected_device is None: if detected_device is None:
raise Exception('No device detected') raise Exception("No device detected")
dual_sense = hidapi.Device(vendor_id=detected_device.vendor_id, product_id=detected_device.product_id) dual_sense = hidapi.Device(
vendor_id=detected_device.vendor_id, product_id=detected_device.product_id
)
return dual_sense return dual_sense
def setLeftMotor(self, intensity: int) -> None: def setLeftMotor(self, intensity: int) -> None:
@@ -187,10 +200,10 @@ class pydualsense:
Exception: intensity out of bounds 0..255 Exception: intensity out of bounds 0..255
""" """
if not isinstance(intensity, int): if not isinstance(intensity, int):
raise TypeError('left motor intensity needs to be an int') raise TypeError("left motor intensity needs to be an int")
if intensity > 255 or intensity < 0: if intensity > 255 or intensity < 0:
raise Exception('maximum intensity is 255') raise Exception("maximum intensity is 255")
self.leftMotor = intensity self.leftMotor = intensity
def setRightMotor(self, intensity: int) -> None: def setRightMotor(self, intensity: int) -> None:
@@ -205,15 +218,14 @@ class pydualsense:
Exception: intensity out of bounds 0..255 Exception: intensity out of bounds 0..255
""" """
if not isinstance(intensity, int): if not isinstance(intensity, int):
raise TypeError('right motor intensity needs to be an int') raise TypeError("right motor intensity needs to be an int")
if intensity > 255 or intensity < 0: if intensity > 255 or intensity < 0:
raise Exception('maximum intensity is 255') raise Exception("maximum intensity is 255")
self.rightMotor = intensity self.rightMotor = intensity
def sendReport(self) -> None: def sendReport(self) -> None:
"""background thread handling the reading of the device and updating its states """background thread handling the reading of the device and updating its states"""
"""
while self.ds_thread: while self.ds_thread:
# read data from the input report of the controller # read data from the input report of the controller
inReport = self.device.read(self.input_report_length) inReport = self.device.read(self.input_report_length)
@@ -239,9 +251,9 @@ class pydualsense:
# the reports for BT and USB are structured the same, # the reports for BT and USB are structured the same,
# but there is one more byte at the start of the bluetooth report. # but there is one more byte at the start of the bluetooth report.
# We drop that byte, so that the format matches up again. # We drop that byte, so that the format matches up again.
states = list(inReport)[1:] # convert bytes to list states = list(inReport)[1:] # convert bytes to list
else: # USB else: # USB
states = list(inReport) # convert bytes to list states = list(inReport) # convert bytes to list
self.states = states self.states = states
# states 0 is always 1 # states 0 is always 1
@@ -282,24 +294,40 @@ class pydualsense:
# trackpad touch # trackpad touch
self.state.trackPadTouch0.ID = inReport[33] & 0x7F self.state.trackPadTouch0.ID = inReport[33] & 0x7F
self.state.trackPadTouch0.isActive = (inReport[33] & 0x80) == 0 self.state.trackPadTouch0.isActive = (inReport[33] & 0x80) == 0
self.state.trackPadTouch0.X = ((inReport[35] & 0x0f) << 8) | (inReport[34]) self.state.trackPadTouch0.X = ((inReport[35] & 0x0F) << 8) | (inReport[34])
self.state.trackPadTouch0.Y = ((inReport[36]) << 4) | ((inReport[35] & 0xf0) >> 4) self.state.trackPadTouch0.Y = ((inReport[36]) << 4) | (
(inReport[35] & 0xF0) >> 4
)
# trackpad touch # trackpad touch
self.state.trackPadTouch1.ID = inReport[37] & 0x7F self.state.trackPadTouch1.ID = inReport[37] & 0x7F
self.state.trackPadTouch1.isActive = (inReport[37] & 0x80) == 0 self.state.trackPadTouch1.isActive = (inReport[37] & 0x80) == 0
self.state.trackPadTouch1.X = ((inReport[39] & 0x0f) << 8) | (inReport[38]) self.state.trackPadTouch1.X = ((inReport[39] & 0x0F) << 8) | (inReport[38])
self.state.trackPadTouch1.Y = ((inReport[40]) << 4) | ((inReport[39] & 0xf0) >> 4) self.state.trackPadTouch1.Y = ((inReport[40]) << 4) | (
(inReport[39] & 0xF0) >> 4
)
# accelerometer # accelerometer
self.state.accelerometer.X = int.from_bytes(([inReport[16], inReport[17]]), byteorder='little', signed=True) self.state.accelerometer.X = int.from_bytes(
self.state.accelerometer.Y = int.from_bytes(([inReport[18], inReport[19]]), byteorder='little', signed=True) ([inReport[16], inReport[17]]), byteorder="little", signed=True
self.state.accelerometer.Z = int.from_bytes(([inReport[20], inReport[21]]), byteorder='little', signed=True) )
self.state.accelerometer.Y = int.from_bytes(
([inReport[18], inReport[19]]), byteorder="little", signed=True
)
self.state.accelerometer.Z = int.from_bytes(
([inReport[20], inReport[21]]), byteorder="little", signed=True
)
# gyrometer # gyrometer
self.state.gyro.Pitch = int.from_bytes(([inReport[22], inReport[23]]), byteorder='little', signed=True) self.state.gyro.Pitch = int.from_bytes(
self.state.gyro.Yaw = int.from_bytes(([inReport[24], inReport[25]]), byteorder='little', signed=True) ([inReport[22], inReport[23]]), byteorder="little", signed=True
self.state.gyro.Roll = int.from_bytes(([inReport[26], inReport[27]]), byteorder='little', signed=True) )
self.state.gyro.Yaw = int.from_bytes(
([inReport[24], inReport[25]]), byteorder="little", signed=True
)
self.state.gyro.Roll = int.from_bytes(
([inReport[26], inReport[27]]), byteorder="little", signed=True
)
# from kit-nya # from kit-nya
battery = states[53] battery = states[53]
@@ -375,21 +403,33 @@ class pydualsense:
if self.state.options != self.last_states.options: if self.state.options != self.last_states.options:
self.option_pressed(self.state.options) self.option_pressed(self.state.options)
if self.state.accelerometer.X != self.last_states.accelerometer.X or \ if (
self.state.accelerometer.Y != self.last_states.accelerometer.Y or \ self.state.accelerometer.X != self.last_states.accelerometer.X
self.state.accelerometer.Z != self.last_states.accelerometer.Z: or self.state.accelerometer.Y != self.last_states.accelerometer.Y
self.accelerometer_changed(self.state.accelerometer.X, self.state.accelerometer.Y, self.state.accelerometer.Z) or self.state.accelerometer.Z != self.last_states.accelerometer.Z
):
self.accelerometer_changed(
self.state.accelerometer.X,
self.state.accelerometer.Y,
self.state.accelerometer.Z,
)
if self.state.gyro.Pitch != self.last_states.gyro.Pitch or \ if (
self.state.gyro.Yaw != self.last_states.gyro.Yaw or \ self.state.gyro.Pitch != self.last_states.gyro.Pitch
self.state.gyro.Roll != self.last_states.gyro.Roll: or self.state.gyro.Yaw != self.last_states.gyro.Yaw
self.gyro_changed(self.state.gyro.Pitch, self.state.gyro.Yaw, self.state.gyro.Roll) or self.state.gyro.Roll != self.last_states.gyro.Roll
):
self.gyro_changed(
self.state.gyro.Pitch, self.state.gyro.Yaw, self.state.gyro.Roll
)
""" """
copy current state into temp object to check next cycle if a change occuret copy current state into temp object to check next cycle if a change occuret
and event trigger is needed and event trigger is needed
""" """
self.last_states = deepcopy(self.state) # copy current state into object to check next time self.last_states = deepcopy(
self.state
) # copy current state into object to check next time
# TODO: control mouse with touchpad for fun as DS4Windows # TODO: control mouse with touchpad for fun as DS4Windows
@@ -411,7 +451,9 @@ class pydualsense:
""" """
if self.conType == ConnectionType.USB: if self.conType == ConnectionType.USB:
outReport = [0] * self.output_report_length # create empty list with range of output report outReport = (
[0] * self.output_report_length
) # create empty list with range of output report
# packet type # packet type
outReport[0] = self.OUTPUT_REPORT_USB outReport[0] = self.OUTPUT_REPORT_USB
@@ -423,7 +465,7 @@ class pydualsense:
# 0x10 modification of audio volume # 0x10 modification of audio volume
# 0x20 toggling of internal speaker while headset is connected # 0x20 toggling of internal speaker while headset is connected
# 0x40 modification of microphone volume # 0x40 modification of microphone volume
outReport[1] = 0xff # [1] outReport[1] = 0xFF # [1]
# further flags determining what changes this packet will perform # further flags determining what changes this packet will perform
# 0x01 toggling microphone LED # 0x01 toggling microphone LED
@@ -434,15 +476,15 @@ class pydualsense:
# 0x20 ??? # 0x20 ???
# 0x40 adjustment of overall motor/effect power (index 37 - read note on triggers) # 0x40 adjustment of overall motor/effect power (index 37 - read note on triggers)
# 0x80 ??? # 0x80 ???
outReport[2] = 0x1 | 0x2 | 0x4 | 0x10 | 0x40 # [2] outReport[2] = 0x1 | 0x2 | 0x4 | 0x10 | 0x40 # [2]
outReport[3] = self.rightMotor # right low freq motor 0-255 # [3] outReport[3] = self.rightMotor # right low freq motor 0-255 # [3]
outReport[4] = self.leftMotor # left low freq motor 0-255 # [4] outReport[4] = self.leftMotor # left low freq motor 0-255 # [4]
# outReport[5] - outReport[8] audio related # outReport[5] - outReport[8] audio related
# set Micrphone LED, setting doesnt effect microphone settings # set Micrphone LED, setting doesnt effect microphone settings
outReport[9] = self.audio.microphone_led # [9] outReport[9] = self.audio.microphone_led # [9]
outReport[10] = 0x10 if self.audio.microphone_mute is True else 0x00 outReport[10] = 0x10 if self.audio.microphone_mute is True else 0x00
@@ -474,10 +516,11 @@ class pydualsense:
outReport[47] = self.light.TouchpadColor[2] outReport[47] = self.light.TouchpadColor[2]
elif self.conType == ConnectionType.BT: elif self.conType == ConnectionType.BT:
outReport = (
outReport = [0] * self.output_report_length # create empty list with range of output report [0] * self.output_report_length
) # create empty list with range of output report
# packet type # packet type
outReport[0] = self.OUTPUT_REPORT_BT # bt type outReport[0] = self.OUTPUT_REPORT_BT # bt type
outReport[1] = 0x02 outReport[1] = 0x02
@@ -489,7 +532,7 @@ class pydualsense:
# 0x10 modification of audio volume # 0x10 modification of audio volume
# 0x20 toggling of internal speaker while headset is connected # 0x20 toggling of internal speaker while headset is connected
# 0x40 modification of microphone volume # 0x40 modification of microphone volume
outReport[2] = 0xff # [1] outReport[2] = 0xFF # [1]
# further flags determining what changes this packet will perform # further flags determining what changes this packet will perform
# 0x01 toggling microphone LED # 0x01 toggling microphone LED
@@ -500,15 +543,15 @@ class pydualsense:
# 0x20 ??? # 0x20 ???
# 0x40 adjustment of overall motor/effect power (index 37 - read note on triggers) # 0x40 adjustment of overall motor/effect power (index 37 - read note on triggers)
# 0x80 ??? # 0x80 ???
outReport[3] = 0x1 | 0x2 | 0x4 | 0x10 | 0x40 # [2] outReport[3] = 0x1 | 0x2 | 0x4 | 0x10 | 0x40 # [2]
outReport[4] = self.rightMotor # right low freq motor 0-255 # [3] outReport[4] = self.rightMotor # right low freq motor 0-255 # [3]
outReport[5] = self.leftMotor # left low freq motor 0-255 # [4] outReport[5] = self.leftMotor # left low freq motor 0-255 # [4]
# outReport[5] - outReport[8] audio related # outReport[5] - outReport[8] audio related
# set Micrphone LED, setting doesnt effect microphone settings # set Micrphone LED, setting doesnt effect microphone settings
outReport[10] = self.audio.microphone_led # [9] outReport[10] = self.audio.microphone_led # [9]
outReport[11] = 0x10 if self.audio.microphone_mute is True else 0x00 outReport[11] = 0x10 if self.audio.microphone_mute is True else 0x00
@@ -541,7 +584,7 @@ class pydualsense:
crcChecksum = compute(outReport) crcChecksum = compute(outReport)
outReport[74] = (crcChecksum & 0x000000FF) outReport[74] = crcChecksum & 0x000000FF
outReport[75] = (crcChecksum & 0x0000FF00) >> 8 outReport[75] = (crcChecksum & 0x0000FF00) >> 8
outReport[76] = (crcChecksum & 0x00FF0000) >> 16 outReport[76] = (crcChecksum & 0x00FF0000) >> 16
outReport[77] = (crcChecksum & 0xFF000000) >> 24 outReport[77] = (crcChecksum & 0xFF000000) >> 24
@@ -556,6 +599,7 @@ class DSTouchpad:
""" """
Dualsense Touchpad class. Contains X and Y position of touch and if the touch isActive Dualsense Touchpad class. Contains X and Y position of touch and if the touch isActive
""" """
def __init__(self) -> None: def __init__(self) -> None:
""" """
Class represents the Touchpad of the controller Class represents the Touchpad of the controller
@@ -567,15 +611,37 @@ class DSTouchpad:
class DSState: class DSState:
def __init__(self) -> None: def __init__(self) -> None:
""" """
All dualsense states (inputs) that can be read. Second method to check if a input is pressed. All dualsense states (inputs) that can be read. Second method to check if a input is pressed.
""" """
self.square, self.triangle, self.circle, self.cross = False, False, False, False self.square, self.triangle, self.circle, self.cross = False, False, False, False
self.DpadUp, self.DpadDown, self.DpadLeft, self.DpadRight = False, False, False, False self.DpadUp, self.DpadDown, self.DpadLeft, self.DpadRight = (
self.L1, self.L2, self.L3, self.R1, self.R2, self.R3, self.R2Btn, self.L2Btn = False, False, False, False, False, False, False, False False,
self.share, self.options, self.ps, self.touch1, self.touch2, self.touchBtn, self.touchRight, self.touchLeft = False, False, False, False, False, False, False, False False,
False,
False,
)
self.L1, self.L2, self.L3, self.R1, self.R2, self.R3, self.R2Btn, self.L2Btn = (
False,
False,
False,
False,
False,
False,
False,
False,
)
(
self.share,
self.options,
self.ps,
self.touch1,
self.touch2,
self.touchBtn,
self.touchRight,
self.touchLeft,
) = False, False, False, False, False, False, False, False
self.touchFinger1, self.touchFinger2 = False, False self.touchFinger1, self.touchFinger2 = False, False
self.micBtn = False self.micBtn = False
self.RX, self.RY, self.LX, self.LY = 128, 128, 128, 128 self.RX, self.RY, self.LX, self.LY = 128, 128, 128, 128
@@ -641,8 +707,9 @@ class DSLight:
""" """
Represents all features of lights on the controller Represents all features of lights on the controller
""" """
def __init__(self) -> None: def __init__(self) -> None:
self.brightness: Brightness = Brightness.low # sets self.brightness: Brightness = Brightness.low # sets
self.playerNumber: PlayerID = PlayerID.PLAYER_1 self.playerNumber: PlayerID = PlayerID.PLAYER_1
self.ledOption: LedOptions = LedOptions.Both self.ledOption: LedOptions = LedOptions.Both
self.pulseOptions: PulseOptions = PulseOptions.Off self.pulseOptions: PulseOptions = PulseOptions.Off
@@ -659,7 +726,7 @@ class DSLight:
TypeError: LedOption is false type TypeError: LedOption is false type
""" """
if not isinstance(option, LedOptions): if not isinstance(option, LedOptions):
raise TypeError('Need LEDOption type') raise TypeError("Need LEDOption type")
self.ledOption = option self.ledOption = option
def setPulseOption(self, option: PulseOptions): def setPulseOption(self, option: PulseOptions):
@@ -673,7 +740,7 @@ class DSLight:
TypeError: Pulse option is false type TypeError: Pulse option is false type
""" """
if not isinstance(option, PulseOptions): if not isinstance(option, PulseOptions):
raise TypeError('Need PulseOption type') raise TypeError("Need PulseOption type")
self.pulseOptions = option self.pulseOptions = option
def setBrightness(self, brightness: Brightness): def setBrightness(self, brightness: Brightness):
@@ -687,7 +754,7 @@ class DSLight:
TypeError: brightness false type TypeError: brightness false type
""" """
if not isinstance(brightness, Brightness): if not isinstance(brightness, Brightness):
raise TypeError('Need Brightness type') raise TypeError("Need Brightness type")
self.brightness = brightness self.brightness = brightness
def setPlayerID(self, player: PlayerID): def setPlayerID(self, player: PlayerID):
@@ -702,7 +769,7 @@ class DSLight:
TypeError: [description] TypeError: [description]
""" """
if not isinstance(player, PlayerID): if not isinstance(player, PlayerID):
raise TypeError('Need PlayerID type') raise TypeError("Need PlayerID type")
self.playerNumber = player self.playerNumber = player
def setColorI(self, r: int, g: int, b: int) -> None: def setColorI(self, r: int, g: int, b: int) -> None:
@@ -719,10 +786,10 @@ class DSLight:
Exception: color channels are out of bounds Exception: color channels are out of bounds
""" """
if not isinstance(r, int) or not isinstance(g, int) or not isinstance(b, int): if not isinstance(r, int) or not isinstance(g, int) or not isinstance(b, int):
raise TypeError('Color parameter need to be int') raise TypeError("Color parameter need to be int")
# check if color is out of bounds # check if color is out of bounds
if (r > 255 or g > 255 or b > 255) or (r < 0 or g < 0 or b < 0): if (r > 255 or g > 255 or b > 255) or (r < 0 or g < 0 or b < 0):
raise Exception('colors have values from 0 to 255 only') raise Exception("colors have values from 0 to 255 only")
self.TouchpadColor = (r, g, b) self.TouchpadColor = (r, g, b)
def setColorT(self, color: tuple) -> None: def setColorT(self, color: tuple) -> None:
@@ -737,12 +804,12 @@ class DSLight:
Exception: color channels are out of bounds Exception: color channels are out of bounds
""" """
if not isinstance(color, tuple): if not isinstance(color, tuple):
raise TypeError('Color type is tuple') raise TypeError("Color type is tuple")
# unpack for out of bounds check # unpack for out of bounds check
r, g, b = map(int, color) r, g, b = map(int, color)
# check if color is out of bounds # check if color is out of bounds
if (r > 255 or g > 255 or b > 255) or (r < 0 or g < 0 or b < 0): if (r > 255 or g > 255 or b > 255) or (r < 0 or g < 0 or b < 0):
raise Exception('colors have values from 0 to 255 only') raise Exception("colors have values from 0 to 255 only")
self.TouchpadColor = (r, g, b) self.TouchpadColor = (r, g, b)
@@ -766,7 +833,7 @@ class DSAudio:
Exception: false state for the led Exception: false state for the led
""" """
if not isinstance(value, bool): if not isinstance(value, bool):
raise TypeError('MicrophoneLED can only be a bool') raise TypeError("MicrophoneLED can only be a bool")
self.microphone_led = value self.microphone_led = value
def setMicrophoneState(self, state: bool): def setMicrophoneState(self, state: bool):
@@ -781,9 +848,9 @@ class DSAudio:
""" """
if not isinstance(state, bool): if not isinstance(state, bool):
raise TypeError('state needs to be bool') raise TypeError("state needs to be bool")
self.setMicrophoneLED(state) # set led accordingly self.setMicrophoneLED(state) # set led accordingly
self.microphone_mute = state self.microphone_mute = state
@@ -793,6 +860,7 @@ class DSTrigger:
# TODO: make this interface more userfriendly so a developer knows what he is doing # TODO: make this interface more userfriendly so a developer knows what he is doing
""" """
def __init__(self) -> None: def __init__(self) -> None:
# trigger modes # trigger modes
self.mode: TriggerModes = TriggerModes.Off self.mode: TriggerModes = TriggerModes.Off
@@ -813,10 +881,10 @@ class DSTrigger:
Exception: choosen a false force parameter Exception: choosen a false force parameter
""" """
if not isinstance(forceID, int) or not isinstance(force, int): if not isinstance(forceID, int) or not isinstance(force, int):
raise TypeError('forceID and force needs to be type int') raise TypeError("forceID and force needs to be type int")
if forceID > 6 or forceID < 0: if forceID > 6 or forceID < 0:
raise Exception('only 7 parameters available') raise Exception("only 7 parameters available")
self.forces[forceID] = force self.forces[forceID] = force
@@ -831,7 +899,7 @@ class DSTrigger:
TypeError: false Trigger mode type TypeError: false Trigger mode type
""" """
if not isinstance(mode, TriggerModes): if not isinstance(mode, TriggerModes):
raise TypeError('Trigger mode parameter needs to be of type `TriggerModes`') raise TypeError("Trigger mode parameter needs to be of type `TriggerModes`")
self.mode = mode self.mode = mode
@@ -840,6 +908,7 @@ class DSGyro:
""" """
Class representing the Gyro2 of the controller Class representing the Gyro2 of the controller
""" """
def __init__(self) -> None: def __init__(self) -> None:
self.Pitch = 0 self.Pitch = 0
self.Yaw = 0 self.Yaw = 0
@@ -850,6 +919,7 @@ class DSAccelerometer:
""" """
Class representing the Accelerometer of the controller Class representing the Accelerometer of the controller
""" """
def __init__(self) -> None: def __init__(self) -> None:
self.X = 0 self.X = 0
self.Y = 0 self.Y = 0
@@ -860,6 +930,7 @@ class DSBattery:
""" """
Class representing the Battery of the controller Class representing the Battery of the controller
""" """
def __init__(self) -> None: def __init__(self) -> None:
self.State = BatteryState.POWER_SUPPLY_STATUS_UNKNOWN self.State = BatteryState.POWER_SUPPLY_STATUS_UNKNOWN
self.Level = 0 self.Level = 0

36
pyproject.toml Normal file
View File

@@ -0,0 +1,36 @@
[build-system]
requires = ["poetry-core"]
build-backend = "poetry.core.masonry.api"
[tool.poetry]
name = "pydualsense"
version = "0.7.1"
description = "use your DualSense (PS5) controller with python"
license = "MIT"
repository = "https://github.com/flok/pydualsense"
authors = ["Florian (flok) K"]
readme = "README.md"
packages = [{include = "pydualsense"}]
include = ["pydualsense/hidapi.dll"]
[tool.poetry.dependencies]
python = "^3.7"
hidapi-usb = "^0.3.1"
[tool.poetry.group.dev.dependencies]
taskipy = "^1.12.2"
[tool.taskipy.tasks]
clear = "find pydualsense/ -type f \\( -iname \\*.c -o -iname \\*.cpp -o -iname \\*.pyd -o -iname \\*.so \\) -delete"
build = "poetry build"
html_docs = "make html -C docs"
post_build = "task clear"
post_test = "task clear"
[tool.poetry_bumpversion.file."pydualsense/__init__.py"]
[tool.ruff]
exclude = [".venv"]
line-length = 120

View File

@@ -1,3 +1,3 @@
hid-usb cffi==1.15.1 ; python_version >= "3.7" and python_version < "4.0"
sphinx hidapi-usb==0.3.1 ; python_version >= "3.7" and python_version < "4.0"
furo pycparser==2.21 ; python_version >= "3.7" and python_version < "4.0"