[实战]Springboot与GB28181摄像头对接。摄像头注册上线(一)

与支持国标摄像头对接

  • 前言:不想看教程?
  • 1、准备阶段
    • 1.1、我们会学到什么?
    • 1.2、创建项目
    • 1.3、pom中用到的依赖
    • 1.4 打开摄像头的网址(了解配置方式)
  • 2、代码编写
    • 2.1、增加项目配置
    • 2.2、在config目录下创建SipConfig
    • 2.3、在service目录下创建SipService
    • 2.4、在adapter目录下创建如下类
    • 2.5、在listener准备如下类
    • 2.7、准备基础的枚举类(enums目录下)
  • 3、按照项目配置摄像头的SIP
  • 4、启动项目

前言:不想看教程?

   想直接拿源码?Qq:1101165230

1、准备阶段

  电脑和idea这个肯定是要准备的,然后准备几台(或一台)支持国标对接的摄像头。要知道摄像头的访问地址账号和密码。

1.1、我们会学到什么?

   在这个项目中我们会用到一些设计模式以及一些注解平时可能不太常用的注解。我们还额外的知道了与物联网相关的一些对接知识。(文章中可能更多的是代码上的,为了便于大家直接CV。对于理论知识的大家可以私我,我可以出一期视频讲解这个项目)

1.2、创建项目

  我们在这里创建的是一个WebFlux的项目,便须后期处理设备的命令。
结构如下:(ps: 在idea的Terminal中输入tree或者tree -f,-f会包含目录下文件名)

<!--打印目录-->
tree
<!--打印目录带文件-->
tree -f
<!--将目录输出到文件并保存-->
tree /f >> D:/tree.txt
gb28181-sg
│
├─src
│  ├─main
│  │  ├─java
│  │  │  └─org
│  │  │      └─ougnuhs
│  │  │          └─gb
│  │  │              │  GbApplication.java 
│  │  │              ├─adapter
│  │  │              ├─config 
│  │  │              ├─controller     
│  │  │              ├─enums
│  │  │              │  └─base        
│  │  │              ├─listener    
│  │  │              ├─service     
│  │  │              └─utils                   
│  │  └─resources         
│  └─test
│      └─java
└─target

1.3、pom中用到的依赖

 &emsp(这里只放了dependencies)SIP依赖特别需要。

 <dependencies>

        <!-- SpringBoot 核心包 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
            <exclusions>
                <exclusion>
                    <artifactId>spring-boot-starter-logging</artifactId>
                    <groupId>org.springframework.boot</groupId>
                </exclusion>
            </exclusions>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-webflux</artifactId>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>

        <!--SIP-->
        <!-- sip协议栈 -->
        <dependency>
            <groupId>javax.sip</groupId>
            <artifactId>jain-sip-ri</artifactId>
            <version>1.3.0-91</version>
        </dependency>
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.17</version>
        </dependency>

        <!-- 引入log4j2依赖 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-log4j2</artifactId>
        </dependency>

    </dependencies>

1.4 打开摄像头的网址(了解配置方式)

这里大家先看一下,熟悉摄像头配置位置,不用填写。
找到如图位置
我这里用的是海康摄像头,摄像头的网页配置地址就是摄像头的ip地址。我们可以看到在平台接入的地方需要填写SIP的一些信息,以及提供服务的ip。
红框里的就是我们在项目中的
这个是我之前配置过的,对于新摄像头可能没有,不过没关系,我们在项目中配置成什么这里就填写成什么即可。

2、代码编写

2.1、增加项目配置

  在前面我们创建好了项目,并知道了摄像头SIP的配置位置。接着我们在application.yml文件中增加我们的sip配置。
application.yml

server:
  port: 8087

sip:
  ip: 192.168.20.78
  port: 5060
  id: 34020000002000000001
  domain: 3402000000
  password: sg@123456

2.2、在config目录下创建SipConfig

  需要在config目录下创建。


import lombok.Getter;
import lombok.Setter;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;

/**
 * @author by Guoshun
 * @version 1.0.0
 * @description SipConfig
 * @date 2024/3/22 10:44
 */
@Getter
@Setter
@Configuration
@ConfigurationProperties(prefix = SipConfig.SIP)
public class SipConfig {

    public static final String SIP = "sip";

