playdirector 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- playdirector-0.1.0/.gitignore +89 -0
- playdirector-0.1.0/PKG-INFO +210 -0
- playdirector-0.1.0/README.md +187 -0
- playdirector-0.1.0/playdirector/__init__.py +58 -0
- playdirector-0.1.0/playdirector/_version.py +24 -0
- playdirector-0.1.0/playdirector/auth_keys.py +14363 -0
- playdirector-0.1.0/playdirector/connection.py +702 -0
- playdirector-0.1.0/playdirector/credentials.py +205 -0
- playdirector-0.1.0/playdirector/crypto.py +141 -0
- playdirector-0.1.0/playdirector/discovery.py +311 -0
- playdirector-0.1.0/playdirector/packets.py +381 -0
- playdirector-0.1.0/playdirector/pairing.py +2998 -0
- playdirector-0.1.0/playdirector/playstation.py +361 -0
- playdirector-0.1.0/playdirector/remoteplay_session.py +723 -0
- playdirector-0.1.0/pyproject.toml +91 -0
- playdirector-0.1.0/tests/test_unit.py +1129 -0
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
# =============================================================================
|
|
2
|
+
# Python
|
|
3
|
+
# =============================================================================
|
|
4
|
+
__pycache__/
|
|
5
|
+
*.py[cod]
|
|
6
|
+
*$py.class
|
|
7
|
+
*.pyo
|
|
8
|
+
*.pyd
|
|
9
|
+
|
|
10
|
+
# Distribution / packaging
|
|
11
|
+
dist/
|
|
12
|
+
build/
|
|
13
|
+
*.egg-info/
|
|
14
|
+
*.egg
|
|
15
|
+
MANIFEST
|
|
16
|
+
|
|
17
|
+
# Virtual environments
|
|
18
|
+
.venv/
|
|
19
|
+
venv/
|
|
20
|
+
env/
|
|
21
|
+
.env/
|
|
22
|
+
|
|
23
|
+
# uv
|
|
24
|
+
.uv/
|
|
25
|
+
# uv.lock is intentionally NOT ignored — commit it for reproducible installs
|
|
26
|
+
|
|
27
|
+
# hatch-vcs generated version file
|
|
28
|
+
playdirector/_version.py
|
|
29
|
+
|
|
30
|
+
# Installer caches
|
|
31
|
+
pip-wheel-metadata/
|
|
32
|
+
|
|
33
|
+
# =============================================================================
|
|
34
|
+
# Testing & coverage
|
|
35
|
+
# =============================================================================
|
|
36
|
+
.pytest_cache/
|
|
37
|
+
.coverage
|
|
38
|
+
.coverage.*
|
|
39
|
+
coverage.xml
|
|
40
|
+
htmlcov/
|
|
41
|
+
|
|
42
|
+
# =============================================================================
|
|
43
|
+
# Type checking
|
|
44
|
+
# =============================================================================
|
|
45
|
+
.mypy_cache/
|
|
46
|
+
.dmypy.json
|
|
47
|
+
dmypy.json
|
|
48
|
+
.pyright/
|
|
49
|
+
|
|
50
|
+
# =============================================================================
|
|
51
|
+
# Linting
|
|
52
|
+
# =============================================================================
|
|
53
|
+
.ruff_cache/
|
|
54
|
+
|
|
55
|
+
# =============================================================================
|
|
56
|
+
# macOS
|
|
57
|
+
# =============================================================================
|
|
58
|
+
.DS_Store
|
|
59
|
+
.AppleDouble
|
|
60
|
+
.LSOverride
|
|
61
|
+
Icon?
|
|
62
|
+
._*
|
|
63
|
+
.Spotlight-V100
|
|
64
|
+
.Trashes
|
|
65
|
+
|
|
66
|
+
# =============================================================================
|
|
67
|
+
# Editors / IDEs
|
|
68
|
+
# =============================================================================
|
|
69
|
+
.vscode/
|
|
70
|
+
*.code-workspace
|
|
71
|
+
.idea/
|
|
72
|
+
*.iml
|
|
73
|
+
*.swp
|
|
74
|
+
*.swo
|
|
75
|
+
*~
|
|
76
|
+
|
|
77
|
+
# =============================================================================
|
|
78
|
+
# Credentials (never commit these)
|
|
79
|
+
# =============================================================================
|
|
80
|
+
*_credentials.json
|
|
81
|
+
*.key
|
|
82
|
+
*.pem
|
|
83
|
+
secrets.*
|
|
84
|
+
|
|
85
|
+
# =============================================================================
|
|
86
|
+
# Misc
|
|
87
|
+
# =============================================================================
|
|
88
|
+
*.pcap
|
|
89
|
+
*.log
|
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: playdirector
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Async Python library for PS4/PS5 second-screen control (wake, standby, button input)
|
|
5
|
+
Project-URL: Homepage, https://github.com/jackjpowell/playdirector
|
|
6
|
+
Project-URL: Repository, https://github.com/jackjpowell/playdirector
|
|
7
|
+
Project-URL: Issues, https://github.com/jackjpowell/playdirector/issues
|
|
8
|
+
Project-URL: Changelog, https://github.com/jackjpowell/playdirector/releases
|
|
9
|
+
License: MIT
|
|
10
|
+
Keywords: asyncio,playstation,ps4,ps5,remote-control
|
|
11
|
+
Classifier: Development Status :: 3 - Alpha
|
|
12
|
+
Classifier: Framework :: AsyncIO
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
18
|
+
Classifier: Topic :: Home Automation
|
|
19
|
+
Requires-Python: >=3.11
|
|
20
|
+
Requires-Dist: aiohttp>=3.9
|
|
21
|
+
Requires-Dist: cryptography>=41.0
|
|
22
|
+
Description-Content-Type: text/markdown
|
|
23
|
+
|
|
24
|
+
# playdirector
|
|
25
|
+
|
|
26
|
+
An async Python library for controlling PS4 and PS5 consoles over your local network — wake from standby, send button inputs, navigate home, and more.
|
|
27
|
+
|
|
28
|
+
[](https://pypi.org/project/playdirector/)
|
|
29
|
+
[](https://pypi.org/project/playdirector/)
|
|
30
|
+
[](LICENSE)
|
|
31
|
+
|
|
32
|
+
## Features
|
|
33
|
+
|
|
34
|
+
- **Discover** PS4/PS5 consoles on your local network via UDP broadcast
|
|
35
|
+
- **Wake** a console from standby without a full session
|
|
36
|
+
- **Connect** and send button inputs (PS4), navigate to home (PS5)
|
|
37
|
+
- **Pair** with a PS5 using your PSN credentials (NPSSO token)
|
|
38
|
+
- **Credential storage** — JSON files persisted to `~/.config/playdirector/`
|
|
39
|
+
- Fully `async`/`await` — built on `asyncio` and `aiohttp`
|
|
40
|
+
|
|
41
|
+
## Requirements
|
|
42
|
+
|
|
43
|
+
- Python 3.11+
|
|
44
|
+
- PS4 (firmware ≥ 8.0) or PS5
|
|
45
|
+
- Console and computer on the same local network
|
|
46
|
+
|
|
47
|
+
## Installation
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
pip install playdirector
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## Quick Start
|
|
54
|
+
|
|
55
|
+
```python
|
|
56
|
+
import asyncio
|
|
57
|
+
from playdirector import discover, connect, RemoteOperation
|
|
58
|
+
from playdirector.credentials import JsonCredentialStorage
|
|
59
|
+
|
|
60
|
+
async def main():
|
|
61
|
+
storage = JsonCredentialStorage()
|
|
62
|
+
|
|
63
|
+
# Find the console (pass ip= to target a specific address)
|
|
64
|
+
device = await discover(ip="192.168.1.50")
|
|
65
|
+
if device is None:
|
|
66
|
+
print("Console not found")
|
|
67
|
+
return
|
|
68
|
+
|
|
69
|
+
# Load previously paired credentials
|
|
70
|
+
cred = storage.load(device.device_id)
|
|
71
|
+
if cred is None:
|
|
72
|
+
print("No credentials — run pairing first")
|
|
73
|
+
return
|
|
74
|
+
|
|
75
|
+
# Connect and send the PS button
|
|
76
|
+
async with connect(device, cred) as session:
|
|
77
|
+
await session.send_keys([RemoteOperation.PS])
|
|
78
|
+
|
|
79
|
+
asyncio.run(main())
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
## Pairing
|
|
83
|
+
|
|
84
|
+
Before connecting you need to pair with the console once to obtain credentials.
|
|
85
|
+
|
|
86
|
+
### PS5
|
|
87
|
+
|
|
88
|
+
You'll need your [NPSSO token](https://ca.account.sony.com/api/v1/ssocookie) from the PSN website and the 8-digit PIN shown on the console under **Settings → System → Remote Play → Link Device**.
|
|
89
|
+
|
|
90
|
+
```python
|
|
91
|
+
import asyncio
|
|
92
|
+
from playdirector import pair
|
|
93
|
+
from playdirector.credentials import JsonCredentialStorage
|
|
94
|
+
|
|
95
|
+
async def main():
|
|
96
|
+
cred = await pair(
|
|
97
|
+
ip="192.168.1.50",
|
|
98
|
+
pin="12345678", # 8-digit PIN from console
|
|
99
|
+
npsso="your-npsso", # from https://ca.account.sony.com/api/v1/ssocookie
|
|
100
|
+
)
|
|
101
|
+
JsonCredentialStorage().save(cred)
|
|
102
|
+
print("Paired:", cred.device_id)
|
|
103
|
+
|
|
104
|
+
asyncio.run(main())
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
### PS4
|
|
108
|
+
|
|
109
|
+
```python
|
|
110
|
+
import asyncio
|
|
111
|
+
from playdirector.pairing import pair_ps4_remoteplay
|
|
112
|
+
from playdirector.credentials import JsonCredentialStorage
|
|
113
|
+
|
|
114
|
+
async def main():
|
|
115
|
+
cred = await pair_ps4_remoteplay(
|
|
116
|
+
ip="192.168.1.100",
|
|
117
|
+
pin="12345678",
|
|
118
|
+
npsso="your-npsso",
|
|
119
|
+
)
|
|
120
|
+
JsonCredentialStorage().save(cred)
|
|
121
|
+
|
|
122
|
+
asyncio.run(main())
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
## API
|
|
126
|
+
|
|
127
|
+
### Discovery
|
|
128
|
+
|
|
129
|
+
```python
|
|
130
|
+
from playdirector import discover
|
|
131
|
+
from playdirector.discovery import DeviceStatus
|
|
132
|
+
|
|
133
|
+
# Discover all devices on the network
|
|
134
|
+
async for device in discover(timeout=5):
|
|
135
|
+
print(device.device_type, device.host, device.status)
|
|
136
|
+
|
|
137
|
+
# Target a specific IP
|
|
138
|
+
device = await discover(ip="192.168.1.50")
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
`DiscoveredDevice` fields:
|
|
142
|
+
|
|
143
|
+
| Field | Type | Description |
|
|
144
|
+
| --- | --- | --- |
|
|
145
|
+
| `host` | `str` | IP address |
|
|
146
|
+
| `device_type` | `DeviceType` | `PS4` or `PS5` |
|
|
147
|
+
| `status` | `DeviceStatus` | `AWAKE` or `STANDBY` |
|
|
148
|
+
| `device_id` | `str` | Unique device identifier |
|
|
149
|
+
| `running_app_name` | `str \| None` | Currently running app (if awake) |
|
|
150
|
+
| `running_app_titleid` | `str \| None` | Title ID of running app |
|
|
151
|
+
|
|
152
|
+
### Control
|
|
153
|
+
|
|
154
|
+
```python
|
|
155
|
+
from playdirector import connect, wake
|
|
156
|
+
from playdirector.packets import RemoteOperation
|
|
157
|
+
|
|
158
|
+
# Wake from standby (no full session needed)
|
|
159
|
+
await wake(device, cred)
|
|
160
|
+
|
|
161
|
+
# Full session — send button inputs (PS4)
|
|
162
|
+
async with connect(device, cred) as session:
|
|
163
|
+
await session.send_keys([RemoteOperation.PS])
|
|
164
|
+
await session.send_keys([RemoteOperation.UP, RemoteOperation.ENTER])
|
|
165
|
+
await session.standby()
|
|
166
|
+
|
|
167
|
+
# Navigate PS5 to home screen
|
|
168
|
+
from playdirector import go_home
|
|
169
|
+
await go_home(device, cred)
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
### Available Buttons (`RemoteOperation`)
|
|
173
|
+
|
|
174
|
+
`UP` · `DOWN` · `LEFT` · `RIGHT` · `ENTER` · `BACK` · `OPTION` · `PS` · `CANCEL`
|
|
175
|
+
|
|
176
|
+
Multiple buttons can be combined: `RemoteOperation.UP | RemoteOperation.LEFT`
|
|
177
|
+
|
|
178
|
+
### Credential Storage
|
|
179
|
+
|
|
180
|
+
```python
|
|
181
|
+
from playdirector.credentials import JsonCredentialStorage
|
|
182
|
+
|
|
183
|
+
storage = JsonCredentialStorage() # defaults to ~/.config/playdirector/
|
|
184
|
+
storage = JsonCredentialStorage("/my/dir") # custom path
|
|
185
|
+
|
|
186
|
+
storage.save(cred) # saves to <dir>/<device_id>.json
|
|
187
|
+
cred = storage.load(device_id) # returns None if not found
|
|
188
|
+
storage.delete(device_id)
|
|
189
|
+
ids = storage.list_device_ids()
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
## Error Handling
|
|
193
|
+
|
|
194
|
+
```python
|
|
195
|
+
from playdirector import PlayActorError, LoginError, UnsupportedDeviceError
|
|
196
|
+
|
|
197
|
+
try:
|
|
198
|
+
async with connect(device, cred) as session:
|
|
199
|
+
...
|
|
200
|
+
except LoginError:
|
|
201
|
+
print("Bad credentials")
|
|
202
|
+
except UnsupportedDeviceError:
|
|
203
|
+
print("Operation not supported on this console")
|
|
204
|
+
except PlayActorError as e:
|
|
205
|
+
print("Protocol error:", e)
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
## License
|
|
209
|
+
|
|
210
|
+
MIT — see [LICENSE](LICENSE).
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
# playdirector
|
|
2
|
+
|
|
3
|
+
An async Python library for controlling PS4 and PS5 consoles over your local network — wake from standby, send button inputs, navigate home, and more.
|
|
4
|
+
|
|
5
|
+
[](https://pypi.org/project/playdirector/)
|
|
6
|
+
[](https://pypi.org/project/playdirector/)
|
|
7
|
+
[](LICENSE)
|
|
8
|
+
|
|
9
|
+
## Features
|
|
10
|
+
|
|
11
|
+
- **Discover** PS4/PS5 consoles on your local network via UDP broadcast
|
|
12
|
+
- **Wake** a console from standby without a full session
|
|
13
|
+
- **Connect** and send button inputs (PS4), navigate to home (PS5)
|
|
14
|
+
- **Pair** with a PS5 using your PSN credentials (NPSSO token)
|
|
15
|
+
- **Credential storage** — JSON files persisted to `~/.config/playdirector/`
|
|
16
|
+
- Fully `async`/`await` — built on `asyncio` and `aiohttp`
|
|
17
|
+
|
|
18
|
+
## Requirements
|
|
19
|
+
|
|
20
|
+
- Python 3.11+
|
|
21
|
+
- PS4 (firmware ≥ 8.0) or PS5
|
|
22
|
+
- Console and computer on the same local network
|
|
23
|
+
|
|
24
|
+
## Installation
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
pip install playdirector
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## Quick Start
|
|
31
|
+
|
|
32
|
+
```python
|
|
33
|
+
import asyncio
|
|
34
|
+
from playdirector import discover, connect, RemoteOperation
|
|
35
|
+
from playdirector.credentials import JsonCredentialStorage
|
|
36
|
+
|
|
37
|
+
async def main():
|
|
38
|
+
storage = JsonCredentialStorage()
|
|
39
|
+
|
|
40
|
+
# Find the console (pass ip= to target a specific address)
|
|
41
|
+
device = await discover(ip="192.168.1.50")
|
|
42
|
+
if device is None:
|
|
43
|
+
print("Console not found")
|
|
44
|
+
return
|
|
45
|
+
|
|
46
|
+
# Load previously paired credentials
|
|
47
|
+
cred = storage.load(device.device_id)
|
|
48
|
+
if cred is None:
|
|
49
|
+
print("No credentials — run pairing first")
|
|
50
|
+
return
|
|
51
|
+
|
|
52
|
+
# Connect and send the PS button
|
|
53
|
+
async with connect(device, cred) as session:
|
|
54
|
+
await session.send_keys([RemoteOperation.PS])
|
|
55
|
+
|
|
56
|
+
asyncio.run(main())
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## Pairing
|
|
60
|
+
|
|
61
|
+
Before connecting you need to pair with the console once to obtain credentials.
|
|
62
|
+
|
|
63
|
+
### PS5
|
|
64
|
+
|
|
65
|
+
You'll need your [NPSSO token](https://ca.account.sony.com/api/v1/ssocookie) from the PSN website and the 8-digit PIN shown on the console under **Settings → System → Remote Play → Link Device**.
|
|
66
|
+
|
|
67
|
+
```python
|
|
68
|
+
import asyncio
|
|
69
|
+
from playdirector import pair
|
|
70
|
+
from playdirector.credentials import JsonCredentialStorage
|
|
71
|
+
|
|
72
|
+
async def main():
|
|
73
|
+
cred = await pair(
|
|
74
|
+
ip="192.168.1.50",
|
|
75
|
+
pin="12345678", # 8-digit PIN from console
|
|
76
|
+
npsso="your-npsso", # from https://ca.account.sony.com/api/v1/ssocookie
|
|
77
|
+
)
|
|
78
|
+
JsonCredentialStorage().save(cred)
|
|
79
|
+
print("Paired:", cred.device_id)
|
|
80
|
+
|
|
81
|
+
asyncio.run(main())
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
### PS4
|
|
85
|
+
|
|
86
|
+
```python
|
|
87
|
+
import asyncio
|
|
88
|
+
from playdirector.pairing import pair_ps4_remoteplay
|
|
89
|
+
from playdirector.credentials import JsonCredentialStorage
|
|
90
|
+
|
|
91
|
+
async def main():
|
|
92
|
+
cred = await pair_ps4_remoteplay(
|
|
93
|
+
ip="192.168.1.100",
|
|
94
|
+
pin="12345678",
|
|
95
|
+
npsso="your-npsso",
|
|
96
|
+
)
|
|
97
|
+
JsonCredentialStorage().save(cred)
|
|
98
|
+
|
|
99
|
+
asyncio.run(main())
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
## API
|
|
103
|
+
|
|
104
|
+
### Discovery
|
|
105
|
+
|
|
106
|
+
```python
|
|
107
|
+
from playdirector import discover
|
|
108
|
+
from playdirector.discovery import DeviceStatus
|
|
109
|
+
|
|
110
|
+
# Discover all devices on the network
|
|
111
|
+
async for device in discover(timeout=5):
|
|
112
|
+
print(device.device_type, device.host, device.status)
|
|
113
|
+
|
|
114
|
+
# Target a specific IP
|
|
115
|
+
device = await discover(ip="192.168.1.50")
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
`DiscoveredDevice` fields:
|
|
119
|
+
|
|
120
|
+
| Field | Type | Description |
|
|
121
|
+
| --- | --- | --- |
|
|
122
|
+
| `host` | `str` | IP address |
|
|
123
|
+
| `device_type` | `DeviceType` | `PS4` or `PS5` |
|
|
124
|
+
| `status` | `DeviceStatus` | `AWAKE` or `STANDBY` |
|
|
125
|
+
| `device_id` | `str` | Unique device identifier |
|
|
126
|
+
| `running_app_name` | `str \| None` | Currently running app (if awake) |
|
|
127
|
+
| `running_app_titleid` | `str \| None` | Title ID of running app |
|
|
128
|
+
|
|
129
|
+
### Control
|
|
130
|
+
|
|
131
|
+
```python
|
|
132
|
+
from playdirector import connect, wake
|
|
133
|
+
from playdirector.packets import RemoteOperation
|
|
134
|
+
|
|
135
|
+
# Wake from standby (no full session needed)
|
|
136
|
+
await wake(device, cred)
|
|
137
|
+
|
|
138
|
+
# Full session — send button inputs (PS4)
|
|
139
|
+
async with connect(device, cred) as session:
|
|
140
|
+
await session.send_keys([RemoteOperation.PS])
|
|
141
|
+
await session.send_keys([RemoteOperation.UP, RemoteOperation.ENTER])
|
|
142
|
+
await session.standby()
|
|
143
|
+
|
|
144
|
+
# Navigate PS5 to home screen
|
|
145
|
+
from playdirector import go_home
|
|
146
|
+
await go_home(device, cred)
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
### Available Buttons (`RemoteOperation`)
|
|
150
|
+
|
|
151
|
+
`UP` · `DOWN` · `LEFT` · `RIGHT` · `ENTER` · `BACK` · `OPTION` · `PS` · `CANCEL`
|
|
152
|
+
|
|
153
|
+
Multiple buttons can be combined: `RemoteOperation.UP | RemoteOperation.LEFT`
|
|
154
|
+
|
|
155
|
+
### Credential Storage
|
|
156
|
+
|
|
157
|
+
```python
|
|
158
|
+
from playdirector.credentials import JsonCredentialStorage
|
|
159
|
+
|
|
160
|
+
storage = JsonCredentialStorage() # defaults to ~/.config/playdirector/
|
|
161
|
+
storage = JsonCredentialStorage("/my/dir") # custom path
|
|
162
|
+
|
|
163
|
+
storage.save(cred) # saves to <dir>/<device_id>.json
|
|
164
|
+
cred = storage.load(device_id) # returns None if not found
|
|
165
|
+
storage.delete(device_id)
|
|
166
|
+
ids = storage.list_device_ids()
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
## Error Handling
|
|
170
|
+
|
|
171
|
+
```python
|
|
172
|
+
from playdirector import PlayActorError, LoginError, UnsupportedDeviceError
|
|
173
|
+
|
|
174
|
+
try:
|
|
175
|
+
async with connect(device, cred) as session:
|
|
176
|
+
...
|
|
177
|
+
except LoginError:
|
|
178
|
+
print("Bad credentials")
|
|
179
|
+
except UnsupportedDeviceError:
|
|
180
|
+
print("Operation not supported on this console")
|
|
181
|
+
except PlayActorError as e:
|
|
182
|
+
print("Protocol error:", e)
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
## License
|
|
186
|
+
|
|
187
|
+
MIT — see [LICENSE](LICENSE).
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
"""
|
|
2
|
+
playdirector — async Python library for PS4/PS5 second-screen control.
|
|
3
|
+
|
|
4
|
+
Quick start::
|
|
5
|
+
|
|
6
|
+
import asyncio
|
|
7
|
+
from playdirector import discover, connect, RemoteOperation
|
|
8
|
+
|
|
9
|
+
async def main():
|
|
10
|
+
device = await discover("192.168.1.50")
|
|
11
|
+
from playdirector.credentials import JsonCredentialStorage
|
|
12
|
+
cred = JsonCredentialStorage().load(device.device_id)
|
|
13
|
+
async with connect(device, cred) as session:
|
|
14
|
+
await session.send_keys([RemoteOperation.PS])
|
|
15
|
+
|
|
16
|
+
asyncio.run(main())
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
from .playstation import (
|
|
20
|
+
DeviceStatus,
|
|
21
|
+
DeviceType,
|
|
22
|
+
DiscoveredDevice,
|
|
23
|
+
InternalRemoteOperation,
|
|
24
|
+
JsonCredentialStorage,
|
|
25
|
+
LoginError,
|
|
26
|
+
PlayActorError,
|
|
27
|
+
RemoteOperation,
|
|
28
|
+
RemotePlayCredentials,
|
|
29
|
+
SecondScreenCredentials,
|
|
30
|
+
Session,
|
|
31
|
+
UnsupportedDeviceError,
|
|
32
|
+
connect,
|
|
33
|
+
discover,
|
|
34
|
+
go_home,
|
|
35
|
+
pair,
|
|
36
|
+
wake,
|
|
37
|
+
)
|
|
38
|
+
|
|
39
|
+
__version__ = "0.1.0"
|
|
40
|
+
__all__ = [
|
|
41
|
+
"connect",
|
|
42
|
+
"discover",
|
|
43
|
+
"go_home",
|
|
44
|
+
"pair",
|
|
45
|
+
"wake",
|
|
46
|
+
"DiscoveredDevice",
|
|
47
|
+
"DeviceType",
|
|
48
|
+
"DeviceStatus",
|
|
49
|
+
"Session",
|
|
50
|
+
"RemoteOperation",
|
|
51
|
+
"InternalRemoteOperation",
|
|
52
|
+
"SecondScreenCredentials",
|
|
53
|
+
"RemotePlayCredentials",
|
|
54
|
+
"JsonCredentialStorage",
|
|
55
|
+
"PlayActorError",
|
|
56
|
+
"LoginError",
|
|
57
|
+
"UnsupportedDeviceError",
|
|
58
|
+
]
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# file generated by vcs-versioning
|
|
2
|
+
# don't change, don't track in version control
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
__all__ = [
|
|
6
|
+
"__version__",
|
|
7
|
+
"__version_tuple__",
|
|
8
|
+
"version",
|
|
9
|
+
"version_tuple",
|
|
10
|
+
"__commit_id__",
|
|
11
|
+
"commit_id",
|
|
12
|
+
]
|
|
13
|
+
|
|
14
|
+
version: str
|
|
15
|
+
__version__: str
|
|
16
|
+
__version_tuple__: tuple[int | str, ...]
|
|
17
|
+
version_tuple: tuple[int | str, ...]
|
|
18
|
+
commit_id: str | None
|
|
19
|
+
__commit_id__: str | None
|
|
20
|
+
|
|
21
|
+
__version__ = version = '0.1.0'
|
|
22
|
+
__version_tuple__ = version_tuple = (0, 1, 0)
|
|
23
|
+
|
|
24
|
+
__commit_id__ = commit_id = None
|