信雅纳网络测试的二次开发集成:XOA(Xena Open-Source Automation)开源自动化测试

目录

XOA是什么

XOA CLI

XOA Python API

​XOA Python Test Suite/测试套件

XOA Converter

Source Code


XOA是什么

XOA(Xena Open-Source Automation)是一个开源的测试自动化框架,追求“高效、易用、灵活”的跨操作系统的开发框架。能与Xena现有解决方案无缝配合,借助XOA可调用Xena(Z系列打流仪、E系列损伤仪)完成自动化测试任务。同时它提供了操作接口可将其他仪表/设备做并栈集成测试验证,统一整理输出测试报告。

XOA包含:
XOA CLI、XOA Python API、XOA Python TestSuite、XOA Converter

信雅纳:网络测试自动化

XOA CLI

XOA CLI 提供了一套简洁直观的基于文本语言的独立命令,用以控制和集成 Xena测试仪硬件,实现各种测试任务的自动化。
任何客户端平台/编程语言(如 Python、Tcl、Bash)都可与 XOA CLI 配合使用。
CLI 可在远程登录终端上使用,直接向 Xena 测试仪发送命令。
ValkyrieManager通过测试端口配置文件(.xpc ),可在 XOA CLI 环境之间无缝转换。

XOA Python API

XOA Python API与XOA CLI和XenaManager无缝集成

  • 面向对象的高级抽象: XOA Python API采用面向对象的方法,提供了更高层次的抽象,加快了自动化脚本的开发。
  • 集成开发环境自动完成,内置手册: XOA Python API 包含 IDE 自动完成以及类、函数和 API 内置手册等功能,可显著提高开发效率。
  • 命令分组和响应自动匹配:该功能允许命令分组和响应自动匹配,从而优化了测试执行效率。
  • 服务器到客户端推送通知订阅: XOA Python API 支持服务器到客户端的推送通知订阅,降低了用户代码的复杂性。
  • 支持 Python 3.8 及更高版本: XOA Python API 兼容 Python 3.8 及更高版本,确保与现代 Python 环境兼容。
    import asyncio
    from contextlib import suppress
    from xoa_driver import testers
    from xoa_driver import modules
    from xoa_driver import ports
    from xoa_driver import utils
    from xoa_driver import enums
    from xoa_driver import exceptions
    from ipaddress import IPv4Address, IPv6Address
    from binascii import hexlify
    from xoa_driver.misc import Hex
    
    #---------------------------
    # Global parameters
    #---------------------------
    
    CHASSIS_IP = "10.165.16.70"      # Chassis IP address or hostname
    USERNAME = "XOA"                # Username
    MODULE_INDEX = 4                # Module index
    TX_PORT_INDEX = 0               # TX Port index
    
    FRAME_SIZE_BYTES = 4178         # Frame size on wire including the FCS.
    FRAME_COUNT = 20              # The number of frames including the first, the middle, and the last.
    REPETITION = 1                  # The number of repetitions of the frame sequence, set to 0 if you want the port to repeat over and over
    TRAFFIC_RATE_FPS = 100          # Traffic rate in frames per second
    TRAFFIC_RATE_PERCENT = int(4/10 * 1000000)
    
    SHOULD_BURST = False            # Whether the middle frames should be bursty
    BURST_SIZE_FRAMES = 9           # Burst size in frames for the middle frames
    INTER_BURST_GAP_BYTES = 3000    # The inter-burst gap in bytes
    INTRA_BURST_GAP_BYTES = 1000    # The inter-frame gap within a burst, aka. intra-burst gap, in bytes
    
    
    
    #---------------------------
    # Header content for streams
    #---------------------------
    class Ethernet:
        def __init__(self):
            self.dst_mac = "0000.0000.0000"
            self.src_mac = "0000.0000.0000"
            self.ethertype = "86DD"
        
        def __str__(self):
            _dst_mac = self.dst_mac.replace(".", "")
            _src_mac = self.src_mac.replace(".", "")
            _ethertype = self.ethertype
            return f"{_dst_mac}{_src_mac}{_ethertype}".upper()
        
    class IPV4:
        def __init__(self):
            self.version = 4
            self.header_length = 5
            self.dscp = 0
            self.ecn = 0
            self.total_length = 42
            self.identification = "0000"
            self.flags = 0
            self.offset = 0
            self.ttl = 255
            self.proto = 255
            self.checksum = "0000"
            self.src = "0.0.0.0"
            self.dst = "0.0.0.0"
    
        def __str__(self):
            _ver = '{:01X}'.format(self.version)
            _header_length = '{:01X}'.format(self.header_length)
            _dscp_ecn = '{:02X}'.format((self.dscp<<2)+self.ecn)
            _total_len = '{:04X}'.format(self.total_length)
            _ident = self.identification
            _flag_offset = '{:04X}'.format((self.flags<<13)+self.offset)
            _ttl = '{:02X}'.format(self.ttl)
            _proto = '{:02X}'.format(self.proto)
            _check = self.checksum
            _src = hexlify(IPv4Address(self.src).packed).decode()
            _dst = hexlify(IPv4Address(self.dst).packed).decode()
            return f"{_ver}{_header_length}{_dscp_ecn}{_total_len}{_ident}{_flag_offset}{_ttl}{_proto}{_check}{_src}{_dst}".upper()
    
    class IPV6:
        def __init__(self):
            self.version = 6
            self.traff_class = 8
            self.flow_label = 0
            self.payload_length = 0
            self.next_header = "11"
            self.hop_limit = 1
            self.src = "2000::2"
            self.dst = "2000::100"
    
        def __str__(self):
            _ver = '{:01X}'.format(self.version)
            _traff_class = '{:01X}'.format(self.traff_class)
            _flow_label = '{:06X}'.format(self.flow_label)
            _payload_len = '{:04X}'.format(self.payload_length)
            _next_header = self.next_header
            _hop_limit = '{:02X}'.format(self.hop_limit)
            _src = hexlify(IPv6Address(self.src).packed).decode()
            _dst = hexlify(IPv6Address(self.dst).packed).decode()
            return f"{_ver}{_traff_class}{_flow_label}{_payload_len}{_next_header}{_hop_limit}{_src}{_dst}".upper()
    
    class UDP:
        def __init__(self):
            self.src_port = 0
            self.dst_port = 0
            self.length = 0
            self.checksum = 0
    
        def __str__(self):
            _src_port = '{:04X}'.format(self.src_port)
            _dst_port = '{:04X}'.format(self.dst_port)
            _length = '{:04X}'.format(self.length)
            _checksum = '{:04X}'.format(self.checksum)
            return f"{_src_port}{_dst_port}{_length}{_checksum}".upper()
    
    class ROCEV2:
        def __init__(self):
            self.opcode = 0
            self.solicited_event = 0
            self.mig_req = 0
            self.pad_count = 1
            self.header_version = 0
            self.partition_key = 65535
            self.reserved = 7
            self.dest_queue_pair = 2
            self.ack_request = 0
            self.reserved_7bits = 0
            self.packet_seq_number =0
    
        def __str__(self):
            _opcode = '{:02X}'.format(self.opcode)
            _combo_1 = '{:02X}'.format((self.solicited_event<<7)+(self.mig_req<<6)+(self.pad_count<<4)+self.header_version)
            _pk = '{:04X}'.format(self.partition_key)
            _reserved = '{:02X}'.format(self.reserved)
            _qp = '{:06X}'.format(self.dest_queue_pair)
            _combo_2 = '{:02X}'.format((self.ack_request<<7)+self.reserved_7bits)
            _ps = '{:06X}'.format(self.packet_seq_number)
            return f"{_opcode}{_combo_1}{_pk}{_reserved}{_qp}{_combo_2}{_ps}".upper()
        
    
    #------------------------------
    # def my_awesome_func()
    #------------------------------
    async def my_awesome_func(stop_event: asyncio.Event, should_burst: bool) -> None:
        """This Python function uses XOA Python API to configure the TX port
    
        :param stop_event:
        :type stop_event: asyncio.Event
        :param should_burst: Whether the middle frames should be bursty.
        :type should_burst: bool
        """
        # create tester instance and establish connection
        tester = await testers.L23Tester(CHASSIS_IP, USERNAME, enable_logging=False) 
    
        # access the module on the tester
        module = tester.modules.obtain(MODULE_INDEX)
    
        # check if the module is of type Loki-100G-5S-2P
        if not isinstance(module, modules.ModuleChimera):
            
            # access the txport on the module
            txport = module.ports.obtain(TX_PORT_INDEX)
    
            #---------------------------
            # Port reservation
            #---------------------------
            print(f"#---------------------------")
            print(f"# Port reservation")
            print(f"#---------------------------")
            if txport.is_released():
                print(f"The txport is released (not owned by anyone). Will reserve the txport to continue txport configuration.")
                await txport.reservation.set_reserve() # set reservation , means txport will be controlled by our session
            elif not txport.is_reserved_by_me():
                print(f"The txport is reserved by others. Will relinquish and reserve the txport to continue txport configuration.")
                await txport.reservation.set_relinquish() # send relinquish the txport
                await txport.reservation.set_reserve() # set reservation , means txport will be controlled by our session
    
            #---------------------------
            # Start port configuration
            #---------------------------
            print(f"#---------------------------")
            print(f"# Start port configuration")
            print(f"#---------------------------")
    
            print(f"Reset the txport")
            await txport.reset.set()
    
            print(f"Configure the txport")
            await utils.apply(
                # txport.speed.mode.selection.set(mode=enums.PortSpeedMode.F100G),
                txport.comment.set(comment="RoCE2 on Loki"),
                txport.tx_config.enable.set_on(),
                txport.latency_config.offset.set(offset=0),
                txport.latency_config.mode.set(mode=enums.LatencyMode.LAST2LAST),
                txport.tx_config.burst_period.set(burst_period=0),
                txport.tx_config.packet_limit.set(packet_count_limit=FRAME_COUNT*REPETITION),
                txport.max_header_length.set(max_header_length=128),
                txport.autotrain.set(interval=0),
                txport.loop_back.set_none(),                                # If you want loopback the port TX to its own RX, change it to set_txoff2rx()
                txport.checksum.set(offset=0),
                txport.tx_config.delay.set(delay_val=0),
                txport.tpld_mode.set_normal(),
                txport.payload_mode.set_normal(),
                #txport.rate.pps.set(port_rate_pps=TRAFFIC_RATE_FPS),       # If you want to control traffic rate with FPS, uncomment this.
                txport.rate.fraction.set(TRAFFIC_RATE_PERCENT),                          # If you want to control traffic rate with fraction, uncomment this. 1,000,000 = 100%
            )
            if should_burst:
                await txport.tx_config.mode.set_burst()
            else:
                await txport.tx_config.mode.set_sequential()
            
            #--------------------------------------
            # Configure stream_0 on the txport
            #--------------------------------------
            print(f"   Configure first-packet stream on the txport")
    
            stream_0 = await txport.streams.create()
            eth = Ethernet()
            eth.src_mac = "aaaa.aaaa.0005"
            eth.dst_mac = "bbbb.bbbb.0005"
    
            ipv4 = IPV4()
            ipv4.src = "1.1.1.5"
            ipv4.dst = "2.2.2.5"
    
            ipv6 = IPV6()
            ipv6.src = "2001::5"
            ipv6.dst = "2002::5"
    
            udp = UDP()
            udp.src_port = 4791
            udp.dst_port = 4791
    
            rocev2 = ROCEV2()
            rocev2.opcode = 0
            rocev2.dest_queue_pair = 2
            rocev2.packet_seq_number = 0
    
            await utils.apply(
                stream_0.enable.set_on(),
                stream_0.packet.limit.set(packet_count=1),
                stream_0.comment.set(f"First packet"),
                stream_0.rate.fraction.set(stream_rate_ppm=10000),
                stream_0.packet.header.protocol.set(segments=[
                    enums.ProtocolOption.ETHERNET,
                    enums.ProtocolOption.IPV6,
                    enums.ProtocolOption.UDP,
                    enums.ProtocolOption.RAW_12,
                    ]),
                stream_0.packet.header.data.set(hex_data=Hex(str(eth)+str(ipv6)+str(udp)+str(rocev2))),
                stream_0.packet.length.set(length_type=enums.LengthType.FIXED, min_val=FRAME_SIZE_BYTES, max_val=FRAME_SIZE_BYTES),
                stream_0.payload.content.set(
                    payload_type=enums.PayloadType.PATTERN, 
                    hex_data=Hex("AABBCCDD")
                    ),
                stream_0.tpld_id.set(test_payload_identifier = 0),
                stream_0.insert_packets_checksum.set_on()
            )
            if should_burst:
                await stream_0.burst.burstiness.set(size=1, density=100)
                await stream_0.burst.gap.set(inter_packet_gap=0, inter_burst_gap=0)
    
            #--------------------------------------
            # Configure stream_1 on the txport
            #--------------------------------------
            print(f"   Configure middle-packets stream on the txport")
    
            stream_1 = await txport.streams.create()
    
            rocev2.opcode = 1
            rocev2.dest_queue_pair = 2
            rocev2.packet_seq_number = 1
    
            await utils.apply(
                stream_1.enable.set_on(),
                stream_1.packet.limit.set(packet_count=FRAME_COUNT-2),
                stream_1.comment.set(f"Middle packets"),
                stream_1.rate.fraction.set(stream_rate_ppm=10000),
                stream_1.packet.header.protocol.set(segments=[
                    enums.ProtocolOption.ETHERNET,
                    enums.ProtocolOption.IPV6,
                    enums.ProtocolOption.UDP,
                    enums.ProtocolOption.RAW_12,
                    ]),
                stream_1.packet.header.data.set(hex_data=Hex(str(eth)+str(ipv6)+str(udp)+str(rocev2))),
                stream_1.packet.length.set(length_type=enums.LengthType.FIXED, min_val=FRAME_SIZE_BYTES, max_val=FRAME_SIZE_BYTES),
                stream_1.payload.content.set(
                    payload_type=enums.PayloadType.PATTERN, 
                    hex_data=Hex("AABBCCDD")
                    ),
                stream_1.tpld_id.set(test_payload_identifier = 1),
                stream_1.insert_packets_checksum.set_on()
            )
            if should_burst:
                await stream_1.burst.burstiness.set(size=BURST_SIZE_FRAMES, density=100)
                await stream_1.burst.gap.set(inter_packet_gap=INTRA_BURST_GAP_BYTES, inter_burst_gap=INTER_BURST_GAP_BYTES)
    
            # Configure a modifier on the stream_1
            await stream_1.packet.header.modifiers.configure(1)
    
            # Modifier on the SQN
            modifier = stream_1.packet.header.modifiers.obtain(0)
            await modifier.specification.set(position=72, mask="FFFF0000", action=enums.ModifierAction.INC, repetition=1)
            await modifier.range.set(min_val=1, step=1, max_val=FRAME_COUNT-2)
    
    
            #--------------------------------------
            # Configure stream_2 on the txport
            #--------------------------------------
            print(f"   Configure last-packet stream on the txport")
    
            stream_2 = await txport.streams.create()
    
            rocev2.opcode = 2
            rocev2.dest_queue_pair = 2
            rocev2.packet_seq_number = FRAME_COUNT-1
    
            await utils.apply(
                stream_2.enable.set_on(),
                stream_2.packet.limit.set(packet_count=1),
                stream_2.comment.set(f"Last packet"),
                stream_2.rate.fraction.set(stream_rate_ppm=10000),
                stream_2.packet.header.protocol.set(segments=[
                    enums.ProtocolOption.ETHERNET,
                    enums.ProtocolOption.IPV6,
                    enums.ProtocolOption.UDP,
                    enums.ProtocolOption.RAW_12,
                    ]),
                stream_2.packet.header.data.set(hex_data=Hex(str(eth)+str(ipv6)+str(udp)+str(rocev2))),
                stream_2.packet.length.set(length_type=enums.LengthType.FIXED, min_val=FRAME_SIZE_BYTES, max_val=FRAME_SIZE_BYTES),
                stream_2.payload.content.set(
                    payload_type=enums.PayloadType.PATTERN, 
                    hex_data=Hex("AABBCCDD")
                    ),
                stream_2.tpld_id.set(test_payload_identifier = 2),
                stream_2.insert_packets_checksum.set_on()
            )
            if should_burst:
                await stream_2.burst.burstiness.set(size=1, density=100)
                await stream_2.burst.gap.set(inter_packet_gap=0, inter_burst_gap=0)
    
    
    
    async def main():
        stop_event =asyncio.Event()
        try:
            await my_awesome_func(stop_event, should_burst=SHOULD_BURST)
        except KeyboardInterrupt:
            stop_event.set()
    
    
    if __name__=="__main__":
        asyncio.run(main())

