Compare commits
82 commits
web-native
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
aacfeb9911 | ||
|
|
c9dd1a2902 | ||
|
|
df2cb16499 | ||
|
|
f98a5429e3 | ||
|
|
a0eb1a6833 | ||
|
|
d38264a533 | ||
|
|
c320cf79b1 | ||
|
|
38dab380be | ||
|
|
6f9633db41 | ||
|
|
8fa835a11b | ||
|
|
aafc9aeb59 | ||
|
|
37a7a0a668 | ||
|
|
b70abd72ea | ||
|
|
94847e7792 | ||
|
|
053e675503 | ||
|
|
ff9790297e | ||
|
|
6dcfecc8cb | ||
|
|
129875768f | ||
|
|
04918f1d11 | ||
|
|
9fa0d9c025 | ||
|
|
0b0b767d6c | ||
|
|
b2d32ea9a7 | ||
|
|
8b8aa8efd0 | ||
|
|
0158a39fc6 | ||
|
|
5923445413 | ||
|
|
a5f81a5053 | ||
|
|
8b0068859b | ||
|
|
f44d1ab582 | ||
|
|
3a4fd3e8df | ||
|
|
6ef92f1809 | ||
|
|
4ace2bc551 | ||
|
|
f2f36f039d | ||
|
|
74074b1973 | ||
|
|
8f3a6df7be | ||
|
|
9b02dc97b8 | ||
|
|
3dd3c637a7 | ||
|
|
8467d92062 | ||
|
|
036492889e | ||
|
|
38a1794a32 | ||
|
|
1c8273c1ba | ||
|
|
684427ae77 | ||
|
|
08a4e9b2b2 | ||
|
|
189b306683 | ||
|
|
f67593fc9f | ||
|
|
c42f98f149 | ||
|
|
1f78bc096c | ||
|
|
44e42807f5 | ||
|
|
07039fdd66 | ||
|
|
869ba82b9a | ||
|
|
bcb8b4e4ca | ||
|
|
3ef787e79e | ||
|
|
3e41dc1bd4 | ||
|
|
835a05c769 | ||
|
|
eb673ca465 | ||
|
|
d33fb423bd | ||
|
|
935de10302 | ||
|
|
1e65b05eb3 | ||
|
|
ca2412d5a7 | ||
|
|
07daf2ba6b | ||
|
|
d8bea463ab | ||
|
|
fc160d0ec5 | ||
|
|
12c5d5f686 | ||
|
|
e97ff1003f | ||
|
|
b40ab1405a | ||
|
|
9dd14ab71c | ||
|
|
7bde129844 | ||
|
|
8996ab0661 | ||
|
|
02cc369eb0 | ||
|
|
daa4ec8503 | ||
|
|
b34994845b | ||
|
|
e3dd1baf5c | ||
|
|
fcf757c9b9 | ||
|
|
24f117a110 | ||
|
|
b874489933 | ||
|
|
3032861ab1 | ||
|
|
33a94b2075 | ||
|
|
e6a8a16db4 | ||
|
|
b442fc7bb8 | ||
|
|
c6028d6788 | ||
|
|
e268e11d35 | ||
|
|
9bc8652835 | ||
|
|
9207e9ea53 |
14 changed files with 10730 additions and 8626 deletions
4
.github/workflows/daily-update.yml
vendored
4
.github/workflows/daily-update.yml
vendored
|
|
@ -42,9 +42,9 @@ jobs:
|
||||||
git submodule init
|
git submodule init
|
||||||
git submodule update --recursive
|
git submodule update --recursive
|
||||||
cd Wippersnapper_Boards
|
cd Wippersnapper_Boards
|
||||||
git reset --hard origin/rp2040_datalogger_feather
|
git reset --hard origin/offline-mode
|
||||||
cd ../Wippersnapper_Components
|
cd ../Wippersnapper_Components
|
||||||
git reset --hard origin/main
|
git reset --hard origin/offline-mode
|
||||||
cd ..
|
cd ..
|
||||||
git add Wippersnapper_Boards Wippersnapper_Components
|
git add Wippersnapper_Boards Wippersnapper_Components
|
||||||
git diff --staged --quiet || git commit -m "Update submodules to latest versions [skip ci]"
|
git diff --staged --quiet || git commit -m "Update submodules to latest versions [skip ci]"
|
||||||
|
|
|
||||||
3
.gitignore
vendored
3
.gitignore
vendored
|
|
@ -3,3 +3,6 @@
|
||||||
__pycache__/
|
__pycache__/
|
||||||
*.pyc
|
*.pyc
|
||||||
|
|
||||||
|
bin/
|
||||||
|
lib/
|
||||||
|
pyvenv.cfg
|
||||||
1
.gitmodules
vendored
1
.gitmodules
vendored
|
|
@ -4,3 +4,4 @@
|
||||||
[submodule "Wippersnapper_Components"]
|
[submodule "Wippersnapper_Components"]
|
||||||
path = Wippersnapper_Components
|
path = Wippersnapper_Components
|
||||||
url = https://github.com/adafruit/Wippersnapper_Components
|
url = https://github.com/adafruit/Wippersnapper_Components
|
||||||
|
branch = offline-mode
|
||||||
|
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
Subproject commit 66d399578444320a039514f1a41160a0c2357212
|
Subproject commit 941e94a52bbe1f33aed3328ddd0ec7a5f3adfbd0
|
||||||
|
|
@ -1 +1 @@
|
||||||
Subproject commit 1f7823e15ee49acffb15aab2cc947ea7d1ad6619
|
Subproject commit dc7f57cb1697e4efc4e9490cc51b7ec569f32c15
|
||||||
|
|
@ -156,7 +156,70 @@ def convert_components_to_json():
|
||||||
component_info["channels"] = 8
|
component_info["channels"] = 8
|
||||||
else:
|
else:
|
||||||
component_info["channels"] = 4
|
component_info["channels"] = 4
|
||||||
|
|
||||||
|
# Special handling for GPS over I2C
|
||||||
|
if component_data.get("isGps", False):
|
||||||
|
component_info["isGps"] = True
|
||||||
|
component_info["gps"] = {}
|
||||||
|
gps_data = component_data.get("gps", {})
|
||||||
|
component_info["gps"]["period"] = gps_data.get("period", 30000)
|
||||||
|
if "commands_ubxes" in gps_data:
|
||||||
|
component_info["gps"]["commands_ubxes"] = gps_data["commands_ubxes"]
|
||||||
|
if "commands_pmtks" in gps_data:
|
||||||
|
component_info["gps"]["commands_pmtks"] = gps_data["commands_pmtks"]
|
||||||
|
|
||||||
|
# Handle UART-specific properties
|
||||||
|
if category == "uart":
|
||||||
|
# Required properties
|
||||||
|
component_info["deviceType"] = component_data.get("deviceType")
|
||||||
|
component_info["deviceId"] = component_data.get("deviceId")
|
||||||
|
# Specific deviceType properties
|
||||||
|
if component_info["deviceType"] == "generic_input":
|
||||||
|
component_info["generic_input"] = {}
|
||||||
|
generic_input_data = component_data.get("generic_input", {})
|
||||||
|
component_info["generic_input"]["period"] = generic_input_data.get("period", 30000)
|
||||||
|
# Extract data types
|
||||||
|
if "generic_input" in component_data and "sensor_types" in component_data["generic_input"]:
|
||||||
|
for meas_type in component_data["generic_input"]["sensor_types"]:
|
||||||
|
if isinstance(meas_type, dict) and "sensorType" in meas_type:
|
||||||
|
component_info["dataTypes"].append({
|
||||||
|
"displayName": meas_type["displayName"] if "displayName" in meas_type else meas_type["sensorType"],
|
||||||
|
"sensorType": map_datatypes_to_offline_types(meas_type["sensorType"]) if "sensorType" in meas_type else None
|
||||||
|
})
|
||||||
|
else:
|
||||||
|
component_info["dataTypes"].append(map_datatypes_to_offline_types(meas_type))
|
||||||
|
elif component_info["deviceType"] == "gps":
|
||||||
|
component_info["gps"] = {}
|
||||||
|
gps_data = component_data.get("gps", {})
|
||||||
|
component_info["gps"]["period"] = gps_data.get("period", 30000)
|
||||||
|
if "commands_ubxes" in gps_data:
|
||||||
|
component_info["gps"]["commands_ubxes"] = gps_data["commands_ubxes"]
|
||||||
|
if "commands_pmtks" in gps_data:
|
||||||
|
component_info["gps"]["commands_pmtks"] = gps_data["commands_pmtks"]
|
||||||
|
elif component_info["deviceType"] == "pm25aqi":
|
||||||
|
component_info["pm25aqi"] = {}
|
||||||
|
# Parse PM2.5 AQI properties
|
||||||
|
if "pm25aqi" in component_data:
|
||||||
|
component_info["pm25aqi"]["period"] = component_data["pm25aqi"].get("period", 30000) # Default to 30s if not specified
|
||||||
|
if component_data["pm25aqi"].get("is_pm1006", False):
|
||||||
|
component_info["pm25aqi"]["is_pm1006"] = True
|
||||||
|
# Extract data types
|
||||||
|
pm25aqi_data = component_data
|
||||||
|
if "pm25aqi" in pm25aqi_data and "sensor_types" in pm25aqi_data["pm25aqi"]:
|
||||||
|
for meas_type in pm25aqi_data["pm25aqi"]["sensor_types"]:
|
||||||
|
if isinstance(meas_type, dict) and "sensorType" in meas_type:
|
||||||
|
component_info["dataTypes"].append({
|
||||||
|
"displayName": meas_type["displayName"] if "displayName" in meas_type else meas_type["sensorType"],
|
||||||
|
"sensorType": map_datatypes_to_offline_types(meas_type["sensorType"]) if "sensorType" in meas_type else None
|
||||||
|
})
|
||||||
|
else:
|
||||||
|
component_info["dataTypes"].append(map_datatypes_to_offline_types(meas_type))
|
||||||
|
elif component_info["deviceType"] == "tmc22xx":
|
||||||
|
# TODO
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
raise ValueError(f"Unknown deviceType {component_info['deviceType']} for {category}/{component_dir}")
|
||||||
|
|
||||||
# Look for an image file
|
# Look for an image file
|
||||||
image_extensions = ['.jpg', '.jpeg', '.png', '.gif', '.svg']
|
image_extensions = ['.jpg', '.jpeg', '.png', '.gif', '.svg']
|
||||||
image_found = False
|
image_found = False
|
||||||
|
|
@ -207,12 +270,12 @@ def convert_components_to_json():
|
||||||
|
|
||||||
# Write the consolidated JSON file
|
# Write the consolidated JSON file
|
||||||
with open(OUTPUT_FILE, 'w') as f:
|
with open(OUTPUT_FILE, 'w') as f:
|
||||||
json.dump({"components": components}, f, indent=2)
|
json.dump({"components": components}, f, ensure_ascii=False, indent=2)
|
||||||
|
|
||||||
# Write the consolidated JS file
|
# Write the consolidated JS file
|
||||||
with open(OUTPUT_FILE.replace('.json', '.js'), 'w') as f:
|
with open(OUTPUT_FILE.replace('.json', '.js'), 'w') as f:
|
||||||
f.write("window.jsonComponentsObject = ")
|
f.write("window.jsonComponentsObject = ")
|
||||||
json.dump({"components": components}, f, indent=2)
|
json.dump({"components": components}, f, ensure_ascii=False, indent=2)
|
||||||
f.write(";\n")
|
f.write(";\n")
|
||||||
|
|
||||||
print(f"Successfully created {OUTPUT_FILE}")
|
print(f"Successfully created {OUTPUT_FILE}")
|
||||||
|
|
|
||||||
258
firmware-data.js
258
firmware-data.js
|
|
@ -1,139 +1,155 @@
|
||||||
// Auto-generated on 2025-07-30 00:22:35
|
// Auto-generated on 2025-08-29 00:19:42
|
||||||
const FIRMWARE_DATA = {
|
const FIRMWARE_DATA = {
|
||||||
"releaseInfo": {
|
"releaseInfo": {
|
||||||
"version": "1.0.0-offline-beta.3",
|
"version": "1.0.0-offline-beta.4",
|
||||||
"name": "WipperSnapper Offline 1.0.0-offline-beta.3",
|
"name": "WipperSnapper Offline 1.0.0-offline-beta.4",
|
||||||
"url": "https://github.com/adafruit/Adafruit_Wippersnapper_Arduino/releases/tag/1.0.0-offline-beta.3",
|
"url": "https://github.com/adafruit/Adafruit_Wippersnapper_Arduino/releases/tag/1.0.0-offline-beta.4",
|
||||||
"publishedDate": "2025-05-13"
|
"publishedDate": "2025-08-18"
|
||||||
},
|
},
|
||||||
"firmwareFiles": [
|
"firmwareFiles": [
|
||||||
{
|
{
|
||||||
"name": "wippersnapper.feather_esp32s2.1.0.0-offline-beta.3.uf2",
|
"name": "wippersnapper.esp32s3_devkitc_1_n8.1.0.0-offline-beta.4.uf2",
|
||||||
"url": "https://github.com/adafruit/Adafruit_Wippersnapper_Arduino/releases/download/1.0.0-offline-beta.3/wippersnapper.feather_esp32s2.1.0.0-offline-beta.3.uf2",
|
"url": "https://github.com/adafruit/Adafruit_Wippersnapper_Arduino/releases/download/1.0.0-offline-beta.4/wippersnapper.esp32s3_devkitc_1_n8.1.0.0-offline-beta.4.uf2",
|
||||||
"size": 2779136,
|
"size": 3044864,
|
||||||
"downloadCount": 1,
|
|
||||||
"contentType": "application/octet-stream",
|
|
||||||
"createdAt": "2025-05-13T17:26:26Z"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "wippersnapper.feather_esp32s2_reverse_tft.1.0.0-offline-beta.3.uf2",
|
|
||||||
"url": "https://github.com/adafruit/Adafruit_Wippersnapper_Arduino/releases/download/1.0.0-offline-beta.3/wippersnapper.feather_esp32s2_reverse_tft.1.0.0-offline-beta.3.uf2",
|
|
||||||
"size": 2779136,
|
|
||||||
"downloadCount": 1,
|
|
||||||
"contentType": "application/octet-stream",
|
|
||||||
"createdAt": "2025-05-13T17:26:26Z"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "wippersnapper.feather_esp32s2_tft.1.0.0-offline-beta.3.uf2",
|
|
||||||
"url": "https://github.com/adafruit/Adafruit_Wippersnapper_Arduino/releases/download/1.0.0-offline-beta.3/wippersnapper.feather_esp32s2_tft.1.0.0-offline-beta.3.uf2",
|
|
||||||
"size": 2778624,
|
|
||||||
"downloadCount": 2,
|
|
||||||
"contentType": "application/octet-stream",
|
|
||||||
"createdAt": "2025-05-13T17:26:26Z"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "wippersnapper.feather_esp32s3.1.0.0-offline-beta.3.uf2",
|
|
||||||
"url": "https://github.com/adafruit/Adafruit_Wippersnapper_Arduino/releases/download/1.0.0-offline-beta.3/wippersnapper.feather_esp32s3.1.0.0-offline-beta.3.uf2",
|
|
||||||
"size": 2836480,
|
|
||||||
"downloadCount": 1,
|
|
||||||
"contentType": "application/octet-stream",
|
|
||||||
"createdAt": "2025-05-13T17:26:26Z"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "wippersnapper.feather_esp32s3_4mbflash_2mbpsram.1.0.0-offline-beta.3.uf2",
|
|
||||||
"url": "https://github.com/adafruit/Adafruit_Wippersnapper_Arduino/releases/download/1.0.0-offline-beta.3/wippersnapper.feather_esp32s3_4mbflash_2mbpsram.1.0.0-offline-beta.3.uf2",
|
|
||||||
"size": 2842112,
|
|
||||||
"downloadCount": 1,
|
|
||||||
"contentType": "application/octet-stream",
|
|
||||||
"createdAt": "2025-05-13T17:26:26Z"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "wippersnapper.feather_esp32s3_reverse_tft.1.0.0-offline-beta.3.uf2",
|
|
||||||
"url": "https://github.com/adafruit/Adafruit_Wippersnapper_Arduino/releases/download/1.0.0-offline-beta.3/wippersnapper.feather_esp32s3_reverse_tft.1.0.0-offline-beta.3.uf2",
|
|
||||||
"size": 2842112,
|
|
||||||
"downloadCount": 1,
|
|
||||||
"contentType": "application/octet-stream",
|
|
||||||
"createdAt": "2025-05-13T17:26:26Z"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "wippersnapper.feather_esp32s3_tft.1.0.0-offline-beta.3.uf2",
|
|
||||||
"url": "https://github.com/adafruit/Adafruit_Wippersnapper_Arduino/releases/download/1.0.0-offline-beta.3/wippersnapper.feather_esp32s3_tft.1.0.0-offline-beta.3.uf2",
|
|
||||||
"size": 2842112,
|
|
||||||
"downloadCount": 0,
|
"downloadCount": 0,
|
||||||
"contentType": "application/octet-stream",
|
"contentType": "application/octet-stream",
|
||||||
"createdAt": "2025-05-13T17:26:26Z"
|
"createdAt": "2025-08-18T17:38:47Z"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "wippersnapper.feather_rp2040_adalogger_tinyusb.1.0.0-offline-beta.3.uf2",
|
"name": "wippersnapper.feather_esp32s2.1.0.0-offline-beta.4.uf2",
|
||||||
"url": "https://github.com/adafruit/Adafruit_Wippersnapper_Arduino/releases/download/1.0.0-offline-beta.3/wippersnapper.feather_rp2040_adalogger_tinyusb.1.0.0-offline-beta.3.uf2",
|
"url": "https://github.com/adafruit/Adafruit_Wippersnapper_Arduino/releases/download/1.0.0-offline-beta.4/wippersnapper.feather_esp32s2.1.0.0-offline-beta.4.uf2",
|
||||||
"size": 669696,
|
"size": 2990080,
|
||||||
"downloadCount": 8,
|
|
||||||
"contentType": "application/octet-stream",
|
|
||||||
"createdAt": "2025-05-13T17:26:26Z"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "wippersnapper.metroesp32s2.1.0.0-offline-beta.3.uf2",
|
|
||||||
"url": "https://github.com/adafruit/Adafruit_Wippersnapper_Arduino/releases/download/1.0.0-offline-beta.3/wippersnapper.metroesp32s2.1.0.0-offline-beta.3.uf2",
|
|
||||||
"size": 2778624,
|
|
||||||
"downloadCount": 1,
|
|
||||||
"contentType": "application/octet-stream",
|
|
||||||
"createdAt": "2025-05-13T17:26:26Z"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "wippersnapper.metro_esp32s3.1.0.0-offline-beta.3.uf2",
|
|
||||||
"url": "https://github.com/adafruit/Adafruit_Wippersnapper_Arduino/releases/download/1.0.0-offline-beta.3/wippersnapper.metro_esp32s3.1.0.0-offline-beta.3.uf2",
|
|
||||||
"size": 2846208,
|
|
||||||
"downloadCount": 0,
|
"downloadCount": 0,
|
||||||
"contentType": "application/octet-stream",
|
"contentType": "application/octet-stream",
|
||||||
"createdAt": "2025-05-13T17:26:26Z"
|
"createdAt": "2025-08-18T17:38:47Z"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "wippersnapper.metro_rp2350_tinyusb.1.0.0-offline-beta.3.uf2",
|
"name": "wippersnapper.feather_esp32s2_reverse_tft.1.0.0-offline-beta.4.uf2",
|
||||||
"url": "https://github.com/adafruit/Adafruit_Wippersnapper_Arduino/releases/download/1.0.0-offline-beta.3/wippersnapper.metro_rp2350_tinyusb.1.0.0-offline-beta.3.uf2",
|
"url": "https://github.com/adafruit/Adafruit_Wippersnapper_Arduino/releases/download/1.0.0-offline-beta.4/wippersnapper.feather_esp32s2_reverse_tft.1.0.0-offline-beta.4.uf2",
|
||||||
"size": 674304,
|
"size": 2990080,
|
||||||
"downloadCount": 2,
|
|
||||||
"contentType": "application/octet-stream",
|
|
||||||
"createdAt": "2025-05-13T17:26:26Z"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "wippersnapper.pico_rp2040_tinyusb.1.0.0-offline-beta.3.uf2",
|
|
||||||
"url": "https://github.com/adafruit/Adafruit_Wippersnapper_Arduino/releases/download/1.0.0-offline-beta.3/wippersnapper.pico_rp2040_tinyusb.1.0.0-offline-beta.3.uf2",
|
|
||||||
"size": 667648,
|
|
||||||
"downloadCount": 2,
|
|
||||||
"contentType": "application/octet-stream",
|
|
||||||
"createdAt": "2025-05-13T17:26:26Z"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "wippersnapper.pico_rp2350_tinyusb.1.0.0-offline-beta.3.uf2",
|
|
||||||
"url": "https://github.com/adafruit/Adafruit_Wippersnapper_Arduino/releases/download/1.0.0-offline-beta.3/wippersnapper.pico_rp2350_tinyusb.1.0.0-offline-beta.3.uf2",
|
|
||||||
"size": 659456,
|
|
||||||
"downloadCount": 1,
|
|
||||||
"contentType": "application/octet-stream",
|
|
||||||
"createdAt": "2025-05-13T17:26:26Z"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "wippersnapper.qtpy_esp32s2.1.0.0-offline-beta.3.uf2",
|
|
||||||
"url": "https://github.com/adafruit/Adafruit_Wippersnapper_Arduino/releases/download/1.0.0-offline-beta.3/wippersnapper.qtpy_esp32s2.1.0.0-offline-beta.3.uf2",
|
|
||||||
"size": 2778624,
|
|
||||||
"downloadCount": 3,
|
|
||||||
"contentType": "application/octet-stream",
|
|
||||||
"createdAt": "2025-05-13T17:26:26Z"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "wippersnapper.qtpy_esp32s3.1.0.0-offline-beta.3.uf2",
|
|
||||||
"url": "https://github.com/adafruit/Adafruit_Wippersnapper_Arduino/releases/download/1.0.0-offline-beta.3/wippersnapper.qtpy_esp32s3.1.0.0-offline-beta.3.uf2",
|
|
||||||
"size": 2836480,
|
|
||||||
"downloadCount": 1,
|
|
||||||
"contentType": "application/octet-stream",
|
|
||||||
"createdAt": "2025-05-13T17:26:26Z"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "wippersnapper.qtpy_esp32s3_n4r2.1.0.0-offline-beta.3.uf2",
|
|
||||||
"url": "https://github.com/adafruit/Adafruit_Wippersnapper_Arduino/releases/download/1.0.0-offline-beta.3/wippersnapper.qtpy_esp32s3_n4r2.1.0.0-offline-beta.3.uf2",
|
|
||||||
"size": 2842112,
|
|
||||||
"downloadCount": 0,
|
"downloadCount": 0,
|
||||||
"contentType": "application/octet-stream",
|
"contentType": "application/octet-stream",
|
||||||
"createdAt": "2025-05-13T17:26:26Z"
|
"createdAt": "2025-08-18T17:38:47Z"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "wippersnapper.feather_esp32s2_tft.1.0.0-offline-beta.4.uf2",
|
||||||
|
"url": "https://github.com/adafruit/Adafruit_Wippersnapper_Arduino/releases/download/1.0.0-offline-beta.4/wippersnapper.feather_esp32s2_tft.1.0.0-offline-beta.4.uf2",
|
||||||
|
"size": 2990080,
|
||||||
|
"downloadCount": 0,
|
||||||
|
"contentType": "application/octet-stream",
|
||||||
|
"createdAt": "2025-08-18T17:38:47Z"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "wippersnapper.feather_esp32s3.1.0.0-offline-beta.4.uf2",
|
||||||
|
"url": "https://github.com/adafruit/Adafruit_Wippersnapper_Arduino/releases/download/1.0.0-offline-beta.4/wippersnapper.feather_esp32s3.1.0.0-offline-beta.4.uf2",
|
||||||
|
"size": 3044864,
|
||||||
|
"downloadCount": 0,
|
||||||
|
"contentType": "application/octet-stream",
|
||||||
|
"createdAt": "2025-08-18T17:38:47Z"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "wippersnapper.feather_esp32s3_4mbflash_2mbpsram.1.0.0-offline-beta.4.uf2",
|
||||||
|
"url": "https://github.com/adafruit/Adafruit_Wippersnapper_Arduino/releases/download/1.0.0-offline-beta.4/wippersnapper.feather_esp32s3_4mbflash_2mbpsram.1.0.0-offline-beta.4.uf2",
|
||||||
|
"size": 3050496,
|
||||||
|
"downloadCount": 0,
|
||||||
|
"contentType": "application/octet-stream",
|
||||||
|
"createdAt": "2025-08-18T17:38:47Z"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "wippersnapper.feather_esp32s3_reverse_tft.1.0.0-offline-beta.4.uf2",
|
||||||
|
"url": "https://github.com/adafruit/Adafruit_Wippersnapper_Arduino/releases/download/1.0.0-offline-beta.4/wippersnapper.feather_esp32s3_reverse_tft.1.0.0-offline-beta.4.uf2",
|
||||||
|
"size": 3050496,
|
||||||
|
"downloadCount": 0,
|
||||||
|
"contentType": "application/octet-stream",
|
||||||
|
"createdAt": "2025-08-18T17:38:47Z"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "wippersnapper.feather_esp32s3_tft.1.0.0-offline-beta.4.uf2",
|
||||||
|
"url": "https://github.com/adafruit/Adafruit_Wippersnapper_Arduino/releases/download/1.0.0-offline-beta.4/wippersnapper.feather_esp32s3_tft.1.0.0-offline-beta.4.uf2",
|
||||||
|
"size": 3050496,
|
||||||
|
"downloadCount": 0,
|
||||||
|
"contentType": "application/octet-stream",
|
||||||
|
"createdAt": "2025-08-18T17:38:47Z"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "wippersnapper.feather_rp2040_adalogger_tinyusb.1.0.0-offline-beta.4.uf2",
|
||||||
|
"url": "https://github.com/adafruit/Adafruit_Wippersnapper_Arduino/releases/download/1.0.0-offline-beta.4/wippersnapper.feather_rp2040_adalogger_tinyusb.1.0.0-offline-beta.4.uf2",
|
||||||
|
"size": 863232,
|
||||||
|
"downloadCount": 0,
|
||||||
|
"contentType": "application/octet-stream",
|
||||||
|
"createdAt": "2025-08-18T17:38:47Z"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "wippersnapper.metroesp32s2.1.0.0-offline-beta.4.uf2",
|
||||||
|
"url": "https://github.com/adafruit/Adafruit_Wippersnapper_Arduino/releases/download/1.0.0-offline-beta.4/wippersnapper.metroesp32s2.1.0.0-offline-beta.4.uf2",
|
||||||
|
"size": 2989568,
|
||||||
|
"downloadCount": 0,
|
||||||
|
"contentType": "application/octet-stream",
|
||||||
|
"createdAt": "2025-08-18T17:38:47Z"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "wippersnapper.metro_esp32s3.1.0.0-offline-beta.4.uf2",
|
||||||
|
"url": "https://github.com/adafruit/Adafruit_Wippersnapper_Arduino/releases/download/1.0.0-offline-beta.4/wippersnapper.metro_esp32s3.1.0.0-offline-beta.4.uf2",
|
||||||
|
"size": 3054592,
|
||||||
|
"downloadCount": 0,
|
||||||
|
"contentType": "application/octet-stream",
|
||||||
|
"createdAt": "2025-08-18T17:38:47Z"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "wippersnapper.metro_rp2350_tinyusb.1.0.0-offline-beta.4.uf2",
|
||||||
|
"url": "https://github.com/adafruit/Adafruit_Wippersnapper_Arduino/releases/download/1.0.0-offline-beta.4/wippersnapper.metro_rp2350_tinyusb.1.0.0-offline-beta.4.uf2",
|
||||||
|
"size": 872960,
|
||||||
|
"downloadCount": 0,
|
||||||
|
"contentType": "application/octet-stream",
|
||||||
|
"createdAt": "2025-08-18T17:38:47Z"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "wippersnapper.pico_rp2040_tinyusb.1.0.0-offline-beta.4.uf2",
|
||||||
|
"url": "https://github.com/adafruit/Adafruit_Wippersnapper_Arduino/releases/download/1.0.0-offline-beta.4/wippersnapper.pico_rp2040_tinyusb.1.0.0-offline-beta.4.uf2",
|
||||||
|
"size": 862208,
|
||||||
|
"downloadCount": 0,
|
||||||
|
"contentType": "application/octet-stream",
|
||||||
|
"createdAt": "2025-08-18T17:38:47Z"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "wippersnapper.pico_rp2350_tinyusb.1.0.0-offline-beta.4.uf2",
|
||||||
|
"url": "https://github.com/adafruit/Adafruit_Wippersnapper_Arduino/releases/download/1.0.0-offline-beta.4/wippersnapper.pico_rp2350_tinyusb.1.0.0-offline-beta.4.uf2",
|
||||||
|
"size": 858112,
|
||||||
|
"downloadCount": 0,
|
||||||
|
"contentType": "application/octet-stream",
|
||||||
|
"createdAt": "2025-08-18T17:38:47Z"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "wippersnapper.qtpy_esp32s2.1.0.0-offline-beta.4.uf2",
|
||||||
|
"url": "https://github.com/adafruit/Adafruit_Wippersnapper_Arduino/releases/download/1.0.0-offline-beta.4/wippersnapper.qtpy_esp32s2.1.0.0-offline-beta.4.uf2",
|
||||||
|
"size": 2989568,
|
||||||
|
"downloadCount": 0,
|
||||||
|
"contentType": "application/octet-stream",
|
||||||
|
"createdAt": "2025-08-18T17:38:47Z"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "wippersnapper.qtpy_esp32s3.1.0.0-offline-beta.4.uf2",
|
||||||
|
"url": "https://github.com/adafruit/Adafruit_Wippersnapper_Arduino/releases/download/1.0.0-offline-beta.4/wippersnapper.qtpy_esp32s3.1.0.0-offline-beta.4.uf2",
|
||||||
|
"size": 3044352,
|
||||||
|
"downloadCount": 0,
|
||||||
|
"contentType": "application/octet-stream",
|
||||||
|
"createdAt": "2025-08-18T17:38:47Z"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "wippersnapper.qtpy_esp32s3_n4r2.1.0.0-offline-beta.4.uf2",
|
||||||
|
"url": "https://github.com/adafruit/Adafruit_Wippersnapper_Arduino/releases/download/1.0.0-offline-beta.4/wippersnapper.qtpy_esp32s3_n4r2.1.0.0-offline-beta.4.uf2",
|
||||||
|
"size": 3050496,
|
||||||
|
"downloadCount": 0,
|
||||||
|
"contentType": "application/octet-stream",
|
||||||
|
"createdAt": "2025-08-18T17:38:47Z"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "wippersnapper.xiao_esp32s3.1.0.0-offline-beta.4.uf2",
|
||||||
|
"url": "https://github.com/adafruit/Adafruit_Wippersnapper_Arduino/releases/download/1.0.0-offline-beta.4/wippersnapper.xiao_esp32s3.1.0.0-offline-beta.4.uf2",
|
||||||
|
"size": 3145728,
|
||||||
|
"downloadCount": 0,
|
||||||
|
"contentType": "application/octet-stream",
|
||||||
|
"createdAt": "2025-08-18T17:38:47Z"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
};
|
};
|
||||||
|
|
|
||||||
12
index.html
12
index.html
|
|
@ -314,7 +314,8 @@
|
||||||
<option value="microsd-bff">Adafruit microSD Card BFF Add-On for QT Py and Xiao</option>
|
<option value="microsd-bff">Adafruit microSD Card BFF Add-On for QT Py and Xiao</option>
|
||||||
<option value="winc1500-shield">Adafruit WINC1500 WiFi Shield</option>
|
<option value="winc1500-shield">Adafruit WINC1500 WiFi Shield</option>
|
||||||
<option value="airlift-shield">Adafruit AirLift Shield - ESP32 WiFi Co-Processor</option>
|
<option value="airlift-shield">Adafruit AirLift Shield - ESP32 WiFi Co-Processor</option>
|
||||||
|
<option value="seeed-xiao-s3sense-camera-addon">Seeed Studio XIAO ESP32S3 Sense Camera/SD Add-on board</option>
|
||||||
|
<option value="seeed-xiao-ssd1306-expansion-base">Seeed Studio XIAO Expansion base board</option>
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
<div id="companion-details" class="hidden">
|
<div id="companion-details" class="hidden">
|
||||||
|
|
@ -358,6 +359,7 @@
|
||||||
<select id="rtc-select">
|
<select id="rtc-select">
|
||||||
<option value="soft">Software RTC</option>
|
<option value="soft">Software RTC</option>
|
||||||
<option value="PCF8523">PCF8523</option>
|
<option value="PCF8523">PCF8523</option>
|
||||||
|
<option value="PCF8563">PCF8563</option>
|
||||||
<option value="DS3231">DS3231</option>
|
<option value="DS3231">DS3231</option>
|
||||||
<option value="DS1307">DS1307</option>
|
<option value="DS1307">DS1307</option>
|
||||||
</select>
|
</select>
|
||||||
|
|
@ -407,17 +409,13 @@
|
||||||
|
|
||||||
<div id="components-section" class="section hidden">
|
<div id="components-section" class="section hidden">
|
||||||
<h2>5. Add Components</h2>
|
<h2>5. Add Components</h2>
|
||||||
<p style="color: red;"><small><i>UART + other component categories are currently being implemented in offline mode (No ETA, but maybe reactive actions too!).</i></small></p>
|
|
||||||
|
|
||||||
<div id="component-type-tabs" class="tab">
|
<div id="component-type-tabs" class="tab">
|
||||||
<button class="comp-tab active" onclick="openComponentTab(event, 'all-components')">All Components</button>
|
<button class="comp-tab active" onclick="openComponentTab(event, 'all-components')">All Components</button>
|
||||||
<button class="comp-tab" onclick="openComponentTab(event, 'i2c-components')">I2C Components</button>
|
<button class="comp-tab" onclick="openComponentTab(event, 'i2c-components')">I2C Components</button>
|
||||||
<button class="comp-tab" onclick="openComponentTab(event, 'ds18x20-components')">DS18x20 Components</button>
|
<button class="comp-tab" onclick="openComponentTab(event, 'ds18x20-components')">DS18x20 Components</button>
|
||||||
<button class="comp-tab" onclick="openComponentTab(event, 'pin-components')">Pin Components</button>
|
<button class="comp-tab" onclick="openComponentTab(event, 'pin-components')">Pin Components</button>
|
||||||
<button class="comp-tab not-available-yet" onclick="openComponentTab(event, 'pixel-components')">Pixel Components</button>
|
<button class="comp-tab" onclick="openComponentTab(event, 'uart-components')">UART Components</button>
|
||||||
<button class="comp-tab not-available-yet" onclick="openComponentTab(event, 'pwm-components')">PWM Components</button>
|
|
||||||
<button class="comp-tab not-available-yet" onclick="openComponentTab(event, 'servo-components')">Servo Components</button>
|
|
||||||
<button class="comp-tab not-available-yet" onclick="openComponentTab(event, 'uart-components')">UART Components</button>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="all-components" class="component-tabcontent" style="display: block;">
|
<div id="all-components" class="component-tabcontent" style="display: block;">
|
||||||
|
|
@ -512,7 +510,7 @@
|
||||||
<div id="generate-section" class="section hidden">
|
<div id="generate-section" class="section hidden">
|
||||||
<h2>7. Generate Configuration</h2>
|
<h2>7. Generate Configuration</h2>
|
||||||
<button id="generate-config-btn">Generate Configuration</button>
|
<button id="generate-config-btn">Generate Configuration</button>
|
||||||
<input type="checkbox" id="use-auto-init" onchange="javascript:appState.enableautoConfig=this.checked;"> <label for="use-auto-init" title="Auto config fallback for I2C sensors that fail to initialise (selects alternative sensors at same address)">Use Auto Init fallback</label>
|
<input type="checkbox" id="use-auto-init" onchange="javascript:appState.enableautoConfig=this.checked;"> <label for="use-auto-init" title="Auto config fallback for I2C sensors that fail to initialise (selects alternative sensors at same address)">Use Auto Init fallback for failed or unspecified components (default)</label>
|
||||||
<div id="config-output-container" class="hidden">
|
<div id="config-output-container" class="hidden">
|
||||||
<h3>Configuration JSON:</h3>
|
<h3>Configuration JSON:</h3>
|
||||||
<pre id="config-output" class="config-output"></pre>
|
<pre id="config-output" class="config-output"></pre>
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
// Load Wippersnapper boards and components data
|
// Load Wippersnapper boards and components data
|
||||||
|
|
||||||
// Configuration - technically unused (instead ./ relative links) but useful for reference
|
// Configuration - technically unused (instead ./ relative links) but useful for reference
|
||||||
const BOARDS_JSON_URL = 'https://raw.githubusercontent.com/adafruit/Adafruit_Wippersnapper_Offline_Configurator/refs/heads/use_boards_sd_card/wippersnapper_boards.json'; //'wippersnapper_boards.json';
|
const BOARDS_JSON_URL = 'https://raw.githubusercontent.com/adafruit/Adafruit_Wippersnapper_Offline_Configurator/refs/heads/offline-mode/wippersnapper_boards.json'; //'wippersnapper_boards.json';
|
||||||
const COMPONENTS_JSON_URL = 'https://raw.githubusercontent.com/adafruit/Adafruit_Wippersnapper_Offline_Configurator/refs/heads/use_boards_sd_card/wippersnapper_components.json'; //'wippersnapper_components.json';
|
const COMPONENTS_JSON_URL = 'https://raw.githubusercontent.com/adafruit/Adafruit_Wippersnapper_Offline_Configurator/refs/heads/offline-mode/wippersnapper_components.json'; //'wippersnapper_components.json';
|
||||||
|
|
||||||
// Global app state
|
// Global app state
|
||||||
const appState = {
|
const appState = {
|
||||||
|
|
@ -159,7 +159,7 @@ function populateBoardSelect() {
|
||||||
|
|
||||||
// Filter boards to only include those with UF2 install method
|
// Filter boards to only include those with UF2 install method
|
||||||
const filteredBoards = Object.entries(appState.boardsData)
|
const filteredBoards = Object.entries(appState.boardsData)
|
||||||
.filter(([boardId, board]) => board.installMethod === 'uf2'); //['uf2', 'web-native-usb'].includes(board.installMethod)); //funhouse
|
.filter(([boardId, board]) => ['uf2', 'web-native-usb'].includes(board.installMethod)); //funhouse
|
||||||
|
|
||||||
// Sort boards by vendor and name
|
// Sort boards by vendor and name
|
||||||
const sortedBoards = filteredBoards
|
const sortedBoards = filteredBoards
|
||||||
|
|
|
||||||
|
|
@ -126,6 +126,22 @@ const companionBoardConfigs = {
|
||||||
productURL: 'https://www.adafruit.com/product/4285',
|
productURL: 'https://www.adafruit.com/product/4285',
|
||||||
documentationURL: 'https://learn.adafruit.com/adafruit-airlift-shield-esp32-wifi-co-processor',
|
documentationURL: 'https://learn.adafruit.com/adafruit-airlift-shield-esp32-wifi-co-processor',
|
||||||
image: 'https://cdn-shop.adafruit.com/640x480/4285-05.jpg'
|
image: 'https://cdn-shop.adafruit.com/640x480/4285-05.jpg'
|
||||||
|
},
|
||||||
|
'seeed-xiao-s3sense-camera-addon': {
|
||||||
|
rtc: null,
|
||||||
|
sdCardCS: 21,
|
||||||
|
extras: 'SD Card, Camera, Microphone, Extra GPIOs D11+D12',
|
||||||
|
productURL: 'https://www.seeedstudio.com/XIAO-ESP32S3-Sense-p-5639.html',
|
||||||
|
documentationURL: 'https://wiki.seeedstudio.com/xiao_esp32s3_getting_started/',
|
||||||
|
image: 'https://files.seeedstudio.com/wiki/SeeedStudio-XIAO-ESP32S3/img/66.jpg'
|
||||||
|
},
|
||||||
|
'seeed-xiao-ssd1306-expansion-base': {
|
||||||
|
rtc: 'PCF8563',
|
||||||
|
sdCardCS: 'D2',
|
||||||
|
extras: 'SD Card, Display, Piezo Speaker, LiPo connector',
|
||||||
|
productURL: 'https://www.seeedstudio.com/Seeeduino-XIAO-Expansion-board-p-4746.html',
|
||||||
|
documentationURL: 'https://wiki.seeedstudio.com/Seeeduino-XIAO-Expansion-Board/',
|
||||||
|
image: 'https://files.seeedstudio.com/wiki/Seeeduino-XIAO-Expansion-Board/Update_pic/zheng1.jpg'
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -249,7 +265,7 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||||
if (boardImageElem) {
|
if (boardImageElem) {
|
||||||
if (board.image) {
|
if (board.image) {
|
||||||
if (!board.image.startsWith('http')) {
|
if (!board.image.startsWith('http')) {
|
||||||
boardImageElem.src = "https://raw.githubusercontent.com/adafruit/Wippersnapper_Boards/refs/heads/rp2040_datalogger_feather/" + board.image;
|
boardImageElem.src = "https://raw.githubusercontent.com/adafruit/Wippersnapper_Boards/refs/heads/offline-mode/" + board.image;
|
||||||
} else {
|
} else {
|
||||||
boardImageElem.src = board.image;
|
boardImageElem.src = board.image;
|
||||||
}
|
}
|
||||||
|
|
@ -365,7 +381,7 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||||
// Mark SD CS pin as used
|
// Mark SD CS pin as used
|
||||||
appState.usedPins.add(pin.number);
|
appState.usedPins.add(pin.number);
|
||||||
} else {
|
} else {
|
||||||
console.warn(`SD card CS pin ${companion.sdCardCS} not found in selected board pins.`);
|
console.warn(`[${companionId}] SD card CS pin ${companion.sdCardCS} not found in selected board pins.`);
|
||||||
document.getElementById('sd-missing').classList.remove('hidden');
|
document.getElementById('sd-missing').classList.remove('hidden');
|
||||||
document.getElementById('sd-present').classList.add('hidden');
|
document.getElementById('sd-present').classList.add('hidden');
|
||||||
}
|
}
|
||||||
|
|
@ -437,8 +453,12 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||||
document.getElementById('sd-card-pin-select').classList.remove('hidden');
|
document.getElementById('sd-card-pin-select').classList.remove('hidden');
|
||||||
} else {
|
} else {
|
||||||
document.getElementById('sd-card-pin-select').classList.add('hidden');
|
document.getElementById('sd-card-pin-select').classList.add('hidden');
|
||||||
|
appState.usedPins.delete(appState.sdCardCS);
|
||||||
|
document.getElementById('manual-sd-cs-pin').textContent = '';
|
||||||
|
document.getElementById('sd-cs-pin').textContent = '';
|
||||||
appState.sdCardCS = null;
|
appState.sdCardCS = null;
|
||||||
}
|
}
|
||||||
|
populatePinsLists();
|
||||||
});
|
});
|
||||||
|
|
||||||
// RTC type selection handler
|
// RTC type selection handler
|
||||||
|
|
@ -1008,7 +1028,7 @@ function createComponentCard(component, type) {
|
||||||
if (component.image) {
|
if (component.image) {
|
||||||
const img = document.createElement('img');
|
const img = document.createElement('img');
|
||||||
if (!component.image.startsWith('http')) {
|
if (!component.image.startsWith('http')) {
|
||||||
img.src = "https://raw.githubusercontent.com/adafruit/Wippersnapper_Components/refs/heads/main/" + component.image;
|
img.src = "https://raw.githubusercontent.com/adafruit/Wippersnapper_Components/refs/heads/offline-mode/" + component.image;
|
||||||
} else {
|
} else {
|
||||||
img.src = component.image;
|
img.src = component.image;
|
||||||
}
|
}
|
||||||
|
|
@ -1523,9 +1543,15 @@ function saveModalData() {
|
||||||
const componentConfig = {
|
const componentConfig = {
|
||||||
instanceId: appState.nextComponentId++,
|
instanceId: appState.nextComponentId++,
|
||||||
name: name,
|
name: name,
|
||||||
componentAPI: componentType == 'pin' ? componentTemplate.componentAPI : componentType,
|
componentAPI: componentType == 'pin' ? componentTemplate.componentAPI : componentType
|
||||||
period: period
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Only add period for components that don't have their own period objects
|
||||||
|
if (! componentTemplate.deviceType !== 'gps' &&
|
||||||
|
componentTemplate.deviceType !== 'pm25aqi' &&
|
||||||
|
componentTemplate.deviceType !== 'generic_input') {
|
||||||
|
componentConfig.period = period;
|
||||||
|
}
|
||||||
let validationError = false; // future use
|
let validationError = false; // future use
|
||||||
|
|
||||||
// Special handling for I2C
|
// Special handling for I2C
|
||||||
|
|
@ -1536,6 +1562,24 @@ function saveModalData() {
|
||||||
componentConfig.i2cDeviceName = componentId;
|
componentConfig.i2cDeviceName = componentId;
|
||||||
componentConfig.i2cDeviceAddress = i2cAddress;
|
componentConfig.i2cDeviceAddress = i2cAddress;
|
||||||
|
|
||||||
|
// Add GPS fields if they exist in the component template
|
||||||
|
if (componentTemplate.isGps) {
|
||||||
|
componentConfig.isGps = componentTemplate.isGps;
|
||||||
|
// Add gps object with period (convert from seconds to milliseconds)
|
||||||
|
if (!componentConfig.gps) {
|
||||||
|
componentConfig.gps = {};
|
||||||
|
}
|
||||||
|
componentConfig.gps.period = period;
|
||||||
|
|
||||||
|
if (componentTemplate.gps.commands_ubxes) {
|
||||||
|
componentConfig.gps.commands_ubxes = componentTemplate.gps.commands_ubxes;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (componentTemplate.gps.commands_pmtks) {
|
||||||
|
componentConfig.gps.commands_pmtks = componentTemplate.gps.commands_pmtks;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Handle multiplexer channel if selected
|
// Handle multiplexer channel if selected
|
||||||
if (i2cBus.startsWith('mux-')) {
|
if (i2cBus.startsWith('mux-')) {
|
||||||
const [_, muxId, __, channelNum] = i2cBus.split('-');
|
const [_, muxId, __, channelNum] = i2cBus.split('-');
|
||||||
|
|
@ -1579,20 +1623,22 @@ function saveModalData() {
|
||||||
appState.selectedComponents = appState.selectedComponents.filter(c =>
|
appState.selectedComponents = appState.selectedComponents.filter(c =>
|
||||||
!(c.i2cMuxAddress && c.i2cMuxAddress === componentConfig.i2cDeviceAddress));
|
!(c.i2cMuxAddress && c.i2cMuxAddress === componentConfig.i2cDeviceAddress));
|
||||||
} else {
|
} else {
|
||||||
// Add data types for non-multiplexer components
|
if (! componentTemplate.isGps) {
|
||||||
const dataTypeCheckboxes = document.querySelectorAll('input[name="data-type"]:checked');
|
// Add data types for non-multiplexer components
|
||||||
if (dataTypeCheckboxes.length > 0) {
|
const dataTypeCheckboxes = document.querySelectorAll('input[name="data-type"]:checked');
|
||||||
componentConfig.i2cDeviceSensorTypes = Array.from(dataTypeCheckboxes).map(checkbox => {
|
if (dataTypeCheckboxes.length > 0) {
|
||||||
try {
|
componentConfig.i2cDeviceSensorTypes = Array.from(dataTypeCheckboxes).map(checkbox => {
|
||||||
return { type: JSON.parse(checkbox.value) };
|
try {
|
||||||
} catch (e) {
|
return { type: JSON.parse(checkbox.value) };
|
||||||
return { type: checkbox.value };
|
} catch (e) {
|
||||||
}
|
return { type: checkbox.value };
|
||||||
});
|
}
|
||||||
} else {
|
});
|
||||||
validationError = true;
|
} else {
|
||||||
alert('Please select at least one data type for the I2C component.');
|
validationError = true;
|
||||||
return false;
|
alert('Please select at least one data type for the I2C component.');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (componentType === 'ds18x20') {
|
} else if (componentType === 'ds18x20') {
|
||||||
|
|
@ -1650,31 +1696,75 @@ function saveModalData() {
|
||||||
// Mark pin as used
|
// Mark pin as used
|
||||||
appState.usedPins.add(parseInt(pin));
|
appState.usedPins.add(parseInt(pin));
|
||||||
} else if (componentType === 'uart') {
|
} else if (componentType === 'uart') {
|
||||||
const txPin = document.getElementById('modal-uart-tx').value;
|
const pinTx = document.getElementById('modal-uart-tx').value;
|
||||||
const rxPin = document.getElementById('modal-uart-rx').value;
|
const pinRx = document.getElementById('modal-uart-rx').value;
|
||||||
if (!rxPin) {
|
if (!pinRx) {
|
||||||
validationError = true;
|
validationError = true;
|
||||||
alert('Please select a RX pin for the component.');
|
alert('Please select a RX pin for the component.');
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (!!txPin) {
|
if (!!pinTx) {
|
||||||
componentConfig.txPin = `D${txPin}`;
|
componentConfig.pinTx = `D${pinTx}`;
|
||||||
appState.usedPins.add(parseInt(txPin));
|
appState.usedPins.add(parseInt(pinTx));
|
||||||
}
|
}
|
||||||
componentConfig.rxPin = `D${rxPin}`;
|
componentConfig.pinRx = `D${pinRx}`;
|
||||||
appState.usedPins.add(parseInt(rxPin));
|
appState.usedPins.add(parseInt(pinRx));
|
||||||
|
|
||||||
// Add data types
|
// Add data types
|
||||||
const dataTypeCheckboxes = document.querySelectorAll('input[name="data-type"]:checked');
|
const dataTypeCheckboxes = document.querySelectorAll('input[name="data-type"]:checked');
|
||||||
if (dataTypeCheckboxes.length > 0) {
|
if (dataTypeCheckboxes.length > 0) {
|
||||||
componentConfig.sensorTypes = Array.from(dataTypeCheckboxes).map(checkbox => {
|
componentConfig.sensorTypes = Array.from(dataTypeCheckboxes).map(checkbox => {
|
||||||
try {
|
try {
|
||||||
return JSON.parse(checkbox.value);
|
return { type: JSON.parse(checkbox.value) };
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
return checkbox.value;
|
return { type: checkbox.value };
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// UART-Specific //
|
||||||
|
// Add deviceType field if it exists in the component template
|
||||||
|
if (componentTemplate.deviceType) {
|
||||||
|
componentConfig.deviceType = componentTemplate.deviceType;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add deviceId field if it exists in the component template
|
||||||
|
if (componentTemplate.deviceId) {
|
||||||
|
componentConfig.deviceId = componentTemplate.deviceId;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add GPS fields if this is a GPS component
|
||||||
|
if (componentTemplate.deviceType === 'gps') {
|
||||||
|
if (!componentConfig.gps) {
|
||||||
|
componentConfig.gps = {};
|
||||||
|
}
|
||||||
|
componentConfig.gps.period = period;
|
||||||
|
|
||||||
|
if (componentTemplate.gps.commands_ubxes) {
|
||||||
|
componentConfig.gps.commands_ubxes = componentTemplate.gps.commands_ubxes;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (componentTemplate.gps.commands_pmtks) {
|
||||||
|
componentConfig.gps.commands_pmtks = componentTemplate.gps.commands_pmtks;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add PM25AQI fields if this is a PM25AQI component
|
||||||
|
if (componentTemplate.deviceType === 'pm25aqi') {
|
||||||
|
if (!componentConfig.pm25aqi) {
|
||||||
|
componentConfig.pm25aqi = {};
|
||||||
|
}
|
||||||
|
componentConfig.pm25aqi.period = period;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add generic_input fields if this is a generic_input component
|
||||||
|
if (componentTemplate.deviceType === 'generic_input') {
|
||||||
|
if (!componentConfig.generic_input) {
|
||||||
|
componentConfig.generic_input = {};
|
||||||
|
}
|
||||||
|
componentConfig.generic_input.period = period;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add component to the selected components list
|
// Add component to the selected components list
|
||||||
|
|
@ -1758,7 +1848,7 @@ function updateSelectedComponentsList() {
|
||||||
detailsText += `<br>Pin: ${component.pinName}`;
|
detailsText += `<br>Pin: ${component.pinName}`;
|
||||||
detailsText += `<br>Pixels: ${component.numPixels}`;
|
detailsText += `<br>Pixels: ${component.numPixels}`;
|
||||||
} else if (component.componentAPI === 'uart') {
|
} else if (component.componentAPI === 'uart') {
|
||||||
detailsText += `<br>TX Pin: ${component.txPin}, RX Pin: ${component.rxPin}`;
|
detailsText += `<br>TX Pin: ${component.pinTx}, RX Pin: ${component.pinRx}`;
|
||||||
|
|
||||||
// Show sensor types
|
// Show sensor types
|
||||||
if (component.sensorTypes && component.sensorTypes.length > 0) {
|
if (component.sensorTypes && component.sensorTypes.length > 0) {
|
||||||
|
|
@ -1810,14 +1900,14 @@ function removeComponent(instanceId) {
|
||||||
appState.usedPins.delete(pinNumber);
|
appState.usedPins.delete(pinNumber);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (component.txPin) {
|
if (component.pinTx) {
|
||||||
const txPinNumber = parseInt(component.txPin.replace('D', ''));
|
const pinTxNumber = parseInt(component.pinTx.replace('D', ''));
|
||||||
appState.usedPins.delete(txPinNumber);
|
appState.usedPins.delete(pinTxNumber);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (component.rxPin) {
|
if (component.pinRx) {
|
||||||
const rxPinNumber = parseInt(component.rxPin.replace('D', ''));
|
const pinRxNumber = parseInt(component.pinRx.replace('D', ''));
|
||||||
appState.usedPins.delete(rxPinNumber);
|
appState.usedPins.delete(pinRxNumber);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if this is a multiplexer and remove it from the multiplexers list
|
// Check if this is a multiplexer and remove it from the multiplexers list
|
||||||
|
|
@ -1870,7 +1960,8 @@ function generateConfiguration() {
|
||||||
referenceVoltage: appState.selectedBoard.referenceVoltage,
|
referenceVoltage: appState.selectedBoard.referenceVoltage,
|
||||||
totalGPIOPins: appState.selectedBoard.totalGPIOPins,
|
totalGPIOPins: appState.selectedBoard.totalGPIOPins,
|
||||||
totalAnalogPins: appState.selectedBoard.totalAnalogPins,
|
totalAnalogPins: appState.selectedBoard.totalAnalogPins,
|
||||||
statusLEDBrightness: appState.statusLEDBrightness
|
statusLEDBrightness: appState.statusLEDBrightness,
|
||||||
|
autoConfig: appState.enableautoConfig
|
||||||
},
|
},
|
||||||
components: []
|
components: []
|
||||||
};
|
};
|
||||||
|
|
@ -2290,14 +2381,14 @@ function importConfigObject(config) {
|
||||||
appState.usedPins.add(pinNumber);
|
appState.usedPins.add(pinNumber);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (component.txPin) {
|
if (component.pinTx) {
|
||||||
const txPinNumber = parseInt(component.txPin.replace('D', ''));
|
const pinTxNumber = parseInt(component.pinTx.replace('D', ''));
|
||||||
appState.usedPins.add(txPinNumber);
|
appState.usedPins.add(pinTxNumber);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (component.rxPin) {
|
if (component.pinRx) {
|
||||||
const rxPinNumber = parseInt(component.rxPin.replace('D', ''));
|
const pinRxNumber = parseInt(component.pinRx.replace('D', ''));
|
||||||
appState.usedPins.add(rxPinNumber);
|
appState.usedPins.add(pinRxNumber);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle I2C bus pins
|
// Handle I2C bus pins
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue