Java modbus 实现RTU串口作为slave(服务端)读写数据

news2025/1/18 21:13:27

这里要了解下modbus的RTU和TCP 的几个名称关系:

Modbus/RTU:主站 和从站 关系

Modbus/TCP:客户端和服务端关系

关系

主站主动找从站读写数据
客户端主动找服务端读写数据

所以当使用Modbus/TCP时,主站一般作为客户端,从站一般作为服务端

modbus poll和modbus slave模拟软件

当使用Modbus/TCP时,modbus poll一般模拟客户端,modbus slave一般模拟服务端。

以上这几个关系必须了解,否则容易搞混乱。

modbus协议是工业使用比较多的协议,大部分设备都支持modbus的,也就是说,通过modbus可以获取市场上90%的设备,一般新设备都支持modbus。

modbus有几种协议:

modbusTCP、modbusRTU、modbusRTUOVERTCP(本质tcp,需要单独解析)、ASCII(不常用,可以忽略)

Modbus RTU和Modbus TCP两个协议的本质都是Modbus协议,都是靠Modbus寄存器地址来交换数据;但所用的硬件接口不一样,Modbus RTU一般采用串口RS232C或RS485/422,而Modbus TCP一般采用以太网口。现在市场上有很多协议转换器,可以轻松的将这些不同的协议相互转换。
实际上Modbus协议包括ASCII、RTU、TCP。
Modbus协议需要对数据进行校验,串行协议中除有奇偶校验外,ASCII模式采用LRC校验,RTU模式采用16位CRC校验.
Modbus TCP模式没有额外规定校验,因为TCP协议是一个面向连接的可靠协议。
TCP和RTU协议非常类似,只要把RTU协议的两个字节的校验码去掉,然后在RTU协议的开始加上5个0和一个6并通过TCP/IP网络协议发送出去即可。

以上应该可以理解modbus到底干啥的了,明白后,我们开始做测试,整理流程比较长。

先说工具准备情况:

1、虚拟串口工具 vspd,正常安装即可(目的是模拟串口,如果是tcp 协议用不到它)

2、modbus 仿真工具,这个工具很好用,也经常使用

3、java依赖,该依赖比较强大,强推

       <dependency>
            <groupId>com.intelligt.modbus</groupId>
            <artifactId>jlibmodbus</artifactId>
            <version>1.2.9.11</version>
        </dependency>

模拟工具和仿真工具下载。

1、串口模拟工具正常安装即可,然后把补丁进行覆盖安装目录,否则只有14天试用期,建议覆盖,永久使用(安装过程省略)

安装成功后,添加串口,默认是COM2和COM3 两个端口,就用这两个就可以了。

我这边是COM2个slave用,也就是tcp的服务端哈,COM3给master用,也就是tcp的客户端。

其实这块在写代码之前可以进行用modbus 仿真工具进行测试下,例如:

1、打开modbus slave;选择串口

协议类型选择:串口

串口设置,这块根据你的串口模拟工具,我把COM2 slave了,如果是真实设备,具体连接到真实设备的串口即可。

其他的设置,根据具体情况来即可。

点击ok,

应该可以看到模拟工具在跑数据了哈

可以看到串口模拟工具已经被modbus slave模拟器连上了 9600-N-8-1 就是刚才配置的其他参数信息,了解就行。

可以看到COM3的Port 是closed状态,我们这时开始启动poll模拟器。

和slave设置很像,我这边细节就不说了,有个注意点串口要连COM3,因为COM2已经被slave占用了(这里因为是模拟的设备,COM2和COM3 模拟器帮我们进行连接了)。

看modbus模拟器数据已经连上了,也获取到数据了:

串口模拟器也显示连上了:

如果报错,请检查内存起止地址和内存数量。这里通过工具进行模拟的,整体是没问题的,说明环境都是没问题的,确保在编码前环境一定没问题,否则只用用代码容易出问题;可以进行编码了。

用java进行连接,其实我的理解,哪种语言连接都是差不多的,比较简单,直接上代码了哈:

监听接口:

public interface ModbusEventListener {

    /**
     * 描述
     * 单个线圈写入监听  function=01 、 02
     *
     * @param address 内存地址
     * @param value   值
     * @return void
     * @author
     * @date 2024/5/11 15:30:31
     */
    default void onWriteToSingleCoil(int address, boolean value) {
        System.out.print("onWriteToSingleCoil: address " + address + ", value " + value);
    }

    /**
     * 描述
     * 批量线圈写入监听  function=01 、 02
     *
     * @param address  地址
     * @param quantity 数量
     * @param values   值
     * @return void
     * @author
     * @date 2024/5/11 15:31:20
     */
    default void onWriteToMultipleCoils(int address, int quantity, boolean[] values) {
        System.out.print("onWriteToMultipleCoils: address " + address + ", quantity " + quantity);
    }

    /**
     * 描述
     * 读保持寄存器	  function=03
     *
     * @param address 地址
     * @param value   值
     * @return void
     * @author 
     * @date 2024/5/11 15:32:26
     */
    void onWriteToSingleHoldingRegister(int address, int value);

    /**
     * 描述
     * 读保持寄存器	  function=03
     *
     * @param address  地址
     * @param quantity 数量
     * @param values   多个值
     * @return void
     * @author
     * @date 2024/5/11 15:49:22
     */
    void onWriteToMultipleHoldingRegisters(int address, int quantity, int[] values);

    /**
     * 描述
     * 获取监听类型
     *
     * @param
     * @return com.goldstar.common.utils.constants.GlobalConstants.ModbusListenerType
     * @author 
     * @date 2024/5/13 10:54:14
     */
    String getListenerType();


}

dataholder:

/**
 * 从机的寄存器
 */
public class CustomDataHolder extends DataHolder {

    final List<ModbusEventListener> modbusEventListenerList = new ArrayList();


    public CustomDataHolder() {
        // you can place the initialization code here
            /*
            something like that:
            setHoldingRegisters(new SimpleHoldingRegisters(10));
            setCoils(new Coils(128));
            ...
            etc.
             */
    }

    public void addEventListener(ModbusEventListener listener) {
        modbusEventListenerList.add(listener);
    }

    public boolean removeEventListener(ModbusEventListener listener) {
        return modbusEventListenerList.remove(listener);
    }

    @Override
    public void writeHoldingRegister(int offset, int value) throws IllegalDataAddressException, IllegalDataValueException {
        System.out.println("writeHoldingRegister: offset " + offset + ", value " + value);
        for (ModbusEventListener l : modbusEventListenerList) {
            l.onWriteToSingleHoldingRegister(offset, value);
        }
        super.writeHoldingRegister(offset, value);
    }

    @Override
    public void writeHoldingRegisterRange(int offset, int[] range) throws IllegalDataAddressException, IllegalDataValueException {
        System.out.println("writeHoldingRegisterRange: offset " + offset + ", range " + range);
        for (ModbusEventListener l : modbusEventListenerList) {
            l.onWriteToMultipleHoldingRegisters(offset, range.length, range);
        }
        super.writeHoldingRegisterRange(offset, range);
    }

    @Override
    public void writeCoil(int offset, boolean value) throws IllegalDataAddressException, IllegalDataValueException {
        System.out.println("writeCoil: offset " + offset + ", value " + value);
        for (ModbusEventListener l : modbusEventListenerList) {
            l.onWriteToSingleCoil(offset, value);
        }
        super.writeCoil(offset, value);
    }

    @Override
    public void writeCoilRange(int offset, boolean[] range) throws IllegalDataAddressException, IllegalDataValueException {
        System.out.println("writeCoilRange: offset " + offset + ", range " + range);
        for (ModbusEventListener l : modbusEventListenerList) {
            l.onWriteToMultipleCoils(offset, range.length, range);
        }
        super.writeCoilRange(offset, range);
    }
}

