Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/main'
Browse files Browse the repository at this point in the history
  • Loading branch information
Advay17 committed Oct 13, 2024
2 parents c7ef939 + c9f1003 commit ef06796
Show file tree
Hide file tree
Showing 3 changed files with 142 additions and 45 deletions.
13 changes: 8 additions & 5 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -40,23 +40,26 @@
</div>

<div class="container" id="interface">
<button id="ButtonBLE">CONNECT</button>
<button id="ble-button">🔗</button>
<button id="battery-level"> &#x1F50B;&#xFE0E; ?V </button>
<button id="ble-status">not connected</button>

<div id="settings-grid">
<div class="settings-label">Mobile Layout</div>

<div class="settings-toggle">
<div id="toggle-mobile-layout" class="toggle-round"><div class="toggle-nub"></div></div>
</div>

<div class="settings-label">Override axes <br> with WASD</div>
<div class="settings-label help-row">Override axes <br> with WASD</div>

<div class="settings-toggle">
<div class="settings-toggle help-row">
<div id="toggle-keyboard-style" class="toggle-round"><div class="toggle-nub"></div></div>
</div>

<div class="settings-label">Help/Info!</div>
<div class="settings-label help-row">Help/Info!</div>

<div class="settings-toggle">
<div class="settings-toggle help-row">
<div id="toggle-info" class="toggle-round"><div class="toggle-nub"></div></div>
</div>

Expand Down
133 changes: 97 additions & 36 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
let isMobile = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)

let bleAgent = createBleAgent();
let keyboardAgent = createKeyboardAgent();
let axisAgent = createMobileAxisAgent();
Expand All @@ -9,6 +11,9 @@ let buttonCallback = null

let mobileElements = document.getElementsByClassName("mobile-only");
let desktopElements = document.getElementsByClassName("desktop-only");

let helpRow = document.getElementsByClassName("help-row");

let infoElement = document.getElementById("info-container");
let hackSpacerElement = document.getElementById("hack-spacer");

Expand All @@ -20,7 +25,6 @@ let lastKeyPressed = 1;
// --------------------------- state management ------------------------------------ //