    /**
     * 默认使用 0.0.0.0
     */
    private String monitorIp = "0.0.0.0";

    private String ip;

    private Integer port;

    private String id;

    private String password;

    private String domain;

}

2.3、在service目录下创建SipService


import gov.nist.javax.sip.SipProviderImpl;
import gov.nist.javax.sip.SipStackImpl;
import lombok.extern.slf4j.Slf4j;
import org.ougnuhs.gb.config.SipConfig;
import org.ougnuhs.gb.listener.MySipListener;
import org.ougnuhs.gb.utils.SIPDefaultProperties;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;

import javax.sip.*;
import java.util.Properties;

/**
 * @author by Guoshun
 * @version 1.0.0
 * @description SipService need SipConfig
 * @date 2024/3/22 11:02
 */
@Slf4j
@Configuration
public class SipService {

    @Autowired
    private SipConfig sipConfig;

    @Autowired
    private MySipListener mySipListener;

    private SipFactory sipFactory;

    private SipStackImpl sipStack;


    @Bean("sipFactory")
    SipFactory createSipFactory(){
        sipFactory = SipFactory.getInstance();
        sipFactory.setPathName("gov.nist");
        return sipFactory;
    }

    @Bean("sipStack")
    @DependsOn("sipFactory")
    SipStackImpl createSipStackImpl() throws PeerUnavailableException {
        Properties sipProperties = SIPDefaultProperties.getSipProperties(sipConfig.getMonitorIp(), false);
        sipStack =(SipStackImpl) sipFactory.createSipStack(sipProperties);
        return sipStack;
    }

    /**
     * 监听TCP 对于产生的异常需要在这个地方处理
     * @return
     * @throws Exception
     */
    @Bean("tcpSipProvider")
    @DependsOn("sipStack")
    public SipProviderImpl startTcpListener() throws Exception {
        // 创建SIP Provider并绑定到SIP Stack
        ListeningPoint lp = sipStack.createListeningPoint(sipConfig.getMonitorIp(), sipConfig.getPort(), "TCP");
        SipProviderImpl sipProvider = (SipProviderImpl)sipStack.createSipProvider(lp);
        // 注册SIP Servlet
        sipProvider.addSipListener(mySipListener);
        log.info("TCP Start SUCCESS");
        return sipProvider;
    }

    /**
     * 监听TCP 对于产生的异常需要在这个地方处理
     * @return
     * @throws Exception
     */
    @Bean("udpSipProvider")
    @DependsOn("sipStack")
    public SipProviderImpl startUdpListener() throws Exception {
        // 创建SIP Provider并绑定到SIP Stack
        ListeningPoint lp = sipStack.createListeningPoint(sipConfig.getMonitorIp(), sipConfig.getPort(), "UDP");
        SipProviderImpl sipProvider =  (SipProviderImpl)sipStack.createSipProvider(lp);
        // 注册SIP Servlet
        sipProvider.addSipListener(mySipListener);
        log.info("UDP Start SUCCESS");
        return sipProvider;
    }


}

2.4、在adapter目录下创建如下类

import org.springframework.beans.factory.InitializingBean;

import javax.sip.RequestEvent;

/**
 * @author by Guoshun
 * @version 1.0.0
 * @description SIP事件处理接口
 * @date 2024/3/22 13:59
 */
public interface ISIPEventHandler extends InitializingBean {

    /**
     * 事件处理方法
     * @param requestEvent
     */
    void process(RequestEvent requestEvent);

}

@Slf4j
public class SIPFactory {

    public static Map<String, ISIPEventHandler> requestHandlerMap = new ConcurrentHashMap<>();

    public static void register(String key, ISIPEventHandler handler){
        if(!StringUtils.hasText(key) || ObjectUtils.isEmpty(handler)){
            log.info("error: key or handler is null");
            return;
        }
        requestHandlerMap.put(key, handler);
        log.info("id:{}, handler:{}, register success", key, handler );
    }

    public static ISIPEventHandler getInvokeStrategy(String key) throws NoSuchMethodException {
        if(!requestHandlerMap.containsKey(key)){
            throw new NoSuchMethodException("未找到执行该方法的策略 key: " + key);
        }
        return requestHandlerMap.get(key);
    }
}
package org.ougnuhs.gb.adapter;