信雅纳:Python XOA测试自动化
 

XOA Python Test Suite/测试套件

XOA Python 测试套件是一个测试框架,为开发人员和测试专家执行和集成 Xena 测试套件提供了定义明确的 API。
该框架以自动化方式处理各种任务,如测试资源管理、测试执行和发布测试结果。
每个 RFC 测试套件都被设计成独立的 "插件",可根据需要有选择性地集成到项目中。
目前,XOA Python 测试套件包括
- RFC2544
- RFC2889
- RFC3918

XOA Converter

如果您希望将当前的 Xena 测试套件配置快速迁移到 XOA,现在使用 XOA 转换器工具比以往任何时候都更容易。

以前,Xena的测试套件应用程序仅与Windows兼容。但今后,所有现有和未来的测试套件都将并入 XOA Python 测试套件,从而消除 Windows 限制。

为了简化过渡,我们推出了 XOA 转换器。该工具允许用户将现有的Xena测试套件配置(Xena2544、Xena2889和Xena3918)从Xena窗口桌面应用程序无缝迁移到XOA Python测试套件中。有了 XOA 转换器,迁移过程变得轻松简单。

信雅纳:网络测试仪自动化测试

Source Code

GitHub 是我们托管 XOA 源代码的首选平台,因为它具有出色的版本控制和协作能力。它为管理代码变更提供了一个极佳的环境,确保项目的历史记录完备且易于访问。我们崇尚开放,鼓励每个人使用、分享、贡献和反馈我们的源代码。GitHub 允许进行无缝协作,并促进以社区为导向的方法,让每个人都能积极参与 XOA 的开发和改进。我们重视来自社区的意见和贡献,因为这能提高源代码的整体质量和创新性。

  • XOA Python API Source Code
  • XOA Python Test Suite – Core Source Code
  • XOA Python Test Suite – Plugin Source Code
  • XOA ANLT Utility Source Code
  • XOA Converter Source Code

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

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

