一个新Arduino项目管理器GPT演示
扫描二维码
随时随地手机看文章
这是一个演示,展示了我正在开发的自定义gpt,并在r/arduino上发布了一系列关于它的内容。它可以很容易地与您的任何项目在您的标准工作。/ Arduino文件夹。它是多平台的,所以无论你运行的是Windows、macOS还是Linux,它都知道文件夹在哪里。
在这个示例项目中,我展示了将它与Arduino Nano一起使用,Arduino Nano上有一个Microchip ATmega328芯片。
它使用‘ arduino-cli ’工具直接与您的板对话,该工具在所有平台上都可用。
示例对话与Arduino项目经理自定义GPT
它可以分析和编辑您现有的任何项目,只需与它交谈,为您提供有关它们的建议,并编译和上传它们,而无需使用任何IDE。
我还发布了一系列关于如何使用OpenAI构建这个和其他客户GPT的文章。
如果有兴趣,我也会为b谷歌的AI平台开发同样专业的Gemini Gem。
是的,我必须拍摄我的屏幕,显示屏幕和Nano视频的两个单独的视频,因为我没有视频编辑功能,无法在图片视频中创建图片。但是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