import gov.nist.javax.sip.SipProviderImpl;
import gov.nist.javax.sip.SipStackImpl;
import gov.nist.javax.sip.message.SIPRequest;
import gov.nist.javax.sip.stack.SIPServerTransactionImpl;
import lombok.extern.slf4j.Slf4j;
import org.ougnuhs.gb.enums.TransportTypeEnum;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;

import javax.sip.*;
import javax.sip.header.ViaHeader;
import javax.sip.message.MessageFactory;
import javax.sip.message.Request;

/**
 * @author by Guoshun
 * @version 1.0.0
 * @description 模板方法
 * @date 2024/3/22 16:43
 */
@Slf4j
public abstract class SIPRequestProcessorParent {

    @Autowired
    @Qualifier(value="tcpSipProvider")
    private SipProviderImpl tcpSipProvider;

    @Autowired
    @Qualifier(value="udpSipProvider")
    private SipProviderImpl udpSipProvider;


    /**
     * 根据 RequestEvent 获取 ServerTransaction
     * @param evt
     * @return
     */
    public ServerTransaction getServerTransaction(RequestEvent evt) {
        Request request = evt.getRequest();
        SIPServerTransactionImpl serverTransaction = (SIPServerTransactionImpl)evt.getServerTransaction();
        // 判断TCP还是UDP
        boolean isTcp = transportTypeIsTcp(request);
        if (serverTransaction != null && serverTransaction.getOriginalRequest() == null) {
            serverTransaction.setOriginalRequest((SIPRequest) evt.getRequest());
        }
        if (serverTransaction == null) {
            try {
                if (isTcp) {
                    SipStackImpl stack = (SipStackImpl)tcpSipProvider.getSipStack();
                    serverTransaction = (SIPServerTransactionImpl) stack.findTransaction((SIPRequest)request, true);
                    if (serverTransaction == null) {
                        serverTransaction = (SIPServerTransactionImpl)tcpSipProvider.getNewServerTransaction(request);
                    }
                } else {
                    SipStackImpl stack = (SipStackImpl)udpSipProvider.getSipStack();
                    serverTransaction = (SIPServerTransactionImpl) stack.findTransaction((SIPRequest)request, true);
                    if (serverTransaction == null) {
                        serverTransaction = (SIPServerTransactionImpl)udpSipProvider.getNewServerTransaction(request);
                    }
                }
            } catch (TransactionAlreadyExistsException e) {
                log.error(e.getMessage());
            } catch (TransactionUnavailableException e) {
                log.error(e.getMessage());
            }
        }
        return serverTransaction;
    }

    /**
     * 判断通讯的方式是TCP吗
     * @param request
     * @return
     */
    private boolean transportTypeIsTcp(Request request){
        ViaHeader reqViaHeader = (ViaHeader) request.getHeader(ViaHeader.NAME);
        String transport = reqViaHeader.getTransport();
        log.info("通讯方式是:{}", transport);
        return transport.equalsIgnoreCase(TransportTypeEnum.TCP.getValue());
    }


    //FIXME 在SipService中不是有一个这个对象吗?
    public MessageFactory getMessageFactory() {
        try {
            return SipFactory.getInstance().createMessageFactory();
        } catch (PeerUnavailableException e) {
            e.printStackTrace();
        }
        return null;
    }



}
package org.ougnuhs.gb.adapter;

import gov.nist.javax.sip.RequestEventExt;
import gov.nist.javax.sip.address.AddressImpl;
import gov.nist.javax.sip.address.SipUri;
import gov.nist.javax.sip.clientauthutils.DigestServerAuthenticationHelper;
import lombok.extern.slf4j.Slf4j;
import org.ougnuhs.gb.config.SipConfig;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;

import javax.sip.InvalidArgumentException;
import javax.sip.RequestEvent;
import javax.sip.ServerTransaction;
import javax.sip.SipException;
import javax.sip.header.AuthorizationHeader;
import javax.sip.header.ExpiresHeader;
import javax.sip.header.FromHeader;
import javax.sip.header.ViaHeader;
import javax.sip.message.Request;
import javax.sip.message.Response;
import java.security.NoSuchAlgorithmException;
import java.text.ParseException;