相关文章

开启Safari手势支持

在使用Safari 的时候&#xff0c;大家有没有觉得不支持手势使用起来不是很方便&#xff0c; 触摸板只支持少量简单的手势&#xff0c;如缩放&#xff0c;滚动等。如果使用鼠标的用户&#xff0c;则完全无法使用手势。经过折腾研究&#xff0c;使用CirMenu应用可以完美解决这个要…

SpringCloud Stream 消息驱动

一、前言 接下来是开展一系列的 SpringCloud 的学习之旅&#xff0c;从传统的模块之间调用&#xff0c;一步步的升级为 SpringCloud 模块之间的调用&#xff0c;此篇文章为第九篇&#xff0c;即介绍 Stream 消息驱动。 二、消息驱动概念 2.1 消息驱动是什么 官方定义 Spring …

k8s helm 删除 tiller

kuberneter 上面装了 helm 想卸载还并不是那么简单, 参考 stackoverflow 回复 kubectl get -n kube-system secrets,sa,clusterrolebinding -o name|grep tiller|xargs kubectl -n kube-system delete kubectl get all -n kube-system -l apphelm -o name|xargs kubectl dele…

【数据结构】串的模式匹配(KMP+朴素模式匹配)

2.串的模式匹配 什么是字符串的模式匹配&#xff1f; 在主串中找到与模式串相同的子串&#xff0c;并返回其所在位置。 模式串&#xff1a;要匹配的一串。注&#xff1a;子串是主串的一部分&#xff0c;一定在主串中存在&#xff0c;但模式串不一定在主串中找得到。 2.1 朴素模…

