针对传统仓储物料人工盘点效率低、多终端并发操作易引发库存数据异常、仓储环境管控难等痛点基于i.MX6ULL嵌入式Linux平台独立开发分布式智能物料管理系统。构建“终端采集-边缘网关-后台管理平台”三层架构实现温湿度/光照采集、人员入侵检测、外设远程控制、历史数据查询与异常报警等核心功能。终端采集代码#include mainwindow.h#include ui_mainwindow.h#include fcntl.h#include unistd.hint Temp_data[51] {0}; // 温度数组int Humi_data[51] {0}; // 湿度数组bool curtain_autoCtl false; //窗帘自动控制标志位void init_all(void){led_init();dht11_init();sr04_init();sg90_init();}// DHT11Thread实现DHT11Thread::DHT11Thread(QObject *parent) : QThread(parent) {}void DHT11Thread::run() {while (!isInterruptionRequested()) {THData data;// DHT11数据读取dht11_read(data);// 发送数据更新信号emit DHT11_dataUpdated(data);msleep(1000); // 1秒采样一次}}DHT11Thread::~DHT11Thread() {requestInterruption(); // 请求中断线程wait(); // 等待线程退出}// SR04Thread实现SR04Thread::SR04Thread(QObject *parent) : QThread(parent) {}void SR04Thread::run() {while (!isInterruptionRequested()) {int distance -1;if (sr04_read(distance) 0) {emit distanceUpdated(distance);// 发送数据到服务端emit sendDistanceData(distance); // 发送信号到主线程} else {qDebug() Failed to read distance from SR04 sensor;}msleep(1000);}}// 析构函数无需手动管理标志位SR04Thread::~SR04Thread() {requestInterruption(); // 请求中断线程wait(); // 等待线程退出}// LightCurtainThread实现LightCurtainThread::LightCurtainThread(QObject *parent) : QThread(parent) {}void LightCurtainThread::run() {while (!isInterruptionRequested()) {// 读取光敏电阻值ADC范围0-4095int lightValue readLightSensor();emit lightValueUpdated(lightValue);// 发送光线值更新信号emit sendLightValue(lightValue); // 发送光线强度到服务端if(curtain_autoCtl true) //只有开启窗帘自动控制才会根据光线强度计算窗帘角度和控制舵机{// 根据光线强度计算窗帘角度int angle calculateCurtainAngle(lightValue);// 控制舵机转动sg90_control(angle);emit curtainAngleChanged(angle);// 发送窗帘角度更新信号emit sendCurtainAngle(angle); // 发送舵机角度到服务端}msleep(1000); // 采样周期1000ms}}LightCurtainThread::~LightCurtainThread() {requestInterruption();wait();}int LightCurtainThread::readLightSensor() {// 通过/sys文件系统读取ADC值int fd open(/sys/bus/iio/devices/iio:device0/in_voltage3_raw, O_RDONLY);if (fd 0) {qDebug() Failed to open ADC device!;return -1;}char buf[20] {0};int bytes read(fd, buf, sizeof(buf));close(fd);if (bytes 0) {bool ok;int rawValue QString(buf).trimmed().toInt(ok);if (ok) {// 假设ADC满量程为409512位ADC进行反向计算// 光线越亮返回值越大int brightness 4095 - rawValue;return brightness;}}return -1;}int LightCurtainThread::calculateCurtainAngle(int light) {// 光线越强窗帘关闭越多角度越小const int minAngle 0; // 窗帘完全打开0度const int maxAngle 180; // 窗帘完全关闭180度// 线性映射ADC值(0-4095) → 角度(0-180)int angle maxAngle - qBound(minAngle, (light * maxAngle) / 4095, maxAngle);// 添加防抖逻辑避免微小波动导致频繁动作static int lastAngle angle;if (qAbs(angle - lastAngle) 5) {return lastAngle;}lastAngle angle;return angle;}void MainWindow::updateChart(const THData data) {static int timeCounter 0;// 更新温度数据tempSeries-append(timeCounter, data.temperature);// 更新湿度数据humiSeries-append(timeCounter, data.humidity);// 更新数值显示ui-lb_Temp-setText(QString(%1°C).arg(data.temperature, 0, f, 1));ui-lb_Humi-setText(QString(%1%).arg(data.humidity, 0, f, 1));// 更新时间轴范围if (timeCounter 30) {axisX-setRange(timeCounter - 30, timeCounter);}// 更新时间戳QString timeStr QDateTime::currentDateTime().toString(yyyy-MM-dd HH:mm:ss);ui-lb_time-setText(QString(最后更新: %1).arg(timeStr));timeCounter;chart-update();}void MainWindow::updateDistance(int distance) {if (distance 0) {ui-lb_dis-setText(QString(距离 %1 cm).arg(distance));ui-lb_status-setText(传感器状态: 正常);if(distance 10)ui-lb_humandetect-setText(有人);elseui-lb_humandetect-setText(没人);} else {ui-lb_dis-setText(距离读取失败);ui-lb_status-setText(传感器状态: 错误);}}void MainWindow::updateLightValue(int value) {ui-lb_lightValue-setText(QString(光线强度: %1/4095).arg(value));}void MainWindow::updateCurtainAngle(int angle) {ui-lb_curtainAngle-setText(QString(窗帘角度: %1°).arg(angle));// 线性映射将0~180°映射到0~100int progress static_castint((angle * 100.0) / 180.0);// 确保进度值在0~100范围内避免计算误差导致超界progress qBound(0, progress, 100);// 更新进度条ui-curtainProgressBar-setValue(progress);// 发送新的窗帘角度数据给服务端sendCurtainAngleToServer(angle);}void MainWindow::sendCurtainAngleToServer(int angle) {if (socket socket-state() QAbstractSocket::ConnectedState) {socket-write(QString(CURTAIN_ANGLE:%1\n).arg(angle).toUtf8());}}MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow){ui-setupUi(this);/* 初始化所有外设 */init_all();// 创建图表chart new QChart();chart-setTitle(DHT11温湿度实时监控);// 创建温度曲线tempSeries new QLineSeries();tempSeries-setName(温度 (°C));tempSeries-setColor(QColor(255, 107, 107)); // 红色// 创建湿度曲线humiSeries new QLineSeries();humiSeries-setName(湿度 (%));humiSeries-setColor(QColor(78, 205, 196)); // 蓝色// 添加曲线到图表chart-addSeries(tempSeries);chart-addSeries(humiSeries);// 创建坐标轴axisX new QValueAxis();axisX-setLabelFormat(%d);axisX-setTitleText(时间 (秒));axisX-setRange(0, 30); // 显示最近30秒的数据axisYTemp new QValueAxis();axisYTemp-setTitleText(温度 (°C));axisYTemp-setRange(10, 40);axisYTemp-setLinePenColor(tempSeries-color());axisYHumi new QValueAxis();axisYHumi-setTitleText(湿度 (%));axisYHumi-setRange(20, 100);axisYHumi-setLinePenColor(humiSeries-color());// 设置坐标轴chart-addAxis(axisX, Qt::AlignBottom);chart-addAxis(axisYTemp, Qt::AlignLeft);chart-addAxis(axisYHumi, Qt::AlignRight);tempSeries-attachAxis(axisX);tempSeries-attachAxis(axisYTemp);humiSeries-attachAxis(axisX);humiSeries-attachAxis(axisYHumi);// 设置图表样式chart-legend()-setVisible(true);chart-legend()-setAlignment(Qt::AlignTop);// 将图表设置到UI中已存在的QChartViewui-chartView-setChart(chart);ui-chartView-setRenderHint(QPainter::Antialiasing);// 创建并启动DHT11线程dht11Thread new DHT11Thread(this);connect(dht11Thread, DHT11Thread::DHT11_dataUpdated,this, MainWindow::updateChart);dht11Thread-start();// 创建并启动SR04线程sr04Thread new SR04Thread(this);connect(sr04Thread, SR04Thread::distanceUpdated,this, MainWindow::updateDistance);sr04Thread-start();// 创建并启动窗帘控制线程curtainThread new LightCurtainThread(this);connect(curtainThread, LightCurtainThread::lightValueUpdated,this, MainWindow::updateLightValue);connect(curtainThread, LightCurtainThread::curtainAngleChanged,this, MainWindow::updateCurtainAngle);curtainThread-start();connectToServer();}MainWindow::~MainWindow(){if (socket) {socket-close();socket-deleteLater();}delete dht11Thread;delete sr04Thread;delete curtainThread;delete ui;// led_close();sr04_close();dht11_close();sg90_close();}void MainWindow::connectToServer() {socket new QTcpSocket(this);socket-connectToHost(192.168.5.10, 8888);if (socket-waitForConnected(3000)) {qDebug() Connected to server!;// //led数据处理// connect(socket, SIGNAL(readyRead()), this, SLOT(readyRead()));// sendLedStatus();//超声波数据处理connect(sr04Thread, SR04Thread::sendDistanceData, this, [this](int distance) {if (socket socket-state() QAbstractSocket::ConnectedState) {socket-write(QString(DISTANCE:%1\n).arg(distance).toUtf8());}});// 光线强度数据处理connect(curtainThread, LightCurtainThread::sendLightValue, this, [this](int value) {if (socket socket-state() QAbstractSocket::ConnectedState) {socket-write(QString(LIGHT:%1\n).arg(value).toUtf8());}});// 舵机角度数据处理connect(curtainThread, LightCurtainThread::sendCurtainAngle, this, [this](int angle) {if (socket socket-state() QAbstractSocket::ConnectedState) {socket-write(QString(CURTAIN_ANGLE:%1\n).arg(angle).toUtf8());}});// 发送窗帘当前自动控制状态给服务端sendCurtainAutoCtlStatus();//发送温湿度数据给服务端connect(dht11Thread, DHT11Thread::DHT11_dataUpdated, this, [this](const THData data) {if (socket socket-state() QAbstractSocket::ConnectedState) {socket-write(QString(TEMPERATURE:%1;HUMIDITY:%2;TIME:%3\n).arg(data.temperature).arg(data.humidity).arg(QDateTime::currentDateTime().toString(yyyy-MM-dd HH:mm:ss)).toUtf8());}});} else {qDebug() Connection failed!;}}// 发送窗帘自动控制状态给服务端void MainWindow::sendCurtainAutoCtlStatus() {if (socket socket-state() QAbstractSocket::ConnectedState) {if (curtain_autoCtl) {socket-write(AUTO_CURTAIN_ON\n);} else {socket-write(AUTO_CURTAIN_OFF\n);}socket-flush();}}//处理服务端传回的void MainWindow::handleServerControl(const QByteArray data) {QString strData QString::fromUtf8(data);if (strData.startsWith(SET_CURTAIN_ANGLE:)) {bool ok;int angle strData.mid(18).toInt(ok);if (ok) {sg90_control(angle);updateCurtainAngle(angle);} else {qDebug() Invalid curtain angle format: strData;}} else if (strData AUTO_CURTAIN_ON) {curtain_autoCtl true;ui-cb_curAutoCtl-setChecked(true);ui-btn_cur_add-setEnabled(false);ui-btn_cur_sub-setEnabled(false);qDebug() 开启窗帘自动控制;} else if (strData AUTO_CURTAIN_OFF) {curtain_autoCtl false;ui-cb_curAutoCtl-setChecked(false);ui-btn_cur_add-setEnabled(true);ui-btn_cur_sub-setEnabled(true);qDebug() 关闭窗帘自动控制;} else {qDebug() Unknown control message: strData;}}void MainWindow::sendLedStatus() {if (socket) {if (LEDSwitch) {socket-write(LED_ON\n);} else {socket-write(LED_OFF\n);}socket-flush();}}void MainWindow::on_btn_led_clicked(){LEDSwitch !LEDSwitch;led_control(LEDSwitch);if(LEDSwitch)ui-btn_led-setIcon(QIcon(:/png/light_on.png));elseui-btn_led-setIcon(QIcon(:/png/light_off.png));sendLedStatus();}void MainWindow::readyRead() {QByteArray data socket-readAll();if (data TOGGLE_LED) {on_btn_led_clicked();}else {handleServerControl(data); // 处理服务端控制指令}}void MainWindow::on_btn_cur_sub_clicked(){QString text ui-lb_curtainAngle-text();// QString cleanText text.remove(QRegExp([^0-9]));QString cleanText;for (QChar ch : text) {if (ch.isDigit()) {cleanText.append(ch);}}int cur_angle cleanText.toInt();int ctl_angle cur_angle - 20;if(ctl_angle 0)ctl_angle 0;sg90_control(ctl_angle);updateCurtainAngle(ctl_angle);}void MainWindow::on_btn_cur_add_clicked(){QString text ui-lb_curtainAngle-text();// QString cleanText text.remove(QRegExp([^0-9]));QString cleanText;for (QChar ch : text) {if (ch.isDigit()) {cleanText.append(ch);}}int cur_angle cleanText.toInt();int ctl_angle cur_angle 20;if(ctl_angle 180)ctl_angle 180;sg90_control(ctl_angle);updateCurtainAngle(ctl_angle);}void MainWindow::on_cb_curAutoCtl_stateChanged(int state){if(state Qt::Checked){curtain_autoCtl true;ui-btn_cur_add-setEnabled(false);ui-btn_cur_sub-setEnabled(false);qDebug()开启窗帘自动控制;}else{curtain_autoCtl false;ui-btn_cur_add-setEnabled(true);ui-btn_cur_sub-setEnabled(true);qDebug()关闭窗帘自动控制;}sendCurtainAutoCtlStatus();}dht11.cpp#include sys/types.h#include sys/stat.h#include fcntl.h#include stdio.h#include errno.h#include string.h#include unistd.h#include QDebug#include dht11.hstatic int fd1;/* dht11初始化函数 */void dht11_init(void){fd1 open(/dev/querydht11, O_RDWR);if (fd1 0){qDebug()open /dev/querydht11 ;}qDebug()open /dev/querydht11 successfully ;}/* dht11读函数 */int dht11_read(THData *data){unsigned char buf[5] {0};int ret ;ret read(fd1, buf, sizeof(buf));if (ret ! sizeof(buf)){qDebug() read failed, got ret bytes, expected 5;return -1;}// 校验和验证// unsigned char checksum buf[0] buf[1] buf[2] buf[3];// if (checksum ! buf[4]) {// qDebug() DHT11 checksum error!;// return -1;// }/>