/**
 * @author by Guoshun
 * @version 1.0.0
 * @description 提供注册事件的处理器
 * TODO 返回Response; 以及错误信息返回需要统一,不能随便写返回的错误!
 * @date 2024/3/22 14:17
 */
@Slf4j
@Component
public class SIPRegisterEventHandler extends SIPRequestProcessorParent implements ISIPEventHandler {

    @Autowired
    private SipConfig sipConfig;

    private static final String KEY = "REGISTER";

    private Response response;

    @Override
    public void afterPropertiesSet() throws Exception {
        SIPFactory.register(KEY, this);
    }

    @Override
    public void process(RequestEvent requestEvent) {
        RequestEventExt requestEventExt = (RequestEventExt) requestEvent;
        String ipAddress = requestEventExt.getRemoteIpAddress() + ":" + requestEventExt.getRemotePort();
        log.info("ipAddress:{}", ipAddress);
        //取出request对象
        Request request = requestEventExt.getRequest();
        //FromHeader
        fromHeader(request);
        //AuthorizationHeader
        authorizationHeader(request);
        //ExpiresHeader
        expiresHeader(request);
        //ViaHeader
        viaHeader(request);
        //TODO 假设一切都ok。我们直接进行回复成功
        try {
            response = getMessageFactory().createResponse(Response.OK, request);
            sendResponse(requestEvent, response);
        }catch (ParseException parseException){
            parseException.printStackTrace();
            log.error("SIPRegisterEventHandler createResponse fail");
        }
    }

    /**
     * 注册参数-主要是为了拿到SIP用户名,这个用户不能重复,如果平台需要级联多个摄像头,该SIP必须唯一
     * deviceId 对应的就是SIP用户名
     * @param request
     */
    private void fromHeader(Request request){
        FromHeader fromHeader =(FromHeader) request.getHeader(FromHeader.NAME);
        AddressImpl addressImpl = (AddressImpl) fromHeader.getAddress();
        SipUri sipUri = (SipUri)addressImpl.getURI();
        String deviceId = sipUri.getUser();
        log.info("fromHeader:{} \t addressImpl:{} \t sipUrl:{} \t deviceId:{}",
                fromHeader, addressImpl, sipUri, deviceId);
    }

    /**
     * 携带参数
     * @param request
     */
    private void expiresHeader(Request request){
        ExpiresHeader expiresHeader =(ExpiresHeader) request.getHeader(ExpiresHeader.NAME);
        if(ObjectUtils.isEmpty(expiresHeader)){
            log.error("[注册请求] {}", Response.BAD_REQUEST);
            return;
        }
        if(expiresHeader.getExpires() == 0){
            log.error("[注册请求] 用户申请注销!");
            return;
        }else{
            log.info("[注册请求] 用户申请注册!");
            //TODO 放入数据库
        }
        log.info("expiresHeader:{}", expiresHeader);
    }

    /**
     * 口令密码等信息
     * @param request
     */
    private void authorizationHeader(Request request) {
        AuthorizationHeader authorizationHeader =(AuthorizationHeader) request.getHeader(AuthorizationHeader.NAME);
        if (ObjectUtils.isEmpty(authorizationHeader) && ObjectUtils.isEmpty(sipConfig.getPassword())){
            log.error("[注册请求] 未携带授权");
            return;
        }
        try{
            boolean passwordCorrect = ObjectUtils.isEmpty(sipConfig.getPassword()) ||
                    new DigestServerAuthenticationHelper().doAuthenticatePlainTextPassword(request, sipConfig.getPassword());
            if(!passwordCorrect){
                log.error("[注册请求] 密码/SIP服务器ID错误, 回复403");
                return;
            }
        }catch (NoSuchAlgorithmException e){
            log.error("[注册请求] 验证授权发生错误!");
            return;
        }
        log.info("authorizationHeader:{}", authorizationHeader.toString());
    }

    /**
     * 主要用来查看是UDP还是TCP传输
     * @param request
     */
    private void viaHeader(Request request){
        ViaHeader viaHeader =(ViaHeader) request.getHeader(ViaHeader.NAME);
        String transport = viaHeader.getTransport();
        log.info("viaHeader:{} \t transport:{}", viaHeader, transport);
    }