modbus slave服务 

public class ModbusSlaveService {


    private String modbusType = "";

    private ModbusSlave modbusSlave;

    // 创建从机的寄存器
    private CustomDataHolder dataHolder = new CustomDataHolder();

    //禁止无参构造函数创建对象
    private ModbusSlaveService() {
    }

    public ModbusSlaveService(@NonNull TcpParameters tcpParameters, @NonNull Integer serverId) {
        this.modbusSlave = ModbusSlaveFactory.createModbusSlaveTCP(tcpParameters);
        modbusSlave.setReadTimeout(0); // if not set default timeout is 1000ms, I think this mus
        // 为从机寄存器添加监听事件,这里的监听事件主要是主机如果发送写命令修改从机则进行业务处理
        //  dataHolder.addEventListener(new DefaultModbusEventListener());
        modbusSlave.setDataHolder(dataHolder);
        modbusSlave.setServerAddress(serverId);
        modbusType = "协议类型:tcp, ip: " + tcpParameters.getHost() + ":" + tcpParameters.getPort();
    }

    public ModbusSlaveService(@NonNull SerialParameters serialParameters, @NonNull Integer serverId) throws SerialPortException {
        this.modbusSlave = ModbusSlaveFactory.createModbusSlaveRTU(serialParameters);
        modbusSlave.setReadTimeout(0); // if not set default timeout is 1000ms, I think this mus
        // 为从机寄存器添加监听事件,这里的监听事件主要是主机如果发送写命令修改从机则进行业务处理
        //  dataHolder.addEventListener(new DefaultModbusEventListener());
        modbusSlave.setDataHolder(dataHolder);
        modbusSlave.setServerAddress(serverId);

        modbusType = "协议类型:RTU(串口), 串口号: " + serialParameters.getDevice();
    }

    /**
     * 注册相关点位数据;用来服务端写到客户端数据
     *
     * @param modbusHoldingRegisters
     * @return
     */
    public ModbusSlaveService addHoldingRegisters(ModbusHoldingRegisters modbusHoldingRegisters) {
        if (modbusHoldingRegisters == null) {
            return this;
        }
        modbusSlave.getDataHolder().setHoldingRegisters(modbusHoldingRegisters);
        return this;
    }

    /**
     * 注册相关点位数据;用来服务端写到客户端数据
     *
     * @param modbusCoils
     * @return
     */
    public ModbusSlaveService addModbusCoils(ModbusCoils modbusCoils) {
        if (modbusCoils == null) {
            return this;
        }
        modbusSlave.getDataHolder().setCoils(modbusCoils);
        return this;
    }

    public ModbusSlaveService addModbusInputRegisters(ModbusHoldingRegisters inputRegisters) {
        if (inputRegisters == null) {
            return this;
        }
        modbusSlave.getDataHolder().setInputRegisters(inputRegisters);
        return this;
    }

    /**
     * 数据监听器,用来监听 客户端写入到数据,进行相关处理
     *
     * @param listener
     * @return
     */
    public ModbusSlaveService addEventListener(ModbusEventListener listener) {
        dataHolder.addEventListener(listener);
        return this;
    }

    public ModbusSlaveService removeEventListener(ModbusEventListener listener) {
        dataHolder.removeEventListener(listener);
        return this;
    }

    /**
     * 开启监听
     *
     * @return
     * @throws Exception
     */
    public ModbusSlaveService startListen() throws Exception {
        modbusSlave.listen();
        log.info("{} ----当前服务已启动", modbusType);
        closeSlave();
        return this;
    }

