Skip to content

Add simple vanilla JS example to repo #260

@stephanbogner

Description

@stephanbogner

First of all:
This is a super interesting and fun project – thanks for putting in the time and effort ❤️

Problem:

I had a hard time getting started. Some notes from my journey:

  • The docs are extensive but also a bit daunting. Even the Quickstart didn't help me much getting stuff running in the beginning unfortunately.
  • This file was helpful as reference, but since there is no dist folder (anymore?) I couldn't get this code to run
  • The list of projects also helped (due to many being open source)
  • Glitch links to docs that don't exist anymore
  • The npm installed version doesn't contain the actual wasm file (I only found it via the CDN)
  • I wasn't sure (and still am not) if one should use the "js" or the "mjs" files
  • I thought the Glitch project is just documentation so only now when retracing my steps I discovered the – very helpful – script.mjs file. In theory Glitch is great, but when you have never used it I think it can be more confusing than helpful.
  • Note: I really like the docs from p5 because even to newbies they make it easy to dive in

Solution:

I think it would be cool to have a simple example to cover a basic but common use case already in the readme of this repository as this is where one lands when checking out buttplug-js. For example:

Quickstart

  1. Basics: There are two ways to connect to a device (supported devices):
  2. Important information:
  3. Download code: Download this index.html-file (should be linked but I posted below)
  4. Setup localhost: The browser won't allow bluetooth connections unless the website comes from a server. You can create a local server (called localhost):
  5. Start localhost: Start the folder with the index.html-file in your preferred localhost
  6. Done: You should now be able to open the website and connect to a device
  7. Tip: Check out what other people have done with buttplug
📄 index.html file (likely not perfect)
<!DOCTYPE html>
<html>
    <head>
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>Buttplug-JS Example</title>
        <meta charset="UTF-8" />
    </head>

    <body>
        <ul>
            <li>
                <button id="scan">Connect to a device ...</button>
                <div id="device">No device connected</div>
            </li>
        </ul>

        <ul>
            <li>
                <button id="vibrate-0">Turn off vibration</button>
            </li>
            <li>
                <button id="vibrate-50">Vibrate 50%</button>
            </li>
            <li>
                <button id="vibrate-100">Vibrate 100%</button>
            </li>
            <li>
                <button id="vibrate-20-100">Motor 1 = 20%, Motor 2 = 100% (if available)</button>
            </li>
        </ul>

        <ul>
            <li>
                <button id="rotate-0">Stop rotating</button>
            </li>
            <li>
                <button id="rotate-50-c">Rotate at 50% strength clockwise</button>
            </li>
            <li>
                <button id="rotate-100-cc">Rotate at 100% strength counter-clockwise</button>
            </li>
        </ul>

        <script type="module">
            import { ButtplugClient, ButtplugBrowserWebsocketClientConnector } from "https://cdn.jsdelivr.net/npm/[email protected]/dist/web/buttplug.mjs"
            import { ButtplugWasmClientConnector } from "https://cdn.jsdelivr.net/npm/[email protected]/dist/buttplug-wasm.mjs"

            let client
            let currentDevice
            initButtplug()

            document.getElementById('scan').addEventListener('click', scan)

            document.getElementById('vibrate-0').addEventListener('click', () => {
                // Turn off vibration for all motors
                currentDevice.vibrate(0)
            })
            document.getElementById('vibrate-50').addEventListener('click', () => {
                // Vibrate all motors at 50% strength
                currentDevice.vibrate(0.5)
            })
            document.getElementById('vibrate-100').addEventListener('click', () => {
                // Vibrate all motors at 100% strength
                currentDevice.vibrate(1)
            })
            document.getElementById('vibrate-20-100').addEventListener('click', () => {
                // Vibrate motor 1 with 20% strength and motor 2 with 100% strength (if the device has multiple motors)
                currentDevice.vibrate([0.2, 1])
            })

            document.getElementById('rotate-0').addEventListener('click', () => {
                // Stop rotating
                currentDevice.rotate(0, true)
            })
            document.getElementById('rotate-50-c').addEventListener('click', () => {
                // Rotate at 50% strength clockwise
                currentDevice.rotate(0.5, true)
            })
            document.getElementById('rotate-100-cc').addEventListener('click', () => {
                // Rotate at 100% strength counter-clockwise
                currentDevice.rotate(1, false)
            })
            
            async function initButtplug() {
                client = new ButtplugClient("Test Client");

                // For direct bluetooth connection
                await ButtplugWasmClientConnector.activateLogging()
                await client.connect(new ButtplugWasmClientConnector())

                // For connection to IntiFace
                let address = "ws://localhost:12345"
                let connector = new ButtplugBrowserWebsocketClientConnector(address)
                try {
                    await client.connect(connector)
                }
                catch (ex) {
                    console.log(ex)
                }

                client.addListener("deviceadded", async (device) => {
                    console.log(`Device Connected: ${device.name}`)
                    currentDevice = device
                    document.getElementById('device').innerHTML = device.name
                    // Vibrate device to show (or make you feel) it's connected
                    vibrateBriefly(currentDevice)
                })

                client.addListener("deviceremoved", async (device) => {
                    console.log('Device removed', device)
                })
            }

            async function vibrateBriefly(device) {
                await device.vibrate(0.4)
                setTimeout(() => {
                    device.vibrate(0)
                }, 200)
            }

            async function scan() {
                console.log('Start scanning')
                await client.startScanning();
            }
        </script>
    </body>
</html>

PS: It feels weirdly taboo to open an issue publicly in such a repository ... but it's also liberating 😅

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions