海康威视-NVR使用及ISAPI协议透传接入

news2025/7/19 1:17:14

目录

1、初始化配置

1.1、设置通道默认密码

1.2、添加摄像头

1.3、设置不采集时间段

1.4、抓拍延迟设置

1.5、录像保存时长设置

1.6、人脸库维护

1.7、导入照片

1.8、设置事件

1.8.1、引擎配置

1.8.2、事件设置

1.8.2.1、目标比对

1.8.2.2、设置屏蔽区

1.8.2.3、人脸库

1.9、事件检索

2、ISAPI透传对接

2.1、下载SDK包

2.2、检查是否支持ISAPI

2.3、引入依赖

2.4、启动demo

3、java端接入

3.1、项目结构

3.2、类属性定义

3.3、初始化 

3.4、登录

3.5、发起ISAPI调用

3.6、入参对象

3.7、出参对象


背景说明:

使用NVR网络录像机接入监控摄像头,NVR内置人脸库、人脸抓拍、比对功能、事件配置。

使用的设备型号:DS-9632NX-I8R/VPro

1、初始化配置

1.1、设置通道默认密码

1.2、添加摄像头

NVR具有自动广播功能,可以在下方的设备列表中显示所有摄像头。

然后选中添加上上方列表,开启监控。

注意勾选默认密码,否则会引起连接失败问题

1.3、设置不采集时间段

下图灰白区域表示摄像头不采集、不启用事件的事件范围,

选择一个摄像头进行配置

批量复制到其他监控

1.4、抓拍延迟设置

此处设置的开头、结尾延迟5秒,为后续的人物目标识别成功后,截取视频时间段前后五秒,共10秒的视频。默认延迟30s

1.5、录像保存时长设置

1.6、人脸库维护

1.7、导入照片

由于nvr限定jpg、jpeg类型,不支持png,所以需要进行转码

具体参见 Java工具-实现无损png转换jpg格式-CSDN博客

1.8、设置事件

1.8.1、引擎配置

必须要设置目标识别,否则人脸库无法建模,后续人脸目标比对无法进行。

1.8.2、事件设置

选择目标事件,确定必须启用

1.8.2.1、目标比对

选择目标比对,开启,

1.8.2.2、设置屏蔽区

点击右键绘图完毕

1.8.2.3、人脸库

关联人脸库和阈值设置

如果需要提高图片质量,可以设置仰俯角,避免低头、偏头图片

1.9、事件检索

在下图,设置检索条件

2、ISAPI透传对接

2.1、下载SDK包

地址:海康开放平台

下载对应操作系统的开发包

2.2、检查是否支持ISAPI

注意检查默认登录端口8000

选择内部的ISAPI透传的demo

2.3、引入依赖

将对应的库文件引入到项目的lib下

3. Windows开发时需要
将“库文件”文件夹中的HCNetSDK.dll、HCCore.dll、HCNetSDKCom文件夹、
libssl-1_1-x64.dll、libcrypto-1_1-x64.dll、hlog.dll、hpr.dll、zlib1.dll等文件拷贝到lib文件夹下,
HCNetSDKCom文件夹(包含里面的功能组件dll库文件)需要和HCNetSDK.dll、HCCore.dll一起加载,放在同一个目录下,
且HCNetSDKCom文件夹名不能修改。如果自行开发软件不能正常实现相应功能,而且程序没有指定加载的dll库路径,
请在程序运行的情况下尝试删除HCNetSDK.dll。如果可以删除,说明程序可能调用到系统盘Windows->System32目录下的dll文件,
建议删除或者更新该目录下的相关dll文件;如果不能删除,dll文件右键选择属性确认SDK库版本。

4. Linux开发时需要将“库文件”文件夹中libhcnetsdk.so、libHCCore.so、libcrypto.so.1.1、libssl.so.1.1、libhpr.so、libz.so
等文件拷贝到lib文件夹下。HCNetSDKCom文件夹(包含里面的功能组件dll库文件)需要和libhcnetsdk.so、libHCCore.so
一起加载,放在同一个目录下,且HCNetSDKCom文件夹名不能修改。如果库文件加载有问题,初始化失败,
也可以尝试将SDK所在路径添加到LD_LIBRARY_PATH环境变量中。