    /**
     * 关闭modbus 服务
     *
     * @throws InterruptedException
     * @throws ModbusIOException
     */
    private void closeSlave() throws InterruptedException, ModbusIOException {
        //这部分代码主要是设置Java虚拟机关闭的时候需要做的事情,即本程序关闭的时候需要做的事情,直接使用即可
        if (modbusSlave.isListening()) {
            Runtime.getRuntime().addShutdownHook(new Thread(() -> {
                synchronized (modbusSlave) {
                    modbusSlave.notifyAll();
                }
            }));

            synchronized (modbusSlave) {
                modbusSlave.wait();
            }
            modbusSlave.shutdown();
            log.info("{} ----当前服务已关闭", modbusType);

        }
    }

    /**
     * 手动进行关闭服务
     */
    public void closeModbusSlave() {
        try {
            modbusSlave.shutdown();
            log.info("{} ----当前服务已手动关闭", modbusType);
        } catch (ModbusIOException e) {
            throw new RuntimeException(e);
        }

    }

    public static void main(String[] args) throws Exception {      

       SerialParameters serialParameters = new SerialParameters();
        serialParameters.setDevice("COM2");
        serialParameters.setParity(SerialPort.Parity.NONE);
        //  SerialPort.BaudRate baudrate = new SerialPort.BaudRate(921600);
        // serialParameters.setBaudRate(baudrate);
        serialParameters.setBaudRate(SerialPort.BaudRate.BAUD_RATE_9600);
        serialParameters.setDataBits(8);
        serialParameters.setStopBits(1);

        ModbusSlaveService modbusSlaveService1 = new ModbusSlaveService(serialParameters, 1);
        //modbusSlaveService1.addEventListener(new DefaultModbusEventListener());
        modbusSlaveService1.addEventListener(new ModbusEventListener() {
            @Override
            public void onWriteToSingleCoil(int address, boolean value) {
                log.info("onWriteToSingleCoil({},{})", address, value);
            }

            @Override
            public void onWriteToMultipleCoils(int address, int quantity, boolean[] values) {
                log.info("onWriteToMultipleCoils({},{},{})", address, quantity, values);
            }

            @Override
            public void onWriteToSingleHoldingRegister(int address, int value) {
                log.info("onWriteToSingleHoldingRegister({},{})", address, value);
            }

            @Override
            public void onWriteToMultipleHoldingRegisters(int address, int quantity, int[] values) {
                log.info("onWriteToMultipleHoldingRegisters({},{},{})", address, quantity, values);
            }


            @Override
            public String getListenerType() {
                return "";
            }

        });
        //更新寄存器值
        ModbusHoldingRegisters hr1 = new ModbusHoldingRegisters(10);
        //主机发送数据
        ThreadUtil.execute(() -> {
            while (true) {
                ThreadUtil.sleep(1000);
                try {
                    hr1.set(0, RandomUtil.randomInt(0, 10000));
                    hr1.set(1, RandomUtil.randomInt(0, 10000));
                    hr1.set(2, RandomUtil.randomInt(0, 10000));
                    hr1.set(3, RandomUtil.randomInt(0, 10000));
                    hr1.set(4, RandomUtil.randomInt(0, 10000));
                    log.info("COM数据:{}", JSONUtil.toJsonStr(hr1));
                    modbusSlaveService1.addHoldingRegisters(hr1);
                } catch (IllegalDataAddressException e) {
                    throw new RuntimeException(e);
                } catch (IllegalDataValueException e) {
                    throw new RuntimeException(e);
                }

            }
        });

        modbusSlaveService1.startListen();
        


    }


}