    /**
     * 响应回复
     * @param requestEvent
     * @param response
     * @throws InvalidArgumentException
     * @throws SipException
     */
    private void sendResponse(RequestEvent requestEvent, Response response){
        ServerTransaction serverTransaction = getServerTransaction(requestEvent);
        if (serverTransaction == null) {
            log.warn("[回复失败]:{}", response);
            return;
        }
        try {
            serverTransaction.sendResponse(response);
            log.info("SIPRegisterEventHandler sendResponse success");
        }catch (InvalidArgumentException | SipException exception){
            exception.printStackTrace();
            log.error("[回复发生异常]:{}", response);
        }finally {
            if (serverTransaction.getDialog() != null) {
                serverTransaction.getDialog().delete();
            }
        }
    }

}

2.5、在listener准备如下类

import javax.sip.SipListener;

/**
 * @author by Guoshun
 * @version 1.0.0
 * @description MySipService 继承 SipListener
 * @date 2024/3/22 11:14
 */
public interface MySipListener extends SipListener {
}

import lombok.extern.slf4j.Slf4j;
import org.ougnuhs.gb.adapter.SIPFactory;
import org.springframework.stereotype.Service;

import javax.sip.*;

/**
 * @author by Guoshun
 * @version 1.0.0
 * @description IMySipService 实现 MySipService
 * @date 2024/3/22 11:16
 */
@Slf4j
@Service
public class MySipListenerImpl implements MySipListener{

    /**
     * 摄像头上报事件
     * @param requestEvent
     */
    @Override
    public void processRequest(RequestEvent requestEvent) {
        String method = requestEvent.getRequest().getMethod();
        try {
            SIPFactory.getInvokeStrategy(method).process(requestEvent);
        }catch (Exception e){
            log.error("processRequest error", e);
        }
    }

    @Override
    public void processResponse(ResponseEvent responseEvent) {
        log.info("processResponse");
    }

    @Override
    public void processTimeout(TimeoutEvent timeoutEvent) {
        log.info("processTimeout");
    }

    @Override
    public void processIOException(IOExceptionEvent exceptionEvent) {
        log.info("processIOException");
    }

    @Override
    public void processTransactionTerminated(TransactionTerminatedEvent transactionTerminatedEvent) {
        log.info("processTransactionTerminated");
    }

    @Override
    public void processDialogTerminated(DialogTerminatedEvent dialogTerminatedEvent) {
        log.info("processDialogTerminated");
    }
}

2.7、准备基础的枚举类(enums目录下)

/**
 * @author by Guoshun
 * @version 1.0.0
 * @description 传输方式类型
 * @date 2024/3/27 9:52
 */
public enum TransportTypeEnum implements BaseEnum {

    TCP("TCP"),
    UDP("UDP");

    private String value;

    TransportTypeEnum(String value) {
        this.value = value;
    }

    public String getValue() {
        return value;
    }

    @Override
    public String getName() {
        return null;
    }

    public void setValue(String value) {
        this.value = value;
    }
}

/**
 * @author by Guoshun
 * @version 1.0.0
 * @description 枚举基类 TODO 没有增加反序列化
 * @date 2024/3/27 9:54
 */
public interface BaseEnum {

    Object getValue();

    default String getText() {
        return null;
    }

    String getName();

    /**
     * 根据枚举value生成枚举
     * @author liyuanxi
     * @date 2019/4/17 11:47
     */
    static <E extends Enum<E> & BaseEnum> E valueOf(Object value, Class<E> clazz) {
        E em;
        E[] enums = clazz.getEnumConstants();
        String enumName = null;
        for (BaseEnum e : enums) {
            if (e.getValue().equals(value)) {
                enumName = e.getName();
            }
        }
        if (null != enumName) {
            em = Enum.valueOf(clazz, enumName);
        } else {
            throw new RuntimeException(value + "未匹配上对应的枚举");
        }
        return em;
    }

    /**
     * 根据枚举name生成枚举类型
     * @author liyuanxi
     * @date 2019/4/17 11:47
     */
    static <E extends Enum<E> & BaseEnum> E nameOf(String name, Class<E> clazz) {
        return Enum.valueOf(clazz, name);
    }
}

以上全部cv走。

3、按照项目配置摄像头的SIP

