Fix images using product API

This commit is contained in:
tyeth 2025-04-09 12:52:54 +01:00
parent d6243f25ba
commit 4b8844a0e1
3 changed files with 128 additions and 139 deletions

View file

@ -11,57 +11,7 @@ def add_custom_board_definitions(boards):
"""
Add custom board definitions for boards that don't have definition.json files
"""
# Adafruit Feather RP2040 Adalogger
boards["feather-rp2040-adalogger"] = {
"boardName": "Adafruit Feather RP2040 Adalogger",
"mcuName": "RP2040",
"referenceVoltage": 3.3,
"displayName": "Adafruit Feather RP2040 Adalogger",
"vendor": "Adafruit",
"productURL": "https://www.adafruit.com/product/5980",
"documentationURL": "https://learn.adafruit.com/adafruit-feather-rp2040-adalogger",
"installMethod": "uf2",
"totalGPIOPins": 22,
"totalAnalogPins": 4,
"pins": [
{"number": 0, "name": "D0", "displayName": "GPIO0", "hasPWM": True, "hasServo": True},
{"number": 1, "name": "D1", "displayName": "GPIO1", "hasPWM": True, "hasServo": True},
{"number": 2, "name": "D2", "displayName": "GPIO2", "hasPWM": True, "hasServo": True},
{"number": 3, "name": "D3", "displayName": "GPIO3", "hasPWM": True, "hasServo": True},
{"number": 4, "name": "D4", "displayName": "GPIO4", "hasPWM": True, "hasServo": True},
{"number": 5, "name": "D5", "displayName": "GPIO5", "hasPWM": True, "hasServo": True},
{"number": 6, "name": "D6", "displayName": "GPIO6", "hasPWM": True, "hasServo": True},
{"number": 7, "name": "D7", "displayName": "GPIO7", "hasPWM": True, "hasServo": True},
{"number": 8, "name": "D8", "displayName": "GPIO8", "hasPWM": True, "hasServo": True},
{"number": 9, "name": "D9", "displayName": "GPIO9", "hasPWM": True, "hasServo": True},
{"number": 10, "name": "D10", "displayName": "GPIO10", "hasPWM": True, "hasServo": True},
{"number": 11, "name": "D11", "displayName": "GPIO11", "hasPWM": True, "hasServo": True},
{"number": 12, "name": "D12", "displayName": "GPIO12", "hasPWM": True, "hasServo": True},
{"number": 13, "name": "D13", "displayName": "GPIO13 (LED)", "hasPWM": True, "hasServo": True},
{"number": 16, "name": "D16", "displayName": "GPIO16 (MOSI)", "hasPWM": True, "hasServo": True},
{"number": 17, "name": "D17", "displayName": "GPIO17 (A1/SCK/SD CS)", "hasPWM": True, "hasServo": True},
{"number": 18, "name": "D18", "displayName": "GPIO18 (MISO)", "hasPWM": True, "hasServo": True},
{"number": 19, "name": "D19", "displayName": "GPIO19", "hasPWM": True, "hasServo": True},
{"number": 20, "name": "D20", "displayName": "GPIO20", "hasPWM": True, "hasServo": True},
{"number": 24, "name": "D24", "displayName": "GPIO24 (A0)", "hasPWM": True, "hasServo": True},
{"number": 25, "name": "D25", "displayName": "GPIO25 (A3)", "hasPWM": True, "hasServo": True},
{"number": 29, "name": "D29", "displayName": "GPIO29 (A2)", "hasPWM": True, "hasServo": True}
],
"analogPins": [
{"name": "A0", "displayName": "GPIO24 (A0)", "direction": "INPUT"},
{"name": "A1", "displayName": "GPIO17 (A1/SD CS)", "direction": "INPUT"},
{"name": "A2", "displayName": "GPIO29 (A2)", "direction": "INPUT"},
{"name": "A3", "displayName": "GPIO25 (A3)", "direction": "INPUT"}
],
"defaultI2C": {
"i2cPortId": 0,
"SCL": "D3",
"SDA": "D2"
},
"sdCardCS": 17, # GPIO17/A1 is the SD card CS pin
"rtcType": "PCF8523", # Built-in RTC chip
"image": None
}
# Generic ESP32-S2 based board
boards["generic-esp32-s2"] = {
"boardName": "Generic ESP32-S2",
@ -261,13 +211,13 @@ def add_custom_board_definitions(boards):
"boardName": "Generic RP23xx",
"mcuName": "RP23xx",
"referenceVoltage": 3.3,
"displayName": "Generic RP23xx Board",
"displayName": "Generic RP2350/RP2354 board",
"vendor": "Generic",
"productURL": "",
"documentationURL": "",
"installMethod": "uf2",
"totalGPIOPins": 30,
"totalAnalogPins": 4,
"totalGPIOPins": 48,
"totalAnalogPins": 8,
"pins": [
{"number": 0, "name": "D0", "displayName": "GPIO0", "hasPWM": True, "hasServo": True},
{"number": 1, "name": "D1", "displayName": "GPIO1", "hasPWM": True, "hasServo": True},
@ -295,16 +245,39 @@ def add_custom_board_definitions(boards):
{"number": 23, "name": "D23", "displayName": "GPIO23", "hasPWM": True, "hasServo": True},
{"number": 24, "name": "D24", "displayName": "GPIO24", "hasPWM": True, "hasServo": True},
{"number": 25, "name": "D25", "displayName": "GPIO25", "hasPWM": True, "hasServo": True},
{"number": 26, "name": "D26", "displayName": "GPIO26", "hasPWM": True, "hasServo": True},
{"number": 27, "name": "D27", "displayName": "GPIO27", "hasPWM": True, "hasServo": True},
{"number": 28, "name": "D28", "displayName": "GPIO28", "hasPWM": True, "hasServo": True},
{"number": 29, "name": "D29", "displayName": "GPIO29", "hasPWM": True, "hasServo": True}
{"number": 26, "name": "A26", "displayName": "GPIO26 (ADC0)", "hasPWM": True, "hasServo": True},
{"number": 27, "name": "A27", "displayName": "GPIO27 (ADC1)", "hasPWM": True, "hasServo": True},
{"number": 28, "name": "A28", "displayName": "GPIO28 (ADC2)", "hasPWM": True, "hasServo": True},
{"number": 29, "name": "A29", "displayName": "GPIO29 (ADC3)", "hasPWM": True, "hasServo": True},
{"number": 30, "name": "D30", "displayName": "GPIO30", "hasPWM": True, "hasServo": True},
{"number": 31, "name": "D31", "displayName": "GPIO31", "hasPWM": True, "hasServo": True},
{"number": 32, "name": "D32", "displayName": "GPIO32", "hasPWM": True, "hasServo": True},
{"number": 33, "name": "D33", "displayName": "GPIO33", "hasPWM": True, "hasServo": True},
{"number": 34, "name": "D34", "displayName": "GPIO34", "hasPWM": True, "hasServo": True},
{"number": 35, "name": "D35", "displayName": "GPIO35", "hasPWM": True, "hasServo": True},
{"number": 36, "name": "D36", "displayName": "GPIO36", "hasPWM": True, "hasServo": True},
{"number": 37, "name": "D37", "displayName": "GPIO37", "hasPWM": True, "hasServo": True},
{"number": 38, "name": "D38", "displayName": "GPIO38", "hasPWM": True, "hasServo": True},
{"number": 39, "name": "D39", "displayName": "GPIO39", "hasPWM": True, "hasServo": True},
{"number": 40, "name": "A40", "displayName": "GPIO40 (ADC0)", "hasPWM": True, "hasServo": True},
{"number": 41, "name": "A41", "displayName": "GPIO41 (ADC1)", "hasPWM": True, "hasServo": True},
{"number": 42, "name": "A42", "displayName": "GPIO42 (ADC2)", "hasPWM": True, "hasServo": True},
{"number": 43, "name": "A43", "displayName": "GPIO43 (ADC3)", "hasPWM": True, "hasServo": True},
{"number": 44, "name": "D44", "displayName": "GPIO44", "hasPWM": True, "hasServo": True},
{"number": 45, "name": "D45", "displayName": "GPIO45", "hasPWM": True, "hasServo": True},
{"number": 46, "name": "D46", "displayName": "GPIO46", "hasPWM": True, "hasServo": True},
{"number": 47, "name": "D47", "displayName": "GPIO47", "hasPWM": True, "hasServo": True},
{"number": 48, "name": "D48", "displayName": "GPIO48", "hasPWM": True, "hasServo": True}
],
"analogPins": [
{"name": "A0", "displayName": "ADC0", "direction": "INPUT"},
{"name": "A1", "displayName": "ADC1", "direction": "INPUT"},
{"name": "A2", "displayName": "ADC2", "direction": "INPUT"},
{"name": "A3", "displayName": "ADC3", "direction": "INPUT"}
{"name": "A26", "displayName": "GPIO26 (ADC0)", "direction": "INPUT"},
{"name": "A27", "displayName": "GPIO27 (ADC1)", "direction": "INPUT"},
{"name": "A28", "displayName": "GPIO28 (ADC2)", "direction": "INPUT"},
{"name": "A29", "displayName": "GPIO29 (ADC3)", "direction": "INPUT"},
{"name": "A40", "displayName": "GPIO40 (ADC0)", "direction": "INPUT"},
{"name": "A41", "displayName": "GPIO41 (ADC1)", "direction": "INPUT"},
{"name": "A42", "displayName": "GPIO42 (ADC2)", "direction": "INPUT"},
{"name": "A43", "displayName": "GPIO43 (ADC3)", "direction": "INPUT"}
],
"defaultI2C": {
"i2cPortId": 0,
@ -314,64 +287,64 @@ def add_custom_board_definitions(boards):
"image": None
}
# Adafruit Metro RP2350 with SD card
boards["metro-rp2350-sd"] = {
"boardName": "Adafruit Metro RP2350",
"mcuName": "RP2350",
"referenceVoltage": 3.3,
"displayName": "Adafruit Metro RP2350 (with SD card)",
"vendor": "Adafruit",
"productURL": "https://www.adafruit.com/product/5786",
"documentationURL": "https://learn.adafruit.com/adafruit-metro-rp2350",
"installMethod": "uf2",
"totalGPIOPins": 30,
"totalAnalogPins": 4,
"pins": [
{"number": 0, "name": "D0", "displayName": "GPIO0", "hasPWM": True, "hasServo": True},
{"number": 1, "name": "D1", "displayName": "GPIO1", "hasPWM": True, "hasServo": True},
{"number": 2, "name": "D2", "displayName": "GPIO2", "hasPWM": True, "hasServo": True},
{"number": 3, "name": "D3", "displayName": "GPIO3", "hasPWM": True, "hasServo": True},
{"number": 4, "name": "D4", "displayName": "GPIO4", "hasPWM": True, "hasServo": True},
{"number": 5, "name": "D5", "displayName": "GPIO5", "hasPWM": True, "hasServo": True},
{"number": 6, "name": "D6", "displayName": "GPIO6", "hasPWM": True, "hasServo": True},
{"number": 7, "name": "D7", "displayName": "GPIO7", "hasPWM": True, "hasServo": True},
{"number": 8, "name": "D8", "displayName": "GPIO8", "hasPWM": True, "hasServo": True},
{"number": 9, "name": "D9", "displayName": "GPIO9", "hasPWM": True, "hasServo": True},
{"number": 10, "name": "D10", "displayName": "GPIO10 (SD CS)", "hasPWM": True, "hasServo": True},
{"number": 11, "name": "D11", "displayName": "GPIO11", "hasPWM": True, "hasServo": True},
{"number": 12, "name": "D12", "displayName": "GPIO12", "hasPWM": True, "hasServo": True},
{"number": 13, "name": "D13", "displayName": "GPIO13", "hasPWM": True, "hasServo": True},
{"number": 14, "name": "D14", "displayName": "GPIO14", "hasPWM": True, "hasServo": True},
{"number": 15, "name": "D15", "displayName": "GPIO15", "hasPWM": True, "hasServo": True},
{"number": 16, "name": "D16", "displayName": "GPIO16", "hasPWM": True, "hasServo": True},
{"number": 17, "name": "D17", "displayName": "GPIO17", "hasPWM": True, "hasServo": True},
{"number": 18, "name": "D18", "displayName": "GPIO18", "hasPWM": True, "hasServo": True},
{"number": 19, "name": "D19", "displayName": "GPIO19", "hasPWM": True, "hasServo": True},
{"number": 20, "name": "D20", "displayName": "GPIO20", "hasPWM": True, "hasServo": True},
{"number": 21, "name": "D21", "displayName": "GPIO21", "hasPWM": True, "hasServo": True},
{"number": 22, "name": "D22", "displayName": "GPIO22", "hasPWM": True, "hasServo": True},
{"number": 23, "name": "D23", "displayName": "GPIO23", "hasPWM": True, "hasServo": True},
{"number": 24, "name": "D24", "displayName": "GPIO24", "hasPWM": True, "hasServo": True},
{"number": 25, "name": "D25", "displayName": "GPIO25", "hasPWM": True, "hasServo": True},
{"number": 26, "name": "D26", "displayName": "GPIO26", "hasPWM": True, "hasServo": True},
{"number": 27, "name": "D27", "displayName": "GPIO27", "hasPWM": True, "hasServo": True},
{"number": 28, "name": "D28", "displayName": "GPIO28", "hasPWM": True, "hasServo": True},
{"number": 29, "name": "D29", "displayName": "GPIO29", "hasPWM": True, "hasServo": True}
],
"analogPins": [
{"name": "A0", "displayName": "ADC0", "direction": "INPUT"},
{"name": "A1", "displayName": "ADC1", "direction": "INPUT"},
{"name": "A2", "displayName": "ADC2", "direction": "INPUT"},
{"name": "A3", "displayName": "ADC3", "direction": "INPUT"}
],
"defaultI2C": {
"i2cPortId": 0,
"SCL": "D3",
"SDA": "D2"
},
"sdCardCS": 10,
"image": None
}
# # Adafruit Metro RP2350 with SD card
# boards["metro-rp2350-sd"] = {
# "boardName": "Adafruit Metro RP2350",
# "mcuName": "RP2350",
# "referenceVoltage": 3.3,
# "displayName": "Adafruit Metro RP2350 (with SD card)",
# "vendor": "Adafruit",
# "productURL": "https://www.adafruit.com/product/5786",
# "documentationURL": "https://learn.adafruit.com/adafruit-metro-rp2350",
# "installMethod": "uf2",
# "totalGPIOPins": 30,
# "totalAnalogPins": 4,
# "pins": [
# {"number": 0, "name": "D0", "displayName": "GPIO0", "hasPWM": True, "hasServo": True},
# {"number": 1, "name": "D1", "displayName": "GPIO1", "hasPWM": True, "hasServo": True},
# {"number": 2, "name": "D2", "displayName": "GPIO2", "hasPWM": True, "hasServo": True},
# {"number": 3, "name": "D3", "displayName": "GPIO3", "hasPWM": True, "hasServo": True},
# {"number": 4, "name": "D4", "displayName": "GPIO4", "hasPWM": True, "hasServo": True},
# {"number": 5, "name": "D5", "displayName": "GPIO5", "hasPWM": True, "hasServo": True},
# {"number": 6, "name": "D6", "displayName": "GPIO6", "hasPWM": True, "hasServo": True},
# {"number": 7, "name": "D7", "displayName": "GPIO7", "hasPWM": True, "hasServo": True},
# {"number": 8, "name": "D8", "displayName": "GPIO8", "hasPWM": True, "hasServo": True},
# {"number": 9, "name": "D9", "displayName": "GPIO9", "hasPWM": True, "hasServo": True},
# {"number": 10, "name": "D10", "displayName": "GPIO10 (SD CS)", "hasPWM": True, "hasServo": True},
# {"number": 11, "name": "D11", "displayName": "GPIO11", "hasPWM": True, "hasServo": True},
# {"number": 12, "name": "D12", "displayName": "GPIO12", "hasPWM": True, "hasServo": True},
# {"number": 13, "name": "D13", "displayName": "GPIO13", "hasPWM": True, "hasServo": True},
# {"number": 14, "name": "D14", "displayName": "GPIO14", "hasPWM": True, "hasServo": True},
# {"number": 15, "name": "D15", "displayName": "GPIO15", "hasPWM": True, "hasServo": True},
# {"number": 16, "name": "D16", "displayName": "GPIO16", "hasPWM": True, "hasServo": True},
# {"number": 17, "name": "D17", "displayName": "GPIO17", "hasPWM": True, "hasServo": True},
# {"number": 18, "name": "D18", "displayName": "GPIO18", "hasPWM": True, "hasServo": True},
# {"number": 19, "name": "D19", "displayName": "GPIO19", "hasPWM": True, "hasServo": True},
# {"number": 20, "name": "D20", "displayName": "GPIO20", "hasPWM": True, "hasServo": True},
# {"number": 21, "name": "D21", "displayName": "GPIO21", "hasPWM": True, "hasServo": True},
# {"number": 22, "name": "D22", "displayName": "GPIO22", "hasPWM": True, "hasServo": True},
# {"number": 23, "name": "D23", "displayName": "GPIO23", "hasPWM": True, "hasServo": True},
# {"number": 24, "name": "D24", "displayName": "GPIO24", "hasPWM": True, "hasServo": True},
# {"number": 25, "name": "D25", "displayName": "GPIO25", "hasPWM": True, "hasServo": True},
# {"number": 26, "name": "D26", "displayName": "GPIO26", "hasPWM": True, "hasServo": True},
# {"number": 27, "name": "D27", "displayName": "GPIO27", "hasPWM": True, "hasServo": True},
# {"number": 28, "name": "D28", "displayName": "GPIO28", "hasPWM": True, "hasServo": True},
# {"number": 29, "name": "D29", "displayName": "GPIO29", "hasPWM": True, "hasServo": True}
# ],
# "analogPins": [
# {"name": "A0", "displayName": "ADC0", "direction": "INPUT"},
# {"name": "A1", "displayName": "ADC1", "direction": "INPUT"},
# {"name": "A2", "displayName": "ADC2", "direction": "INPUT"},
# {"name": "A3", "displayName": "ADC3", "direction": "INPUT"}
# ],
# "defaultI2C": {
# "i2cPortId": 0,
# "SCL": "D3",
# "SDA": "D2"
# },
# "sdCardCS": 10,
# "image": None
# }
return boards
@ -415,6 +388,12 @@ def convert_boards_to_json():
"image": None
}
SUPPORTED_ARCHITECTURES = ["rp2350", "rp2040", "esp32s2", "esp32s3"]
# Filter out boards that are not supported
if board_info["mcuName"] not in SUPPORTED_ARCHITECTURES:
print(f"Skipping {board_dir} - Unsupported architecture {board_info['mcuName']}")
continue
# Get pins
if "components" in board_data and "digitalPins" in board_data["components"]:
for pin in board_data["components"]["digitalPins"]:

