一個新Arduino項目管理器GPT演示
這是一個演示,展示了我正在開發(fā)的自定義gpt,并在r/arduino上發(fā)布了一系列關(guān)于它的內(nèi)容。它可以很容易地與您的任何項目在您的標準工作。/ Arduino文件夾。它是多平臺的,所以無論你運行的是Windows、macOS還是Linux,它都知道文件夾在哪里。
在這個示例項目中,我展示了將它與Arduino Nano一起使用,Arduino Nano上有一個Microchip ATmega328芯片。
它使用‘ arduino-cli ’工具直接與您的板對話,該工具在所有平臺上都可用。
示例對話與Arduino項目經(jīng)理自定義GPT
它可以分析和編輯您現(xiàn)有的任何項目,只需與它交談,為您提供有關(guān)它們的建議,并編譯和上傳它們,而無需使用任何IDE。
我還發(fā)布了一系列關(guān)于如何使用OpenAI構(gòu)建這個和其他客戶GPT的文章。
如果有興趣,我也會為b谷歌的AI平臺開發(fā)同樣專業(yè)的Gemini Gem。
是的,我必須拍攝我的屏幕,顯示屏幕和Nano視頻的兩個單獨的視頻,因為我沒有視頻編輯功能,無法在圖片視頻中創(chuàng)建圖片。但是GPT控制著Nano,我保證。所有的代碼都可以在本系列中以及我的github存儲庫中獲得。
代碼
#!/usr/bin/env python3
"""
server.py
FastAPI server for managing Arduino projects with arduino-cli.
Exposes granular endpoints for OpenAI GPT integration.
@author Trent M. Wyatt (ripred)
@date February 19, 2025
@version 1.1
"""
import os
import subprocess
import logging
import platform
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
from typing import Optional, Dict, List
from pathlib import Path
# Set up logging
logging.basicConfig(
level=logging.INFO,
format="%(asctime)s - %(levelname)s - %(message)s",
handlers=[
logging.FileHandler("server.log"),
logging.StreamHandler()
]
)
logger = logging.getLogger(__name__)
app = FastAPI(
title="Arduino Project Manager",
description="API for managing Arduino projects with arduino-cli",
version="1.1.0"
)
# Determine OS and set Arduino directory dynamically
OS_TYPE = platform.system() # Detects 'Windows', 'Linux', or 'Darwin' (macOS)
if OS_TYPE == "Darwin": # macOS
ARDUINO_DIR = Path.home() / "Documents" / "Arduino"
elif OS_TYPE == "Windows": # Windows
ARDUINO_DIR = Path(os.environ["USERPROFILE"]) / "Documents" / "Arduino"
elif OS_TYPE == "Linux": # Linux
ARDUINO_DIR = Path.home() / "Arduino"
else:
raise RuntimeError(f"Unsupported operating system: {OS_TYPE}")
# Ensure the directory exists
ARDUINO_DIR.mkdir(parents=True, exist_ok=True)
logger.info(f"Arduino projects directory set to: {ARDUINO_DIR}")
# Pydantic models for request validation
class ProjectRequest(BaseModel):
project_name: str
class SketchRequest(BaseModel):
project_name: str
sketch_content: str
class UploadRequest(BaseModel):
project_name: str
port: str
# Helper function to run shell commands
def run_command(command: List[str], cwd: Optional[Path] = None) -> Dict[str, str]:
try:
result = subprocess.run(
command,
cwd=cwd,
capture_output=True,
text=True,
check=True
)
return {"status": "success", "output": result.stdout, "error": ""}
except subprocess.CalledProcessError as e:
logger.error(f"Command failed: {command}, Error: {e.stderr}")
return {"status": "error", "output": "", "error": e.stderr}
except Exception as e:
logger.error(f"Unexpected error: {str(e)}")
return {"status": "error", "output": "", "error": str(e)}
@app.post("/check_folder", summary="Check if project folder exists")
async def check_folder(request: ProjectRequest):
"""Check if the specified project folder exists."""
project_dir = ARDUINO_DIR / request.project_name
exists = project_dir.exists() and project_dir.is_dir()
logger.info(f"Checked folder {project_dir}: {'exists' if exists else 'does not exist'}")
return {"exists": exists}
@app.post("/read_files", summary="Read all files in project folder")
async def read_files(request: ProjectRequest):
"""Read all files in the specified project folder."""
project_dir = ARDUINO_DIR / request.project_name
if not project_dir.exists() or not project_dir.is_dir():
logger.error(f"Project folder not found: {project_dir}")
raise HTTPException(status_code=404, detail="Project folder not found")
files_content = {}
for file_path in project_dir.glob("*"):
try:
with open(file_path, "r") as f:
files_content[file_path.name] = f.read()
except Exception as e:
logger.error(f"Failed to read file {file_path}: {str(e)}")
raise HTTPException(status_code=500, detail=f"Failed to read file {file_path.name}: {str(e)}")
logger.info(f"Read files from {project_dir}: {list(files_content.keys())}")
return {"files": files_content}
@app.post("/create_project", summary="Create project folder and write sketch")
async def create_project(request: SketchRequest):
"""Create a project folder and write the sketch file if it doesn't exist."""
project_dir = ARDUINO_DIR / request.project_name
sketch_file = project_dir / f"{request.project_name}.ino"
if project_dir.exists() and sketch_file.exists():
logger.error(f"Project already exists: {project_dir}")
raise HTTPException(status_code=400, detail="Project already exists")
try:
project_dir.mkdir(parents=True, exist_ok=True)
with open(sketch_file, "w") as f:
f.write(request.sketch_content)
logger.info(f"Created project {project_dir} with sketch {sketch_file}")
return {"status": "success", "message": f"Created project {request.project_name}"}
except Exception as e:
logger.error(f"Failed to create project {project_dir}: {str(e)}")
raise HTTPException(status_code=500, detail=f"Failed to create project: {str(e)}")
@app.post("/update_sketch", summary="Update sketch file contents")
async def update_sketch(request: SketchRequest):
"""Update the contents of the sketch file in the project folder."""
project_dir = ARDUINO_DIR / request.project_name
sketch_file = project_dir / f"{request.project_name}.ino"
if not project_dir.exists() or not sketch_file.exists():
logger.error(f"Project or sketch not found: {sketch_file}")
raise HTTPException(status_code=404, detail="Project or sketch file not found")
try:
with open(sketch_file, "w") as f:
f.write(request.sketch_content)
logger.info(f"Updated sketch {sketch_file}")
return {"status": "success", "message": f"Updated sketch {request.project_name}.ino"}
except Exception as e:
logger.error(f"Failed to update sketch {sketch_file}: {str(e)}")
raise HTTPException(status_code=500, detail=f"Failed to update sketch: {str(e)}")
@app.post("/compile_project", summary="Compile project using arduino-cli")
async def compile_project(request: ProjectRequest):
"""Compile the specified project using arduino-cli."""
project_dir = ARDUINO_DIR / request.project_name
if not project_dir.exists() or not (project_dir / f"{request.project_name}.ino").exists():
logger.error(f"Project or sketch not found: {project_dir}")
raise HTTPException(status_code=404, detail="Project or sketch file not found")
command = ["arduino-cli", "compile", "--fqbn", "arduino:avr:nano:cpu=atmega328old", str(project_dir)]
result = run_command(command, cwd=ARDUINO_DIR)
logger.info(f"Compilation result for {project_dir}: {result['status']}")
if result["status"] == "error":
raise HTTPException(status_code=500, detail=f"Compilation failed: {result['error']}")
return result
@app.post("/upload_project", summary="Upload compiled project to Arduino")
async def upload_project(request: UploadRequest):
"""Upload the compiled project to the specified Arduino port."""
project_dir = ARDUINO_DIR / request.project_name
if not project_dir.exists() or not (project_dir / f"{request.project_name}.ino").exists():
logger.error(f"Project or sketch not found: {project_dir}")
raise HTTPException(status_code=404, detail="Project or sketch file not found")
command = ["arduino-cli", "upload", "-p", request.port, "--fqbn", "arduino:avr:nano:cpu=atmega328old", str(project_dir)]
result = run_command(command, cwd=ARDUINO_DIR)
logger.info(f"Upload result for {project_dir} to {request.port}: {result['status']}")
if result["status"] == "error":
raise HTTPException(status_code=500, detail=f"Upload failed: {result['error']}")
return result
本文編譯自hackster.io