502 lines
16 KiB
HTML
502 lines
16 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>ATA Firmware Update</title>
|
|
<style>
|
|
body {
|
|
font-family: Arial, sans-serif;
|
|
margin: 0;
|
|
padding: 20px;
|
|
background-color: #f4f4f4;
|
|
text-align: center;
|
|
}
|
|
|
|
h1 {
|
|
font-size: 22px;
|
|
margin-bottom: 20px;
|
|
}
|
|
|
|
.status-container {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: left;
|
|
margin-bottom: 15px;
|
|
}
|
|
|
|
.status-indicator-ble {
|
|
width: 20px;
|
|
height: 20px;
|
|
border-radius: 50%;
|
|
background-color: gray;
|
|
margin-right: 10px;
|
|
}
|
|
|
|
.status-indicator-wifi {
|
|
width: 20px;
|
|
height: 20px;
|
|
border-radius: 50%;
|
|
background-color: gray;
|
|
margin-right: 10px;
|
|
}
|
|
|
|
.status-indicator-internet {
|
|
width: 20px;
|
|
height: 20px;
|
|
border-radius: 50%;
|
|
background-color: gray;
|
|
margin-right: 10px;
|
|
}
|
|
|
|
.btn-container {
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
justify-content: center;
|
|
gap: 10px;
|
|
margin-bottom: 10px;
|
|
}
|
|
|
|
/* Adds space above the WiFi Connect button */
|
|
.btn-container.wifi {
|
|
margin-top: 20px;
|
|
}
|
|
|
|
button {
|
|
flex: 1;
|
|
max-width: 130px;
|
|
padding: 10px;
|
|
font-size: 16px;
|
|
border: none;
|
|
border-radius: 5px;
|
|
cursor: pointer;
|
|
background-color: #007bff;
|
|
color: white;
|
|
transition: background 0.3s ease;
|
|
}
|
|
|
|
button:disabled {
|
|
background-color: #ccc;
|
|
}
|
|
|
|
button:hover:not(:disabled) {
|
|
background-color: #0056b3;
|
|
}
|
|
|
|
textarea {
|
|
width: 100%;
|
|
height: 300px;
|
|
font-size: 14px;
|
|
padding: 10px;
|
|
border-radius: 5px;
|
|
border: 1px solid #ccc;
|
|
resize: none;
|
|
}
|
|
|
|
.input-container {
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
gap: 10px;
|
|
margin-top: 15px;
|
|
}
|
|
|
|
input {
|
|
width: 90%;
|
|
max-width: 300px;
|
|
padding: 10px;
|
|
font-size: 16px;
|
|
border: 1px solid #ccc;
|
|
border-radius: 5px;
|
|
text-align: center;
|
|
}
|
|
|
|
input::placeholder {
|
|
text-align: center;
|
|
}
|
|
|
|
@media (max-width: 480px) {
|
|
body {
|
|
padding: 15px;
|
|
}
|
|
|
|
h1 {
|
|
font-size: 20px;
|
|
}
|
|
|
|
button {
|
|
font-size: 14px;
|
|
padding: 8px;
|
|
}
|
|
|
|
input, textarea {
|
|
font-size: 14px;
|
|
}
|
|
}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
|
|
<h1>ATA Firmware Update</h1>
|
|
|
|
<!-- Status Indicators -->
|
|
<div class="status-container">
|
|
<span class="status-indicator-ble"></span>
|
|
<label id="status-ble-connection">Device: ...</label>
|
|
</div>
|
|
|
|
<div class="status-container">
|
|
<span class="status-indicator-wifi"></span>
|
|
<label id="status-wifi-client">Wifi Client: ...</label>
|
|
</div>
|
|
|
|
<div class="status-container">
|
|
<span class="status-indicator-internet"></span>
|
|
<label id="status-internet">Internet: ...</label>
|
|
</div>
|
|
|
|
<div class="status-container">
|
|
<label id="status-current-version">Curr Version: ...</label>
|
|
</div>
|
|
<div class="status-container">
|
|
<label id="status-new-version">New Version: ...</label>
|
|
</div>
|
|
|
|
<!-- Buttons -->
|
|
<div class="btn-container">
|
|
<button id="bleConnectBtn">Connect</button>
|
|
<button id="checkStatusBtn" disabled>Check Status</button>
|
|
</div>
|
|
|
|
<!-- Log Area -->
|
|
<textarea id="logArea" readonly></textarea>
|
|
|
|
<div class="btn-container">
|
|
<button id="checkVersionBtn" disabled>Check Version</button>
|
|
<button id="startUpgradeBtn" disabled>Start Update</button>
|
|
</div>
|
|
|
|
<!-- Wi-Fi Input Fields -->
|
|
<div class="input-container">
|
|
<input type="text" id="wifissid" name="wifissid" placeholder="Enter WiFi SSID" required>
|
|
<input type="password" id="wifipassword" name="wifipassword" placeholder="Enter WiFi Password" required>
|
|
<div style="display: flex; align-items: center; gap: 5px;">
|
|
<input type="checkbox" id="showPassword" style="width: auto;">
|
|
<label for="showPassword">Show Password</label>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Added margin-top above this button -->
|
|
<div class="btn-container wifi">
|
|
<button id="wifiConnectBtn" disabled>Connect Wifi</button>
|
|
</div>
|
|
|
|
<script>
|
|
// Constants
|
|
const BLE_SERVER_NAME = "ATALIGHTS"; // Replace with your server name
|
|
const BLE_SERVICE_UUID = "abcdef01-2345-6789-1234-56789abcdef0"; // Replace with your service UUID
|
|
const BLE_CHARACTERISTIC1_UUID = "abcdef01-2345-6789-1234-56789abcdef1"; // Replace with your characteristic UUID
|
|
const BLE_CHARACTERISTIC2_UUID = "abcdef02-2345-6789-1234-56789abcdef1"; // Replace with your characteristic UUID
|
|
|
|
let bleDevice = null;
|
|
let bleCharacteristic1 = null;
|
|
let bleCharacteristic2 = null;
|
|
let bleConnected = false;
|
|
|
|
const WIFI_STAT = { WIFI_DISCONNECTED:0, WIFI_BAD_CREDS:1, WIFI_NO_AP:2, WIFI_CONNECTED:3 };
|
|
|
|
let updatePacket = {
|
|
wifiConnected: false,
|
|
wifiOnline: false,
|
|
wifiIP: [0, 0, 0, 0],
|
|
currVersion: [0, 0, 0],
|
|
newVersion: [0, 0, 0]
|
|
};
|
|
|
|
// Log messages to the textarea
|
|
function logMessage(message) {
|
|
const logArea = document.getElementById('logArea');
|
|
logArea.value += message + '\n';
|
|
logArea.scrollTop = logArea.scrollHeight;
|
|
}
|
|
|
|
// Function to scan for BLE devices
|
|
async function scanForDevices() {
|
|
logMessage('Scanning for BLE devices...');
|
|
try {
|
|
const device = await navigator.bluetooth.requestDevice({
|
|
acceptAllDevices: true,
|
|
optionalServices: [BLE_SERVICE_UUID]
|
|
});
|
|
|
|
if (device) {
|
|
logMessage(`Found device: ${device.name || "Unnamed"} (ID: ${device.id})`);
|
|
} else {
|
|
logMessage('No devices found.');
|
|
}
|
|
} catch (error) {
|
|
logMessage(`Scan failed: ${error.message}`);
|
|
}
|
|
}
|
|
|
|
// Function to connect to the BLE server
|
|
async function connectToBle() {
|
|
try {
|
|
bleDevice = await navigator.bluetooth.requestDevice({
|
|
filters: [{ name: BLE_SERVER_NAME }],
|
|
optionalServices: [BLE_SERVICE_UUID]
|
|
});
|
|
|
|
//logMessage(`Connecting to ${bleDevice.name}`);
|
|
const server = await bleDevice.gatt.connect();
|
|
//await server.setPreferredMtu(247); // Request larger MTU size
|
|
|
|
const service = await server.getPrimaryService(BLE_SERVICE_UUID);
|
|
|
|
bleCharacteristic1 = await service.getCharacteristic(BLE_CHARACTERISTIC1_UUID);
|
|
|
|
// Subscribe to notifications
|
|
//await bleCharacteristic1.startNotifications();
|
|
|
|
// Add event listener for incoming notifications
|
|
//bleCharacteristic1.addEventListener('characteristicvaluechanged', handleChar1Notifications);
|
|
|
|
|
|
//logMessage('Getting characteristic...');
|
|
bleCharacteristic2 = await service.getCharacteristic(BLE_CHARACTERISTIC2_UUID);
|
|
|
|
// Subscribe to notifications
|
|
await bleCharacteristic2.startNotifications();
|
|
|
|
// Add event listener for incoming notifications
|
|
bleCharacteristic2.addEventListener('characteristicvaluechanged', (event) => {
|
|
const value = event.target.value;
|
|
const decoder = new TextDecoder();
|
|
const decodedValue = decoder.decode(value);
|
|
logMessage('--> ' + decodedValue);
|
|
});
|
|
|
|
bleConnected = true;
|
|
document.getElementById('bleConnectBtn').disabled = true;
|
|
document.querySelector('.status-indicator-ble').style.backgroundColor = 'green';
|
|
document.getElementById('status-ble-connection').textContent = 'Device: Connected';
|
|
document.getElementById('wifiConnectBtn').disabled = false;
|
|
document.getElementById('checkStatusBtn').disabled = false;
|
|
logMessage(`Connected to ${bleDevice.name}`);
|
|
|
|
await readPacket();
|
|
processUpdatePacket(updatePacket);
|
|
|
|
} catch (error) {
|
|
if (error.message.includes("cancelled")) {
|
|
logMessage("Connection cancelled by user.");
|
|
} else {
|
|
logMessage(`Connection failed: ${error.message}`);
|
|
}
|
|
}
|
|
}
|
|
|
|
async function sendPacket(packetMsg) {
|
|
if (!bleCharacteristic1) {
|
|
console.log("Cannot send packet: Not connected to BLE server.");
|
|
return;
|
|
}
|
|
|
|
const maxRetries = 3;
|
|
const retryDelay = 1000; // 1 second
|
|
let attempt = 0;
|
|
|
|
while (attempt < maxRetries) {
|
|
try {
|
|
//logMessage(`Sending request: ${packetMsg} (Attempt ${attempt + 1})`);
|
|
const encoder = new TextEncoder();
|
|
await bleCharacteristic1.writeValueWithResponse(encoder.encode(packetMsg));
|
|
//console.log("Request sent successfully");
|
|
return;
|
|
} catch (error) {
|
|
console.error(`Failed to send packet: ${error.message}`);
|
|
attempt++;
|
|
if (attempt < maxRetries) {
|
|
console.log(`Retrying in ${retryDelay / 1000} seconds...`);
|
|
await new Promise(resolve => setTimeout(resolve, retryDelay));
|
|
} else {
|
|
console.error("Max retries reached. Failed to send request.");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
async function readPacket() {
|
|
if (!bleCharacteristic1) {
|
|
console.log("Cannot read packet: Not connected to BLE server.");
|
|
return;
|
|
}
|
|
|
|
const maxRetries = 3;
|
|
const retryDelay = 1000; // 1 second
|
|
let attempt = 0;
|
|
|
|
while (attempt < maxRetries) {
|
|
try {
|
|
const value = await bleCharacteristic1.readValue();
|
|
const data = new Uint8Array(value.buffer);
|
|
if (data.length === 12) {
|
|
updatePacket.wifiConnected = data[0] !== 0;
|
|
updatePacket.wifiOnline = data[1] !== 0;
|
|
updatePacket.wifiIP = [data[2], data[3], data[4], data[5]];
|
|
updatePacket.currVersion = [data[6], data[7], data[8]];
|
|
updatePacket.newVersion = [data[9], data[10], data[11]];
|
|
|
|
//processUpdatePacket(updatePacket);
|
|
return;
|
|
}
|
|
console.log("Invalid packet length");
|
|
return;
|
|
} catch (error) {
|
|
console.error(`Failed to read packet: ${error.message}`);
|
|
attempt++;
|
|
if (attempt < maxRetries) {
|
|
console.log(`Retrying in ${retryDelay / 1000} seconds...`);
|
|
await new Promise(resolve => setTimeout(resolve, retryDelay));
|
|
} else {
|
|
console.error("Max retries reached. Failed to read packet.");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Process update packet
|
|
function processUpdatePacket(packet) {
|
|
// Process the packet data
|
|
//console.log("Processing update packet:", packet);
|
|
if(packet.wifiConnected === true) {
|
|
if(packet.wifiConnected && packet.wifiIP[0] > 0) {
|
|
document.getElementById('status-wifi-client').textContent = 'Wifi Client: Connected (' + packet.wifiIP.join('.') + ')';
|
|
} else {
|
|
document.getElementById('status-wifi-client').textContent = 'Wifi Client: Connected';
|
|
}
|
|
document.querySelector('.status-indicator-wifi').style.backgroundColor = 'green';
|
|
} else {
|
|
document.getElementById('status-wifi-client').textContent = 'Wifi Client: ...';
|
|
document.querySelector('.status-indicator-wifi').style.backgroundColor = 'gray';
|
|
}
|
|
|
|
if(packet.wifiOnline === true) {
|
|
document.getElementById('status-internet').textContent = 'Online';
|
|
document.querySelector('.status-indicator-internet').style.backgroundColor = 'green';
|
|
document.getElementById('checkVersionBtn').disabled = false;
|
|
|
|
} else {
|
|
document.getElementById('status-internet').textContent = 'Offline';
|
|
document.querySelector('.status-indicator-internet').style.backgroundColor = 'gray';
|
|
document.getElementById('checkVersionBtn').disabled = true;
|
|
}
|
|
|
|
if (packet.currVersion[0] > 0) {
|
|
document.getElementById('status-current-version').textContent = 'Curr Version: ' + packet.currVersion.join('.');
|
|
} else {
|
|
document.getElementById('status-current-version').textContent = 'Curr Version: ...';
|
|
}
|
|
|
|
if (packet.newVersion[0] > 0) {
|
|
document.getElementById('status-new-version').textContent = 'New Version: ' + packet.newVersion.join('.');
|
|
|
|
if(packet.wifiOnline && packet.newVersion[0] > packet.currVersion[0] ||
|
|
(packet.newVersion[0] === packet.currVersion[0] && packet.newVersion[1] > packet.currVersion[1]) ||
|
|
(packet.newVersion[0] === packet.currVersion[0] && packet.newVersion[1] === packet.currVersion[1] && packet.newVersion[2] > packet.currVersion[2])) {
|
|
|
|
//enable start upgrade button
|
|
logMessage("New Version Available:");
|
|
document.getElementById('checkVersionBtn').disabled = true;
|
|
document.getElementById('startUpgradeBtn').disabled = false;
|
|
} else {
|
|
//disable start upgrade button
|
|
document.getElementById('checkVersionBtn').disabled = false;
|
|
document.getElementById('startUpgradeBtn').disabled = true;
|
|
logMessage("New Version: Not Available");
|
|
}
|
|
} else {
|
|
document.getElementById('status-new-version').textContent = 'New Version: ...';
|
|
}
|
|
|
|
}
|
|
|
|
//BLE_Characteristic.addEventListener('characteristicvaluechanged', handleNotifications);
|
|
function handleChar1Notifications(event) {
|
|
const data = new Uint8Array(event.data);
|
|
|
|
if (data.length !== 12) { // 1 byte for id, 4 bytes for booleans, 4 bytes for wifiIP, 3 bytes for currVersion, 3 bytes for newVersion
|
|
console.log("Invalid packet length");
|
|
return;
|
|
}
|
|
|
|
// Update existing updatePacket object instead of creating new one
|
|
updatePacket.wifiConnected = data[0] !== 0;
|
|
updatePacket.internetAvailable = data[1] !== 0;
|
|
updatePacket.wifiIP = [data[2], data[3], data[4], data[5]];
|
|
updatePacket.currVersion = [data[6], data[7], data[8]];
|
|
updatePacket.newVersion = [data[9], data[10], data[11]];
|
|
|
|
processUpdatePacket(updatePacket);
|
|
}
|
|
|
|
document.getElementById('showPassword').addEventListener('change', function() {
|
|
const passwordInput = document.getElementById('wifipassword');
|
|
passwordInput.type = this.checked ? 'text' : 'password';
|
|
});
|
|
|
|
// Event listeners for buttons
|
|
document.getElementById('bleConnectBtn').addEventListener('click', connectToBle);
|
|
document.getElementById('checkStatusBtn').addEventListener('click', async () => {
|
|
if (bleCharacteristic1) {
|
|
await readPacket();
|
|
processUpdatePacket(updatePacket);
|
|
} else {
|
|
logMessage('BLE device not connected.');
|
|
}
|
|
});
|
|
document.getElementById('checkVersionBtn').addEventListener('click', async () => {
|
|
await sendPacket('version-check');
|
|
// loop and monitor the the updatePacket.newVersion
|
|
success = false;
|
|
for (let i = 0; i < 20; i++) {
|
|
await readPacket();
|
|
if (updatePacket.newVersion[0] > 0) {
|
|
break;
|
|
}
|
|
|
|
await new Promise(resolve => setTimeout(resolve, 1000));
|
|
}
|
|
if(success) {
|
|
processUpdatePacket(updatePacket);
|
|
logMessage("New Version: Available");
|
|
} else {
|
|
logMessage("New Version: Not Available");
|
|
}
|
|
|
|
});
|
|
document.getElementById('wifiConnectBtn').addEventListener('click', async () => {
|
|
const ssid = document.getElementById('wifissid').value;
|
|
const password = document.getElementById('wifipassword').value;
|
|
if (ssid && password) {
|
|
// Send credentials to the device
|
|
jsonString = ' {"ssid":"' + ssid + '","pass":"' + password + '"} ';
|
|
await sendPacket('wifi-connect' + jsonString);
|
|
|
|
await readPacket();
|
|
processUpdatePacket(updatePacket);
|
|
} else {
|
|
alert('Please enter both SSID and password.');
|
|
}
|
|
|
|
|
|
});
|
|
document.getElementById('startUpgradeBtn').addEventListener('click', async () => {
|
|
await sendPacket('upgrade-start');
|
|
});
|
|
|
|
processUpdatePacket(updatePacket);
|
|
</script>
|
|
</body>
|
|
</html>
|