测试代码说明:

 public static void main(String[] args) throws Exception { 
//串口参数实体类
        SerialParameters serialParameters = new SerialParameters();
        //这是设置串口 刚才上面说了,用COM2作为slave
        serialParameters.setDevice("COM2");
        //用模拟器时的其他几个参数设置
        serialParameters.setParity(SerialPort.Parity.NONE);
        //  SerialPort.BaudRate baudrate = new SerialPort.BaudRate(921600);
        // serialParameters.setBaudRate(baudrate);
        serialParameters.setBaudRate(SerialPort.BaudRate.BAUD_RATE_9600);
        serialParameters.setDataBits(8);
        serialParameters.setStopBits(1);
        //new modbus slave 对象
        ModbusSlaveService modbusSlaveService1 = new ModbusSlaveService(serialParameters, 1);
        //modbusSlaveService1.addEventListener(new DefaultModbusEventListener());
        //添加监听;此处监听是为了让 master写数据时,slave能监听到,这样就可以相互通信了,这是扩展项
        modbusSlaveService1.addEventListener(new ModbusEventListener() {
            @Override
            public void onWriteToSingleCoil(int address, boolean value) {
                log.info("onWriteToSingleCoil({},{})", address, value);
            }

            @Override
            public void onWriteToMultipleCoils(int address, int quantity, boolean[] values) {
                log.info("onWriteToMultipleCoils({},{},{})", address, quantity, values);
            }

            @Override
            public void onWriteToSingleHoldingRegister(int address, int value) {
                log.info("onWriteToSingleHoldingRegister({},{})", address, value);
            }

            @Override
            public void onWriteToMultipleHoldingRegisters(int address, int quantity, int[] values) {
                log.info("onWriteToMultipleHoldingRegisters({},{},{})", address, quantity, values);
            }


            @Override
            public String getListenerType() {
                return "";
            }

        });
        //更新寄存器值,每个一秒更新一次数据
        ModbusHoldingRegisters hr1 = new ModbusHoldingRegisters(10);
        //主机发送数据;这里如果是真实场景的业务,就是业务数据了,我这边通过随机生成的数据进行模拟的,大家根据自己的情况进行设置即可
        ThreadUtil.execute(() -> {
            while (true) {
                ThreadUtil.sleep(1000);
                try {
                    hr1.set(0, RandomUtil.randomInt(0, 10000));
                    hr1.set(1, RandomUtil.randomInt(0, 10000));
                    hr1.set(2, RandomUtil.randomInt(0, 10000));
                    hr1.set(3, RandomUtil.randomInt(0, 10000));
                    hr1.set(4, RandomUtil.randomInt(0, 10000));
                    log.info("COM数据:{}", JSONUtil.toJsonStr(hr1));
                    modbusSlaveService1.addHoldingRegisters(hr1);
                } catch (IllegalDataAddressException e) {
                    throw new RuntimeException(e);
                } catch (IllegalDataValueException e) {
                    throw new RuntimeException(e);
                }

            }
        });
        //启动监听
        modbusSlaveService1.startListen();
      } 

上面明白后,咱们运行起来:

1、开发工具日志:

已经启动了,再看看串口模拟器:

这里可以看到,COM2已经换成了java.exe了,这就对了

在看poll工具:

数据实时读取到了,我们测试下poll也就是master 发送数据,slave能否接收到:

Ok,slave 发送master(poll)  和master(poll) 发送slave 都是没问题的,完美解决,后面进行业务集成即可。

总结说明:

其实工业的协议要比TCP简单很多,逻辑不复杂,大家尝试下就明白了,modbusTCP 相互通信更简单了,这里不进行演示了,上面代码其实我已经写了,大家可以写下测试代码就支持tcp了,Ok到此结束。

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

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

相关文章

C/C++:Windows动态链接库

动态链接库&#xff08;Dynamic Link Library&#xff0c;简称DLL&#xff09;是在运行时加载的库&#xff0c;它们的代码和数据在内存中与目标程序共享&#xff1b;这意味着多个程序可以共享相同的库实例&#xff0c;并且库的代码可以在不重新编译目标程序的情况下更新。 工作…

怎么转换音频?看这3款音频转换器

随着数字媒体的发展&#xff0c;音频文件在我们的日常生活中占据了越来越重要的地位。有时候在不同的应用场景里&#xff0c;无论是音乐、语音还是其他类型的音频内容&#xff0c;我们都需要对其进行转换以满足不同的需求。 本文将为您介绍3款常用的音频转换器&#xff0c;帮助…