2.4、启动demo

启动类 JavaDemoSTDXMLConfigApp

启动后效果,使用这个demo可以进行api调试。

后续可以参照平台的接口出入参进行对接开发

3、java端接入

3.1、项目结构

win下存放dll文件,需要额外引入 sdk中的examples.jar、jna.jar文件

其中 HIKSDKStructure 类用于解决兼容低版本的Structure调用问题

import com.sun.jna.Structure;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.List;

/***
 * 由于 这个问题是因为海康jna.jar比较老,结构体定义没有getFiledOrder,可创建一个类继承 Structure
 * 产生错误:Structure.getFieldOrder() on class com.xxx.sdk.HCNetSDK$NET_DVR_DEVICEINFO_V30 does not provide enough names [0] ([]) to match declared fields [31] ([byAlarmInPortNum,
 * 解决:对 HCNetSDK 接口中的静态类里面,所有继承 Structure 替换为 HIKSDKStructure 即可
 * @author xuancg
 * @date 2024/6/13
 */
public class HIKSDKStructure extends Structure {
    protected List<String> getFieldOrder(){
        List<String> fieldOrderList = new ArrayList<String>();
        for (Class<?> cls = getClass();
             !cls.equals(HIKSDKStructure.class);
             cls = cls.getSuperclass()) {
            Field[] fields = cls.getDeclaredFields();
            int modifiers;
            for (Field field : fields) {
                modifiers = field.getModifiers();
                if (Modifier.isStatic(modifiers) || !Modifier.isPublic(modifiers)) {
                    continue;
                }
                fieldOrderList.add(field.getName());
            }
        }
        return fieldOrderList;
    }
}

HCNetSDK 类可以通过sdk中查找引入。但需要将所有的Structure 替换为HIKSDKStructure

public class OsSelect {

    public static boolean isLinux() {
        return System.getProperty("os.name").toLowerCase().contains("linux");
    }

    public static boolean isWindows() {
        return System.getProperty("os.name").toLowerCase().contains("windows");
    }
}

3.2、类属性定义

static HCNetSDK hCNetSDK = null;
    static int lUserID;//用户句柄

    private static String rootPath;

    public static final int ISAPI_DATA_LEN = 1024*1024;
    public static final int ISAPI_STATUS_LEN = 4*4096;
    public static final int BYTE_ARRAY_LEN = 1024;

3.3、初始化 

public static boolean init(){
        if(null == rootPath){
            rootPath = System.getProperty("user.dir");
             //由于我是多模块下的,此处路径存在问题,实际最好通过外部配置定义
            rootPath += "/my-project";
        }
        log.info("加载lib路径=" + rootPath);
        if (hCNetSDK == null) {
            if (!createSDKInstance()) {
                System.out.println("Load SDK fail");
                return false;
            }
        }
        //linux系统建议调用以下接口加载组件库
        if (OsSelect.isLinux()) {
            HCNetSDK.BYTE_ARRAY ptrByteArray1 = new HCNetSDK.BYTE_ARRAY(256);
            HCNetSDK.BYTE_ARRAY ptrByteArray2 = new HCNetSDK.BYTE_ARRAY(256);

            // TODO 需要下载对应linux版本 并替换
            //这里是库的绝对路径,请根据实际情况修改,注意改路径必须有访问权限
            String strPath1 = rootPath + "/libs/libcrypto.so.1.1";
            String strPath2 = rootPath + "/libs/libssl.so.1.1";

            System.arraycopy(strPath1.getBytes(), 0, ptrByteArray1.byValue, 0, strPath1.length());
            ptrByteArray1.write();
            hCNetSDK.NET_DVR_SetSDKInitCfg(3, ptrByteArray1.getPointer());

            System.arraycopy(strPath2.getBytes(), 0, ptrByteArray2.byValue, 0, strPath2.length());
            ptrByteArray2.write();
            hCNetSDK.NET_DVR_SetSDKInitCfg(4, ptrByteArray2.getPointer());

            String strPathCom = rootPath + "/libs/";
            HCNetSDK.NET_DVR_LOCAL_SDK_PATH struComPath = new HCNetSDK.NET_DVR_LOCAL_SDK_PATH();
            System.arraycopy(strPathCom.getBytes(), 0, struComPath.sPath, 0, strPathCom.length());
            struComPath.write();
            hCNetSDK.NET_DVR_SetSDKInitCfg(2, struComPath.getPointer());
        }

        boolean initSuc = hCNetSDK.NET_DVR_Init();
        if (initSuc != true)
        {
            log.info("初始化失败");
        }
        /**加载日志*/
        return  hCNetSDK.NET_DVR_SetLogToFile(3, "./sdklog", false);
    }


private static boolean createSDKInstance() {
        if (hCNetSDK == null) {
            synchronized (HCNetSDK.class) {
                String strDllPath = "";
                try {
                    if (OsSelect.isWindows())
                        //win系统加载SDK库路径
                        strDllPath = rootPath + "\\libs\\win\\HCNetSDK.dll";

                    else if (OsSelect.isLinux())
                        //Linux系统加载SDK库路径
                        strDllPath = rootPath + "/libs/linux/libhcnetsdk.so";
                    hCNetSDK = (HCNetSDK) Native.loadLibrary(strDllPath, HCNetSDK.class);
                } catch (Exception ex) {
                    System.out.println("loadLibrary: " + strDllPath + " Error: " + ex.getMessage());
                    return false;
                }
            }
        }
        return true;
    }

3.4、登录

/**
     * 登录,端口默认8000,成功后会将其他终端登录下线
     * @param sDeviceIP ip地址
     * @param sUsername 登录名
     * @param sPassword 密码
     */
    public static boolean loginByV40(String sDeviceIP,String sUsername,String sPassword){
        //注册之前先注销已注册的用户,预览情况下不可注销
        if (lUserID > -1) {
            //先注销
            hCNetSDK.NET_DVR_Logout(lUserID);
            lUserID = -1;
        }

        //注册
        HCNetSDK.NET_DVR_USER_LOGIN_INFO m_strLoginInfo = new HCNetSDK.NET_DVR_USER_LOGIN_INFO();//设备登录信息
        HCNetSDK.NET_DVR_DEVICEINFO_V40 m_strDeviceInfo = new HCNetSDK.NET_DVR_DEVICEINFO_V40();//设备信息


        m_strLoginInfo.sDeviceAddress = new byte[HCNetSDK.NET_DVR_DEV_ADDRESS_MAX_LEN];
        System.arraycopy(sDeviceIP.getBytes(), 0, m_strLoginInfo.sDeviceAddress, 0, sDeviceIP.length());

        m_strLoginInfo.sUserName = new byte[HCNetSDK.NET_DVR_LOGIN_USERNAME_MAX_LEN];
        System.arraycopy(sUsername.getBytes(), 0, m_strLoginInfo.sUserName, 0, sUsername.length());

        m_strLoginInfo.sPassword = new byte[HCNetSDK.NET_DVR_LOGIN_PASSWD_MAX_LEN];
        System.arraycopy(sPassword.getBytes(), 0, m_strLoginInfo.sPassword, 0, sPassword.length());

        m_strLoginInfo.wPort = 8000;

        // 此处只能设置0,否则errcode=9
        m_strLoginInfo.byLoginMode = 0;
        //登录模式(不同模式具体含义详见“Remarks”说明):0- SDK私有协议,1- ISAPI协议,2- 自适应(设备支持协议类型未知时使用,一般不建议)
        m_strLoginInfo.byHttps = 0;
        //ISAPI协议登录时是否启用HTTPS(byLoginMode为1时有效):0- 不启用,1- 启用,2- 自适应(设备支持协议类型未知时使用,一般不建议)

        m_strLoginInfo.bUseAsynLogin = false; //是否异步登录:0- 否,1- 是

        m_strLoginInfo.write();
        lUserID = hCNetSDK.NET_DVR_Login_V40(m_strLoginInfo, m_strDeviceInfo);

        if (lUserID == -1) {
            // 9-从设备接收数据失败。
            log.info("注册失败,错误号:" + hCNetSDK.NET_DVR_GetLastError());
        } else {
            log.info("注册成功,lUserID=" + lUserID);
        }
        return true;
    }


