【嵌入式linux开发】智能家居入门5:老版ONENET,多协议接入(QT、微信小程序、HTTP协议、ONENET云平台、旭日x3派)

news2024/9/25 21:24:40

智能家居入门5(QT、微信小程序、HTTP协议、ONENET云平台、旭日x3派)

    • 前言
    • 一、QT界面设计
    • 二、云平台产品创建与连接
    • 三、下位机端QT代码总览:
    • 四、微信小程序端代码总览
    • 五、板端测试

前言

前四篇智能家居相关文章都是使用STM32作为主控,本篇使用旭日x3派作为主控,这是一款嵌入式linux开发板,运行linux操作系统。本项目在开发板端运行QT,使用http协议与onenet云平台通信,微信小程序作为移动端,可以接收到下位机上传至服务器的数据,也可以下发指令到服务器,开发板端不断获取指令,进而执行指令。界面设置是在QTcreator中进行,相较于代码设计来说更简单,然后是在电脑虚拟机的ubuntu中进行设计和测试,成功之后直接将项目移植到板端即可,这里是因为开发板能直接运行qt,所以可以直接移植项目,如果板端不能直接运行qt的话,就参考正点原子的交叉编译,最好是使用他官方的开发板。

本文使用的是onenet平台的多协议接入,目前对于新用户已经没有这个功能了,然后老用户之前没创建产品的话,现在也创建不了了,所以本篇文章仅给使用多协议接入的小伙伴参考,新版onenet的接入也已经实现,可以到这篇文章参考。


由于本文的目的主要是在linux下实现双向通信和QT练习,所以没有真的连接温湿度传感器等外设。最终现象如下视频所示:

本文中开发板端称为下位机,微信小程序称为上位机,ONENET云平台称为服务器。


环境:
ubuntu20.04
QT5
旭日x3派
微信开发者工具


一、QT界面设计

虚拟机端的QT5安装,直接网上搜,有很多,一般用命令行安装比较快。
这里直接使用视频的方式来简单展示搭建的过程,主要包括:添加资源文件qrc,添加qss样式表,界面设计等。

视频中用到的qss样式表代码参考如下,都给出了注释很好理解:
①QRadiobutton

QRadioButton::indicator{     //设置点击区域的长和宽
	width:45px;
	height:30px;
}
QRadioButton::indicator:unchecked{     //设置未点击时的显示图像
    image: url(:/images/switch_off.png);
}
QRadioButton::indicator:checked{    //设置点击时的显示图像
    image: url(:/images/switch_on.png);
}

②QWidget

QWidget#widget {              // #特指某个对象,从右上角的类和对象中可以看当前选中的是哪个对象。
    background-color:rgb(150, 150, 150);        //背景颜色
    background-image: url(:/images/light.png);    //背景图片
    background-repeat: no-repeat;    //表示不要应用到子对象上,不设置的话开关里面也会添加一张背景图片
    background-position: top left;   //显示到左上角
	border-radius: 18px;    //边框圆角
}

视频中用到的图像,可以到阿里巴巴矢量图标库中找到,下载png图像即可,然后最好将图像大小重新设置成60*60,不然就有问题:
在这里插入图片描述
ps:这里最后设计成自己喜欢的样子就可以了,当然可以不参考我的设计,如果只对通信感兴趣的直接往后看就好了,本文的重点也是在双向通信上。

二、云平台产品创建与连接

1、云平台产品创建

前言中已经提到了多协议接入的问题,这里不再赘述,使用最新物联网组件的小伙伴可以评论区讨论,我看了官方文档的http接入,只看到了数据上传,没有看到获取指令或者数据的部分,是不是新版的onenet中http不支持双向了呢?MQTT协议好像还是和之前差不多的,只是不再是以前的三元组了。

2、云平台连接测试
这部分可以直接参考正点原子的视频,写一个tcp客户端,就可以正常连接云平台了,注意连接的ONENET云平台的IP地址是:183.230.40.33,端口号是:80。
建议直接跟着视频写一下:TCP客户端程序编写,主要是防止后续代码看不懂。

三、下位机端QT代码总览:

