Skip to content

Commit a2a95b8

Browse files
committed
chore: Add full application web example
1 parent 3af7678 commit a2a95b8

1 file changed

Lines changed: 197 additions & 0 deletions

File tree

Lines changed: 197 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,197 @@
1+
// Buttplug Web - Complete Application Example
2+
//
3+
// This is a complete, working example that demonstrates the full workflow
4+
// of a Buttplug application in a browser. If you're new to Buttplug, start here!
5+
//
6+
// Prerequisites:
7+
// 1. Install Intiface Central: https://intiface.com/central
8+
// 2. Start the server in Intiface Central (click "Start Server")
9+
// 3. Include Buttplug via CDN in your HTML:
10+
// <script src="https://cdn.jsdelivr.net/npm/buttplug@4.0.0/dist/web/buttplug.min.js"></script>
11+
// 4. Call runApplicationExample() from your page
12+
13+
async function runApplicationExample() {
14+
console.log("===========================================");
15+
console.log(" Buttplug Web Application Example");
16+
console.log("===========================================\n");
17+
18+
// Step 1: Create a client
19+
// The client name identifies your application to the server.
20+
const client = new Buttplug.ButtplugClient("My Buttplug Application");
21+
22+
// Step 2: Set up event handlers
23+
// Always do this BEFORE connecting to avoid missing events.
24+
client.addListener("deviceadded", (device) => {
25+
console.log(`[+] Device connected: ${device.name}`);
26+
});
27+
28+
client.addListener("deviceremoved", (device) => {
29+
console.log(`[-] Device disconnected: ${device.name}`);
30+
});
31+
32+
client.addListener("disconnect", () => {
33+
console.log("[!] Server connection lost!");
34+
});
35+
36+
// Step 3: Connect to the server
37+
console.log("Connecting to Intiface Central...");
38+
try {
39+
const connector = new Buttplug.ButtplugBrowserWebsocketClientConnector(
40+
"ws://127.0.0.1:12345"
41+
);
42+
await client.connect(connector);
43+
} catch (e) {
44+
if (e instanceof Buttplug.ButtplugClientConnectorException) {
45+
alert(
46+
"Could not connect to Intiface Central!\n\n" +
47+
"Make sure Intiface Central is running and the server is started.\n" +
48+
"Default address: ws://127.0.0.1:12345"
49+
);
50+
console.log("ERROR: Could not connect to Intiface Central!");
51+
return;
52+
}
53+
throw e;
54+
}
55+
console.log("Connected!\n");
56+
57+
// Step 4: Scan for devices
58+
console.log("Scanning for devices...");
59+
console.log("Turn on your Bluetooth/USB devices now.\n");
60+
await client.startScanning();
61+
62+
// Wait for devices (using alert/confirm for browser interaction)
63+
alert("Scanning for devices...\n\nTurn on your devices, then click OK when ready.");
64+
await client.stopScanning();
65+
66+
// Step 5: Check what devices we found
67+
const devices = Array.from(client.devices.values());
68+
if (devices.length === 0) {
69+
alert(
70+
"No devices found!\n\n" +
71+
"Make sure your device is:\n" +
72+
"- Turned on\n" +
73+
"- In pairing/discoverable mode\n" +
74+
"- Supported by Buttplug (check https://iostindex.com)"
75+
);
76+
console.log("No devices found.");
77+
await client.disconnect();
78+
return;
79+
}
80+
81+
console.log(`\nFound ${devices.length} device(s):\n`);
82+
83+
// Step 6: Display device capabilities
84+
for (const device of devices) {
85+
console.log(` ${device.name}`);
86+
87+
// Check output capabilities
88+
const outputs = [];
89+
if (device.hasOutput(Buttplug.OutputType.Vibrate)) outputs.push("Vibrate");
90+
if (device.hasOutput(Buttplug.OutputType.Rotate)) outputs.push("Rotate");
91+
if (device.hasOutput(Buttplug.OutputType.Oscillate)) outputs.push("Oscillate");
92+
if (device.hasOutput(Buttplug.OutputType.Position)) outputs.push("Position");
93+
if (device.hasOutput(Buttplug.OutputType.Constrict)) outputs.push("Constrict");
94+
95+
if (outputs.length > 0) {
96+
console.log(` Outputs: ${outputs.join(", ")}`);
97+
}
98+
99+
// Check input capabilities
100+
const inputs = [];
101+
if (device.hasInput(Buttplug.InputType.Battery)) inputs.push("Battery");
102+
if (device.hasInput(Buttplug.InputType.RSSI)) inputs.push("RSSI");
103+
104+
if (inputs.length > 0) {
105+
console.log(` Inputs: ${inputs.join(", ")}`);
106+
}
107+
}
108+
109+
// Step 7: Interactive device control
110+
console.log("\n=== Interactive Control ===");
111+
console.log("Use the prompts to control devices.");
112+
113+
let running = true;
114+
while (running) {
115+
const input = prompt(
116+
"Commands:\n" +
117+
" v <0-100> - Vibrate all devices at percentage\n" +
118+
" s - Stop all devices\n" +
119+
" b - Read battery levels\n" +
120+
" q - Quit\n\n" +
121+
"Enter command:"
122+
);
123+
124+
if (input === null) {
125+
// User clicked Cancel
126+
running = false;
127+
continue;
128+
}
129+
130+
const cmd = input.trim().toLowerCase();
131+
132+
if (!cmd) continue;
133+
134+
try {
135+
if (cmd.startsWith("v ")) {
136+
// Vibrate command
137+
const percentStr = cmd.slice(2);
138+
const percent = parseInt(percentStr, 10);
139+
if (!isNaN(percent) && percent >= 0 && percent <= 100) {
140+
const intensity = percent / 100.0;
141+
for (const device of devices) {
142+
if (device.hasOutput(Buttplug.OutputType.Vibrate)) {
143+
await device.runOutput(Buttplug.DeviceOutput.Vibrate.percent(intensity));
144+
console.log(` ${device.name}: vibrating at ${percent}%`);
145+
}
146+
}
147+
} else {
148+
alert("Usage: v <0-100>");
149+
}
150+
} else if (cmd === "s") {
151+
// Stop all devices
152+
await client.stopAllDevices();
153+
console.log(" All devices stopped.");
154+
} else if (cmd === "b") {
155+
// Read battery levels
156+
let batteryInfo = "Battery Levels:\n\n";
157+
for (const device of devices) {
158+
if (device.hasInput(Buttplug.InputType.Battery)) {
159+
try {
160+
const battery = await device.battery();
161+
const msg = `${device.name}: ${(battery * 100).toFixed(0)}%`;
162+
console.log(` ${msg}`);
163+
batteryInfo += msg + "\n";
164+
} catch (e) {
165+
console.log(` ${device.name}: could not read battery`);
166+
batteryInfo += `${device.name}: could not read battery\n`;
167+
}
168+
} else {
169+
console.log(` ${device.name}: no battery sensor`);
170+
batteryInfo += `${device.name}: no battery sensor\n`;
171+
}
172+
}
173+
alert(batteryInfo);
174+
} else if (cmd === "q") {
175+
running = false;
176+
} else {
177+
alert("Unknown command. Use v, s, b, or q.");
178+
}
179+
} catch (e) {
180+
if (e instanceof Buttplug.ButtplugDeviceError) {
181+
console.log(` Device error: ${e.message}`);
182+
alert(`Device error: ${e.message}`);
183+
} else if (e instanceof Buttplug.ButtplugError) {
184+
console.log(` Error: ${e.message}`);
185+
alert(`Error: ${e.message}`);
186+
} else {
187+
throw e;
188+
}
189+
}
190+
}
191+
192+
// Step 8: Clean up
193+
console.log("\nStopping devices and disconnecting...");
194+
await client.stopAllDevices();
195+
await client.disconnect();
196+
console.log("Goodbye!");
197+
}

0 commit comments

Comments
 (0)