如何处理并发POST请求?树莓派GPIO继电器防闪烁重叠需求问询
解决POST请求并发导致灯光闪烁重叠的问题
这个问题的核心是要保证灯光闪烁操作的互斥性——同一时间只能有一个闪烁任务在执行,所以我们可以通过一个状态标记来实现“忙则忽略”的逻辑,具体方案如下:
核心思路
添加一个全局状态变量来标记当前是否正在执行闪烁操作:
- 当收到POST请求时,先检查这个状态,如果正在闪烁,直接返回响应忽略请求
- 如果空闲,则标记为“忙碌”,执行闪烁逻辑
- 闪烁完成后,重置状态为“空闲”,允许后续请求处理
修改后的代码示例
假设你使用onoff库控制GPIO(如果用其他库,调整GPIO操作部分即可):
var app = require('express')(); var http = require('http').Server(app); var bodyParser = require("body-parser"); // 补全解析器依赖 var Gpio = require('onoff').Gpio; // 初始化继电器(根据你的实际GPIO引脚调整) const relay = new Gpio(17, 'out'); // 闪烁总时长(X秒,这里示例为5秒) const BLINK_DURATION = 5000; // 状态标记:是否正在闪烁 let isBlinking = false; app.use(bodyParser.urlencoded({ extended: true })); app.use(bodyParser.json()); // 支持JSON格式的POST请求 app.post('/truck-alert', (req, res) => { // 检查当前是否正在闪烁,是则直接返回 if (isBlinking) { return res.status(409).send('Light is currently active, request skipped'); } // 标记为忙碌状态 isBlinking = true; let blinkTimer; try { // 启动闪烁:每隔500ms切换继电器状态 blinkTimer = setInterval(() => { // 翻转继电器状态(0变1,1变0) relay.writeSync(relay.readSync() ^ 1); }, 500); // 到设定时长后停止闪烁,重置状态 setTimeout(() => { clearInterval(blinkTimer); // 确保继电器最终处于关闭状态(根据你的需求调整) relay.writeSync(0); isBlinking = false; console.log('Blink cycle completed, ready for next alert'); }, BLINK_DURATION); // 返回成功响应 res.status(200).send('Alert triggered, light is blinking'); } catch (error) { // 出错时清理资源,重置状态,避免锁死 console.error('Error handling alert:', error); if (blinkTimer) clearInterval(blinkTimer); relay.writeSync(0); isBlinking = false; res.status(500).send('Failed to trigger alert'); } }); http.listen(3000, () => { console.log('Server running on port 3000'); }); // 程序退出时释放GPIO资源,避免树莓派引脚异常 process.on('SIGINT', () => { relay.unexport(); process.exit(); });
关键细节说明
- 状态锁
isBlinking:这个变量是整个逻辑的核心,它确保了同一时间只有一个闪烁任务能被执行,完全避免了重叠问题。 - 资源清理:
- 每次闪烁结束后,必须清理定时器并重置继电器状态,避免设备处于异常状态
- 程序退出时要释放GPIO资源,这是树莓派GPIO编程的最佳实践
- 错误处理:添加
try-catch块,确保即使闪烁过程中出现错误,也能重置isBlinking状态,不会导致后续请求一直被忽略。
如果你的GPIO控制库不是onoff,只需要替换继电器操作的相关代码即可,核心的状态控制逻辑是通用的。
内容的提问来源于stack exchange,提问作者Adolfo Alonso
相关产品推荐
相关产品推荐