// 登出
public void logout() {
        //注销
        if (lUserID > -1) {
            //先注销
            hCNetSDK.NET_DVR_Logout(lUserID);
            lUserID = -1;
        }
        hCNetSDK.NET_DVR_Cleanup();
    }

3.5、发起ISAPI调用

/**
     * 事件搜索
     * @param req
     * @return
     */
    public EventRecordSearchResp eventSearchApi(EventRecordSearchReq req) {
        HCNetSDK.NET_DVR_XML_CONFIG_INPUT struXMLInput = new HCNetSDK.NET_DVR_XML_CONFIG_INPUT();
        struXMLInput.read();
        struXMLInput.dwSize = struXMLInput.size();
        String strURL = "POST /ISAPI/ContentMgmt/eventRecordSearch?format=json";
        int iURLlen = strURL.length();
        HCNetSDK.BYTE_ARRAY ptrUrl = new HCNetSDK.BYTE_ARRAY(iURLlen+1);
        System.arraycopy(strURL.getBytes(), 0, ptrUrl.byValue, 0, strURL.length());
        ptrUrl.write();
        struXMLInput.lpRequestUrl = ptrUrl.getPointer();
        struXMLInput.dwRequestUrlLen = iURLlen;
        String strInbuffer = JSONUtil.toJsonStr(req);
        int iInBufLen = strInbuffer.length();
        if(iInBufLen==0)
        {
            struXMLInput.lpInBuffer=null;
            struXMLInput.dwInBufferSize=0;
            struXMLInput.write();
        }
        else
        {
            HCNetSDK.BYTE_ARRAY ptrInBuffer = new HCNetSDK.BYTE_ARRAY(iInBufLen+1);
            ptrInBuffer.read();
            ptrInBuffer.byValue = strInbuffer.getBytes();
            ptrInBuffer.write();

            struXMLInput.lpInBuffer = ptrInBuffer.getPointer();
            struXMLInput.dwInBufferSize = iInBufLen;
            struXMLInput.write();

        }
        HCNetSDK.BYTE_ARRAY ptrStatusByte = new HCNetSDK.BYTE_ARRAY(ISAPI_STATUS_LEN);
        ptrStatusByte.read();

        HCNetSDK.BYTE_ARRAY ptrOutByte = new HCNetSDK.BYTE_ARRAY(ISAPI_DATA_LEN);
        ptrOutByte.read();

        HCNetSDK.NET_DVR_XML_CONFIG_OUTPUT struXMLOutput = new HCNetSDK.NET_DVR_XML_CONFIG_OUTPUT();
        struXMLOutput.read();
        struXMLOutput.dwSize = struXMLOutput.size();
        struXMLOutput.lpOutBuffer = ptrOutByte.getPointer();
        struXMLOutput.dwOutBufferSize = ptrOutByte.size();
        struXMLOutput.lpStatusBuffer = ptrStatusByte.getPointer();
        struXMLOutput.dwStatusSize  = ptrStatusByte.size();
        struXMLOutput.write();

        if(!hCNetSDK.NET_DVR_STDXMLConfig(lUserID, struXMLInput, struXMLOutput))
        {
            int iErr = hCNetSDK.NET_DVR_GetLastError();
            log.error( "NET_DVR_STDXMLConfig失败,错误号:" + iErr);
            return null;

        }
        else
        {
            struXMLOutput.read();
            ptrOutByte.read();
            ptrStatusByte.read();
            // 输出结果
            String strOutXML = new String(ptrOutByte.byValue).trim();
            // 输出状态
            String strStatus = new String(ptrStatusByte.byValue).trim();
            return JSONUtil.toBean(strOutXML, EventRecordSearchResp.class);
        }
    }

3.6、入参对象



import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.Getter;

import java.util.UUID;

/***
 * 事件搜索入参
 * @author xuancg
 * @date 2024/6/14
 */
@Data
public class EventRecordSearchReq {

    private EventSearchDescription EventSearchDescription;

    public void setChannels(int...channels){
        this.EventSearchDescription.setChannels(channels);
    }

    public void setEventType(EventType type){
        this.EventSearchDescription.setEventType(type.name());
    }

    public void  setAlarmResult(AlarmResult type){
        this.EventSearchDescription.setAlarmResultAuxEventType(type.name());
    }

    public void setPageNum(int pageNum){
        this.EventSearchDescription.setMaxResults(pageNum);
    }

    /**
     * 默认从1开始
     * @param pageSize
     */
    public void setPageSize(int pageSize){
        int offset = (pageSize - 1) * this.EventSearchDescription.getMaxResults();
        if(offset < 0){
            offset = 0;
        }
        this.EventSearchDescription.setSearchResultPosition(offset);
    }


    @Data
    public class EventSearchDescription{

        public EventSearchDescription() {
            this.searchID = UUID.randomUUID().toString();
        }

        // 随机生成 搜索记录唯一标识, range:[,], desc:用来确认上层客户端是否为同一个(倘若是同一个,则设备记录内存,下次搜索加快速度)
        private String searchID;

        private String eventType;
        private String alarmResultAuxEventType;
        private int[] channels;
        // 每页个数
        private int maxResults = 30;
        // 起始位置相当于offset ,如果第二页则=30
        private int searchResultPosition = 0;

        private String type = "all";
    }

    @Data
    public class timeSpanList {
        // 格式 2024-06-14T23:59:59 08:00
        private String endTime;
        private String startTime;
    }

    /***
     * 检索类型
     */
    @Getter
    @AllArgsConstructor
    public enum EventType{
        alarmResult("目标事件"),
        ;
        private String desc;
    }

    @Getter
    @AllArgsConstructor
    public enum AlarmResult{
        alarmResultSuccess("目标比对成功"),
        ;
        private String desc;
    }

}

3.7、出参对象

import lombok.Data;
import java.util.List;

/***
 * 事件搜索出参
 * 日期格式均为=2024-06-13T11:39:00+08:00  东八区
 * @author xuancg
 * @date 2024/6/14
 */
@Data
public class EventRecordSearchResp {

    private EventSearchResult EventSearchResult;

    @Data
    public class EventSearchResult{

        /**搜索结果数*/
        private int numOfMatches;
        /**是否有更多结果 MORE=是*/
        private String responseStatusStrg;
        /**总结果数*/
        private int totalMatches;

        private List<Targets> Targets;

    }

    @Data
    public class Targets{
        /**抓拍时间*/
        private String alarmEndTime;
        private AlarmResult alarmResult;
        private String alarmResultAuxEventType;
        /**2024-06-13T11:39:00+08:00*/
        private String alarmStartTime;
        private int channel;
        private String eventType;
        private int id;
        private MetadataMatches metadataMatches;
        /**背景图地址http*/
        private String pictureUrl;
        /**人脸范围照地址http*/
        private String smallPictureUrl;
        /**前置后置延迟时间,单位秒 */
        private int postRecordTimeSeconds;
        private int preRecordTimeSeconds;
        /**视频采集开始时间  用于换取采集视频*/
        private String startTime;
        private String endTime;
        /**等同channel*/
        private int triggerChannel;
    }

    @Data
    public class AlarmResult{
        private String FDID;
        /**人脸库名称*/
        private String FDLibName;
        /**人脸库照片地址,http开头*/
        private String FDPicURL;
        private String ageGroup;
        private String gender;
        /**人物姓名*/
        private String name;
        /**相似度,小于1*/
        private float similarity;
    }

    @Data
    public class MetadataMatches{
        private List<AssociatedMetadata> associatedMetadataUrlList;
        private String eventType;
    }

    @Data
    public class AssociatedMetadata {
        private AssociatedMetadataUrl associatedMetadataUrl;
    }

    @Data
    public class AssociatedMetadataUrl {
         private int channelID;
         /**video*/
         private String metadataType;
    }

}

具体完整的代码见资源绑定

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

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

相关文章

每日一练:攻防世界:北京地铁

首先是找图片隐写 在这里可以看到一串类似base64格式的字符串 再结合题目&#xff0c;这应该就是明文了&#xff0c;要AES解密&#xff0c;还需要密钥&#xff0c;提示要看图片本身&#xff0c;那密钥可能藏在里面&#xff0c;找了半天没找到&#xff0c;参考师傅的wp&#x…

