JetLinks设备接入的认识与理解【woodwhales.cn】

为了更好的阅读体验,建议移步至笔者的博客阅读:JetLinks设备接入的认识与理解

1、认识 JetLinks

1.1、官网文档

官网:https://www.jetlinks.cn/

JetLinks 有两个产品:JetLinks-lot和JetLinks-view

官方文档:

  • JetLinks 物联网基础平台

  • JetLinks 物联网平台开发手册

1.2、JetLinks

JetLinks 是可支持多种方式接入设备的物联网设备管理平台

https://hanta.yuque.com/px7kg1/yfac2l/fwqriw24lp3cy2lw
请添加图片描述
JetLinks IOT 是一个开源的、企业级的物联网平台,它集成了设备管理、数据安全通信、消息订阅、规则引擎等一系列物联网核心能力,支持以平台适配设备的方式连接海量设备,采集设备数据上云,提供云端API,通过调用云端API实现远程控制。JetLinks物联网平台还支持多种设备接入协议,并提供了丰富的协议库。

支持:多协议(MQTT、HTTP、CoAP、UDP、TCP、WebSocket)自定义编解码插件接入;

支持:云平台对接接入;

支持: ModBus/TCP、OPC UA通道接入;

支持:基于GB/T 28181国标协议视频接入;

支持:自研边缘计算网关接入。

1.3、产品架构的理解

https://hanta.yuque.com/px7kg1/yfac2l/tvlxz93cht8zyl94

1.3.1、理解1

通过不同层级功能职责的封装、组合,以支持多设备、多协议接入平台

请添加图片描述

  1. 设备连接层:支持MQTT、TCP、UDP、CoAP、HTTP、WebSocket协议,提供统一设备接入的能力。

  2. 设备管理层:提供设备注册、配置、维护和监控的功能,支持设备属性、状态实时展示和历史属性、设备日志记录查询等。

  3. 业务逻辑层:提供规则引擎、数据转发和数据解析等功能,支持多种业务场景下的数据处理和交互操作。

  4. 应用开发层:提供RESTAPI和WebSocket接口,支持前端对接和自定义应用开发。同时还提供了可视化的数据展示和操作页面,方便用户快速搭建物联网应用系统。

1.3.2、理解2

设备接入JetLinks物联网平台后,可实现:设备通讯、数据的采集、认证、流转、存储、分析和实时监控

请添加图片描述

13.3、理解3

开发者需要自行实现编解码器逻辑,才可以让平台对设备数据进行全面管理
在这里插入图片描述

1.4、基本概念

https://hanta.yuque.com/px7kg1/yfac2l/dagxgfzc3vnul0sn

1.4.1、产品

产品是指一组具有相同功能和规格的设备集合,通常由同一家生产厂家制造。

设备可能是传感器、执行器、控制器等各种不同类型的物联网设备,它们可以通过网络连接到物联网平台。通过将这些设备组合到一个产品中,企业可以对这些设备进行统一管理和监控,以便更有效地控制其行为和状态。

1.4.2、设备

设备是指物理存在的、可通过网络连接的单个物联网设备。

设备可以是各种类型的物品,例如传感器、执行器、控制器等。这些设备通过物联网连接到平台,以便与其他设备或应用程序进行通信、交换数据和接收命令。

1.4.3、物模型

物模型说明:http://doc.jetlinks.cn/function-description/metadata_description.html

物模型是物理空间中的实体在云端的数字化表示,有 4 个纬度:属性、功能、事件、标签。

  • 属性:用于描述设备运行时具体信息和状态。例如温湿度传感器包含“温度”、“湿度”两个属性。

  • 功能:设备可被外部调用的能力或方法,可设置输入参数和输出参数。相比于属性,服务可通过一条指令实现更复杂的业务逻辑

  • 事件:用于描述设备上报云端的多个参数,多用于复杂报文结构或设备本身在某个阈值触发的报文。

  • 标签:统一为设备添加拓展字段,添加后将在设备信息页显示。

在这里插入图片描述

2、开发手册

社区版后端工程:

  • github 仓库:https://github.com/jetlinks/jetlinks-community
  • gitee 仓库:https://gitee.com/jetlinks/jetlinks-community

2.1、模块说明

社区版系统模块说明:https://hanta.yuque.com/px7kg1/nn1gdr/gfqb3xmxg8fsvyxf#lR7Pd

  • jetlinks-components # 组件库
    • common-component # 通用组件、工具类等
    • configure-component # 统一配置模块
    • dashboard-component # 仪表盘模块
    • elasticsearch-component # ElasticSearch集成
    • gateway-component # 网关模块,统一定义网关接口等信息
    • io-component # IO模块,文件管理等
    • logging-component # 日志模块
    • network-component # 网络组件模块,统一定义网络组件规范以及默认实现
      • http-component # http模块
      • mqtt-component # mqtt模块
      • network-core # 网络组件核心模块
      • tcp-component # tcp模块
    • notify-component # 通知模块,统一定义通知规范以及默认实现
      • notify-core # 通知模块核心
      • notify-dingtalk # 钉钉通知模块
      • notify-email # 邮件通知模块
      • notify-sms # 短信通知模块
      • notify-voice # 语音通知模块
      • notify-webhook # webhook通知模块
      • notify-wechat # 微信通知模块
    • protocol-component # 协议模块
    • relation-component # 关系模块,用于描述物与物之间的关系
    • rule-engine-component # 规则引擎模块,集成规则引擎通用功能
    • script-component # 脚本模块,封装脚本引擎
    • tdengine-component # 对tdengine的支持
    • things-component # 物管理模块
    • timeseries-component # 时序数据组件
  • jetlinks-manager # 管理功能
    • authentication-manager # 用户,权限管理模块
    • device-manager # 设备管理模块
    • logging-manager # 日志管理模块
    • network-manager # 网络组件管理模块
    • notify-manager # 通知管理模块
    • rule-engine-manager # 规则引擎管理模块
  • jetlinks-standalone #单例模块,启动JetLinks平台

2.2、技术选型

技术栈描述
Java8编程语言
hsweb Framework业务基础框架
Spring Boot 2.7.x响应式web支持
vert.x,netty高性能网络框架
R2DBC关系型数据库响应式驱动
Postgresql关系型数据库,可更换为mysql、sqlserver
ElasticSearch设备数据与日志存储,可更换为其他中间件
Redis用户信息与权限缓存、设备注册中心缓存
scalecube基于JVM的分布式服务框架,支持响应式
micrometer监控指标框架

2.3、必要的开发知识

响应式编程:http://doc.jetlinks.cn/dev-guide/reactor.html

事件驱动:http://doc.jetlinks.cn/dev-guide/event-driver.html

添加自定义模块:https://hanta.yuque.com/px7kg1/dev/wdymp6flcfa1vwh5

3、设备接入流程

设备接入流程:http://doc.jetlinks.cn/function-description/device_message_description.html#%E8%AE%BE%E5%A4%87%E6%8E%A5%E5%85%A5%E6%B5%81%E7%A8%8B

HTTP协议设备接入:https://hanta.yuque.com/px7kg1/yfac2l/qlr6nz5btr5rwrgk

3.1、流程图

在这里插入图片描述

3.2、开发:协议包

开发者自行实现自定义协议,官方教程:http://doc.jetlinks.cn/dev-guide/custom-message-protocol.html

官方提供了协议开发示例工程:https://github.com/jetlinks/jetlinks-official-protocol

JetLinks 官方协议 jar 包:https://github.com/jetlinks/jetlinks-official-protocol/blob/v3/package/jetlinks-official-protocol-3.0.0.jar

  1. 编写自定义编解码器

    创建org.jetlinks.core.message.codec.DeviceMessageCodec接口实现类,重写encode()decode()getSupportTransport()方法

  2. 编写协议的元信息

    创建org.jetlinks.core.metadata.DefaultConfigMetadata对象并设置对应属性

  3. 编写自定义设备协议支持提供商

    创建org.jetlinks.core.spi.ProtocolSupportProvider接口实现类,并重写create()方法,

    create()方法中将:将自定义编解码器注册到协议中

  4. 配置路由配置:

    org.jetlinks.core.spi.ProtocolSupportProvider接口实现类的create()方法中创建org.jetlinks.core.defaults.CompositeProtocolSupport对象,在其中配置路由配置、身份认证(可选)

