void vApplicationIdleHook(void)
{
	static char sending=0;
	static char state=0;
	static char* sendData=NULL;
	OBD2HW_Header* pobd2hw;

	#ifdef APPLICATION_START_TIME
		if(xTaskGetTickCount()-ob_app_start<APPLICATION_START_TIME) {
			usb_stat.stat_time 	  = ob_app_start + 2*APPLICATION_START_TIME;
			ob_int_mgmt.stat_time = ob_app_start + 2*APPLICATION_START_TIME + OPENBEACON_STATS_AUTO_SEND_TIME/2;

			return;
		}
	#endif

	// TODO: erforsche diesen Einfluss | nRFAPI_GetStatus()&STATUS_TX_DS
	if(xTaskGetTickCount()-ob_send_time > OPENBEACON_SEND_WIRELESS ) {
		AT91F_PIO_SetOutput( AT91C_BASE_PIOA, LED_RED );
		sending=0;
		ob_switchRXMode();
	}

	#ifdef OPENBEACON_RECIVE_WIRELESS
		if( last_usb_sendmesg==NULL ) last_usb_sendmesg = pullFreeBlock();

		if(sending==0 && last_usb_sendmesg!=NULL) {
			// Wirless Packete empfangen
			pobd2hw = (OBD2HW_Header*) last_usb_sendmesg->pValue;
			pobd2hw->length=recvBeacon( &recv_buffer );

			if( pobd2hw->length>0 ) {
				sending=1;
				memcpy(last_usb_sendmesg->pValue+sizeof(OBD2HW_Header)+sizeof(Click2OBD_header)-OPENBEACON_MACSIZE, recv_buffer.payload, pobd2hw->length );

				// TODO: auswerten der Daten (ggf. weiterleiten an Click)
				pobd2hw->type=PACKET_DATA;
				pobd2hw->length += sizeof(Click2OBD_header);

				Click2OBD_header* pclick2obd = (Click2OBD_header*) (last_usb_recvmesg->pValue+sizeof(OBD2HW_Header) );
				pclick2obd->channel = ob_int_mgmt.TxChannel;
				pclick2obd->rate	= ob_int_mgmt.TxRate;
				pclick2obd->power 	= ob_int_mgmt.TxPowerLevel;
				#ifdef OPENBEACON_TRANSMIT_WIRELESS_TO_USB
					vUSBSendPacket( last_usb_sendmesg, pobd2hw->length+sizeof(OBD2HW_Header) );
					last_usb_sendmesg = NULL;
				#endif
			}
		}
	#endif
	#ifdef OPENBEACON_TEST_AUTO_SEND
		if(sending==0 && xTaskGetTickCount()-ob_send_time > OPENBEACON_SEND_WIRELESS) {
			if( ob_int_mgmt.test_hw_diff<255 && xTaskGetTickCount()-ob_send_time>ob_int_mgmt.test_hw_diff ) {
				// TODO: Testpacket einrichten
				HW_rxtx_Test *htestp = (HW_rxtx_Test *)send_buffer.payload;
				char i;

				for(i=0; i<OPENBEACON_MACSIZE; i++) htestp->openbeacon_smac[ i ] = 0xFF;
				htestp->prot_type[0] = ETHERNET_TEST_PROTOCOL_FIRST;
				htestp->prot_type[1] = ETHERNET_TEST_PROTOCOL_SECOND;
				increment(htestp->pID, 4);

				switch( sendBeacon( &send_buffer ) ) {
					case 0:	sending=1;
						AT91F_PIO_ClearOutput( AT91C_BASE_PIOA, LED_RED );
						ob_send_time=xTaskGetTickCount();
						break;
					case -1:
					break;
				}
			}
		}
	#endif

	// Sendet USB-Statistics
	#ifdef USB_STATS_AUTO_SEND
		#ifdef USB_STATS_AUTO_SEND_TIME
			sendUSBStat( USB_STATS_AUTO_SEND_TIME );
		#else
			sendUSBStat( 1000 );
		#endif
	#endif

	// Sendet Wirless-Statistics
	#ifdef OPENBEACON_STATS_AUTO_SEND
		#ifdef OPENBEACON_STATS_AUTO_SEND_TIME
			sendBeaconStat( OPENBEACON_STATS_AUTO_SEND_TIME );
		#else
			sendBeaconStat( 1000 );
		#endif
	#endif



	// Shelleingaben verarbeiten
	#ifdef APPLICATION_USBSHELL
			useShell();
	#endif

	// verarbeiten der USB Packete ( Datenpackete )
	#ifdef OPENBEACON_SEND_USB_PACKET_DATA
		if(last_usb_recvmesg==NULL) vUSBRecivePacket( &last_usb_recvmesg );
		if(sending==0 && last_usb_recvmesg!=NULL && xTaskGetTickCount()-ob_send_time > OPENBEACON_SEND_WIRELESS) {
			OBD2HW_Header* pobd2hw = (OBD2HW_Header*) last_usb_recvmesg->pValue;

			if( pobd2hw->type==PACKET_DATA ) {
				Click2OBD_header* pclick2obd = (Click2OBD_header*) (last_usb_recvmesg->pValue+sizeof(OBD2HW_Header) );

				ob_setChannel( pclick2obd->channel );
				ob_setRate( pclick2obd->rate );
				ob_setPower( pclick2obd->power );
				ob_setNetID( pclick2obd->openbeacon_dmac );

				// TODO: den Payload ob_data richtig festlegen
				memcpy(send_buffer.payload, last_usb_recvmesg->pValue+sizeof(OBD2HW_Header)+sizeof(Click2OBD_header)-OPENBEACON_MACSIZE, OPENBEACON_MAX_DATA);

				switch( sendBeacon( &send_buffer ) ) {
					case 0:	sending=1;
							AT91F_PIO_ClearOutput( AT91C_BASE_PIOA, LED_RED );
							pushFreeBlock( last_usb_recvmesg );
							last_usb_recvmesg=NULL;
						break;
					case -1:

						break;
				}
				ob_send_time=xTaskGetTickCount();
			} else {
				pushFreeBlock( last_usb_recvmesg );
				last_usb_recvmesg=NULL;
			}
		}
	#endif
}
// ////////////////////////////////////////////////////////////////////////////
// ////////////////////////////////////////////////////////////////////////////
// Recv Messages. Get a message and dispatch to relevant function.
bool recvMessage(void)
{
	NETQUEUE queue;
	uint8_t type;

	while (NETrecvNet(&queue, &type) || NETrecvGame(&queue, &type))          // for all incoming messages.
	{
		bool processedMessage1 = false;
		bool processedMessage2 = false;

		if (queue.queueType == QUEUE_GAME)
		{
			syncDebug("Processing player %d, message %s", queue.index, messageTypeToString(type));
		}

		// messages only in game.
		if(!ingame.localJoiningInProgress)
		{
			processedMessage1 = true;
			switch(type)
			{
			case GAME_DROIDINFO:					//droid update info
				recvDroidInfo(queue);
				break;
			case NET_TEXTMSG:					// simple text message
				recvTextMessage(queue);
				break;
			case NET_DATA_CHECK:
				recvDataCheck(queue);
				break;
			case NET_AITEXTMSG:					//multiplayer AI text message
				recvTextMessageAI(queue);
				break;
			case NET_BEACONMSG:					//beacon (blip) message
				recvBeacon(queue);
				break;
			case GAME_DROIDDISEMBARK:
				recvDroidDisEmbark(queue);           //droid has disembarked from a Transporter
				break;
			case GAME_GIFT:						// an alliance gift from one player to another.
				recvGift(queue);
				break;
			case GAME_LASSAT:
				recvLasSat(queue);
				break;
			case GAME_DEBUG_MODE:
				recvProcessDebugMappings(queue);
				break;
			case GAME_DEBUG_ADD_DROID:
				recvDroid(queue);
				break;
			case GAME_DEBUG_ADD_STRUCTURE:
				recvBuildFinished(queue);
				break;
			case GAME_DEBUG_ADD_FEATURE:
				recvMultiPlayerFeature(queue);
				break;
			case GAME_DEBUG_REMOVE_DROID:
				recvDestroyDroid(queue);
				break;
			case GAME_DEBUG_REMOVE_STRUCTURE:
				recvDestroyStructure(queue);
				break;
			case GAME_DEBUG_REMOVE_FEATURE:
				recvDestroyFeature(queue);
				break;
			case GAME_DEBUG_FINISH_RESEARCH:
				recvResearch(queue);
				break;
			default:
				processedMessage1 = false;
				break;
			}
		}

		// messages usable all the time
		processedMessage2 = true;
		switch(type)
		{
		case GAME_TEMPLATE:					// new template
			recvTemplate(queue);
			break;
		case GAME_TEMPLATEDEST:				// template destroy
			recvDestroyTemplate(queue);
			break;
		case NET_PING:						// diagnostic ping msg.
			recvPing(queue);
			break;
		case NET_OPTIONS:
			recvOptions(queue);
			break;
		case NET_PLAYER_DROPPED:				// remote player got disconnected
		{
			uint32_t player_id;

			NETbeginDecode(queue, NET_PLAYER_DROPPED);
			{
				NETuint32_t(&player_id);
			}
			NETend();

			if (whosResponsible(player_id) != queue.index && queue.index != NET_HOST_ONLY)
			{
				HandleBadParam("NET_PLAYER_DROPPED given incorrect params.", player_id, queue.index);
				break;
			}

			debug(LOG_INFO,"** player %u has dropped!", player_id);

			if (NetPlay.players[player_id].allocated)
			{
				MultiPlayerLeave(player_id);		// get rid of their stuff
				NET_InitPlayer(player_id, false);
			}
			NETsetPlayerConnectionStatus(CONNECTIONSTATUS_PLAYER_DROPPED, player_id);
			break;
		}
		case NET_PLAYERRESPONDING:			// remote player is now playing
		{
			uint32_t player_id;

			resetReadyStatus(false);

			NETbeginDecode(queue, NET_PLAYERRESPONDING);
				// the player that has just responded
				NETuint32_t(&player_id);
			NETend();
			if (player_id >= MAX_PLAYERS)
			{
				debug(LOG_ERROR, "Bad NET_PLAYERRESPONDING received, ID is %d", (int)player_id);
				break;
			}
			// This player is now with us!
			ingame.JoiningInProgress[player_id] = false;
			break;
		}
		// FIXME: the next 4 cases might not belong here --check (we got two loops for this)
		case NET_COLOURREQUEST:
			recvColourRequest(queue);
			break;
		case NET_POSITIONREQUEST:
			recvPositionRequest(queue);
			break;
		case NET_TEAMREQUEST:
			recvTeamRequest(queue);
			break;
		case NET_READY_REQUEST:
			recvReadyRequest(queue);

			// if hosting try to start the game if everyone is ready
			if(NetPlay.isHost && multiplayPlayersReady(false))
			{
				startMultiplayerGame();
			}
			break;
		case GAME_ALLIANCE:
			recvAlliance(queue, true);
			break;
		case NET_KICK:	// in-game kick message
		{
			uint32_t player_id;
			char reason[MAX_KICK_REASON];
			LOBBY_ERROR_TYPES KICK_TYPE = ERROR_NOERROR;

			NETbeginDecode(queue, NET_KICK);
				NETuint32_t(&player_id);
				NETstring(reason, MAX_KICK_REASON);
				NETenum(&KICK_TYPE);
			NETend();

			if (player_id == NET_HOST_ONLY)
			{
				char buf[250]= {'\0'};

				ssprintf(buf, "Player %d (%s : %s) tried to kick %u", (int) queue.index, NetPlay.players[queue.index].name, NetPlay.players[queue.index].IPtextAddress, player_id);
				NETlogEntry(buf, SYNC_FLAG, 0);
				debug(LOG_ERROR, "%s", buf);
				if (NetPlay.isHost)
				{
					NETplayerKicked((unsigned int) queue.index);
				}
				break;
			}
			else if (selectedPlayer == player_id)  // we've been told to leave.
			{
				debug(LOG_ERROR, "You were kicked because %s", reason);
				setPlayerHasLost(true);
			}
			else
			{
				debug(LOG_NET, "Player %d was kicked: %s", player_id, reason);
				NETplayerKicked(player_id);
			}
			break;
		}
		case GAME_RESEARCHSTATUS:
			recvResearchStatus(queue);
			break;
		case GAME_STRUCTUREINFO:
			recvStructureInfo(queue);
			break;
		case NET_PLAYER_STATS:
			recvMultiStats(queue);
			break;
		case GAME_PLAYER_LEFT:
			recvPlayerLeft(queue);
			break;
		default:
			processedMessage2 = false;
			break;
		}

		if (processedMessage1 && processedMessage2)
		{
			debug(LOG_ERROR, "Processed %s message twice!", messageTypeToString(type));
		}
		if (!processedMessage1 && !processedMessage2)
		{
			debug(LOG_ERROR, "Didn't handle %s message!", messageTypeToString(type));
		}

		NETpop(queue);
	}

	return true;
}