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 ③点击(...)改动网络节点的名字 ④改 ...
随机推荐
- struts 乱码
在进行struts开发的过程中,总也是出现很多的乱码问题 ,但归根到底,也只是以下三种情况: ㈠页面显示中文乱码 ㈡传递参数中文乱码 ㈢国际化资源文件乱码 下面就这三中情况介绍怎么在具体项目中处理这些 ...
- 使用adb命令启查看已安装的Android应用的versionCode、versionName
列出已经安装的应用 adb shell pm list package C:\Users\CJTDEV003>adb shell pm list package package:com.sams ...
- 关于EGE图形库在CodeBlocks下的配置
非常感谢[地球]呵呵@的细心帮助,我差点都放弃了! 我这里使用的是Code::Blocks svn 10595 与 TDM-GCC 5.10 首先下载为 GCC 5.0 以上编译好的 EGE 文件,稍 ...
- [uiautomator篇]uiwatcher 的使用场景
http://www.yangyanxing.com/article/use-watcher-in-uiautomator.html 今天在uiautomator中实践了watcher的用法,这个 ...
- C语言的那些秘密之---函数返回局部变量[转]
来源:http://blog.csdn.net/haiwil/article/details/6691854/ 一般的来说,函数是可以返回局部变量的. 局部变量的作用域只在函数内部,在函数返回后,局部 ...
- 鼠标移动或者鼠标点击div消失不见排查
点击事件,导致某div或者容器样式隐藏,如果不能直接发现click事件绑定,那么首先排查哪些方法在控制div的样式, 然后看一看哪些方法在调用修改样式的方法. 然后再排查什么在调用修改样式的方法的方法 ...
- 【bzoj3489】A simple rmq problem 三维KD-tree
题目描述 因为是OJ上的题,就简单点好了.给出一个长度为n的序列,给出M个询问:在[l,r]之间找到一个在这个区间里只出现过一次的数,并且要求找的这个数尽可能大.如果找不到这样的数,则直接输出0.我会 ...
- BZOJ 3749: [POI2015]Łasuchy【动态规划】
Description 圆桌上摆放着n份食物,围成一圈,第i份食物所含热量为c[i]. 相邻两份食物之间坐着一个人,共有n个人.每个人有两种选择,吃自己左边或者右边的食物.如果两个人选择了同一份食物, ...
- 刷题总结——子串(NOIP2015提高组)
题目: 题目背景 NOIP2015 提高组 Day2 T2 题目描述 有两个仅包含小写英文字母的字符串 A 和 B .现在要从字符串 A 中取出 k 个互不重叠的非空子串,然后把这 k 个子串按照其在 ...
- 【2018.10.18】CXM笔记(动态规划)
1.给你一棵树,让你修任意多条点不相交的铁路(每条铁路都是一根链),定义一个点的代价为它到根节点的路径中不在铁路上的边数,求一种设计方案代价最大的点最小. 铁路点不相交与 每个点连出去的铁路条数 $\ ...