-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.html
184 lines (160 loc) · 5.89 KB
/
index.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Arduino Light Control</title>
<style>
#red {border: solid 5px red;}
#red.on {background-color: red;}
#yellow {border: solid 5px yellow;}
#yellow.on {background-color: yellow;}
#blue {border: solid 5px blue;}
#blue.on {background-color: blue;}
#green {border: solid 5px green;}
#green.on {background-color: green;}
button {
font-size:80px;
padding: 20px;
}
</style>
</head>
<body>
<button id="connect">Connect</button>
<div id="controls" style="display:none">
<button id="red" data-num="1">RED</button>
<button id="yellow" data-num="2">YELLOW</button>
<button id="blue" data-num="4">BLUE</button>
<button id="green" data-num="8">GREEN</button>
</div>
<img src="./hand-pointer-svgrepo-com.svg" style="width: 100px; height: 100px; display: none" id="pointer"/>
<script>
let device;
let characteristic;
let currentColorValue;
document.getElementById('connect').addEventListener('click', async () => {
try {
//const btPermission = await navigator.permissions.query({ name: "bluetooth" });
//if (btPermission.state !== "denied") {
// console.log("HELLO YES")
//}
device = await navigator.bluetooth.requestDevice({
filters: [{services: ['cae55316-6575-413c-9858-0f76c95f6590']}]});
device.addEventListener('gattserverdisconnected', () => {
controls.style.display = "none";
connect.style.display = "block";
});
const server = await device.gatt.connect();
console.log("server is connected")
const service = await server.getPrimaryService('cae55316-6575-413c-9858-0f76c95f6590');
console.log("service is connected");
setupJoystick(service);
characteristic = await service.getCharacteristic('bd13c171-c34c-46ef-9078-70fd20719d31');
const colors = await getColors();
updateColors(colors);
controls.style.display = "block";
connect.style.display = "none";
} catch (error) {
console.error('Error:', error);
}
});
async function getColors(){
const value = await characteristic.readValue();
const bitmask = value.getUint8(0);
return bitmaskToColors(bitmask);
}
function bitmaskToColors(bitmask){
return {
red: !!(bitmask & 1),
yellow: !!(bitmask & 2),
blue: !!(bitmask & 4),
green: !!(bitmask & 8),
}
}
function colorsToBitMask(colors){
return (colors.red ? 1 : 0)+
2*(colors.yellow ? 1 : 0)+
4*(colors.blue ? 1 : 0)+
8*(colors.green ? 1 : 0)
}
function updateColors(colors){
Object.keys(colors).forEach((color) => {
const show = colors[color];
const el = document.getElementById(color);
if( show ){
el.classList.add("on");
} else {
el.classList.remove("on");
}
})
}
document.getElementById('controls').addEventListener('click', async (event) => {
const maskString = event.target.getAttribute("data-num");
if(maskString) {
const maskNumber = parseInt(maskString, 10);
const colors = await getColors();
const isOn = event.target.classList.contains("on");
let newValue;
if(isOn) {
const clearMask = ~maskNumber;
newValue = colorsToBitMask(colors) & clearMask;
} else {
newValue = colorsToBitMask(colors) | maskNumber;
}
await characteristic.writeValue(new Uint8Array([newValue]));
updateColors(bitmaskToColors(newValue) );
}
})
async function setupJoystick(service) {
const characteristic = await service.getCharacteristic('629e077d-fa31-47b1-a681-a0fe99dd8493');
const result = await characteristic.startNotifications();
characteristic.addEventListener('characteristicvaluechanged', handleJoystickNotification);
pointer.style.display = "block"
pointer.style.position = "fixed";
}
let lastPressedValue = 0;
function handleJoystickNotification(event) {
const value = event.target.value;
// Decode x and y values from the 4-byte array
const xReadValue = value.getUint16(0, true); // Little-endian, start at byte 0
const yReadValue = value.getUint16(2, true); // Little-endian, start at byte 2
const buttonState = value.getUint8(4);
const xValue = yReadValue;
const yValue = 1023 - xReadValue;
const widthOfPointer = 40 / window.innerWidth;
const heightOfPointer = 0 / window.innerHeight;
//console.log('Joystick x:', xValue, 'y:', yValue);
// Here you can update the UI or handle joystick movements
const leftPercent = ( (xValue / 1023 - widthOfPointer));
const rightPercent = (yValue / 1023 - heightOfPointer)
pointer.style.left = leftPercent*100 +"%";
pointer.style.top = rightPercent*100 +"%"
if(lastPressedValue !== buttonState) {
lastPressedValue = buttonState;
if(buttonState === 1) {
triggerClick( (xValue / 1023) * window.innerWidth, (yValue / 1023) * window.innerHeight )
}
}
}
function triggerClick(x, y) {
// Create a new mouse event
const clickEvent = new MouseEvent('click', {
bubbles: true,
cancelable: true,
clientX: x,
clientY: y,
view: window
});
// Find the element at the specified coordinates
const elements = document.elementsFromPoint(x, y);
element = elements.filter( e => e !== pointer)[0];
console.log("trying to click", x, y, element);
// Dispatch the click event on the element if it exists
if (element) {
element.dispatchEvent(clickEvent);
} else {
console.warn("No element found at specified coordinates.");
}
}
</script>
</body>
</html>