kicad:EasyEDA→KiCad 工程(Board1/Board2)、库、脚本与评审文档(IC 引脚、风扇、热、EDL 供电、布局规则)
Co-Authored-By: Claude Opus 5.5 <[email protected]>
这个提交包含在:
@@ -0,0 +1,95 @@
|
||||
"""Read the live EasyEDA component catalog through the installed API bridge.
|
||||
|
||||
Archive exact device-search and device-detail responses for fan selection.
|
||||
This does not edit the EasyEDA project or claim that catalog entries are stocked.
|
||||
"""
|
||||
import argparse
|
||||
from datetime import datetime, timezone
|
||||
import json
|
||||
from pathlib import Path
|
||||
import sys
|
||||
|
||||
import requests
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[1]
|
||||
|
||||
|
||||
def bridge(session):
|
||||
for port in range(49620, 49630):
|
||||
base = f'http://127.0.0.1:{port}'
|
||||
try:
|
||||
response = session.get(base + '/health', timeout=.5)
|
||||
health = response.json()
|
||||
except (requests.RequestException, ValueError):
|
||||
continue
|
||||
if health.get('service') == 'easyeda-bridge':
|
||||
return base, health
|
||||
raise RuntimeError('Installed EasyEDA API bridge not reachable on 49620-49629')
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
sub = parser.add_subparsers(dest='action', required=True)
|
||||
sub.add_parser('probe')
|
||||
search = sub.add_parser('search')
|
||||
search.add_argument('keywords', nargs='+')
|
||||
search.add_argument('--page', type=int, default=1)
|
||||
search.add_argument('--limit', type=int, default=100)
|
||||
search.add_argument('--category', nargs=2, metavar=('PRIMARY_UUID', 'SECONDARY_UUID'))
|
||||
detail = sub.add_parser('detail')
|
||||
detail.add_argument('uuid')
|
||||
detail.add_argument('--library')
|
||||
args = parser.parse_args()
|
||||
session = requests.Session()
|
||||
session.trust_env = False
|
||||
base, health = bridge(session)
|
||||
if args.action == 'probe':
|
||||
print(json.dumps(health, ensure_ascii=False, indent=2))
|
||||
return 0 if health.get('edaConnected') else 2
|
||||
if not health.get('edaConnected'):
|
||||
raise RuntimeError('Bridge is healthy but no EasyEDA API Gateway window is connected')
|
||||
# Reading the public catalog does not require selecting or editing a project.
|
||||
window = health.get('activeWindowId')
|
||||
if not window:
|
||||
raise RuntimeError('No active EasyEDA window; select a client window first')
|
||||
if args.action == 'search':
|
||||
assert 1 <= args.limit <= 100 and args.page >= 1
|
||||
category = json.dumps({'libraryUuid': '0819f05c4eef4c71ace90d822a990e87', 'libraryType': '3',
|
||||
'primaryClassificationUuid': args.category[0],
|
||||
'secondaryClassificationUuid': args.category[1]}) if args.category else 'undefined'
|
||||
queries = [(key, 'return await eda.lib_Device.search(' + json.dumps('' if key == '*' else key) +
|
||||
f', undefined, {category}, undefined, {args.limit}, {args.page});') for key in args.keywords]
|
||||
else:
|
||||
queries = [(args.uuid, 'return await eda.lib_Device.get(' + json.dumps(args.uuid) +
|
||||
', ' + (json.dumps(args.library) if args.library else 'undefined') + ');')]
|
||||
output = ROOT/'out/fan-catalog'
|
||||
output.mkdir(exist_ok=True)
|
||||
for query, code in queries:
|
||||
response = session.post(base+'/execute', json={'code': code, 'windowId': window}, timeout=40)
|
||||
response.raise_for_status()
|
||||
result = response.json()
|
||||
if result.get('success') is False or result.get('error'):
|
||||
raise RuntimeError(str(result))
|
||||
timestamp = datetime.now(timezone.utc)
|
||||
record = {'retrieved_at_utc': timestamp.isoformat(), 'source': 'Live EasyEDA lib_Device API',
|
||||
'window_id': window, 'operation': args.action, 'query': query,
|
||||
'page': getattr(args, 'page', None), 'category': getattr(args, 'category', None), 'response': result}
|
||||
path = output/(timestamp.strftime('%Y%m%dT%H%M%S%f')+'-'+args.action+'.json')
|
||||
path.write_text(json.dumps(record, indent=2, ensure_ascii=False)+'\n', encoding='utf-8')
|
||||
print(path.relative_to(ROOT))
|
||||
data = result.get('result')
|
||||
if isinstance(data, list):
|
||||
print('Results:', len(data), flush=True)
|
||||
for part in data:
|
||||
print(json.dumps({k: part.get(k) for k in ['name', 'uuid', 'supplierId', 'description']}, ensure_ascii=False), flush=True)
|
||||
else:
|
||||
print(json.dumps(data, ensure_ascii=False), flush=True)
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
try:
|
||||
raise SystemExit(main())
|
||||
except (RuntimeError, requests.RequestException) as exc:
|
||||
print(str(exc), file=sys.stderr)
|
||||
raise SystemExit(2)
|
||||
在新工单中引用
屏蔽一个用户