Docker:利用Docker搭建一个nginx服务

文章目录 搭建一个nginx服务认识nginx服务Web服务器反向代理服务器高性能特点 安装nginx启动nginx停止nginx查找nginx镜像拉取nginx镜像&#xff0c;启动nginx站点其他方式拉取nginx镜像信息通过 DIGEST 拉取镜像 搭建一个nginx服务 首先先认识一下nginx服务&#xff1a; NGI…

FreeRTOS 简单内核实现1 前言

文章目录 0、写在前面1、参考资料2、准备工作2.1、STM32 空工程2.2、创建 RTOS 文件目录 3、约定4、专栏目录5、项目仓库 0、写在前面 为深入理解 RTOS 内核工作机制&#xff0c;笔者制作了名为 “FreeRTOS 内核简单实现” 的项目专栏 &#xff0c;目标为自己动手从 0 到 1 编…

第二证券股市资讯:苹果,重回第一!

苹果以弱小的优势&#xff0c;从头夺回市值榜首宝座。 当地时间6月13日周四&#xff0c;美股三大股指涨跌纷歧&#xff0c;纳指与标普500指数均录得接连第四日上涨&#xff0c;而且再创前史新高。 周四&#xff0c;美国5月份生产者价格指数&#xff08;PPI&#xff09;意外下…

Apache Doris单机快速安装(已踩坑)

官方文档&#xff1a;https://doris.incubator.apache.org/zh-CN/docs/get-starting/quick-start/ 环境&#xff1a; 操作系统&#xff1a;CentOS7.6 X86_64 JDK&#xff1a;Oracle jdk1.8.0_351 1.版本下载 从 doris.apache.org 下载相应的 Doris 安装包&#xff0c;并且解压…

碎片化知识如何被系统性地吸收?

一、方法论 碎片化知识指的是通过各种渠道快速获取的零散信息和知识点&#xff0c;这些信息由于其不完整性和孤立性&#xff0c;不易于记忆和应用。为了系统性地吸收碎片化知识&#xff0c;可以采用以下策略&#xff1a; 1. **构建知识框架**&#xff1a; - 在开始吸收之前&am…

吉时利Keithley2611B单通道SMU数字源表

Keithley吉时利2611B数字源表 2611B、2612B、2614B 系统 Sourcemeter SMU 仪器 2611B、2612B 和 2634B 系统 Sourcemeter SMU 仪器为 30W DC / 200W 脉冲 SMU&#xff0c;支持 10A 脉冲&#xff0c;1.5A 至 100fA 和 200V 至 100nV DC。所有 2600B SMU 均配备吉时利 TSP 脚本…

硬件开发笔记(十八):核心板与底板之间的连接方式介绍说明:板对板连接器

若该文为原创文章&#xff0c;转载请注明原文出处 本文章博客地址&#xff1a;https://hpzwl.blog.csdn.net/article/details/139663096 长沙红胖子Qt&#xff08;长沙创微智科&#xff09;博文大全&#xff1a;开发技术集合&#xff08;包含Qt实用技术、树莓派、三维、OpenCV…

基于SSD的安全帽检测

目录 1. 作者介绍2. SSD算法介绍2.1 SSD算法网络结构2.2 SSD算法训练过程2.3 SSD算法优缺点 3. 基于SSD的安全帽检测实验3.1 VOC 2007安全帽数据集3.2 SSD网络架构3.3 训练和验证所需的2007_train.txt和2007_val.txt文件生成3.4 模型训练3.5 GUI界面3.6 结果展示3.7 文件下载 4…

C#版 iText7——画发票PDF(完整)

显示描述&#xff1a; 1、每页显示必须带有发票头、“销售方和购买方信息” 2、明细填充为&#xff1a;当n≤8 行时&#xff0c;发票总高度140mm&#xff0c;每条发票明细行款高度4.375mm&#xff1b; 当8<n≤12行时&#xff0c;发票高度增加17.5mm&#xff0c;不换页&#…

人工智能内容生成元年-AI绘画原理解析

