diff --git a/convert_boards_to_json.py b/convert_boards_to_json.py index bac39a0..0867794 100644 --- a/convert_boards_to_json.py +++ b/convert_boards_to_json.py @@ -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 @@ -398,7 +371,7 @@ def convert_boards_to_json(): # Read the definition.json file with open(definition_file, 'r') as f: board_data = json.load(f) - + # Extract relevant information board_info = { "boardName": board_data.get("boardName"), @@ -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"]: diff --git a/convert_components_to_json.py b/convert_components_to_json.py index 5d8f2b3..2118fef 100644 --- a/convert_components_to_json.py +++ b/convert_components_to_json.py @@ -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): """ diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..663bd1f --- /dev/null +++ b/requirements.txt @@ -0,0 +1 @@ +requests \ No newline at end of file