diff --git a/data/ata-boothifier-upgrade(updated).html b/data/ata-boothifier-upgrade(updated).html
new file mode 100644
index 0000000..de07c66
--- /dev/null
+++ b/data/ata-boothifier-upgrade(updated).html
@@ -0,0 +1,531 @@
+
+
+
+
+
+ ATA Firmware Update
+
+
+
+
+ ATA Firmware Update
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/data/system/ble.json b/data/system/ble.json
new file mode 100644
index 0000000..c35b40d
--- /dev/null
+++ b/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/data/system/update.json b/data/system/update.json
index 4e5f82b..02aa6ac 100644
--- a/data/system/update.json
+++ b/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/UploadToMinio.py b/firmware_update/UploadToMinio.py
new file mode 100644
index 0000000..516301d
--- /dev/null
+++ b/firmware_update/UploadToMinio.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 = False
+UPLOAD_MANIFEST = True
+UPLOAD_DATA = False
+
+# 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/update.json b/firmware_update/latest/update.json
index 4343b57..7c7aa5a 100644
--- a/firmware_update/latest/update.json
+++ b/firmware_update/latest/update.json
@@ -2,8 +2,14 @@
"version": {
"major": 1,
"minor": 4,
- "patch": 5
+ "patch": 7
},
+ "release_date": "2024-01-15",
+ "description": "This is a firmware update.",
+ "changelog": [
+ "Fixed issue with device connectivity.",
+ "Improved firmware update process."
+ ],
"firmware": {
"file": "firmware.bin",
"md5": "b8c880418a180efb23260ee093d13e61",
diff --git a/firmware_update/minio-boothifier-key.json b/firmware_update/minio-boothifier-key.json
new file mode 100644
index 0000000..26c56bc
--- /dev/null
+++ b/firmware_update/minio-boothifier-key.json
@@ -0,0 +1 @@
+{"url":"https://s3-minio.boothwizard.com/api/v1/service-account-credentials","accessKey":"qu3aDl5mWKJjqaQPkR19","secretKey":"5A0rktd88CiwNUQAr6k6OtUuoxJLy2Xqd9E9dmyZ","api":"s3v4","path":"auto"}
\ No newline at end of file
diff --git a/include/AppUpgrade.h b/include/AppUpgrade.h
index 8734aad..41f54f7 100644
--- a/include/AppUpgrade.h
+++ b/include/AppUpgrade.h
@@ -41,7 +41,8 @@ class AppUpdater {
public:
Version localVersion;
Version otaVersion;
- const char* bucketUrl;
+ // Base URL (bucket) for update resources. Supports either Google Cloud Storage or MinIO (or any HTTP host)
+ String baseUrl;
const char* appName;
const char* manifestName;
JsonDocument jsonManifest;
@@ -68,7 +69,17 @@ class AppUpdater {
* @param bucket Base URL for updates
* @param fs Filesystem reference
*/
- AppUpdater(fs::FS& fs, Version localVersion, const char* bucket, const char* manifestName ="update.json", const char* appBin = "firmware.bin" );
+ AppUpdater(fs::FS& fs, Version localVersion, const char* bucket, const char* manifestName ="update.json", const char* appBin = "firmware.bin" );
+
+ /**
+ * @brief Change the base URL after construction (e.g. switch between MinIO and GCS)
+ */
+ void setBaseUrl(const String& newBaseUrl) { baseUrl = newBaseUrl; }
+
+ /**
+ * @brief Get the currently configured base URL
+ */
+ const String& getBaseUrl() const { return baseUrl; }
/**
* @brief Set progress callback function
@@ -104,7 +115,7 @@ class AppUpdater {
* @param manifestPath Path to manifest file
* @return Manifest content as a json document
*/
- bool checkManifest(void);
+ bool checkManifest(void);
bool updateApp(void);
@@ -128,15 +139,21 @@ class AppUpdater {
* @param expectedMd5 Expected MD5 hash
* @return true if successful
*/
- bool verifyAndSaveFile(WiFiClient* stream, size_t contentLength,
- const char* localPath, const char* expectedMd5);
+ bool verifyAndSaveFile(WiFiClient* stream, size_t contentLength,
+ const char* localPath, const char* expectedMd5);
/**
* @brief Update progress callback
* @param percentage Progress percentage
* @param newStatus Current status
*/
- void updateProgress(UpdateStatus newStatus, int percentage, const char* message = nullptr);
+ void updateProgress(UpdateStatus newStatus, int percentage, const char* message = nullptr);
+
+ /**
+ * @brief Build a full URL by combining baseUrl and a relative path. Absolute (http/https) paths pass through.
+ * Ensures exactly one slash joins base and path. Leading slash on path is stripped.
+ */
+ String buildUrl(const char* path) const;
String getLocalMD5(const char* filePath);
};
diff --git a/include/BleSettings.h b/include/BleSettings.h
new file mode 100644
index 0000000..a890a66
--- /dev/null
+++ b/include/BleSettings.h
@@ -0,0 +1,22 @@
+// BLE settings (loaded from JSON)
+#pragma once
+#include "Arduino.h"
+
+// Defaults (used if JSON missing fields)
+#define DEFAULT_BT_DEVICE_NAME "ATALIGHTS"
+#define DEFAULT_BT_SERVICE "FFE0"
+#define DEFAULT_BT_SP110E_CHAR "FFE1"
+#define DEFAULT_BT_STICK_CHAR "FFE2"
+#define DEFAULT_UPGRADE_SERVICE "abcdef01-2345-6789-1234-56789abcdef0"
+#define DEFAULT_UPGRADE_CHAR1 "abcdef01-2345-6789-1234-56789abcdef1"
+#define DEFAULT_UPGRADE_CHAR2 "abcdef02-2345-6789-1234-56789abcdef1"
+
+extern String BTDeviceName;
+extern String BTServiceUUID;
+extern String BTSP110ECharacteristicUUID;
+extern String BTStickCharacteristicUUID;
+extern String BTUpgradeServiceUUID;
+extern String BTUpgradeCharacteristic1UUID;
+extern String BTUpgradeCharacteristic2UUID;
+
+void Load_BLE_Settings(const String &configPath);
\ No newline at end of file
diff --git a/src/AppUpgrade.cpp b/src/AppUpgrade.cpp
index 991a952..91e6c90 100644
--- a/src/AppUpgrade.cpp
+++ b/src/AppUpgrade.cpp
@@ -22,9 +22,12 @@ Version otaVersion;
AppUpdater::AppUpdater(fs::FS& fs, Version localVersion, const char* bucket, const char* manifestName, const char* appBin)
- : localVersion(localVersion), bucketUrl(bucket), manifestName(manifestName), appName(appBin), fileSystem(fs), downloadBuffer(new uint8_t[BUFFER_SIZE])
+ : localVersion(localVersion), manifestName(manifestName), appName(appBin), fileSystem(fs), downloadBuffer(new uint8_t[BUFFER_SIZE])
{
- ESP_LOGI(TAG, "AppUpdater initialized with version %s", localVersion.toString().c_str());
+ baseUrl = bucket ? String(bucket) : String(DEFAULT_MANIFEST_URL);
+ // Ensure baseUrl ends with a single '/'
+ if(!baseUrl.endsWith("/")) baseUrl += "/";
+ ESP_LOGI(TAG, "AppUpdater initialized (local v%s) baseUrl=%s", localVersion.toString().c_str(), baseUrl.c_str());
}
void AppUpdater::setProgressCallback(void (*callback)( UpdateStatus status, int percentage, const char* message)) {
@@ -39,7 +42,7 @@ void AppUpdater::updateProgress(UpdateStatus newStatus, int percentage, const ch
}
bool AppUpdater::checkManifest() {
- String url = String(bucketUrl) + manifestName;
+ String url = buildUrl(manifestName);
ESP_LOGD(TAG, "Fetching manifest from: %s", url.c_str());
// Start the HTTP client and Send GET request for manifest
@@ -110,7 +113,7 @@ bool AppUpdater::updateFile(const char* remotePath, const char* localPath, const
//updateProgress(UpdateStatus::DOWNLOADING, 0, localPath);
// Construct full URL
- String url = String(bucketUrl) + remotePath;
+ String url = buildUrl(remotePath);
ESP_LOGD(TAG, "Downloading: %s -> %s", url.c_str(), localPath);
String localMd5 = getLocalMD5(localPath);
@@ -295,7 +298,7 @@ bool AppUpdater::updateApp() {
// Get the firmware MD5 hash and URL
const char* expectedMd5 = jsonManifest["firmware"]["md5"];
- String firmwareUrl = String(bucketUrl) + appName;
+ String firmwareUrl = buildUrl(appName);
// Download the firmware
HTTPClient http;
@@ -393,6 +396,19 @@ bool AppUpdater::IsUpdateAvailable(){
return updateAvailable;
}
+String AppUpdater::buildUrl(const char* path) const {
+ if(!path || !*path) return baseUrl; // just base
+ String p(path);
+ // If already absolute URL, pass through
+ if(p.startsWith("http://") || p.startsWith("https://")) return p;
+ // Strip leading slashes to avoid double
+ while(p.startsWith("/")) p.remove(0,1);
+ // Ensure baseUrl has single trailing slash
+ String b = baseUrl;
+ if(!b.endsWith("/")) b += "/";
+ return b + p;
+}
+
AsyncEventSource* eventProgress = nullptr;
void startFirmwareUpdateTask(AsyncEventSource* evProg) {
@@ -491,8 +507,8 @@ void loadUpdateJson(void) {
// Get update configuration
JsonObject jObj = doc.as();
- String baseUrl = jsonConstrainString(TAG, jObj, "baseurl", "https://storage.googleapis.com/boothifier/");
String folderName = jsonConstrainString(TAG, jObj, "folder", "latest/");
+ String baseUrl = jsonConstrainString(TAG, jObj, "baseurl", "https://s3-minio.boothwizard.com/boothifier/");
updateUrl = baseUrl + folderName;
ESP_LOGD(TAG, "updateUrl: %s", updateUrl.c_str());
diff --git a/src/BLE_SP110E.cpp b/src/BLE_SP110E.cpp
index 2a44229..8a5868d 100644
--- a/src/BLE_SP110E.cpp
+++ b/src/BLE_SP110E.cpp
@@ -3,14 +3,24 @@
#include "esp_log.h"
#include "WiFi.h"
#include "ATALights.h"
+#include "BleSettings.h"
static const char *tag = "BLE_SP110E";
-#define BT_SERVICE "FFE0"
-#define BT_SP110E_CHARACTERISTIC "FFE1"
+//#ifndef BT_SERVICE
+ // #define BT_SERVICE "FFE0"
+//#endif
+
+//#ifndef BT_SP110E_CHARACTERISTIC
+// #define BT_SP110E_CHARACTERISTIC "FFE1"
+//#endif
+
NimBLECharacteristic *pSP110ECharacteristic = nullptr;
-#define BT_STICK_CHARACTERISTIC "FFE2"
+//#ifndef BT_STICK_CHARACTERISTIC
+// #define BT_STICK_CHARACTERISTIC "FFE2"
+//#endif
+
NimBLECharacteristic *pStickCharacteristic = nullptr;
NimBLEClient* pStickClient;
@@ -258,11 +268,11 @@ void Init_BLE_SP110E(NimBLEServer* pServer) {
led_status.count_lsb = 20;
// Create BLE Service
- NimBLEService *pService = pServer->createService( BT_SERVICE );
+ NimBLEService *pService = pServer->createService( BTServiceUUID.c_str() ); // Use the defined service UUID
// Create FFE1 Characteristic with WRITE and NOTIFY properties
pSP110ECharacteristic = pService->createCharacteristic(
- BT_SP110E_CHARACTERISTIC,
+ BTSP110ECharacteristicUUID.c_str(),
NIMBLE_PROPERTY::WRITE | NIMBLE_PROPERTY::NOTIFY
);
@@ -272,7 +282,7 @@ void Init_BLE_SP110E(NimBLEServer* pServer) {
/************* Light Stick Characteristic ***************/
pStickCharacteristic = pService->createCharacteristic(
- BT_STICK_CHARACTERISTIC,
+ BTStickCharacteristicUUID.c_str(),
NIMBLE_PROPERTY::NOTIFY
);
@@ -288,7 +298,7 @@ void Init_BLE_SP110E(NimBLEServer* pServer) {
// Configure Advertising
NimBLEAdvertising *pAdvertising = NimBLEDevice::getAdvertising();
- pAdvertising->addServiceUUID( BT_SERVICE ); // Advertise the FFE0 service UUID
+ pAdvertising->addServiceUUID( BTServiceUUID.c_str() ); // Advertise the FFE0 service UUID
const uint8_t manufacturerData[] = {0x00, 0x00, 0x38, 0x93, 0x0E, 0x12, 0xAA, 0x08}; // Example Manufacturer Data
pAdvertising->setManufacturerData(std::string((char *)manufacturerData, sizeof(manufacturerData)));
@@ -333,13 +343,13 @@ void BLE_LightStick_Client_Task(void *parameter) {
ESP_LOGI(tag, "Connected to the server");
// Get the service.
- NimBLERemoteService* pRemoteService = pStickClient->getService(BT_SERVICE);
+ NimBLERemoteService* pRemoteService = pStickClient->getService(BTServiceUUID.c_str());
if (pRemoteService == nullptr) {
- ESP_LOGE(tag, "Failed to find service UUID: %s", BT_SERVICE);
+ ESP_LOGE(tag, "Failed to find service UUID: %s", BTServiceUUID.c_str());
pStickClient->disconnect();
} else {
// Get the characteristic.
- pRemoteCharacteristic = pRemoteService->getCharacteristic(BT_STICK_CHARACTERISTIC);
+ pRemoteCharacteristic = pRemoteService->getCharacteristic(BTStickCharacteristicUUID.c_str());
if (pRemoteCharacteristic != nullptr && pRemoteCharacteristic->canNotify()) {
pRemoteCharacteristic->subscribe(true, [](NimBLERemoteCharacteristic* pRemoteCharacteristic,
uint8_t* pData, size_t length, bool isNotify) {
diff --git a/src/BLE_UpdateService.cpp b/src/BLE_UpdateService.cpp
index 258b305..791db2b 100644
--- a/src/BLE_UpdateService.cpp
+++ b/src/BLE_UpdateService.cpp
@@ -4,12 +4,13 @@
#include "global.h"
#include "AppUpgrade.h"
#include "AppVersion.h"
+#include "BleSettings.h"
static const char *tag = "BLE_UpdateService";
-#define UPGRADE_SERVICE_UUID "abcdef01-2345-6789-1234-56789abcdef0"
-#define UPGRADE_CHARACTERISTIC1_UUID "abcdef01-2345-6789-1234-56789abcdef1"
-#define UPGRADE_CHARACTERISTIC2_UUID "abcdef02-2345-6789-1234-56789abcdef1"
+//#define UPGRADE_SERVICE_UUID "abcdef01-2345-6789-1234-56789abcdef0"
+//#define UPGRADE_CHARACTERISTIC1_UUID "abcdef01-2345-6789-1234-56789abcdef1"
+//#define UPGRADE_CHARACTERISTIC2_UUID "abcdef02-2345-6789-1234-56789abcdef1"
NimBLEService *pUpgradeService = nullptr;
NimBLECharacteristic *pUpgradeCharacteristic1 = nullptr;
@@ -42,7 +43,7 @@ class UpgradeChar_Callbacks : public NimBLECharacteristicCallbacks {
return;
}
- DynamicJsonDocument doc(512);
+ JsonDocument doc;
DeserializationError err = deserializeJson(doc, value.substr(jsonStart));
if (err) {
ESP_LOGW(tag, "JSON parse error for wifi-connect: %s", err.c_str());
@@ -138,10 +139,10 @@ void bleUpgrade_send_message(String s){
void Init_UpgradeBLEService(NimBLEServer *pServer){
// Create Upgrade BLE Service
- pUpgradeService= pServer->createService( UPGRADE_SERVICE_UUID );
+ pUpgradeService= pServer->createService( BTUpgradeServiceUUID.c_str() );
pUpgradeCharacteristic1 = pUpgradeService->createCharacteristic(
- UPGRADE_CHARACTERISTIC1_UUID,
+ BTUpgradeCharacteristic1UUID.c_str(),
NIMBLE_PROPERTY::READ | NIMBLE_PROPERTY::WRITE | NIMBLE_PROPERTY::NOTIFY
);
@@ -151,7 +152,7 @@ void Init_UpgradeBLEService(NimBLEServer *pServer){
pUpgradeCharacteristic2 = pUpgradeService->createCharacteristic(
- UPGRADE_CHARACTERISTIC2_UUID,
+ BTUpgradeCharacteristic2UUID.c_str(),
NIMBLE_PROPERTY::READ | NIMBLE_PROPERTY::NOTIFY
);
@@ -162,7 +163,7 @@ void Init_UpgradeBLEService(NimBLEServer *pServer){
pUpgradeService->start();
NimBLEAdvertising *pAdvertising = NimBLEDevice::getAdvertising();
- pAdvertising->addServiceUUID( UPGRADE_SERVICE_UUID ); // Advertise service UUID
+ pAdvertising->addServiceUUID( BTUpgradeServiceUUID.c_str() ); // Advertise service UUID
}
diff --git a/src/BleServer.cpp b/src/BleServer.cpp
index fa0c711..95ef79d 100644
--- a/src/BleServer.cpp
+++ b/src/BleServer.cpp
@@ -2,6 +2,7 @@
#include "esp_log.h"
#include "BLE_SP110E.h"
#include "BLE_UpdateService.h"
+#include "BleSettings.h"
static const char* tag = "BleServer";
@@ -36,8 +37,7 @@ void Init_BleServer( bool isSP110EActive, bool isUpgradeActive) {
ESP_LOGI(tag, "Initializing BLE...");
static bool isInitialized = false;
if (!isInitialized) {
- //NimBLEDevice::init("ATALIGHTS");
- NimBLEDevice::init("SP110E-ATA");
+ NimBLEDevice::init(BTDeviceName.c_str());
//NimBLEDevice::setMTU(247); // Set preferred MTU size (max 247 for BLE)
isInitialized = true;
}
diff --git a/src/BleSettings.cpp b/src/BleSettings.cpp
new file mode 100644
index 0000000..3e2d549
--- /dev/null
+++ b/src/BleSettings.cpp
@@ -0,0 +1,69 @@
+#include "BleSettings.h"
+#include "FS.h"
+#include
+#include
+#include "esp_log.h"
+
+static const char *tag = "ble-settings";
+
+// Global variables (initialized with defaults)
+String BTDeviceName = DEFAULT_BT_DEVICE_NAME;
+String BTServiceUUID = DEFAULT_BT_SERVICE;
+String BTSP110ECharacteristicUUID = DEFAULT_BT_SP110E_CHAR;
+String BTStickCharacteristicUUID = DEFAULT_BT_STICK_CHAR;
+String BTUpgradeServiceUUID = DEFAULT_UPGRADE_SERVICE;
+String BTUpgradeCharacteristic1UUID = DEFAULT_UPGRADE_CHAR1;
+String BTUpgradeCharacteristic2UUID = DEFAULT_UPGRADE_CHAR2;
+
+static String safeJsonString(JsonVariant obj, const char *key, const char *defVal) {
+ if (!obj.is()) return defVal;
+ JsonVariant v = obj[key];
+ if (!v.is()) return defVal;
+ const char *s = v.as();
+ if (!s || *s == '\0') return defVal;
+ return String(s);
+}
+
+void Load_BLE_Settings(const String &configPath) {
+ File file = LittleFS.open(configPath, "r");
+ if (!file) {
+ ESP_LOGW(tag, "Config %s not found. Using defaults.", configPath.c_str());
+ return; // keep defaults
+ }
+
+ // Use a dynamic document sized to file length (clamped)
+ size_t sz = file.size();
+ if (sz == 0 || sz > 4096) { // protect against unrealistically large file
+ ESP_LOGE(tag, "Invalid config size: %u", (unsigned)sz);
+ file.close();
+ return;
+ }
+
+ JsonDocument doc; // heuristic
+ DeserializationError error = deserializeJson(doc, file);
+ file.close();
+ if (error) {
+ ESP_LOGE(tag, "Deserialize error: %s", error.c_str());
+ return; // keep previous / defaults
+ }
+
+ JsonObject root = doc.as();
+ if (root.isNull()) {
+ ESP_LOGE(tag, "Empty JSON root");
+ return;
+ }
+
+ // Map expected keys
+ BTDeviceName = safeJsonString(root, "name", BTDeviceName.c_str());
+ BTServiceUUID = safeJsonString(root, "lights-service", BTServiceUUID.c_str());
+ BTSP110ECharacteristicUUID = safeJsonString(root, "lights-char", BTSP110ECharacteristicUUID.c_str());
+ BTStickCharacteristicUUID = safeJsonString(root, "stick-char", BTStickCharacteristicUUID.c_str());
+ BTUpgradeServiceUUID = safeJsonString(root, "upgrade-service", BTUpgradeServiceUUID.c_str());
+ BTUpgradeCharacteristic1UUID = safeJsonString(root, "upgrade-char1", BTUpgradeCharacteristic1UUID.c_str());
+ BTUpgradeCharacteristic2UUID = safeJsonString(root, "upgrade-char2", BTUpgradeCharacteristic2UUID.c_str());
+
+ ESP_LOGI(tag, "Loaded BLE config: name=%s svc=%s char1=%s stick=%s upg_svc=%s upg1=%s upg2=%s",
+ BTDeviceName.c_str(), BTServiceUUID.c_str(), BTSP110ECharacteristicUUID.c_str(),
+ BTStickCharacteristicUUID.c_str(), BTUpgradeServiceUUID.c_str(),
+ BTUpgradeCharacteristic1UUID.c_str(), BTUpgradeCharacteristic2UUID.c_str());
+}
\ No newline at end of file
diff --git a/src/global.cpp b/src/global.cpp
index 7b60b3f..388f280 100644
--- a/src/global.cpp
+++ b/src/global.cpp
@@ -45,7 +45,6 @@ void print_chip_info(void) {
print_ram_info();
}
-
void printTaskInfo(TaskStatus_t taskStatus) {
uint32_t ulTotalRunTime = taskStatus.ulRunTimeCounter;
uint32_t ulStatsAsPercentage = (ulTotalRunTime * 100) / ulTotalRunTime; // Total runtime equals 100%
diff --git a/src/main.cpp b/src/main.cpp
index b06911d..d6af7c7 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -33,6 +33,7 @@
#include "ATALights.h"
#include "OnEveryN.h"
#include "BLE_SP110E.h"
+#include "BleSettings.h"
#define FREERTOs_DIAGNOSTICS 0
#define OLED_ENABLED 0
@@ -69,6 +70,8 @@ PWM_Output *pwmOutputs[4];
RAMP_LIGHT *rampLight1;
RAMP_LIGHT *rampLight2;
+bool UpgradeMode = false;
+
void Init_ADC(void);
float readBoardInputVoltage(void);
void setupLogLevels(esp_log_level_t logLevel);
@@ -122,6 +125,10 @@ void setup()
// Load Board Pins
Load_Board_Pins(sys_settings.boardPins, board_file_path);
+ // Set status pins off
+ setStatusPin1(false);
+ setStatusPin2(false);
+
// Load Booth Settings
Load_Booth_Settings(sys_settings, booth_file_path);
@@ -143,17 +150,22 @@ void setup()
// Initialize Ramp Lights
Init_Ramp_Lights(sys_settings.rampLightSettings, boardButtons, pwmOutputs);
+ // Initialize ADC
+ Init_ADC();
+
// Initialize Temperature Sensor
Init_TSensor(72);
- Init_ADC();
float val = readBoardInputVoltage();
ESP_LOGI(tag, "Input Volage = %f", val);
// Initialize BLE
+ Load_BLE_Settings("/system/ble.json");
if (digitalRead(sys_settings.boardPins.btn[0]) == LOW)
{
+ setStatusPin1(true);
+ UpgradeMode = true;
ESP_LOGE(tag, "Enabling BLE and Update Service");
Init_BleServer(true, true);
ESP_LOGW(tag, "Enabling Wifi AP and Client");
@@ -198,7 +210,14 @@ void loop()
// Button Scanning
ON_EVERY_N_MILLISECONDS(10)
{
- if (boardButtons[0] != NULL)
+ for (int i = 0; i < 3; i++)
+ {
+ if (boardButtons[i] != NULL)
+ {
+ boardButtons[i]->tick();
+ }
+ }
+ /*
{
boardButtons[0]->tick();
}
@@ -210,6 +229,7 @@ void loop()
{
boardButtons[2]->tick();
}
+ */
}
// Temperature Monitor
@@ -232,10 +252,10 @@ void loop()
}
// Update Tune Playing
- if (anyrtttl::nonblocking::isPlaying())
- {
- anyrtttl::nonblocking::play();
- }
+ //if (anyrtttl::nonblocking::isPlaying())
+ //{
+ // anyrtttl::nonblocking::play();
+ //}
// Animation TestMode Timeout
#if LEDS_ENABLED
@@ -284,6 +304,14 @@ void loop()
}
}
+ // Upgrade Mode Tune
+ if(UpgradeMode){
+ ON_EVERY_N_MILLISECONDS(5000)
+ {
+ Buzzer_Play_Tune(TUNE_THUMP, true, true);
+ }
+ }
+
#if FREERTOs_DIAGNOSTICS
ON_EVERY_N_MILLISECONDS(60000)
{
diff --git a/src/my_buzzer.cpp b/src/my_buzzer.cpp
index 5452cbc..a45ccc9 100644
--- a/src/my_buzzer.cpp
+++ b/src/my_buzzer.cpp
@@ -33,32 +33,47 @@ void Init_Buzzer(int8_t pin, const char* configFile)
void Buzzer_Play_Tune(TUNE_TYPE tune, bool async, bool hasPriority)
{
static int prev_tune = -1;
- if(buzzPin < 0) return;
-
- if (hasPriority || !anyrtttl::nonblocking::isPlaying()) {
- if (anyrtttl::nonblocking::isPlaying()) {
- anyrtttl::nonblocking::stop();
- }
+ if (buzzPin < 0) return;
- // Load nonblocking if different from previous
- if (prev_tune != tune && async) {
- anyrtttl::nonblocking::begin(buzzPin, buzzTune[tune].melody.c_str());
- }
-
- ESP_LOGD(tag, "Playing tune: %d, melody: %s", tune, buzzTune[tune].melody.c_str());
-
- for (int c = 0; c < buzzTune[tune].cycles; c++) {
- if (async) {
- anyrtttl::nonblocking::play();
- } else {
- anyrtttl::blocking::play(buzzPin, buzzTune[tune].melody.c_str());
- }
- }
-
- prev_tune = tune;
- } else {
- ESP_LOGD(tag, "buzzer busy");
+ // Range / data validation
+ if (tune < 0 || tune >= TUNE_MAX_COUNT) {
+ ESP_LOGW(tag, "Invalid tune index: %d", (int)tune);
+ return;
}
+ const String &melody = buzzTune[tune].melody;
+ if (melody.isEmpty()) {
+ ESP_LOGW(tag, "Empty melody for tune %d", (int)tune);
+ return;
+ }
+
+ // Async mode: begin once, then caller should periodically call again to advance playback
+ if (async) {
+ bool playing = anyrtttl::nonblocking::isPlaying();
+ if (hasPriority && playing) {
+ anyrtttl::nonblocking::stop();
+ playing = false;
+ }
+ if (!playing || prev_tune != tune) {
+ // (Re)start tune
+ anyrtttl::nonblocking::begin(buzzPin, melody.c_str());
+ prev_tune = tune;
+ ESP_LOGD(tag, "Started async tune %d (%s)", (int)tune, melody.c_str());
+ }
+ // Advance playback one tick
+ anyrtttl::nonblocking::play();
+ return;
+ }
+
+ // Blocking mode: play full tune cycles with optional pause
+ ESP_LOGD(tag, "Playing blocking tune %d cycles=%d pause=%d", (int)tune, buzzTune[tune].cycles, buzzTune[tune].pause);
+ for (int c = 0; c < buzzTune[tune].cycles; ++c) {
+ anyrtttl::blocking::play(buzzPin, melody.c_str());
+ if (buzzTune[tune].pause > 0 && c + 1 < buzzTune[tune].cycles) {
+ delay(buzzTune[tune].pause); // simple pause between cycles
+ }
+ yield(); // allow other tasks to run
+ }
+ prev_tune = tune;
}
// TODO Buzzer Beep finish
diff --git a/src/my_wifi.cpp b/src/my_wifi.cpp
index a47f90c..c2d5ae2 100644
--- a/src/my_wifi.cpp
+++ b/src/my_wifi.cpp
@@ -20,7 +20,6 @@
static const char *tag = "WIFI";
-volatile bool WifiClientConnected = false;
volatile bool InternetAvailable;
AsyncWebServer webServer(80);
AsyncEventSource eventUpgradeProgress("/upgrade-progress");
@@ -125,7 +124,6 @@ bool StartWifiConnectTask(String ssid = "", String pass = "")
if (Wifi_Task_Handle == NULL)
{
ESP_LOGD(tag, "Creating WiFi task");
- WifiClientConnected = false;
xTaskCreatePinnedToCore(Wifi_ConnectTask, "Wifi_Task", 1024 * 4, NULL, 1, &Wifi_Task_Handle, 0);
}
else
@@ -148,9 +146,8 @@ void Wifi_ConnectTask(void *parameter)
static const char *tag = "Wifi_Task";
wifi_task_running = true;
- if (!WifiClientConnected || client_ssid != WiFi.SSID())
+ if (WiFi.status() != WL_CONNECTED || client_ssid != WiFi.SSID())
{
- WifiClientConnected = false;
ESP_LOGD(tag, "Connecting to: %s", client_ssid.c_str());
// Disconnect and connect to new network
@@ -181,7 +178,6 @@ void Wifi_ConnectTask(void *parameter)
if (WiFi.status() == WL_CONNECTED)
{
ESP_LOGI(tag, "Connected to %s", client_ssid.c_str());
- WifiClientConnected = true;
WiFi.setAutoReconnect(true);
if (!Wifi_Save_Credentials("/system/wifi.json"))
@@ -391,7 +387,7 @@ void Setup_WebServer_Handlers(AsyncWebServer &server)
request->send(200, "application/json", "{\"status\":\"connecting\"}"); });
server.on("/wifi/status", HTTP_GET, [](AsyncWebServerRequest *request)
{
- String jsonStr = "{\"status\":\"" + String(WifiClientConnected ? "Connected" : "Disconnected") +
+ String jsonStr = "{\"status\":\"" + String(WiFi.status() == WL_CONNECTED ? "Connected" : "Disconnected") +
"\",\"ip\":\"" + WiFi.localIP().toString() + "\"}";
request->send(200, "application/json", jsonStr); });
server.on("/wifi/scans", HTTP_GET, [](AsyncWebServerRequest *request)
@@ -547,7 +543,7 @@ void Setup_WebServer_Handlers(AsyncWebServer &server)
// System and LED related handlers
server.on("/system/summary", HTTP_GET, [](AsyncWebServerRequest *request)
{
- String response = "{\"status\":\"" + String(WifiClientConnected ? "Connected" : "Disconnected") + "\"}";
+ String response = "{\"status\":\"" + String(WiFi.status() == WL_CONNECTED ? "Connected" : "Disconnected") + "\"}";
request->send(200, "application/json", response); });
server.on("/leds/settings", HTTP_GET, [](AsyncWebServerRequest *request)
{
@@ -557,25 +553,25 @@ void Setup_WebServer_Handlers(AsyncWebServer &server)
serializeJson(jsDoc, summary);
request->send(200, "application/json", summary);
*/
- String response = "{\"status\":\"" + String(WifiClientConnected ? "Connected" : "Disconnected") + "\"}";
+ String response = "{\"status\":\"" + String(WiFi.status() == WL_CONNECTED ? "Connected" : "Disconnected") + "\"}";
request->send(200, "application/json", response); });
server.on("/leds/settings", HTTP_POST, [](AsyncWebServerRequest *request)
{
- String response = "{\"status\":\"" + String(WifiClientConnected ? "Connected" : "Disconnected") + "\"}";
+ String response = "{\"status\":\"" + String(WiFi.status() == WL_CONNECTED ? "Connected" : "Disconnected") + "\"}";
request->send(200, "application/json", response); });
// LightStik related handlers
server.on("/lightstik/settings", HTTP_GET, [](AsyncWebServerRequest *request)
{
- String response = "{\"status\":\"" + String(WifiClientConnected ? "Connected" : "Disconnected") + "\"}";
+ String response = "{\"status\":\"" + String(WiFi.status() == WL_CONNECTED ? "Connected" : "Disconnected") + "\"}";
request->send(200, "application/json", response); });
server.on("/lightstik/settings", HTTP_POST, [](AsyncWebServerRequest *request)
{
- String response = "{\"status\":\"" + String(WifiClientConnected ? "Connected" : "Disconnected") + "\"}";
+ String response = "{\"status\":\"" + String(WiFi.status() == WL_CONNECTED ? "Connected" : "Disconnected") + "\"}";
request->send(200, "application/json", response); });
server.on("/lightstik/register", HTTP_POST, [](AsyncWebServerRequest *request)
{
- String response = "{\"status\":\"" + String(WifiClientConnected ? "Connected" : "Disconnected") + "\"}";
+ String response = "{\"status\":\"" + String(WiFi.status() == WL_CONNECTED ? "Connected" : "Disconnected") + "\"}";
request->send(200, "application/json", response); });
// Firmware Update Handlers
@@ -934,7 +930,6 @@ void onWiFiEvent(WiFiEvent_t event)
ESP_LOGD(tag, "Connected to AP");
break;
case ARDUINO_EVENT_WIFI_STA_DISCONNECTED:
- WifiClientConnected = false;
ESP_LOGD(tag, "WiFi Disconnected");
setStatusPin1(false);
Buzzer_Play_Tune(TUNE_DISCONNECTED);
@@ -943,14 +938,12 @@ void onWiFiEvent(WiFiEvent_t event)
ESP_LOGD(tag, "Authentication mode of access point has changed");
break;
case ARDUINO_EVENT_WIFI_STA_GOT_IP:
- WifiClientConnected = true;
ESP_LOGD(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:
- WifiClientConnected = false;
ESP_LOGD(tag, "Lost IP address and IP address is reset to 0");
break;
case ARDUINO_EVENT_WPS_ER_SUCCESS:
diff --git a/temporary/ata-boothifier-upgrade(copy).html b/temporary/ata-boothifier-upgrade(copy).html
new file mode 100644
index 0000000..e69de29
diff --git a/z_old/wifi_temp.cpp b/z_old/wifi_temp.cpp
index 4d2645f..56bcacd 100644
--- a/z_old/wifi_temp.cpp
+++ b/z_old/wifi_temp.cpp
@@ -313,7 +313,7 @@ void Wifi_Save_Credentials(String newSSID, String newPass)
}
// Parse the JSON file
- DynamicJsonDocument doc(1024);
+ JsonDocument doc;
DeserializationError error = deserializeJson(doc, credsFile);
if(!error){
JsonObject cred1Json = doc.createNestedObject("cred1");
@@ -675,7 +675,8 @@ void postBody(AsyncWebServerRequest *request, uint8_t *data, size_t len, size_t
else if(!strncmp(dataType, "anim-profile", 12)){
if (strlen(dataType) > 12) {
int profile_index = (dataType[12] - '0' - 1) % 8; // extract index, assuming dataType has enough characters
- DynamicJsonDocument profJson(4 * 1024);
+ //DynamicJsonDocument profJson(4 * 1024);
+ JsonDocument profJson;
DeserializationError error = deserializeJson(profJson, postData, total);
if(!error){
@@ -711,7 +712,7 @@ void postBody(AsyncWebServerRequest *request, uint8_t *data, size_t len, size_t
}
}
else if(!strcmp(dataType, "play-anim")){
- DynamicJsonDocument animData(1024);
+ JsonDocument animData;
DeserializationError error = deserializeJson(animData, postData, total);
if(!error){
ANIMATION_EVENT testEvent;
@@ -765,7 +766,7 @@ void postBody(AsyncWebServerRequest *request, uint8_t *data, size_t len, size_t
getpostSuccess = true;
}
else if(!strcmp(dataType, "set-pixel")){
- DynamicJsonDocument js(1024);
+ JsonDocument js;
DeserializationError error = deserializeJson(js, postData, total);
if(!error){
ANIMATION_EVENT testEvent;
@@ -796,7 +797,7 @@ void postBody(AsyncWebServerRequest *request, uint8_t *data, size_t len, size_t
Buzzer_Beep(50, 3000);
}
else if(!strcmp(dataType, "setup-save")){
- DynamicJsonDocument js(1024);
+ JsonDocument js;
DeserializationError error = deserializeJson(js, postData, total);
if(!error){
// If app index is different open app-events.json and update
@@ -808,7 +809,7 @@ void postBody(AsyncWebServerRequest *request, uint8_t *data, size_t len, size_t
return;
}
- DynamicJsonDocument doc(2048);
+ JsonDocument doc;
DeserializationError error = deserializeJson(doc, file);
file.close();
@@ -846,7 +847,7 @@ void postBody(AsyncWebServerRequest *request, uint8_t *data, size_t len, size_t
return;
}
- DynamicJsonDocument doc(2048);
+ JsonDocument doc;
DeserializationError error = deserializeJson(doc, file);
file.close();