随着人工智能技术的飞速发展&#xff0c;AI绘画作为其引人注目的应用领域&#xff0c;正在以惊人的速度崭露头角。从最初的生成对抗网络&#xff08;GAN&#xff09;到如今的深度学习&#xff0c;AI绘画技术在艺术创作、设计等领域展现出了无限的可能性。其独特的算法和智能化特…

构建 deno/fresh 的 docker 镜像

众所周知, 最近 docker 镜像的使用又出现了新的困难. 但是不怕, 窝们可以使用曲线救国的方法: 自己制作容器镜像 ! 下面以 deno/fresh 举栗, 部署一个简单的应用. 目录 1 创建 deno/fresh 项目2 构建 docker 镜像3 部署和测试4 总结与展望 1 创建 deno/fresh 项目 执行命令…

情侣飞行棋系统微信小程序+H5+微信公众号+APP 源码

情侣飞行棋系统&#xff1a;浪漫与策略并存的双人游戏 &#x1f3b2; 一、引言&#xff1a;寻找爱情的乐趣 在繁忙的生活中&#xff0c;情侣们总是渴望找到一种既能增进感情又能带来乐趣的活动。而“情侣飞行棋系统”正是这样一个完美的选择。它结合了传统飞行棋的玩法和情侣…

接口自动化测试工程化——了解接口测试

什么是接口测试 接口测试也是一种功能测试 我理解的接口测试&#xff0c;其实也是一种功能测试&#xff0c;只是平时大家说的功能测试更多代指 UI 层面的功能测试&#xff0c;而接口测试更偏向于服务端层面的功能测试。 接口测试的目的 测试左移&#xff0c;尽早介入测试&a…

失眠焦虑?这些小妙招助你重拾宁静之夜

在这个快节奏的时代&#xff0c;失眠与焦虑似乎成了不少人的“常客”。每当夜幕降临&#xff0c;躺在床上却辗转反侧&#xff0c;思绪万千&#xff0c;仿佛整个世界的喧嚣都涌入了脑海。&#x1f4ad; 其实&#xff0c;放松心情&#xff0c;调整心态&#xff0c;是缓解失眠焦虑…

【MATLAB源码-第225期】基于matlab的计算器GUI设计仿真,能够实现基础运算,三角函数以及幂运算。

操作环境&#xff1a; MATLAB 2022a 1、算法描述 界面布局 计算器界面的主要元素分为几大部分&#xff1a;显示屏、功能按钮、数字按钮和操作符按钮。 显示屏 显示屏&#xff08;Edit Text&#xff09;&#xff1a;位于界面顶部中央&#xff0c;用于显示用户输入的表达式和…

Java聚合快递系统对接云洋系统快递小程序APP公众号系统源码

聚合快递对接云洋系统小程序&#xff1a;一键解决物流难题 一、引言&#xff1a;为何选择聚合快递对接&#xff1f; 在电商日益繁荣的今天&#xff0c;物流成为了连接卖家与买家的关键桥梁。然而&#xff0c;面对市场上琳琅满目的快递公司&#xff0c;如何高效、便捷地进行快…

Fluid 1.0 版发布,打通云原生高效数据使用的“最后一公里”

作者&#xff1a;顾荣 前言 得益于云原生技术在资源成本集约、部署运维便捷、算力弹性灵活方面的优势&#xff0c;越来越多企业和开发者将数据密集型应用&#xff0c;特别是 AI 和大数据领域应用&#xff0c;运行于云原生环境中。然而&#xff0c;云原生计算与存储分离架构虽…

低代码组件扩展方案在复杂业务场景下的设计与实践

组件是爱速搭的前端页面可视化模块的核心能力之一&#xff0c;它将前端研发人员从无休止的页面样式微调和分辨率兼容工作中解放了出来。 目前&#xff0c;爱速搭通过内置的上百种功能组件&#xff08;120&#xff09;&#xff0c;基本可以覆盖大部分中后台页面的可视化设计场景…

什么是数字人大?一分钟带你了解!

在数字化浪潮席卷全球的今天&#xff0c;中国作为数字经济的领跑者&#xff0c;正积极推动数字技术与国家治理体系的深度融合。其中&#xff0c;“数字人大”作为新时代国家治理体系和治理能力现代化的重要一环&#xff0c;正逐步成为推动民主法治建设、提升人大工作效能的新引…