STM32W108无线传感器网络节点自组织与移动智能体导航技术
使用STM32W108无线开发板及节点完毕大规模网络的自组建,网络模型选择树型,网络组建完毕之后,使用基于接收信号强度指示RSSI(ReceivedSignal Strength Indication)的N次三边质心加权定位法进行节点定位及智能车导航。
节点自组织及移动智能体导航实际场景
程序设计与实现
基于SimpleMac协议栈sample实例及第15章给出的N次三边质心加权定位算法程序,进行本章程序的设计,对于本章使用的N次三边质心加权定位算法及三边质心定位算法的实如今此就不再说明。主要给出自组网及智能车导航程序的设计实现。
数据包类型定义:
//负载类型定义 //已知位置的节点进行广播信息,用于移动位置节点的定位 #define PT_FIXED_NODE_SEND_SITE (0x07) /*用于移动节点广播搜索信道。当已知位置节点收到此类型信息时回复PT_CHANNEL_AVAILABLE类型信息*/ #define PT_CHANNEL_SEARCH (0x08) /*已知位置节点回复移动节点信息类型,当移动节点收到此信息说明网络当前信道即为其当前信道*/ #define PT_CHANNEL_AVAILABLE (0x09) //移动节点广播信息。请求已知位置节点广播其位置信息,以用于移动节点的定位 #define PT_POSITIONING_REQUEST (0x0A) #define PT_DATA_TO_ROOT (0x0B) //定位传送数据到根节点类型的数据包 //移动智能体进行广播询问定位 #define PT_MOBILE_NODE_POSITIONING_REQUEST (0x0C) //移动智能体发送数据到网络,传送至根节点 #define PT_DATA_FROM_MOBILE_NODE (0x0D) #define PT_DATA_TO_MOBILE_NODE (0x0E) //网络发送数据给移动智能体 /*网络广播数据给移动智能体。和PT_DATA_TO_MOBILE_NODE相差别。当来自汇聚节点的数据到达最后一个与移动智能体通信的节点时此节点进行广播,而此广播信息仅仅有移动节点会接收处理*/ #define PT_DATA_BROADCAST_TO_MOBILE_NODE (0x0F) //数据包类型定义 #define POSITIONING_REQUEST_PACKET ((FT_DATA << 4) | (PT_POSITIONING_REQUEST <<0)) //0x1A #define DATA_TO_ROOT_PACKET ((FT_DATA <<4) | (PT_DATA_TO_ROOT <<0)) //0x1B #define MOBILE_NODE_POSITIONING_REQUEST_PACKET ((FT_DATA <<4) |(PT_MOBILE_NODE_POSITIONING_REQUEST <<0)) //0x1C #define DATA_FROM_MOBILE_NODE_PACKET ((FT_DATA <<4) | (PT_DATA_FROM_MOBILE_NODE <<0))//0x1D #define DATA_TO_MOBILE_NODE_PACKET ((FT_DATA <<4) | (PT_DATA_TO_MOBILE_NODE <<0))//0x1E #define DATA_BROADCAST_TO_MOBILE_NODE_PACKET ((FT_DATA <<4) | (PT_DATA_BROADCAST_TO_MOBILE_NODE <<0))//0x1F |
本文的实验採用的是大边飞翔科技有限公司的STM32W108无线射频开发板及节点完毕大规模物联网网络的组建。
函数processRxPacket():
/************************************************************************** 功能描写叙述:对接收的数据包进行解析。并运行对应的操作 输入參数:无 输出參数:无 *************************************************************************/ void processRxPacket(void) { u8 i; boolean pktHasSrcPanId = FALSE; u8 srcAddrOffset = 0; u16 srcPanId=0xFFFF; u16 shortSrcAddr=0; u8 longSrcAddr[8]={0,};//64位数据源地址 u8 pt = PT_JOIN_DENIED; //负载类型 u8 assignedShortId[2] = {0xFE, 0xFF}; #ifdef ROOT_ROLE u8 fatherLongAddr[8]={0,},childLongAddr[8]={0,}; //记录64位长地址 #endif u8 payloadStart; //负载的起始位置 u8 packetType; //数据包类型 u8 packet[128]; //用于记录将发送的数据包内容 int x,y;//用于记录节点的坐标 if(!rxData.packetBeingProcessed) { return; } //数据包的长度不能小于10 if(rxData.packet[0]<10) { RX_DETAILS(printf("Length byte too short\r\n");) goto stopProcessing; } //推断帧类型 switch(rxData.packet[1]&0x7) { case FT_DATA: RX_DETAILS(printf("FT_DATA\r\n");) packetType = (FT_DATA<<4); RX_DETAILS(printf("the packet type is:%X\r\n",packetType);) break; case FT_MAC_COMMAND: RX_DETAILS(printf("FT_MAC_COMMAND\r\n");) packetType = (FT_MAC_COMMAND<<4); break; default: RX_DETAILS(printf("Unknown frame type\r\n");) goto stopProcessing; }; //推断是否有PAN ID if((rxData.packet[1]&0x40)!=0x40) { pktHasSrcPanId=TRUE; srcAddrOffset = 2; } //推断地址类型 switch(rxData.packet[2]) { case FCF_SHORTDST + FCF_SHORTSRC: RX_DETAILS(printf("short dst, short src\r\n");) shortSrcAddr = (rxData.packet[8+srcAddrOffset+1]<<8)| (rxData.packet[8+srcAddrOffset+0]<<0); payloadStart = 10+srcAddrOffset; if(pktHasSrcPanId) { srcPanId = (rxData.packet[9]<<8)|(rxData.packet[8]<<0); } break; case FCF_SHORTDST + FCF_LONGSRC: RX_DETAILS(printf("short dst, long src\r\n");) memcpy(longSrcAddr, (rxData.packet+8+srcAddrOffset), 8); payloadStart = 16+srcAddrOffset; if(pktHasSrcPanId) { srcPanId = (rxData.packet[9]<<8)|(rxData.packet[8]<<0); } break; case FCF_LONGDST + FCF_SHORTSRC: RX_DETAILS(printf("long dst, short src\r\n");) shortSrcAddr = (rxData.packet[14+srcAddrOffset+1]<<8)| (rxData.packet[14+srcAddrOffset+0]<<0); payloadStart = 16+srcAddrOffset; if(pktHasSrcPanId) { srcPanId = (rxData.packet[15]<<8)|(rxData.packet[14]<<0); } break; case FCF_LONGDST + FCF_LONGSRC: RX_DETAILS(printf("long dst, long src\r\n");) memcpy(longSrcAddr, (rxData.packet+14+srcAddrOffset), 8); payloadStart = 22+srcAddrOffset; if(pktHasSrcPanId) { srcPanId = (rxData.packet[15]<<8)|(rxData.packet[14]<<0); } break; default: RX_DETAILS(printf("Unknown addressing mode\r\n");) goto stopProcessing; } RX_DETAILS( if(pktHasSrcPanId) { RX_DETAILS(printf("src pan = 0x%04X\r\n", srcPanId);) } ) //确保数据包的长度足够包括负载类型数据 if(rxData.packet[0]<payloadStart) { RX_DETAILS(printf("Length byte too short\r\n");) goto stopProcessing; } //获取数据包的负载类型 packetType |= (rxData.packet[payloadStart]<<0); RX_DETAILS(printf("packet type = 0x%02X\r\n", packetType); printf("the longAddr is:");printLongAddr(longSrcAddr);) //依据负载类型,处理数据包 switch(packetType) { case (GENERIC_DATA_PACKET): //普通类型数据包,用于更新最新通信时间 RX_DETAILS(printf("GENERIC_DATA_PACKET\r\n");) rxData.lqi = calculateLqi(rxData.errors, (rxData.packet[0]+3)); //计算通信联络质量 //节点坐标 x=((rxData.packet[payloadStart+3]&0xFF) |((rxData.packet[payloadStart+4]&0xFF)<<8) |((rxData.packet[payloadStart+5]&0xFF)<<16) |((rxData.packet[payloadStart+6]&0xFF)<<24)); y=((rxData.packet[payloadStart+7]&0xFF) |((rxData.packet[payloadStart+8]&0xFF)<<8) |((rxData.packet[payloadStart+9]&0xFF)<<16) |((rxData.packet[payloadStart+10]&0xFF)<<24)); printLongAddr(longSrcAddr); RX_DETAIL(printf("RSSI=%d,X=%d,Y=%d\n",rxData.rssi,x,y);) //更新父节点与子节点之间的通信时间 for(i=0;i<CHILD_TABLE_SIZE;i++) { if(childTable[i].active&&whetherEqual(longSrcAddr,childTable[i].longAddr))//子节点 { //更新子节点记录信息 childTable[i].lastDataTransmitTick=halCommonGetInt16uQuarterSecondTick(); childTable[i].nodeSite.x=x; childTable[i].nodeSite.y=y; break; } } break; /*当节点收到增加请求数据包时。首先推断自己是否是根节点,假设是则回复数据包, 假设不是则推断自己是否已增加网络,假设已增加网络则可作为路由节点使用,假设 没有增加网络则忽略此数据包*/ case (FATHER_SEARCH_PACKET): if(rxData.rssi<RELIABLE_RSSI) //依据数据包RSSI进行数据包的过滤 { goto stopProcessing; } if(father.active&&childAvailable) //推断是否具有作为父节点的条件 { //数据包封装 packet[0] = (25+2); //数据包长度 packet[1] = FCF_DATA; //帧类型 packet[2] = FCF_LONGDST + FCF_LONGSRC; //地址类型 currSeqNum++; //数据包序列号 packet[3]=currSeqNum; packet[4] = (0xFFFF>>0)&0xFF; //目标PAN ID packet[5] = (0xFFFF>>8)&0xFF; memcpy((packet+6), longSrcAddr, 8); //64位长目标地址 packet[14] = (ST_RadioGetPanId()>>0)&0xFF; //源PAN ID packet[15] = (ST_RadioGetPanId()>>8)&0xFF; memcpy((packet+16), ST_RadioGetEui64(), 8); //64位长目标地址 packet[24] = PT_FATHER_AVAILABLE; //负载类型,父节点可用数据包 packet[25]=currentHopCount; //传递当前节点的跳数 enqueueTxPacket(TRUE, 0xFFFF, packet, 0); //广播通信 } break; /*当节点搜索父节点增加网络时,收到回复的数据。此前是广播所以可能会有多个节 点进行回复,此时须要延时,等待收到全部的回复。然后从回复的数据中选择跳数 最少,假设跳数最少的有多个节点,则选择RSSI最大的节点作为父节点进行增加 网络*/ case (FATHER_AVAILABLE_PACKET): //父节点可用数据包 if(rxData.rssi<RELIABLE_RSSI) //依据数据包RSSI进行数据包的过滤 { goto stopProcessing; } if(!father.active) //假设当前没有增加网络。进入例如以下操作 { for(i=0;i<current_optional_father_num;i++) //扫描当前可用父节点数组 { //推断数组中是否包括此父节点的信息 if(whetherEqual(longSrcAddr,optionalFather[i].longAddr)) { optionalFather[i].rssi += rxData.rssi; //RSSI值累加 optionalFather[i].packetNum++; //记录接收数据包次数 //推断数据包次数是否满足成为有效父节点的最小次数 if(optionalFather[i].packetNum==MIN_PACKET_NUM) optionalFather[i].active=TRUE; break; } } if(i==current_optional_father_num) //数组中不包括此数据包信息 { //记录跳数信息 optionalFather[current_optional_father_num].hop=rxData.packet[payloadStart+1]; //数据包源地址 memcpy(optionalFather[current_optional_father_num].longAddr,longSrcAddr,8); optionalFather[current_optional_father_num].panId=srcPanId; //PAN ID值 optionalFather[current_optional_father_num].rssi=rxData.rssi; //RSSI optionalFather[current_optional_father_num].packetNum=1; //数据包个数 optionalFather[current_optional_father_num].active=FALSE; //不能够 current_optional_father_num++; //可用父节点数添加 } } break; case (JOIN_REQUEST_PACKET): //增加网络请求数据包 if(rxData.rssi<RELIABLE_RSSI) //依据数据包RSSI进行数据包的过滤 { goto stopProcessing; } RX_DETAIL(printf("JOIN_REQUEST_PACKET\r\n");) //数据包封装 packet[0] = (24+2); //数据包长度 packet[1] = FCF_DATA + FCF_ACKREQ + FCF_INTRAPAN; //帧类型 packet[2] = FCF_LONGDST + FCF_LONGSRC; //地址类型 currSeqNum++; //数据包序列号 packet[3]=currSeqNum; packet[4] = (ST_RadioGetPanId()>>0)&0xFF; //目标PAN ID packet[5] = (ST_RadioGetPanId()>>8)&0xFF; memcpy((packet+6), longSrcAddr, 8); //64位长目标地址 memcpy((packet+14), ST_RadioGetEui64(), 8);//64位长源地址 //扫描子节点数组,推断是否有可用空间加入新的子节点 for(i=0;i<CHILD_TABLE_SIZE;i++) { //推断数组中是否已包括此子节点 if(whetherEqual(childTable[i].longAddr,longSrcAddr)) { //记录子节点坐标信息 childTable[i].nodeSite.x=(rxData.packet[payloadStart+1]&0xFF |(rxData.packet[payloadStart+2]&0xFF)<<8 |(rxData.packet[payloadStart+3]&0xFF)<<16 |(rxData.packet[payloadStart+4]&0xFF)<<24); childTable[i].nodeSite.y=(rxData.packet[payloadStart+5]&0xFF |(rxData.packet[payloadStart+6]&0xFF)<<8 |(rxData.packet[payloadStart+7]&0xFF)<<16 |(rxData.packet[payloadStart+8]&0xFF)<<24); //记录最新通信时间 childTable[i].lastDataTransmitTick=halCommonGetInt16uQuarterSecondTick(); if(!childTable[i].active) //更新该数组位置信息 { childNum++; //子节点数添加 childTable[i].active=TRUE; //此子节点位置占用 if(childNum==CHILD_TABLE_SIZE) //推断子节点数是否等于最大子节点数 childAvailable=FALSE; //假设是。则此节点不能再作为其它节点的父节点 } pt = PT_JOIN_ACCEPTED; //发送增加网络同意数据包 assignedShortId[0] = (shortAddrCounter>>0)&0xFF; assignedShortId[1] = (shortAddrCounter>>8)&0xFF; RX_DETAIL(printf("Join: the child in the childtable Planet 0x%04X (index %d) has joined the network\r\n", shortAddrCounter, i);) break; } else if(!childTable[i].active) //假设数组空间没有被占用,占用该位置空间 { childTable[i].active = TRUE; //占用该位置空间 childNum++; //子节点数添加 if(childNum==CHILD_TABLE_SIZE) //推断子节点数是否等于最大子节点数 childAvailable=FALSE; //假设是,则此节点不能再作为其它节点的父节点 shortAddrCounter++; //短地址添加 childTable[i].shortAddr = shortAddrCounter; //短地址 memcpy(childTable[i].longAddr,longSrcAddr, 8); //64位长地址 //子节点坐标 childTable[i].nodeSite.x=(rxData.packet[payloadStart+1]&0xFF |(rxData.packet[payloadStart+2]&0xFF)<<8 |(rxData.packet[payloadStart+3]&0xFF)<<16 |(rxData.packet[payloadStart+4]&0xFF)<<24); childTable[i].nodeSite.y=(rxData.packet[payloadStart+5]&0xFF |(rxData.packet[payloadStart+6]&0xFF)<<8 |(rxData.packet[payloadStart+7]&0xFF)<<16 |(rxData.packet[payloadStart+8]&0xFF)<<24); //最新通信时间 childTable[i].lastDataTransmitTick=halCommonGetInt16uQuarterSecondTick(); pt = PT_JOIN_ACCEPTED; //负载类型 assignedShortId[0] = (shortAddrCounter>>0)&0xFF; assignedShortId[1] = (shortAddrCounter>>8)&0xFF; RX_DETAIL(printf("Join: the child is a new child Planet 0x%04X (index %d) has joined the network\r\n", shortAddrCounter, i);) #ifndef ROOT_ROLE #ifndef MOBILE_NODE //将子节点信息发送到汇聚节点 sendNewNodeSiteToRoot(longSrcAddr,childTable[i].nodeSite); #endif #endif break; } } packet[22] = pt; //负载类型 packet[23] = assignedShortId[0]; //节点Node ID packet[24] = assignedShortId[1]; enqueueTxPacket(TRUE, 0xFFFF, packet, 0); //广播回复 break; case (JOIN_ACCEPTED_PACKET): //同意增加网络数据包 if(rxData.rssi<RELIABLE_RSSI) //依据数据包RSSI进行数据包的过滤 { goto stopProcessing; } RX_DETAIL(printf("JOIN_ACCEPTED_PACKET\r\n");) //设置Node ID ST_RadioSetNodeId((rxData.packet[payloadStart+1]<<0) |(rxData.packet[payloadStart+2]<<8)); networkJoinedStopSearching = TRUE; //增加网络成功。停止搜索 break; case (JOIN_DENIED_PACKET): //增加网络拒绝数据包 RX_DETAIL(printf("JOIN_DENIED_PACKET\r\n");) ST_RadioSetPanId(0xFFFF); //重置PAN ID break; case (LEAVING_PACKET): //离开网络数据包 RX_DETAIL(printf("LEAVING_PACKET\r\n");) //将节点信息从子节点表中删除 for(i=0;i<CHILD_TABLE_SIZE;i++) //扫描子节点表。查找子节点 { if(childTable[i].active && whetherEqual(childTable[i].longAddr,longSrcAddr)) { RX_DETAIL(printLongAddr(longSrcAddr);printf("the node leave the network\n");) childTable[i].active = FALSE; //将该子节点设置为无效 childNum--; //子节点数降低 childAvailable=TRUE; //而且设置该节点可继续作为父节点,执行子节点的增加 break; } } break; //信标节点发送的位置信息数据包,用于移动节点的定位 case (FIXED_NODE_SEND_SITE_PACKET): if(rxData.rssi<RELIABLE_RSSI) //依据数据包RSSI进行数据包的过滤 { goto stopProcessing; } if(!siteIsFixed) //假设位置为固定,则处理此数据包 { for(i=0;i<current_node_num;i++) //扫描信标节点数组 { //推断是否有此节点的信息 if(whetherEqual(longSrcAddr,receivePacketRecord[i].longAddr)) { receivePacketRecord[i].totalRssi+=rxData.rssi; //RSSI值累加 receivePacketRecord[i].current_num++; //数据包数添加 break; } } if(i==current_node_num) //假设数组中无此节点的记录信息 { //获取信标节点的坐标 x=(rxData.packet[payloadStart+1]&0xFF |(rxData.packet[payloadStart+2]&0xFF)<<8 |(rxData.packet[payloadStart+3]&0xFF)<<16 |(rxData.packet[payloadStart+4]&0xFF)<<24); y=(rxData.packet[payloadStart+5]&0xFF |(rxData.packet[payloadStart+6]&0xFF)<<8 |(rxData.packet[payloadStart+7]&0xFF)<<16 |(rxData.packet[payloadStart+8]&0xFF)<<24); RX_DETAIL(printf("the node site x is:%d, y is:%d\n",x,y);) receivePacketRecord[current_node_num].nodeSite.x=x; //记录坐标 receivePacketRecord[current_node_num].nodeSite.y=y; receivePacketRecord[current_node_num].current_num=1;//第一个数据包 receivePacketRecord[current_node_num].totalRssi=rxData.rssi;//RSSI值 memcpy(receivePacketRecord[i].longAddr,longSrcAddr,8); //64位长地址 current_node_num++; //当前可用定位节点个数 } } break; case (CHANNEL_SEARCH_PACKET): //信道搜索数据包 if(channelSearched) { RX_DETAIL(printf("CHANNEL_SEARCH_PACKET\r\n");) //数据包封装 packet[0] = (24+2); //数据包长度 packet[1] = FCF_DATA; //帧类型 packet[2] = FCF_LONGDST + FCF_LONGSRC; //地址类型 currSeqNum++; //数据包序列号 packet[3]=currSeqNum; packet[4] = (0xFFFF>>0)&0xFF; //目标PAN ID packet[5] = (0xFFFF>>8)&0xFF; memcpy((packet+6), longSrcAddr, 8); //长目标地址 packet[14] = (ST_RadioGetPanId()>>0)&0xFF; //源PAN ID packet[15] = (ST_RadioGetPanId()>>8)&0xFF; memcpy((packet+16), ST_RadioGetEui64(), 8); //长源地址 packet[24] = PT_CHANNEL_AVAILABLE; //负载类型。信道可用数据包 enqueueTxPacket(TRUE, 0xFFFF, packet, 0); //广播回复 } break; case (CHANNEL_AVAILABLE_PACKET): //信道可用数据包 RX_DETAIL(printf("CHANNEL_AVAILABLE_PACKET\r\n");) channelStopSearching=TRUE; break; //移动节点请求定位数据包,当信标节点接收到此数据包时广播其位置信息 case (POSITIONING_REQUEST_PACKET): if(rxData.rssi<RELIABLE_RSSI) //依据数据包RSSI进行数据包的过滤 { goto stopProcessing; } #ifndef ROOT_ROLE #ifndef MOBILE_NODE if(siteIsFixed) //假设为信标节点 { fixedNodeBroadcast(longSrcAddr,FALSE); //广播其位置信息 } #endif #endif break; //移动智能体请求定位数据包,当信标节点接收到此数据包时广播其位置信息 case (MOBILE_NODE_POSITIONING_REQUEST_PACKET): if(rxData.rssi<RELIABLE_RSSI) //依据数据包RSSI进行数据包的过滤 { goto stopProcessing; } #ifndef ROOT_ROLE #ifndef MOBILE_NODE if(siteIsFixed) { fixedNodeBroadcast(longSrcAddr,TRUE); //信标节点广播,用于移动智能体定位 } #endif #endif break; case (DATA_FROM_MOBILE_NODE_PACKET): //移动智能体发送的数据包 if(rxData.rssi<RELIABLE_RSSI) //依据数据包RSSI进行数据包的过滤 { goto stopProcessing; } #ifdef ROOT_ROLE //假设为汇聚节点 //获取移动智能体的坐标信息 x=((rxData.packet[payloadStart+1]&0xFF) |((rxData.packet[payloadStart+2]&0xFF)<<8) |((rxData.packet[payloadStart+3]&0xFF)<<16) |((rxData.packet[payloadStart+4]&0xFF)<<24)); y=((rxData.packet[payloadStart+5]&0xFF) |((rxData.packet[payloadStart+6]&0xFF)<<8) |((rxData.packet[payloadStart+7]&0xFF)<<16) |((rxData.packet[payloadStart+8]&0xFF)<<24)); memcpy(childLongAddr,(rxData.packet+payloadStart+9),8); //64位长地址 RX_DETAIL(printf("%d %d\n",x,y);) for(i=0;i<CHILD_TABLE_SIZE;i++) //扫描其子节点表 { if(whetherEqual(longSrcAddr,childTable[i].longAddr)) //查找数据包来自哪个子节点 { //TRUE表示可以在移动智能体和汇聚节点之间建立通信路由 inDirectDataOfMobileNode=TRUE; //表示此子节点可以和移动智能体之间建立通信路由 childTable[i].transDataFromMobileNode=TRUE; childTable[i].pathStartTime=((rxData.packet[payloadStart+9]) |((rxData.packet[payloadStart+10]&0xFF)<<8)); //记录通信路由的建立时间 break; } } #else #ifndef MOBILE_NODE //非汇聚节点和非移动智能体 /*间节点收到来自移动智能体的数据包进行转发。发送给其父节点, 父节点继续向其父节点转发,直到到达汇聚节点*/ transmitDataFromMobileNode(payloadStart+1,rxData.packet[0]-payloadStart); //转发数据 for(i=0;i<CHILD_TABLE_SIZE;i++) //扫描其子节点表 { if(whetherEqual(longSrcAddr,childTable[i].longAddr)) //查找数据包来自哪个子节点 { inDirectDataOfMobileNode=TRUE; //表示此节点与移动智能体之间建立通信路径 childTable[i].transDataFromMobileNode=TRUE; //通信路径的下一跳为此子节点 if(rxData.packet[0]-payloadStart==8) //推断数据包中是否包括时间信息 childTable[i].pathStartTime=halCommonGetInt16uQuarterSecondTick(); //当前时间 else childTable[i].pathStartTime=((rxData.packet[payloadStart+9]) |((rxData.packet[payloadStart+10]&0xFF)<<8)); //数据包中的时间 break; } } #endif #endif break; case (DATA_TO_MOBILE_NODE_PACKET): //发往移动智能体的数据包 #ifndef MOBILE_NODE #ifndef ROOT_ROLE //非移动智能体节点收到来自汇聚节点发送给移动智能体的数据,进行转发 dataTransmitToMobileNode(payloadStart+1,rxData.packet[0]-payloadStart); #endif #endif break; //广播发送给移动智能体的数据包 case (DATA_BROADCAST_TO_MOBILE_NODE_PACKET): #ifdef MOBILE_NODE /*移动智能体依据收到来自汇聚节点的信息。调整自己的移动 汇聚节点发送给移动智能体的数据可能是控制命令,可能是新的目标坐标*/ if(rxData.packet[0]-payloadStart > 1)//发送的是目标坐标 { x=((rxData.packet[payloadStart+1]&0xFF) |((rxData.packet[payloadStart+2]&0xFF)<<8) |((rxData.packet[payloadStart+3]&0xFF)<<16) |((rxData.packet[payloadStart+4]&0xFF)<<24)); y=((rxData.packet[payloadStart+5]&0xFF) |((rxData.packet[payloadStart+6]&0xFF)<<8) |((rxData.packet[payloadStart+7]&0xFF)<<16) |((rxData.packet[payloadStart+8]&0xFF)<<24)); RX_DETAIL(printf("mobile node receive new site:x=%d,y=%d\n",x,y);) if(x!=targetSite.x||y!=targetSite.y) { targetSite.x=x; //设置新的移动坐标 targetSite.y=y; isArriveTargetSite=FALSE; //表示没有达到指定位置 arriveTargetSiteTimes=0; //清空达到指定位置次数 } } else //发送的是控制命令 { u8 data; data=rxData.packet[payloadStart+1]; switch (data) { case 's': //停止移动命令 isArriveTargetSite=TRUE; STOP(); //运行STOP()函数,停止移动智能体的移动 break; case 'm': //移动命令 isArriveTargetSite=FALSE; adjustAngle(nodeSite,targetSite); //依据当前位置和目标位置调整移动方向及角度 break; default://不可识别的信息,不进行不论什么操作 break; } } #endif break; case (DATA_TO_ROOT_PACKET): //收到发送到根节点的数据 //假设汇聚节点接收到此信息,通过串口显示信息 #ifdef ROOT_ROLE //获取坐标信息 x=((rxData.packet[payloadStart+17]&0xFF) |((rxData.packet[payloadStart+18]&0xFF)<<8) |((rxData.packet[payloadStart+19]&0xFF)<<16) |((rxData.packet[payloadStart+20]&0xFF)<<24)); y=((rxData.packet[payloadStart+21]&0xFF) |((rxData.packet[payloadStart+22]&0xFF)<<8) |((rxData.packet[payloadStart+23]&0xFF)<<16) |((rxData.packet[payloadStart+24]&0xFF)<<24)); memcpy(fatherLongAddr,(rxData.packet+payloadStart+1),8); //父节点64位长地址 memcpy(childLongAddr,(rxData.packet+payloadStart+9),8); //子节点64为长地址 //输出64位长地址信息 printFatherLongAddr(fatherLongAddr); printChildLongAddr(childLongAddr); RX_DETAIL(printf("RSSI=%d,",rxData.rssi);) RX_DETAIL(printf("X=%d,Y=%d\n",x,y);) #else //不是汇聚节点而是中间路由节点 #ifndef MOBILE_NODE dataTransmitToRoot(payloadStart+1,rxData.packet[0]-payloadStart); //转发数据 #endif #endif break; default: RX_DETAIL(printf("Unknown payload type\r\n");) goto stopProcessing; } stopProcessing: rxData.packetBeingProcessed = FALSE; } |
本文出自《STM32W108嵌入式无线传感器网络》邱铁。夏锋。周玉编著.清华大学出版社。2014年5月
STM32W108无线传感器网络节点自组织与移动智能体导航技术的更多相关文章
- STM32W108无线传感器网络嵌入式uCOS-II的移植及实时环境监測
基于STM32W108无线开发板,将ucos-ii v2.86内核移植到其上,并加入用户任务.实现对温湿度.超声波.声音.光敏等传感器的控制及实时数据採集. 14.1开发环境说明 硬件:STM32W1 ...
- 6.openstack之mitaka搭建网络节点
部署网络服务 一:控制节点配置 1.建库建用户 mysql -u root -p CREATE DATABASE neutron; GRANT ALL PRIVILEGES ON neutron.* ...
- openstack grizzly版network网络节点安装
版本以及源的配置和控制节点一致 1.安装完操作系统已经apt源配置完成之后,一定要执行 apt-get update root@cloud:~# mv /etc/apt/sources.list /e ...
- OpenStack Havana 部署在Ubuntu 12.04 Server 【OVS+GRE】(二)——网络节点的安装
序:OpenStack Havana 部署在Ubuntu 12.04 Server [OVS+GRE] 网络节点: 1.安装前更新系统 安装好ubuntu 12.04 Server 64bits后,进 ...
- openstack controller ha测试环境搭建记录(十一)——配置neutron(网络节点)
在网络节点配置内核参数:vi /etc/sysctl.confnet.ipv4.ip_forward=1net.ipv4.conf.all.rp_filter=0net.ipv4.conf.defau ...
- 四:OVS+GRE之网络节点
关于Neutron上的三种Agent的作用: Neutron-OVS-Agent:从OVS-Plugin上接收tunnel和tunnel flow的配置,驱动OVS来建立GRE Tunnel Neut ...
- OpenStack IceHouse 部署 - 5 - 网络节点部署
Neutron网络服务(网络节点) 目录 [隐藏] 1 参考 2 前置工作 2.1 调整内核参数 3 安装 4 配置 4.1 keystone对接 4.2 rabbitmq对接 4.3 me ...
- 【java规则引擎】模拟rete算法的网络节点以及匹配过程
转载请注明:http://www.cnblogs.com/shangxiaofei/p/6340655.html 本文只用于理解rete算法,通过一个规则的编译成的网络结构,以及匹配过程去理解rete ...
- Allegro改动shape网络节点
使用Allegro时改动shape的网络节点方法: ①选择shape->Select Shape or Void/Cavity ②选择要改动的shape ③点击(...)改动网络节点的名字 ④改 ...
随机推荐
- Arthas诊断工具使用资料
1.https://github.com/alibaba/arthas/issues/327 2.https://alibaba.github.io/arthas/jad.html 3.https:/ ...
- win10系统中virtualbox无法安装64位系统
win10系统中virtualbox无法安装64位系统 先总结下如果想在虚拟机中安装64位的Linux系统,最好能满足这几个条件: 64位CPU 64位操作系统 64位的虚拟机软件 开启BIOS虚拟化 ...
- luogu1640 [SCOI2010]连续攻击游戏
二分图匹配,一边是属性值,一边是武器 #include <iostream> #include <cstring> #include <cstdio> using ...
- java 词频统计代码
package hello; import java.io.BufferedReader; import java.io.FileNotFoundException; import java.io.F ...
- Windows 通过 SecureCRT 8.x 上传文件到Linux服务器
1.SecureCRT 连接 Linux 服务器,这一步操作简单: 2.连接并登录成功后,直接在连接成功的页签上 右键 -> Connect SFTP Session 打开SFTP窗口: 3. ...
- [android开发篇] api demo 官网学习网址
http://www.android-doc.com/resources/samples/wifidirectdemo/index.html
- Charlie's Change(完全背包记录路径)
Charlie is a driver of Advanced Cargo Movement, Ltd. Charlie drives a lot and so he often buys coffe ...
- Codeforces Round #401 (Div. 2) 离翻身就差2分钟
Codeforces Round #401 (Div. 2) 很happy,现场榜很happy,完全将昨晚的不悦忘了.终判我校一片惨白,小董同学怒怼D\E,离AK就差一个C了,于是我AC了C题还剩35 ...
- cell展开的几种方式
一.插入新的cell 原理: (1)定义是否展开,和展开的cell的下标 @property (assign, nonatomic) BOOL isExpand; //是否展开 @property ( ...
- Laravel 之Cache缓存
写入缓存 Cache::put('key','value',10);//设置10分钟 获取缓存 Cache::get('key'); 增加缓存 Cache::add('key','value',10) ...