软件无线电系列——带通信号采样定理

本节目录 一、带通信号采样定理 1、带通信号采样定理的定义 2、带通信号采样定理的证明本节内容 一、带通信号采样定理 1、带通信号采样定理的定义 Nyquist采样定理是对频谱分布在(0,fH)上的基带信号的采样分析的&#xff0c;如果信号的频谱分布在某一限定的频带(fL,fH)上&…

Docker使用(四)Docker常见问题分析和解决收集整理

Docker使用(四)Docker常见问题分析和解决收集整理 五、常见问题 1、 启动异常 【描述】&#xff1a; 【分析】&#xff1a;[rootlocalhost ~]# systemctl status docker 【解决】&#xff1a; &#xff08;1&#xff09;卸载后重新安装&#xff0c;不能解决这个问题。 …

腾讯与字节跳动联合创立萨罗斯网络科技公司 深度整合游戏项目

易采游戏网3月15日消息&#xff1a;抖音集团已将其游戏部门的资产转交给腾讯公司管理&#xff0c;而该部门的员工亦将整体迁移至腾讯新成立的子公司。此举在业界引起了广泛的激烈探讨与深度关注。 据透露&#xff0c;由深圳引力工作室主导的S1手游项目和由江南独力工作室研发的…

鸿蒙Harmony应用开发—ArkTS声明式开发(容器组件:List)

