12 Commits

Author SHA1 Message Date
Florian K
c39f3f2ea5 Merge pull request #6 from flok/examples
Examples
2020-12-22 15:12:05 +01:00
Florian K
ea319db5a3 Merge branch 'master' into examples 2020-12-22 15:09:36 +01:00
Florian Kaiser
d62e8d133e update version and readme 2020-12-22 15:05:21 +01:00
Florian Kaiser
fe435f6e36 Update 0.3.0
* Added low freq motor support
2020-12-22 15:00:46 +01:00
Florian Kaiser
cc767d5fcd add and update examples 2020-12-22 14:58:21 +01:00
Florian Kaiser
1ab69d6c96 Aligned the sticks x and y values so idle position is 0 on both axes 2020-12-22 14:32:39 +01:00
Florian Kaiser
b004d2bc7b Added init function for better usability, added check for HIDGuardian usage 2020-12-22 14:15:42 +01:00
Florian K
3f16538555 added credits to README.md 2020-12-22 14:15:42 +01:00
Florian Kaiser
f1be774e68 0.2.0
- added more light functions
- added docstrings for functions
2020-12-22 14:15:42 +01:00
Florian Kaiser
9560d8e637 delete demo 2020-12-22 14:15:42 +01:00
Florian Kaiser
ecb42d9c0a Added init function for better usability, added check for HIDGuardian usage 2020-12-22 14:11:33 +01:00
Florian K
604c5f2800 added credits to README.md 2020-11-30 21:25:13 +01:00
8 changed files with 139 additions and 52 deletions

View File