mainwindow.h:

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QRadioButton>
#include <QDebug>
#include <QTimer>
//日期时间
#include <QDateTimeEdit>
#include <QTimeEdit>
#include <QDateEdit>
//tcp客户端通过http协议连接云服务器
#include <QTcpSocket>
#include <QJsonObject>
#include <QByteArray>
#include <QJsonDocument>
#include "QHostAddress"
#include <QJsonArray>
#include <QJsonValue>

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

    bool deng_flag = 0;
    int last_mainkongtiaoValue;

    const char *str[4] = {"POST /devices/1188390993/datapoints HTTP/1.1",
                    "api-key:=4T1J3khTpmZO99YYNDHvM5EZiI=",
                    "Host:api.heclouds.com",
                    ""};
    QString getbtnRequest = "GET /devices/1188390993/datastreams/ HTTP/1.1\r\napi-key:=4T1J3khTpmZO99YYNDHvM5EZiI=\r\nHost:api.heclouds.com\r\n\r\n" ;

private:
    Ui::MainWindow *ui;

    QDateTimeEdit *dateTimeEdit;
    QTimer *timer;

    QTcpSocket *tcpsocket;

private slots:
    void onRadioButtonToggled(bool checked);//五个radiobutton
    void onRadioButton2Toggled(bool checked);
    void onRadioButton3Toggled(bool checked);
    void onRadioButton4Toggled(bool checked);
    void onRadioButton5Toggled(bool checked);

    void updateDateTimeEdit();//刷新日期时间,上传数据至云服务器

    void receiveMessage();//tcp相关
    void mStateChange(QAbstractSocket::SocketState);
    void on_pushButton_clicked();
    void on_pushButton_2_clicked();

};
#endif // MAINWINDOW_H

mainwindow.cpp:

#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    //tcp客户端通过http连接云服务器
    this->setWindowTitle("智能家居");
    tcpsocket = new QTcpSocket(this);
    connect(tcpsocket, SIGNAL(readyRead()), this, SLOT(receiveMessage()));
    connect(tcpsocket, SIGNAL(stateChanged(QAbstractSocket::SocketState)),
            this, SLOT(mStateChange(QAbstractSocket::SocketState)));
    connect(ui->pushButton,SIGNAL(clicked()),this,SLOT(on_pushButton_clicked()));
    connect(ui->pushButton_2,SIGNAL(clicked()),this,SLOT(on_pushButton_2_clicked()));

    //显示当前的时间和日期
    dateTimeEdit = new QDateTimeEdit(QDateTime::currentDateTime(),this);
    dateTimeEdit->setGeometry(50,400, 200, 40);
    timer = new QTimer(this);
    connect(timer, &QTimer::timeout, this, &MainWindow::updateDateTimeEdit);
    timer->start(1000);

    //下面是按钮对应的信号与槽连接
    connect(ui->radioButton,SIGNAL(toggled(bool)), this, SLOT(onRadioButtonToggled(bool)));
    connect(ui->radioButton_2,SIGNAL(toggled(bool)), this, SLOT(onRadioButton2Toggled(bool)));
    connect(ui->radioButton_3,SIGNAL(toggled(bool)), this, SLOT(onRadioButton3Toggled(bool)));
    connect(ui->radioButton_4,SIGNAL(toggled(bool)), this, SLOT(onRadioButton4Toggled(bool)));
    connect(ui->radioButton_5,SIGNAL(toggled(bool)), this, SLOT(onRadioButton5Toggled(bool)));
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::receiveMessage()
{
    QString response = tcpsocket->readAll();
    qDebug() << "接收到服务器下发消息" << endl;

    // 提取 JSON 部分
    int jsonStartIndex = response.indexOf('{');
    QString jsonString = response.mid(jsonStartIndex);

    // 解析 JSON
    QJsonDocument jsonResponse = QJsonDocument::fromJson(jsonString.toUtf8());
    QJsonObject jsonObject = jsonResponse.object();

    QJsonArray dataArray = jsonObject["data"].toArray();
    for (const QJsonValue &value : dataArray)
    {
        QJsonObject obj = value.toObject();
        if (obj["id"].toString() == "led_ctl")
        {
            int ledCtlValue = obj["current_value"].toInt();
            //qDebug() << "LED Control Value:" << ledCtlValue;
            // 可以在这里处理 ledCtlValue,如更新 UI 显示
            if(ledCtlValue == 0)
            {
                ui->textBrowser->append("手机控制关闭客厅灯");
                ui->radioButton->setText("客厅灯|离线");
                ui->radioButton->setChecked(0);
            }
            else if(ledCtlValue == 1)
            {
                ui->textBrowser->append("手机控制打开客厅灯");
                ui->radioButton->setText("客厅灯|在线");
                ui->radioButton->setChecked(1);
            }
        }
        else if (obj["id"].toString() == "mainroom_kongtiao")
        {
            int mainkongtiaoValue = obj["current_value"].toInt();
                bool ischecked = ui->radioButton_3->isChecked();
                if((ischecked == 1) && (mainkongtiaoValue ==0))
                {
                    ui->textBrowser->append("手机控制关闭主卧空调");
                    ui->radioButton_3->setText("空调|离线");
                    ui->radioButton_3->setChecked(0);
                }
                else if((ischecked == 0) && (mainkongtiaoValue ==1))
                {
                    ui->textBrowser->append("手机控制打开主卧空调");
                    ui->radioButton_3->setText("空调|在线");
                    ui->radioButton_3->setChecked(1);
                }
        }
    }
}