列表包含一系列相同宽度的列表项。适合连续、多行呈现同类数据&#xff0c;例如图片和文本。 说明&#xff1a; 该组件从API Version 7开始支持。后续版本如有新增内容&#xff0c;则采用上角标单独标记该内容的起始版本。该组件内容区小于一屏时&#xff0c;默认没有回弹效果。…

uniapp uview 头像裁剪组件的问题

当切换页面频繁进出头像裁剪组件u-avatar-cropper.vue 获取同一个设备信息时会出现两种不同的高度具体如下 导致 头像裁剪页面高度出现问题&#xff0c;下方按钮被canvas组件遮盖了 解决方法 在进入这个页面前的一个页面做如下代码操作 直接将设备信息提前获取&#xff0c;保…

【论文翻译】UP-DETR—Unsupervised Pre-training for Detection Transformers

0.论文摘要 摘要——通过Transformer model编码器——解码器架构&#xff0c;用于目标检测的检测Transformer model&#xff08;DETR&#xff09;达到了与Faster R-CNN相比具有竞争力的性能。然而&#xff0c;使用scratch transformers训练&#xff0c;DETR需要大规模的训练数…

android seekbar thumb 上添加进度值并居中

环境&#xff1a;android studio 、java 项目需要在进度条的滑块上显示进度值并居中&#xff0c; UI设计图&#xff1a; 代码实现效果图&#xff1a; 浅色模式&#xff1a; 深色模式&#xff1a; 由于一开始没有自定义seekbar&#xff0c; 使用源码Seekar&#xff0c; 滑块要…