3.3、添加:协议包

将协议包上传到协议管理中
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

3.4、添加:网络组件

  1. 配置:本地和公网的接口地址、端口号
  2. 配置:接口处理的服务类型

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

3.5、添加:设备接入网关

将上述的协议包和网络组件进行绑定

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

3.6、添加:产品

  1. 配置:产品信息

  2. 绑定:上述的自定义网络组件(官方定义:设备接入)

  3. 配置:认证信息

  4. 配置存储策略

  5. 配置:物模型

    1. 属性定义
    2. 功能定义
    3. 事件定义
    4. 标签定义
  6. 启用:产品

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

  1. 行式存储

    ElasticSearch-行式存储是系统默认情况下使用的存储方案。每一个属性值都保存为一条索引记录。

    典型应用场景:设备每次只会上报一部分属性, 以及支持读取部分属性数据的时候。

  2. 列式存储

    一个属性作为一列,一条属性消息作为一条索引记录进行存储。

    典型应用场景:适合设备每次都上报所有的属性值的场景。

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

3.7、添加:设备

  1. 配置:设备ID、名称
  2. 绑定:上述配置好的产品(只能配置状态是正常的产品,即已启用的产品)
  3. 启动:设备
  4. (可选)默认继承了所属产品的物模型。可以配置专属当前设备的物模型

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

4、理解协议包

关于协议包:https://hanta.yuque.com/px7kg1/nn1gdr/kcqv8dn8y6778t2a

协议包主要包含 4 个部分

  1. 数据传输协议:协议包约定了常见的网络通信协议,例如MQTT、HTTP、TCP、CoAP等,来实现物联网设备与JetLinks平台之间的数据传输。开发者可根据设备实际情况选择对应的通信协议。

    在这里插入图片描述

  2. 数据解析标准:协议包定义了一套设备数据解析标准,使得各种类型的物联网设备通过网络协议传输至JetLinks后,根据协议包内的数据解析标准将不同类型的报文转换成平台统一的消息。

    在这里插入图片描述

  3. 设备管理功能:协议包内可以获取平台内定义的设备数据,包括设备信息、设备配置、设备状态等,方便开发者在接入设备时获取设备相关数据进行自定义的业务逻辑处理。

  4. 身份认证:协议包支持物联网设备的身份认证,用户可以在协议包内编写身份认证逻辑来验证连接的客户端身份,以保护设备和数据的安全。

5、理解自定义编解码器开发流程

5.1、步骤1

自定义 DeviceMessageCodec 接口实现类,重写 encode()、decode() 方法

在这里插入图片描述

5.1.1、消息编码

重写 DeviceMessageCodec 接口中的encode()方法

在这里插入图片描述

5.1.2、消息解码

重写 DeviceMessageCodec 接口中的decode()方法

在这里插入图片描述

5.2、步骤2

自定义 ProtocolSupportProvider 接口实现类,配置元数据信息

在这里插入图片描述

5.3、步骤3

配置路由与 DeviceMessage 的绑定关系

在这里插入图片描述

5.4、步骤4

自定义 Authenticator 接口实现并配置

在这里插入图片描述

6、理解编解码涉及的核心类关系

协议加载设计:https://hanta.yuque.com/px7kg1/nn1gdr/gascdx49ia6u4lsf

平台统一设备消息定义:http://doc.jetlinks.cn/function-description/device_message_description.html

在这里插入图片描述

7、协议包上传逻辑分析

7.1、步骤1:上传协议 jar

后端接口

POST

/api/file/upload

请求报文

表单请求,接收参数名为:file 的文件数据对象