void MainWindow::mStateChange(QAbstractSocket::SocketState state)
{
    switch (state) {
    case QAbstractSocket::UnconnectedState:
        ui->textBrowser->append("因某种原因与服务端连接断开,尝试重连");
        qDebug() << "因某种原因与服务端连接断开,尝试重连" << endl;
        tcpsocket->connectToHost(QHostAddress("183.230.40.33"),80);
        ui->pushButton->setEnabled(true);
        ui->pushButton_2->setEnabled(false);
        break;
    case QAbstractSocket::ConnectedState:
        qDebug() << "已连接服务器" << endl;
        ui->textBrowser->append("已连接服务端");
        ui->pushButton->setEnabled(false);
        ui->pushButton_2->setEnabled(true);
        break;
    default:
        break;
    }
}

//开启关闭客厅灯
void MainWindow::onRadioButtonToggled(bool checked)
{
    if (checked) {
        ui->radioButton->setText("客厅灯|在线");
        //deng_flag = 1;
        qDebug() << "客厅灯打开" << endl;

    } else {
        ui->radioButton->setText("客厅灯|离线");
        //deng_flag = 0;
        qDebug() << "客厅灯关闭" << endl;
    }
}

//场景选择:居家
void MainWindow::onRadioButton2Toggled(bool checked)
{
    if (checked) {
        qDebug() << "居家模式已打开" << endl;
    } else {
        qDebug() << "居家模式已关闭" << endl;
    }
}

//开启关闭主卧空调
void MainWindow::onRadioButton3Toggled(bool checked)
{
    if (checked) {
        ui->radioButton_3->setText("空调|在线");
        qDebug() << "主卧空调打开" << endl;
    } else {
        ui->radioButton_3->setText("空调|离线");
        qDebug() << "主卧空调关闭" << endl;
    }
}

//场景选择:暂时出门
void MainWindow::onRadioButton4Toggled(bool checked)
{
    if (checked) {
        //ui->radioButton_3->setForegroundRole();
        qDebug() << "暂时出门模式已打开" << endl;
    } else {
        //ui->radioButton_3->setText("空调|离线");
        qDebug() << "暂时出门模式已关闭" << endl;
    }
}


//场景选择:出远门
void MainWindow::onRadioButton5Toggled(bool checked)
{
    if (checked) {
        qDebug() << "出远门模式已打开" << endl;
    } else {
        qDebug() << "出远门模式已关闭" << endl;
    }
}

void MainWindow::on_pushButton_clicked()
{
    tcpsocket->connectToHost(QHostAddress("183.230.40.33"),80);
}

