dualsense-ts 3.1.4 → 5.0.0
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.
- package/MIGRATION_GUIDE.md +21 -0
- package/README.md +59 -17
- package/dist/dualsense.d.ts +7 -0
- package/dist/dualsense.d.ts.map +1 -1
- package/dist/dualsense.js +22 -2
- package/dist/dualsense.js.map +1 -1
- package/dist/hid/dualsense_hid.d.ts +3 -0
- package/dist/hid/dualsense_hid.d.ts.map +1 -1
- package/dist/hid/dualsense_hid.js +6 -1
- package/dist/hid/dualsense_hid.js.map +1 -1
- package/dist/hid/node_hid_provider.d.ts +1 -1
- package/dist/hid/node_hid_provider.d.ts.map +1 -1
- package/dist/hid/node_hid_provider.js +47 -15
- package/dist/hid/node_hid_provider.js.map +1 -1
- package/package.json +12 -4
- package/src/dualsense.ts +34 -1
- package/src/hid/dualsense_hid.ts +8 -2
- package/src/hid/node_hid_provider.ts +44 -18
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# Migration Guide
|
|
2
|
+
|
|
3
|
+
### v4 to v5
|
|
4
|
+
|
|
5
|
+
`node-hid` is now an optional peer dependency, simplifying the use of this library in the browser.
|
|
6
|
+
|
|
7
|
+
Node.js users will need to add `node-hid` as a dependency.
|
|
8
|
+
|
|
9
|
+
### v3 to v4
|
|
10
|
+
|
|
11
|
+
The constructor no longer throws when a Dualsense controller is unavailable. It will keep attempting to connect in the background. A new input is provided for monitoring the connection state.
|
|
12
|
+
|
|
13
|
+
### v2 to v3
|
|
14
|
+
|
|
15
|
+
In v2, inputs were EventEmitters. In v3 a new, similar class is used, but the API differs slightly.
|
|
16
|
+
|
|
17
|
+
If you are using unavailable EventEmitter features or relying on `instanceof EventEmitter`, you will need to refactor accordingly.
|
|
18
|
+
|
|
19
|
+
### v1 to v2
|
|
20
|
+
|
|
21
|
+
Version 2 adds an abstraction over the `node-hid` interface; if you were accessing it directly, you'll need to refactor accordingly.
|
package/README.md
CHANGED
|
@@ -6,23 +6,21 @@ This module provides a natural interface for your DualSense controller.
|
|
|
6
6
|
|
|
7
7
|
### Installation
|
|
8
8
|
|
|
9
|
-
This package is distributed via npm
|
|
10
|
-
|
|
11
|
-
Install it using your preferred package manager:
|
|
9
|
+
[This package is distributed via npm](https://npmjs.org/package.dualsense-ts). Install it the usual way:
|
|
12
10
|
|
|
13
11
|
- `yarn add dualsense-ts`
|
|
14
12
|
- `npm add dualsense-ts`
|
|
15
13
|
|
|
16
|
-
|
|
14
|
+
In the browser, `dualsense-ts` has zero dependencies and relies on the native WebHID interface.
|
|
17
15
|
|
|
18
|
-
`dualsense-ts`
|
|
16
|
+
In Node.js, `dualsense-ts` relies on `node-hid`, so you'll need to add that as well:
|
|
19
17
|
|
|
20
|
-
-
|
|
21
|
-
-
|
|
18
|
+
- `yarn add node-hid`
|
|
19
|
+
- `npm add node-hid`
|
|
22
20
|
|
|
23
21
|
### Connecting
|
|
24
22
|
|
|
25
|
-
|
|
23
|
+
When you construct a `new Dualsense()`, the connection to your controller will be managed in the background.
|
|
26
24
|
|
|
27
25
|
```typescript
|
|
28
26
|
import { Dualsense } from "dualsense-ts";
|
|
@@ -31,7 +29,17 @@ import { Dualsense } from "dualsense-ts";
|
|
|
31
29
|
const controller = new Dualsense();
|
|
32
30
|
```
|
|
33
31
|
|
|
34
|
-
|
|
32
|
+
If your device becomes disconnected, `dualsense-ts` will quietly wait for it to come back. You can monitor the connection state using the same APIs as any other input:
|
|
33
|
+
|
|
34
|
+
```typescript
|
|
35
|
+
const connected = controller.connection.active
|
|
36
|
+
|
|
37
|
+
controller.connection.on("change", ({ active }) = > {
|
|
38
|
+
console.log(`controller ${active ? '' : 'dis'}connected`)
|
|
39
|
+
});
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
### Input APIs
|
|
35
43
|
|
|
36
44
|
`dualsense-ts` provides several interfaces for reading input:
|
|
37
45
|
|
|
@@ -39,22 +47,22 @@ const controller = new Dualsense();
|
|
|
39
47
|
|
|
40
48
|
```typescript
|
|
41
49
|
// Buttons
|
|
42
|
-
controller.circle.state;
|
|
50
|
+
controller.circle.state; // false
|
|
43
51
|
controller.left.bumper.state; // true
|
|
44
52
|
|
|
45
53
|
// Triggers
|
|
46
|
-
controller.right.trigger.active;
|
|
54
|
+
controller.right.trigger.active; // true
|
|
47
55
|
controller.right.trigger.pressure; // 0.72, 0 - 1
|
|
48
56
|
|
|
49
57
|
// Analog Sticks - represented as a position on a unit circle
|
|
50
|
-
controller.left.analog.x.active;
|
|
51
|
-
controller.left.analog.x.state;
|
|
58
|
+
controller.left.analog.x.active; // true, when away from center
|
|
59
|
+
controller.left.analog.x.state; // 0.51, -1 to 1
|
|
52
60
|
controller.left.analog.direction; // 4.32, radians
|
|
53
61
|
controller.left.analog.magnitude; // 0.23, 0 to 1
|
|
54
62
|
|
|
55
63
|
// Touchpad - each touch point works like an analog input
|
|
56
64
|
controller.touchpad.right.contact.state; // false
|
|
57
|
-
+controller.touchpad.right.x;
|
|
65
|
+
+controller.touchpad.right.x; // -0.44, -1 to 1
|
|
58
66
|
```
|
|
59
67
|
|
|
60
68
|
- _Callbacks_: Each input is an EventEmitter, or EventTarget that provides `input`, `press`, `release`, and `change` events
|
|
@@ -100,13 +108,47 @@ await controller.promise();
|
|
|
100
108
|
|
|
101
109
|
```typescript
|
|
102
110
|
for await (const { pressure } of controller.left.trigger) {
|
|
103
|
-
console.log(`L2: ${Math.round(pressure*100)}%`);
|
|
111
|
+
console.log(`L2: ${Math.round(pressure * 100)}%`);
|
|
112
|
+
}
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
### React
|
|
116
|
+
|
|
117
|
+
Set up a context for your controller:
|
|
118
|
+
|
|
119
|
+
```typescript
|
|
120
|
+
// Controller.tsx
|
|
121
|
+
import React from "react";
|
|
122
|
+
import { Dualsense } from "dualsense-ts";
|
|
123
|
+
|
|
124
|
+
export const ControllerContext = React.createContext<Dualsense>(
|
|
125
|
+
new Dualsense()
|
|
126
|
+
);
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
Use the context to set up your component:
|
|
130
|
+
|
|
131
|
+
```typescript
|
|
132
|
+
// MyButton.tsx
|
|
133
|
+
import React from "react";
|
|
134
|
+
import { ControllerContext } from "./Controller.tsx";
|
|
135
|
+
|
|
136
|
+
// A button that's only active while the user is holding triangle on the controller
|
|
137
|
+
export const MyButton = () => {
|
|
138
|
+
const { state: controller } = React.useContext(ControllerContext);
|
|
139
|
+
const [triangle, setTriangle] = React.useState(controller.triangle);
|
|
140
|
+
React.useCallback(
|
|
141
|
+
() => triangle.on("change", (new) => setTriangle(new)),
|
|
142
|
+
[triangle]
|
|
143
|
+
);
|
|
144
|
+
|
|
145
|
+
return <button active={triangle.active}>
|
|
104
146
|
}
|
|
105
147
|
```
|
|
106
148
|
|
|
107
|
-
##
|
|
149
|
+
## Migration Guide
|
|
108
150
|
|
|
109
|
-
|
|
151
|
+
`dualsense-ts` uses semantic versioning. For more info on breaking changes, [check out the migration guide](MIGRATION_GUIDE.md).
|
|
110
152
|
|
|
111
153
|
## Credits
|
|
112
154
|
|
package/dist/dualsense.d.ts
CHANGED
|
@@ -36,7 +36,14 @@ export declare class Dualsense extends Input<Dualsense> {
|
|
|
36
36
|
readonly left: Unisense;
|
|
37
37
|
readonly right: Unisense;
|
|
38
38
|
readonly touchpad: Touchpad;
|
|
39
|
+
/**
|
|
40
|
+
* Represents the underlying HID mechanism and device.
|
|
41
|
+
*/
|
|
39
42
|
readonly hid: DualsenseHID;
|
|
43
|
+
/**
|
|
44
|
+
* A virtual button representing whether or not a controller is connected.
|
|
45
|
+
*/
|
|
46
|
+
readonly connection: Momentary;
|
|
40
47
|
get active(): boolean;
|
|
41
48
|
constructor(params?: DualsenseParams);
|
|
42
49
|
/**
|
package/dist/dualsense.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dualsense.d.ts","sourceRoot":"","sources":["../src/dualsense.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,SAAS,EACT,IAAI,EACJ,UAAU,EACV,IAAI,EACJ,QAAQ,EACR,cAAc,EACd,QAAQ,EACT,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,KAAK,EAAY,WAAW,EAAE,MAAM,SAAS,CAAC;AACvD,OAAO,EAEL,YAAY,EAGb,MAAM,OAAO,CAAC;AAEf,MAAM,WAAW,eAAgB,SAAQ,WAAW;IAClD;;OAEG;IACH,GAAG,CAAC,EAAE,YAAY,GAAG,IAAI,CAAC;IAE1B,EAAE,CAAC,EAAE,WAAW,CAAC;IACjB,IAAI,CAAC,EAAE,WAAW,CAAC;IACnB,OAAO,CAAC,EAAE,WAAW,CAAC;IACtB,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,QAAQ,CAAC,EAAE,WAAW,CAAC;IACvB,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB,IAAI,CAAC,EAAE,cAAc,CAAC;IACtB,KAAK,CAAC,EAAE,cAAc,CAAC;IACvB,QAAQ,CAAC,EAAE,WAAW,CAAC;CACxB;AAED;;GAEG;AACH,qBAAa,SAAU,SAAQ,KAAK,CAAC,SAAS,CAAC;IAC7C,SAAgB,KAAK,EAAE,SAAS,CAAQ;IAExC,SAAgB,EAAE,EAAE,SAAS,CAAC;IAC9B,SAAgB,IAAI,EAAE,IAAI,CAAC;IAE3B,SAAgB,OAAO,EAAE,SAAS,CAAC;IACnC,SAAgB,MAAM,EAAE,SAAS,CAAC;IAElC,SAAgB,QAAQ,EAAE,SAAS,CAAC;IACpC,SAAgB,MAAM,EAAE,SAAS,CAAC;IAClC,SAAgB,KAAK,EAAE,SAAS,CAAC;IACjC,SAAgB,MAAM,EAAE,SAAS,CAAC;IAElC,SAAgB,IAAI,EAAE,IAAI,CAAC;IAE3B,SAAgB,IAAI,EAAE,QAAQ,CAAC;IAC/B,SAAgB,KAAK,EAAE,QAAQ,CAAC;IAEhC,SAAgB,QAAQ,EAAE,QAAQ,CAAC;IAEnC,SAAgB,GAAG,EAAE,YAAY,CAAC;IAElC,IAAW,MAAM,IAAI,OAAO,CAI3B;gBAEW,MAAM,GAAE,eAAoB;
|
|
1
|
+
{"version":3,"file":"dualsense.d.ts","sourceRoot":"","sources":["../src/dualsense.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,SAAS,EACT,IAAI,EACJ,UAAU,EACV,IAAI,EACJ,QAAQ,EACR,cAAc,EACd,QAAQ,EACT,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,KAAK,EAAY,WAAW,EAAE,MAAM,SAAS,CAAC;AACvD,OAAO,EAEL,YAAY,EAGb,MAAM,OAAO,CAAC;AAEf,MAAM,WAAW,eAAgB,SAAQ,WAAW;IAClD;;OAEG;IACH,GAAG,CAAC,EAAE,YAAY,GAAG,IAAI,CAAC;IAE1B,EAAE,CAAC,EAAE,WAAW,CAAC;IACjB,IAAI,CAAC,EAAE,WAAW,CAAC;IACnB,OAAO,CAAC,EAAE,WAAW,CAAC;IACtB,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,QAAQ,CAAC,EAAE,WAAW,CAAC;IACvB,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB,IAAI,CAAC,EAAE,cAAc,CAAC;IACtB,KAAK,CAAC,EAAE,cAAc,CAAC;IACvB,QAAQ,CAAC,EAAE,WAAW,CAAC;CACxB;AAED;;GAEG;AACH,qBAAa,SAAU,SAAQ,KAAK,CAAC,SAAS,CAAC;IAC7C,SAAgB,KAAK,EAAE,SAAS,CAAQ;IAExC,SAAgB,EAAE,EAAE,SAAS,CAAC;IAC9B,SAAgB,IAAI,EAAE,IAAI,CAAC;IAE3B,SAAgB,OAAO,EAAE,SAAS,CAAC;IACnC,SAAgB,MAAM,EAAE,SAAS,CAAC;IAElC,SAAgB,QAAQ,EAAE,SAAS,CAAC;IACpC,SAAgB,MAAM,EAAE,SAAS,CAAC;IAClC,SAAgB,KAAK,EAAE,SAAS,CAAC;IACjC,SAAgB,MAAM,EAAE,SAAS,CAAC;IAElC,SAAgB,IAAI,EAAE,IAAI,CAAC;IAE3B,SAAgB,IAAI,EAAE,QAAQ,CAAC;IAC/B,SAAgB,KAAK,EAAE,QAAQ,CAAC;IAEhC,SAAgB,QAAQ,EAAE,QAAQ,CAAC;IAEnC;;OAEG;IACH,SAAgB,GAAG,EAAE,YAAY,CAAC;IAElC;;OAEG;IACH,SAAgB,UAAU,EAAE,SAAS,CAAC;IAEtC,IAAW,MAAM,IAAI,OAAO,CAI3B;gBAEW,MAAM,GAAE,eAAoB;IAiGxC;;OAEG;IACH,OAAO,CAAC,UAAU;CAwCnB"}
|
package/dist/dualsense.js
CHANGED
|
@@ -71,12 +71,32 @@ class Dualsense extends input_1.Input {
|
|
|
71
71
|
name: "Touchpad",
|
|
72
72
|
...(params.touchpad || {}),
|
|
73
73
|
});
|
|
74
|
+
this.connection = new elements_1.Momentary({
|
|
75
|
+
icon: "🔗",
|
|
76
|
+
name: "Connected",
|
|
77
|
+
...(params.square || {}),
|
|
78
|
+
});
|
|
79
|
+
this.connection[input_1.InputSet](false);
|
|
74
80
|
this.hid = params.hid || new hid_1.DualsenseHID(new hid_1.PlatformHIDProvider());
|
|
75
81
|
this.hid.register((state) => {
|
|
76
82
|
this.processHID(state);
|
|
77
83
|
});
|
|
78
|
-
|
|
79
|
-
this
|
|
84
|
+
setInterval(() => {
|
|
85
|
+
const { hid } = this;
|
|
86
|
+
if (this.hid) {
|
|
87
|
+
const { provider: { connected }, } = hid;
|
|
88
|
+
this.connection[input_1.InputSet](connected);
|
|
89
|
+
if (!connected) {
|
|
90
|
+
try {
|
|
91
|
+
this.hid.provider.connect();
|
|
92
|
+
this.connection[input_1.InputSet](true);
|
|
93
|
+
}
|
|
94
|
+
catch {
|
|
95
|
+
this.connection[input_1.InputSet](false);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}, 100);
|
|
80
100
|
}
|
|
81
101
|
get active() {
|
|
82
102
|
return Object.values(this).some((input) => input !== this && input instanceof input_1.Input && input.active);
|
package/dist/dualsense.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dualsense.js","sourceRoot":"","sources":["../src/dualsense.ts"],"names":[],"mappings":";;;AAAA,yCAQoB;AACpB,mCAAuD;AACvD,+BAKe;AAsBf;;GAEG;AACH,MAAa,SAAU,SAAQ,aAAgB;
|
|
1
|
+
{"version":3,"file":"dualsense.js","sourceRoot":"","sources":["../src/dualsense.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import { HIDProvider, DualsenseHIDState } from "./hid_provider";
|
|
2
2
|
export declare type HIDCallback = (state: DualsenseHIDState) => void;
|
|
3
|
+
export declare type ErrorCallback = (error: Error) => void;
|
|
3
4
|
/**
|
|
4
5
|
* Coordinates a HIDProvider and tracks the latest HID state.
|
|
5
6
|
*/
|
|
6
7
|
export declare class DualsenseHID {
|
|
7
8
|
readonly provider: HIDProvider;
|
|
8
9
|
private readonly subscribers;
|
|
10
|
+
private readonly errorSubscribers;
|
|
9
11
|
state: DualsenseHIDState;
|
|
10
12
|
constructor(provider: HIDProvider);
|
|
11
13
|
/**
|
|
@@ -16,6 +18,7 @@ export declare class DualsenseHID {
|
|
|
16
18
|
* Cancel a previously registered handler.
|
|
17
19
|
*/
|
|
18
20
|
unregister(callback: (state: DualsenseHIDState) => void): void;
|
|
21
|
+
on(type: "data" | "error", callback: ErrorCallback): void;
|
|
19
22
|
private set;
|
|
20
23
|
private handleError;
|
|
21
24
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dualsense_hid.d.ts","sourceRoot":"","sources":["../../src/hid/dualsense_hid.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,iBAAiB,EAAW,MAAM,gBAAgB,CAAC;AAEzE,oBAAY,WAAW,GAAG,CAAC,KAAK,EAAE,iBAAiB,KAAK,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"dualsense_hid.d.ts","sourceRoot":"","sources":["../../src/hid/dualsense_hid.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,iBAAiB,EAAW,MAAM,gBAAgB,CAAC;AAEzE,oBAAY,WAAW,GAAG,CAAC,KAAK,EAAE,iBAAiB,KAAK,IAAI,CAAC;AAC7D,oBAAY,aAAa,GAAG,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;AAEnD;;GAEG;AACH,qBAAa,YAAY;IAgDX,QAAQ,CAAC,QAAQ,EAAE,WAAW;IA/C1C,OAAO,CAAC,QAAQ,CAAC,WAAW,CAA0B;IACtD,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAA4B;IAEtD,KAAK,EAAE,iBAAiB,CA0C7B;gBAEmB,QAAQ,EAAE,WAAW;IAK1C;;OAEG;IACI,QAAQ,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,iBAAiB,KAAK,IAAI,GAAG,IAAI;IAInE;;OAEG;IACI,UAAU,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,iBAAiB,KAAK,IAAI,GAAG,IAAI;IAI9D,EAAE,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,EAAE,QAAQ,EAAE,aAAa,GAAG,IAAI;IAIhE,OAAO,CAAC,GAAG;IAKX,OAAO,CAAC,WAAW;CAOpB"}
|
|
@@ -8,6 +8,7 @@ class DualsenseHID {
|
|
|
8
8
|
constructor(provider) {
|
|
9
9
|
this.provider = provider;
|
|
10
10
|
this.subscribers = new Set();
|
|
11
|
+
this.errorSubscribers = new Set();
|
|
11
12
|
this.state = {
|
|
12
13
|
["LX" /* InputId.LeftAnalogX */]: 0,
|
|
13
14
|
["LY" /* InputId.LeftAnalogY */]: 0,
|
|
@@ -66,12 +67,16 @@ class DualsenseHID {
|
|
|
66
67
|
unregister(callback) {
|
|
67
68
|
this.subscribers.delete(callback);
|
|
68
69
|
}
|
|
70
|
+
on(type, callback) {
|
|
71
|
+
if (type === "error")
|
|
72
|
+
this.errorSubscribers.add(callback);
|
|
73
|
+
}
|
|
69
74
|
set(state) {
|
|
70
75
|
this.state = state;
|
|
71
76
|
this.subscribers.forEach((callback) => callback(state));
|
|
72
77
|
}
|
|
73
78
|
handleError(error) {
|
|
74
|
-
|
|
79
|
+
this.errorSubscribers.forEach((callback) => callback(error));
|
|
75
80
|
setTimeout(() => {
|
|
76
81
|
this.provider.disconnect();
|
|
77
82
|
this.provider.connect();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dualsense_hid.js","sourceRoot":"","sources":["../../src/hid/dualsense_hid.ts"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"dualsense_hid.js","sourceRoot":"","sources":["../../src/hid/dualsense_hid.ts"],"names":[],"mappings":"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"}
|
|
@@ -3,7 +3,7 @@ import { HIDProvider, DualsenseHIDState } from "./hid_provider";
|
|
|
3
3
|
export declare class NodeHIDProvider extends HIDProvider {
|
|
4
4
|
private device?;
|
|
5
5
|
wireless: boolean;
|
|
6
|
-
connect(): void
|
|
6
|
+
connect(): Promise<void>;
|
|
7
7
|
get connected(): boolean;
|
|
8
8
|
disconnect(): void;
|
|
9
9
|
process(buffer: Buffer): DualsenseHIDState;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"node_hid_provider.d.ts","sourceRoot":"","sources":["../../src/hid/node_hid_provider.ts"],"names":[],"mappings":";
|
|
1
|
+
{"version":3,"file":"node_hid_provider.d.ts","sourceRoot":"","sources":["../../src/hid/node_hid_provider.ts"],"names":[],"mappings":";AAAA,OAAO,EACL,WAAW,EACX,iBAAiB,EAIlB,MAAM,gBAAgB,CAAC;AAOxB,qBAAa,eAAgB,SAAQ,WAAW;IAC9C,OAAO,CAAC,MAAM,CAAC,CAAU;IAClB,QAAQ,EAAE,OAAO,CAAS;IAE3B,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IA4C9B,IAAI,SAAS,IAAI,OAAO,CAEvB;IAED,UAAU,IAAI,IAAI;IASlB,OAAO,CAAC,MAAM,EAAE,MAAM,GAAG,iBAAiB;CA2D3C"}
|
|
@@ -1,27 +1,59 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
2
25
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
26
|
exports.NodeHIDProvider = void 0;
|
|
4
|
-
const node_hid_1 = require("node-hid");
|
|
5
27
|
const hid_provider_1 = require("./hid_provider");
|
|
6
28
|
class NodeHIDProvider extends hid_provider_1.HIDProvider {
|
|
7
29
|
constructor() {
|
|
8
30
|
super(...arguments);
|
|
9
31
|
this.wireless = false;
|
|
10
32
|
}
|
|
11
|
-
connect() {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
33
|
+
async connect() {
|
|
34
|
+
if (typeof window !== undefined)
|
|
35
|
+
return this.onError(new Error("Attempted to use node-hid in browser environment"));
|
|
36
|
+
return Promise.resolve().then(() => __importStar(require("node-hid"))).then(({ HID, devices }) => {
|
|
37
|
+
if (!HID)
|
|
38
|
+
return this.onError(new Error("Failed import of 'node-hid'"));
|
|
39
|
+
this.disconnect();
|
|
40
|
+
const controllers = devices(hid_provider_1.HIDProvider.vendorId, hid_provider_1.HIDProvider.productId);
|
|
41
|
+
if (controllers.length === 0 || !controllers[0].path) {
|
|
42
|
+
return this.onError(new Error(`No controllers (${devices().length} other devices)`));
|
|
43
|
+
}
|
|
44
|
+
if (controllers[0].interface === -1)
|
|
45
|
+
this.wireless = true;
|
|
46
|
+
const device = new HID(controllers[0].path);
|
|
47
|
+
device.on("data", (arg) => {
|
|
48
|
+
this.onData(this.process(arg));
|
|
49
|
+
});
|
|
50
|
+
device.on("error", (err) => {
|
|
51
|
+
this.onError(err);
|
|
52
|
+
});
|
|
53
|
+
this.device = device;
|
|
54
|
+
})
|
|
55
|
+
.catch((err) => {
|
|
56
|
+
this.onError(new Error(`Could not import 'node-hid'. Did you add it?\nError: ${err instanceof Error ? err.message : "???"}`));
|
|
25
57
|
});
|
|
26
58
|
}
|
|
27
59
|
get connected() {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"node_hid_provider.js","sourceRoot":"","sources":["../../src/hid/node_hid_provider.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"node_hid_provider.js","sourceRoot":"","sources":["../../src/hid/node_hid_provider.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dualsense-ts",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "5.0.0",
|
|
4
4
|
"description": "A natural interface for your DualSense controller, with Typescript",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"dualsense",
|
|
@@ -29,9 +29,11 @@
|
|
|
29
29
|
"license": "GPL-3.0",
|
|
30
30
|
"private": false,
|
|
31
31
|
"main": "dist/index.js",
|
|
32
|
-
"browser": "dist/main.js",
|
|
33
32
|
"types": "dist/index.d.ts",
|
|
34
33
|
"sideEffects": false,
|
|
34
|
+
"browser": {
|
|
35
|
+
"node-hid": false
|
|
36
|
+
},
|
|
35
37
|
"scripts": {
|
|
36
38
|
"prebuild": "yarn barrels",
|
|
37
39
|
"build": "tsc --project tsconfig.build.json",
|
|
@@ -40,15 +42,20 @@
|
|
|
40
42
|
"lint": "eslint src",
|
|
41
43
|
"test": "jest src --verbose",
|
|
42
44
|
"test:watch": "jest src --verbose --watch",
|
|
43
|
-
"coverage": "jest src --coverage --verbose",
|
|
45
|
+
"coverage": "jest src --coverage --verbose --forceExit",
|
|
44
46
|
"coverage:watch": "jest src --coverage --verbose --watch",
|
|
45
47
|
"barrels": "barrelsby -d src -D -l replace -e 'spec.ts$'",
|
|
46
48
|
"docs": "typedoc src/index.ts",
|
|
47
49
|
"debug": "node --inspect --enable-source-maps --experimental-specifier-resolution=node --loader ts-node/esm ./util/debug.ts"
|
|
48
50
|
},
|
|
49
|
-
"
|
|
51
|
+
"peerDependencies": {
|
|
50
52
|
"node-hid": "^2.1.1"
|
|
51
53
|
},
|
|
54
|
+
"peerDependenciesMeta": {
|
|
55
|
+
"node-hid": {
|
|
56
|
+
"optional": true
|
|
57
|
+
}
|
|
58
|
+
},
|
|
52
59
|
"devDependencies": {
|
|
53
60
|
"@types/jest": "^27.5.0",
|
|
54
61
|
"@types/node": "^18.0.0",
|
|
@@ -62,6 +69,7 @@
|
|
|
62
69
|
"eslint-plugin-import": "^2.26.0",
|
|
63
70
|
"html-webpack-plugin": "^5.5.0",
|
|
64
71
|
"jest": "^27.5.1",
|
|
72
|
+
"node-hid": "^2.1.1",
|
|
65
73
|
"prettier": "^2.3.2",
|
|
66
74
|
"ts-jest": "^27.1.3",
|
|
67
75
|
"ts-loader": "^9.3.1",
|
package/src/dualsense.ts
CHANGED
|
@@ -59,8 +59,16 @@ export class Dualsense extends Input<Dualsense> {
|
|
|
59
59
|
|
|
60
60
|
public readonly touchpad: Touchpad;
|
|
61
61
|
|
|
62
|
+
/**
|
|
63
|
+
* Represents the underlying HID mechanism and device.
|
|
64
|
+
*/
|
|
62
65
|
public readonly hid: DualsenseHID;
|
|
63
66
|
|
|
67
|
+
/**
|
|
68
|
+
* A virtual button representing whether or not a controller is connected.
|
|
69
|
+
*/
|
|
70
|
+
public readonly connection: Momentary;
|
|
71
|
+
|
|
64
72
|
public get active(): boolean {
|
|
65
73
|
return Object.values(this).some(
|
|
66
74
|
(input) => input !== this && input instanceof Input && input.active
|
|
@@ -131,12 +139,37 @@ export class Dualsense extends Input<Dualsense> {
|
|
|
131
139
|
...(params.touchpad || {}),
|
|
132
140
|
});
|
|
133
141
|
|
|
142
|
+
this.connection = new Momentary({
|
|
143
|
+
icon: "🔗",
|
|
144
|
+
name: "Connected",
|
|
145
|
+
...(params.square || {}),
|
|
146
|
+
});
|
|
147
|
+
this.connection[InputSet](false);
|
|
148
|
+
|
|
134
149
|
this.hid = params.hid || new DualsenseHID(new PlatformHIDProvider());
|
|
135
150
|
this.hid.register((state: DualsenseHIDState) => {
|
|
136
151
|
this.processHID(state);
|
|
137
152
|
});
|
|
138
153
|
|
|
139
|
-
|
|
154
|
+
setInterval(() => {
|
|
155
|
+
const { hid } = this;
|
|
156
|
+
if (this.hid) {
|
|
157
|
+
const {
|
|
158
|
+
provider: { connected },
|
|
159
|
+
} = hid;
|
|
160
|
+
|
|
161
|
+
this.connection[InputSet](connected);
|
|
162
|
+
|
|
163
|
+
if (!connected) {
|
|
164
|
+
try {
|
|
165
|
+
this.hid.provider.connect();
|
|
166
|
+
this.connection[InputSet](true);
|
|
167
|
+
} catch {
|
|
168
|
+
this.connection[InputSet](false);
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
}, 100);
|
|
140
173
|
}
|
|
141
174
|
|
|
142
175
|
/**
|
package/src/hid/dualsense_hid.ts
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
import { HIDProvider, DualsenseHIDState, InputId } from "./hid_provider";
|
|
2
2
|
|
|
3
3
|
export type HIDCallback = (state: DualsenseHIDState) => void;
|
|
4
|
+
export type ErrorCallback = (error: Error) => void;
|
|
4
5
|
|
|
5
6
|
/**
|
|
6
7
|
* Coordinates a HIDProvider and tracks the latest HID state.
|
|
7
8
|
*/
|
|
8
9
|
export class DualsenseHID {
|
|
9
10
|
private readonly subscribers = new Set<HIDCallback>();
|
|
11
|
+
private readonly errorSubscribers = new Set<ErrorCallback>();
|
|
10
12
|
|
|
11
13
|
public state: DualsenseHIDState = {
|
|
12
14
|
[InputId.LeftAnalogX]: 0,
|
|
@@ -71,13 +73,17 @@ export class DualsenseHID {
|
|
|
71
73
|
this.subscribers.delete(callback);
|
|
72
74
|
}
|
|
73
75
|
|
|
76
|
+
public on(type: "data" | "error", callback: ErrorCallback): void {
|
|
77
|
+
if (type === "error") this.errorSubscribers.add(callback);
|
|
78
|
+
}
|
|
79
|
+
|
|
74
80
|
private set(state: DualsenseHIDState): void {
|
|
75
81
|
this.state = state;
|
|
76
82
|
this.subscribers.forEach((callback) => callback(state));
|
|
77
83
|
}
|
|
78
84
|
|
|
79
|
-
private handleError(error:
|
|
80
|
-
|
|
85
|
+
private handleError(error: Error): void {
|
|
86
|
+
this.errorSubscribers.forEach((callback) => callback(error));
|
|
81
87
|
setTimeout(() => {
|
|
82
88
|
this.provider.disconnect();
|
|
83
89
|
this.provider.connect();
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
import { HID, devices } from "node-hid";
|
|
2
|
-
|
|
3
1
|
import {
|
|
4
2
|
HIDProvider,
|
|
5
3
|
DualsenseHIDState,
|
|
@@ -8,29 +6,57 @@ import {
|
|
|
8
6
|
mapTrigger,
|
|
9
7
|
} from "./hid_provider";
|
|
10
8
|
|
|
9
|
+
interface HIDable {
|
|
10
|
+
close: () => void;
|
|
11
|
+
removeAllListeners: () => void;
|
|
12
|
+
}
|
|
13
|
+
|
|
11
14
|
export class NodeHIDProvider extends HIDProvider {
|
|
12
|
-
private device?:
|
|
15
|
+
private device?: HIDable;
|
|
13
16
|
public wireless: boolean = false;
|
|
14
17
|
|
|
15
|
-
connect(): void {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
const controllers = devices(HIDProvider.vendorId, HIDProvider.productId);
|
|
19
|
-
if (controllers.length === 0 || !controllers[0].path) {
|
|
18
|
+
async connect(): Promise<void> {
|
|
19
|
+
if (typeof window !== undefined)
|
|
20
20
|
return this.onError(
|
|
21
|
-
new Error(
|
|
21
|
+
new Error("Attempted to use node-hid in browser environment")
|
|
22
22
|
);
|
|
23
|
-
}
|
|
24
23
|
|
|
25
|
-
|
|
24
|
+
return import("node-hid")
|
|
25
|
+
.then(({ HID, devices }) => {
|
|
26
|
+
if (!HID) return this.onError(new Error("Failed import of 'node-hid'"));
|
|
27
|
+
this.disconnect();
|
|
28
|
+
|
|
29
|
+
const controllers = devices(
|
|
30
|
+
HIDProvider.vendorId,
|
|
31
|
+
HIDProvider.productId
|
|
32
|
+
);
|
|
33
|
+
if (controllers.length === 0 || !controllers[0].path) {
|
|
34
|
+
return this.onError(
|
|
35
|
+
new Error(`No controllers (${devices().length} other devices)`)
|
|
36
|
+
);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
if (controllers[0].interface === -1) this.wireless = true;
|
|
40
|
+
|
|
41
|
+
const device = new HID(controllers[0].path);
|
|
42
|
+
device.on("data", (arg: Buffer) => {
|
|
43
|
+
this.onData(this.process(arg));
|
|
44
|
+
});
|
|
45
|
+
device.on("error", (err: Error) => {
|
|
46
|
+
this.onError(err);
|
|
47
|
+
});
|
|
26
48
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
49
|
+
this.device = device;
|
|
50
|
+
})
|
|
51
|
+
.catch((err) => {
|
|
52
|
+
this.onError(
|
|
53
|
+
new Error(
|
|
54
|
+
`Could not import 'node-hid'. Did you add it?\nError: ${
|
|
55
|
+
err instanceof Error ? err.message : "???"
|
|
56
|
+
}`
|
|
57
|
+
)
|
|
58
|
+
);
|
|
59
|
+
});
|
|
34
60
|
}
|
|
35
61
|
|
|
36
62
|
get connected(): boolean {
|