基于.NetCore和ABP.VNext的项目实战一:abp cli 搭建项目

学习了阿星Plus的博客项目,自己也试着搭建自己的博客。 ABP和ABP.VNext的主要区别在于核心库的精简、对领域驱动设计(DDD)的关注、以及使用的技术栈。 1、ABP VNext的核心库相比ABP更加精简,它将原有许多组件从核心库中抽离成独立的组件,这使得开发者可以更灵活地选择需要…

Github新手入门使用方法

**存在问题&#xff1a;**新手如何快速入门github&#xff0c;能够下载开源文件&#xff0c;并且修改后更新远程github仓库&#xff1b; 解决方案&#xff1a; 参考&#xff1a; http://www.360doc.com/content/24/0301/12/60419_1115656653.shtml https://blog.csdn.net/gongd…

Python环境变量的访问:从入门到精通

环境变量是操作系统中的一种特殊变量&#xff0c;它允许用户在不修改程序的情况下&#xff0c;通过配置文件来改变程序的行为。在Python中&#xff0c;访问环境变量是一个常见的需求&#xff0c;无论是为了读取配置信息、获取系统信息&#xff0c;还是进行程序调试。本文将详细…

荆州科技局副局长乔梁莅临湖北点赋网络科技公司参观调研

近日&#xff0c;荆州科技局副局长乔梁&#xff0c;莅临湖北点赋网络科技公司进行参观调研。点赋科技总经理崔梦娇亲自陪同&#xff0c;向副局长介绍了公司的D咖智能饮品机器人经营状况和研发进展情况。 在参观过程中&#xff0c;副局长乔梁对点赋科技的创新能力和技术成果给予…

商业模式都验证不了,还搞APP,莫非想早死早投胎。

有几个原因可以解释为什么大部分互联网创业者选择先开发小程序而不是直接做App&#xff1a; 低成本和快速开发&#xff1a;相比于开发一个完整的App&#xff0c;开发小程序的成本更低且开发周期更短。小程序可以在现有的移动平台上运行&#xff0c;无需独立的安装和更新&#…

地产人的福音!VR全景分屏对比,让装修施工一目了然

现如今&#xff0c;VR全景已成为地产行业不可或缺的应用工具&#xff0c;从地产直播到楼市VR地图&#xff0c;从效果图到水电家装施工记录&#xff0c;可以说整个地产行业的上下游生态中都可以看到720云VR全景的身影。 以720云VR全景作为直播载体 VR全景高清矩阵地图等多种内容…

干部民主测评:深化管理智慧,凝聚团队力量

在现代化组织管理的广阔舞台上&#xff0c;干部民主测评扮演着举足轻重的角色。它不仅是评价干部工作实绩、能力素质的有力工具&#xff0c;更是推动组织向民主化、科学化、规范化迈进的强大引擎。通过民主测评&#xff0c;我们能够深入洞察每位干部的工作表现、群众基础和领导…

好物分享类视频带货怎么做?萤瓴优选开启爆款视频领取模式!千万不要错过!

好物分享类视频带货&#xff0c;作为当下热门的电商营销方式&#xff0c;正以其独特的魅力和效果吸引着越来越多的 keJ0277 商家和消费者。在这个充满机遇和挑战的时代&#xff0c;如何成功打造一款爆款好物分享视频&#xff0c;成为了众多商家关注的焦点。萤瓴优选&#xff0c…

【js刷题:数据结构链表篇之移除链表元素】

移除链表元素 一、定义链表节点&#xff08;面试时要自己写&#xff09;二、题目三、移除头节点1、直接在原链表中操作移除2、设置一个虚拟头结点在再进行删除操作 四、解题代码 一、定义链表节点&#xff08;面试时要自己写&#xff09; class ListNode {val;next null;cons…