void MainWindow::on_pushButton_2_clicked()
{
    tcpsocket->disconnectFromHost();
}

//定时器刷新时间、上传数据至服务器、刷新本地显示数据
void MainWindow::updateDateTimeEdit() {
    static int flag = 0;

    dateTimeEdit->setDateTime(QDateTime::currentDateTime());

    //请求设备数据,这里会读回来所有的数据,比如温适度和数据流模板
    QByteArray getbtnRequestBytes = getbtnRequest.toUtf8();
    if(tcpsocket->state() == QAbstractSocket::ConnectedState) {
        tcpsocket->write(getbtnRequestBytes);
        //qDebug() << "请求已发送" << endl;;
    } else {
        ui->textBrowser->append("请先连接服务端");
        //qDebug() << "请先连接服务器" << endl;;
    }


    if(flag == 10)
   {
        ui->label_6->setText("14度");
        ui->label_8->setText("70");
        ui->label_10->setText("9.7 ppm");

        QJsonObject postData;
        postData["temp"] = 14;
        postData["humi"] = 70;

        QJsonDocument jsonDoc(postData);
        QByteArray jsonData = jsonDoc.toJson(QJsonDocument::Compact);

        // 计算请求体的长度
        int contentLength = jsonData.size();

        // 构建HTTP请求
        QString httpRequestString =
            "POST /devices/1188390993/datapoints?type=3 HTTP/1.1\r\n"
            "api-key:=4T1J3khTpmZO99YYNDHvM5EZiI=\r\n"  // 请注意api-key的值需要是您的实际API密钥
            "Host: api.heclouds.com\r\n"
            "Content-Length: " + QString::number(contentLength) + "\r\n"  // 设置正确的内容长度
            "\r\n"  // 请求头和请求体之间的空行
            + QString(jsonData)  // 添加JSON请求体
        ;
        QByteArray httpRequest(httpRequestString.toUtf8());

        if(tcpsocket->state() == QAbstractSocket::ConnectedState) {
            tcpsocket->write(httpRequest);
            qDebug() << "请求已发送" << endl;
        } else {
            ui->textBrowser->append("请先连接服务端");
            //qDebug() << "请先连接服务器" << endl;;
        }
        flag = 0;
    }
    flag++;
}


只要简单学过QT,上述的代码都能看懂,并不是直接复制就能用,如果自己画的ui界面和我的不一样,那就要改代码,有兴趣的可以私聊拿原项目。

四、微信小程序端代码总览

有用的目录格式如下:
在这里插入图片描述
各部分的代码如下,注意只测试了温度和湿度,其他的想加很简单(微信小程序直接使用的b站up的代码:彼岸有光我们有船):
index.js:

