报警输出完成
This commit is contained in:
Binary file not shown.
@@ -1,7 +1,5 @@
|
||||
/*
|
||||
本程序用于读取配置文件
|
||||
根据配置文件发送高低电平
|
||||
发送引脚固定:7,8
|
||||
本程序用于控制引脚输出高低电平
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
@@ -13,12 +11,6 @@
|
||||
using namespace std;
|
||||
using namespace QCL;
|
||||
|
||||
/*
|
||||
Parmas:
|
||||
argv[1]: GPIO引脚编号
|
||||
argv[2]: 设置引脚为高/低电平
|
||||
*/
|
||||
|
||||
const string SetFile = "/home/orangepi/RKApp/InitAuth/conf/.env";
|
||||
|
||||
// 初始化GPIO引脚
|
||||
@@ -35,14 +27,11 @@ int main(int argc, char *argv[])
|
||||
int GPIO_Pin1 = 7;
|
||||
int GPIO_Pin2 = 8;
|
||||
|
||||
int value = 0;
|
||||
cout << "[sendGpioSignal] 启动,读取配置: " << SetFile << endl;
|
||||
if (GetOutValue(value) == false)
|
||||
if (argc < 2)
|
||||
{
|
||||
cerr << "[sendGpioSignal] 未读取到 outPutMode,程序退出" << endl;
|
||||
cerr << "传入参数错误" << endl;
|
||||
return -1;
|
||||
}
|
||||
cout << "[sendGpioSignal] 读取到 outPutMode=" << (value == 1 ? "true" : "false") << endl;
|
||||
|
||||
// 初始化GPIO引脚
|
||||
if (InitGpio(GPIO_Pin1, GPIO_Pin2) != 0)
|
||||
@@ -50,14 +39,48 @@ int main(int argc, char *argv[])
|
||||
cout << "Error: Failed to initialize GPIO pin " << endl;
|
||||
return 1;
|
||||
}
|
||||
// 写入GPIO引脚
|
||||
cout << "[sendGpioSignal] 设置 GPIO(" << GPIO_Pin1 << "," << GPIO_Pin2 << ") 为 "
|
||||
<< (value == 1 ? "HIGH" : "LOW") << endl;
|
||||
WriteGpio(GPIO_Pin1, value);
|
||||
WriteGpio(GPIO_Pin2, value);
|
||||
cout << "[sendGpioSignal] 完成" << endl;
|
||||
|
||||
this_thread::sleep_for(chrono::milliseconds(100));
|
||||
WriteGpio(GPIO_Pin1, stoi(argv[1]));
|
||||
WriteGpio(GPIO_Pin2, stoi(argv[1]));
|
||||
|
||||
return 0;
|
||||
|
||||
// int value = 0;
|
||||
// bool useArg = false;
|
||||
|
||||
// // 修改点:如果传入了参数,直接使用参数作为电平值 (1 或 0)
|
||||
// if (argc > 1)
|
||||
// {
|
||||
// value = atoi(argv[1]);
|
||||
// useArg = true;
|
||||
// cout << "[sendGpioSignal] 使用命令行参数: " << value << endl;
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// // 原有的读取文件逻辑
|
||||
// cout << "[sendGpioSignal] 启动,读取配置: " << SetFile << endl;
|
||||
// if (GetOutValue(value) == false)
|
||||
// {
|
||||
// cerr << "[sendGpioSignal] 未读取到 outPutMode,程序退出" << endl;
|
||||
// return -1;
|
||||
// }
|
||||
// cout << "[sendGpioSignal] 读取到 outPutMode=" << (value == 1 ? "true" : "false") << endl;
|
||||
// }
|
||||
|
||||
// // 初始化GPIO引脚
|
||||
// if (InitGpio(GPIO_Pin1, GPIO_Pin2) != 0)
|
||||
// {
|
||||
// cout << "Error: Failed to initialize GPIO pin " << endl;
|
||||
// return 1;
|
||||
// }
|
||||
// // 写入GPIO引脚
|
||||
// cout << "[sendGpioSignal] 设置 GPIO(" << GPIO_Pin1 << "," << GPIO_Pin2 << ") 为 "
|
||||
// << (value == 1 ? "HIGH" : "LOW") << endl;
|
||||
// WriteGpio(GPIO_Pin1, value);
|
||||
// WriteGpio(GPIO_Pin2, value);
|
||||
// cout << "[sendGpioSignal] 完成" << endl;
|
||||
|
||||
// this_thread::sleep_for(chrono::milliseconds(100));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
116
GPIOSignal/src/sendGpioSignal.cpp.bak2
Normal file
116
GPIOSignal/src/sendGpioSignal.cpp.bak2
Normal file
@@ -0,0 +1,116 @@
|
||||
/*
|
||||
本程序用于控制引脚输出高低电平
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
#include <thread>
|
||||
#include <wiringPi.h>
|
||||
|
||||
#include "/home/orangepi/RKApp/softWareInit/NetraLib/include/Netra.hpp"
|
||||
|
||||
using namespace std;
|
||||
using namespace QCL;
|
||||
|
||||
const string SetFile = "/home/orangepi/RKApp/InitAuth/conf/.env";
|
||||
|
||||
// 初始化GPIO引脚
|
||||
int InitGpio(int GPIO_Pin1, int GPIO_Pin2);
|
||||
|
||||
// 写入GPIO引脚
|
||||
void WriteGpio(int GPIO_Pin, int value);
|
||||
|
||||
// 获取输出模式
|
||||
bool GetOutValue(int &value);
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int GPIO_Pin1 = 7;
|
||||
int GPIO_Pin2 = 8;
|
||||
|
||||
int value = 0;
|
||||
bool useArg = false;
|
||||
|
||||
// 修改点:如果传入了参数,直接使用参数作为电平值 (1 或 0)
|
||||
if (argc > 1)
|
||||
{
|
||||
value = atoi(argv[1]);
|
||||
useArg = true;
|
||||
cout << "[sendGpioSignal] 使用命令行参数: " << value << endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
// 原有的读取文件逻辑
|
||||
cout << "[sendGpioSignal] 启动,读取配置: " << SetFile << endl;
|
||||
if (GetOutValue(value) == false)
|
||||
{
|
||||
cerr << "[sendGpioSignal] 未读取到 outPutMode,程序退出" << endl;
|
||||
return -1;
|
||||
}
|
||||
cout << "[sendGpioSignal] 读取到 outPutMode=" << (value == 1 ? "true" : "false") << endl;
|
||||
}
|
||||
|
||||
// 初始化GPIO引脚
|
||||
if (InitGpio(GPIO_Pin1, GPIO_Pin2) != 0)
|
||||
{
|
||||
cout << "Error: Failed to initialize GPIO pin " << endl;
|
||||
return 1;
|
||||
}
|
||||
// 写入GPIO引脚
|
||||
cout << "[sendGpioSignal] 设置 GPIO(" << GPIO_Pin1 << "," << GPIO_Pin2 << ") 为 "
|
||||
<< (value == 1 ? "HIGH" : "LOW") << endl;
|
||||
WriteGpio(GPIO_Pin1, value);
|
||||
WriteGpio(GPIO_Pin2, value);
|
||||
cout << "[sendGpioSignal] 完成" << endl;
|
||||
|
||||
this_thread::sleep_for(chrono::milliseconds(100));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 获取输出模式
|
||||
bool GetOutValue(int &value)
|
||||
{
|
||||
bool flag = true;
|
||||
// 读取文件
|
||||
ReadFile rf(SetFile);
|
||||
if (rf.Open() == false)
|
||||
{
|
||||
cerr << "读取文件失败" << endl;
|
||||
flag = false;
|
||||
}
|
||||
|
||||
auto str = rf.ReadLines();
|
||||
for (auto &ii : str)
|
||||
{
|
||||
if (ii.find("outPutMode") != string::npos)
|
||||
{
|
||||
value = (ii.substr(string("outPutMode:").size()) == "true" ? 1 : 0);
|
||||
}
|
||||
}
|
||||
|
||||
rf.Close();
|
||||
return flag;
|
||||
}
|
||||
|
||||
// 初始化GPIO引脚
|
||||
int InitGpio(int GPIO_Pin1, int GPIO_Pin2)
|
||||
{
|
||||
// 使用物理引脚编号,确保与实际排针一致
|
||||
if (wiringPiSetupPhys() != 0)
|
||||
{
|
||||
return -1; // 初始化失败
|
||||
}
|
||||
|
||||
pinMode(GPIO_Pin1, OUTPUT);
|
||||
pinMode(GPIO_Pin2, OUTPUT);
|
||||
digitalWrite(GPIO_Pin1, LOW); // 默认设置为低电平
|
||||
digitalWrite(GPIO_Pin2, LOW); // 默认设置为低电平
|
||||
|
||||
return 0; // 初始化成功
|
||||
}
|
||||
|
||||
// 写入GPIO引脚
|
||||
void WriteGpio(int GPIO_Pin, int value)
|
||||
{
|
||||
digitalWrite(GPIO_Pin, value == 1 ? HIGH : LOW);
|
||||
}
|
||||
@@ -5,7 +5,7 @@ UUID:null
|
||||
ServerPwd:"17227ca72f30f8bca8158bb78f25b43e"
|
||||
|
||||
#以下配置存储GPIO输出高低电平--状态机
|
||||
outPutMode:true
|
||||
outPutMode:false
|
||||
|
||||
#以下配置存储报警距离
|
||||
NEAR_THRESHOLD=3
|
||||
|
||||
Binary file not shown.
@@ -3,7 +3,8 @@
|
||||
1.推流摄像头画面,使用UDP原生协议进行推流,交由YOLO模型进行处理
|
||||
2.接收YOLO传来的坐标和度数据
|
||||
3.根据获取到的数据绘制边框和相应数据
|
||||
4.将绘制完毕的视频流继续推流至RTSP服务器用于输出
|
||||
4.根据距离信息进行报警和图片视频保存
|
||||
5.将绘制完毕的视频流继续推流至RTSP服务器用于输出
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
@@ -55,6 +56,8 @@ mutex alertMutex; // 保护alertQueue的互斥锁
|
||||
condition_variable alertcv; // 通知报警线程有新任务
|
||||
queue<nlohmann::json> alertQueue; // 存放解析后的数据
|
||||
std::atomic<bool> alertWorkerRunning{false}; // 工作线程运行标志
|
||||
atomic<bool> outPutMode = false; // 保存报警输出false--电平
|
||||
// atomic<bool> currentFrameHasDanger{false}; // 是否进行了报警
|
||||
|
||||
// mqtt初始化
|
||||
void MqttInit();
|
||||
@@ -72,8 +75,14 @@ void mainLoop(VideoCapture &cap, FILE *pipe);
|
||||
void getMsgCallback(mqtt::const_message_ptr msg);
|
||||
// 绘制矩形方框和深度信息
|
||||
void drawRect(int x, int y, int w, int h, double distance);
|
||||
// 获取报警距离
|
||||
// 报警线程
|
||||
void warnThread();
|
||||
// 获取报警距离和输出模式
|
||||
bool GetDistance();
|
||||
// 调用报警输出程序
|
||||
void setGPIOLevel(int level);
|
||||
// // 状态机
|
||||
// void warnStatus();
|
||||
|
||||
int main()
|
||||
{
|
||||
@@ -102,6 +111,135 @@ int main()
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 调用报警输出程序
|
||||
void setGPIOLevel(int level)
|
||||
{
|
||||
string cmd = "echo 'orangepi' | sudo -S /home/orangepi/RKApp/GPIOSignal/bin/sendGpioSignal " + to_string(level);
|
||||
system(cmd.c_str());
|
||||
}
|
||||
|
||||
// // 状态机
|
||||
// void warnStatus()
|
||||
// {
|
||||
// thread([]()
|
||||
// {
|
||||
// bool isAlarm = false;
|
||||
// auto lastDangerTime = chrono::steady_clock::now();
|
||||
// while(alertWorkerRunning.load())
|
||||
// {
|
||||
|
||||
// } });
|
||||
// }
|
||||
|
||||
// 报警线程
|
||||
void warnThread()
|
||||
{
|
||||
// 开启报警线程
|
||||
thread([]()
|
||||
{
|
||||
//状态变量
|
||||
bool isAlarming = false; //报警状态
|
||||
auto lastDangerTime = chrono::steady_clock::now(); //上次报警时间
|
||||
|
||||
//读取配置设置初始状态
|
||||
GetDistance();
|
||||
int normalLevel = outPutMode?0:1; //false:正常高,输出低,true:正常低,输出高
|
||||
int alarmLevel = outPutMode?1:0; //报警输出,true:报警高,false:报警低
|
||||
|
||||
cout << "normalLevel = " << normalLevel <<",alarmLevel = " << alarmLevel << endl;
|
||||
|
||||
//设置初始状态为正常状态
|
||||
setGPIOLevel(normalLevel);
|
||||
|
||||
while (alertWorkerRunning.load())
|
||||
{
|
||||
unique_lock<mutex> lk(alertMutex);
|
||||
// 等待条件,队列非空或者收到停止信号
|
||||
if(isAlarming)
|
||||
{ //如果触发报警,就每每100ms检查一次
|
||||
alertcv.wait_for(lk,100ms,[](){
|
||||
return !alertQueue.empty() || !alertWorkerRunning.load();});
|
||||
}
|
||||
else{
|
||||
//没有触发报警,就死等
|
||||
alertcv.wait(lk,[](){
|
||||
return !alertQueue.empty() || !alertWorkerRunning.load();});
|
||||
}
|
||||
|
||||
|
||||
//如果线程应退出切队列为空,退出循环
|
||||
if(alertQueue.empty() && !alertWorkerRunning.load())
|
||||
break;
|
||||
|
||||
//当前帧是否触发报警
|
||||
bool currentFrameHasDanger = false;
|
||||
|
||||
//处理队列中的所有信号
|
||||
while(!alertQueue.empty())
|
||||
{
|
||||
auto job = move(alertQueue.front());
|
||||
alertQueue.pop(); //释放空指针
|
||||
//解锁,以便于增加队列任务
|
||||
lk.unlock();
|
||||
|
||||
//报警处理函数
|
||||
try
|
||||
{
|
||||
//获取报警距离
|
||||
GetDistance();
|
||||
|
||||
// 更新电平定义(防止运行时修改了配置文件)
|
||||
normalLevel = outPutMode ? 0 : 1;
|
||||
alarmLevel = outPutMode ? 1 : 0;
|
||||
|
||||
for(auto&ii:job)
|
||||
{
|
||||
if(ii["distance"] <= dis.danger)
|
||||
{ //触发警报
|
||||
currentFrameHasDanger = true;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
catch(const std::exception& e)
|
||||
{
|
||||
std::cerr << e.what() << '\n';
|
||||
}
|
||||
|
||||
lk.lock(); //重新上锁,以继续处理下个任务
|
||||
|
||||
}
|
||||
|
||||
//逻辑处理,状态机
|
||||
if(currentFrameHasDanger)
|
||||
{
|
||||
lastDangerTime = chrono::steady_clock::now();
|
||||
if(!isAlarming)
|
||||
{
|
||||
//刚进入报警状态
|
||||
isAlarming = true;
|
||||
setGPIOLevel(alarmLevel);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//当前帧没有危险,检测是否需要恢复
|
||||
if(isAlarming)
|
||||
{
|
||||
auto now = chrono::steady_clock::now();
|
||||
auto dur = chrono::duration_cast<chrono::seconds>(now - lastDangerTime).count();
|
||||
if(dur >= 2)
|
||||
{//超过两秒恢复正常
|
||||
isAlarming=false;
|
||||
setGPIOLevel(normalLevel);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} })
|
||||
.detach();
|
||||
}
|
||||
|
||||
// 获取报警距离
|
||||
bool GetDistance()
|
||||
{
|
||||
@@ -123,6 +261,12 @@ bool GetDistance()
|
||||
dis.warn = stoi(line.substr(sizeof("MID_THRESHOLD=") - 1));
|
||||
else if (line.find("MAX_DISTANCE=") != string::npos)
|
||||
dis.safe = stoi(line.substr(sizeof("MAX_DISTANCE=") - 1));
|
||||
else if (line.find("outPutMode:") != string::npos)
|
||||
{
|
||||
// 确认输电平模式
|
||||
string val = line.substr(sizeof("outPutMode:"));
|
||||
outPutMode = (val == "true");
|
||||
}
|
||||
}
|
||||
|
||||
rf.Close();
|
||||
@@ -163,43 +307,10 @@ void MqttInit()
|
||||
client.connect()->wait();
|
||||
client.subscribe(Topic, Qos)->wait();
|
||||
|
||||
// 开启报警线程
|
||||
thread([]()
|
||||
{
|
||||
while (alertWorkerRunning.load())
|
||||
{
|
||||
unique_lock<mutex> lk(alertMutex);
|
||||
// 等待条件,队列非空或者收到停止信号
|
||||
alertcv.wait(lk,[](){
|
||||
return !alertQueue.empty() || !alertWorkerRunning.load();});
|
||||
alertWorkerRunning = true;
|
||||
|
||||
//如果线程应退出切队列为空,退出循环
|
||||
if(alertQueue.empty() && !alertWorkerRunning.load())
|
||||
break;
|
||||
|
||||
//处理队列中的所有信号
|
||||
while(!alertQueue.empty())
|
||||
{
|
||||
auto job = move(alertQueue.front());
|
||||
alertQueue.pop(); //释放空指针
|
||||
//解锁,以便于增加队列任务
|
||||
lk.unlock();
|
||||
|
||||
//报警处理函数
|
||||
try
|
||||
{
|
||||
|
||||
}
|
||||
catch(const std::exception& e)
|
||||
{
|
||||
std::cerr << e.what() << '\n';
|
||||
}
|
||||
|
||||
lk.lock(); //重新上锁,以继续处理下个任务
|
||||
|
||||
}
|
||||
} })
|
||||
.detach();
|
||||
// 开启线程
|
||||
warnThread();
|
||||
}
|
||||
|
||||
// mqtt接收订阅消息的回调
|
||||
@@ -316,9 +427,8 @@ bool processFrame(VideoCapture &cap, FILE *pipe, Mat &frame, int64 &count, chron
|
||||
// 拷贝视频帧
|
||||
handleFrame = frame;
|
||||
|
||||
// 读取最新检测:短锁获取并将结果拷贝到本地变量
|
||||
vector<Dection> destCopy;
|
||||
|
||||
// 读取最新检测:短锁获取并将结果拷贝到本地变量
|
||||
{
|
||||
lock_guard<mutex> lk(detMutex);
|
||||
destCopy = latestDection; // 复制到本地后释放锁
|
||||
@@ -330,7 +440,11 @@ bool processFrame(VideoCapture &cap, FILE *pipe, Mat &frame, int64 &count, chron
|
||||
drawRect(ii.x, ii.y, ii.w, ii.h, ii.distance);
|
||||
}
|
||||
|
||||
// 短锁进行清除
|
||||
{
|
||||
lock_guard<mutex> lk(detMutex);
|
||||
latestDection.clear();
|
||||
}
|
||||
|
||||
// 可选:显示窗口
|
||||
// imshow("测试画面", frame);
|
||||
|
||||
Reference in New Issue
Block a user