Content-Disposition: form-data; name="file"; filename="jetlinks-official-protocol-3.0.0.jar"
Content-Type: application/octet-stream

接口类:org.jetlinks.community.io.file.web.FileManagerController#upload

处理逻辑
  1. 获取文件信息,并将文件数据保存到本地指定目录

    • 默认文件目录为:./data/files/yyyyMMdd/

    • 重命名 jar 文件名,生成规则:md5(uuid())

    • 计算当前文件的 md5 和 sha256 值

  2. 将文件相关信息保存到数据库中,数据对象:org.jetlinks.community.io.file.FileEntity

  3. 保存成功的文件数据记录主键和文件信息一起通过接口返回

响应报文

返回文件数据相关记录信息,核心信息:

{ "message": "success", "result": { "id": "9c9ce661a1fadb8019ca50145b33a074", "name": "jetlinks-official-protocol-3.0.0.jar", "extension": "jar", "length": 102512, "md5": "24504ceb0d6570b84b86e6180d9fca9f", "sha256": "fb0c6144ad056326e26eb829c13759b5080da095c7bb02386c7f064ac059f24e", "createTime": 1699859432789, "creatorId": "1199596756811550720", "options": [], "others": { "accessKey": "c24b19b0c91119c6673fa1a06a4d2ae0" } }, "status": 200, "timestamp": 1699859454032 }

7.2、步骤2:确定协议

7.2.1、后端接口

PATCH

/api/protocol

接口类:org.jetlinks.community.device.web.ProtocolSupportController

7.2.2、请求报文
{
    "id": "1722876422724329472",
    "name": "官方协议v3.0",
    "description": "",
    "type": "jar",
    "state": 1,
    "creatorId": "1199596756811550720",
    "createTime": 1699600723328,
    "configuration": {
        "location": "http://localhost:5173/api/file/9c9ce661a1fadb8019ca50145b33a074?accessKey=c24b19b0c91119c6673fa1a06a4d2ae0"
    }
}
7.2.3、处理逻辑
  • 将前端请求的文件信息保存到数据库中,数据对象:org.jetlinks.community.device.entity.ProtocolSupportEntity

前端逻辑:将步骤1 的响应结果拼接成:文件地址(用户不可编辑)+ 用户填写的协议包基本信息(名称、类型、说明)

org.jetlinks.community.device.web.ProtocolSupportController 实现了org.hswebframework.web.crud.web.reactive.ReactiveServiceCrudController接口。

org.hswebframework.web.crud.web.reactive.ReactiveServiceCrudController接口又继承了三个接口:org.hswebframework.web.crud.web.reactive.ReactiveServiceSaveControllerorg.hswebframework.web.crud.web.reactive.ReactiveServiceQueryControllerorg.hswebframework.web.crud.web.reactive.ReactiveServiceDeleteController

ProtocolSupportController

package org.jetlinks.community.device.web;

import org.hswebframework.web.crud.web.reactive.ReactiveServiceCrudController;
import org.jetlinks.community.device.service.LocalProtocolSupportService;

@RestController
@RequestMapping("/protocol")
public class ProtocolSupportController
    implements ReactiveServiceCrudController<ProtocolSupportEntity, String> {
    
    @Autowired
    @Getter
    private LocalProtocolSupportService service;
    
}

ReactiveServiceCrudController

package org.hswebframework.web.crud.web.reactive;

public interface ReactiveServiceCrudController<E, K> extends
        ReactiveServiceSaveController<E, K>,
        ReactiveServiceQueryController<E, K>,
        ReactiveServiceDeleteController<E, K> {
}

PATH /api/protocol 接口实际由:ReactiveServiceSaveController接口提供的默认 save() 方法处理数据,最终调用getService()方法进行save()操作。

package org.hswebframework.web.crud.web.reactive;

import org.hswebframework.web.authorization.annotation.Authorize;

public interface ReactiveServiceSaveController<E, K> {

    @Authorize(ignore = true)
    ReactiveCrudService<E, K> getService();