View file

@ -3,7 +3,7 @@ import json
import glob
import re
import requests
from bs4 import BeautifulSoup
# from bs4 import BeautifulSoup
from pathlib import Path
# Base directory for the components
@ -12,8 +12,8 @@ OUTPUT_FILE = r"./wippersnapper_components.json"
def get_image_from_adafruit_product_url(product_url):
"""
Fetch the product image URL from an Adafruit product page by extracting
the og:image meta tag from the HTML.
Fetch the product image URL from an Adafruit product API
(was from prod page by extracting the og:image meta tag from the HTML).
Args:
product_url (str): URL to an Adafruit product page
@ -21,28 +21,37 @@ def get_image_from_adafruit_product_url(product_url):
Returns:
str or None: URL to the product image, or None if not found
"""
if not product_url or not re.match(r'https?://(?:www\.)?adafruit\.com/product/\d+', product_url):
if not product_url or not re.match(r'https?://(?:www\.)?adafruit\.com/(?:product|category)/\d+', product_url):
return None
# Grab product JSON from https://www.adafruit.com/api/products, cache, save as ISO date string filename so can be easily used as cache key
try:
response = requests.get(product_url, timeout=10)
product_id = re.search(r'/product/(\d+)', product_url)
category = re.search(r'/category/(\d+)', product_url)
response = requests.get(f"https://www.adafruit.com/api/{("category" if category else "product")}/{(product_id.groups(1)[0] if product_id else category.groups(1)[0])}", timeout=10)
if response.status_code != 200:
print(f"Failed to fetch product page: {product_url}, status code: {response.status_code}")
print(f"Failed to fetch product data: {product_url}, status code: {response.status_code}")
return None
soup = BeautifulSoup(response.text, 'html.parser')
og_image = soup.find('meta', property='og:image')
if og_image and 'content' in og_image.attrs:
image_url = og_image['content']
print(f"Found image URL from product page: {image_url}")
response_json = response.json()
if 'product_image' in response_json:
image_url = response_json['product_image']
print(f"Found image URL from API: {image_url}")
return image_url
else:
print(f"No og:image meta tag found for: {product_url}")
return None
except Exception as e:
print(f"Error fetching image from product URL {product_url}: {str(e)}")
elif 'subcategories' in response_json:
subcategories = response_json['subcategories']
for subcategory in subcategories:
if 'product_image' in subcategory:
image_url = subcategory['product_image']
print(f"Found image URL from API: {image_url}")
return image_url
print(f"No image found in subcategory for: {product_url}")
return None
except Exception as e:
print(f"Error fetching image from API for {product_url}: {str(e)}")
return None
## Consider removing beautifulsoup...
def map_datatypes_to_offline_types(datatype):
"""

1
requirements.txt Normal file
View file

@ -0,0 +1 @@
requests