robot-control 0.1.2

A Rust library for controlling DC motor robots via PCA9685 PWM boards over I2C
Documentation
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Robot Control</title>
    <style>
        body {
            display: flex;
            flex-direction: column;
            align-items: center;
            justify-content: center;
            height: 100vh;
            margin: 0;
        }
        #joysticks {
            display: flex;
            gap: 20px;
        }
        .joystick {
            width: 150px;
            height: 150px;
            position: relative;
        }
        .nipple {
            width: 100%;
            height: 100%;
        }
    </style>
    <script src="static/nipplejs.min.js"></script>
</head>
<body>
    <h1>Robot Control</h1>
    <div id="joysticks">
        <div id="leftJoystick" class="joystick"></div>
        <div id="rightJoystick" class="joystick"></div>
    </div>

    <script>
        const leftJoystick = document.getElementById('leftJoystick');
        const rightJoystick = document.getElementById('rightJoystick');

        const socketProtocol = location.protocol === 'https:' ? 'wss:' : 'ws:';
        const socket = new WebSocket(`${socketProtocol}//${location.host}/ws`);

        socket.onopen = () => {
            console.log('WebSocket connection established');
        };

        socket.onerror = (error) => {
            console.error('WebSocket error:', error);
        };

        function sendDriveCommand(left, right) {
            if (socket.readyState !== WebSocket.OPEN) {
                return;
            }
            const message = JSON.stringify({ left, right });
            socket.send(message);
        }

        const leftNipple = nipplejs.create({
            zone: leftJoystick,
            mode: 'static',
            position: { left: '50%', top: '50%' },
            color: 'blue'
        });

        const rightNipple = nipplejs.create({
            zone: rightJoystick,
            mode: 'static',
            position: { left: '50%', top: '50%' },
            color: 'red'
        });

        leftNipple.on('move', (evt, data) => {
            const value = Math.max(-1, Math.min(1, data.vector.y));
            sendDriveCommand(value, rightJoystick.value || 0);
            leftJoystick.value = value;
        });

        rightNipple.on('move', (evt, data) => {
            const value = Math.max(-1, Math.min(1, data.vector.y));
            sendDriveCommand(leftJoystick.value || 0, value);
            rightJoystick.value = value;
        });

        leftNipple.on('end', () => {
            leftJoystick.value = 0;
            sendDriveCommand(0, rightJoystick.value || 0);
        });

        rightNipple.on('end', () => {
            rightJoystick.value = 0;
            sendDriveCommand(leftJoystick.value || 0, 0);
        });
    </script>
</body>
</html>