最新VS code配置C/C++环境(tasks.json, launch.json,c_cpp_properties.json)及运行多个文件、配置Cmake

目录 一、VScode配置C/C环境&#xff0c;需设置tasks.json, launch.json文件 二、安装C/C扩展&#xff0c;配置tasks.json、launch.json、c_cpp_properties.json文件 (1)安装c/c扩展 (2)配置tasks.json文件 (3)配置launch.json文件 (4)配置中的参数(属性)说明 (5)运行程序(运行…

JINGWHALE 数字科学艺术创新中心

使命宗旨 JINGWHALE 数字科学艺术创新中心 以人文思想&#xff0c;结合自然科学&#xff0c;知行合一的践行人类数字化共产事业&#xff01;凝聚创造智慧&#xff0c;指导引领创建更美好的物质世界&#xff0c;获得更好的精神体验&#xff01; JINGWHALE 全人类数字共产主义理…

Oracle sqlnet.ora配置文件

一、作用 这里可以看官网解释Parameters for the sqlnet.ora File (oracle.com) 该文件是配置文件配置文件。它驻留在客户端计算机和数据库服务器上。配置文件使用此文件进行存储和实现。可以使用文件中的访问控制参数配置数据库服务器。这些参数根据协议.sqlnet.orasqlnet.o…

59.基于SSM实现的网上花店系统(项目 + 论文)

项目介绍 本站是一个B/S模式系统&#xff0c;网上花店是在MySQL中建立数据表保存信息&#xff0c;运用SSMVue框架和Java语言编写。并按照软件设计开发流程进行设计实现充分保证系统的稳定性。系统具有界面清晰、操作简单&#xff0c;功能齐全的特点&#xff0c;使得基于SSM的网…

宝兰德成为中国信通院政企信创促进中心成员 共谱信创产业新篇章

近日&#xff0c;中国信通院云计算标准和开源推进委员会2024年第一次全体工作会议圆满结束。会上&#xff0c;宝兰德获得由中国信通院和EDCC政企信息技术应用创新促进中心授予的荣誉证书&#xff0c;成为政企信创促进中心成员单位。 关于政企信创促进中心 中国信通院政企信创促…

langchain_community切分各种文档数据;加载向量模型;使用向量库

参考: https://github.com/langchain-ai/langchain https://api.python.langchain.com/en/latest/community_api_reference.html https://github.com/shibing624/ChatPilot/blob/384f18e4f10f87e10f104f9ff57f02c655588035/chatpilot/apps/rag_app.py 安装: pip instal…

视频号小店怎么做?详细步骤分享,简单易学!

哈喽&#xff0c;大家好&#xff0c;我是醒醒团队的电商花花。 视频号小店电商最近我们应该也听到过不少&#xff0c;这个项目作为一个新平台电商项目&#xff0c;有着很大的流量和市场&#xff0c;值得我们去投资去深入。 而且视频号小店项目我们不用囤货&#xff0c;发货&a…

全球量子计算已开始商业化!应用最多的行业你一定想不到

内容来源&#xff1a;量子前哨&#xff08;ID&#xff1a;Qforepost&#xff09; 文丨卉可 排版丨沛贤 深度好文&#xff1a;2600字丨5 分钟阅读 01 量子计算是一场高风险的游戏 近日&#xff0c;PsiQuantum从澳大利亚联邦政府和地方政府获得了10亿澳元资金&#xff0c;这…

Kubernetes集群自动化部署

目录 1.1 实验介绍 1.1.1 关于本实验 1.1.2 实验目的 1.2 环境准备 步骤 1 设置节点名 步骤 2 配置 hosts 节点名解析 步骤 3 配置免密登录 步骤 4 清空 iptables、关闭防火墙并禁用 selinux 步骤 5 关闭交换分区 步骤 6 开启 ipvs 步骤 7 设置时间同步 步骤 8 配置…