diff --git a/data/ata-boothifier-upgrade(updated).html b/data/ata-boothifier-upgradeV2.html similarity index 90% rename from data/ata-boothifier-upgrade(updated).html rename to data/ata-boothifier-upgradeV2.html index de07c66..d95fd0b 100644 --- a/data/ata-boothifier-upgrade(updated).html +++ b/data/ata-boothifier-upgradeV2.html @@ -162,18 +162,26 @@ +
+ +
+ +
+ +
+
- - + +
- - + +
@@ -181,14 +189,14 @@
- +
- +
+ + diff --git a/firmware_update/GenUpdateV2.py b/firmware_update/GenUpdateV2.py new file mode 100644 index 0000000..38dbbf8 --- /dev/null +++ b/firmware_update/GenUpdateV2.py @@ -0,0 +1,202 @@ +import os +import shutil +import hashlib +import json +from typing import Iterable, List, Optional +import datetime + +def copy_folder_to_destination(src_path: str, dest_path: str, skip_dirs: Optional[Iterable[str]] = None, skip_files: Optional[Iterable[str]] = None) -> None: + # Ensure the destination directory exists + os.makedirs(os.path.dirname(dest_path), exist_ok=True) + + # Remove existing folder if present + if os.path.exists(dest_path): + shutil.rmtree(dest_path) + + # Create destination directory + os.makedirs(dest_path) + + # Walk through source directory + for root, dirs, files in os.walk(src_path): + # Remove directories to skip from dirs list + if skip_dirs: + dirs[:] = [d for d in dirs if d not in skip_dirs] + + # Calculate relative path + rel_path = os.path.relpath(root, src_path) + dest_dir = os.path.join(dest_path, rel_path) + + # Create corresponding destination directory + os.makedirs(dest_dir, exist_ok=True) + + # Copy files that aren't in skip_files + for file in files: + if skip_files and file in skip_files: + continue + src_file = os.path.join(root, file) + dest_file = os.path.join(dest_dir, file) + shutil.copy2(src_file, dest_file) + +def calculate_md5(file_path: str) -> str: + hash_md5 = hashlib.md5() + with open(file_path, "rb") as f: + for chunk in iter(lambda: f.read(4096), b""): + hash_md5.update(chunk) + return hash_md5.hexdigest() + +def get_file_size(file_path: str) -> int: + return os.path.getsize(file_path) + +def update_json_file(json_array: List[dict], folder_path: str) -> None: + # Create new data array for files + file_array = [] + + # Walk through the copied folder and collect file details + for root, _, files in os.walk(folder_path): + for file in files: + file_path = os.path.join(root, file) + relative_path = os.path.relpath(file_path, folder_path) + + # Replace backslashes with forward slashes + relative_path = relative_path.replace('\\', '/') + + # Build remote/local using forward slashes only + file_entry = { + "remote": f"data/{relative_path}", + "local": f"/{relative_path}", + "md5": calculate_md5(file_path), + "size": get_file_size(file_path) + } + file_array.append(file_entry) + + # Replace the contents of the input json_array with new data + json_array.clear() + json_array.extend(file_array) + + +def perform_data_copy(src_path: str, dest_path: str, skip_dirs: Optional[Iterable[str]] = None, skip_files: Optional[Iterable[str]] = None) -> bool: + # Check if the source folder exists + if not os.path.isdir(src_path): + print(f"Source folder does not exist: {src_path}") + return False + copy_folder_to_destination(src_path, dest_path, skip_dirs, skip_files) + print("Data folder copied successfully.") + return True + + +def main(): + + here_path = os.path.dirname(os.path.abspath(__file__)) + project_path = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) + + # Path of the folder to copy (you can modify this) + src_folder_name = "data" + src_path = os.path.join(project_path, src_folder_name) + #print(f"source path: {src_path}") + + # Path of the destination folder + dest_folder_name = "firmware_update\\latest\\data" + dest_path = os.path.join(project_path, dest_folder_name) + #print(f"destination path: {dest_path}") + + # Path of the firmware binary file + bin_name = ".pio\\build\\esp32s3dev\\firmware.bin" + + # Skip these directories + skip_dirs = ["boards", "booths"] + + # Skip these files + skip_files = ["wifi.json", "system.json", "luma-stiks.json", ] + + + # Allow non-interactive mode via environment variable (set NON_INTERACTIVE=y to auto 'y') + non_interactive = os.environ.get("NON_INTERACTIVE", "n").lower() in ("1", "y", "yes", "true") + + file_choice = os.environ.get("UPDATE_FILES") if non_interactive else input("Do you want to update the files? (y/n): ") + if file_choice is None: + file_choice = "n" + file_choice = file_choice.strip().lower() + + + # *********************** Copy Data Files *********************** + copied = False + if file_choice == "y": + copied = perform_data_copy(src_path, dest_path, skip_dirs, skip_files) + + + # *********************** Copy Binary file *********************** + fw_choice = os.environ.get("UPDATE_FIRMWARE") if non_interactive else input("Do you want to update the firmware? (y/n): ") + if fw_choice is None: + fw_choice = "n" + fw_choice = fw_choice.strip().lower() + if fw_choice == "y": + # Copy firmware.bin to the destination + bin_path = os.path.join(project_path, bin_name) + if not os.path.isfile(bin_path): + print(f"Firmware binary not found: {bin_path}") + else: + shutil.copy(bin_path, here_path) + print("firmware.bin copied successfully.") + + + + # *********************** Process update.json *********************** + # Update the JSON file + #json_path = os.path.join(here_path, "update.json") + json_path = os.path.join(here_path, "latest", "update.json") + print(f"json path: {json_path}") + + # Read existing JSON + if not os.path.isfile(json_path): + print(f"update.json not found at {json_path}; creating a new one.") + json_doc = {"files": [], "firmware": {"md5": "", "size": 0}} + else: + with open(json_path, "r") as f: + try: + json_doc = json.load(f) + except json.JSONDecodeError: + print("Invalid JSON file! Aborting.") + return + + # Ensure required keys exist + json_doc.setdefault("files", []) + json_doc.setdefault("firmware", {"md5": "", "size": 0}) + + + # process the files array + #if update_files.lower() == "y": + if file_choice == "y": + if not copied: + print("Skipping file list update because data copy failed.") + else: + json_files_array = json_doc["files"] + update_json_file(json_files_array, dest_path) + #print(f"Folder {os.path.basename(src_path)} processed successfully.") + + + # *********************** Process firmwware.bin in update.json *********************** + # process the firmware + if fw_choice == "y": + json_firmware = json_doc["firmware"] + firmware_path = os.path.join(here_path, "firmware.bin") + if os.path.isfile(firmware_path): + json_firmware["md5"] = calculate_md5(firmware_path) + json_firmware["size"] = get_file_size(firmware_path) + else: + print("Firmware file missing; firmware section not updated.") + + + # *********************** Update release date, time in update.json *********************** + now = datetime.datetime.now() + json_doc["release_date"] = now.strftime("%Y-%m-%d") + json_doc["release_time"] = now.strftime("%H:%M:%S") + + + # Write updated JSON + with open(json_path, "w") as f: + json.dump(json_doc, f, indent=4) + + print("update.json updated successfully.") + +if __name__ == "__main__": + main() diff --git a/firmware_update/UploadToMinioV2.py b/firmware_update/UploadToMinioV2.py new file mode 100644 index 0000000..6f68fec --- /dev/null +++ b/firmware_update/UploadToMinioV2.py @@ -0,0 +1,337 @@ +#!/usr/bin/env python3 +"""Upload firmware, manifest, and data assets to a MinIO (S3-compatible) bucket. + +Features preserved from original GCS script: + - Optional backup (copies existing objects under destination prefix to timestamped folder under backups/) + - Upload firmware.bin, update.json, and recursively mirror a data directory + - Cache-Control set to disable caching on clients + +Switches from google.cloud.storage to boto3 (S3 API) for MinIO compatibility. +""" +import os +import sys +import datetime +import json +from pathlib import Path + +try: + import boto3 + from botocore.exceptions import ClientError + from botocore.config import Config +except ImportError: + print("ERROR: boto3 is required. Install with: pip install boto3") + sys.exit(1) + +# ============================================================================= +# CONFIGURATION CONSTANTS (edit as needed or supply via environment variables) +# ============================================================================= + +CREATE_BACKUP = False +UPLOAD_FIRMWARE = True +UPLOAD_MANIFEST = True +UPLOAD_DATA = True + +# Bucket / endpoint configuration +BUCKET_NAME = os.getenv('MINIO_BUCKET', 'boothifier') +DESTINATION_DIR = os.getenv('MINIO_DEST_PREFIX', 'latest') # prefix inside bucket +BACKUPS_DIR = os.getenv('MINIO_BACKUPS_PREFIX', 'backups') + +LOCAL_ROOT_PATH = Path(__file__).parent.resolve() + +# Optional service account style JSON key (generated by MinIO Console). Expected fields: +# {"url":"https://minio.example.com/api/v1/service-account-credentials","accessKey":"...","secretKey":"...","api":"s3v4","path":"auto"} +MINIO_KEY_FILE = LOCAL_ROOT_PATH / 'minio-boothifier-key.json' + +# Defaults before loading file / env +_json_access = None +_json_secret = None +_json_url = None + +def _load_json_key(): + global _json_access, _json_secret, _json_url + try: + if MINIO_KEY_FILE.is_file(): + with open(MINIO_KEY_FILE, 'r', encoding='utf-8') as fh: + data = json.load(fh) + _json_access = data.get('accessKey') or None + _json_secret = data.get('secretKey') or None + _json_url = data.get('url') or None + except Exception as e: + print(f"WARN: Failed to load MinIO key file '{MINIO_KEY_FILE.name}': {e}") + +_load_json_key() + +def _derive_endpoint(url_value: str) -> str: + if not url_value: + return 'https://s3-minio.boothwizard.com' + # Remove known API suffix if present (/api/...) + # e.g. https://s3-minio.boothwizard.com/api/v1/service-account-credentials -> https://s3-minio.boothwizard.com + parts = url_value.split('/api/') + return parts[0] if parts else url_value + +# MinIO credentials with precedence: ENV > JSON file > fallback +MINIO_ENDPOINT = os.getenv('MINIO_ENDPOINT') or _derive_endpoint(_json_url) +MINIO_ACCESS_KEY = os.getenv('MINIO_ACCESS_KEY') or _json_access or 'CHANGE_ME_ACCESS' +MINIO_SECRET_KEY = os.getenv('MINIO_SECRET_KEY') or _json_secret or 'CHANGE_ME_SECRET' +MINIO_REGION = os.getenv('MINIO_REGION', 'us-east-1') # MinIO ignores but boto3 wants some value + + # Addressing / SSL options +MINIO_ADDRESSING = os.getenv('MINIO_ADDRESSING_STYLE', 'path').lower() # 'path' or 'virtual' +MINIO_VERIFY_SSL = os.getenv('MINIO_TLS_VERIFY', '1') not in ('0','false','no') +MINIO_DEBUG = os.getenv('MINIO_DEBUG', '0') in ('1','true','yes') +MINIO_ALLOW_VARIANTS = os.getenv('MINIO_ALLOW_ENDPOINT_VARIANTS', '0') in ('1','true','yes') # normally false with nginx redirect + +LOCAL_FIRMWARE_PATH = str(LOCAL_ROOT_PATH / 'latest' / 'firmware.bin') +LOCAL_MANIFEST_PATH = str(LOCAL_ROOT_PATH / 'latest' / 'update.json') +LOCAL_DATA_DIRECTORY = str(LOCAL_ROOT_PATH / 'latest' / 'data') + +# ============================================================================= +# HELPERS +# ============================================================================= + +def s3_client(): + """Create an S3 client pointed at MinIO endpoint, forcing path-style unless overridden, with short timeouts.""" + addressing = 'path' if MINIO_ADDRESSING not in ('virtual','auto') else 'virtual' + cfg = Config( + s3={'addressing_style': addressing}, + signature_version='s3v4', + connect_timeout=3, + read_timeout=5, + retries={'max_attempts': 2} + ) + if MINIO_DEBUG: + masked_key = (MINIO_ACCESS_KEY[:3] + '...' + MINIO_ACCESS_KEY[-3:]) if MINIO_ACCESS_KEY else 'None' + print(f"[DEBUG] Creating client: endpoint={MINIO_ENDPOINT} addressing={addressing} verifySSL={MINIO_VERIFY_SSL} region={MINIO_REGION} accessKey={masked_key}") + return boto3.client( + 's3', + endpoint_url=MINIO_ENDPOINT, + aws_access_key_id=MINIO_ACCESS_KEY, + aws_secret_access_key=MINIO_SECRET_KEY, + region_name=MINIO_REGION, + verify=MINIO_VERIFY_SSL, + config=cfg, + ) + +def _endpoint_variants(base: str): + """Return endpoint variants only if explicitly allowed; otherwise just the base (nginx handles forwarding).""" + if not MINIO_ALLOW_VARIANTS: + return [base] + # Fallback to previous expanded logic if variants are enabled + try: + variants = [] + if not base: + return variants + base = base.rstrip('/') + proto_sep = '://' + if proto_sep in base: + scheme, rest = base.split(proto_sep,1) + else: + scheme, rest = 'https', base + host_port = rest + if ':' in host_port: + host, port = host_port.split(':',1) + else: + host, port = host_port, '' + variants.append(f"{scheme}://{host_port}") + common_ports = ['9000','443','80'] + for p in common_ports: + if port != p: + variants.append(f"{scheme}://{host}:{p}") + alt_scheme = 'http' if scheme == 'https' else 'https' + variants.append(f"{alt_scheme}://{host_port}") + for p in common_ports: + if port != p: + variants.append(f"{alt_scheme}://{host}:{p}") + seen = set() + uniq = [] + for v in variants: + if v not in seen: + uniq.append(v) + seen.add(v) + return uniq + except Exception: + return [base] + +def create_validated_client(): + """Validate (or create) client using only provided endpoint unless variants enabled.""" + global MINIO_ENDPOINT + primary = MINIO_ENDPOINT + variants = _endpoint_variants(primary) or [primary] + errors = [] + probe_bucket = BUCKET_NAME # we will head the target bucket directly + for candidate in variants: + saved = MINIO_ENDPOINT + MINIO_ENDPOINT = candidate + if MINIO_DEBUG: + print(f"[DEBUG] Probing endpoint candidate: {candidate}") + try: + c = s3_client() + try: + c.head_bucket(Bucket=probe_bucket) + if MINIO_DEBUG: + print(f"[DEBUG] head_bucket succeeded on {candidate} for '{probe_bucket}'.") + return c + except ClientError as e: + msg = str(e) + # Acceptable if bucket not found (we can create later) + if any(code in msg for code in ('404', 'NoSuchBucket', 'NotFound')): + if MINIO_DEBUG: + print(f"[DEBUG] Bucket not found on {candidate} (expected if first deploy). Using this endpoint.") + return c + if 'API Requests must be made to API port' in msg: + errors.append(f"{candidate}: wrong port (console endpoint)") + else: + errors.append(f"{candidate}: {msg}") + MINIO_ENDPOINT = saved + except Exception as ex: + errors.append(f"{candidate}: {ex}") + MINIO_ENDPOINT = saved + continue + print("ERROR: Could not validate any endpoint candidate.") + for e in errors: + print(' - ' + e) + print("Provide correct API endpoint (e.g. https://host:9000) via MINIO_ENDPOINT env var.") + sys.exit(3) + +def list_objects(client, prefix: str): + """Generator yielding object keys under a prefix (non-recursive listing with pagination).""" + kwargs = {'Bucket': BUCKET_NAME, 'Prefix': prefix} + while True: + resp = client.list_objects_v2(**kwargs) + for obj in resp.get('Contents', []): + yield obj['Key'] + if not resp.get('IsTruncated'): + break + kwargs['ContinuationToken'] = resp['NextContinuationToken'] + +def normalize_prefix(p: str) -> str: + p = p.strip('/') + return p + +def join_key(*parts: str) -> str: + parts_clean = [p.strip('/') for p in parts if p is not None and p != ''] + return '/'.join(parts_clean) + +def backup_existing_files(client, destination_prefix: str, backups_prefix: str, backup_folder: str): + if not destination_prefix: + prefix = '' + else: + prefix = destination_prefix + '/' + print(f"Scanning existing objects under '{prefix}' for backup...") + for key in list_objects(client, prefix): + if backups_prefix and key.startswith(backups_prefix + '/'): # Skip prior backups + continue + # relative path within destination + relative = key[len(prefix):] if prefix and key.startswith(prefix) else key + backup_key = join_key(backups_prefix, backup_folder, relative) + print(f"Backup copy: {key} -> {backup_key}") + client.copy_object( + Bucket=BUCKET_NAME, + CopySource={'Bucket': BUCKET_NAME, 'Key': key}, + Key=backup_key, + MetadataDirective='COPY' + ) + +def upload_file(client, local_path: str, key: str, cache_control: str = 'private, max-age=0, no-transform'): + if not os.path.isfile(local_path): + print(f"WARN: File missing, skipping: {local_path}") + return + print(f"Upload: {local_path} -> s3://{BUCKET_NAME}/{key}") + extra_args = { 'CacheControl': cache_control } + client.upload_file(local_path, BUCKET_NAME, key, ExtraArgs=extra_args) + +def upload_directory(client, local_directory: str, destination_prefix: str): + if not os.path.isdir(local_directory): + print(f"WARN: Data directory missing: {local_directory}") + return + for root, _, files in os.walk(local_directory): + for fname in files: + full = os.path.join(root, fname) + rel = os.path.relpath(full, local_directory) + key = join_key(destination_prefix, rel) + upload_file(client, full, key) + +def ensure_bucket(client): + """Ensure bucket exists; provide diagnostics if HeadBucket returns 400/other errors.""" + try: + client.head_bucket(Bucket=BUCKET_NAME) + if MINIO_DEBUG: + print(f"[DEBUG] Bucket '{BUCKET_NAME}' exists.") + return + except ClientError as e: + code = e.response.get('Error', {}).get('Code') + status = e.response.get('ResponseMetadata', {}).get('HTTPStatusCode') + print(f"HeadBucket failed (code={code}, status={status}).") + + # List buckets for diagnostics + try: + resp = client.list_buckets() + bucket_names = [b['Name'] for b in resp.get('Buckets', [])] + print(f"Available buckets: {bucket_names or 'None'}") + except Exception as le: + print(f"WARN: list_buckets failed: {le}") + + if code in ('404', 'NoSuchBucket', 'NotFound'): + print(f"Bucket '{BUCKET_NAME}' not found. Attempting to create...") + try: + client.create_bucket(Bucket=BUCKET_NAME) + print(f"Created bucket '{BUCKET_NAME}'.") + return + except ClientError as ce: + print(f"ERROR: Cannot create bucket: {ce}") + sys.exit(2) + + if status == 400: + print("HINTS: \n - Verify endpoint URL (MINIO_ENDPOINT).\n - Ensure no trailing slash in endpoint.\n - Check that TLS verify matches server cert (set MINIO_TLS_VERIFY=0 to test).\n - Confirm bucket name is correct and DNS compatible.\n - Credentials may lack permission: verify access key policies.") + + # Retry once forcing path style if not already + if MINIO_ADDRESSING != 'path': + print("Retrying with path-style addressing...") + os.environ['MINIO_ADDRESSING_STYLE'] = 'path' + new_client = s3_client() + try: + new_client.head_bucket(Bucket=BUCKET_NAME) + print("Second attempt succeeded with path-style addressing.") + return + except ClientError as e2: + print(f"Second HeadBucket attempt failed: {e2}") + print(f"ERROR: head_bucket ultimately failed: {e}") + sys.exit(2) + +# ============================================================================= +# MAIN +# ============================================================================= + +def main(): + dest_prefix = normalize_prefix(DESTINATION_DIR) + backups_prefix = normalize_prefix(BACKUPS_DIR) if BACKUPS_DIR else '' + client = create_validated_client() + if MINIO_DEBUG: + print("[DEBUG] Starting ensure_bucket phase...") + ensure_bucket(client) + + if CREATE_BACKUP: + ts = datetime.datetime.now().strftime('%Y%m%d_%H%M%S') + backup_folder = f"backup_{ts}" + print(f"Creating backup under '{backups_prefix}/{backup_folder}' from prefix '{dest_prefix}'") + backup_existing_files(client, dest_prefix, backups_prefix, backup_folder) + + # Firmware + if UPLOAD_FIRMWARE: + firmware_key = join_key(dest_prefix, 'firmware.bin') if dest_prefix else 'firmware.bin' + upload_file(client, LOCAL_FIRMWARE_PATH, firmware_key) + + # Manifest + if UPLOAD_MANIFEST: + manifest_key = join_key(dest_prefix, 'update.json') if dest_prefix else 'update.json' + upload_file(client, LOCAL_MANIFEST_PATH, manifest_key) + + # Data directory + if UPLOAD_DATA: + data_prefix = join_key(dest_prefix, 'data') if dest_prefix else 'data' + upload_directory(client, LOCAL_DATA_DIRECTORY, data_prefix) + + print("All uploads complete.") + +if __name__ == '__main__': + main() diff --git a/firmware_update/latest/data/ata-boothifier-upgrade.html b/firmware_update/latest/data/ata-boothifier-upgrade.html index 3821ad8..3327522 100644 --- a/firmware_update/latest/data/ata-boothifier-upgrade.html +++ b/firmware_update/latest/data/ata-boothifier-upgrade.html @@ -400,18 +400,17 @@ if (packet.newVersion[0] > 0) { document.getElementById('status-new-version').textContent = 'New Version: ' + packet.newVersion.join('.'); - + document.getElementById('checkVersionBtn').disabled = true; + 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"); } @@ -458,10 +457,12 @@ document.getElementById('checkVersionBtn').addEventListener('click', async () => { await sendPacket('version-check'); // loop and monitor the the updatePacket.newVersion + await new Promise(resolve => setTimeout(resolve, 2000)); success = false; for (let i = 0; i < 20; i++) { await readPacket(); if (updatePacket.newVersion[0] > 0) { + success = true; break; } @@ -492,9 +493,15 @@ }); document.getElementById('startUpgradeBtn').addEventListener('click', async () => { - await sendPacket('upgrade-start'); + try { + await sendPacket('upgrade-start'); + logMessage("Upgrade Starting... Please wait."); + } catch (error) { + logMessage(`Error starting upgrade: ${error.message}`); + } }); + // Initial call to process the update packet with defaults processUpdatePacket(updatePacket); diff --git a/firmware_update/latest/data/ata-boothifier-upgradeV2.html b/firmware_update/latest/data/ata-boothifier-upgradeV2.html new file mode 100644 index 0000000..d95fd0b --- /dev/null +++ b/firmware_update/latest/data/ata-boothifier-upgradeV2.html @@ -0,0 +1,547 @@ + + + + + + ATA Firmware Update + + + + +