【四 (4)数据可视化之 Ploty Express常用图表及代码实现 】

目录 文章导航一、介绍二、安装Plotly Express三、导入Plotly Express四、占比类图表1、饼图2、环形图3、堆叠条形图4、百分比堆叠条形图 五、比较排序类1、条形图2、漏斗图3、面积漏斗图 六、趋势类图表1、折线图2、多图例折线图3、分列折线图4、面积图5、多图例面积图 七、频…

【回归预测】基于DBO-RF(蜣螂优化算法优化随机森林)的回归预测 多输入单输出【Matlab代码#67】

文章目录 【可更换其他算法&#xff0c;获取资源请见文章第6节&#xff1a;资源获取】1. 随机森林RF算法2. 蜣螂优化算法3. 实验模型4. 部分代码展示5. 仿真结果展示6. 资源获取 【可更换其他算法&#xff0c;获取资源请见文章第6节&#xff1a;资源获取】 1. 随机森林RF算法 …

MM1: Methods, Analysis Insights from Multimodal LLM Pre-training

MM1: Methods, Analysis & Insights from Multimodal LLM Pre-training 相关链接&#xff1a;arxiv 关键字&#xff1a;多模态学习、大型语言模型、预训练、视觉语言连接、混合专家模型 摘要 本文讨论了构建高性能的多模态大型语言模型&#xff08;MLLMs&#xff09;。特别…

