zigbee基础知识笔记_第1页
zigbee基础知识笔记_第2页
zigbee基础知识笔记_第3页
zigbee基础知识笔记_第4页
zigbee基础知识笔记_第5页
已阅读5页,还剩7页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

精品文档1.基础知识11.1IEEE地址11.2簇11.3 Profile ID21.4 网络地址与端点号、节点21.5 PANID21.6 zigbee设备22.绑定机制32.1描述符绑定32.2设备绑定91.基础知识1.1IEEE地址IEEE地址是64位,在设备进入网络之前就分配好了的,应该在全球是唯一的,而网络地址是在网络建立后,设备加入网络时,它的父节点给它分配的,在设备通信时,首先由ieee地址找到设备的网络地址,然后根据网络地址实现设备之间的通信,这样可以减少帧头长度,多传有效数据通俗的说IEEE地址相当于你的手机号(11位的那个),短地址就相当于你们公司的小号(3、4)位,一个公司的互打电话就用小号噻。假设你的手机号138xxxxx666,这个是唯一的,但你的小号,假设是666,在你的公司网中是唯一的,但是在另一个网中,可能别人的小号也是666。1.2簇簇就是相当于端点房间里面的人,是接收最终的目标。这东西是2个字节编号,在射频发送的时候,必须要指定接收模块的镞,发送模块不需要指定。首先每一个端点可以看成是一个1个字节数字编号的开有一扇门的房间,数据最终的目标是进入到无线数据包指定的目标端点房间,而取无线数据这个相关的代码在任务事件处理函数里,TI协议栈有那么多的任务事件处理函数,所以必须要指定在哪个任务事件处理函数 来取这个无线数据包里面的有用数据。端点就相当于一个房间的门牌号!SimonApp_epDesc.endPoint = 10;/SimonApp_ENDPOINT; 此端点编号为10SimonApp_epDesc.task_id = &SimonApp_TaskID; 和我们应用层任务挂钩完成了簇信息表的构建,因为簇信息封装在SimonApp_SimpleDesc里面,这里面却只是起到一个信息表的作用!方便数据到来的时候查询相关信息表!const cId_t SimonApp_ClusterListSimonApp_MAX_CLUSTERS = SimonApp_CLUSTERID;const SimpleDescriptionFormat_t SimonApp_SimpleDesc = SimonApp_ENDPOINT, / int Endpoint; SimonApp_PROFID, / uint16 AppProfId2; SimonApp_DEVICEID, / uint16 AppDeviceId2; SimonApp_DEVICE_VERSION, / int AppDevVer:4; SimonApp_FLAGS, / int AppFlags:4; SimonApp_MAX_CLUSTERS, / byte AppNumInClusters; (cId_t *)SimonApp_ClusterList, / byte *pAppInClusterList; SimonApp_MAX_CLUSTERS, / byte AppNumInClusters; (cId_t *)SimonApp_ClusterList / byte *pAppInClusterList;接收到数据以后,判断是属于哪一个端点、属于哪一个簇1.3 Profile ID这个是由Zigbee组织来分配的应用ID号,比如无线开关用0x0001,智能电表用ox0002,万用遥控器用0x0003等等。在这个例子里,这个ID号是专门用来做电灯开关的。为什么要这么做呢?这里就体现了“标准”的意义,不同厂家功能的设备,由于有了这个ID就能互相间使用了,你使用这种开关一样可以达到别的开关控制灯的效果1.4 网络地址与端点号、节点在zigbee中,节点对应主机,相当于一个物理射频模块,一个端点对应一个任务号,即交由哪一个任务对象,端点号在端点描述符中,是要向操作系统注册端点描述符的,网络中的一个数据消息通过寻址(即网络地址)到达一个节点,节点收到消息后,操作系统查看消息端点对应的任务号,然后交由这个任务号的事件处理函数执行。1.5 PANIDPANID就是个人网络id号,Zigbee协议规定,用一个14位的个人域网来标识一个网络,1.6 zigbee设备Zigbee定义了三种功能的设备,每种设备都有自己的功能要求:ZigBee协调器是启动和配置网络的一种设备。协调器可以保持间接寻址用的绑定表格,支持关联,同时还能设计信任中心和执行其它活动。一个ZigBee网络只允许有一个ZigBee协调器。ZigBee路由器是一种支持关联的设备,能够将消息转发到其它设备。ZigBee网格或树型网络可以有多个ZigBee路由器。ZigBee星型网络不支持ZigBee路由器。ZigBee终端设备可以执行它的相关功能,并使用ZigBee网络到达其它需要与其通信的设备。它的存储器容量要求最少Zigbee协议栈类似ucos,有自己的任务调度,不过它是轮询,没有优先级,只要查询到每一层有相应的事件发生,就进行处理。具体代码如下:void osal_run_system( void ) uint8 idx = 0; osalTimeUpdate(); Hal_ProcessPoll(); do if (tasksEventsidx) / Task is highest priority that is ready. break; while (+idx tasksCnt); if (idx EndPoint, TRUE);Zigbee协议栈默认是允许的有了允许绑定就会有绑定请求,在myAllowBindTimeout规定的时间内,终端设备调用zb_BindDevice()函数,请求绑定。由于zb_BindDevice()函数的第三个参数是NULL,所以是以,未知IEEE地址的绑定。在zb_HandleKeys()函数中调用了,zb_BindDevice(TRUE, TOGGLE_LIGHT_CMD_ID, NULL); zb_BindDevice函数中调用了ZDP_MatchDescReq()函数,这个函数的参数,在上一篇文章中也做了介绍,这个函数是是初始化一个匹配描述符请求,也就是发现服务,或者叫自动寻求匹配设备。其中destination.addr.shortAddr = NWK_BROADCAST_SHORTADDR;终端发起请求:afStatus_t ZDP_MatchDescReq( zAddrType_t *dstAddr, uint16 nwkAddr,uint16 ProfileID, byte NumInClusters, cId_t *InClusterList, byte NumOutClusters, cId_t *OutClusterList, byte SecurityEnable )-return fillAndSend( &ZDP_TransID, dstAddr, Match_Desc_req, len );-return AF_DataRequest( &afAddr, &ZDApp_epDesc, clusterID, (uint16)(len+1), (uint8*)(ZDP_TmpBuf-1), transSeq, ZDP_TxOptions, AF_DEFAULT_RADIUS );将Match_Desc_req发送至协调器的ZDO层协调器控制端:控制接收到匹配请求后,对其匹配作出响应。目的设备收到绑定请求帧数据后生成ZDAppTaskID任务的AF_INCOMING_MSG_CMD事件。收到数据后,首先调用ZDAppTaskID任务的事件处理函数ZDApp_event_loop(),然后调用ZDApp_ProcessOSALMsg()函数,在这个函数中调用ZDP_IncomingData函数。case AF_INCOMING_MSG_CMD: ZDP_IncomingData( (afIncomingMSGPacket_t *)msgPtr ); break;在这里调用了ZDP_IncomingData()函数,下面是这个函数的源代码。这个函数表明了PDU数据从APS子层-ZDO层的数据传输。因为ZDO层是管理绑定的(绑定表建在APS中),管理器接收到的描述符匹配请求是发往其ZDO层的。ZDO_SendMsgCBs函数会生成sapi_TaskID的ZDO_CB_MSG事件,进而执行SAPI_ProcessZDOMsgs()函数中的Match_Desc_rsp选项通过 ZDO_SendMsgCBs()这个函数把ZDO信息发送到注册过ZDO信息的任务中去.比如sapi中SAPI_Init()注册过两种类型clusterId的ZDO信息:NWK_addr_rsp 和 Match_Desc_rsp因此其它命令,比如匹配请求命令Match_Desc_rep一般不会发送到sapi应用层中注意,即使发送了也不会处理,可以在如下代码中看到是发送了的,这里只会对请求/设置/通知命令才调用相应处理函数,如果是响应命令则不处理。但是要ZDO信息处理表中包含的命令才有相应的处理函数,有些没有的就不会调用End_Device_Bind_req这个ZDO信息是注册在ZDAppTaskID任务中的.DApp_ProcessOSALMsg-DP_IncomingData-ZDO_SendMsgCBsZDO_SendMsgCBs( &inMsg ); 把ZDO接收信息发送到注册过ZDO信息的任务中去;具体流程是比较接收信息的簇ID与注册过的簇ID,有相同则调用osal_msg_send()触发相应任务事件,事件这里默认为ZDO_CB_MSG,然后发将消息送SAPI应用层,因此可以看到SAPI_ProcessEvent()中有这个事件.注意这个函数只会传送信息到注册过相应ZDO信息的任务中去。ZDO_SendMsgCBs部分代码如下: ZDO_MsgCB_t *pList = zdoMsgCBs; while ( pList )/接收到的簇ID和注册过的簇ID进行比较if ( pList-clusterID = inMsg-clusterID )msgPtr-hdr.event = ZDO_CB_MSG;osal_msg_send( pList-taskID, (uint8 *)msgPtr );ret = TRUE;通过代码我们可以看到,这个函数首先是查找一个链表,看看这个链表到底是指向什么的,有下面这样一句话,pList指向了zdoMsgCBs。它的结构定义也如下:ZDO_MsgCB_t *pList = zdoMsgCBs;ZDO_MsgCB_t *zdoMsgCBs = (ZDO_MsgCB_t *)NULL;typedef struct void *next; uint8 taskID; uint16 clusterID; ZDO_MsgCB_t; 我们搜索代码可以发现,只有在这个函数中有对ZDO_MsgCB_t的赋值,也就是作为左值。ZStatus_t ZDO_RegisterForZDOMsg( uint8 taskID, uint16 clusterID ).zdoMsgCBs = pNew;这个函数的意思就是注册ZDO消息,我们可以回过头来看一下ZDO_SendMsgCBs()函数,这个函数中有了个while(pList);的循环,如果没有在ZDO_RegisterForZDOMsg()函数中注册的话,那意味着,这个循环是不成立的,也就是说为什么只有ZDO消息注册后才会真正的执行这个函数,但又有一个问题,在SAPI_Init ()函数中,我们可以发现下面两句话void SAPIApp_Init( byte task_id ) ZDO_RegisterForZDOMsg( GenericApp_TaskID, End_Device_Bind_rsp ); ZDO_RegisterForZDOMsg( GenericApp_TaskID, Match_Desc_rsp );oid ZDApp_RegisterCBs( void ) #if defined ( ZDO_IEEEADDR_REQUEST ) | defined ( REFLECTOR ) HalUARTWrite(0, IEEADDR , sizeof( IEEADDR ); /z c ZDO_RegisterForZDOMsg( ZDAppTaskID, IEEE_addr_rsp );#endif#if defined ( ZDO_NWKADDR_REQUEST ) | defined ( REFLECTOR ) HalUARTWrite(0, ZDO_NWKADDR , sizeof( ZDO_NWKADDR ); ZDO_RegisterForZDOMsg( ZDAppTaskID, NWK_addr_rsp );/z c#endif#if ZG_BUILD_COORDINATOR_TYPE HalUARTWrite(0, register , sizeof( register ); /c ZDO_RegisterForZDOMsg( ZDAppTaskID, Bind_rsp ); ZDO_RegisterForZDOMsg( ZDAppTaskID, Unbind_rsp ); ZDO_RegisterForZDOMsg( ZDAppTaskID, End_Device_Bind_req );#endif#if defined ( REFLECTOR ) HalUARTWrite(0, LECT , sizeof( LECT ); ZDO_RegisterForZDOMsg( ZDAppTaskID, Bind_req ); ZDO_RegisterForZDOMsg( ZDAppTaskID, Unbind_req );/z c#endif在这里对这两个响应消息进行了注册,注意这里的任务ID都是sapi_TaskID,还有一个地方也对End_Device_Bind_req进行了注册,也就是在ZDApp_RegisterCBs( void )函数中,这个函数在初始化函数ZDApp_Init( taskID+ );中被调用。当然这里还注册了很多其它的消息。问题就又来了,那既然这个链表是不为空的,这个函数的while(pList);就会成功执行,但下面还有一层验证就是簇ID,不要忘记我们的簇ID是什么,我们收到是Match_Desc_rep;而我们注册的是Match_Desc_rsp。所以在这个链表中找不到这个簇ID,所以也就不会触发msgPtr-hdr.event = ZDO_CB_MSG;继续向下执行。也就执行到了zdpMsgProcsx.pFn(&inMsg)处理函数中从这里我们也可以总结一下,我们知道在ZigBee中有四种格式的原语,分别是Request,Indication,Response,Confirm,这里注册的XX_XX_req,就表示的是请求消息,XX_XX_rsp就是响应消息。一定要注意的时这里只相差一个字母的区别把pfnZDPMsgProcessor声明为一种带一个参数的函数指针的类型别名,指向类似Fun(*inMsg)这种类型的函数.如果用此别名来声明一个指针变量,如:pfnZDPMsgProcessor pFn,则当pFn获取函数的地址后,就可以像调用原函数一样来使用这个函数指针:pFn(*inMsg)typedef void (*pfnZDPMsgProcessor)( zdoIncomingMsg_t *inMsg );typedef struct uint16 clusterID; pfnZDPMsgProcessor pFn; zdpMsgProcItem_t;定义一个zdpMsgProcItem_t类型的数组zdpMsgProcs,则数组zdpMsgProcs中的每个元素都是zdpMsgProcItem_t类型的结构体:clusterID,pFn,也就是一个是簇ID,另一个是相对应的处理函数。CONST zdpMsgProcItem_t zdpMsgProcs = NWK_addr_req, zdpProcessAddrReq , IEEE_addr_req, zdpProcessAddrReq , Node_Desc_req, ZDO_ProcessNodeDescReq , Power_Desc_req, ZDO_ProcessPowerDescReq , Simple_Desc_req, ZDO_ProcessSimpleDescReq , Active_EP_req, ZDO_ProcessActiveEPReq , Match_Desc_req, ZDO_ProcessMatchDescReq , (后面省略) 0xFFFF, NULL / Last; 既然ZDO_SendMsgCBs()函数不执行,那么就会查找ZDO信息处理表,当x=6时发现命令相符,两个簇ID相同,则调用ZDO_ProcessMatchDescReq()对描述符匹配请求进行处理.部分代码如下: pRspSent-hdr.event = ZDO_MATCH_DESC_RSP_SENT; osal_msg_send( *epDesc-epDesc-task_id, (uint8 *)pRspSent );/task_id为SAPIApp_TaskID会将此消息发送至 SPAIApp_ProcessEvent中,但是处理函数并未找到对应的处理函数,所以会执行下面语句: default: HalUARTWrite(0, default , sizeof( default );/自己加的 break;if ( ZSuccess = ZDP_MatchDescRsp( inMsg-TransSeq, &(inMsg-srcAddr), ZDP_SUCCESS, ZDAppNwkAddr.addr.shortAddr, epCnt, (uint8 *)ZDOBuildBuf, inMsg-SecurityUse ) )#if defined( LCD_SUPPORTED ) HalLcdWriteScreen( Match Desc Req, Rsp Sent ); /显示屏会证明执行到这里#endifZDP_MatchDescRsp可以看到这里管理器首先通过ZDP_MatchDescRsp()发送匹配响应给终端.而ZDP_MatchDescRsp()宏定义为ZDP_EPRsp(),#define ZDP_MatchDescRsp( TransSeq, dstAddr, Status, nwkAddr, Count, pEPList, SecurityEnable ) ZDP_EPRsp( Match_Desc_rsp, TransSeq, dstAddr, Status, nwkAddr, Count, pEPList, SecurityEnable )ZDP_EPRsp()设置clusterID为Match_Desc_rsp并调用FillAndSendTxOptions(),FillAndSendTxOptions()中调用fillAndSend(),fillAndSend()中最终调用AF_DataRequest()来发送匹配响应给终端。发送完匹配响应后管理器触发一个确认事件ZDO_MATCH_DESC_RSP_SENT,来指示有个设备试图与自己绑定.管理器是如何对这个确认事件进行处理的?如下:SAPI_ProcessEvent()中对ZDO_MATCH_DESC_RSP_SENT的处理:case ZDO_MATCH_DESC_RSP_SENT: /*发送匹配响应*/ SAPI_AllowBindConfirm( (ZDO_MatchDescRspSent_t *)pMsg)-nwkAddr );管理器接收到终端发送的描述符匹配请求后,发送一个描述符匹配请求的响应给终端,并触发一个确认事件指示有个设备试图与本设备进行绑定.终端: 终端接收到数据后生成ZDAppTaskID任务的AF_INCOMING_MSG_CMD事件。调用ZDP_IncomingData()函数,在函数中调用ZDO_SendMsgCBs()函数。ZDO_SendMsgCBs函数会生成sapi_TaskID的ZDO_CB_MSG事件,进而执行SAPI_ProcessZDOMsgs()函数中的Match_Desc_rsp选项。 在ZDP_IncomingData()函数中,这次会调用ZDO_SendMsgCBs()函数,因为在SAPI_Init()函数中,对Match_Desc_rsp进行了注册,这次在终端收到的是匹配请求响应,ZDO_RegisterForZDOMsg( sapi_TaskID, Match_Desc_rsp );这次正好和上一步中收到的Match_Desc_rep相对应,所以下面的zdpMsgProcs数组中找不到与Match_Desc_rsp相匹配的项,这时就会触发ZDO_CB_MSG事件。这一步的处理正好上上一步接收到Match_Desc_rep相反。ZDO_SendMsgCBs中 osal_msg_send( pList-taskID, (uint8 *)msgPtr );taskID为SAPIApp_TaskIDSAPI_ProcessZDOMsgs部分代码如下: case ZDO_CB_MSG: SAPI_ProcessZDOMsgs( (zdoIncomingMsg_t *)pMsg ); break;case Match_Desc_rsp: zAddrType_t dstAddr; ZDO_ActiveEndpointRsp_t *pRsp = ZDO_ParseEPListRsp( inMsg ); if ( sapi_bindInProgress != 0xffff ) /允许基于commandID的绑定 / Create a binding table entry 创建一个绑定条目 dstAddr.addrMode = Addr16Bit; dstAddr.addr.shortAddr = pRsp-nwkAddr; /通过描述符匹配响应信息得到管理器的网络地址 /*调用这个函数来实现两个设备的绑定*/ if ( APSME_BindRequest( sapi_epDesc.simpleDesc-EndPoint, /源EP sapi_bindInProgress, /簇ID &dstAddr, /目的地址模式 pRsp-epList0 ) = ZSuccess ) /目的EP /成功实现绑定后 /zb_BindDevice()中开启了一个定时器,用于接收Match_Desc_rsp计时 /如果接收到,则停止这个定时器,如下;如果溢出,则触发相应任务事件 osal_stop_timerEx(sapi_TaskID, ZB_BIND_TIMER); osal_start_timerEx( ZDAppTaskID, ZDO_NWK_UPDATE_NV, 250 ); sapi_bindInProgress = 0xffff;/不允许绑定过程 / Find IEEE addr ZDP_IEEEAddrReq( pRsp-nwkAddr, ZDP_ADDR_REQTYPE_SINGLE, 0, 0 ); / Send bind confirm callback to application /告诉应用绑定成功 zb_BindConfirm( sapi_bindInProgress, ZB_SUCCESS ); break; 最终过程如下:终端-控制器控制器-终端 终端发起绑定请求,控制器处理,并发送响应请求,终端收到响应请求,进行处理可以看到通过接收到的描述符匹配响应信息,终端获得允许绑定模式下管理器的16位网络地址:dstAddr.addr.shortAddr = pRsp-nwkAddr;最终调用APSME_BindRequest()来绑定终端设备与管理器.这样整个的绑定过程就结束,两个设备之间就可以进行相互的通信。这里采用的手动绑定的过程。很多情况下应该是自动绑定的。2.2设备绑定数据通打包成消息,最终通过无线发送出去, events & SYS_EVENT_MSG 会成立,最终在事件处理器中会到case AF_INCOMING_MSG_CMD: 终端: afStatus_t ZDP_EndDeviceBindReq( zAddrType_t *dstAddr, uint16 LocalCoordinator, byte endPoint, uint16 ProfileID, byte NumInClusters, cId_t *InClusterList, byte NumOutClusters, cId_t *OutClusterList, byte SecurityEnable ) dstAddr.addrMode = Addr16Bit; dstAddr.addr.shortAddr = 0x0000; / Coordinator ZDP_EndDeviceBindReq( &dstAddr, NLME_GetShortAddr(), GenericApp_epDesc.endPoint, GENERICAPP_PROFID, GENERICAPP_MAX_CLUSTERS, (cId_t *)GenericApp_ClusterList, GENERICAPP_MAX_CLUSTERS, (cId_t *)GenericApp_ClusterList, FALSE );ZDP_EndDeviceBindReq-return fillAndSend( &ZDP_TransID, dstAddr, End_Device_Bind_req, len )-AF_DataRequest( &afAddr, &ZDApp_epDesc, clusterID, (uint16)(len+1), (uint8*)(ZDP_TmpBuf-1), transSeq, ZDP_TxOptions, AF_DEFAULT_RADIUS );协调器控制端:协调器收到终端设备绑定请求End_Device_Bind_req这个信息会传送到ZDO层,在ZDO层的事件处理函数中,调用ZDApp_ProcessOSALMsg( (osal_event_hdr_t *)msg_ptr );ZDApp_event_loop-ZDApp_ProcessOSALMsg-case AF_INCOMING_MSG_CMD: -ZDP_IncomingData( (afIncomingMSGPacket_t *)msgPtr )ZDP_IncomingData它的代码部分如下:ZDO_SendMsgCBs( &inMsg )if ( zdpMsgProcsx.clusterID = inMsg.clusterID ) HalLedBlink (HAL_LED_1, 9,50, 1000); HalUARTWrite(0, endclusterID , sizeof( endclusterID ); LCD_write_CN_string(9, 110, ttttt); zdpMsgProcsx.pFn( &inMsg ); return; 因为ZDO信息处理表zdpMsgProcs 没有对应的End_Device_Bind_req簇,因此没有调用ZDO信息处理表中的处理函数,但是前面的ZDO_SendMsgCBs()会把这个终端设备绑定请求发送到登记过这个ZDO信息的任务中去。那这个登记注册的程序在哪里呢?对于协调器来说,由于在void ZDApp_Init( byte task_id )函数中调用了ZDApp_RegisterCBs();面的函数。进行注册了终端绑定请求信息。void ZDApp_RegisterCBs( void ) #if defined ( ZDO_IEEEADDR_REQUEST ) | defined ( REFLECTOR ) HalUARTWrite(0, IEEADDR , sizeof( IEEADDR ); /z c ZDO_RegisterForZDOMsg( ZDAppTaskID, IEEE_addr_rsp );#endif#if defined ( ZDO_NWKADDR_REQUEST ) | defined ( REFLECTOR ) HalUARTWrite(0, ZDO_NWKADDR , sizeof( ZDO_NWKADDR ); ZDO_RegisterForZDOMsg( ZDAppTaskID, NWK_addr_rsp );/z c#endif#if ZG_BUILD_COORDINATOR_TYPE HalUARTWrite(0, register , sizeof( register ); /c ZDO_RegisterForZDOMsg( ZDAppTaskID, Bind_rsp ); ZDO_RegisterForZDOMsg( ZDAppTaskID, Unbind_rsp ); ZDO_RegisterForZDOMsg( ZDAppTaskID, End_Device_Bind_req );#endif#if defined ( REFLECTOR ) HalUARTWrite(0, LECT , sizeof( LECT ); ZDO_RegisterForZDOMsg( ZDAppTaskID, Bind_req ); ZDO_RegisterForZDOMsg( ZDAppTaskID, Unbind_req );/z c#endif而GenericApp_Init()中初始化的是ZDO_RegisterForZDOMsg( TransmitApp_TaskID, End_Device_Bind_rsp );ZDO_RegisterForZDOMsg( TransmitApp_TaskID, Match_Desc_rsp );因此,协调器节点的 ZDApp 接收到外界输入的数据后,由于注册了 ZDO 反馈消息,即ZDO_CB_MSG,ZDApp 层任务事件处理函数将进行处理:也就是调用下面的程序,也就是ZDApp_event_loop-ZDApp_ProcessOSALMsg-case ZDO_CB_MSG-ZDApp_ProcessMsgCBs case End_Device_Bind_req: HalUARTWri

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论