Page({
    data: {
     temp:0
    },
    // 事件处理函数
    getinfo(){
      var that = this
      wx.request({
      url: "https://api.heclouds.com/devices/1188390993/datapoints",   
      //将请求行中的数字换成自己的设备ID
      header: {
    
        "api-key": "=4T1J3khTpmZO99YYNDHvM5EZiI="
      },
      method: "GET",
      success: function (e) {
        console.log("获取成功",e)
        that.setData({
          temp:e.data.data.datastreams[0].datapoints[0].value,
          humi:e.data.data.datastreams[2].datapoints[0].value,
        })
        console.log("temp==",that.data.temp),
        console.log("humi==",that.data.humi)
      }
     });
    },


kai:function(){
  let data={
  "datastreams": [  
  {"id": "led_ctl","datapoints":[{"value": 1}]},
  //led是数据流的名称,value是要传上去的数值
      ]	
  }
 //按钮发送命令控制硬件
  wx.request({
    url:'https://api.heclouds.com/devices/1188390993/datapoints',
    header: {
      'content-type': 'application/json',
      'api-key':'=4T1J3khTpmZO99YYNDHvM5EZiI='
    },
    method: 'POST',
    data: JSON.stringify(data),//data数据转换成JSON格式
    success(res){
      console.log("成功",res.data)
    },
    fail(res){
      console.log("失败",res)
    }
  })
},

guan:function(){
  let data={
  "datastreams": [  
  {"id": "led_ctl","datapoints":[{"value": 0}]},
  //led是数据流的名称,value是要传上去的数值
      ]	
  }
 //按钮发送命令控制硬件
  wx.request({
    url:'https://api.heclouds.com/devices/1188390993/datapoints',
    header: {
      'content-type': 'application/json',
      'api-key':'=4T1J3khTpmZO99YYNDHvM5EZiI='
    },
    method: 'POST',
    data: JSON.stringify(data),//data数据转换成JSON格式
    success(res){
      console.log("成功",res.data)
    },
    fail(res){
      console.log("失败",res)
    }
  })
},

kaikong:function(){
  let data={
  "datastreams": [  
  {"id": "mainroom_kongtiao","datapoints":[{"value": 1}]},
  //led是数据流的名称,value是要传上去的数值
      ]	
  }
 //按钮发送命令控制硬件
  wx.request({
    url:'https://api.heclouds.com/devices/1188390993/datapoints',
    header: {
      'content-type': 'application/json',
      'api-key':'=4T1J3khTpmZO99YYNDHvM5EZiI='
    },
    method: 'POST',
    data: JSON.stringify(data),//data数据转换成JSON格式
    success(res){
      console.log("成功",res.data)
    },
    fail(res){
      console.log("失败",res)
    }
  })
},

guankong:function(){
  let data={
  "datastreams": [  
  {"id": "mainroom_kongtiao","datapoints":[{"value": 0}]},
  //led是数据流的名称,value是要传上去的数值
      ]	
  }
 //按钮发送命令控制硬件
  wx.request({
    url:'https://api.heclouds.com/devices/1188390993/datapoints',
    header: {
      'content-type': 'application/json',
      'api-key':'=4T1J3khTpmZO99YYNDHvM5EZiI='
    },
    method: 'POST',
    data: JSON.stringify(data),//data数据转换成JSON格式
    success(res){
      console.log("成功",res.data)
    },
    fail(res){
      console.log("失败",res)
    }
  })
},


    onLoad() {
      var that = this
      setInterval(function(){
        that.getinfo()
      },5000)
    }
  })

index.wxml:

<view class="userinfo">
 <image class="img" src="../images/温度 .png"></image>
 <text>温度:{{temp}}℃</text> 
</view>

<view class="userinfo">
 <image class="img" src="../images/湿度.png"></image>
 <text>湿度:{{humi}}%</text> 
</view>

<view class="userinfo">
 <image class="img" src="../images/甲烷.png"></image>
 <text>天然气:{{gas_ch4}}PPM</text> 
</view>

<view class="userinfo">
 <image class="img" src="../images/可燃气体.png"></image>
 <text>可燃气体:{{ranqi}}PPM</text> 
</view>

<button type="primary" style="margin-top: 20px;" bindtap="kai">开灯</button>
<button type="warn" bindtap="guan">关灯</button>

<button type="primary" style="margin-top: 20px;" bindtap="kaikong">开主卧空调</button>
<button type="warn" bindtap="guankong">关主卧空调</button>

index.wxss:

/**index.wxss**/
.userinfo {
  display: flex;
  flex-direction: column;
  align-items: center;
  color: rgb(141, 10, 10);
  font-size: 15px;
}

.img {
  width: 100rpx;
  height: 100rpx;
}

.usermotto {
  margin-top: 200px;
}

index.json:

{
  "usingComponents": {}
}

也是非常简单,比起qt还要更简单,简单看看就能看懂。愉快的测试即可。

五、板端测试

虚拟机端代码跑通之后其实就可以到板子上跑了。直接远程登录开发板,然后安装QT5:

sudo apt-get install qt5-default qt5-qmake qtcreator

随后将项目拷贝至任意目录下,打开qtcreator,然后打开项目,即可运行。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2053086.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

用时间序列数据画蜡烛图

数据集&#xff1a;时间序列数据集&#xff08;2024.8.16收集&#xff09;-修改date资源-CSDN文库 示例一 import pandas as pd import mplfinance as mpf# 读取CSV文件 df pd.read_csv(999999_dcolhchg.csv)# 将日期列加上19000000&#xff0c;然后转换为日期格式 df[date]…