ATA Firmware Update

+ + +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ +
+
+ +
+ +
+ +
+ +
+ +
+ + +
+ + +
+ + + + +
+ + +
+ + +
+ + +
+ + +
+
+ + +
+ +
+ + + + diff --git a/firmware_update/latest/data/ata-boothifier-upgradeV3.html b/firmware_update/latest/data/ata-boothifier-upgradeV3.html new file mode 100644 index 0000000..8f500d2 --- /dev/null +++ b/firmware_update/latest/data/ata-boothifier-upgradeV3.html @@ -0,0 +1,476 @@ + + + + + + ATA Firmware Update + + + + +

ATA Firmware Update

+ + +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ +
+
+ +
+ +
+ +
+ +
+ +
+ + +
+ + +
+ + + + +
+ + +
+ + +
+ + +
+ + +
+
+ + +
+ +
+ + + + diff --git a/firmware_update/latest/data/flashstik-reg.html b/firmware_update/latest/data/flashstik-reg.html new file mode 100644 index 0000000..7cef51f --- /dev/null +++ b/firmware_update/latest/data/flashstik-reg.html @@ -0,0 +1,472 @@ + + + + + + ATA Light Stick Reg + + + + +

ATA Flash-Stick Link/Registration

+ + +
+ + +
+ +
+ + +
+ +
+ + + +
+ + + + + + + diff --git a/firmware_update/latest/data/system/ble.json b/firmware_update/latest/data/system/ble.json new file mode 100644 index 0000000..c35b40d --- /dev/null +++ b/firmware_update/latest/data/system/ble.json @@ -0,0 +1,9 @@ +{ + "name": "ATALIGHTS", + "lights-service": "FFE0", + "lights-char": "FFE1", + "stick-char": "FFE2", + "upgrade-service": "abcdef01-2345-6789-1234-56789abcdef0", + "upgrade-char1": "abcdef01-2345-6789-1234-56789abcdef1", + "upgrade-char2": "abcdef02-2345-6789-1234-56789abcdef1" +} \ No newline at end of file diff --git a/firmware_update/latest/data/system/readme.txt b/firmware_update/latest/data/system/readme.txt new file mode 100644 index 0000000..d0db09f --- /dev/null +++ b/firmware_update/latest/data/system/readme.txt @@ -0,0 +1,5 @@ + +#Setting up /system/system.json + 1 - Choose the +modes: + booth, roamer, stick \ No newline at end of file diff --git a/firmware_update/latest/data/system/update.json b/firmware_update/latest/data/system/update.json index 4e5f82b..02aa6ac 100644 --- a/firmware_update/latest/data/system/update.json +++ b/firmware_update/latest/data/system/update.json @@ -1,4 +1,5 @@ { - "baseurl": "https://storage.googleapis.com/boothifier/", - "folder": "latest/" + "folder": "latest/", + "baseurl": "https://s3-minio.boothwizard.com/boothifier/", + "baseurl2": "https://storage.googleapis.com/boothifier/" } \ No newline at end of file diff --git a/firmware_update/latest/update.json b/firmware_update/latest/update.json index 7c7aa5a..30368e5 100644 --- a/firmware_update/latest/update.json +++ b/firmware_update/latest/update.json @@ -2,25 +2,38 @@ "version": { "major": 1, "minor": 4, - "patch": 7 + "patch": 8 }, - "release_date": "2024-01-15", + "release_date": "2025-08-20", + "release_time": "08:57:43", "description": "This is a firmware update.", "changelog": [ - "Fixed issue with device connectivity.", - "Improved firmware update process." + "...", + "..." ], "firmware": { "file": "firmware.bin", - "md5": "b8c880418a180efb23260ee093d13e61", - "size": 1409568 + "md5": "fcec6e659842cc0333880b701a3e2634", + "size": 1401712 }, "files": [ { "remote": "data/ata-boothifier-upgrade.html", "local": "/ata-boothifier-upgrade.html", - "md5": "e452db020a5ad660599129ab35e01058", - "size": 16736 + "md5": "92074ec24fd467545272eb9e837d644c", + "size": 16980 + }, + { + "remote": "data/ata-boothifier-upgradeV2.html", + "local": "/ata-boothifier-upgradeV2.html", + "md5": "484648993370e4b6aff13124bd1c55c1", + "size": 18178 + }, + { + "remote": "data/ata-boothifier-upgradeV3.html", + "local": "/ata-boothifier-upgradeV3.html", + "md5": "79426145db379ac15ccc742245a31ecb", + "size": 17233 }, { "remote": "data/favicon.ico", @@ -28,6 +41,12 @@ "md5": "ba4c4e3bf5e5db2bbfc56a52f3657d79", "size": 1150 }, + { + "remote": "data/flashstik-reg.html", + "local": "/flashstik-reg.html", + "md5": "394fdfe3cd3fb89a8ddb3d6edf2d2da4", + "size": 15651 + }, { "remote": "data/css/global-style.css", "local": "/css/global-style.css", @@ -76,6 +95,18 @@ "md5": "fdb81281d3773a7462998fdddbe6f5bf", "size": 196885 }, + { + "remote": "data/system/ble.json", + "local": "/system/ble.json", + "md5": "faebefd5b50046a01d4a8aa27f8504d0", + "size": 307 + }, + { + "remote": "data/system/readme.txt", + "local": "/system/readme.txt", + "md5": "198c92a2cc06b3effce3b5ba313cc6a0", + "size": 86 + }, { "remote": "data/system/tunes.json", "local": "/system/tunes.json", @@ -85,8 +116,8 @@ { "remote": "data/system/update.json", "local": "/system/update.json", - "md5": "8046dbf9490cfd88fe5970b4ec1ac2cd", - "size": 91 + "md5": "01cc6a1935601085df49308cab646673", + "size": 156 }, { "remote": "data/www/about.html", diff --git a/platformio.ini b/platformio.ini index 904b8cb..9ff1f0c 100644 --- a/platformio.ini +++ b/platformio.ini @@ -32,7 +32,8 @@ lib_deps = build_flags = -mfix-esp32-psram-cache-issue -D CONFIG_LOG_DYNAMIC_LEVEL_CONTROL=1 - -D CORE_DEBUG_LEVEL=ARDUHAL_LOG_LEVEL_VERBOSE + #-D CORE_DEBUG_LEVEL=ARDUHAL_LOG_LEVEL_VERBOSE + -D CORE_DEBUG_LEVEL=ARDUHAL_LOG_LEVEL_INFO -D CONFIG_ARDUHAL_LOG_COLORS=1 upload_port = COM5 debug_init_break = tbreak setup diff --git a/src/ATALights.cpp b/src/ATALights.cpp index befd7da..6098bc9 100644 --- a/src/ATALights.cpp +++ b/src/ATALights.cpp @@ -338,7 +338,7 @@ void Lights_Control_Task(void *parameters){ COLOR_PACK colorPack; CRGBPalette16 firePalette; - ESP_LOGD(tag, "Lights Control Task Entered..."); + ESP_LOGD(tag, "Lights Control Task Entered & Suspended..."); vTaskSuspend(NULL); ESP_LOGD(tag, "Lights Control Task Resumed..."); vTaskDelay(1000); @@ -349,7 +349,7 @@ void Lights_Control_Task(void *parameters){ while (true) { if (xQueueReceive(animationQueue, &AnimEvent, portMAX_DELAY) == pdTRUE) { - ESP_LOGD(tag, "New Animation Event: Index: %d", AnimEvent.AnimationIndex); + ESP_LOGI(tag, "New Animation Event: Index: %d", AnimEvent.AnimationIndex); switch (AnimEvent.AnimationIndex) { case -3: // Set Pixel by index if (AnimEvent.data.data[7] >= 0 && AnimEvent.data.data[7] < ledSettings[0].size) { @@ -460,7 +460,7 @@ void Lights_Control_Task(void *parameters){ Anim_GradientRotate(AnimationLooping, ledSettings[0].leds, ledSettings[0].size, colorPack, 50); break; default: - ESP_LOGD(tag, "Loop default"); + ESP_LOGW(tag, "Loop default"); break; } diff --git a/src/BLE_UpdateService.cpp b/src/BLE_UpdateService.cpp index 791db2b..f1ff77c 100644 --- a/src/BLE_UpdateService.cpp +++ b/src/BLE_UpdateService.cpp @@ -24,10 +24,10 @@ struct updateStatus { byte wifiIP[4] = {0, 0, 0, 0}; byte currVersion[3] = {FIRMWARE_VERSION_MAJOR, FIRMWARE_VERSION_MINOR, FIRMWARE_VERSION_PATCH}; byte newVersion[3] = {0, 0, 0}; + char wifiSSID[20] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; }updatePacket; - // Class for handling characteristic events class UpgradeChar_Callbacks : public NimBLECharacteristicCallbacks { @@ -64,6 +64,7 @@ class UpgradeChar_Callbacks : public NimBLECharacteristicCallbacks { updatePacket.wifiStatus = WIFI_DISCONNECTED; updatePacket.wifiOnline = false; updatePacket.wifiIP[0] = updatePacket.wifiIP[1] = updatePacket.wifiIP[2] = updatePacket.wifiIP[3] = 0; + strncpy(updatePacket.wifiSSID, ssid.c_str(), sizeof(updatePacket.wifiSSID) - 1); } else { ESP_LOGW(tag, "Failed to start WiFi connection task"); } @@ -97,12 +98,15 @@ class UpgradeChar_Callbacks : public NimBLECharacteristicCallbacks { updatePacket.wifiIP[1] = ip[1]; updatePacket.wifiIP[2] = ip[2]; updatePacket.wifiIP[3] = ip[3]; + strncpy(updatePacket.wifiSSID, WiFi.SSID().c_str(), sizeof(updatePacket.wifiSSID) - 1); + ESP_LOGI(tag, "WiFi packet: SSID='%s'", updatePacket.wifiSSID); } else { updatePacket.wifiStatus = WIFI_DISCONNECTED; updatePacket.wifiIP[0] = 0; updatePacket.wifiIP[1] = 0; updatePacket.wifiIP[2] = 0; updatePacket.wifiIP[3] = 0; + memset(updatePacket.wifiSSID, 0, sizeof(updatePacket.wifiSSID)); } //update version diff --git a/src/common/fileSystem.cpp b/src/common/fileSystem.cpp index 685cb6b..73c4d6a 100644 --- a/src/common/fileSystem.cpp +++ b/src/common/fileSystem.cpp @@ -13,14 +13,14 @@ void Init_File_System(void){ } // Get all information of your LITTLEFS - ESP_LOGD(tag, "File system info."); - ESP_LOGD(tag, "Total: %d, Used: %d, Free:%d", LittleFS.totalBytes(), LittleFS.usedBytes(), LittleFS.totalBytes() - LittleFS.usedBytes()); + ESP_LOGI(tag, "File system info."); + ESP_LOGI(tag, "Total: %d, Used: %d, Free:%d", LittleFS.totalBytes(), LittleFS.usedBytes(), LittleFS.totalBytes() - LittleFS.usedBytes()); // Open dir folder File dir = LittleFS.open("/"); // Cycle all the content - printAllFiles(); + //printAllSystemFiles(); } void getAllDirectories(String (&directoryList)[MAX_DIRECTORIES], int &count){ @@ -52,7 +52,7 @@ void getAllDirectories(String (&directoryList)[MAX_DIRECTORIES], int &count){ void printFilesInDirectories(const String directoryList[], int count){ for (int i = 0; i < count; i++){ - ESP_LOGD(tag, "Dir: %s", directoryList[i].c_str()); + ESP_LOGI(tag, "Dir: %s", directoryList[i].c_str()); File dir = LittleFS.open(directoryList[i]); if (!dir || !dir.isDirectory()){ @@ -63,7 +63,7 @@ void printFilesInDirectories(const String directoryList[], int count){ File file = dir.openNextFile(); while (file){ if (!file.isDirectory()){ - ESP_LOGD(tag, " File: %s", file.name()); + ESP_LOGI(tag, " File: %s", file.name()); } file = dir.openNextFile(); } @@ -72,13 +72,13 @@ void printFilesInDirectories(const String directoryList[], int count){ } } -void printAllFiles(void){ +void printAllSystemFiles(void){ String directories[MAX_DIRECTORIES]; int dirCount = 0; getAllDirectories(directories, dirCount); - ESP_LOGD(tag, "File System Listing:"); + ESP_LOGI(tag, "File System Listing:"); printFilesInDirectories(directories, dirCount); } diff --git a/src/common/fileSystem.h b/src/common/fileSystem.h index 8c97d04..13a1414 100644 --- a/src/common/fileSystem.h +++ b/src/common/fileSystem.h @@ -20,7 +20,7 @@ void getAllDirectories(String (&directoryList)[MAX_DIRECTORIES], int& count); void printFilesInDirectories(const String directoryList[], int count); //void printAllFiles(int maxDirs); -void printAllFiles(void); +void printAllSystemFiles(void); diff --git a/src/main.cpp b/src/main.cpp index d6af7c7..7343c7b 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -119,6 +119,11 @@ void setup() // Init LittleFS Init_File_System(); + // Print all system files + if (digitalRead(sys_settings.boardPins.btn[0]) == LOW){ + printAllSystemFiles(); + } + String board_file_path, booth_file_path; Get_Board_and_Booth_File_Paths("/system/system.json", board_file_path, booth_file_path); @@ -156,7 +161,7 @@ void setup() // Initialize Temperature Sensor Init_TSensor(72); - + float val = readBoardInputVoltage(); ESP_LOGI(tag, "Input Volage = %f", val); @@ -166,14 +171,14 @@ void setup() { setStatusPin1(true); UpgradeMode = true; - ESP_LOGE(tag, "Enabling BLE and Update Service"); + ESP_LOGW(tag, "Enabling BLE and Update Service"); Init_BleServer(true, true); ESP_LOGW(tag, "Enabling Wifi AP and Client"); Wifi_Init(); } else { - ESP_LOGE(tag, "Enabling BLE, No Update Service"); + ESP_LOGI(tag, "Enabling BLE, No Update Service"); Init_BleServer(true, false); // Dont start the Upgrade service } @@ -308,7 +313,7 @@ void loop() if(UpgradeMode){ ON_EVERY_N_MILLISECONDS(5000) { - Buzzer_Play_Tune(TUNE_THUMP, true, true); + Buzzer_Play_Tune(TUNE_ACK, true, true); } } diff --git a/src/my_buttons.cpp b/src/my_buttons.cpp index a6d9911..5a1c4ee 100644 --- a/src/my_buttons.cpp +++ b/src/my_buttons.cpp @@ -11,25 +11,25 @@ void Init_ButtonEvents(int8_t (&pin)[3]){ if (pin[0] >= 0) { if (boardButtons[0] == nullptr) { boardButtons[0] = new OneButton(pin[0], true, true); - ESP_LOGD(tag, "Button1 Events, pin=%d", pin[0]); + ESP_LOGI(tag, "Button1 Events, pin=%d", pin[0]); } else { - ESP_LOGD(tag, "Button1 already initialized (pin=%d)", pin[0]); + ESP_LOGW(tag, "Button1 already initialized (pin=%d)", pin[0]); } } if (pin[1] >= 0) { if (boardButtons[1] == nullptr) { boardButtons[1] = new OneButton(pin[1], true, true); - ESP_LOGD(tag, "Button2 Events, pin=%d", pin[1]); + ESP_LOGI(tag, "Button2 Events, pin=%d", pin[1]); } else { - ESP_LOGD(tag, "Button2 already initialized (pin=%d)", pin[1]); + ESP_LOGW(tag, "Button2 already initialized (pin=%d)", pin[1]); } } if (pin[2] >= 0) { if (boardButtons[2] == nullptr) { boardButtons[2] = new OneButton(pin[2], true, false); - ESP_LOGD(tag, "Button3 Events, pin=%d", pin[2]); + ESP_LOGI(tag, "Button3 Events, pin=%d", pin[2]); } else { - ESP_LOGD(tag, "Button3 already initialized (pin=%d)", pin[2]); + ESP_LOGW(tag, "Button3 already initialized (pin=%d)", pin[2]); } } @@ -66,10 +66,10 @@ void Init_ButtonEvents(int8_t (&pin)[3]){ boardButtons[2]->attachLongPressStart(btn3_LongPressStart); boardButtons[2]->attachLongPressStop(btn3_LongPressStop); boardButtons[2]->attachDuringLongPress(btn3_DuringLongPress); - ESP_LOGD(tag, "Button3 Events Initialized"); + ESP_LOGI(tag, "Button3 Events Initialized"); } else { - ESP_LOGD(tag, "Button3 Not Initialized"); + ESP_LOGW(tag, "Button3 Not Initialized"); } } diff --git a/src/my_buzzer.cpp b/src/my_buzzer.cpp index a45ccc9..b30cfb0 100644 --- a/src/my_buzzer.cpp +++ b/src/my_buzzer.cpp @@ -27,7 +27,7 @@ void Init_Buzzer(int8_t pin, const char* configFile) } Buzzer_Load_Tunes(configFile); // Load Tunes - ESP_LOGD(tag, "Buzzer initialized.."); + ESP_LOGI(tag, "Buzzer initialized.."); } void Buzzer_Play_Tune(TUNE_TYPE tune, bool async, bool hasPriority) diff --git a/src/my_tsensor.cpp b/src/my_tsensor.cpp index 2a3ac50..15a3817 100644 --- a/src/my_tsensor.cpp +++ b/src/my_tsensor.cpp @@ -61,27 +61,27 @@ TI_TMP102_Compatible *tSensor = nullptr; if ((FanState == 2) && (temperature < (sp2 - hyst))) { newDuty = fp1; FanState = 1; - //ESP_LOGD(tag, "Dropping down to FanPower1"); + ESP_LOGD(tag, "Dropping down to FanPower1"); } else if ((FanState == 1) && (temperature < (sp1 - hyst))) { newDuty = 0; FanState = 0; - //ESP_LOGD(tag, "Dropping down to FanPower0"); + ESP_LOGD(tag, "Dropping down to FanPower0"); } else if ((FanState <= 1) && (temperature > sp1)) { newDuty = fp1; if (temperature > sp2) { newDuty = fp2; FanState = 2; - //ESP_LOGD(tag, "Raising up to FanPower2"); - } //else { - //ESP_LOGD(tag, "Raising up to FanPower1"); - //} + ESP_LOGD(tag, "Raising up to FanPower2"); + } else { + ESP_LOGD(tag, "Raising up to FanPower1"); + } } // Apply new duty cycle if changed if (currentDuty != newDuty) { pwmOut->setOutput(newDuty); - ESP_LOGD(tag, "Board T: %.2f F, Fan -> %.2f (state=%u)", temperature, newDuty, FanState); + ESP_LOGI(tag, "Board T: %.2f F, Fan -> %.2f (state=%u)", temperature, newDuty, FanState); } } \ No newline at end of file diff --git a/src/my_wifi.cpp b/src/my_wifi.cpp index c2d5ae2..f3be694 100644 --- a/src/my_wifi.cpp +++ b/src/my_wifi.cpp @@ -102,7 +102,7 @@ void Wifi_Init() WiFi.onEvent(onWiFiEvent); WiFi.setHostname(mDnsName.c_str()); webServer.begin(); - ESP_LOGD(tag, "AP started with IP: %s", WiFi.softAPIP().toString().c_str()); + ESP_LOGI(tag, "AP started with IP: %s", WiFi.softAPIP().toString().c_str()); StartWifiConnectTask(client_ssid, client_pass); @@ -123,12 +123,12 @@ bool StartWifiConnectTask(String ssid = "", String pass = "") client_pass = pass; if (Wifi_Task_Handle == NULL) { - ESP_LOGD(tag, "Creating WiFi task"); + ESP_LOGI(tag, "Creating WiFi task"); xTaskCreatePinnedToCore(Wifi_ConnectTask, "Wifi_Task", 1024 * 4, NULL, 1, &Wifi_Task_Handle, 0); } else { - ESP_LOGD(tag, "WiFi task already running"); + ESP_LOGI(tag, "WiFi task already running"); } return true; @@ -148,7 +148,7 @@ void Wifi_ConnectTask(void *parameter) if (WiFi.status() != WL_CONNECTED || client_ssid != WiFi.SSID()) { - ESP_LOGD(tag, "Connecting to: %s", client_ssid.c_str()); + ESP_LOGI(tag, "Connecting to: %s", client_ssid.c_str()); // Disconnect and connect to new network WiFi.disconnect(true); @@ -168,7 +168,7 @@ void Wifi_ConnectTask(void *parameter) ESP_LOGW(tag, "Connection failed - check password"); break; default: - ESP_LOGD(tag, "Connecting... (%d/%d)", attempts + 1, MAX_ATTEMPTS); + ESP_LOGI(tag, "Connecting... (%d/%d)", attempts + 1, MAX_ATTEMPTS); } vTaskDelay(pdMS_TO_TICKS(ATTEMPT_DELAY_MS)); attempts++; @@ -383,7 +383,7 @@ void Setup_WebServer_Handlers(AsyncWebServer &server) // Start connection StartWifiConnectTask(ssid, pass); - ESP_LOGD(tag, "Starting connection to %s", client_ssid.c_str()); + ESP_LOGI(tag, "Starting connection to %s", client_ssid.c_str()); request->send(200, "application/json", "{\"status\":\"connecting\"}"); }); server.on("/wifi/status", HTTP_GET, [](AsyncWebServerRequest *request) { @@ -420,7 +420,7 @@ void Setup_WebServer_Handlers(AsyncWebServer &server) try { String filename = uriDecode(request->getParam("file")->value()); - ESP_LOGD(tag, "Download request for: %s", filename.c_str()); + ESP_LOGI(tag, "Download request for: %s", filename.c_str()); request->send(LittleFS, filename, "application/octet-stream"); } catch (const std::exception& e) { @@ -490,7 +490,7 @@ void Setup_WebServer_Handlers(AsyncWebServer &server) // Get and decode filename String fileName = uriDecode(request->getParam(param_edit_path)->value()); - ESP_LOGD(tag, "Edit request for file: %s", fileName.c_str()); + ESP_LOGI(tag, "Edit request for file: %s", fileName.c_str()); // Set save path savePath = (fileName == "new") ? "/new.txt" : fileName; @@ -500,7 +500,7 @@ void Setup_WebServer_Handlers(AsyncWebServer &server) savePath = "/" + savePath; } - ESP_LOGD(tag, "Save path set to: %s", savePath.c_str()); + ESP_LOGI(tag, "Save path set to: %s", savePath.c_str()); try { sendHtmlFile("/www/edit.html", request, fileManagerHtmlProcessor); @@ -651,7 +651,7 @@ void Setup_WebServer_Handlers(AsyncWebServer &server) contentType = "application/octet-stream"; } - ESP_LOGD(tag, "Sending file: %s (%s)", filePath.c_str(), contentType); + ESP_LOGI(tag, "Sending file: %s (%s)", filePath.c_str(), contentType); request->send(LittleFS, filePath, contentType); } catch (const std::runtime_error &e) @@ -688,7 +688,7 @@ void handleFilesUpload_OnBody(AsyncWebServerRequest *request, String filename, s AsyncWebParameter *p = request->getParam("dir-path", true, false); String path = p->value() + "/" + filename; - ESP_LOGD(tag, "Starting upload: %s", path.c_str()); + ESP_LOGI(tag, "Starting upload: %s", path.c_str()); // Validate path if (!path.startsWith("/")) @@ -729,7 +729,7 @@ void handleFilesUpload_OnBody(AsyncWebServerRequest *request, String filename, s if (final) { request->_tempFile.close(); - ESP_LOGD(tag, "Upload complete: %s, %u bytes", filename.c_str(), index + len); + ESP_LOGI(tag, "Upload complete: %s, %u bytes", filename.c_str(), index + len); request->redirect("/files"); } } @@ -750,7 +750,7 @@ void sendHtmlFile(const char *filePath, AsyncWebServerRequest *request, String ( String processedData = varReplace(htmlFile, callback); delete[] htmlFile; // Clean up allocated memory - ESP_LOGD(tag, "Sent file: %s", filePath); + ESP_LOGI(tag, "Sent file: %s", filePath); request->send(200, "text/html", processedData); } catch (const std::exception &e) @@ -773,11 +773,11 @@ const char *getFileExtension(const char *filename) const char *lastDot = strrchr(filename, '.'); if (!lastDot || lastDot == filename || *(lastDot + 1) == '\0') { - ESP_LOGD(tag, "No valid extension found in: %s", filename); + ESP_LOGI(tag, "No valid extension found in: %s", filename); return ""; } - ESP_LOGD(tag, "Found extension: %s", lastDot + 1); + ESP_LOGI(tag, "Found extension: %s", lastDot + 1); return lastDot + 1; } @@ -786,7 +786,7 @@ const char *getFileType(const char *ext) if (!ext) return "application/octet-stream"; - ESP_LOGD(tag, "Getting file type for extension: %s", ext); + ESP_LOGI(tag, "Getting file type for extension: %s", ext); if (strcmp(ext, "png") == 0) return "image/png"; @@ -915,92 +915,92 @@ void onWiFiEvent(WiFiEvent_t event) switch (event) { case ARDUINO_EVENT_WIFI_READY: - ESP_LOGD(tag, "WiFi interface ready"); + ESP_LOGI(tag, "WiFi interface ready"); break; case ARDUINO_EVENT_WIFI_SCAN_DONE: - ESP_LOGD(tag, "Completed scan for access points"); + ESP_LOGI(tag, "Completed scan for access points"); break; case ARDUINO_EVENT_WIFI_STA_START: - ESP_LOGD(tag, "WiFi client started"); + ESP_LOGI(tag, "WiFi client started"); break; case ARDUINO_EVENT_WIFI_STA_STOP: - ESP_LOGD(tag, "WiFi clients stopped"); + ESP_LOGI(tag, "WiFi clients stopped"); break; case ARDUINO_EVENT_WIFI_STA_CONNECTED: - ESP_LOGD(tag, "Connected to AP"); + ESP_LOGI(tag, "Connected to AP"); break; case ARDUINO_EVENT_WIFI_STA_DISCONNECTED: - ESP_LOGD(tag, "WiFi Disconnected"); + ESP_LOGI(tag, "WiFi Disconnected"); setStatusPin1(false); Buzzer_Play_Tune(TUNE_DISCONNECTED); break; case ARDUINO_EVENT_WIFI_STA_AUTHMODE_CHANGE: - ESP_LOGD(tag, "Authentication mode of access point has changed"); + ESP_LOGI(tag, "Authentication mode of access point has changed"); break; case ARDUINO_EVENT_WIFI_STA_GOT_IP: - ESP_LOGD(tag, "My IP: %s", WiFi.localIP().toString()); + ESP_LOGI(tag, "My IP: %s", WiFi.localIP().toString()); // Wifi_Start_MDNS(); setStatusPin1(true); Buzzer_Play_Tune(TUNE_CONNECTED); break; case ARDUINO_EVENT_WIFI_STA_LOST_IP: - ESP_LOGD(tag, "Lost IP address and IP address is reset to 0"); + ESP_LOGI(tag, "Lost IP address and IP address is reset to 0"); break; case ARDUINO_EVENT_WPS_ER_SUCCESS: - ESP_LOGD(tag, "WiFi Protected Setup (WPS): succeeded in enrollee mode"); + ESP_LOGI(tag, "WiFi Protected Setup (WPS): succeeded in enrollee mode"); break; case ARDUINO_EVENT_WPS_ER_FAILED: - ESP_LOGD(tag, "WiFi Protected Setup (WPS): failed in enrollee mode"); + ESP_LOGI(tag, "WiFi Protected Setup (WPS): failed in enrollee mode"); break; case ARDUINO_EVENT_WPS_ER_TIMEOUT: - ESP_LOGD(tag, "WiFi Protected Setup (WPS): timeout in enrollee mode"); + ESP_LOGI(tag, "WiFi Protected Setup (WPS): timeout in enrollee mode"); break; case ARDUINO_EVENT_WPS_ER_PIN: - ESP_LOGD(tag, "WiFi Protected Setup (WPS): pin code in enrollee mode"); + ESP_LOGI(tag, "WiFi Protected Setup (WPS): pin code in enrollee mode"); break; case ARDUINO_EVENT_WIFI_AP_START: - ESP_LOGD(tag, "WiFi access point started"); + ESP_LOGI(tag, "WiFi access point started"); break; case ARDUINO_EVENT_WIFI_AP_STOP: - ESP_LOGD(tag, "WiFi access point stopped"); + ESP_LOGI(tag, "WiFi access point stopped"); break; case ARDUINO_EVENT_WIFI_AP_STACONNECTED: - ESP_LOGD(tag, "Client connected"); + ESP_LOGI(tag, "Client connected"); break; case ARDUINO_EVENT_WIFI_AP_STADISCONNECTED: - ESP_LOGD(tag, "SoftAP Client Disconnected"); + ESP_LOGI(tag, "SoftAP Client Disconnected"); Buzzer_Play_Tune(TUNE_DISCONNECTED); break; case ARDUINO_EVENT_WIFI_AP_STAIPASSIGNED: - ESP_LOGD(tag, "SoftAP Client Connected"); + ESP_LOGI(tag, "SoftAP Client Connected"); Buzzer_Play_Tune(TUNE_CONNECTED); break; case ARDUINO_EVENT_WIFI_AP_PROBEREQRECVED: - ESP_LOGD(tag, "Received probe request"); + ESP_LOGI(tag, "Received probe request"); break; case ARDUINO_EVENT_WIFI_AP_GOT_IP6: - ESP_LOGD(tag, "AP IPv6 is preferred"); + ESP_LOGI(tag, "AP IPv6 is preferred"); break; case ARDUINO_EVENT_WIFI_STA_GOT_IP6: - ESP_LOGD(tag, "STA IPv6 is preferred"); + ESP_LOGI(tag, "STA IPv6 is preferred"); break; case ARDUINO_EVENT_ETH_GOT_IP6: - ESP_LOGD(tag, "Ethernet IPv6 is preferred"); + ESP_LOGI(tag, "Ethernet IPv6 is preferred"); break; case ARDUINO_EVENT_ETH_START: - ESP_LOGD(tag, "Ethernet started"); + ESP_LOGI(tag, "Ethernet started"); break; case ARDUINO_EVENT_ETH_STOP: - ESP_LOGD(tag, "Ethernet stopped"); + ESP_LOGI(tag, "Ethernet stopped"); break; case ARDUINO_EVENT_ETH_CONNECTED: - ESP_LOGD(tag, "Ethernet connected"); + ESP_LOGI(tag, "Ethernet connected"); break; case ARDUINO_EVENT_ETH_DISCONNECTED: - ESP_LOGD(tag, "Ethernet disconnected"); + ESP_LOGI(tag, "Ethernet disconnected"); break; case ARDUINO_EVENT_ETH_GOT_IP: - ESP_LOGD(tag, "Obtained IP address"); + ESP_LOGI(tag, "Obtained IP address"); break; default: break; @@ -1102,7 +1102,7 @@ bool writeFile(fs::FS &fs, const char *path, const char *message) return false; } - ESP_LOGD(tag, "Successfully wrote %u bytes to %s", (unsigned)totalSize, finalPath.c_str()); + ESP_LOGI(tag, "Successfully wrote %u bytes to %s", (unsigned)totalSize, finalPath.c_str()); return true; } @@ -1157,7 +1157,7 @@ char *readFile(fs::FS &fs, const char *path) // Null terminate fileContent[bytesRead] = '\0'; - ESP_LOGD(tag, "Successfully read %u bytes from %s", bytesRead, path); + ESP_LOGI(tag, "Successfully read %u bytes from %s", bytesRead, path); return fileContent; } diff --git a/update.json b/update.json new file mode 100644 index 0000000..007f91a --- /dev/null +++ b/update.json @@ -0,0 +1,190 @@ +{ + "files": [ + { + "remote": "data/ata-boothifier-upgrade.html", + "local": "/ata-boothifier-upgrade.html", + "md5": "92074ec24fd467545272eb9e837d644c", + "size": 16980 + }, + { + "remote": "data/ata-boothifier-upgradeV2.html", + "local": "/ata-boothifier-upgradeV2.html", + "md5": "484648993370e4b6aff13124bd1c55c1", + "size": 18178 + }, + { + "remote": "data/ata-boothifier-upgradeV3.html", + "local": "/ata-boothifier-upgradeV3.html", + "md5": "79426145db379ac15ccc742245a31ecb", + "size": 17233 + }, + { + "remote": "data/favicon.ico", + "local": "/favicon.ico", + "md5": "ba4c4e3bf5e5db2bbfc56a52f3657d79", + "size": 1150 + }, + { + "remote": "data/flashstik-reg.html", + "local": "/flashstik-reg.html", + "md5": "394fdfe3cd3fb89a8ddb3d6edf2d2da4", + "size": 15651 + }, + { + "remote": "data/css/global-style.css", + "local": "/css/global-style.css", + "md5": "217a9cca8b4eae2d28fa8bc5a0f6db09", + "size": 1239 + }, + { + "remote": "data/css/nav.css", + "local": "/css/nav.css", + "md5": "e653a75433056f28e3f410f567b8622c", + "size": 1538 + }, + { + "remote": "data/images/atalogo.png", + "local": "/images/atalogo.png", + "md5": "5a18c88a4ea80c8d8d0ad52b2fdbbadc", + "size": 16690 + }, + { + "remote": "data/images/favicon-32x32.png", + "local": "/images/favicon-32x32.png", + "md5": "d80cf74ace3a8be487a5158bca48f9b6", + "size": 2428 + }, + { + "remote": "data/js/event-box.js", + "local": "/js/event-box.js", + "md5": "553f26707686038e275227a97eb96659", + "size": 12341 + }, + { + "remote": "data/js/fwUoload.js", + "local": "/js/fwUoload.js", + "md5": "d4a734cce529c3adf831ea46259f9c2d", + "size": 1524 + }, + { + "remote": "data/js/hue-select.js", + "local": "/js/hue-select.js", + "md5": "0a58f1a339af5c54aecfc5ce1aac7168", + "size": 6367 + }, + { + "remote": "data/js/jquery-3.7.1.js", + "local": "/js/jquery-3.7.1.js", + "md5": "fdb81281d3773a7462998fdddbe6f5bf", + "size": 196885 + }, + { + "remote": "data/system/ble.json", + "local": "/system/ble.json", + "md5": "faebefd5b50046a01d4a8aa27f8504d0", + "size": 307 + }, + { + "remote": "data/system/readme.txt", + "local": "/system/readme.txt", + "md5": "198c92a2cc06b3effce3b5ba313cc6a0", + "size": 86 + }, + { + "remote": "data/system/tunes.json", + "local": "/system/tunes.json", + "md5": "814999e88296bee179cef5d394f3f696", + "size": 1149 + }, + { + "remote": "data/system/update.json", + "local": "/system/update.json", + "md5": "01cc6a1935601085df49308cab646673", + "size": 156 + }, + { + "remote": "data/www/about.html", + "local": "/www/about.html", + "md5": "23f0c991c5c67e7eefe6c24aa50b59fb", + "size": 4222 + }, + { + "remote": "data/www/edit.html", + "local": "/www/edit.html", + "md5": "fed238dcf87d3797b08ed371330ea800", + "size": 5546 + }, + { + "remote": "data/www/edit_old.html", + "local": "/www/edit_old.html", + "md5": "9aafba533ac77352d30841cdc34db0c4", + "size": 4240 + }, + { + "remote": "data/www/failed.html", + "local": "/www/failed.html", + "md5": "a24025d56bef1cd2ed5375f6e8853dde", + "size": 828 + }, + { + "remote": "data/www/files.html", + "local": "/www/files.html", + "md5": "52d82d4d23b038929691cd0fb20e8ee0", + "size": 9369 + }, + { + "remote": "data/www/home.html", + "local": "/www/home.html", + "md5": "767fd73b733d8e37dc79252fcd20b610", + "size": 7822 + }, + { + "remote": "data/www/index.html", + "local": "/www/index.html", + "md5": "af690aaa4dec02691ffdb2765c837370", + "size": 806 + }, + { + "remote": "data/www/lights.html", + "local": "/www/lights.html", + "md5": "272f8dc423923bb5026837240f654efe", + "size": 19056 + }, + { + "remote": "data/www/navbar.html", + "local": "/www/navbar.html", + "md5": "89af40b990e297e41e116105b04b66ee", + "size": 533 + }, + { + "remote": "data/www/ok.html", + "local": "/www/ok.html", + "md5": "db42bd2ff52293c3b4d6ef62fb4e3a42", + "size": 865 + }, + { + "remote": "data/www/setup.html", + "local": "/www/setup.html", + "md5": "19e1f419844852800757ccd36bb7892a", + "size": 11349 + }, + { + "remote": "data/www/upgrade.html", + "local": "/www/upgrade.html", + "md5": "f4a3efb67be66b5214d905e605984c93", + "size": 9080 + }, + { + "remote": "data/www/wifi.html", + "local": "/www/wifi.html", + "md5": "c6e55946a02cb0ff28689dd10d265987", + "size": 5320 + } + ], + "firmware": { + "md5": "fcec6e659842cc0333880b701a3e2634", + "size": 1401712 + }, + "release_date": "2025-08-20", + "release_time": "08:53:05" +} \ No newline at end of file