if (localStorage.getItem(toggleMobile.id) == null) {
let isMobile = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)
if (isMobile) {
localStorage.setItem(toggleMobile.id, 'true');
} else {
Expand All @@ -29,6 +33,8 @@ if (localStorage.getItem(toggleMobile.id) == null) {
updateMobileSlider(toggleMobile, false);
}

if(isMobile) for (let element of helpRow) element.style.display = "none";

document.addEventListener('DOMContentLoaded', function () {
updateMobileSlider(toggleMobile, toggleState=false);
updateSlider(toggleKeyboardWASD, toggleState=false);
Expand Down Expand Up @@ -106,7 +112,7 @@ function renderLoop() {
//bytes 0: packet version
//bytes 1-4: axes
//bytes 5-6: button states
//bytes 7-19: pressed keyboard keys
//bytes 7-17: pressed keyboard keys
let rawPacket = new Uint8Array(1 + 4 + 2 + 11)

rawPacket[0] = 0x01; //packet version
Expand Down Expand Up @@ -225,42 +231,35 @@ function renderLoop() {
// -------------------------------------------- bluetooth --------------------------------------- //

function createBleAgent() {
let parent = document.getElementById('ButtonBLE')
let buttonBLE = document.getElementById('ble-button')
let statusBLE = document.getElementById('ble-status')
let batteryDisplay = document.getElementById('battery-level')

const SERVICE_UUID_PESTOBLE = '27df26c5-83f4-4964-bae0-d7b7cb0a1f54';
const CHARACTERISTIC_UUID_GAMEPAD = '452af57e-ad27-422c-88ae-76805ea641a9';
const CHARACTERISTIC_UUID_TELEMETRY = '266d9d74-3e10-4fcd-88d2-cb63b5324d0c';

parent.onclick = changeBleState;
parent.ontouchend = changeBleState;

function displayBleStatus(status) {
parent.innerHTML = status;
switch (status) {
case 'Connecting':
parent.style.backgroundColor = 'grey';
break;
case 'Connected':
parent.style.backgroundColor = '#4dae50';
break;
case 'Disconnecting':
parent.style.backgroundColor = 'grey';
break;
case 'Not Connected':
parent.style.backgroundColor = 'grey';
break;
default:
parent.style.backgroundColor = '#eb5b5b';
}
if (isMobile){
buttonBLE.ontouchend = updateBLE;
} else {
buttonBLE.onclick = updateBLE;
}

function displayBleStatus(status, color) {
statusBLE.innerHTML = status;
console.log(status)
statusBLE.style.backgroundColor = color;
}

let device;
let device = null;
let server;
let service;
let characteristic_gamepad;
let bleUpdateInProgress = false;
let characteristic_battery;
let isConnectedBLE = false;
let bleUpdateInProgress = false;

async function changeBleState() {
async function updateBLE() {
if (bleUpdateInProgress) return
bleUpdateInProgress = true;
if (!isConnectedBLE) connectBLE();
Expand All @@ -269,46 +268,89 @@ function createBleAgent() {
}

async function connectBLE() {
displayBleStatus('Connecting');

try {
device = await navigator.bluetooth.requestDevice({ filters: [{ services: [SERVICE_UUID_PESTOBLE] }] });
if (device == null){
displayBleStatus('Connecting', 'black');
device = await navigator.bluetooth.requestDevice({ filters: [{ services: [SERVICE_UUID_PESTOBLE] }] });
} else {
displayBleStatus('Attempting Reconnect...', 'black');
}

server = await device.gatt.connect();
service = await server.getPrimaryService(SERVICE_UUID_PESTOBLE);

characteristic_gamepad = await service.getCharacteristic(CHARACTERISTIC_UUID_GAMEPAD);
try{
characteristic_battery = await service.getCharacteristic(CHARACTERISTIC_UUID_TELEMETRY);
await characteristic_battery.startNotifications()
await characteristic_battery.addEventListener('characteristicvaluechanged', handleBatteryCharacteristic);
}catch{
console.log("Pestolink version on robot is real old :(")
}

await device.addEventListener('gattserverdisconnected', robotDisconnect);

displayBleStatus('Connected');
isConnectedBLE = true;
buttonBLE.innerHTML = '❌';
displayBleStatus('Connected', '#4dae50'); //green

} catch (error) {
displayBleStatus("Error");
console.error('Error:', error);
if (error.name === 'NotFoundError') {
displayBleStatus('No Device Selected', '#eb5b5b');
} else if (error.name === 'SecurityError') {
displayBleStatus('Security error', '#eb5b5b');
} else {
console.log( error);
displayBleStatus('Connection failed', '#eb5b5b');
connectBLE();
}
}
}

function handleBatteryCharacteristic(event){
batteryWatchdogReset();
let value = event.target.value.getUint8(0);
let voltage = (value/255.0) * 12

if(voltage >= 7.6) {
batteryDisplay.style.textShadow = "0 0 2px green, 0 0 2px green, 0 0 2px green, 0 0 2px green";
} else if (voltage >= 7) {
batteryDisplay.style.textShadow = "0 0 2px green, 0 0 2px yellow, 0 0 2px yellow, 0 0 2px yellow";
} else {
batteryDisplay.style.textShadow = "0 0 2px red, 0 0 2px red, 0 0 2px red, 0 0 2px red";
}

batteryDisplay.innerHTML = "&#x1F50B;&#xFE0E; " + voltage.toFixed(1) + "V";
}

async function disconnectBLE() {
displayBleStatus('Disconnecting');
try {
batteryWatchdogStop();
await device.removeEventListener('gattserverdisconnected', robotDisconnect);
await device.gatt.disconnect();

displayBleStatus('Not Connected');
displayBleStatus('Not Connected', 'grey');
isConnectedBLE = false;
buttonBLE.innerHTML = '🔗';


} catch (error) {
displayBleStatus("Error");
displayBleStatus("Error", '#eb5b5b');
console.error('Error:', error);
}
}

function robotDisconnect(event) {
displayBleStatus('Not Connected');
batteryWatchdogStop();
displayBleStatus('Not Connected', 'grey');
isConnectedBLE = false;
connectBLE();
}

async function sendPacketBLE(byteArray) {
if (!isConnectedBLE) return;
if (bleUpdateInProgress) return;

try {
await characteristic_gamepad.writeValueWithoutResponse(new Uint8Array(byteArray));
Expand All @@ -317,11 +359,30 @@ function createBleAgent() {
}
}

// Function to create and manage the watchdog timer
let timer;
const timeout = 1000; // 400ms
// Function to start or reset the watchdog timer
function batteryWatchdogReset() {
displayBleStatus('Connected', '#4dae50'); //green
if (timer) {clearTimeout(timer);}
timer = setTimeout(() => {
displayBleStatus('timeout?', 'black');
}, timeout);
}
// Function to stop the watchdog timer
function batteryWatchdogStop() {
batteryWatchdogReset()
if (timer) {clearTimeout(timer);timer = null;}
}

return {
attemptSend: sendPacketBLE
};
}



// -------------------------------------------- mobile --------------------------------------- //

function createMobileAxisAgent() {
Expand Down
41 changes: 37 additions & 4 deletions styles.css
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ body {
border-radius: 50%;
-webkit-user-select: none;
user-select: none;
-webkit-user-select: none;
cursor: pointer;
height: 13vw;
width: 13vw;
Expand All @@ -122,21 +123,52 @@ body {
width: 20vw;
height: 30vw;
display: grid;
grid-template-rows: 1fr 3fr;
grid-template-columns: 1fr;
grid-template-rows: 1fr 1fr 2fr;
grid-template-columns: 1fr 1fr;
grid-gap: 1vw;
padding: 1vw;
}

#ButtonBLE {
#ble-button {
background-color: rgb(189, 188, 188);
border-radius: 1vw;
font-size: 2vw;
font-size: 4vw;
grid-row: 1;
grid-column: 1;
cursor: pointer;
border: none;
color: #e6e5e5;
text-align: center;
transition: background-color 0.3s, transform 0.1s, box-shadow 0.3s;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
}
#ble-button:hover {
background-color: rgb(121, 121, 121);
}
#ble-button:active {
background-color: rgb(159, 159, 159);
transform: translateY(2px);
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}

#battery-level {
background-color: grey;
color: white;
border-radius: 1vw;
font-size: 2vw;
grid-row: 1;
grid-column: 2;
}

#ble-status {
background-color: black;
font-size: 2vw;
grid-row: 2;
grid-column: 1;
grid-column: span 2;
}


#mobile-button button {
font-size: 5vw;
background-color: grey;
Expand Down Expand Up @@ -196,6 +228,7 @@ body {
padding: 0.5vw;
grid-column-gap: 0.5vw;
grid-template-columns: 2fr 1fr;
grid-column: span 2;
background-color: grey;
border-radius: 1vw;
justify-content: center;
Expand Down

0 comments on commit ef06796

Please sign in to comment.