Spaces:
Build error
Build error
| import gradio as gr | |
| import json | |
| import zipfile | |
| import io | |
| from datetime import datetime | |
| from utils import ( | |
| generate_esp32_code, | |
| get_esp32_templates, | |
| get_component_libraries, | |
| validate_pin_config, | |
| format_code | |
| ) | |
| class ESP32Wizard: | |
| def __init__(self): | |
| self.templates = get_esp32_templates() | |
| self.libraries = get_component_libraries() | |
| self.current_step = 0 | |
| self.config = { | |
| "project_info": { | |
| "name": "", | |
| "description": "", | |
| "author": "", | |
| "version": "1.0.0" | |
| }, | |
| "board": { | |
| "model": "ESP32 DevKit", | |
| "frequency": "240MHz", | |
| "flash_size": "4MB" | |
| }, | |
| "wifi": { | |
| "enabled": False, | |
| "ssid": "", | |
| "password": "", | |
| "mode": "STA", | |
| "static_ip": "", | |
| "gateway": "", | |
| "subnet": "" | |
| }, | |
| "components": [], | |
| "pins": {}, | |
| "variables": {}, | |
| "custom_code": "", | |
| "libraries": [] | |
| } | |
| def reset_config(self): | |
| self.__init__() | |
| return self.get_step_content(0) | |
| def get_step_content(self, step): | |
| if step == 0: | |
| return self.project_info_step() | |
| elif step == 1: | |
| return self.board_config_step() | |
| elif step == 2: | |
| return self.wifi_config_step() | |
| elif step == 3: | |
| return self.components_step() | |
| elif step == 4: | |
| return self.pins_config_step() | |
| elif step == 5: | |
| return self.variables_step() | |
| elif step == 6: | |
| return self.custom_code_step() | |
| elif step == 7: | |
| return self.preview_step() | |
| else: | |
| return self.download_step() | |
| def project_info_step(self): | |
| with gr.Column(): | |
| gr.Markdown("## π Project Information") | |
| gr.Markdown("Let's start with basic project details.") | |
| with gr.Row(): | |
| with gr.Column(): | |
| name = gr.Textbox( | |
| label="Project Name", | |
| placeholder="My ESP32 Project", | |
| value=self.config["project_info"]["name"] | |
| ) | |
| description = gr.Textbox( | |
| label="Description", | |
| placeholder="Describe your project...", | |
| lines=3, | |
| value=self.config["project_info"]["description"] | |
| ) | |
| with gr.Column(): | |
| author = gr.Textbox( | |
| label="Author", | |
| placeholder="Your Name", | |
| value=self.config["project_info"]["author"] | |
| ) | |
| version = gr.Textbox( | |
| label="Version", | |
| placeholder="1.0.0", | |
| value=self.config["project_info"]["version"] | |
| ) | |
| return gr.Column(name, description, author, version) | |
| def board_config_step(self): | |
| with gr.Column(): | |
| gr.Markdown("## ποΈ Board Configuration") | |
| gr.Markdown("Select your ESP32 board specifications.") | |
| board_model = gr.Dropdown( | |
| choices=["ESP32 DevKit", "ESP32 WROOM-32", "ESP32-C3", "ESP32-S2", "ESP32-S3", "M5Stack", "ESP32-CAM"], | |
| label="Board Model", | |
| value=self.config["board"]["model"] | |
| ) | |
| with gr.Row(): | |
| frequency = gr.Dropdown( | |
| choices=["240MHz", "160MHz", "80MHz"], | |
| label="CPU Frequency", | |
| value=self.config["board"]["frequency"] | |
| ) | |
| flash_size = gr.Dropdown( | |
| choices=["4MB", "8MB", "16MB"], | |
| label="Flash Size", | |
| value=self.config["board"]["flash_size"] | |
| ) | |
| return gr.Column(board_model, frequency, flash_size) | |
| def wifi_config_step(self): | |
| with gr.Column(): | |
| gr.Markdown("## πΆ WiFi Configuration") | |
| gr.Markdown("Configure WiFi settings for your ESP32.") | |
| wifi_enabled = gr.Checkbox( | |
| label="Enable WiFi", | |
| value=self.config["wifi"]["enabled"] | |
| ) | |
| with gr.Group() as wifi_group: | |
| with gr.Row(): | |
| ssid = gr.Textbox( | |
| label="WiFi SSID", | |
| placeholder="Your WiFi Network Name", | |
| value=self.config["wifi"]["ssid"] | |
| ) | |
| password = gr.Textbox( | |
| label="WiFi Password", | |
| type="password", | |
| placeholder="Your WiFi Password", | |
| value=self.config["wifi"]["password"] | |
| ) | |
| mode = gr.Radio( | |
| choices=["STA (Station)", "AP (Access Point)", "STA+AP"], | |
| label="WiFi Mode", | |
| value=self.config["wifi"]["mode"] | |
| ) | |
| with gr.Accordion("Static IP Configuration (Optional)", open=False): | |
| with gr.Row(): | |
| static_ip = gr.Textbox( | |
| label="Static IP", | |
| placeholder="192.168.1.100", | |
| value=self.config["wifi"]["static_ip"] | |
| ) | |
| gateway = gr.Textbox( | |
| label="Gateway", | |
| placeholder="192.168.1.1", | |
| value=self.config["wifi"]["gateway"] | |
| ) | |
| subnet = gr.Textbox( | |
| label="Subnet", | |
| placeholder="255.255.255.0", | |
| value=self.config["wifi"]["subnet"] | |
| ) | |
| return gr.Column(wifi_enabled, wifi_group, ssid, password, mode, static_ip, gateway, subnet) | |
| def components_step(self): | |
| with gr.Column(): | |
| gr.Markdown("## π§© Components & Libraries") | |
| gr.Markdown("Select the components and libraries you want to include.") | |
| components = gr.CheckboxGroup( | |
| choices=[ | |
| ("LED Control (Builtin LED)", "led"), | |
| ("Button Input", "button"), | |
| ("Sensor (DHT22)", "dht22"), | |
| ("Sensor (BME280)", "bme280"), | |
| ("Display (OLED SSD1306)", "oled"), | |
| ("Servo Motor", "servo"), | |
| ("Stepper Motor", "stepper"), | |
| ("Ultrasonic Sensor", "ultrasonic"), | |
| ("PIR Motion Sensor", "pir"), | |
| ("Relay", "relay"), | |
| ("MQTT Client", "mqtt"), | |
| ("Web Server", "webserver"), | |
| ("Web Client (HTTP)", "webclient"), | |
| ("Bluetooth", "bluetooth"), | |
| ("LoRa", "lora"), | |
| ("GPS", "gps"), | |
| ("SD Card", "sdcard"), | |
| ("Camera", "camera"), | |
| ("Audio I2S", "audio_i2s"), | |
| ("Neopixel (WS2812)", "neopixel") | |
| ], | |
| label="Components", | |
| value=self.config["components"] | |
| ) | |
| gr.Markdown("### Additional Libraries") | |
| libraries = gr.Textbox( | |
| label="Custom Libraries (comma separated)", | |
| placeholder="Adafruit_Sensor, ArduinoJson, etc.", | |
| value=", ".join(self.config["libraries"]) | |
| ) | |
| return gr.Column(components, libraries) | |
| def pins_config_step(self): | |
| with gr.Column(): | |
| gr.Markdown("## π Pin Configuration") | |
| gr.Markdown("Configure the GPIO pins for your components.") | |
| with gr.Row(): | |
| pin_type = gr.Dropdown( | |
| choices=["Digital Input", "Digital Output", "PWM", "Analog Input", "I2C SDA", "I2C SCL", "SPI MOSI", "SPI MISO", "SPI SCK", "SPI CS", "UART TX", "UART RX"], | |
| label="Pin Type" | |
| ) | |
| pin_number = gr.Dropdown( | |
| choices=[str(i) for i in range(0, 40)], | |
| label="GPIO Pin" | |
| ) | |
| pin_name = gr.Textbox(label="Pin Name/Variable") | |
| add_pin_btn = gr.Button("Add Pin", variant="primary") | |
| pins_list = gr.Dataframe( | |
| headers=["Type", "Pin", "Name"], | |
| datatype=["str", "str", "str"], | |
| label="Configured Pins", | |
| value=[[k, str(v), k] for k, v in self.config["pins"].items()] | |
| ) | |
| remove_pin_btn = gr.Button("Remove Selected", variant="secondary") | |
| return gr.Column(pin_type, pin_number, pin_name, add_pin_btn, pins_list, remove_pin_btn) | |
| def variables_step(self): | |
| with gr.Column(): | |
| gr.Markdown("## π§ Global Variables") | |
| gr.Markdown("Define global variables for your project.") | |
| with gr.Row(): | |
| var_name = gr.Textbox(label="Variable Name") | |
| var_type = gr.Dropdown( | |
| choices=["int", "float", "String", "bool", "long", "double", "char"], | |
| label="Type" | |
| ) | |
| var_value = gr.Textbox(label="Initial Value") | |
| add_var_btn = gr.Button("Add Variable", variant="primary") | |
| variables_list = gr.Dataframe( | |
| headers=["Name", "Type", "Value"], | |
| datatype=["str", "str", "str"], | |
| label="Global Variables", | |
| value=[[k, v["type"], v["value"]] for k, v in self.config["variables"].items()] | |
| ) | |
| remove_var_btn = gr.Button("Remove Selected", variant="secondary") | |
| return gr.Column(var_name, var_type, var_value, add_var_btn, variables_list, remove_var_btn) | |
| def custom_code_step(self): | |
| with gr.Column(): | |
| gr.Markdown("## π Custom Code") | |
| gr.Markdown("Add your custom setup and loop code.") | |
| gr.Markdown("### Setup Code (runs once)") | |
| setup_code = gr.Code( | |
| language="cpp", | |
| label="Setup Code", | |
| lines=10, | |
| value=self.config["custom_code"].get("setup", "") | |
| ) | |
| gr.Markdown("### Loop Code (runs repeatedly)") | |
| loop_code = gr.Code( | |
| language="cpp", | |
| label="Loop Code", | |
| lines=10, | |
| value=self.config["custom_code"].get("loop", "") | |
| ) | |
| gr.Markdown("### Helper Functions (optional)") | |
| helper_code = gr.Code( | |
| language="cpp", | |
| label="Helper Functions", | |
| lines=10, | |
| value=self.config["custom_code"].get("helpers", "") | |
| ) | |
| return gr.Column(setup_code, loop_code, helper_code) | |
| def preview_step(self): | |
| with gr.Column(): | |
| gr.Markdown("## π Code Preview") | |
| gr.Markdown("Review the generated ESP32 code before downloading.") | |
| code_preview = gr.Code( | |
| language="cpp", | |
| label="Generated Code", | |
| lines=30, | |
| value=generate_esp32_code(self.config) | |
| ) | |
| with gr.Row(): | |
| back_btn = gr.Button("β Back", variant="secondary") | |
| generate_btn = gr.Button("π Regenerate", variant="primary") | |
| continue_btn = gr.Button("Continue β", variant="primary") | |
| return gr.Column(code_preview, back_btn, generate_btn, continue_btn) | |
| def download_step(self): | |
| with gr.Column(): | |
| gr.Markdown("## π¦ Download Package") | |
| gr.Markdown("Your ESP32 project is ready!") | |
| generated_code = generate_esp32_code(self.config) | |
| libraries_code = self.generate_libraries_txt() | |
| with gr.Accordion("Generated Code", open=True): | |
| final_code = gr.Code( | |
| language="cpp", | |
| label="Final Code", | |
| lines=25, | |
| value=generated_code | |
| ) | |
| with gr.Accordion("Libraries Required", open=False): | |
| gr.Code( | |
| value=libraries_code, | |
| label="Libraries", | |
| language="text" | |
| ) | |
| download_file = gr.File( | |
| label="Download Complete Project", | |
| visible=False | |
| ) | |
| with gr.Row(): | |
| download_btn = gr.Button("π₯ Download ZIP", variant="primary", size="lg") | |
| new_project_btn = gr.Button("π New Project", variant="secondary", size="lg") | |
| return gr.Column(final_code, libraries_code, download_file, download_btn, new_project_btn) | |
| def create_esp32_wizard(): | |
| wizard = ESP32Wizard() | |
| with gr.Blocks( | |
| title="ESP32 Payload Creation Wizard", | |
| theme=gr.themes.Soft(), | |
| css=""" | |
| .wizard-step { | |
| border: 1px solid #e0e0e0; | |
| border-radius: 10px; | |
| padding: 20px; | |
| margin: 10px 0; | |
| } | |
| .step-indicator { | |
| background: linear-gradient(90deg, #4CAF50 0%, #45a049 100%); | |
| color: white; | |
| padding: 10px; | |
| border-radius: 5px; | |
| margin-bottom: 20px; | |
| } | |
| """ | |
| ) as demo: | |
| with gr.Row(): | |
| gr.HTML(""" | |
| <div style="text-align: center; margin-bottom: 20px;"> | |
| <h1>π§ ESP32 Payload Creation Wizard</h1> | |
| <p>Create complete, installable ESP32 projects with all dependencies</p> | |
| <a href="https://huggingface.co/spaces/akhaliq/anycoder" target="_blank" style="color: #4CAF50; text-decoration: none;"> | |
| Built with anycoder | |
| </a> | |
| </div> | |
| """) | |
| step_display = gr.Markdown("### Step 1 of 9: Project Information") | |
| with gr.Column(elem_classes="wizard-step"): | |
| content = wizard.get_step_content(0) | |
| with gr.Row(): | |
| prev_btn = gr.Button("β Previous", variant="secondary", visible=False) | |
| next_btn = gr.Button("Next β", variant="primary") | |
| reset_btn = gr.Button("π Reset", variant="secondary") | |
| def update_step(step, *inputs): | |
| # Update config based on current step | |
| if step == 0: # Project info | |
| wizard.config["project_info"].update({ | |
| "name": inputs[0], | |
| "description": inputs[1], | |
| "author": inputs[2], | |
| "version": inputs[3] | |
| }) | |
| elif step == 1: # Board config | |
| wizard.config["board"].update({ | |
| "model": inputs[0], | |
| "frequency": inputs[1], | |
| "flash_size": inputs[2] | |
| }) | |
| elif step == 2: # WiFi config | |
| wizard.config["wifi"].update({ | |
| "enabled": inputs[0], | |
| "ssid": inputs[2], | |
| "password": inputs[3], | |
| "mode": inputs[4], | |
| "static_ip": inputs[5], | |
| "gateway": inputs[6], | |
| "subnet": inputs[7] | |
| }) | |
| elif step == 3: # Components | |
| wizard.config["components"] = inputs[0] | |
| wizard.config["libraries"] = [lib.strip() for lib in inputs[1].split(",") if lib.strip()] | |
| # ... handle other steps | |
| # Navigate to next step | |
| new_step = min(step + 1, 8) | |
| step_names = [ | |
| "Project Information", | |
| "Board Configuration", | |
| "WiFi Configuration", | |
| "Components & Libraries", | |
| "Pin Configuration", | |
| "Global Variables", | |
| "Custom Code", | |
| "Code Preview", | |
| "Download Package" | |
| ] | |
| return ( | |
| gr.Column(visible=True), # Show new content | |
| f"### Step {new_step + 1} of 9: {step_names[new_step]}", | |
| wizard.get_step_content(new_step), | |
| gr.Button(visible=new_step > 0), | |
| gr.Button(visible=new_step < 8) | |
| ) | |
| def create_download_package(): | |
| # Create ZIP file with all project files | |
| zip_buffer = io.BytesIO() | |
| with zipfile.ZipFile(zip_buffer, 'w', zipfile.ZIP_DEFLATED) as zip_file: | |
| # Main sketch file | |
| code = generate_esp32_code(wizard.config) | |
| zip_file.writestr(f"{wizard.config['project_info']['name']}/{wizard.config['project_info']['name']}.ino", code) | |
| # libraries.txt | |
| libraries = wizard.generate_libraries_txt() | |
| zip_file.writestr(f"{wizard.config['project_info']['name']}/libraries.txt", libraries) | |
| # README.md | |
| readme = f"""# {wizard.config['project_info']['name']} | |
| {wizard.config['project_info']['description']} | |
| ## Author | |
| {wizard.config['project_info']['author']} | |
| ## Version | |
| {wizard.config['project_info']['version']} | |
| ## Board Configuration | |
| - Model: {wizard.config['board']['model']} | |
| - Frequency: {wizard.config['board']['frequency']} | |
| - Flash Size: {wizard.config['board']['flash_size']} | |
| ## Installation | |
| 1. Install Arduino IDE | |
| 2. Install ESP32 board support | |
| 3. Install required libraries (see libraries.txt) | |
| 4. Open the .ino file | |
| 5. Select your board and port | |
| 6. Upload to ESP32 | |
| ## Required Libraries | |
| {libraries} | |
| """ | |
| zip_file.writestr(f"{wizard.config['project_info']['name']}/README.md", readme) | |
| zip_buffer.seek(0) | |
| return zip_buffer.getvalue() | |
| # Event handlers | |
| next_btn.click( | |
| update_step, | |
| inputs=[gr.Number(wizard.current_step, visible=False)] + content.children, | |
| outputs=[content, step_display, content, prev_btn, next_btn] | |
| ) | |
| download_btn.click( | |
| create_download_package, | |
| outputs=[gr.File()] | |
| ) | |
| reset_btn.click( | |
| wizard.reset_config, | |
| outputs=[content, step_display, content, prev_btn, next_btn] | |
| ) | |
| return demo | |
| if __name__ == "__main__": | |
| demo = create_esp32_wizard() | |
| demo.launch() | |