You've already forked AiraPulsar
Compare commits
14 Commits
b86ffd9f5b
...
main
Author | SHA1 | Date | |
---|---|---|---|
f33d7bbec8 | |||
bf400ca9c2 | |||
24c1a94f36 | |||
fd67663868 | |||
27d7ffe4bf | |||
89c8b34550 | |||
fdf2e1a3ff | |||
a7b0373425 | |||
890543e3c1 | |||
bce75a1727 | |||
551ed9a4ce | |||
28986de6ea | |||
da3da80b17 | |||
84372e6dd8 |
@@ -12,7 +12,7 @@ venv.bak/
|
||||
*.egg-info/
|
||||
dist/
|
||||
build/
|
||||
|
||||
.tmp
|
||||
# IDEs and editors
|
||||
.vscode/
|
||||
.idea/
|
||||
|
27
README.md
27
README.md
@@ -1,2 +1,27 @@
|
||||
# AiraPulsar 飞行控制系统
|
||||
AiraPulsar (空中脉冲星, 简称 APSR) 是一套基于 WebSocket 的三点架构的轻量级网络飞行控制系统
|
||||
AiraPulsar 是一套适用于固定翼无人机/航模的轻量级通用网络飞行控制系统
|
||||
|
||||
(待)支持功能:
|
||||
- 影像实时回传/录制
|
||||
- HUD 支持
|
||||
- 多驾驶员/操作员链接支持 & 同步
|
||||
- 鼠标/键盘飞行姿态控制
|
||||
- 计算机辅助姿态修正 & 改出
|
||||
- 自动辅助降落控制
|
||||
- 物理断链情况下的自降落/修正/重新连接
|
||||
- 飞行数据/机载设备监控
|
||||
- 机体状态图像式监控
|
||||
- 垂直载荷投放计算 (持续计算打击点)
|
||||
|
||||
特色:
|
||||
- 通用机载计算机部署
|
||||
- 模块化设计
|
||||
- 数据中转服务器
|
||||
|
||||
目录说明:
|
||||
- comet: 飞行器侧载端
|
||||
- pulsar: 控制器客户端
|
||||
- moon: 数据中转服务器端
|
||||
- vgl: 矢量图形层 (库)
|
||||
- testfield: 开发中组件
|
||||
- auxiliary: 辅助程序
|
@@ -1,52 +0,0 @@
|
||||
import pygame
|
||||
|
||||
|
||||
def selector():
|
||||
pygame.init()
|
||||
try:
|
||||
width = int(input("Frame Width: "))
|
||||
height = int(input("Frame Height: "))
|
||||
except:
|
||||
width = 800
|
||||
height = 600
|
||||
screen = pygame.display.set_mode((width, height))
|
||||
pygame.display.set_caption("UI Design Auxiliary Tool")
|
||||
selecting = False
|
||||
start_pos = None
|
||||
end_pos = None
|
||||
running = True
|
||||
screen.fill((0,0,0))
|
||||
while running:
|
||||
screen.fill((0,0,0))
|
||||
for event in pygame.event.get():
|
||||
if event.type == pygame.QUIT:
|
||||
running = False
|
||||
elif event.type == pygame.MOUSEBUTTONDOWN:
|
||||
if event.button == 1: # 左键
|
||||
selecting = True
|
||||
start_pos = event.pos
|
||||
elif event.type == pygame.MOUSEMOTION:
|
||||
if selecting:
|
||||
end_pos = event.pos
|
||||
elif event.type == pygame.MOUSEBUTTONUP:
|
||||
if event.button == 1:
|
||||
selecting = False
|
||||
if start_pos and end_pos:
|
||||
rect = pygame.Rect(
|
||||
start_pos,
|
||||
(end_pos[0] - start_pos[0], end_pos[1] - start_pos[1]),
|
||||
)
|
||||
|
||||
if selecting and start_pos and end_pos:
|
||||
rect = pygame.Rect(
|
||||
start_pos, (end_pos[0] - start_pos[0], end_pos[1] - start_pos[1])
|
||||
)
|
||||
pygame.draw.rect(screen, (255, 0, 0), rect, 2) # 绘制选区矩形
|
||||
|
||||
pygame.display.flip()
|
||||
|
||||
pygame.quit()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
@@ -1,28 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>图形参数生成器</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>图形参数生成器</h1>
|
||||
<label for="shape">图形类型:</label>
|
||||
<select id="shape">
|
||||
<option value="rect">矩形</option>
|
||||
<option value="line">线条</option>
|
||||
<option value="circle">圆形</option>
|
||||
<option value="ellipse">椭圆</option>
|
||||
<option value="polygon">多边形</option>
|
||||
<option value="arc">弧形</option>
|
||||
<option value="point">点</option>
|
||||
<option value="lines">线段</option>
|
||||
</select><br><br>
|
||||
|
||||
<div id="params"></div><br>
|
||||
|
||||
<button id="generate">生成图形参数</button><br><br>
|
||||
|
||||
<div id="result"></div>
|
||||
|
||||
<script src="script.js"></script>
|
||||
</body>
|
||||
</html>
|
@@ -1,152 +0,0 @@
|
||||
function generateShapeDict(shape, params) {
|
||||
if (shape === 'rect') {
|
||||
return {
|
||||
method: 'rect',
|
||||
pos: params.pos || [0, 0],
|
||||
size: params.size || [1, 1],
|
||||
color: params.color || [255, 255, 255],
|
||||
width: params.width || 0
|
||||
};
|
||||
} else if (shape === 'line') {
|
||||
return {
|
||||
method: 'line',
|
||||
start_pos: params.start_pos || [0, 0],
|
||||
end_pos: params.end_pos || [1, 1],
|
||||
color: params.color || [255, 255, 255]
|
||||
};
|
||||
} else if (shape === 'circle') {
|
||||
return {
|
||||
method: 'circle',
|
||||
center: params.center || [0, 0],
|
||||
radius: params.radius || 1,
|
||||
color: params.color || [255, 255, 255]
|
||||
};
|
||||
} else if (shape === 'ellipse') {
|
||||
return {
|
||||
method: 'ellipse',
|
||||
pos: params.pos || [0, 0],
|
||||
size: params.size || [1, 1],
|
||||
color: params.color || [255, 255, 255]
|
||||
};
|
||||
} else if (shape === 'polygon') {
|
||||
return {
|
||||
method: 'polygon',
|
||||
pointlist: params.pointlist || [],
|
||||
color: params.color || [255, 255, 255]
|
||||
};
|
||||
} else if (shape === 'arc') {
|
||||
return {
|
||||
method: 'arc',
|
||||
pos: params.pos || [0, 0],
|
||||
size: params.size || [1, 1],
|
||||
color: params.color || [255, 255, 255],
|
||||
start_angle: params.start_angle || 0,
|
||||
stop_angle: params.stop_angle || 3.14
|
||||
};
|
||||
} else if (shape === 'point') {
|
||||
return {
|
||||
method: 'point',
|
||||
pos: params.pos || [0, 0],
|
||||
color: params.color || [255, 255, 255]
|
||||
};
|
||||
} else if (shape === 'lines') {
|
||||
return {
|
||||
method: 'lines',
|
||||
pointlist: params.pointlist || [],
|
||||
color: params.color || [255, 255, 255]
|
||||
};
|
||||
} else {
|
||||
throw new Error("Unsupported shape type");
|
||||
}
|
||||
}
|
||||
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
const shapeSelect = document.getElementById('shape');
|
||||
const paramsDiv = document.getElementById('params');
|
||||
const generateButton = document.getElementById('generate');
|
||||
const resultDiv = document.getElementById('result');
|
||||
|
||||
function createInput(label, id, type = 'text') {
|
||||
const input = document.createElement('input');
|
||||
input.type = type;
|
||||
input.id = id;
|
||||
const labelElement = document.createElement('label');
|
||||
labelElement.textContent = label + ': ';
|
||||
labelElement.setAttribute('for', id);
|
||||
paramsDiv.appendChild(labelElement);
|
||||
paramsDiv.appendChild(input);
|
||||
paramsDiv.appendChild(document.createElement('br'));
|
||||
return input;
|
||||
}
|
||||
|
||||
function updateParamsInputs() {
|
||||
paramsDiv.innerHTML = '';
|
||||
const shape = shapeSelect.value;
|
||||
|
||||
if (shape === 'rect') {
|
||||
createInput('矩形位置 (x y)', 'pos');
|
||||
createInput('矩形大小 (width height)', 'size');
|
||||
createInput('矩形颜色 (R G B)', 'color');
|
||||
createInput('矩形边框宽度', 'width', 'number');
|
||||
} else if (shape === 'line') {
|
||||
createInput('起始位置 (x y)', 'start_pos');
|
||||
createInput('结束位置 (x y)', 'end_pos');
|
||||
createInput('线条颜色 (R G B)', 'color');
|
||||
} else if (shape === 'circle') {
|
||||
createInput('圆心位置 (x y)', 'center');
|
||||
createInput('圆的半径', 'radius', 'number');
|
||||
createInput('圆的颜色 (R G B)', 'color');
|
||||
} else if (shape === 'ellipse') {
|
||||
createInput('椭圆位置 (x y)', 'pos');
|
||||
createInput('椭圆大小 (width height)', 'size');
|
||||
createInput('椭圆颜色 (R G B)', 'color');
|
||||
} else if (shape === 'polygon') {
|
||||
createInput('多边形的点 (x1 y1 x2 y2 ...)', 'pointlist');
|
||||
createInput('多边形颜色 (R G B)', 'color');
|
||||
} else if (shape === 'arc') {
|
||||
createInput('弧的位置 (x y)', 'pos');
|
||||
createInput('弧的大小 (width height)', 'size');
|
||||
createInput('弧的颜色 (R G B)', 'color');
|
||||
createInput('弧的起始角度 (弧度制)', 'start_angle', 'number');
|
||||
createInput('弧的结束角度 (弧度制)', 'stop_angle', 'number');
|
||||
} else if (shape === 'point') {
|
||||
createInput('点的位置 (x y)', 'pos');
|
||||
createInput('点的颜色 (R G B)', 'color');
|
||||
} else if (shape === 'lines') {
|
||||
createInput('线段的点 (x1 y1 x2 y2 ...)', 'pointlist');
|
||||
createInput('线段颜色 (R G B)', 'color');
|
||||
}
|
||||
}
|
||||
|
||||
shapeSelect.addEventListener('change', updateParamsInputs);
|
||||
updateParamsInputs();
|
||||
|
||||
generateButton.addEventListener('click', function() {
|
||||
const shape = shapeSelect.value;
|
||||
const params = {};
|
||||
const inputs = paramsDiv.querySelectorAll('input');
|
||||
|
||||
inputs.forEach(input => {
|
||||
if (input.id === 'pointlist') {
|
||||
const points = input.value.split(' ').map(Number);
|
||||
params.pointlist = [];
|
||||
for (let i = 0; i < points.length; i += 2) {
|
||||
params.pointlist.push([points[i], points[i + 1]]);
|
||||
}
|
||||
} else if (input.id === 'pos' || input.id === 'size' || input.id === 'start_pos' || input.id === 'end_pos' || input.id === 'center' || input.id === 'color') {
|
||||
params[input.id] = input.value.split(' ').map(Number);
|
||||
} else if (input.type === 'number') {
|
||||
params[input.id] = parseFloat(input.value);
|
||||
} else {
|
||||
params[input.id] = input.value;
|
||||
}
|
||||
});
|
||||
|
||||
try {
|
||||
const shapeDict = generateShapeDict(shape, params);
|
||||
resultDiv.innerHTML = '<pre>' + JSON.stringify(shapeDict, null, 2) + '</pre>';
|
||||
} catch (error) {
|
||||
resultDiv.innerHTML = '<p>错误: ' + error.message + '</p>';
|
||||
}
|
||||
});
|
||||
});
|
1
comet/.python-version
Normal file
1
comet/.python-version
Normal file
@@ -0,0 +1 @@
|
||||
3.13
|
@@ -1,213 +0,0 @@
|
||||
2025-03-07T08:56:35.501146+0800 - INFO - 初始化代理对象
|
||||
2025-03-07T08:56:35.501324+0800 - INFO - 卫星地址: ws://127.0.0.1:8765
|
||||
2025-03-07T08:56:35.501414+0800 - INFO - 代理对象代号: comet
|
||||
2025-03-07T08:57:13.903527+0800 - INFO - 初始化代理对象
|
||||
2025-03-07T08:57:13.903678+0800 - INFO - 卫星地址: ws://127.0.0.1:8765
|
||||
2025-03-07T08:57:13.903742+0800 - INFO - 代理对象代号: comet
|
||||
2025-03-07T08:58:55.379859+0800 - INFO - 初始化代理对象
|
||||
2025-03-07T08:58:55.380016+0800 - INFO - 卫星地址: ws://127.0.0.1:8765
|
||||
2025-03-07T08:58:55.380084+0800 - INFO - 代理对象代号: comet
|
||||
2025-03-07T08:59:05.381232+0800 - INFO - 初始化代理对象
|
||||
2025-03-07T08:59:05.381387+0800 - INFO - 卫星地址: ws://127.0.0.1:8765
|
||||
2025-03-07T08:59:05.381444+0800 - INFO - 代理对象代号: comet
|
||||
2025-03-07T08:59:52.906831+0800 - INFO - 初始化代理对象
|
||||
2025-03-07T08:59:52.906996+0800 - INFO - 卫星地址: ws://127.0.0.1:8765
|
||||
2025-03-07T08:59:52.907060+0800 - INFO - 代理对象代号: comet
|
||||
2025-03-07T09:00:41.008959+0800 - INFO - 初始化代理对象
|
||||
2025-03-07T09:00:41.008959+0800 - INFO - 初始化代理对象
|
||||
2025-03-07T09:00:41.009179+0800 - INFO - 卫星地址: ws://127.0.0.1:8765
|
||||
2025-03-07T09:00:41.009179+0800 - INFO - 卫星地址: ws://127.0.0.1:8765
|
||||
2025-03-07T09:00:41.009279+0800 - INFO - 代理对象代号: comet
|
||||
2025-03-07T09:00:41.009279+0800 - INFO - 代理对象代号: comet
|
||||
2025-03-07T09:00:44.632829+0800 - INFO - 初始化代理对象
|
||||
2025-03-07T09:00:44.632829+0800 - INFO - 初始化代理对象
|
||||
2025-03-07T09:00:44.633010+0800 - INFO - 卫星地址: ws://127.0.0.1:8765
|
||||
2025-03-07T09:00:44.633010+0800 - INFO - 卫星地址: ws://127.0.0.1:8765
|
||||
2025-03-07T09:00:44.633098+0800 - INFO - 代理对象代号: comet
|
||||
2025-03-07T09:00:44.633098+0800 - INFO - 代理对象代号: comet
|
||||
2025-03-07T09:01:31.329481+0800 - INFO - 初始化代理对象
|
||||
2025-03-07T09:01:31.329481+0800 - INFO - 初始化代理对象
|
||||
2025-03-07T09:01:31.329691+0800 - INFO - 卫星地址: ws://127.0.0.1:8765
|
||||
2025-03-07T09:01:31.329691+0800 - INFO - 卫星地址: ws://127.0.0.1:8765
|
||||
2025-03-07T09:01:31.329762+0800 - INFO - 代理对象代号: comet
|
||||
2025-03-07T09:01:31.329762+0800 - INFO - 代理对象代号: comet
|
||||
2025-03-07T09:02:18.294306+0800 - INFO - 初始化代理对象
|
||||
2025-03-07T09:02:18.294306+0800 - INFO - 初始化代理对象
|
||||
2025-03-07T09:02:18.294467+0800 - INFO - 卫星地址: ws://127.0.0.1:8765
|
||||
2025-03-07T09:02:18.294467+0800 - INFO - 卫星地址: ws://127.0.0.1:8765
|
||||
2025-03-07T09:02:18.294542+0800 - INFO - 代理对象代号: comet
|
||||
2025-03-07T09:02:18.294542+0800 - INFO - 代理对象代号: comet
|
||||
2025-03-07T09:02:49.424696+0800 - INFO - 初始化代理对象
|
||||
2025-03-07T09:02:49.424696+0800 - INFO - 初始化代理对象
|
||||
2025-03-07T09:02:49.424863+0800 - INFO - 卫星地址: ws://127.0.0.1:8765
|
||||
2025-03-07T09:02:49.424863+0800 - INFO - 卫星地址: ws://127.0.0.1:8765
|
||||
2025-03-07T09:02:49.424947+0800 - INFO - 代理对象代号: comet
|
||||
2025-03-07T09:02:49.424947+0800 - INFO - 代理对象代号: comet
|
||||
2025-03-07T09:03:12.117053+0800 - INFO - 初始化代理对象
|
||||
2025-03-07T09:03:12.117053+0800 - INFO - 初始化代理对象
|
||||
2025-03-07T09:03:12.117278+0800 - INFO - 卫星地址: ws://127.0.0.1:8765
|
||||
2025-03-07T09:03:12.117278+0800 - INFO - 卫星地址: ws://127.0.0.1:8765
|
||||
2025-03-07T09:03:12.117377+0800 - INFO - 代理对象代号: comet
|
||||
2025-03-07T09:03:12.117377+0800 - INFO - 代理对象代号: comet
|
||||
2025-03-07T09:03:43.470032+0800 - INFO - 初始化代理对象
|
||||
2025-03-07T09:03:43.470032+0800 - INFO - 初始化代理对象
|
||||
2025-03-07T09:03:43.470267+0800 - INFO - 卫星地址: ws://127.0.0.1:8765
|
||||
2025-03-07T09:03:43.470267+0800 - INFO - 卫星地址: ws://127.0.0.1:8765
|
||||
2025-03-07T09:03:43.470342+0800 - INFO - 代理对象代号: comet
|
||||
2025-03-07T09:03:43.470342+0800 - INFO - 代理对象代号: comet
|
||||
2025-03-07T09:11:06.876601+0800 - INFO - 初始化代理对象
|
||||
2025-03-07T09:11:06.876601+0800 - INFO - 初始化代理对象
|
||||
2025-03-07T09:11:06.876858+0800 - INFO - 卫星地址: ws://127.0.0.1:8765
|
||||
2025-03-07T09:11:06.876858+0800 - INFO - 卫星地址: ws://127.0.0.1:8765
|
||||
2025-03-07T09:11:06.876965+0800 - INFO - 代理对象代号: comet
|
||||
2025-03-07T09:11:06.876965+0800 - INFO - 代理对象代号: comet
|
||||
2025-03-07T09:12:16.848236+0800 - INFO - 初始化代理对象
|
||||
2025-03-07T09:12:16.848236+0800 - INFO - 初始化代理对象
|
||||
2025-03-07T09:12:16.848397+0800 - INFO - 卫星地址: ws://127.0.0.1:8765
|
||||
2025-03-07T09:12:16.848397+0800 - INFO - 卫星地址: ws://127.0.0.1:8765
|
||||
2025-03-07T09:12:16.848476+0800 - INFO - 代理对象代号: comet
|
||||
2025-03-07T09:12:16.848476+0800 - INFO - 代理对象代号: comet
|
||||
2025-03-07T09:19:10.751685+0800 - INFO - 初始化代理对象
|
||||
2025-03-07T09:19:10.751685+0800 - INFO - 初始化代理对象
|
||||
2025-03-07T09:19:10.751843+0800 - INFO - 卫星地址: ws://127.0.0.1:8765
|
||||
2025-03-07T09:19:10.751843+0800 - INFO - 卫星地址: ws://127.0.0.1:8765
|
||||
2025-03-07T09:19:10.751912+0800 - INFO - 代理对象代号: comet
|
||||
2025-03-07T09:19:10.751912+0800 - INFO - 代理对象代号: comet
|
||||
2025-03-07T09:19:20.013536+0800 - INFO - 初始化代理对象
|
||||
2025-03-07T09:19:20.013536+0800 - INFO - 初始化代理对象
|
||||
2025-03-07T09:19:20.013686+0800 - INFO - 卫星地址: ws://127.0.0.1:8765
|
||||
2025-03-07T09:19:20.013686+0800 - INFO - 卫星地址: ws://127.0.0.1:8765
|
||||
2025-03-07T09:19:20.013757+0800 - INFO - 代理对象代号: comet
|
||||
2025-03-07T09:19:20.013757+0800 - INFO - 代理对象代号: comet
|
||||
2025-03-07T09:19:39.079365+0800 - INFO - 初始化代理对象
|
||||
2025-03-07T09:19:39.079365+0800 - INFO - 初始化代理对象
|
||||
2025-03-07T09:19:39.079590+0800 - INFO - 卫星地址: ws://127.0.0.1:8765
|
||||
2025-03-07T09:19:39.079590+0800 - INFO - 卫星地址: ws://127.0.0.1:8765
|
||||
2025-03-07T09:19:39.079663+0800 - INFO - 代理对象代号: comet
|
||||
2025-03-07T09:19:39.079663+0800 - INFO - 代理对象代号: comet
|
||||
2025-03-07T09:20:13.855104+0800 - INFO - 初始化代理对象
|
||||
2025-03-07T09:20:13.855104+0800 - INFO - 初始化代理对象
|
||||
2025-03-07T09:20:13.855261+0800 - INFO - 卫星地址: ws://127.0.0.1:8765
|
||||
2025-03-07T09:20:13.855261+0800 - INFO - 卫星地址: ws://127.0.0.1:8765
|
||||
2025-03-07T09:20:13.855328+0800 - INFO - 代理对象代号: comet
|
||||
2025-03-07T09:20:13.855328+0800 - INFO - 代理对象代号: comet
|
||||
2025-03-07T09:20:22.574788+0800 - INFO - 初始化代理对象
|
||||
2025-03-07T09:20:22.574788+0800 - INFO - 初始化代理对象
|
||||
2025-03-07T09:20:22.574961+0800 - INFO - 卫星地址: ws://127.0.0.1:8765
|
||||
2025-03-07T09:20:22.574961+0800 - INFO - 卫星地址: ws://127.0.0.1:8765
|
||||
2025-03-07T09:20:22.575035+0800 - INFO - 代理对象代号: comet
|
||||
2025-03-07T09:20:22.575035+0800 - INFO - 代理对象代号: comet
|
||||
2025-03-07T09:26:57.804810+0800 - INFO - 初始化代理对象
|
||||
2025-03-07T09:26:57.804810+0800 - INFO - 初始化代理对象
|
||||
2025-03-07T09:26:57.804965+0800 - INFO - 卫星地址: ws://127.0.0.1:8765
|
||||
2025-03-07T09:26:57.804965+0800 - INFO - 卫星地址: ws://127.0.0.1:8765
|
||||
2025-03-07T09:26:57.805033+0800 - INFO - 代理对象代号: comet
|
||||
2025-03-07T09:26:57.805033+0800 - INFO - 代理对象代号: comet
|
||||
2025-03-07T09:28:26.670684+0800 - INFO - 初始化代理对象
|
||||
2025-03-07T09:28:26.670684+0800 - INFO - 初始化代理对象
|
||||
2025-03-07T09:28:26.670920+0800 - INFO - 卫星地址: ws://127.0.0.1:8765
|
||||
2025-03-07T09:28:26.670920+0800 - INFO - 卫星地址: ws://127.0.0.1:8765
|
||||
2025-03-07T09:28:26.671025+0800 - INFO - 代理对象代号: comet
|
||||
2025-03-07T09:28:26.671025+0800 - INFO - 代理对象代号: comet
|
||||
2025-03-07T09:28:26.674242+0800 - INFO - 成功建立连接
|
||||
2025-03-07T09:28:26.674242+0800 - INFO - 成功建立连接
|
||||
2025-03-07T09:28:35.156211+0800 - INFO - 初始化代理对象
|
||||
2025-03-07T09:28:35.156211+0800 - INFO - 初始化代理对象
|
||||
2025-03-07T09:28:35.156372+0800 - INFO - 卫星地址: ws://127.0.0.1:8765
|
||||
2025-03-07T09:28:35.156372+0800 - INFO - 卫星地址: ws://127.0.0.1:8765
|
||||
2025-03-07T09:28:35.156458+0800 - INFO - 代理对象代号: comet
|
||||
2025-03-07T09:28:35.156458+0800 - INFO - 代理对象代号: comet
|
||||
2025-03-07T09:28:35.159041+0800 - INFO - 成功建立连接
|
||||
2025-03-07T09:28:35.159041+0800 - INFO - 成功建立连接
|
||||
2025-03-07T09:29:25.100332+0800 - INFO - 初始化代理对象
|
||||
2025-03-07T09:29:25.100332+0800 - INFO - 初始化代理对象
|
||||
2025-03-07T09:29:25.100478+0800 - INFO - 卫星地址: ws://127.0.0.1:8765
|
||||
2025-03-07T09:29:25.100478+0800 - INFO - 卫星地址: ws://127.0.0.1:8765
|
||||
2025-03-07T09:29:25.100548+0800 - INFO - 代理对象代号: comet
|
||||
2025-03-07T09:29:25.100548+0800 - INFO - 代理对象代号: comet
|
||||
2025-03-07T09:29:25.102459+0800 - INFO - 成功建立连接
|
||||
2025-03-07T09:29:25.102459+0800 - INFO - 成功建立连接
|
||||
2025-03-07T09:30:13.965473+0800 - INFO - 初始化代理对象
|
||||
2025-03-07T09:30:13.965473+0800 - INFO - 初始化代理对象
|
||||
2025-03-07T09:30:13.965675+0800 - INFO - 卫星地址: ws://127.0.0.1:8765
|
||||
2025-03-07T09:30:13.965675+0800 - INFO - 卫星地址: ws://127.0.0.1:8765
|
||||
2025-03-07T09:30:13.965765+0800 - INFO - 代理对象代号: comet
|
||||
2025-03-07T09:30:13.965765+0800 - INFO - 代理对象代号: comet
|
||||
2025-03-07T09:30:13.967862+0800 - INFO - 成功建立连接
|
||||
2025-03-07T09:30:13.967862+0800 - INFO - 成功建立连接
|
||||
2025-03-07T09:31:20.560819+0800 - INFO - 初始化代理对象
|
||||
2025-03-07T09:31:20.560819+0800 - INFO - 初始化代理对象
|
||||
2025-03-07T09:31:20.561346+0800 - INFO - 卫星地址: ws://127.0.0.1:8765
|
||||
2025-03-07T09:31:20.561346+0800 - INFO - 卫星地址: ws://127.0.0.1:8765
|
||||
2025-03-07T09:31:20.561512+0800 - INFO - 代理对象代号: comet
|
||||
2025-03-07T09:31:20.561512+0800 - INFO - 代理对象代号: comet
|
||||
2025-03-07T09:31:20.564821+0800 - INFO - 成功建立连接
|
||||
2025-03-07T09:31:20.564821+0800 - INFO - 成功建立连接
|
||||
2025-03-07T09:31:41.871167+0800 - INFO - 初始化代理对象
|
||||
2025-03-07T09:31:41.871167+0800 - INFO - 初始化代理对象
|
||||
2025-03-07T09:31:41.871318+0800 - INFO - 卫星地址: ws://127.0.0.1:8765
|
||||
2025-03-07T09:31:41.871318+0800 - INFO - 卫星地址: ws://127.0.0.1:8765
|
||||
2025-03-07T09:31:41.871391+0800 - INFO - 代理对象代号: comet
|
||||
2025-03-07T09:31:41.871391+0800 - INFO - 代理对象代号: comet
|
||||
2025-03-07T09:31:41.873516+0800 - INFO - 成功建立连接
|
||||
2025-03-07T09:31:41.873516+0800 - INFO - 成功建立连接
|
||||
2025-03-07T10:02:22.246919+0800 - INFO - 初始化代理对象
|
||||
2025-03-07T10:02:22.246919+0800 - INFO - 初始化代理对象
|
||||
2025-03-07T10:02:22.247153+0800 - INFO - 卫星地址: ws://127.0.0.1:8765
|
||||
2025-03-07T10:02:22.247153+0800 - INFO - 卫星地址: ws://127.0.0.1:8765
|
||||
2025-03-07T10:02:22.247261+0800 - INFO - 代理对象代号: comet
|
||||
2025-03-07T10:02:22.247261+0800 - INFO - 代理对象代号: comet
|
||||
2025-03-07T10:02:22.247736+0800 - INFO - 等待连接成功
|
||||
2025-03-07T10:02:22.247736+0800 - INFO - 等待连接成功
|
||||
2025-03-07T10:02:22.249670+0800 - INFO - 成功建立连接
|
||||
2025-03-07T10:02:22.249670+0800 - INFO - 成功建立连接
|
||||
2025-03-07T10:02:22.347928+0800 - INFO - 连接成功, 取消阻塞
|
||||
2025-03-07T10:02:22.347928+0800 - INFO - 连接成功, 取消阻塞
|
||||
2025-03-07T15:55:55.862879+0800 - INFO - 初始化代理对象
|
||||
2025-03-07T15:55:55.862879+0800 - INFO - 初始化代理对象
|
||||
2025-03-07T15:55:55.863020+0800 - INFO - 卫星地址: ws://127.0.0.1:8765
|
||||
2025-03-07T15:55:55.863020+0800 - INFO - 卫星地址: ws://127.0.0.1:8765
|
||||
2025-03-07T15:55:55.863103+0800 - INFO - 代理对象代号: comet
|
||||
2025-03-07T15:55:55.863103+0800 - INFO - 代理对象代号: comet
|
||||
2025-03-07T15:55:55.863455+0800 - INFO - 等待连接成功
|
||||
2025-03-07T15:55:55.863455+0800 - INFO - 等待连接成功
|
||||
2025-03-07T15:55:55.865329+0800 - INFO - 成功建立连接, 单向延迟 7.05718994140625e-05ms
|
||||
2025-03-07T15:55:55.865329+0800 - INFO - 成功建立连接, 单向延迟 7.05718994140625e-05ms
|
||||
2025-03-07T15:55:55.963668+0800 - INFO - 连接成功, 取消阻塞
|
||||
2025-03-07T15:55:55.963668+0800 - INFO - 连接成功, 取消阻塞
|
||||
2025-03-07T15:56:29.263974+0800 - INFO - 初始化代理对象
|
||||
2025-03-07T15:56:29.263974+0800 - INFO - 初始化代理对象
|
||||
2025-03-07T15:56:29.264145+0800 - INFO - 卫星地址: ws://127.0.0.1:8765
|
||||
2025-03-07T15:56:29.264145+0800 - INFO - 卫星地址: ws://127.0.0.1:8765
|
||||
2025-03-07T15:56:29.264238+0800 - INFO - 代理对象代号: comet
|
||||
2025-03-07T15:56:29.264238+0800 - INFO - 代理对象代号: comet
|
||||
2025-03-07T15:56:29.264733+0800 - INFO - 等待连接成功
|
||||
2025-03-07T15:56:29.264733+0800 - INFO - 等待连接成功
|
||||
2025-03-07T15:56:29.266574+0800 - INFO - 成功建立连接, 单向延迟 0ms
|
||||
2025-03-07T15:56:29.266574+0800 - INFO - 成功建立连接, 单向延迟 0ms
|
||||
2025-03-07T15:56:29.364981+0800 - INFO - 连接成功, 取消阻塞
|
||||
2025-03-07T15:56:29.364981+0800 - INFO - 连接成功, 取消阻塞
|
||||
2025-03-07T15:56:47.266556+0800 - INFO - 初始化代理对象
|
||||
2025-03-07T15:56:47.266556+0800 - INFO - 初始化代理对象
|
||||
2025-03-07T15:56:47.266726+0800 - INFO - 卫星地址: ws://127.0.0.1:8765
|
||||
2025-03-07T15:56:47.266726+0800 - INFO - 卫星地址: ws://127.0.0.1:8765
|
||||
2025-03-07T15:56:47.266820+0800 - INFO - 代理对象代号: comet
|
||||
2025-03-07T15:56:47.266820+0800 - INFO - 代理对象代号: comet
|
||||
2025-03-07T15:56:47.267230+0800 - INFO - 等待连接成功
|
||||
2025-03-07T15:56:47.267230+0800 - INFO - 等待连接成功
|
||||
2025-03-07T15:56:47.269156+0800 - INFO - 成功建立连接, 单向延迟 0.1ms
|
||||
2025-03-07T15:56:47.269156+0800 - INFO - 成功建立连接, 单向延迟 0.1ms
|
||||
2025-03-07T15:56:47.367454+0800 - INFO - 连接成功, 取消阻塞
|
||||
2025-03-07T15:56:47.367454+0800 - INFO - 连接成功, 取消阻塞
|
||||
2025-03-07T17:45:08.362971+0800 - INFO - 初始化代理对象
|
||||
2025-03-07T17:45:08.362971+0800 - INFO - 初始化代理对象
|
||||
2025-03-07T17:45:08.363174+0800 - INFO - 卫星地址: ws://127.0.0.1:8765
|
||||
2025-03-07T17:45:08.363174+0800 - INFO - 卫星地址: ws://127.0.0.1:8765
|
||||
2025-03-07T17:45:08.363287+0800 - INFO - 代理对象代号: comet
|
||||
2025-03-07T17:45:08.363287+0800 - INFO - 代理对象代号: comet
|
||||
2025-03-07T17:45:08.363894+0800 - INFO - 等待连接成功
|
||||
2025-03-07T17:45:08.363894+0800 - INFO - 等待连接成功
|
||||
2025-03-07T17:45:08.365733+0800 - INFO - 成功建立连接, 单向延迟 0.1ms
|
||||
2025-03-07T17:45:08.365733+0800 - INFO - 成功建立连接, 单向延迟 0.1ms
|
||||
2025-03-07T17:45:08.464116+0800 - INFO - 连接成功, 取消阻塞
|
||||
2025-03-07T17:45:08.464116+0800 - INFO - 连接成功, 取消阻塞
|
||||
|
6
comet/main.py
Normal file
6
comet/main.py
Normal file
@@ -0,0 +1,6 @@
|
||||
def main():
|
||||
print("Hello from comet!")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
7
comet/pyproject.toml
Normal file
7
comet/pyproject.toml
Normal file
@@ -0,0 +1,7 @@
|
||||
[project]
|
||||
name = "Comet"
|
||||
version = "0.1.0"
|
||||
description = "A onboard controller implementation of AiraPulsar Flight Control System"
|
||||
readme = "README.md"
|
||||
requires-python = ">=3.13"
|
||||
dependencies = []
|
0
lib/__init__.py
Normal file
0
lib/__init__.py
Normal file
BIN
lib/__pycache__/__init__.cpython-313.pyc
Normal file
BIN
lib/__pycache__/__init__.cpython-313.pyc
Normal file
Binary file not shown.
4
lib/agency/__init__.py
Normal file
4
lib/agency/__init__.py
Normal file
@@ -0,0 +1,4 @@
|
||||
from .main import *
|
||||
|
||||
version = '0.1.0'
|
||||
print(f"Powered by Moons Agency, version {version}")
|
BIN
lib/agency/__pycache__/__init__.cpython-312.pyc
Normal file
BIN
lib/agency/__pycache__/__init__.cpython-312.pyc
Normal file
Binary file not shown.
BIN
lib/agency/__pycache__/__init__.cpython-313.pyc
Normal file
BIN
lib/agency/__pycache__/__init__.cpython-313.pyc
Normal file
Binary file not shown.
BIN
lib/agency/__pycache__/main.cpython-312.pyc
Normal file
BIN
lib/agency/__pycache__/main.cpython-312.pyc
Normal file
Binary file not shown.
BIN
lib/agency/__pycache__/main.cpython-313.pyc
Normal file
BIN
lib/agency/__pycache__/main.cpython-313.pyc
Normal file
Binary file not shown.
1
moon/.python-version
Normal file
1
moon/.python-version
Normal file
@@ -0,0 +1 @@
|
||||
3.13
|
119
moon/logs.log
119
moon/logs.log
@@ -1,119 +0,0 @@
|
||||
2025-03-07T08:44:59.049714+0800 - INFO - 启动"卫星"中继服务器: ws://0.0.0.0:8765
|
||||
2025-03-07T08:54:33.168394+0800 - INFO - 启动"卫星"中继服务器: ws://0.0.0.0:8765
|
||||
2025-03-07T08:56:35.504311+0800 - INFO - 新客户端连接: 1
|
||||
2025-03-07T08:57:12.572151+0800 - INFO - 客户端断开连接: 1
|
||||
2025-03-07T08:57:13.906086+0800 - INFO - 新客户端连接: 2
|
||||
2025-03-07T08:57:18.478193+0800 - INFO - 客户端断开连接: 2
|
||||
2025-03-07T08:58:55.383088+0800 - INFO - 新客户端连接: 3
|
||||
2025-03-07T08:59:04.634280+0800 - INFO - 客户端断开连接: 3
|
||||
2025-03-07T08:59:05.383848+0800 - INFO - 新客户端连接: 4
|
||||
2025-03-07T08:59:51.560133+0800 - INFO - 启动"卫星"中继服务器: ws://0.0.0.0:8765
|
||||
2025-03-07T08:59:52.909275+0800 - INFO - 新客户端连接: 1
|
||||
2025-03-07T08:59:55.915998+0800 - INFO - 客户端断开连接: 1
|
||||
2025-03-07T09:00:43.283319+0800 - INFO - 启动"卫星"中继服务器: ws://0.0.0.0:8765
|
||||
2025-03-07T09:00:44.635715+0800 - INFO - 新客户端连接: 1
|
||||
2025-03-07T09:01:29.896734+0800 - INFO - 启动"卫星"中继服务器: ws://0.0.0.0:8765
|
||||
2025-03-07T09:01:31.332525+0800 - INFO - 新客户端连接: 1
|
||||
2025-03-07T09:02:17.026957+0800 - INFO - 启动"卫星"中继服务器: ws://0.0.0.0:8765
|
||||
2025-03-07T09:02:18.296634+0800 - INFO - 新客户端连接: 1
|
||||
2025-03-07T09:02:48.143588+0800 - INFO - 启动"卫星"中继服务器: ws://0.0.0.0:8765
|
||||
2025-03-07T09:02:49.427049+0800 - INFO - 新客户端连接: 1
|
||||
2025-03-07T09:03:10.834981+0800 - INFO - 启动"卫星"中继服务器: ws://0.0.0.0:8765
|
||||
2025-03-07T09:03:12.119704+0800 - INFO - 新客户端连接: 1
|
||||
2025-03-07T09:03:12.119986+0800 - INFO - 处理信息: {"id": "comet", "receiver": "auth", "content": "auth"}
|
||||
2025-03-07T09:03:12.120071+0800 - INFO - 客户端断开连接: 1
|
||||
2025-03-07T09:03:42.168476+0800 - INFO - 启动"卫星"中继服务器: ws://0.0.0.0:8765
|
||||
2025-03-07T09:03:43.472305+0800 - INFO - 新客户端连接: 1
|
||||
2025-03-07T09:03:43.472547+0800 - INFO - 处理信息: {"id": "comet", "receiver": "auth", "content": "auth"}
|
||||
2025-03-07T09:11:05.352860+0800 - INFO - 启动"卫星"中继服务器: ws://0.0.0.0:8765
|
||||
2025-03-07T09:11:06.882419+0800 - INFO - 新客户端连接: 1
|
||||
2025-03-07T09:11:06.882773+0800 - INFO - 处理信息: {"id": "comet", "receiver": "auth", "content": "auth"}
|
||||
2025-03-07T09:12:14.693477+0800 - INFO - 启动"卫星"中继服务器: ws://0.0.0.0:8765
|
||||
2025-03-07T09:12:16.851004+0800 - INFO - 新客户端连接: 1
|
||||
2025-03-07T09:12:16.851656+0800 - INFO - 处理信息: {"id": "comet", "receiver": "auth", "content": "auth"}
|
||||
2025-03-07T09:19:09.007145+0800 - INFO - 启动"卫星"中继服务器: ws://0.0.0.0:8765
|
||||
2025-03-07T09:19:10.754140+0800 - INFO - 新客户端连接: 1
|
||||
2025-03-07T09:19:10.754434+0800 - INFO - 处理信息: {"id": "comet", "receiver": "auth", "content": "auth"}
|
||||
2025-03-07T09:19:18.493238+0800 - INFO - 启动"卫星"中继服务器: ws://0.0.0.0:8765
|
||||
2025-03-07T09:19:20.016578+0800 - INFO - 新客户端连接: 1
|
||||
2025-03-07T09:19:20.016862+0800 - INFO - 处理信息: {"id": "comet", "receiver": "auth", "content": "auth"}
|
||||
2025-03-07T09:19:37.700993+0800 - INFO - 启动"卫星"中继服务器: ws://0.0.0.0:8765
|
||||
2025-03-07T09:19:39.081530+0800 - INFO - 新客户端连接: 1
|
||||
2025-03-07T09:19:39.081796+0800 - INFO - 处理信息: {"id": "comet", "receiver": "auth", "content": "auth"}
|
||||
2025-03-07T09:19:43.080448+0800 - INFO - 处理信息: {"id": "comet", "receiver": "1", "content": "hi"}
|
||||
2025-03-07T09:19:43.080720+0800 - ERROR - 无法解码 JSON 消息
|
||||
2025-03-07T09:20:12.487057+0800 - INFO - 启动"卫星"中继服务器: ws://0.0.0.0:8765
|
||||
2025-03-07T09:20:13.857585+0800 - INFO - 新客户端连接: 1
|
||||
2025-03-07T09:20:13.857880+0800 - INFO - 处理信息: {"id": "comet", "receiver": "auth", "content": "auth"}
|
||||
2025-03-07T09:20:14.799728+0800 - INFO - 客户端断开连接: 1
|
||||
2025-03-07T09:20:17.208026+0800 - INFO - 启动"卫星"中继服务器: ws://0.0.0.0:8765
|
||||
2025-03-07T09:20:22.577076+0800 - INFO - 新客户端连接: 1
|
||||
2025-03-07T09:20:22.577489+0800 - INFO - 处理信息: {"id": "comet", "receiver": "auth", "content": "auth"}
|
||||
2025-03-07T09:20:23.575751+0800 - INFO - 处理信息: {"id": "comet", "receiver": "1", "content": "hi"}
|
||||
2025-03-07T09:20:23.576044+0800 - ERROR - 无法解码 JSON 消息
|
||||
2025-03-07T09:26:56.246176+0800 - INFO - 启动"卫星"中继服务器: ws://0.0.0.0:8765
|
||||
2025-03-07T09:26:57.807128+0800 - INFO - 新客户端连接: 1
|
||||
2025-03-07T09:26:57.807419+0800 - INFO - 处理信息: {"id": "comet", "receiver": "auth", "content": "auth"}
|
||||
2025-03-07T09:26:58.805874+0800 - INFO - 处理信息: {"id": "comet", "receiver": "1", "content": "hi"}
|
||||
2025-03-07T09:26:58.806066+0800 - ERROR - 无法解码 JSON 消息
|
||||
2025-03-07T09:28:25.117434+0800 - INFO - 启动"卫星"中继服务器: ws://0.0.0.0:8765
|
||||
2025-03-07T09:28:26.673876+0800 - INFO - 新客户端连接: 1
|
||||
2025-03-07T09:28:26.674262+0800 - INFO - 处理信息: {"id": "comet", "receiver": "auth", "content": "auth"}
|
||||
2025-03-07T09:28:27.671936+0800 - INFO - 处理信息: {"id": "comet", "receiver": "1", "content": "hi"}
|
||||
2025-03-07T09:28:27.672177+0800 - ERROR - 无法解码 JSON 消息
|
||||
2025-03-07T09:28:29.778081+0800 - INFO - 客户端断开连接: 1
|
||||
2025-03-07T09:28:33.464911+0800 - INFO - 启动"卫星"中继服务器: ws://0.0.0.0:8765
|
||||
2025-03-07T09:28:35.158721+0800 - INFO - 新客户端连接: 1
|
||||
2025-03-07T09:28:35.159064+0800 - INFO - 处理信息: {"id": "comet", "receiver": "auth", "content": "auth"}
|
||||
2025-03-07T09:28:36.157310+0800 - INFO - 处理信息: {"id": "comet", "receiver": "1", "content": "hi"}
|
||||
2025-03-07T09:28:36.157514+0800 - ERROR - 无法解码 JSON 消息
|
||||
2025-03-07T09:29:18.205614+0800 - INFO - 客户端断开连接: 1
|
||||
2025-03-07T09:29:22.053522+0800 - INFO - 启动"卫星"中继服务器: ws://0.0.0.0:8765
|
||||
2025-03-07T09:29:25.102228+0800 - INFO - 新客户端连接: 1
|
||||
2025-03-07T09:29:25.102476+0800 - INFO - 处理信息: {"id": "comet", "receiver": "auth", "content": "auth"}
|
||||
2025-03-07T09:29:26.101162+0800 - INFO - 处理信息: {"id": "comet", "receiver": "1", "content": "hi"}
|
||||
2025-03-07T09:29:26.101351+0800 - ERROR - 无法解码 JSON 消息
|
||||
2025-03-07T09:30:12.603632+0800 - INFO - 启动"卫星"中继服务器: ws://0.0.0.0:8765
|
||||
2025-03-07T09:30:13.967524+0800 - INFO - 新客户端连接: 1
|
||||
2025-03-07T09:30:13.967874+0800 - INFO - 处理信息: {"id": "comet", "receiver": "auth", "content": "auth"}
|
||||
2025-03-07T09:30:14.966548+0800 - INFO - 处理信息: {"id": "comet", "receiver": "1", "content": {"hi": "hi"}}
|
||||
2025-03-07T09:30:14.966787+0800 - INFO - 客户端断开连接: 1
|
||||
2025-03-07T09:31:19.129916+0800 - INFO - 启动"卫星"中继服务器: ws://0.0.0.0:8765
|
||||
2025-03-07T09:31:20.564382+0800 - INFO - 新客户端连接: 1
|
||||
2025-03-07T09:31:20.564841+0800 - INFO - 处理信息: {"id": "comet", "receiver": "auth", "content": "auth"}
|
||||
2025-03-07T09:31:21.562523+0800 - INFO - 处理信息: {"id": "comet", "receiver": "1", "content": {"hi": "hi"}}
|
||||
2025-03-07T09:31:21.562718+0800 - WARNING - 无法发送至端点
|
||||
2025-03-07T09:31:31.503846+0800 - INFO - 启动"卫星"中继服务器: ws://0.0.0.0:8765
|
||||
2025-03-07T09:31:41.873175+0800 - INFO - 新客户端连接: 1
|
||||
2025-03-07T09:31:41.873532+0800 - INFO - 处理信息: {"id": "comet", "receiver": "auth", "content": "auth"}
|
||||
2025-03-07T09:31:42.872072+0800 - INFO - 处理信息: {"id": "comet", "receiver": "*", "content": {"hi": "hi"}}
|
||||
2025-03-07T09:31:42.872284+0800 - WARNING - 无法发送至端点
|
||||
2025-03-07T09:31:42.872356+0800 - WARNING - 无法发送至端点
|
||||
2025-03-07T10:02:07.173456+0800 - INFO - 启动"卫星"中继服务器: ws://0.0.0.0:8765
|
||||
2025-03-07T10:02:22.249420+0800 - INFO - 新客户端连接: 1
|
||||
2025-03-07T10:02:22.249683+0800 - INFO - 处理信息: {"id": "comet", "receiver": "auth", "content": "auth"}
|
||||
2025-03-07T10:02:22.348277+0800 - INFO - 处理信息: {"id": "comet", "receiver": "*", "content": {"hi": "hi"}}
|
||||
2025-03-07T10:02:22.348428+0800 - WARNING - 无法发送至端点
|
||||
2025-03-07T10:02:22.348504+0800 - WARNING - 无法发送至端点
|
||||
2025-03-07T15:55:54.389580+0800 - INFO - 启动"卫星"中继服务器: ws://0.0.0.0:8765
|
||||
2025-03-07T15:55:55.865014+0800 - INFO - 新客户端连接: 1
|
||||
2025-03-07T15:55:55.865334+0800 - INFO - 处理信息: {"id": "comet", "receiver": "auth", "content": "auth"}
|
||||
2025-03-07T15:55:55.964049+0800 - INFO - 处理信息: {"id": "comet", "receiver": "*", "content": {"hi": "hi"}}
|
||||
2025-03-07T15:55:55.964208+0800 - WARNING - 无法发送至端点
|
||||
2025-03-07T15:55:55.964276+0800 - WARNING - 无法发送至端点
|
||||
2025-03-07T15:55:58.304575+0800 - INFO - 客户端断开连接: 1
|
||||
2025-03-07T15:56:27.769208+0800 - INFO - 启动"卫星"中继服务器: ws://0.0.0.0:8765
|
||||
2025-03-07T15:56:29.266347+0800 - INFO - 新客户端连接: 1
|
||||
2025-03-07T15:56:29.266586+0800 - INFO - 处理信息: {"id": "comet", "receiver": "auth", "content": "auth"}
|
||||
2025-03-07T15:56:29.365433+0800 - INFO - 处理信息: {"id": "comet", "receiver": "*", "content": {"hi": "hi"}}
|
||||
2025-03-07T15:56:29.365581+0800 - WARNING - 无法发送至端点
|
||||
2025-03-07T15:56:29.365643+0800 - WARNING - 无法发送至端点
|
||||
2025-03-07T15:56:45.972404+0800 - INFO - 启动"卫星"中继服务器: ws://0.0.0.0:8765
|
||||
2025-03-07T15:56:47.268864+0800 - INFO - 新客户端连接: 1
|
||||
2025-03-07T15:56:47.269164+0800 - INFO - 处理信息: {"id": "comet", "receiver": "auth", "content": "auth"}
|
||||
2025-03-07T15:56:47.367838+0800 - INFO - 处理信息: {"id": "comet", "receiver": "*", "content": {"hi": "hi"}}
|
||||
2025-03-07T15:56:47.367979+0800 - WARNING - 无法发送至端点
|
||||
2025-03-07T15:56:47.368041+0800 - WARNING - 无法发送至端点
|
||||
2025-03-07T17:45:07.183410+0800 - INFO - 客户端断开连接: 1
|
||||
2025-03-07T17:45:08.365484+0800 - INFO - 新客户端连接: 2
|
||||
2025-03-07T17:45:08.365737+0800 - INFO - 处理信息: {"id": "comet", "receiver": "auth", "content": "auth"}
|
6
moon/main.py
Normal file
6
moon/main.py
Normal file
@@ -0,0 +1,6 @@
|
||||
def main():
|
||||
print("Hello from moon!")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
7
moon/pyproject.toml
Normal file
7
moon/pyproject.toml
Normal file
@@ -0,0 +1,7 @@
|
||||
[project]
|
||||
name = "Moon"
|
||||
version = "0.1.0"
|
||||
description = "A relay server implementation of AiraPulsar Flight Control System"
|
||||
readme = "README.md"
|
||||
requires-python = ">=3.13"
|
||||
dependencies = []
|
1
pulsar/.python-version
Normal file
1
pulsar/.python-version
Normal file
@@ -0,0 +1 @@
|
||||
3.13
|
Binary file not shown.
0
pulsar/agent_logs.log
Normal file
0
pulsar/agent_logs.log
Normal file
24
pulsar/components/__horizontal_indicator.py
Normal file
24
pulsar/components/__horizontal_indicator.py
Normal file
@@ -0,0 +1,24 @@
|
||||
import vgl
|
||||
|
||||
|
||||
name = "Marking Lines"
|
||||
|
||||
def main(window):
|
||||
frame = vgl.Frame().attach(window_object=window, poscale=(0,0), clone_name="Marking Line")
|
||||
lines = list()
|
||||
for i in range(0, 24):
|
||||
lines.append(vgl.elements.Line(ends=[(0, i/24), (1, i/24)], color="green").attach(frame_object=frame))
|
||||
for i in range(0, 32):
|
||||
lines.append(vgl.elements.Line(ends=[(i/32, 0), (i/32, 1)], color="green").attach(frame_object=frame))
|
||||
# We monitor events like this.
|
||||
@window.observerize
|
||||
def observer(info):
|
||||
if info["delta"] == "key":
|
||||
print(info)
|
||||
if info["delta"] == "click":
|
||||
if info["click"]:
|
||||
print(info["cursor"]["poscale"])
|
||||
# We make changes like this.
|
||||
for i in lines:
|
||||
i.set_color('#' + str((info['cursor']['position'][0] + info['cursor']['position'][1]*100 + info['cursor']['position'][0]*10000) % 999999).zfill(6))
|
||||
observer()
|
BIN
pulsar/components/__pycache__/marker.cpython-312.pyc
Normal file
BIN
pulsar/components/__pycache__/marker.cpython-312.pyc
Normal file
Binary file not shown.
BIN
pulsar/components/__pycache__/marker.cpython-313.pyc
Normal file
BIN
pulsar/components/__pycache__/marker.cpython-313.pyc
Normal file
Binary file not shown.
BIN
pulsar/components/__pycache__/marking_lines.cpython-312.pyc
Normal file
BIN
pulsar/components/__pycache__/marking_lines.cpython-312.pyc
Normal file
Binary file not shown.
25
pulsar/components/marker.py
Normal file
25
pulsar/components/marker.py
Normal file
@@ -0,0 +1,25 @@
|
||||
from lib import vgl
|
||||
name = "Marking Lines"
|
||||
|
||||
def main(window):
|
||||
frame = vgl.Frame().attach(window_object=window, poscale=(0,0), clone_name="Marking Line")
|
||||
lines = list()
|
||||
for i in range(0, 24):
|
||||
lines.append(vgl.elements.Line(ends=[(0, i/24), (1, i/24)], color="green").attach(frame_object=frame))
|
||||
for i in range(0, 32):
|
||||
lines.append(vgl.elements.Line(ends=[(i/32, 0), (i/32, 1)], color="green").attach(frame_object=frame))
|
||||
# We monitor events like this.
|
||||
@window.observerize
|
||||
def observer(info):
|
||||
if info["delta"] == "key":
|
||||
print(info)
|
||||
if info["delta"] == "click":
|
||||
if info["click"]:
|
||||
print(info["cursor"]["poscale"])
|
||||
# We make changes like this.
|
||||
for i in lines:
|
||||
i.set_color('#' + str((info['cursor']['position'][0] + info['cursor']['position'][1]*100 + info['cursor']['position'][0]*10000) % 999999).zfill(6))
|
||||
observer()
|
||||
#@vgl.loop # TODO
|
||||
#def toloop():
|
||||
# pass
|
15
pulsar/layouts.yaml
Normal file
15
pulsar/layouts.yaml
Normal file
@@ -0,0 +1,15 @@
|
||||
horizontal_indicator:
|
||||
- type: line
|
||||
args:
|
||||
ends: [(0.4, 0.5), (0.6, 0.5)]
|
||||
color: green
|
||||
- type: line
|
||||
name: remote
|
||||
args:
|
||||
ends: [(0.4, 0.5), (0.6, 0.5)]
|
||||
color: green
|
||||
- type: line
|
||||
args:
|
||||
ends: [(0.4, 0.5), (0.6, 0.5)]
|
||||
color: green
|
||||
|
49
pulsar/main.py
Normal file
49
pulsar/main.py
Normal file
@@ -0,0 +1,49 @@
|
||||
from lib import vgl
|
||||
from lib import agency
|
||||
import colorama
|
||||
import os
|
||||
import importlib.util
|
||||
|
||||
window = vgl.Window(title="Pulsar", size=(1600, 1000))
|
||||
|
||||
def loader():
|
||||
components_dir = "components"
|
||||
for i in os.listdir(components_dir):
|
||||
if i.endswith(".py") and (not i.startswith("__")):
|
||||
module_name = i[:-3]
|
||||
module_path = os.path.join(components_dir, i)
|
||||
|
||||
spec = importlib.util.spec_from_file_location(module_name, module_path)
|
||||
module = importlib.util.module_from_spec(spec)
|
||||
spec.loader.exec_module(module)
|
||||
try:
|
||||
if hasattr(module, "main") and callable(module.main):
|
||||
print(f"[ .... ] Starting {module.name} module")
|
||||
try:
|
||||
module.main(window=window)
|
||||
print(f"[{colorama.Fore.GREEN} OK {colorama.Style.RESET_ALL}] Started {module.name} module")
|
||||
except Exception as e:
|
||||
print(f"[{colorama.Fore.RED}FAILED{colorama.Style.RESET_ALL}] Failed to start {module_name} module: {e}")
|
||||
except:
|
||||
print(f"Unsupported module: {module_name}.py")
|
||||
|
||||
def console():
|
||||
print("You've entered Pulsar's command console, an embbedded Python interpreter for debugging & testing")
|
||||
while True:
|
||||
try:
|
||||
i = input(">>> ")
|
||||
if i == "q":
|
||||
return
|
||||
exec(i)
|
||||
except:
|
||||
print("An error occured & captured")
|
||||
|
||||
if __name__ == '__main__':
|
||||
os.chdir(os.path.dirname(os.path.abspath(__file__)))
|
||||
print("Welcome to AiraPulsar Client")
|
||||
window.start()
|
||||
loader()
|
||||
console()
|
||||
print("Quitting")
|
||||
window.kill()
|
||||
exit()
|
0
pulsar/numerator.py
Normal file
0
pulsar/numerator.py
Normal file
7
pulsar/pyproject.toml
Normal file
7
pulsar/pyproject.toml
Normal file
@@ -0,0 +1,7 @@
|
||||
[project]
|
||||
name = "Pulsar"
|
||||
version = "0.1.0"
|
||||
description = "A client implementation of AiraPulsar Flight Control System"
|
||||
readme = "README.md"
|
||||
requires-python = ">=3.13"
|
||||
dependencies = []
|
BIN
pulsar/src/dock/angle_limit.png
Normal file
BIN
pulsar/src/dock/angle_limit.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 435 B |
BIN
pulsar/src/dock/drop_indicator.png
Normal file
BIN
pulsar/src/dock/drop_indicator.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 400 B |
BIN
pulsar/src/dock/extremis.png
Normal file
BIN
pulsar/src/dock/extremis.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 426 B |
BIN
pulsar/src/dock/landing_mode.png
Normal file
BIN
pulsar/src/dock/landing_mode.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 422 B |
BIN
pulsar/src/dock/recording_indicator.png
Normal file
BIN
pulsar/src/dock/recording_indicator.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 332 B |
BIN
pulsar/src/dock/sync_indicator.png
Normal file
BIN
pulsar/src/dock/sync_indicator.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 399 B |
48
pulsar/tester.py
Normal file
48
pulsar/tester.py
Normal file
@@ -0,0 +1,48 @@
|
||||
import vgl
|
||||
import colorama
|
||||
import os
|
||||
import importlib.util
|
||||
|
||||
window = vgl.Window(title="Pulsar", size=(1024, 768))
|
||||
|
||||
def loader():
|
||||
components_dir = "components"
|
||||
for i in os.listdir(components_dir):
|
||||
if i.endswith(".py") and (not i.startswith("__")):
|
||||
module_name = i[:-3]
|
||||
module_path = os.path.join(components_dir, i)
|
||||
|
||||
spec = importlib.util.spec_from_file_location(module_name, module_path)
|
||||
module = importlib.util.module_from_spec(spec)
|
||||
spec.loader.exec_module(module)
|
||||
try:
|
||||
if hasattr(module, "main") and callable(module.main):
|
||||
print(f"[ .... ] Starting {module.name} module")
|
||||
try:
|
||||
module.main(window=window)
|
||||
print(f"[{colorama.Fore.GREEN} OK {colorama.Style.RESET_ALL}] Started {module.name} module")
|
||||
except Exception as e:
|
||||
print(f"[{colorama.Fore.RED}FAILED{colorama.Style.RESET_ALL}] Failed to start {module_name} module: {e}")
|
||||
except:
|
||||
print(f"Unsupported module: {module_name}.py")
|
||||
|
||||
def console():
|
||||
print("You've entered Pulsar's command console, an embbedded Python interpreter for debugging & testing")
|
||||
while True:
|
||||
try:
|
||||
i = input(">>> ")
|
||||
if i == "q":
|
||||
return
|
||||
exec(i)
|
||||
except:
|
||||
print("An error occured & captured")
|
||||
|
||||
if __name__ == '__main__':
|
||||
os.chdir(os.path.dirname(os.path.abspath(__file__)))
|
||||
print("Tester")
|
||||
window.start()
|
||||
loader()
|
||||
console()
|
||||
print("Quitting")
|
||||
window.kill()
|
||||
exit()
|
@@ -1,3 +1,8 @@
|
||||
# 实验与参考用代码
|
||||
仅作技术分析验证与历史留存, 若要修改此项目代码, 不必处理此文件夹
|
||||
若你要使用此软件, 可以克隆后直接将 testfield 文件夹删除
|
||||
若你要使用此软件, 可以克隆后直接将 testfield 文件夹删除
|
||||
子目录说明:
|
||||
- legacy: 旧版飞控系统存档
|
||||
- vgl: 矢量图形绘制库
|
||||
- network: sin 波形传输
|
||||
- visual: "总览"组件开发
|
||||
|
27
testfield/kbemu/1.py
Normal file
27
testfield/kbemu/1.py
Normal file
@@ -0,0 +1,27 @@
|
||||
import time
|
||||
from pynput.keyboard import Controller
|
||||
import threading
|
||||
|
||||
# 创建键盘控制器
|
||||
keyboard = Controller()
|
||||
|
||||
def press_keys():
|
||||
while True: # 持续循环
|
||||
keyboard.press('1') # 按下 'w' 键
|
||||
time.sleep(0.5) # 等待0.5秒
|
||||
keyboard.release('w') # 释放 'w' 键
|
||||
keyboard.press('d') # 按下 'd' 键
|
||||
time.sleep(0.5) # 等待0.5秒
|
||||
keyboard.release('d') # 释放 'd' 键
|
||||
|
||||
# 创建并启动线程
|
||||
thread = threading.Thread(target=press_keys)
|
||||
thread.daemon = True # 设置为守护线程
|
||||
thread.start()
|
||||
|
||||
# 主线程可以在这里执行其他操作
|
||||
try:
|
||||
while True:
|
||||
time.sleep(1) # 主线程保持运行
|
||||
except KeyboardInterrupt:
|
||||
print("程序已停止。")
|
@@ -1,113 +0,0 @@
|
||||
def generate_shape_dict(shape, **kwargs):
|
||||
if shape == 'rect':
|
||||
return {
|
||||
'method': 'rect',
|
||||
'pos': kwargs.get('pos', (0, 0)),
|
||||
'size': kwargs.get('size', (1, 1)),
|
||||
'color': kwargs.get('color', (255, 255, 255)),
|
||||
'width': kwargs.get('width', 0) # 添加边框宽度
|
||||
}
|
||||
elif shape == 'line':
|
||||
return {
|
||||
'method': 'line',
|
||||
'start_pos': kwargs.get('start_pos', (0, 0)),
|
||||
'end_pos': kwargs.get('end_pos', (1, 1)),
|
||||
'color': kwargs.get('color', (255, 255, 255))
|
||||
}
|
||||
elif shape == 'circle':
|
||||
return {
|
||||
'method': 'circle',
|
||||
'center': kwargs.get('center', (0, 0)),
|
||||
'radius': kwargs.get('radius', 1),
|
||||
'color': kwargs.get('color', (255, 255, 255))
|
||||
}
|
||||
elif shape == 'ellipse':
|
||||
return {
|
||||
'method': 'ellipse',
|
||||
'pos': kwargs.get('pos', (0, 0)),
|
||||
'size': kwargs.get('size', (1, 1)),
|
||||
'color': kwargs.get('color', (255, 255, 255))
|
||||
}
|
||||
elif shape == 'polygon':
|
||||
return {
|
||||
'method': 'polygon',
|
||||
'pointlist': kwargs.get('pointlist', []),
|
||||
'color': kwargs.get('color', (255, 255, 255))
|
||||
}
|
||||
elif shape == 'arc':
|
||||
return {
|
||||
'method': 'arc',
|
||||
'pos': kwargs.get('pos', (0, 0)),
|
||||
'size': kwargs.get('size', (1, 1)),
|
||||
'color': kwargs.get('color', (255, 255, 255)),
|
||||
'start_angle': kwargs.get('start_angle', 0),
|
||||
'stop_angle': kwargs.get('stop_angle', 3.14)
|
||||
}
|
||||
elif shape == 'point':
|
||||
return {
|
||||
'method': 'point',
|
||||
'pos': kwargs.get('pos', (0, 0)),
|
||||
'color': kwargs.get('color', (255, 255, 255))
|
||||
}
|
||||
elif shape == 'lines':
|
||||
return {
|
||||
'method': 'lines',
|
||||
'pointlist': kwargs.get('pointlist', []),
|
||||
'color': kwargs.get('color', (255, 255, 255))
|
||||
}
|
||||
else:
|
||||
raise ValueError("Unsupported shape type")
|
||||
|
||||
def main():
|
||||
print("欢迎使用图形参数生成器!")
|
||||
shape = input("请输入图形类型 (rect, line, circle, ellipse, polygon, arc, point, lines): ").strip().lower()
|
||||
|
||||
params = {}
|
||||
|
||||
if shape == 'rect':
|
||||
params['pos'] = tuple(map(int, input("请输入矩形位置 (x y): ").split()))
|
||||
params['size'] = tuple(map(int, input("请输入矩形大小 (width height): ").split()))
|
||||
params['color'] = tuple(map(int, input("请输入矩形颜色 (R G B): ").split()))
|
||||
params['width'] = int(input("请输入矩形边框宽度: ")) # 添加边框宽度输入
|
||||
elif shape == 'line':
|
||||
params['start_pos'] = tuple(map(int, input("请输入起始位置 (x y): ").split()))
|
||||
params['end_pos'] = tuple(map(int, input("请输入结束位置 (x y): ").split()))
|
||||
params['color'] = tuple(map(int, input("请输入线条颜色 (R G B): ").split()))
|
||||
elif shape == 'circle':
|
||||
params['center'] = tuple(map(int, input("请输入圆心位置 (x y): ").split()))
|
||||
params['radius'] = int(input("请输入圆的半径: "))
|
||||
params['color'] = tuple(map(int, input("请输入圆的颜色 (R G B): ").split()))
|
||||
elif shape == 'ellipse':
|
||||
params['pos'] = tuple(map(int, input("请输入椭圆位置 (x y): ").split()))
|
||||
params['size'] = tuple(map(int, input("请输入椭圆大小 (width height): ").split()))
|
||||
params['color'] = tuple(map(int, input("请输入椭圆颜色 (R G B): ").split()))
|
||||
elif shape == 'polygon':
|
||||
points = input("请输入多边形的点 (x1 y1 x2 y2 ...): ").split()
|
||||
params['pointlist'] = [(int(points[i]), int(points[i + 1])) for i in range(0, len(points), 2)]
|
||||
params['color'] = tuple(map(int, input("请输入多边形颜色 (R G B): ").split()))
|
||||
elif shape == 'arc':
|
||||
params['pos'] = tuple(map(int, input("请输入弧的位置 (x y): ").split()))
|
||||
params['size'] = tuple(map(int, input("请输入弧的大小 (width height): ").split()))
|
||||
params['color'] = tuple(map(int, input("请输入弧的颜色 (R G B): ").split()))
|
||||
params['start_angle'] = float(input("请输入弧的起始角度 (弧度制): "))
|
||||
params['stop_angle'] = float(input("请输入弧的结束角度 (弧度制): "))
|
||||
elif shape == 'point':
|
||||
params['pos'] = tuple(map(int, input("请输入点的位置 (x y): ").split()))
|
||||
params['color'] = tuple(map(int, input("请输入点的颜色 (R G B): ").split()))
|
||||
elif shape == 'lines':
|
||||
points = input("请输入线段的点 (x1 y1 x2 y2 ...): ").split()
|
||||
params['pointlist'] = [(int(points[i]), int(points[i + 1])) for i in range(0, len(points), 2)]
|
||||
params['color'] = tuple(map(int, input("请输入线段颜色 (R G B): ").split()))
|
||||
else:
|
||||
print("不支持的图形类型")
|
||||
return
|
||||
|
||||
# 生成图形字典
|
||||
shape_dict = generate_shape_dict(shape, **params)
|
||||
|
||||
# 输出结果
|
||||
print("生成的图形参数字典:")
|
||||
print(shape_dict)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
@@ -1,26 +0,0 @@
|
||||
import pygame
|
||||
import sys
|
||||
from testfield.vgl.vgllib import *
|
||||
pygame.init()
|
||||
window_size = (800, 600)
|
||||
window = pygame.display.set_mode(window_size)
|
||||
|
||||
frame = Frame("Main Frame", window_size)
|
||||
|
||||
# 注册一个矩形组件
|
||||
frame.register("rectangle", {"method": "rect", "pos": (100, 100), "size": (200, 150), "color": (255, 0, 0)})
|
||||
|
||||
# 注册一个圆形组件
|
||||
frame.register("circle", {"method": "circle", "center": (400, 300), "radius": 50, "color": (0, 255, 0)})
|
||||
|
||||
# 主循环
|
||||
while True:
|
||||
for event in pygame.event.get():
|
||||
if event.type == pygame.QUIT:
|
||||
pygame.quit()
|
||||
sys.exit()
|
||||
|
||||
window.fill((0, 0, 0)) # 清空窗口
|
||||
frame.drawall(frame.components) # 绘制所有组件
|
||||
frame.show(window, (0, 0)) # 显示框架
|
||||
pygame.display.flip() # 更新显示
|
@@ -1,114 +0,0 @@
|
||||
# Vector Graphics Library
|
||||
# vgllib.py
|
||||
import pygame
|
||||
import uuid
|
||||
|
||||
class Graph:
|
||||
@staticmethod
|
||||
def rect(frame, pos: tuple = (0, 0), size: tuple = (1, 1), color: tuple = (255, 255, 255), width: int = 0):
|
||||
pygame.draw.rect(frame.surface, color=color, rect=(pos[0], pos[1], size[0], size[1]), width=width)
|
||||
|
||||
@staticmethod
|
||||
def line(frame, start_pos: tuple, end_pos: tuple, color: tuple = (255, 255, 255)):
|
||||
pygame.draw.aaline(frame.surface, color, start_pos, end_pos)
|
||||
|
||||
@staticmethod
|
||||
def circle(frame, center: tuple, radius: int, color: tuple = (255, 255, 255), width: int = 0):
|
||||
pygame.draw.circle(frame.surface, color, center, radius, width)
|
||||
|
||||
@staticmethod
|
||||
def ellipse(frame, pos: tuple = (0, 0), size: tuple = (1, 1), color: tuple = (255, 255, 255), width: int = 0):
|
||||
rect=(pos[0], pos[1], size[0], size[1])
|
||||
pygame.draw.ellipse(frame.surface, color, rect, width)
|
||||
|
||||
@staticmethod
|
||||
def polygon(frame, pointlist: list, color: tuple = (255, 255, 255), width: int = 0):
|
||||
pygame.draw.polygon(frame.surface, color, pointlist, width)
|
||||
|
||||
@staticmethod
|
||||
def arc(frame, pos: tuple = (0, 0), size: tuple = (1, 1), color: tuple = (255, 255, 255), start_angle: float = 0, stop_angle: float = 3.14, width: int = 1):
|
||||
rect=(pos[0], pos[1], size[0], size[1])
|
||||
pygame.draw.arc(frame.surface, color, rect, start_angle, stop_angle, width)
|
||||
|
||||
@staticmethod
|
||||
def point(frame, pos: tuple, color: tuple = (255, 255, 255)):
|
||||
pygame.draw.point(frame.surface, color, pos)
|
||||
|
||||
@staticmethod
|
||||
def lines(frame, pointlist: list, color: tuple = (255, 255, 255)):
|
||||
pygame.draw.aalines(frame.surface, color, closed=False, points=pointlist)
|
||||
|
||||
@staticmethod
|
||||
def call(frame, method, **kwargs):
|
||||
if hasattr(Graph, method):
|
||||
getattr(Graph, method)(frame, **kwargs)
|
||||
else:
|
||||
print(f"方法 {method} 不存在")
|
||||
|
||||
class Frame(object):
|
||||
components = dict()
|
||||
components_stat = dict()
|
||||
def __init__(self, name: str, size: tuple):
|
||||
self.name = name
|
||||
self.size = size
|
||||
self.surface = pygame.Surface(size, flags=pygame.HWSURFACE)
|
||||
self.is_hide = False
|
||||
print("初始化子模块")
|
||||
|
||||
def show(self, window, position: tuple):
|
||||
if not self.is_hide:
|
||||
window.blit(self.surface, position)
|
||||
|
||||
def set_visible(self, newstat=True):
|
||||
self.is_hide = newstat
|
||||
|
||||
def set_position(self, newposition):
|
||||
self.position = newposition
|
||||
|
||||
def register(self, subname="", attr=None):
|
||||
if subname == "":
|
||||
subname = uuid.uuid4()
|
||||
self.components[subname] = attr
|
||||
self.components_stat[subname] = 1 # by default, not hiding
|
||||
|
||||
def draw(self, attr):
|
||||
attr['pos'][0] = round(attr['pos'][0] / 100 * self.size[1])
|
||||
attr['pos'][0] = round(attr['pos'][0] / 100 * self.size[1])
|
||||
attr['pos'][0] = round(attr['pos'][0] / 100 * self.size[1])
|
||||
attr['pos'][0] = round(attr['pos'][0] / 100 * self.size[1])
|
||||
Graph.call(self, **attr)
|
||||
|
||||
def set_component_visible(self, subname, newstat):
|
||||
self.components_stat[subname] = newstat
|
||||
|
||||
def drawall(self, attr):
|
||||
for i in self.components.keys():
|
||||
if self.components_stat[i]:
|
||||
self.draw(self.components[i])
|
||||
|
||||
def clear(self, color=(0,0,0)):
|
||||
self.surface.fill(color)
|
||||
|
||||
def loads(self, ):
|
||||
|
||||
|
||||
# 示例
|
||||
if __name__ == "__main__":
|
||||
pygame.init()
|
||||
window = pygame.display.set_mode((800, 600))
|
||||
frame = Frame("Test", (800, 600))
|
||||
|
||||
frame.draw({'method':'rect', 'pos':(50, 50), 'size':(200, 100), 'color':(255, 0, 0)}) # 绘制红色矩形
|
||||
|
||||
# 主循环
|
||||
running = True
|
||||
while running:
|
||||
for event in pygame.event.get():
|
||||
if event.type == pygame.QUIT:
|
||||
running = False
|
||||
|
||||
window.fill((0, 0, 0)) # 清空窗口
|
||||
frame.show(window, (0, 0)) # 显示帧
|
||||
pygame.display.flip() # 更新显示
|
||||
|
||||
pygame.quit()
|
7
vgl/__init__.py
Normal file
7
vgl/__init__.py
Normal file
@@ -0,0 +1,7 @@
|
||||
import os
|
||||
os.environ["PYGAME_HIDE_SUPPORT_PROMPT"] = "True"
|
||||
from .main import *
|
||||
from . import basic_elements as elements
|
||||
|
||||
version = '0.3.0'
|
||||
print(f"Powered by Vector Graphic Layer, version {version}")
|
BIN
vgl/__pycache__/__init__.cpython-312.pyc
Normal file
BIN
vgl/__pycache__/__init__.cpython-312.pyc
Normal file
Binary file not shown.
BIN
vgl/__pycache__/__init__.cpython-313.pyc
Normal file
BIN
vgl/__pycache__/__init__.cpython-313.pyc
Normal file
Binary file not shown.
BIN
vgl/__pycache__/basic_elements.cpython-312.pyc
Normal file
BIN
vgl/__pycache__/basic_elements.cpython-312.pyc
Normal file
Binary file not shown.
BIN
vgl/__pycache__/basic_elements.cpython-313.pyc
Normal file
BIN
vgl/__pycache__/basic_elements.cpython-313.pyc
Normal file
Binary file not shown.
BIN
vgl/__pycache__/main.cpython-312.pyc
Normal file
BIN
vgl/__pycache__/main.cpython-312.pyc
Normal file
Binary file not shown.
BIN
vgl/__pycache__/main.cpython-313.pyc
Normal file
BIN
vgl/__pycache__/main.cpython-313.pyc
Normal file
Binary file not shown.
96
vgl/basic_elements.py
Normal file
96
vgl/basic_elements.py
Normal file
@@ -0,0 +1,96 @@
|
||||
from .main import *
|
||||
import pygame
|
||||
import time
|
||||
|
||||
class Line(Element):
|
||||
def __init__(self, ends = [(0.1, 0.1), (0.2, 0.2)], color = "#ffffff"):
|
||||
self.color = color
|
||||
self.ends = ends
|
||||
def set_color(self, new_color):
|
||||
self.color = new_color
|
||||
def move(self, delta, duration):
|
||||
self.add_task(group = "move", start_time = Aux.gettime(), duration = duration, delta = delta)
|
||||
def update(self):
|
||||
for i in self.tasks.get("move", []):
|
||||
self.teleport(Aux.tuple_scale(tup = i['delta'], mul = Aux.getprogress(i)))
|
||||
def render(self):
|
||||
pygame.draw.aaline(self.attached_frame.surface, self.color, Aux.pixelizer(self.ends[0], self.attached_window), Aux.pixelizer(self.ends[1], self.attached_window))
|
||||
class Rect(Element):
|
||||
def __init__(self, nw_posc=(0.1, 0.1), se_posc=(0.2,0.2), color = "#114514", width = 0): # non-0 for "frame"
|
||||
self.color = color
|
||||
self.width = width
|
||||
self.rect = (nw_posc[0], nw_posc[1], se_posc[0], se_posc[1])
|
||||
def move(self, delta, duration):
|
||||
self.add_task(group = "move", start_time = Aux.gettime(), duration = duration, delta = delta)
|
||||
def update(self):
|
||||
for i in self.tasks.get("move", []):
|
||||
self.teleport(Aux.tuple_scale(tup = i['delta'], mul = Aux.getprogress(i)))
|
||||
def render(self):
|
||||
pygame.draw.rect(surface=self.attached_frame.surface, color=self.color, rect=Aux.pixelizer(self.rect, self.attached_window), width=self.width)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class Graph:
|
||||
@staticmethod
|
||||
def rect(frame, pos: tuple = (0, 0), size: tuple = (1, 1), color: tuple = (255, 255, 255), width: int = 0):
|
||||
pygame.draw.rect(frame.surface, color=color, rect=(pos[0], pos[1], size[0], size[1]), width=width)
|
||||
|
||||
@staticmethod
|
||||
def line(frame, start_pos: tuple, end_pos: tuple, color: tuple = (255, 255, 255)):
|
||||
pygame.draw.aaline(frame.surface, color, start_pos, end_pos)
|
||||
|
||||
@staticmethod
|
||||
def circle(frame, center: tuple, radius: int, color: tuple = (255, 255, 255), width: int = 0):
|
||||
pygame.draw.circle(frame.surface, color, center, radius, width)
|
||||
|
||||
@staticmethod
|
||||
def ellipse(frame, pos: tuple = (0, 0), size: tuple = (1, 1), color: tuple = (255, 255, 255), width: int = 0):
|
||||
rect=(pos[0], pos[1], size[0], size[1])
|
||||
pygame.draw.ellipse(frame.surface, color, rect, width)
|
||||
|
||||
@staticmethod
|
||||
def polygon(frame, pointlist: list, color: tuple = (255, 255, 255), width: int = 0):
|
||||
pygame.draw.polygon(frame.surface, color, pointlist, width)
|
||||
|
||||
@staticmethod
|
||||
def arc(frame, pos: tuple = (0, 0), size: tuple = (1, 1), color: tuple = (255, 255, 255), start_angle: float = 0, stop_angle: float = 3.14, width: int = 1):
|
||||
rect=(pos[0], pos[1], size[0], size[1])
|
||||
pygame.draw.arc(frame.surface, color, rect, start_angle, stop_angle, width)
|
||||
|
||||
@staticmethod
|
||||
def point(frame, pos: tuple, color: tuple = (255, 255, 255)):
|
||||
pygame.draw.point(frame.surface, color, pos)
|
||||
|
||||
@staticmethod
|
||||
def lines(frame, pointlist: list, color: tuple = (255, 255, 255)):
|
||||
pygame.draw.aalines(frame.surface, color, closed=False, points=pointlist)
|
||||
|
||||
@staticmethod
|
||||
def call(frame, method, **kwargs):
|
||||
if hasattr(Graph, method):
|
||||
getattr(Graph, method)(frame, **kwargs)
|
||||
else:
|
||||
print(f"方法 {method} 不存在")
|
283
vgl/main.py
Normal file
283
vgl/main.py
Normal file
@@ -0,0 +1,283 @@
|
||||
# Vector Graphics Library
|
||||
# vgllib.py
|
||||
import pygame
|
||||
import uuid
|
||||
import time
|
||||
import threading
|
||||
import copy
|
||||
import queue
|
||||
|
||||
class Aux():
|
||||
def gettime():
|
||||
return round(time.time(), 1)
|
||||
def getprogress(task):
|
||||
return (Aux.gettime() - task["start"] / task["duration"])
|
||||
def tuple_scale(tup, mul):
|
||||
return (tup[0]*mul, tup[1]*mul)
|
||||
def pixelizer(arg, base):
|
||||
if not isinstance(base, tuple):
|
||||
base = base.size
|
||||
if isinstance(arg, int):
|
||||
return arg * base
|
||||
else:
|
||||
if len(arg) == 2:
|
||||
return (round(arg[0] * base[0]), round(arg[1] * base[1]))
|
||||
if len(arg) == 4:
|
||||
return (round(arg[0] * base[0]), round(arg[1] * base[1]), round(arg[2] * base[0]), round(arg[3] * base[1]))
|
||||
def eventproc(events_dict, event, window_size):
|
||||
"""events = {
|
||||
"cursor": {
|
||||
"position": (15,12),
|
||||
"relative": (13,11),
|
||||
"poscale": (0.1,0.5),
|
||||
"relscale": (0.05,0.1),
|
||||
},
|
||||
"wheel": 1, # 远离用户为 1, 靠近为 -1, 无动作为 0
|
||||
"click": [1, 2], # 被按下的按钮
|
||||
#"focus": 1, # 或 0
|
||||
"key": ["ctrl", "k"],
|
||||
"delta": ""
|
||||
}"""
|
||||
if event.type == pygame.MOUSEMOTION:
|
||||
events_dict["cursor"]["position"] = event.pos
|
||||
events_dict["cursor"]["relative"] = event.rel
|
||||
events_dict["cursor"]["poscale"] = (round(event.pos[0] / window_size[0], 3), round(event.pos[1] / window_size[1],3))
|
||||
events_dict["cursor"]["relscale"] = (round(event.rel[0] / window_size[0], 3), round(event.rel[1] / window_size[1], 3))
|
||||
events_dict["delta"] = "cursor"
|
||||
elif event.type == pygame.MOUSEWHEEL:
|
||||
events_dict["wheel"] = event.y # 远离用户为正,靠近为负
|
||||
events_dict["delta"] = "wheel"
|
||||
elif event.type == pygame.MOUSEBUTTONDOWN:
|
||||
if event.button not in events_dict["click"]:
|
||||
events_dict.setdefault("click", []).append(event.button)
|
||||
events_dict["delta"] = "click"
|
||||
elif event.type == pygame.MOUSEBUTTONUP:
|
||||
if event.button in events_dict["click"]:
|
||||
events_dict["click"].remove(event.button)
|
||||
events_dict["delta"] = "click"
|
||||
elif event.type == pygame.KEYDOWN:
|
||||
keys = events_dict.setdefault("key", [])
|
||||
key_name = pygame.key.name(event.key).lower()
|
||||
# 简单的修饰键处理, 为兼容部分精简键盘 故合并左右功能键
|
||||
if key_name in ["left ctrl", "right ctrl"]:
|
||||
if "ctrl" not in keys:
|
||||
keys.append("ctrl")
|
||||
elif key_name in ["left shift", "right shift"]:
|
||||
if "shift" not in keys:
|
||||
keys.append("shift")
|
||||
elif key_name in ["left alt", "right alt"]:
|
||||
if "alt" not in keys:
|
||||
keys.append("alt")
|
||||
elif len(key_name) == 1: # 处理字母和数字
|
||||
keys.append(key_name)
|
||||
events_dict["delta"] = "key"
|
||||
elif event.type == pygame.KEYUP:
|
||||
events_dict["delta"] = "key"
|
||||
if "key" in events_dict:
|
||||
key_name = pygame.key.name(event.key).lower()
|
||||
if key_name in ["left ctrl", "right ctrl"] and "ctrl" in events_dict["key"]:
|
||||
events_dict["key"].remove("ctrl")
|
||||
elif key_name in ["left shift", "right shift"] and "shift" in events_dict["key"]:
|
||||
events_dict["key"].remove("shift")
|
||||
elif key_name in ["left alt", "right alt"] and "alt" in events_dict["key"]:
|
||||
events_dict["key"].remove("alt")
|
||||
elif len(key_name) == 1 and key_name in events_dict["key"]:
|
||||
events_dict["key"].remove(key_name)
|
||||
else:
|
||||
#print("不重要事件")
|
||||
return 0
|
||||
return 1
|
||||
class Anchor(object):
|
||||
"""
|
||||
"锚定点" 对象
|
||||
镜像
|
||||
@: 矩阵乘法
|
||||
*: 中心/任意参照点缩放
|
||||
中点/比例点
|
||||
|
||||
"""
|
||||
poscale = (0, 0) # 位置
|
||||
fixed = 3 # 小数点后精度
|
||||
def __init__(self, *args):
|
||||
if isinstance(args[0], tuple) or isinstance(args[0], Anchor):
|
||||
if isinstance(args[0], Anchor):
|
||||
self.poscale = args[0].poscale
|
||||
else:
|
||||
self.poscale = args[0]
|
||||
else:
|
||||
self.poscale = (args[0], args[1])
|
||||
def x(self):
|
||||
return self.poscale[0]
|
||||
def y(self):
|
||||
return self.poscale[1]
|
||||
def __add__(self, other):
|
||||
"矩阵加法"
|
||||
if isinstance(other, tuple):
|
||||
return Anchor((self.poscale[0] + other[0], self.poscale[1] + other[1]))
|
||||
elif isinstance(other, Anchor):
|
||||
return Anchor((self.poscale[0] + other.poscale[0], self.poscale[1] + other.poscale[1]))
|
||||
else:
|
||||
raise TypeError("不支持的加法操作数类型")
|
||||
def __mul__(self, other):
|
||||
"中心倍增/倍缩"
|
||||
if isinstance(other, tuple):
|
||||
return Anchor((0.5 + other[0] * (self.poscale[0] - 0.5), 0.5 + other[1] * (self.poscale[1] - 0.5)))
|
||||
elif isinstance(other, (int, float)):
|
||||
return Anchor((0.5 + other * (self.poscale[0] - 0.5), 0.5 + other * (self.poscale[1] - 0.5)))
|
||||
else:
|
||||
raise TypeError("不支持的乘法操作数类型")
|
||||
def __imul__(self, other):
|
||||
result = self.__mul__(other)
|
||||
self.poscale = result.poscale
|
||||
return self
|
||||
def __truediv__(self, other):
|
||||
"乘以倒数"
|
||||
if isinstance(other, (int, float)):
|
||||
if other == 0:
|
||||
return Anchor((0.5, 0.5))
|
||||
else:
|
||||
return self.__mul__(1 / other)
|
||||
elif isinstance(other, Anchor) or isinstance(other, tuple):
|
||||
divisor_x = other[0] if isinstance(other, tuple) else other.x()
|
||||
divisor_y = other[1] if isinstance(other, tuple) else other.y()
|
||||
# TODO: 错误代码, 应当予以修正
|
||||
if divisor_x == 0 and divisor_y == 0:
|
||||
return Anchor((0.5, 0.5))
|
||||
if divisor_x == 0 and divisor_y == 0:
|
||||
return Anchor((0.5, 0.5))
|
||||
else:
|
||||
return self.__mul__((1 / divisor_x, 1 / divisor_y))
|
||||
else:
|
||||
raise TypeError("不支持的除法操作数类型")
|
||||
def __itruediv__(self, other):
|
||||
"就地除法"
|
||||
result = self.__truediv__(other)
|
||||
self.poscale = result.poscale
|
||||
return self
|
||||
def __str__(self):
|
||||
if self.fixed is not None:
|
||||
return f"({round(self.poscale[0], self.fixed)}, {round(self.poscale[1], self.fixed)})"
|
||||
else:
|
||||
return f"({self.poscale[0]}, {self.poscale[1]})"
|
||||
class Element(object):
|
||||
is_hide = False
|
||||
is_template = True
|
||||
attached = None
|
||||
attached_frame = None
|
||||
attached_window = None
|
||||
tasks = dict()
|
||||
def __init__(self, name="Element"):
|
||||
self.name = name
|
||||
def attach(self, frame_object, clone_name=""):
|
||||
if clone_name == "":
|
||||
clone_name = str(uuid.uuid4())
|
||||
clone = copy.deepcopy(self)
|
||||
clone.is_template = False
|
||||
frame_object.elements[clone_name] = clone
|
||||
clone.attached_frame = frame_object
|
||||
clone.attached_window = frame_object.attached_window
|
||||
return clone
|
||||
def teleport(self, delta: tuple):
|
||||
if not self.is_template:
|
||||
pass
|
||||
def add_task(self, group, start_time, duration, **kwargs):
|
||||
if group not in self.tasks():
|
||||
self.tasks[group] = list()
|
||||
self.tasks[group].append({"start": start_time, "duration":duration, "para":kwargs})
|
||||
def render():
|
||||
print("未配置渲染器")
|
||||
pass
|
||||
def update():
|
||||
pass
|
||||
|
||||
class Frame(object):
|
||||
surface = None
|
||||
elements = dict()
|
||||
is_hide = False
|
||||
is_template = True
|
||||
attached_window = None
|
||||
poscale: tuple = (0, 0) # 左上角, 对于每个实例的位置矢量
|
||||
def __init__(self, name="Frame"):
|
||||
self.name = name
|
||||
def attach(self, window_object, poscale, clone_name=""):
|
||||
if clone_name == "":
|
||||
clone_name = str(uuid.uuid4())
|
||||
clone = copy.deepcopy(self)
|
||||
clone.surface = pygame.Surface(window_object.size)
|
||||
clone.poscale = poscale
|
||||
clone.is_template = False
|
||||
clone.attached_window = window_object
|
||||
window_object.frames[clone_name] = clone
|
||||
return window_object.frames[clone_name]
|
||||
def render(self):
|
||||
for i in self.elements.values():
|
||||
i.render()
|
||||
self.attached_window.screen.blit(self.surface, self.poscale)
|
||||
|
||||
class Window(object):
|
||||
frames = dict()
|
||||
events = {
|
||||
"cursor": {
|
||||
"position": (0,0),
|
||||
"relative": (0,0),
|
||||
"poscale": (0,0),
|
||||
"relscale": (0,0),
|
||||
},
|
||||
"wheel": 0, # 远离用户为 1, 靠近为 -1, 无动作为 0
|
||||
"click": [], # 被按下的按钮
|
||||
"focus": 1, # 或 0
|
||||
"key": [],
|
||||
"delta": "" # 变化的键值, 避免多次调用
|
||||
}
|
||||
"""{
|
||||
"cursor": {
|
||||
"position": (15,12),
|
||||
"relative": (13,11),
|
||||
"poscale": (0.1,0.5),
|
||||
"relscale": (0.05,0.1),
|
||||
},
|
||||
"wheel": 1, # 远离用户为 1, 靠近为 -1, 无动作为 0
|
||||
"click": [1, 2], # 被按下的按钮
|
||||
"focus": 1, # 或 0
|
||||
"key": ["ctrl", "k"],
|
||||
"delta": ["key"]
|
||||
}"""
|
||||
observers = list()
|
||||
def __init__(self, title="Vector Graphic Layer Window", size: tuple=(1024,768)):
|
||||
self.title = title
|
||||
self.size = size
|
||||
self.running = 1
|
||||
pygame.init()
|
||||
self.screen = pygame.display.set_mode(size)
|
||||
pygame.display.set_caption(title)
|
||||
def set_title(self, title):
|
||||
self.title = title
|
||||
pygame.display.set_caption(title)
|
||||
def start(self):
|
||||
self.thr = threading.Thread(target=self.main_loop, name="main_loop")
|
||||
self.thr.start()
|
||||
def kill(self):
|
||||
self.running = 0
|
||||
def main_loop(self):
|
||||
while self.running:
|
||||
for event in pygame.event.get():
|
||||
if event.type == pygame.QUIT:
|
||||
self.running = 0
|
||||
if_matters = Aux.eventproc(self.events, event, self.size)
|
||||
if if_matters:
|
||||
#print(self.observers)
|
||||
for i in self.observers:
|
||||
i(self.events)
|
||||
#print(self.events)
|
||||
|
||||
for i in self.frames.values():
|
||||
i.render()
|
||||
pygame.display.flip()
|
||||
pygame.time.delay(10)
|
||||
pygame.quit()
|
||||
def observerize(self, func):
|
||||
def wrapper():
|
||||
self.observers.append(func)
|
||||
return wrapper
|
||||
def remove_observer(self, func):
|
||||
self.observers.remove(func)
|
28
vgl/test.py
Normal file
28
vgl/test.py
Normal file
@@ -0,0 +1,28 @@
|
||||
import pygame
|
||||
import sys
|
||||
|
||||
# 初始化 Pygame
|
||||
pygame.init()
|
||||
|
||||
# 设置窗口大小
|
||||
screen = pygame.display.set_mode((800, 600))
|
||||
|
||||
# 设置颜色 (RGB)
|
||||
background_color = (255, 255, 255) # 白色背景
|
||||
line_color = (255, 0, 0) # 红色线条
|
||||
|
||||
# 主循环
|
||||
while True:
|
||||
for event in pygame.event.get():
|
||||
if event.type == pygame.QUIT:
|
||||
pygame.quit()
|
||||
sys.exit()
|
||||
|
||||
# 填充背景
|
||||
screen.fill(background_color)
|
||||
|
||||
# 绘制抗锯齿线条
|
||||
pygame.draw.aaline(screen, line_color, (100, 100), (700, 500))
|
||||
|
||||
# 更新显示
|
||||
pygame.display.flip()
|
Reference in New Issue
Block a user