Jmeter系列之作用域、执行顺序

这一节主要解释元件作用域和执行顺序&#xff0c;以及整理之前说过的参数化的方式。 作用域 之前也留下了一个问题。怎么给不同的请求设置不同的Header&#xff1f;后续也透露了可以使用Sample Controller&#xff0c;结合元件的作用域来实现 在Jmeter中&#xff0c;元件的作…

轻松搞定由于找不到msvcr120.dll,无法继续执行代码的问题,总结五种msvcr120.dll丢失修复方法

当您在使用基于Windows的系统运行软件或游戏时&#xff0c;可能会遇到如下错误提示&#xff1a;“由于找不到 msvcr120.dll&#xff0c;无法继续执行代码”。这个问题表明您的系统缺少 Microsoft Visual C Redistributable Packages for Visual Studio 2013 中的一个关键组件&a…

【LeetCode Cookbook(C++ 描述)】一刷二叉树综合(下)

目录 LeetCode #257&#xff1a;Binary Tree Paths 二叉树的所有路径深度优先搜索广度优先搜索 LeetCode #404&#xff1a;Sum of Left Leaves 左叶子之和深度优先搜索广度优先搜索 LeetCode #199&#xff1a;Binary Tree Right Side View 二叉树的右视图广度优先搜索深度优先搜…

单体应用spring Task和分布式调度

Spring Task 1.通过 Spring Task&#xff0c;您可以方便地在 Java 应用程序中实现定时任务&#xff0c;比如每天凌晨进行数据同步、每小时执行一次清理操作等。 2.1 启动类添加EnableScheduling注解(默认情况下&#xff0c;系统会自动启动一个线程) 2.2 在需要定时执行的方…

解决 Swift 6 全局变量不能满足并发安全(concurrency-safe)读写的问题

概述 WWDC 24 终于在 Swift 十岁生日发布了全新的 Swift 6。这不仅意味着 Swift 进入了全新的“大”版本时代&#xff0c;而且 Swift 编译器终于做到了并发代码执行的“绝对安全”。 不过&#xff0c;从 Swift 5 一步迈入“新时代”的小伙伴们可能对新的并发检查有些许“水土不…

连锁美业门店收银系统拓客系统预约系统Java源码-博弈美业APP如何进行课程核销?

* 课程开课后&#xff0c;到课程结束前&#xff0c;这段时间均可以进行课程核销 * 课程核销的权限&#xff0c;仅限内部员工 * 核销课程时&#xff0c;需要切换到总部&#xff0c;才有核销课程的权限 方法一&#xff1a;通过“课程核销”直接核销 点击“课程核销”&#xff…

强大的接口测试可视化工具:Postman Flows

Postman Flows是一种接口测试可视化工具&#xff0c;可以使用流的形式在Postman工作台将请求接口、数据处理和创建实际流程整合到一起。如下图所示 Postman Flows是以API为中心的可视化应用程序开发界面。它提供了一个无限的画布用于编排和串连API&#xff0c;数据可视化来显示…

