]> git.taranathan.com Git - FRC2026.git/commitdiff
made a simple rumble tester
authoriefomit <timofei.stem@gmail.com>
Wed, 4 Mar 2026 06:05:18 +0000 (22:05 -0800)
committeriefomit <timofei.stem@gmail.com>
Wed, 4 Mar 2026 06:05:18 +0000 (22:05 -0800)
controller-tester.html [new file with mode: 0644]

diff --git a/controller-tester.html b/controller-tester.html
new file mode 100644 (file)
index 0000000..dc5c6c0
--- /dev/null
@@ -0,0 +1,70 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <title>DualSense rumble test</title>
+    <style>
+        body { font-family: sans-serif; padding: 20px; background: #1a1a1a; color: #fff; }
+        button { padding: 15px 30px; font-size: 16px; margin: 10px; cursor: pointer; }
+        #status { margin: 20px 0; padding: 10px; background: #333; }
+    </style>
+</head>
+<body>
+    <h1>DualSense rumble test</h1>
+    <div id="status">Not connected</div>
+    <button onclick="connect()">connect controller</button>
+    <button onclick="rumble()" id="rumbleBtn" disabled>test rumble</button>
+
+    <script>
+        const SONY_VENDOR_ID = 0x054c;
+        const DUALSENSE_PRODUCT_ID = 0x0ce6;
+        let device = null;
+
+        async function connect() {
+            const devices = await navigator.hid.requestDevice({
+                filters: [{ vendorId: SONY_VENDOR_ID, productId: DUALSENSE_PRODUCT_ID }]
+            });
+            if (devices.length === 0) return;
+
+            device = devices[0];
+            await device.open();
+            document.getElementById('status').textContent = 'connected: ' + device.productName;
+            document.getElementById('rumbleBtn').disabled = false;
+        }
+
+        async function sendRumble(left, right) {
+            if (!device) return;
+
+            // get report size from device
+            let size = 47;
+            if (device.collections?.[0]?.outputReports?.[0]?.items?.[0]) {
+                const item = device.collections[0].outputReports[0].items[0];
+                size = (item.reportSize * item.reportCount) / 8;
+            }
+
+            const report = new Uint8Array(size);
+            report[0] = 0x03;  // enable rumble
+            report[1] = 0xF7;
+            report[2] = right;
+            report[3] = left;
+
+            await device.sendReport(0x02, report);
+        }
+
+        async function rumble() {
+            await sendRumble(255, 255);
+            setTimeout(() => sendRumble(0, 0), 500);
+        }
+
+        // auto-connect if already paired
+        navigator.hid.getDevices().then(async devices => {
+            const ds = devices.find(d => d.vendorId === SONY_VENDOR_ID && d.productId === DUALSENSE_PRODUCT_ID);
+            if (ds) {
+                device = ds;
+                await device.open();
+                document.getElementById('status').textContent = 'connected: ' + device.productName;
+                document.getElementById('rumbleBtn').disabled = false;
+            }
+        });
+    </script>
+</body>
+</html>