	@PatchMapping
    @Operation(summary = "保存数据", description = "如果传入了id,并且对应数据存在,则尝试覆盖,不存在则新增.")
    default Mono<SaveResult> save(@RequestBody Flux<E> payload) {
        return Authentication
                .currentReactive()
                .flatMapMany(auth -> payload.map(entity -> applyAuthentication(entity, auth)))
                .switchIfEmpty(payload)
                .as(getService()::save);
    }
	
}

由于ProtocolSupportController注入了org.jetlinks.community.device.service.LocalProtocolSupportService,并且属性名为:service,因此ProtocolSupportControllergetService()就是ReactiveServiceSaveController接口的getService()方法实现。显而易见,确定协议的核心逻辑就在:LocalProtocolSupportServicesave()方法。

org.jetlinks.community.device.service.LocalProtocolSupportService类继承了org.hswebframework.web.crud.service.GenericReactiveCrudService抽象类,而GenericReactiveCrudService抽象类又实现了org.hswebframework.web.crud.service.ReactiveCrudService接口,在ReactiveCrudService中有save()方法

ProtocolSupportController

package org.jetlinks.community.device.service;

import org.jetlinks.community.reference.DataReferenceManager;
import org.jetlinks.supports.protocol.management.ProtocolSupportManager;

@Service
public class LocalProtocolSupportService extends GenericReactiveCrudService<ProtocolSupportEntity, String> {
	
	@Autowired
    private ProtocolSupportManager supportManager;

    @Autowired
    private DataReferenceManager referenceManager;
	
}

GenericReactiveCrudService

package org.hswebframework.web.crud.service;

import org.hswebframework.ezorm.rdb.mapping.ReactiveRepository;
import org.springframework.beans.factory.annotation.Autowired;

public abstract class GenericReactiveCrudService<E, K> implements ReactiveCrudService<E, K> {

    @Autowired
    private ReactiveRepository<E, K> repository;

    @Override
    public ReactiveRepository<E, K> getRepository() {
        return repository;
    }

}

GenericReactiveCrudService 注入了 ReactiveRepository 接口,该接口的实现类为:org.hswebframework.ezorm.rdb.mapping.defaults.DefaultReactiveRepository,里面实现了save()方法:

package org.hswebframework.ezorm.rdb.mapping.defaults;

import org.hswebframework.ezorm.rdb.mapping.ReactiveRepository;

public class DefaultReactiveRepository<E, K> extends DefaultRepository<E> implements ReactiveRepository<E, K> {
	
	@Override
    public Mono<SaveResult> save(Publisher<E> data) {
        return Flux
                .from(data)
                .collectList()
                .filter(CollectionUtils::isNotEmpty)
                .flatMap(list -> doSave(list).reactive().as(this::setupLogger))
                .defaultIfEmpty(SaveResult.of(0, 0));
    }
}

上述doSave()方法是org.hswebframework.ezorm.rdb.mapping.defaults.DefaultRepository抽象类提供的默认方法:

package org.hswebframework.ezorm.rdb.mapping.defaults;

import org.hswebframework.ezorm.rdb.mapping.events.EventResultOperator;

public abstract class DefaultRepository<E> {
	
	protected SaveResultOperator doSave(Collection<E> data) {
        RDBTableMetadata table = getTable();
        UpsertOperator upsert = operator.dml().upsert(table.getFullName());

        return EventResultOperator.create(
                () -> {
                    upsert.columns(getProperties());
                    List<String> ignore = new ArrayList<>();
                    for (E e : data) {
                        upsert.values(Stream.of(getProperties())
                                            .map(property -> getInsertColumnValue(e, property, (prop, val) -> ignore.add(prop)))
                                            .toArray());
                    }
                    upsert.ignoreUpdate(ignore.toArray(new String[0]));
                    return upsert.execute();
                },
                SaveResultOperator.class,
                table,
                MappingEventTypes.save_before,
                MappingEventTypes.save_after,
                getDefaultContextKeyValue(instance(data),
                                          type("batch"),
                                          tableMetadata(table),
                                          upsert(upsert))
        );
    }
}