请按照这个配置
需要说明的是多个摄像头的话,SIP用户名请保证唯一

4、启动项目

  启动项目后,设备会自动注册上来,我方会告知他注册成功。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

如何在Windows 10中打开屏幕键盘?这里有详细步骤

本文解释了在Windows 10中打开或关闭屏幕键盘的不同方法,还解释了如何将屏幕键盘固定到开始菜单。 使用屏幕键盘的快捷键 如果你喜欢快捷方式,你会喜欢这个:按物理键盘上的Win+CTRL+O。这将立即显示屏幕键盘,而无需通过轻松使用。 ​提示:使用运行窗口也可以打开键盘。…

Tuxera for Mac2024软件产品密钥及下载安装教程

Tuxera for Mac在安全性和稳定性方面表现出色&#xff0c;为用户提供了可靠的数据保障和无忧的使用体验。 首先&#xff0c;从安全性角度来看&#xff0c;Tuxera for Mac采用了先进的技术来保护用户的数据。它支持快速全面的数据保护&#xff0c;通过智能缓存技术确保文件传输…

《手把手教你》系列技巧篇(五十七)-java+ selenium自动化测试-下载文件-下篇(详细教程)

1.简介 前边几篇文章讲解完如何上传文件&#xff0c;既然有上传&#xff0c;那么就可能会有下载文件。因此宏哥就接着讲解和分享一下&#xff1a;自动化测试下载文件。可能有的小伙伴或者童鞋们会觉得这不是很简单吗&#xff0c;还用你介绍和讲解啊&#xff0c;不说就是访问到…

图神经网络实战(6)——使用PyTorch构建图神经网络

图神经网络实战&#xff08;6&#xff09;——使用PyTorch构建图神经网络 0. 前言1. 传统机器学习与人工智能2. 人工神经网络基础2.1 人工神经网络组成2.2 神经网络的训练 3. 图神经网络4. 使用香草神经网络执行节点分类4.1 数据集构建4.2 模型构建4.3 模型训练 5. 实现香草图神…

聚观早报 | 比亚迪2023年营收;vivo X Fold3系列发布

聚观早报每日整理最值得关注的行业重点事件&#xff0c;帮助大家及时了解最新行业动态&#xff0c;每日读报&#xff0c;就读聚观365资讯简报。 整理丨Cutie 3月28日消息 比亚迪2023年营收 vivo X Fold3系列发布 现代汽车拟投入68万亿韩元 华为P70系列最新渲染图 苹果A1…

Art Gallery Vol.2

Art Gallery Vol.2为您的游戏、VR项目和模拟器提供了一个很好的解决方案,图片库。 一个充满雕塑和框架的现代艺术画廊。它包括11件雕塑、14幅画作。适合收藏展览或画作展示。 所有画作都是独立的纹理,非常适合ArchViz、VR或任何类型的AAA游戏。 下载:​​Unity资源商店链接…

[linux] AttributeError: module ‘transformer_engine‘ has no attribute ‘pytorch‘

[BUG] AttributeError: module transformer_engine has no attribute pytorch Issue #696 NVIDIA/Megatron-LM GitHub 其中这个答案并没有解决我的问题&#xff1a; import flash_attn_2_cuda as flash_attn_cuda Traceback (most recent call last): File "<stdi…

国产数据库中统计信息自动更新机制

数据库中统计信息描述的数据库中表和索引的大小数以及数据分布状况&#xff0c;统计信息的准确性对优化器选择执行计划时具有重要的参考意义。本文简要整理了下传统数据库和国产数据库中统计信息的自动更新机制&#xff0c;以加深了解。 1、数据库统计信息介绍 优化器是数据库…

【系统架构师】-第13章-层次式架构设计

层次式体系结构设计是将系统组成一个层次结构&#xff0c;每一层 为上层服务 &#xff0c;并作为下层客户。 在一些层次系统中&#xff0c;除了一些精心挑选的输出函数外&#xff0c; 内部的层接口只对相邻的层可见 。 连接件通过决定层间如何交互的协议来定义&#xff0c;拓扑…

优化体验课转化流程:提升转化率,实现教育品牌增长