[SAP ABAP] 异常处理

异常 是在程序执行期间出现的问题 当异常发生时&#xff0c;程序的正常流程被中断&#xff0c;应用程序将会异常终止 例1 执行上述代码出现以下错误 我们可以使用TRY和CATCH关键字的组合捕获异常 执行上述代码出现以下结果 例2 执行上述代码出现以下错误 我们可以使用TRY和CAT…

springboot+poi-tl根据模板导出word(含动态表格和图片),并将导出的文档压缩zip导出

springbootpoi-tl根据模板导出word&#xff08;含动态表格和图片&#xff09; 官网&#xff1a;http://deepoove.com/poi-tl/ 参考网站&#xff1a;https://blog.csdn.net/M625387195/article/details/124855854 pom导入的maven依赖 <dependency><groupId>com.dee…

Soft Robotics 变结构手掌和变刚度手指的仿人软体手的人机交互操作-武科大ESIR课题组师兄成果

一、引言 在当今的机器人技术领域&#xff0c;人类对机器人的需求日益增长&#xff0c;涉及到工业生产、医疗护理、服务业等各个领域。然而&#xff0c;由于任务的多样性和复杂性&#xff0c;单独依靠自主机器人操作往往难以满足实际需求。为了解决这一问题&#xff0c;人机协作…

白话微机:9.解释SoC和Linux

一. 前言&#xff08;回顾世界观&#xff09; 在“微机世界”&#xff0c;普通的城市(单片机)里&#xff0c;人又有一个别的名字叫做“数据”&#xff0c;人有0有1&#xff1b;人们也有住房&#xff0c;这些住房在这个世界叫做“存储器”&#xff1b;地上有路&#xff0c;这些路…

鸿蒙开发实战:【音频组件】

简介 音频组件用于实现音频相关的功能&#xff0c;包括音频播放&#xff0c;录制&#xff0c;音量管理和设备管理。 图 1 音频组件架构图 基本概念 采样 采样是指将连续时域上的模拟信号按照一定的时间间隔采样&#xff0c;获取到离散时域上离散信号的过程。 采样率 采样…

数据仓库的设计开发应用(一)

目录 一、数据仓库设计的特点二、数据仓库系统开发过程三、数据仓库系统的规划 一、数据仓库设计的特点 1、“数据驱动” 的设计 数据仓库是从已有数据出发的设计方法&#xff0c;即从数据源抽取数据&#xff0c;经转换形成面向主题&#xff0c;支持决策的数据集合。 以全面了…