上述EventResultOperatorcreate()方法中,发布了EntitySavedEvent<E>事件(通过 Spring的ApplicationEventPublisher 发送事件)。

org.jetlinks.community.device.service.ProtocolSupportHandler中订阅了EntitySavedEvent<ProtocolSupportEntity>事件:

package org.jetlinks.community.device.service;

import lombok.AllArgsConstructor;
import org.jetlinks.core.ProtocolSupport;
import org.jetlinks.community.reference.DataReferenceManager;
import org.jetlinks.supports.protocol.management.ProtocolSupportLoader;
import org.jetlinks.supports.protocol.management.ProtocolSupportManager;

@Component
@AllArgsConstructor
public class ProtocolSupportHandler {

    private final DataReferenceManager referenceManager;
    private       ProtocolSupportLoader  loader;
    private       ProtocolSupportManager supportManager;
	
	@EventListener
    public void handleCreated(EntityCreatedEvent<ProtocolSupportEntity> event) {
        event.async(reloadProtocol(event.getEntity()));
    }

    @EventListener
    public void handleSaved(EntitySavedEvent<ProtocolSupportEntity> event) {
        event.async(reloadProtocol(event.getEntity()));
    }

    @EventListener
    public void handleModify(EntityModifyEvent<ProtocolSupportEntity> event) {
        event.async(reloadProtocol(event.getAfter()));
    }

	// 重新加载协议
    private Mono<Void> reloadProtocol(Collection<ProtocolSupportEntity> protocol) {
        return Flux
            .fromIterable(protocol)
            .filter(entity -> entity.getState() != null)
            .map(entity -> entity.getState() == 1 ? entity.toDeployDefinition() : entity.toUnDeployDefinition())
            .flatMap(def -> loader
                //加载一下检验是否正确,然后就卸载
                .load(def)
                .doOnNext(ProtocolSupport::dispose)
                .thenReturn(def))
            .onErrorMap(err -> new BusinessException("error.unable_to_load_protocol", 500, err.getMessage()))
            .flatMap(supportManager::save)
            .then();
    }
	
}

上述ProtocolSupportLoader接口的实现类为org.jetlinks.community.protocol.SpringProtocolSupportLoader,其中load()方法会动态加载 jar 包为org.jetlinks.core.spi.ProtocolSupportProvider接口实现,并执行create()方法。

7.2.4、响应报文
{
    "message": "success",
    "result": {
        "added": 0,
        "updated": 1,
        "total": 1
    },
    "status": 200,
    "timestamp": 1699859463951
}

8、加载协议包时机

8.1、加载协议包时机1

通过org.jetlinks.community.device.service.ProtocolSupportHandler监听EntityCreatedEvent<ProtocolSupportEntity>EntitySavedEvent<ProtocolSupportEntity>EntityModifyEvent<ProtocolSupportEntity>事件,调用ProtocolSupportLoaderload()方法加载协议

在 ProtocolSupportLoader 的 load() 方法中:会调用 org.jetlinks.core.spi.ProtocolSupportProvider 接口实现,并执行 create() 方法

8.2、加载协议包时机2

通过org.jetlinks.community.protocol.LazyInitManagementProtocolSupports实现org.springframework.boot.CommandLineRunner接口,在项目启动时执行init()方法,调用ProtocolSupportLoaderload()方法加载协议

在 ProtocolSupportLoader 的 load() 方法中:会调用 org.jetlinks.core.spi.ProtocolSupportProvider 接口实现,并执行 create() 方法

9、设备网关加载机制

  1. 通过 DeviceGatewayEventHandler 实现 CommandLineRunner 接口,在项目启动时执行 init() 方法
  2. 通过 DeviceGatewayEventHandler 监听 DeviceGatewayEntity 的保存、创建、更新事件

在这里插入图片描述

为了更好的阅读体验,建议移步至笔者的博客阅读:JetLinks设备接入的认识与理解

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

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

相关文章

WPF树形控件TreeView使用介绍