随着在线教育市场的竞争日益激烈&#xff0c;体验课转化流程成为影响教育机构发展的关键环节之一。本文将深入探讨如何优化体验课转化流程&#xff0c;提升转化率&#xff0c;实现教育品牌的可持续增长。 ### 什么是体验课转化流程&#xff1f; 体验课转化流程是指教育机构通…

windows安全中心设置@WindowsDefender@windows安全中心常用开关

文章目录 abstractwindows defender相关服务&#x1f47a; 停用windows Defender临时关闭实时防护使用软件工具关闭defender control(慎用)dismdControl 其他方法使其他杀毒软件注册表修改 保护历史恢复被认为是有病毒的文件添加信任目录,文件,文件类型或进程 abstract window…

Stable Diffusion XL之使用Stable Diffusion XL训练自己的AI绘画模型

文章目录 一 SDXL训练基本步骤二 从0到1上手使用Stable Diffusion XL训练自己的AI绘画模型2.1 配置训练环境与训练文件2.2 SDXL训练数据集制作(1) 数据筛选与清洗(2) 使用BLIP自动标注caption(3) 使用Waifu Diffusion 1.4自动标注tag(4) 补充标注特殊tag(5) 训练数据预处理(标注…

Sublime for Mac 使用插件Terminus

1. 快捷键打开命令面板 commandshiftp2. 选择 Package Control: Install Package&#xff0c;然后会出现安装包的列表 3. 在安装终端插件前&#xff0c;我们先装个汉化包&#xff0c;ChineseLocallization&#xff0c;安装完重启 4. 输入 terminus&#xff0c;选择第一个&am…

面试题:Java虚拟机JVM的组成

1. 基础概念 JVM是什么 Java Virtual Machine Java程序的运行环境&#xff08;java二进制字节码的运行环境&#xff09; 好处&#xff1a; 一次编写&#xff0c;到处运行 自动内存管理&#xff0c;垃圾回收机制 JVM由哪些部分组成&#xff0c;运行流程是什么&#xff1f; …

DoCAN配置

DoCAN涉及模块 CanTrcv -> Can -> CanIf -> CanTp -> PduR -> Dcm DCM DcmDslProtocolRow DcmDslProtocolID: DCM_UDS_ON_CAN DslProtocolSIDTable DcmDslMainConnection Rx 物理寻址/功能寻址 PDUR PduRBswModules-Dcm

spring安全框架之Shiro

Shiro 一、现存问题 1.1 现存问题 认证&#xff08;登录&#xff09;&#xff1a;认证操作流程都差不多&#xff0c;但是每次都需要手动的基于业务代码去实现&#xff0c;很麻烦&#xff01; 授权&#xff1a;如果权限控制粒度比较粗&#xff0c;可以自身去实现&#xff0c…

【论文阅读】Faster Neural Networks Straight from JPEG

Faster Neural Networks Straight from JPEG 论文链接&#xff1a;Faster Neural Networks Straight from JPEG (neurips.cc) 作者&#xff1a;Lionel Gueguen&#xff0c;Alex Sergeev&#xff0c;Ben Kadlec&#xff0c;Rosanne Liu&#xff0c;Jason Yosinski 机构&#…

数据结构与算法 单链表的基本运算

一、实验内容 编写一个程序实现&#xff0c;实现单链表的各种基本运算&#xff08;假设单链表的元素类型为char&#xff09;&#xff0c;并以此为基础设计一个程序完成下列功能&#xff1a; 初始化单链表&#xff1b;采用尾插法依次插入元素a&#xff0c;b&#xff0c;c&…

GitHub Copilot如何订阅使用

1.Copilot是什么 Copilot是由Github和OpenAI联合开发的一个基于人工智能大模型的代码写作工具。 我们都知道Github是世界上拥有开源项目及代码最多的一个平台&#xff0c;有了这么一个得天独厚的资源&#xff0c;Github联合OpenAI喂出了Copilot。经过不断地更新迭代&#xff…

GNU Radio之OFDM Carrier Allocator底层C++实现

文章目录 前言一、OFDM Carrier Allocator 简介二、底层 C 实现1、make 函数2、ofdm_carrier_allocator_cvc_impl 函数3、calculate_output_stream_length 函数4、work 函数5、~ofdm_carrier_allocator_cvc_impl 函数 三、OFDM 数据格式 前言 OFDM Carrier Allocator 是 OFDM …
最新文章