[C#]winform基于深度学习算法MVANet部署高精度二分类图像分割onnx模型高精度图像二值化

【训练源码】 https://github.com/qianyu-dlut/MVANet 【参考源码】 https://github.com/hpc203/MVANet-onnxrun 【算法介绍】 二分图像分割&#xff08;DIS&#xff09;最近出现在从高分辨率自然图像中进行高精度对象分割方面。在设计有效的DIS模型时&#xff0c;主要的挑战是…

XMGoat:一款针对Azure的环境安全检测工具

关于XMGoat XMGoat是一款针对Azure的环境安全检测工具&#xff0c;XM Goat 由 XM Cyber Terraform 模板组成&#xff0c;可帮助您了解常见的 Azure 安全问题。每个模板都是一个用于安全技术学习的靶机环境&#xff0c;包含了一些严重的配置错误。 在该工具的帮助下&#xff0c…

景区门票预订系统开发方案概述

随着旅游业的蓬勃发展&#xff0c;提升游客体验、优化景区管理成为了各大景区亟待解决的问题。景区门票预订系统的开发&#xff0c;正是顺应这一趋势的重要举措。以下是一个简要的景区门票预订系统开发方案概述&#xff0c;旨在通过科技手段实现票务管理的智能化、便捷化。 一、…

faiss向量数据库测试《三体》全集,这家国产AI加速卡,把性能提了7倍!

在人工智能和机器学习技术的飞速发展中&#xff0c;向量数据库在处理高维数据方面扮演着日益重要的角色。近年来&#xff0c;随着大型模型的流行&#xff0c;向量数据库技术也得到了进一步的发展和完善。 向量数据库为大型模型提供了一个高效的数据管理和检索平台&#xff0c;…

如何将音乐保存为文件格式为铃声,怎么把音乐保存为MP3格式

许多小伙伴在听到好听的音乐时&#xff0c;会将其下载保存。如果需要将音乐文件格式转换成来电铃声时&#xff0c;就需要借助专业的音频处理软件了&#xff0c;音频处理软件可以帮助我们转化音乐文件格式&#xff0c;那么下面就来给大家介绍如何将音乐保存为文件格式为铃声&…

Kali Linux-设置系统24小时时间制

文章目录 设置系统24小时时间制 设置系统24小时时间制 在Kali Linux中&#xff0c;如果系统时间不是以24小时制显示&#xff0c;你可以通过修改系统时间格式配置文件来调整为24小时制。以下是具体的操作步骤&#xff1a; 1.编辑/etc/locale.conf配置文件。 vim /etc/locale.c…

【gitlab】gitlab-ce:17.3.0-ce.0 之2:配置

参考阿里云的教程docker的重启 sudo systemctl daemon-reload sudo systemctl restart docker配置 –publish 8443:443 --publish 8084:80 --publish 22:22 sudo docker ps -a 當容器狀態為healthy時,說明GitLab容器已經正常啟動。 root@k8s-master-pfsrv:~

Python WebSocket自动化测试:构建高效接口测试框架

为了更高效地进行WebSocket接口的自动化测试&#xff0c;我们可以搭建一个专门的测试框架。本文将介绍如何使用Python构建一个高效的WebSocket接口测试框架&#xff0c;并重点关注以下四个方面的内容&#xff1a;运行测试文件封装、报告和日志的封装、数据驱动测试以及测试用例…

调查显示:超过30 %企业遭受过网络攻击,如何防范?

对于企业来讲&#xff0c;屡禁不止的网络安全攻击始终是阻碍业务发展的重大隐患。调查结果显示&#xff0c;有近8成的企业将网络安全视为企业很重要的工作之一&#xff0c;另外&#xff0c;有超过三成的企业遭受过网络安全攻击。 企业作为网络安全事故的责任承担方&#xff0c;…

synchronized和Lock(ReentrantLock)及二者区别

synchronized 是用于实现线程同步的关键字。它提供了两种主要的方式来保证多个线程访问共享资源时的互斥性和可见性&#xff1a;同步块和同步方法。 同步块 同步块允许你指定一个对象作为锁&#xff0c;并保护一段代码区域。这样&#xff0c;同一时刻只有一个线程可以执行这…

ChatGPT 为什么不建议关闭 MySQL 严格模式?

社区王牌专栏《一问一实验&#xff1a;AI 版》全新改版归来&#xff0c;得到了新老读者们的关注。其中不乏对 ChatDBA 感兴趣的读者前来咨询&#xff0c;表达了想试用体验 ChatDBA 的意愿&#xff0c;对此我们表示感谢 &#x1f91f;。 目前&#xff0c;ChatDBA 还在最后的准备…

记录一次 npm ERR! cb() never called! 解决过程

gitlab cicd过程&#xff0c;使用docker部署Vue3前端项目&#xff0c;报错如下&#xff1a; 针对 npm ERR! cb() never called! 这个报错&#xff0c;网上有很多解决方案&#xff0c;大都是清空缓存&#xff0c;重新运行npm 之类的。笔者全都试过&#xff0c;无法解决问题。笔者…