WPF 中的 TreeView 控件用于显示层次结构数据。它是由可展开和可折叠的 TreeViewItem 节点组成的&#xff0c;这些节点可以无限嵌套以表示数据的层次。 TreeView 基本用法 例如实现下图的效果&#xff1a; xaml代码如下&#xff1a; <Window x:Class"TreeView01.Mai…

优秀智慧园区案例 - 上海世博文化公园智慧园区,先进智慧园区建设方案经验

一、项目背景 世博文化公园是上海的绿色新地标&#xff0c;是生态自然永续、文化融合创新、市民欢聚共享的大公园。作为世博地区的城市更新项目&#xff0c;世博文化公园的建设关乎上海城市风貌、上海文化展示、城市生态环境、市民游客体验、上海服务品牌等&#xff0c;被赋予…

防火墙部署模式 -- 镜像流量(旁路模式)

镜像流量&#xff08;旁路模式&#xff09; 如图&#xff0c;与单臂路由模式不同&#xff0c;旁路模式中&#xff0c;PC的流量不会流经防火墙&#xff0c;就算防火墙宕机也不会影他们之间的数据传输。 镜像的原理是交换机把被镜像端口的流量复制一份&#xff0c;发到监听端口&…

打不开clickonce问题解决过程

1.用户电脑user文件夹下有xx和xx.1两个账户,原先安装在xx账户下,后修了电脑原数据保留在xx.1,新创建XX,之后clickonce就打不开了表现为没有反应,,删除注册表和appdata都只能正常安装,但是不能打开,没有任何报错,发现在我的电脑下打开有这样的提示,,在用户电脑上没有 尝试通过修…

了解CCC认证流程,确保产品合规通过

CCC认证是指中国强制性产品认证制度&#xff0c;也是中国国家质量监督检验检疫总局实施的一项重要认证制度。对于想要在中国市场销售的产品来说&#xff0c;CCC认证是必不可少的步骤。本文将详细介绍CCC认证的流程&#xff0c;帮助您了解并确保产品顺利通过认证。 第一步&#…

智能监控,高效观测 IT 系统瓶颈

前言 云原生时代的监控系统贯穿于移动端、前端、业务服务端、中间件、应用层、操作系统等&#xff0c;渗透 IT 系统的各个环节。因此&#xff0c;在构建 IT 系统之初&#xff0c;就需要考虑如何打造一个完善的监控系统。当面临大量业务流量数据时&#xff0c;借助监控进行问题…

FreeRTOS列表和列表项

FreeRTOS内核调度使用了大量的列表&#xff08;list&#xff09;和列表项&#xff08;listitem&#xff09;数据结构。它的源码中涉及到很多列表的操作&#xff0c;对于FreeRTOS来说&#xff0c;列表就是它最基础的一部分&#xff0c;列表被用作FreeRTOS调度器使用&#xff0c;…

C语言--判断年月日是否合理

一.题目描述 比如输入2001&#xff0c;2&#xff0c;29&#xff0c;输出&#xff1a; 不合理 。因为平年的二月只有28天 比如输入2000&#xff0c;6&#xff0c;31&#xff0c;输出&#xff1a;不合理。因为6月是小月&#xff0c;只有30天。 二.思路分析 本题主要注意两个问…

Android : ListView + BaseAdapter-2简单应用

​​容器与适配器&#xff1a;​​​​​ http://t.csdnimg.cn/ZfAJ7 实体类 News.java package com.example.mylistviewadapter2.entity;public class News {private String title;private String content;private int img;public News(String title, String conte…

CentOS 7 使用pugixml 库

安装 pugixml Git下载地址&#xff1a;https://github.com/zeux/pugixml 步骤1&#xff1a;首先&#xff0c;你需要下载pugixml 的源代码。你可以从Github或者源代码官方网站下载。并上传至/usr/local/source_code/ 步骤2&#xff1a;下载完成后&#xff0c;需要将源代码解压…

【MySQL】多表查询、子查询、自连接、合并查询详解,包含大量示例,包你会。

