版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
第五章物联网多端应用开发1今天我们要学点啥?202EMQX+钉钉Webhook实现从“被动运维”到“主动监控”的转变03H5页面可视化与WebSocket实时通信实时通信高速公路的技术融合微信小程序物联网的轻量级前端0105本章小结本章核心知识点回顾04数字孪生应用开发从二维视界到三维实境微信里的“神奇小工具”微信小程序无需安装,即点即用就像在微信里点一个链接,直接就能用,不用下载App。跨平台体验一致在苹果手机和安卓手机上打开,看起来和用起来都一样。开发门槛低微信提供了很多现成的“零件”,我们只需要把它们组装起来。3小程序+物联网=天生一对微信小程序用户触达零门槛你的长辈可能不会装App,但他们一定会用微信,极大降低使用门槛。完美的控制终端手机是你最常用的设备,用它来当“万能遥控器”再合适不过。轻松实现数据可视化利用小程序丰富的图表组件,直观展示家里的温度、湿度等数据变化。4工欲善其事,必先利其器微信小程序01下载开发者工具前往微信开放平台下载官方唯一指定的开发软件,集成了编码、调试与发布功能。02获取AppID注册小程序账号,在后台获取你的专属AppID,它是小程序的“身份证号”。03新建项目打开工具,填入AppID和项目信息,点击确定即可开启你的小程序之旅。5微信小程序6项目创建登录微信开发者工具后,在工具中选择“新建项目”,输入小程序AppID、项目名称及存储路径,即可生成基础项目框架。创建微信小程序项目一个小程序的“身体构造”微信小程序.js文件(逻辑层)——大脑负责处理页面的各种数据和逻辑,比如点击按钮后的响应。.wxml文件(视图层)——外貌用类似HTML的标签搭建页面结构,决定页面上显示哪些元素。.wxss文件(样式层)——衣服用来美化页面的外观,设置字体、颜色、布局等视觉效果。.json文件(配置层)——身份证配置页面的全局信息,如页面标题、导航栏颜色等基础设置。7微信小程序目录与文件结构微信小程序8调试与发布开发者可在微信开发者工具中使用调试功能,实时查看页面渲染情况,检查console日志,查看网络请求等,也可以点击预览按钮进行小程序的预览。开发完成后,需要提交代码进行审核,审核通过后可发布小程序。微信小程序编译与预览微信小程序MQTT通信关键代码微信小程序连接模块(connect.js)-核心:建立MQTT连接9//【核心】发布消息方法publishMsg(){//前置校验:判断是否已连接if(!app.globalData.isConnected){wx.showToast({title:"未连接MQTT",icon:"none"})return}//发布消息(核心API)app.globalData.client.publish(this.data.topic,this.data.msg)wx.showToast({title:"发送成功"})}connectMQTT(){//1.连接配置constoptions={clientId:'wx_'+Math.random().toString(36).substr(2,8),//账号密码/超时时间等配置}//2.建立连接(核心API)app.globalData.client=mqtt.connect(this.data.broker,options)constclient=app.globalData.client//3.连接状态监听(核心)client.on('error',()=>{this.setData({tips:"连接失败"})})client.on('connect',()=>{this.setData({tips:"连接成功"})app.globalData.isConnected=truewx.switchTab({url:'../sub/sub'}//跳转到订阅页面})发布模块(pub.js)-核心:发布MQTT消息微信小程序MQTT通信关键代码微信小程序订阅模块(sub.js)-核心:订阅/接收MQTT消息10App({globalData:{client:null,//【核心】存储MQTT客户端实例isConnected:false//【核心】标记连接状态}})constapp=getApp()Page({data:{isSubscribed:false,topic:"自定义主题",msgList:""},//【核心】订阅/取消订阅+消息接收toggleSubscribe(){if(!app.globalData.isConnected){//连接校验wx.showToast({title:"未连接MQTT",icon:"none"});return;}const{client}=app.globalData;const{topic}=this.data;if(this.data.isSubscribed){//取消订阅client.unsubscribe(topic);this.setData({isSubscribed:false});}else{//订阅+监听消息client.subscribe(topic);this.setData({isSubscribed:true});client.on('message',(t,p)=>{this.setData({msgList:p.toString()+'\n'+this.data.msgList});});}}})全局配置(app.js)-核心:共享MQTT客户端EMQX+钉钉Webhook11📌物联网监控现状与需求随着IoT发展,海量设备需实时监控。设备通过MQTT与云端通信,核心依赖EMQX处理连接与路由;而企业日常运营高度依赖钉钉等协同工具,二者的结合成为必然趋势。⚠业务联动的核心痛点设备产生的实时异常数据(如传感器超限、设备离线)无法高效触达业务人员。传统人工查看后台日志的方式效率低、响应滞后,难以满足实时监控的业务需求。🚀自动化告警联动方案将EMQXEnterprise与钉钉Webhook深度对接,利用EMQX规则引擎构建“设备→Broker→钉钉群”的高效联动通道,实现事件驱动的自动化消息推送,打通数据流转的“最后一公里”。🎯本实验的核心目标演示如何配置EMQX规则引擎,筛选设备上报的特定数据(如温度超标),并将其自动触发推送到指定钉钉群,最终完成智能化、自动化的设备状态监控与告警闭环。核心价值:实现从“被动运维”到“主动监控”的转变,大幅提升物联网业务响应效率什么是Webhook?EMQX+钉钉Webhook12Webhook核心定义一种基于事件触发的通信机制。源系统发生特定事件时,自动向目标URL发送HTTP请求,实现系统间的实时数据同步。传统模式:主动轮询(Pull)客户端定时、主动向服务器“要”数据。就像每隔5分钟问一次快递员“到了吗?”,效率低且浪费资源。Webhook模式:主动推送(Push)事件发生时,服务器主动把数据“送”到客户端。就像快递员送货后发短信通知,按需触发,实时高效。核心思想:从“拉”到“推”改变传统的“人找数据”模式
实现“数据找人”的高效协同
这就是Webhook的核心价值Webhookvs.PollingEMQX+钉钉Webhook13轮询(Polling)-传统拉取模式核心机制:客户端定时主动发起HTTP请求查询数据关键痛点:实时性差(依赖间隔)、资源消耗高(大量无效请求)适用场景:数据更新频率低、实时性要求不高的后台同步Webhook(Pushing)-事件驱动推送核心机制:服务端监测到事件发生,主动向客户端发送数据核心优势:实时性极高(毫秒级)、资源消耗低(按需推送)适用场景:即时告警、订单通知、IoT设备状态同步等IoT场景的最优解物联网设备通常需要对状态变化(如温度超标、设备离线)做出即时响应。相比轮询的“定期打扰”,Webhook的“有事才报”模式能显著降低服务器负载,同时保证数据的实时性。结论:在物联网数据交互中,Webhook是实现高效、实时通信的理想选择。Webhook在IoT中的典型应用场景EMQX+钉钉Webhook14设备状态监控设备断开连接时,EMQX触发Webhook,向业务后端推送离线事件,后端服务立即更新数据库并发送告警。数据持久化传感器发布数据到MQTTTopic,EMQX规则引擎拦截消息,通过Webhook推送到后端API,API将数据写入数据库。智能联动与报警智能家居门锁检测到“强行撬锁”信号,发布MQTT消息,EMQX触发Webhook,后端服务调用短信网关,业主立即收到告警短信。Webhookvs.WebSocket:实时通信的两种范式EMQX+钉钉Webhook15Webhook(短信通知)通信方向:单向(服务端→接收端)连接方式:短连接(基于HTTPPOST请求)适用场景:系统间异步通知、订单状态同步WebSocket(打电话)通信方向:双向全双工(客户端↔服务端)连接方式:长连接(建立持久TCP通道)适用场景:实时聊天、监控大屏、在线游戏核心范式差异📢被动触发(Webhook)有事件发生才发送数据,无事件则无交互,轻量级且资源消耗低。🔗主动维持(WebSocket)连接建立后持续保持,双方可随时推送数据,延迟极低,适合高频互动。目标:创建一个钉钉机器人,并获取用于接收消息的WebhookURL,实现告警消息的实时推送。EMQX+钉钉Webhook——配置钉钉接收端1601进入群设置打开钉钉群聊,点击右上角的「群设置」,在功能列表中找到并点击「机器人」选项。02添加自定义机器人在机器人管理页面,点击「添加机器人」,在弹出的列表中选择「自定义」机器人类型。03配置机器人安全信息输入机器人名称(如“告警机器人”),并勾选「自定义关键词」添加关键词(如“告警”)。04获取WebhookURL完成上述配置后,点击「完成」。系统将生成一个唯一的WebhookURL。请立即复制并妥善保存该地址,它是后续服务端向钉钉群推送消息的核心凭证。⚠️注意:WebhookURL包含敏感信息,请勿随意分享给他人。钉钉机器人配置过程(1/2)17进入群设置中的机器人管理选择添加自定义机器人EMQX+钉钉Webhook——配置钉钉接收端钉钉机器人配置过程(2/2)18配置机器人名称和安全设置复制WebhookURLEMQX+钉钉Webhook——配置钉钉接收端目标:通过EMQX规则引擎,实现MQTT消息的筛选和转发,将特定消息推送到钉钉平台。EMQX+钉钉Webhook——配置EMQX发送端1901登录EMQXDashboard访问http://<服务器IP>:18083,使用默认账号admin/public登录后台。02创建HTTP连接器进入「集成」→「连接器」,新建HTTP服务,URL填写钉钉开放平台地址。03创建规则(SQL筛选)进入「集成」→「规则」,编写SQL语句定义需要转发的MQTT消息条件。04添加动作(发送请求)配置钉钉WebhookURL和JSON消息体,完成消息转发配置。EMQX+钉钉Webhook——配置EMQX发送端20创建HTTP连接器在EMQXDashboard中,通过“集成”模块进入连接器列表,选择HTTP服务类型,完成基础的URL与请求头配置。进入连接器创建页面选择HTTP服务EMQX+钉钉Webhook——配置EMQX发送端21填写基础URL点击确认保存EMQX+钉钉Webhook——配置EMQX发送端22创建规则与动作编写SQL规则此规则持续监听MQTT主题t/a。当接收到的JSON格式消息体中,temp字段的数值大于25时,规则将被自动触发,执行后续的消息处理动作。核心机制:通过SQL语句实现数据提取与条件过滤的结合,是实现物联网设备消息自动化处理的基础。SQL规则脚本编辑器SELECTpayload.tempAStemperature,topicASmqtt_topic,clientidASclient_idFROM"t/a"WHEREpayload.temp>25示例:基于温度阈值的自动化规则配置EMQX+钉钉Webhook——配置动作参数选择连接器关联已创建的`DingTalk-Connector`,确保与钉钉服务正确对接。配置URL路径填写钉钉机器人回调地址:
`/robot/send?access_token=您的机器人Token`请求方法(Method)选择`POST`方法,用于向钉钉服务器提交JSON格式的消息体。请求体配置(JSONPayload){"msgtype":"text","text":{"content":"告警:设备${client_id}在${mqtt_topic}发布的温度为${temperature}度,已超过阈值!"}}提示:JSON中使用`${变量名}`包裹的部分,会自动替换为SQL语句中提取的实时监控数据,实现消息内容的动态生成。23EMQX+钉钉Webhook——配置动作参数24创建规则与动作配置动作参数SQL规则脚本编辑器配置参数点击添加动作通过实际场景演示,验证从设备消息上报到平台触发钉钉告警的完整数据流转链路。EMQX+钉钉Webhook——测试对接效果使用MQTTX发布测试消息钉钉群收到告警消息25EMQX+钉钉Webhook——注意事项与故障排查网络不通确保部署EMQX的服务器能够正常访问``地址。关键词不匹配钉钉机器人发送的消息内容中,必须包含创建机器人时设置的关键词。JSON格式错误MQTT消息体必须是合法的JSON格式,否则EMQX规则引擎将无法解析。规则未命中检查SQL语句的主题和筛选条件是否与实际发送的消息匹配。26从“写信”到“打电话”H5页面可视化与WebSocket实时通信27传统HTTP:被动的“写信”模式客户端每问一句,服务器才答一句。如同写信交流,必须等待回信才能获取信息,无法实现数据的实时推送。WebSocket:实时的“打电话”模式建立持久的双向通信通道,如同打电话般即时。连接一旦建立,数据即可自由、快速地双向流动,完美满足物联网实时性需求。核心价值:真正的实时通信允许服务器主动向客户端推送数据,打破了传统HTTP“请求-响应”模式的单向限制,实现了全双工的即时交互。技术优势:极致低延迟传输仅需一次TCP握手即可建立持久连接,后续数据传输无需重复建立连接,大幅降低了连接建立的耗时,响应速度极快。技术优势:低开销与双向自由数据帧头部极小,相比HTTP请求头节省大量带宽;支持客户端与服务器随时互相发送数据,通信模式更加灵活高效。WebSocket的诞生28H5页面可视化与WebSocket实时通信WebSocket连接的“三次握手”01.客户端打招呼小程序发送特殊HTTP请求,发起连接建立申请。02.服务器回应服务器审核通过后,回复“同意升级”响应。03.握手成功双方确认,建立双向通信的“高速公路”。04.自由通信数据在高速路上自由、快速地双向传输。29H5页面可视化与WebSocket实时通信WebSocket的“握手”与“长聊”Step1:发起握手请求客户端(小程序)向服务器发送HTTP请求,包含协议升级信息,请求建立连接。Step2:建立长连接通道服务器同意升级协议,返回成功响应,双方正式建立基于WebSocket的长连接通道。Step3:双向实时通信双方通过通道随时、双向地发送数据,保持“长聊”状态,直到连接主动关闭。30H5页面可视化与WebSocket实时通信H5可视化技术概览:主流库对比📊Chart.js轻量级图表库核心基于Canvas渲染,特点是轻量易用、体积小,提供折线、柱状等8种常见图表。非常适合需要快速开发、对性能要求不极致的中小型Web项目。📈ECharts企业级数据大屏首选支持Canvas/SVG双渲染,功能极其强大,图表类型丰富(含地图、3D图表等)。专为大数据量、高交互性场景设计,是构建复杂数据可视化大屏的最佳选择。⚙D3.js高度定制化的底层引擎直接操作DOM的底层库,灵活性极高,几乎可以绘制任何自定义图形。学习曲线较陡,但能满足科研、艺术化展示等对视觉效果有极致要求的复杂可视化场景。💡技术选型核心思路没有最好的库,只有最适合的。快速开发选Chart.js,复杂大屏选ECharts,高度定制选D3.js。结合团队技术栈与项目的实际数据规模进行选择。核心价值:让实时数据“活”起来,直观、高效地呈现给用户,辅助业务快速决策31H5页面可视化与WebSocket实时通信技术融合:MQTToverWebSocket架构32▍核心原理:WebSocket通信隧道在物联网场景中,H5页面受限于浏览器安全策略无法直接建立TCP连接。解决方案是利用WebSocket作为双向通信的“隧道”,将MQTT协议的数据包完整封装在WebSocket帧的载荷中,从而实现Web端与IoT服务端的安全、实时通信。▍架构流程:交互的前半程01.连接建立:H5客户端通过HTTP握手升级为WebSocket连接Broker02.帧解码还原:Broker剥离WebSocket帧头,解析出内部的MQTT数据包03.协议层处理(MQTTCore)Broker依据MQTT协议规范,对还原后的数据包进行逻辑处理,包括主题匹配、QoS确认、消息的发布与订阅路由等核心业务逻辑。04.封装回推&核心价值Broker将处理结果重新封装进WebSocket帧,主动推送给H5客户端。这种架构完美融合了两者优势:WebSocket解决Web连通性,MQTT解决IoT消息路由。H5页面可视化与WebSocket实时通信WebSocket连接MQTT服务核心代码解析33连接MQTT服务器functionpublish(){//校验必填项if(!pub_topic.value||!pub_payload.value){alert("Topic/消息内容不能为空");return;}//核心:发布消息(指定Topic+QoS)client.publish(pub_topic.value,//发布主题pub_payload.value,//消息内容{qos:parseInt(pub_qos.value)},//QoS等级(0/1/2)(err)=>{if(!err)alert("发布成功");}//发布回调);}letclient;//客户端实例functionconnect(){//基础校验+连接配置if(!host.value||!port.value){alert("主机/端口不能为空");return;}constoptions={clientId:'mqttjs_'+Math.random().toString(16).substr(2,8),username:username.value,password:password.value//账号密码};//核心:建立连接+监听连接状态client=mqtt.connect(`ws://${host.value}:${port.value}/mqtt`,options);client.on('connect',()=>{console.log("连接成功");document.getElementById("info").innerText="连接成功";//状态更新});}发布消息H5页面可视化与WebSocket实时通信WebSocket连接MQTT服务核心代码解析34订阅/接收消息//MQTT断开连接+取消订阅functionunsubscribe(){//取消订阅指定Topicclient.unsubscribe(sub_topic.value,(err)=>{if(!err){alert("取消订阅成功");//重置UIdocument.getElementById("sub_topic").disabled=false;}});}functiondisconnect(){//核心:断开MQTT连接+重置状态client.end();document.getElementById("info").innerText="未连接";document.getElementById("on").disabled=false;//启用连接按钮}functionsubscribe(){if(!sub_topic.value){alert("订阅Topic不能为空");return;}//订阅Topicclient.subscribe(sub_topic.value,{qos:parseInt(sub_qos.value)});//监听消息client.on('message',(t,p)=>{console.log("主题:",t,"内容:",p);});}取消订阅H5页面可视化与WebSocket实时通信实验案例:关键实现细节H5页面可视化与WebSocket实时通信前端UI设计·TailwindCSS利用原子化CSS框架快速构建现代化卡片式布局,高效完成仪表盘界面的视觉开发。数据可视化·Chart.js配置动态数据源,绘制实时更新的折线图,直观展示环境温湿度的变化趋势与波动。容器化部署·Docker封装Nginx运行环境,挂载本地代码目录,实现开发环境的热更新与生产环境的快速交付。🚀核心部署指令(Docker+Nginx)dockerrun-d-p8080:80\-v/usr/mqtt-h5:/usr/share/nginx/html:ro\nginx:alpine💡参数说明:
-d:后台运行容器|-p:端口映射(主机:容器)|-v:目录挂载(只读模式)WebSocket连接MQTT服务示例36MQTT客户端网页应用文件结构H5页面可视化与WebSocket实时通信WebSocket连接MQTT服务示例37网页运行效果H5页面可视化与WebSocket实时通信回顾与痛点:传统二维数据可视化的局限性数字孪生应用开发抽象与不直观面对屏幕上滚动的数字(如“俯仰角:45°”),难以迅速构建设备的真实空间姿态,信息传递存在延迟和失真。信息维度缺失二维图表无法体现物理实体各部分之间的空间关系和动态交互(如机械臂的运动轨迹),数据展示不够完整。缺乏全局视角分散的二维数据图表无法提供统一、直观的全局视图,使得复杂系统的故障诊断和整体优化变得异常困难。传统二维数据监控示意38数字孪生理论概论数字孪生应用开发📌物理实体现实世界中被监测和控制的对象,如本实验中的ESP32开发板、ADXL345加速度计等,是数字孪生的数据源头。💻虚拟实体计算机中创建的物理实体数字化模型,包含几何外形、物理属性与行为规则。本实验中即浏览器中由Three.js渲染的3D设备模型。🔗数据连接连接物理与虚拟实体的实时双向通道,确保状态同步。本实验中通过MQTT协议传输传感器数据,WebSocket协议实现3D模型的实时渲染更新。📊成熟度分级体系从L1静态建模到L5自主演化共五个等级。本实验重点关注L2“以虚映实”阶段,通过数据驱动实现对物理实体状态的精准描述与实时映射。核心价值:构建“感知-传输-映射-分析”的虚实闭环,实现对物理系统的全生命周期数字化管理39技术底座:WebGLvs.Three.js数字孪生应用开发WebGL(底层基石)核心机制:JavaScriptAPI,直接调用GPU进行硬件加速的3D渲染。关键点:性能极强,但需编写复杂着色器代码,开发门槛极高。适用场景:面向对图形学有深入理解的底层研发人员。Three.js(主流选择)核心机制:最流行的WebGL封装库,提供简洁易用的上层API。关键点:封装复杂底层操作,提供场景、相机等直观对象,降低开发难度。适用场景:快速构建Web端3D应用,是数字孪生可视化的首选。可视化开发的最优解数字孪生可视化需要兼顾开发效率与渲染性能。直接使用WebGL进行开发,学习曲线陡峭且耗时漫长。Three.js作为成熟的封装库,屏蔽了底层复杂的图形学细节,让开发者可以专注于业务逻辑与场景构建,完美平衡了效率与效果。总结:对于绝大多数数字孪生项目而言,Three.js是实现Web端3D可视化最理想、最高效的技术选择。40姿态孪生基础和实现步骤数字孪生应用开发边缘计算与姿态解算在ESP32端利用加速度计数据计算稳定的俯仰角和翻滚角,通过滤波算法有效滤除高频噪声干扰。构建Three.js3D舞台创建WebGL可视化的三大核心组件:Scene(场景容器)、Camera(视角控制)、Renderer(画面渲染)。动态纹理映射技术在内存中创建离屏Canvas实时绘制角度数值,并将其作为动态纹理实时映射到旋转的立方体表面。Step1:数据采集与传输ESP32读取ADXL345传感器数据,计算姿态角后,通过MQTT协议发布到云端Broker。Step2:消息代理与转发MQTTBroker(如EMQX)接收并转发消息到所有订阅者,实现消息的高效路由。Step3:实时订阅与渲染前端Web页面通过WebSocket协议订阅MQTT主题,接收数据后,通过Three.js实时更新3D模型状态。41智慧物流箱:结合硬件传感与3D交互,打造高价值货物运输监控系统。数字孪生应用开发应用场景模拟对高价值货物在运输过程中的监控,解决暴力分拣、货物安全、装载状态检测等实际痛点。多传感器融合融合ADXL345加速度计(监测冲击与姿态)和HC-SR04超声波传感器(检测开盖与满载)的实时数据。核心逻辑实现在Three.js3D场景中实现开盖动画、暴力抖动特效、状态标签显示等丰富的交互逻辑,直观呈现数据变化。42构建带有物理关节的数字孪生体数字孪生应用开发:智慧物流箱43//1.创建物流箱主体组(用于整体姿态和震动控制)constboxGroup=newTHREE.Group();constbodyMesh=newTHREE.Mesh(newTHREE.BoxGeometry(3,2,2),boxMaterial);boxGroup.add(bodyMesh);//2.创建箱盖及铰链系统constlidGroup=newTHREE.Group();//关键:将铰链(旋转中心)设置在箱体后上方边缘lidGroup.position.set(0,2,-1);constlidMesh=newTHREE.Mesh(newTHREE.
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2026年行政文员测试题及答案
- 2026年麦萌游戏测试题及答案
- 小学礼仪习惯养成说课稿2025年43
- 四 电磁铁及其应用教学设计初中物理九年级全册北师大版(闫金铎)
- 牙齿外伤急救措施
- 课文古代诗词诵读说课稿2025学年中职基础课-职业模块 工科类-高教版-(语文)-50
- 小学古诗2025年说课稿
- 高中生社交恐惧2025说课稿
- 浙江省A9协作体2025-2026学年高二下学期期中联考技术试卷
- 小学2025分享喜悦说课稿
- 2026及未来5年中国氯磺化聚乙烯(CSM)行业市场动态分析及投资前景研判报告
- 行吊培训资料
- GB 4053.1-2025固定式金属梯及平台安全要求第1部分:直梯
- 知乎社区运营专员面试题集
- 2025年下半年湖北省十堰市郧阳区事业单位招考易考易错模拟试题(共500题)试卷后附参考答案
- 供热行业有限空间培训
- 雪茄烟经营知识培训总结课件
- 石膏娃娃涂鸦课件
- 药品管理知识培训课件
- 《中小学跨学科课程开发规范》
- DB32∕T 4313-2022 滨海盐碱地生态化整治技术规程
评论
0/150
提交评论