@@ -3,7 +3,7 @@ control your dualsense through python. using the hid library this module impleme
# install # install
Just install the package from pypi Just install the package from [pypi](https://pypi.org/project/pydualsense/)
```bash ```bash
pip install pydualsense pip install pydualsense
@@ -25,11 +25,24 @@ ds.close() # closing the controller
See ``examples`` folder for some more ideas See ``examples`` folder for some more ideas
# Help wanted
Help wanted from people that want to use this and have feature requests. Just open a issue with the correct label.
# dependecies # dependecies
- hid >= 1.0.4 - hid >= 1.0.4
# Credits
Most stuff for this implementation were provided by and used from:
- [https://www.reddit.com/r/gamedev/comments/jumvi5/dualsense_haptics_leds_and_more_hid_output_report/](https://www.reddit.com/r/gamedev/comments/jumvi5/dualsense_haptics_leds_and_more_hid_output_report/)
- [https://github.com/Ryochan7/DS4Windows](https://github.com/Ryochan7/DS4Windows)
# Coming soon # Coming soon
- reading the states of the controller to enable a fully compatibility with python - partially done - reading the states of the controller to enable a fully compatibility with python - partially done
- add documentation using sphinx - add documentation using sphinx

15
examples/README.md Normal file
View File

@@ -0,0 +1,15 @@
# Examples
This folder contains some examples on applications for the library and its usage
## leds.py
The leds.py shows you how you can interact and change the lights of the controller
## effects.py
The effects.py show some effects of the controller
## read_controller.py
The read_controller.py display how you can access the button state of the controller

22
examples/effects.py Normal file
View File

@@ -0,0 +1,22 @@
from pydualsense import *
# get dualsense instance
dualsense = pydualsense()
dualsense.init()
print('Trigger Effect demo started')
dualsense.setLeftMotor(255)
dualsense.setRightMotor(100)
dualsense.setLeftTriggerMode(TriggerModes.Rigid)
dualsense.setLeftTriggerForce(1, 255)
dualsense.setRightTriggerMode(TriggerModes.Pulse_A)
dualsense.setRightTriggerForce(0, 200)
dualsense.setRightTriggerForce(1, 255)
dualsense.setRightTriggerForce(2, 175)
import time; time.sleep(3)
# terminate the thread for message and close the device
dualsense.close()

View File

@@ -2,12 +2,13 @@ from pydualsense import *
# get dualsense instance # get dualsense instance
dualsense = pydualsense() dualsense = pydualsense()
dualsense.init()
# set color around touchpad to red # set color around touchpad to red
dualsense.setColor(0,0,255) dualsense.setColor(0,0,255)
# enable microphone indicator # enable microphone indicator
dualsense.setMicrophoneLED(1) dualsense.setMicrophoneLED(1)
# set all player indicators on # set all player indicators on
dualsense.setPlayer(PlayerID.all) dualsense.setPlayerID(PlayerID.all)
# 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) import time; time.sleep(2)

View File

@@ -0,0 +1,15 @@
from pydualsense import *
# create dualsense
dualsense = pydualsense()
# find device and initialize
dualsense.init()
# read controller state until R1 is pressed
while not dualsense.state.R1:
print(f"Circle : {dualsense.state.circle} Cross : {dualsense.state.cross} L Stick X : {dualsense.state.LX} L Stick Y : {dualsense.state.LY}")
# close device
dualsense.close()

View File

@@ -1,12 +0,0 @@
from pydualsense import *
# get dualsense instance
dualsense = pydualsense()
# set left trigger mode to rigid and put some force values on it
dualsense.setLeftTriggerMode(TriggerModes.Rigid)
dualsense.setLeftTriggerForce(1, 255)
# sleep a little to see the result on the controller
# this is not needed in normal usage
import time; time.sleep(2)
# terminate the thread for message and close the device
dualsense.close()

View File

@@ -1,59 +1,95 @@
from os import device_encoding
import hid import hid
from .enums import (LedOptions, PlayerID, from .enums import (LedOptions, PlayerID,
PulseOptions, TriggerModes, Brightness) PulseOptions, TriggerModes, Brightness)
import threading import threading
import sys
import winreg
class pydualsense: class pydualsense:
def __init__(self, verbose: bool = False) -> None: def __init__(self, verbose: bool = False) -> None:
# TODO: maybe add a init function to not automatically allocate controller when class is declared # TODO: maybe add a init function to not automatically allocate controller when class is declared
self.verbose = verbose self.verbose = verbose
self.device: hid.Device = self.__find_device()
self.light = DSLight() # control led light of ds
self.audio = DSAudio()
self.triggerL = DSTrigger()
self.triggerR = DSTrigger()
self.color = (0,0,255) # set color around touchpad to blue
self.receive_buffer_size = 64 self.receive_buffer_size = 64
self.send_report_size = 48 self.send_report_size = 48
# controller states self.color = (0,0,255) # set color around touchpad to blue
self.state = DSState()
self.leftMotor = 0
self.rightMotor = 0
def init(self):
"""initialize module and device
"""
self.device: hid.Device = self.__find_device()
self.light = DSLight() # control led light of ds
self.audio = DSAudio() # ds audio setting
self.triggerL = DSTrigger() # left trigger
self.triggerR = DSTrigger() # right trigger
self.state = DSState() # controller states
# thread for receiving and sending # thread for receiving and sending
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()
self.init = True
def close(self): def close(self):
self.ds_thread = False self.ds_thread = False
self.report_thread.join() self.report_thread.join()
self.device.close() self.device.close()
def __find_device(self): def _check_hide(self):
devices = hid.enumerate(vid=0x054c) """check if hidguardian is used and controller is hidden
found_devices = [] """
for device in devices: if sys.platform.startswith('win32'):
if device['vendor_id'] == 0x054c and device['product_id'] == 0x0CE6: try:
found_devices.append(device) access_reg = winreg.ConnectRegistry(None, winreg.HKEY_LOCAL_MACHINE)
access_key = winreg.OpenKey(access_reg, '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:
return True
return False
except OSError as e:
print(e)
else:
# TODO: find something for other platforms. Maybe not even needed on linux
return False
def __find_device(self):
# 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 len(found_devices) != 1: if self._check_hide():
raise Exception('no dualsense controller detected') raise Exception('HIDGuardian detected. Delete the controller from HIDGuardian and restart PC to connect to controller')
detected_device = None
devices = hid.enumerate(vid=0x054c)
for device in devices:
if device['vendor_id'] == 0x054c and device['product_id'] == 0x0CE6:
detected_device = device
dual_sense = hid.Device(vid=found_devices[0]['vendor_id'], pid=found_devices[0]['product_id']) if detected_device == None:
raise Exception('No device detected')
dual_sense = hid.Device(vid=detected_device['vendor_id'], pid=detected_device['product_id'])
return dual_sense return dual_sense
def setLeftMotor(self, intensity: int):
if intensity > 255:
raise Exception('maximum intensity is 255')
self.leftMotor = intensity
def setRightMotor(self, intensity: int):
if intensity > 255:
raise Exception('maximum intensity is 255')
self.rightMotor = intensity
# right trigger # right trigger
def setRightTriggerMode(self, mode: TriggerModes): def setRightTriggerMode(self, mode: TriggerModes):
"""set the trigger mode for R2 """set the trigger mode for R2
@@ -63,6 +99,7 @@ class pydualsense:
""" """
self.triggerR.mode = mode self.triggerR.mode = mode
def setRightTriggerForce(self, forceID: int, force: int): def setRightTriggerForce(self, forceID: int, force: int):
"""set the right trigger force. trigger consist of 7 parameter """set the right trigger force. trigger consist of 7 parameter
@@ -77,7 +114,6 @@ class pydualsense:
self.triggerR.setForce(id=forceID, force=force) self.triggerR.setForce(id=forceID, force=force)
# left trigger
def setLeftTriggerMode(self, mode: TriggerModes): def setLeftTriggerMode(self, mode: TriggerModes):
"""set the trigger mode for L2 """set the trigger mode for L2
@@ -86,6 +122,7 @@ class pydualsense:
""" """
self.triggerL.mode = mode self.triggerL.mode = mode
def setLeftTriggerForce(self, forceID: int, force: int): def setLeftTriggerForce(self, forceID: int, force: int):
"""set the left trigger force. trigger consist of 7 parameter """set the left trigger force. trigger consist of 7 parameter
@@ -180,10 +217,10 @@ class pydualsense:
""" """
states = list(inReport) # convert bytes to list states = list(inReport) # convert bytes to list
# states 0 is always 1 # states 0 is always 1
self.state.LX = states[1] self.state.LX = states[1] - 127
self.state.LY = states[2] self.state.LY = states[2] - 127
self.state.RX = states[3] self.state.RX = states[3] - 127
self.state.RY = states[4] self.state.RY = states[4] - 127
self.state.L2 = states[5] self.state.L2 = states[5]
self.state.R2 = states[6] self.state.R2 = states[6]
@@ -279,8 +316,8 @@ class pydualsense:
# 0x80 ??? # 0x80 ???
outReport[2] = 0x1 | 0x2 | 0x4 | 0x10 | 0x40 # [2] outReport[2] = 0x1 | 0x2 | 0x4 | 0x10 | 0x40 # [2]
outReport[3] = 0 # left low freq motor 0-255 # [3] outReport[3] = self.leftMotor # left low freq motor 0-255 # [3]
outReport[4] = 0 # right low freq motor 0-255 # [4] outReport[4] = self.rightMotor # right low freq motor 0-255 # [4]
# outReport[5] - outReport[8] audio related # outReport[5] - outReport[8] audio related
@@ -398,10 +435,6 @@ class DSLight:
def setBrightness(self, brightness: Brightness): def setBrightness(self, brightness: Brightness):
self._brightness = brightness self._brightness = brightness
def setPlayerNumer(self, player):
if player > 5:
raise Exception('only 5 players supported. choose 1-5')
class DSAudio: class DSAudio:

View File

@@ -6,7 +6,7 @@ with open("README.md", "r") as fh:
setup( setup(
name='pydualsense', name='pydualsense',
version='0.2.0', version='0.3.0',
description='use your DualSense (PS5) controller with python', description='use your DualSense (PS5) controller with python',
long_description=long_description, long_description=long_description,
long_description_content_type="text/markdown", long_description_content_type="text/markdown",