复合查询 前言正式开始一些开胃菜多表查询自连接子查询单行子查询多行子查询in关键字all关键字any关键字多列子查询在from中使用子查询 合并查询union 和 union all 前言 我前面博客讲的所有的查询都是在单表中进行的&#xff0c;从这里开始就要专门针对查询这个话题进行进一步…

STM32-标准库和HAL库-不同容量系列的代码移植

使用STM32单片机过程中经常会涉及到不同芯片间的代码转换&#xff0c;手头上熟悉的工程需要稍作处理才能用到新的板子上。常见的是STM32F103xE、STM32F103xC&#xff08;大容量&#xff09;和STM32F103x8、STM32F103xB&#xff08;中容量&#xff09;的转换。这里做一下总结&am…

93.STL-系统内置仿函数

目录 算术仿函数 关系仿函数 逻辑仿函数 C 标准库中提供了一些内置的函数对象&#xff0c;也称为仿函数&#xff0c;它们通常位于 <functional> 头文件中。以下是一些常见的系统内置仿函数&#xff1a; 算术仿函数 功能描述&#xff1a; 实现四则运算其中negate是一元…

PTA-6-45 工厂设计模式-运输工具

题目如下&#xff1a; 工厂类用于根据客户提交的需求生产产品&#xff08;火车、汽车或拖拉机&#xff09;。火车类有两个子类属性&#xff1a;车次和节数。拖拉机类有1个子类方法耕地&#xff0c;方法只需简单输出“拖拉机在耕地”。为了简化程序设计&#xff0c;所有…

依托数据、平台、知识增强等优势 夸克大模型大幅降低问答幻觉率

“大模型时代&#xff0c;夸克有巨大机会创造出革新性搜索产品。”11月22日&#xff0c;夸克大模型公布了其面向搜索、生产力工具和资产管理助手的大模型技术布局。数据显示&#xff0c;夸克千亿级参数大模型登顶C-Eval和CMMLU两大权威榜单&#xff0c;夸克百亿级参数大模型同样…

Linux-编译器

编译器 gcc-arm-linux-gnueabihf gcc-arm-linux-gnueabihf 是一个针对 ARM 架构 Linux 系统的交叉编译工具链&#xff0c;它包括了 C、C、Objective-C 和 Fortran 编译器以及一些辅助工具&#xff0c;用于将源代码编译成可在 ARM 架构的 Linux 系统上运行的二进制程序。arm架…

2023年,人工智能在医疗行业领域的应用场景

本期行业洞察将带领大家了解人工智能在医疗行业领域的应用&#xff0c;主要了解在患者治疗和运营中的应用、人工智能作为预防工具以及大型医院目前如何使用人工智能。未来的智慧医疗时代已经悄然到来。 人工智能在患者治疗和机构运营中的应用 人工智能有望彻底改变医疗护理的…

基本的弹层,点击弹出

<div class"role"><el-button type"primary" size"mini" click"showDialog true">添加角色</el-button></div><!--控制弹框的显示隐藏visible .sync可以点击X关闭弹框 --> <el-dialog width"…

C语言从入门到实战——数组和指针的强化练习题

数组和指针的强化练习题 前言1. sizeof和strlen的对比1.1 sizeof1.2 strlen1.3 sizeof和strlen的对⽐ 2. 数组和指针笔试题解析2.1 一维数组2.2 字符数组2.3 二维数组 3. 指针运算笔试题解析3.1 题目1&#xff1a;3.2 题目23.3 题目33.4 题目43.5 题目53.6 题目63.7 题目7 前言…

如何解决msvcp110.dll丢失问题,分享5个有效的解决方法

最近&#xff0c;我在使用电脑时遇到了一个令人头疼的问题——msvcp110.dll丢失。这个错误通常会导致某些应用程序无法正常运行。为了解决这个问题&#xff0c;我们需要采取一些有效的方法来修复丢失的msvcp110.dll文件。那么&#xff0c;msvcp110.dll到底是什么呢&#xff1f;…