Android手机控制ZigBee板上LED

环境:Windows

编译器:IAREW8051-8.1

硬件:CC2530

协议栈:ZStack-CC2530-2.3.0-1.4.0

手机:Android4.1.2

又重新开始学习ZigBee技术,摸索了一哈通信流程,本例程没有涉及到ZigBee组网,读者可自行扩展。

ZigBee流程如下:从串口接收指令信息,根据指令信息控制相应的LED资源,工作模式为协调器,可用GenericApp工程改编,代码如下

/**************************************************************************************************
  Filename:       TESTApp.c
  Revised:        $Date: 2009-03-18 15:56:27 -0700 (Wed, 18 Mar 2009) $
  Revision:       $Revision: 19453 $

  Description:    TEST Application (no Profile).


  Copyright 2004-2009 Texas Instruments Incorporated. All rights reserved.

  IMPORTANT: Your use of this Software is limited to those specific rights
  granted under the terms of a software license agreement between the user
  who downloaded the software, his/her employer (which must be your employer)
  and Texas Instruments Incorporated (the "License").  You may not use this
  Software unless you agree to abide by the terms of the License. The License
  limits your use, and you acknowledge, that the Software may not be modified,
  copied or distributed unless embedded on a Texas Instruments microcontroller
  or used solely and exclusively in conjunction with a Texas Instruments radio
  frequency transceiver, which is integrated into your product.  Other than for
  the foregoing purpose, you may not use, reproduce, copy, prepare derivative
  works of, modify, distribute, perform, display or sell this Software and/or
  its documentation for any purpose.

  YOU FURTHER ACKNOWLEDGE AND AGREE THAT THE SOFTWARE AND DOCUMENTATION ARE
  PROVIDED 揂S IS?WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, 
  INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY, TITLE, 
  NON-INFRINGEMENT AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL
  TEXAS INSTRUMENTS OR ITS LICENSORS BE LIABLE OR OBLIGATED UNDER CONTRACT,
  NEGLIGENCE, STRICT LIABILITY, CONTRIBUTION, BREACH OF WARRANTY, OR OTHER
  LEGAL EQUITABLE THEORY ANY DIRECT OR INDIRECT DAMAGES OR EXPENSES
  INCLUDING BUT NOT LIMITED TO ANY INCIDENTAL, SPECIAL, INDIRECT, PUNITIVE
  OR CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF PROCUREMENT
  OF SUBSTITUTE GOODS, TECHNOLOGY, SERVICES, OR ANY CLAIMS BY THIRD PARTIES
  (INCLUDING BUT NOT LIMITED TO ANY DEFENSE THEREOF), OR OTHER SIMILAR COSTS.

  Should you have any questions regarding your right to use this Software,
  contact Texas Instruments Incorporated at www.TI.com. 
**************************************************************************************************/

/*********************************************************************
  This application isn't intended to do anything useful, it is
  intended to be a simple example of an application's structure.

  This application sends "Hello World" to another "TEST"
  application every 15 seconds.  The application will also
  receive "Hello World" packets.

  The "Hello World" messages are sent/received as MSG type message.

  This applications doesn't have a profile, so it handles everything
  directly - itself.

  Key control:
    SW1:
    SW2:  initiates end device binding
    SW3:
    SW4:  initiates a match description request
*********************************************************************/

/*********************************************************************
 * INCLUDES
 */
#include "OSAL.h"
#include "AF.h"
#include "ZDApp.h"
#include "ZDObject.h"
#include "ZDProfile.h"

#include "Common.h"
#include "DebugTrace.h"

#if !defined( WIN32 )
  #include "OnBoard.h"
#endif

/* HAL */
#include "hal_lcd.h"
#include "hal_led.h"
#include "hal_key.h"
#include "hal_uart.h"

#include "OSAL_Nv.h"

/*********************************************************************
 * MACROS
 */

/*********************************************************************
 * CONSTANTS
 */

/*********************************************************************
 * TYPEDEFS
 */

/*********************************************************************
 * GLOBAL VARIABLES
 */

// This list should be filled with Application specific Cluster IDs.
const cId_t TESTApp_ClusterList[TESTAPP_MAX_CLUSTERS] =
{
  TESTAPP_CLUSTERID
};

const SimpleDescriptionFormat_t TestApp_SimpleDesc =
{
  TESTAPP_ENDPOINT,              //  int Endpoint;
  TESTAPP_PROFID,                //  uint16 AppProfId[2];
  TESTAPP_DEVICEID,              //  uint16 AppDeviceId[2];
  TESTAPP_DEVICE_VERSION,        //  int   AppDevVer:4;
  TESTAPP_FLAGS,                 //  int   AppFlags:4;
  TESTAPP_MAX_CLUSTERS,          //  byte  AppNumInClusters;
  (cId_t *)TESTApp_ClusterList,  //  byte *pAppInClusterList;
  0,          //  byte  AppNumInClusters;
  (cId_t *)NULL  //  byte *pAppInClusterList;
};//用于描述一个设备节点

// This is the Endpoint/Interface description.  It is defined here, but
// filled-in in TESTApp_Init().  Another way to go would be to fill
// in the structure here and make it a "const" (in code space).  The
// way it's defined in this sample app it is define in RAM.
endPointDesc_t TestApp_epDesc;//节点描述符

/*********************************************************************
 * EXTERNAL VARIABLES
 */

/*********************************************************************
 * EXTERNAL FUNCTIONS
 */

/*********************************************************************
 * LOCAL VARIABLES
 */
byte TestApp_TaskID;   // Task ID for internal task/event processing
                          // This variable will be received when
                          // TESTApp_Init() is called.
devStates_t TestApp_NwkState;


byte TestApp_TransID;  // This is the unique message ID (counter)

afAddrType_t TestApp_DstAddr;


static uint8 SerialApp_TxLen;
static void rxCB(uint8 port, uint8 event);
/*********************************************************************
 * LOCAL FUNCTIONS
 */
void TestApp_ProcessZDOMsgs( zdoIncomingMsg_t *inMsg );
void TestApp_HandleKeys( byte shift, byte keys );
void TestApp_MessageMSGCB( afIncomingMSGPacket_t *pckt );
void TestApp_SendTheMessage( void );

/*********************************************************************
 * NETWORK LAYER CALLBACKS
 */

/*********************************************************************
 * PUBLIC FUNCTIONS
 */

/*********************************************************************
 * @fn      TESTApp_Init
 *
 * @brief   Initialization function for the TEST App Task.
 *          This is called during initialization and should contain
 *          any application specific initialization (ie. hardware
 *          initialization/setup, table initialization, power up
 *          notificaiton ... ).
 *
 * @param   task_id - the ID assigned by OSAL.  This ID should be
 *                    used to send messages and set timers.
 *
 * @return  none
 */
void TestApp_Init( byte task_id )
{
  halUARTCfg_t uartConfig;
  TestApp_TaskID = task_id;
  TestApp_NwkState = DEV_INIT;
  TestApp_TransID = 0;

  // Device hardware initialization can be added here or in main() (Zmain.c).
  // If the hardware is application specific - add it here.
  // If the hardware is other parts of the device add it in main().

  TestApp_DstAddr.addrMode = (afAddrMode_t)Addr16Bit;
  TestApp_DstAddr.endPoint = TESTAPP_ENDPOINT;
  TestApp_DstAddr.addr.shortAddr = 0xFFFF;

  // Fill out the endpoint description.
  TestApp_epDesc.endPoint = TESTAPP_ENDPOINT;
  TestApp_epDesc.task_id = &TestApp_TaskID;
  TestApp_epDesc.simpleDesc
            = (SimpleDescriptionFormat_t *)&TestApp_SimpleDesc;
  TestApp_epDesc.latencyReq = noLatencyReqs;

  // Register the endpoint description with the AF
  afRegister( &TestApp_epDesc );
  
  uartConfig.configured = TRUE;
  uartConfig.baudRate = HAL_UART_BR_115200;
  uartConfig.flowControl                    = FALSE; 
  uartConfig.flowControlThreshold = 64; // 2x30 don't care - see uart driver. 
  uartConfig.rx.maxBufSize                = 128;    // 2x30 don't care - see uart driver. 
  uartConfig.tx.maxBufSize                = 128;    // 2x30 don't care - see uart driver. 
  uartConfig.idleTimeout                    = 6;      // 2x30 don't care - see uart driver. 
  uartConfig.intEnable                        = TRUE;                            // 2x30 don't care - see uart driver. 
  uartConfig.callBackFunc                  = rxCB; 
  HalUARTOpen (0, &uartConfig); 

  // Register for all key events - This app will handle all key events
  //RegisterForKeys( TestApp_TaskID );

  // Update the display
#if defined ( LCD_SUPPORTED )
    HalLcdWriteString( "TestApp", HAL_LCD_LINE_1 );
#endif
    
  ZDO_RegisterForZDOMsg( TestApp_TaskID, End_Device_Bind_rsp );
  ZDO_RegisterForZDOMsg( TestApp_TaskID, Match_Desc_rsp );
}

/*********************************************************************
 * @fn      TESTApp_ProcessEvent
 *
 * @brief   TEST Application Task event processor.  This function
 *          is called to process all events for the task.  Events
 *          include timers, messages and any other user defined events.
 *
 * @param   task_id  - The OSAL assigned task ID.
 * @param   events - events to process.  This is a bit map and can
 *                   contain more than one event.
 *
 * @return  none
 */
UINT16 TestApp_ProcessEvent( byte task_id, UINT16 events )
{
  afIncomingMSGPacket_t *MSGpkt;
 


  (void)task_id;  // Intentionally unreferenced parameter

  if ( events & SYS_EVENT_MSG )
  {
    MSGpkt = (afIncomingMSGPacket_t *)osal_msg_receive( TestApp_TaskID );
    while ( MSGpkt )
    {
      switch ( MSGpkt->hdr.event )
      {
          
        case KEY_CHANGE:
          TestApp_HandleKeys( ((keyChange_t *)MSGpkt)->state, ((keyChange_t *)MSGpkt)->keys );
          break;

        case AF_INCOMING_MSG_CMD:
          TestApp_MessageMSGCB( MSGpkt );
          break;

        default:
          break;
      }

      // Release the memory
      osal_msg_deallocate( (uint8 *)MSGpkt );//释放消息所占用空间

      // Next
      MSGpkt = (afIncomingMSGPacket_t *)osal_msg_receive( TestApp_TaskID );//接着获取消息
    }

    // return unprocessed events
    return (events ^ SYS_EVENT_MSG);
  }

  // Send a message out - This event is generated by a timer
  //  (setup in TESTApp_Init()).
  if ( events & TESTAPP_SEND_MSG_EVT )
  {
    // Send "the" message
    TestApp_SendTheMessage();

    // Setup to send message again
    osal_start_timerEx( TestApp_TaskID,
                        TESTAPP_SEND_MSG_EVT,
                      TESTAPP_SEND_MSG_TIMEOUT );

    // return unprocessed events
    return (events ^ TESTAPP_SEND_MSG_EVT);
  }

  // Discard unknown events
  return 0;
}

/*********************************************************************
 * Event Generation Functions
 */

/*********************************************************************
 * @fn      TESTApp_ProcessZDOMsgs()
 *
 * @brief   Process response messages
 *
 * @param   none
 *
 * @return  none
 */
void TestApp_ProcessZDOMsgs( zdoIncomingMsg_t *inMsg )
{
  switch ( inMsg->clusterID )
  {
    case End_Device_Bind_rsp:
      if ( ZDO_ParseBindRsp( inMsg ) == ZSuccess )
      {
        // Light LED
        HalLedSet( HAL_LED_4, HAL_LED_MODE_ON );
      }
#if defined(BLINK_LEDS)
      else
      {
        // Flash LED to show failure
        HalLedSet ( HAL_LED_4, HAL_LED_MODE_FLASH );
      }
#endif
      break;

    case Match_Desc_rsp:
      {
        ZDO_ActiveEndpointRsp_t *pRsp = ZDO_ParseEPListRsp( inMsg );
        if ( pRsp )
        {
          if ( pRsp->status == ZSuccess && pRsp->cnt )
          {
            TestApp_DstAddr.addrMode = (afAddrMode_t)Addr16Bit;
            TestApp_DstAddr.addr.shortAddr = pRsp->nwkAddr;
            // Take the first endpoint, Can be changed to search through endpoints
            TestApp_DstAddr.endPoint = pRsp->epList[0];

            // Light LED
            HalLedSet( HAL_LED_4, HAL_LED_MODE_ON );
          }
          osal_mem_free( pRsp );
        }
      }
      break;
  }
}

/*********************************************************************
 * @fn      TESTApp_HandleKeys
 *
 * @brief   Handles all key events for this device.
 *
 * @param   shift - true if in shift/alt.
 * @param   keys - bit field for key events. Valid entries:
 *                 HAL_KEY_SW_4
 *                 HAL_KEY_SW_3
 *                 HAL_KEY_SW_2
 *                 HAL_KEY_SW_1
 *
 * @return  none
 */
void TestApp_HandleKeys( byte shift, byte keys )
{
  zAddrType_t dstAddr;
  
  // Shift is used to make each button/switch dual purpose.
  if ( shift )
  {
    if ( keys & HAL_KEY_SW_1 )
    {
    }
    if ( keys & HAL_KEY_SW_2 )
    {
    }
    if ( keys & HAL_KEY_SW_3 )
    {
    }
    if ( keys & HAL_KEY_SW_4 )
    {
    }
  }
  else
  {
    if ( keys & HAL_KEY_SW_1 )
    {
    }

    if ( keys & HAL_KEY_SW_2 )
    {
      HalLedSet ( HAL_LED_4, HAL_LED_MODE_OFF );

      // Initiate an End Device Bind Request for the mandatory endpoint
      dstAddr.addrMode = Addr16Bit;
      dstAddr.addr.shortAddr = 0x0000; // Coordinator
      ZDP_EndDeviceBindReq( &dstAddr, NLME_GetShortAddr(), 
                            TestApp_epDesc.endPoint,
                            TESTAPP_PROFID,
                            TESTAPP_MAX_CLUSTERS, (cId_t *)TESTApp_ClusterList,
                            TESTAPP_MAX_CLUSTERS, (cId_t *)TESTApp_ClusterList,
                            FALSE );
    }

    if ( keys & HAL_KEY_SW_3 )
    {
    }

    if ( keys & HAL_KEY_SW_4 )
    {
      HalLedSet ( HAL_LED_4, HAL_LED_MODE_OFF );
      // Initiate a Match Description Request (Service Discovery)
      dstAddr.addrMode = AddrBroadcast;
      dstAddr.addr.shortAddr = NWK_BROADCAST_SHORTADDR;
      ZDP_MatchDescReq( &dstAddr, NWK_BROADCAST_SHORTADDR,
                        TESTAPP_PROFID,
                        TESTAPP_MAX_CLUSTERS, (cId_t *)TESTApp_ClusterList,
                        TESTAPP_MAX_CLUSTERS, (cId_t *)TESTApp_ClusterList,
                        FALSE );
    }
  }
}

/*********************************************************************
 * LOCAL FUNCTIONS
 */

/*********************************************************************
 * @fn      TESTApp_MessageMSGCB
 *
 * @brief   Data message processor callback.  This function processes
 *          any incoming data - probably from other devices.  So, based
 *          on cluster ID, perform the intended action.
 *
 * @param   none
 *
 * @return  none
 */
void TestApp_MessageMSGCB( afIncomingMSGPacket_t *pkt )
{
  unsigned char buffer;
  static unsigned char LEDState[5];
  switch ( pkt->clusterId )
  {
    case TESTAPP_CLUSTERID:
      // "the" message
      osal_memcpy(&buffer, pkt->cmd.Data, 1);
      switch(buffer)
      {
        case 1:
          LEDState[0]++;
          if(LEDState[0] == 2)
          {
            LEDState[0] = 0;
          }
          if(LEDState[0] == 0)
          {
            HalLedSet(HAL_LED_1, HAL_LED_MODE_ON);
          }
          else
          {
            HalLedSet(HAL_LED_1, HAL_LED_MODE_OFF);
          }
          break;
        case 2:
          LEDState[1]++;
          if(LEDState[1] == 2)
          {
            LEDState[1] = 0;
          }
          if(LEDState[1] == 0)
          {
            HalLedSet(HAL_LED_2, HAL_LED_MODE_ON);
          }
          else
          {
            HalLedSet(HAL_LED_2, HAL_LED_MODE_OFF);
          }
          break;
        case 3:
          LEDState[2]++;
          if(LEDState[2] == 2)
          {
            LEDState[2] = 0;
          }
          if(LEDState[2] == 0)
          {
            HalLedSet(HAL_LED_3, HAL_LED_MODE_ON);
          }
          else
          {
            HalLedSet(HAL_LED_3, HAL_LED_MODE_OFF);
          }
          break;
        case 4:
          LEDState[3]++;
          if(LEDState[3] == 2)
          {
            LEDState[3] = 0;
          }
          if(LEDState[3] == 0)
          {
            HalLedSet(HAL_LED_4, HAL_LED_MODE_ON);
          }
          else
          {
            HalLedSet(HAL_LED_4, HAL_LED_MODE_OFF);
          }
          break;
        case 5:
          LEDState[4]++;
          if(LEDState[4] == 2)
          {
            LEDState[4] = 0;
          }
          if(LEDState[4] == 0)
          {
            HalLedSet(HAL_LED_ALL, HAL_LED_MODE_ON);
          }
          else
          {
            HalLedSet(HAL_LED_ALL, HAL_LED_MODE_OFF);
          }
          break;
      }
#if defined( LCD_SUPPORTED )
      HalLcdWriteScreen( (char*)pkt->cmd.Data, "rcvd" );
#elif defined( WIN32 )
      WPRINTSTR( pkt->cmd.Data );
#endif
      break;
  }
}

/*********************************************************************
 * @fn      TESTApp_SendTheMessage
 *
 * @brief   Send "the" message.
 *
 * @param   none
 *
 * @return  none
 */
void TestApp_SendTheMessage( void )
{
  char theMessageData[] = "LED";

  if ( AF_DataRequest( &TestApp_DstAddr, &TestApp_epDesc,
                       TESTAPP_CLUSTERID,
                       3,
                       theMessageData,
                       &TestApp_TransID,
                       AF_DISCV_ROUTE, AF_DEFAULT_RADIUS ) == afStatus_SUCCESS )
  {
    // Successfully requested to be sent.
  }
  else
  {
    // Error occurred in request to send.
  }
}

/*********************************************************************
*********************************************************************/
static void rxCB(uint8 port, uint8 event)
{
  uint8 Uartbuf[80];
  uint8 buffer;
  static unsigned char LEDState[5];
  bool result = false;
  if((event &(HAL_UART_RX_FULL|HAL_UART_RX_ABOUT_FULL|HAL_UART_RX_TIMEOUT)) && 
#if SERIAL_APP_LOOPBACK
     (SerialApp_TxLen < SERIAL_APP_TX_MAX))
#else
    !SerialApp_TxLen)
#endif
  {
    SerialApp_TxLen = HalUARTRead(0, Uartbuf, 2);
    
    osal_memcpy(&buffer, Uartbuf, 1);
    buffer -=0x30;
    switch(buffer)
    {
      case 0:
        HalLedSet(HAL_LED_1, HAL_LED_MODE_ON);
        result = true;
        break;
      case 1:
        HalLedSet(HAL_LED_2, HAL_LED_MODE_ON);
        result = true;
        break;
      case 2:
        HalLedSet(HAL_LED_3, HAL_LED_MODE_ON);
        result = true;
        break;
      case 3:
        HalLedSet(HAL_LED_ALL, HAL_LED_MODE_ON);
        result = true;
        break;
      case 4:
        HalLedSet(HAL_LED_1, HAL_LED_MODE_OFF);
        result = true;
        break;
      case 5:
        HalLedSet(HAL_LED_2, HAL_LED_MODE_OFF);
        result = true;
       break;
      case 6:
        HalLedSet(HAL_LED_3, HAL_LED_MODE_OFF);
        result = true;
        break; 
      case 7:
        HalLedSet(HAL_LED_ALL, HAL_LED_MODE_OFF);
        result = true;
        break;
    }
    if(result)
    {
      HalUARTWrite(0, "success\r\n", 9); 
    }
    else
    {
      HalUARTWrite(0, "failed\r\n", 8);
    }
    SerialApp_TxLen = 0;
  }
}

只需查看TestApp_Init()以及rxCB()函数即可,在TestApp_Init()函数中对串口0进行配置,在rxCB()函数中对接收到的数据进行解析并对LED资源做出相应的处理。下载程序到板子上,此时可用串口工具来实现对LED资源的控制,串口信息如下所示:

Android手机控制ZigBee板上LED_第1张图片

此时已经完成了一半。

Android端流程:Android建立一个TCP的服务端,然后等待连接,有连接接入时即可发送控制指令到TCP的客户端,

布局文件如下

<?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:background="#eee"
        android:orientation="vertical" >
        
        <RelativeLayout 
  			android:layout_width="fill_parent"
  			android:layout_height="45dp"
  			android:id="@+id/title" 
  			android:background="@drawable/title_bar"
  			android:gravity="center_vertical"
  			> 
  			<Button
  			    android:id="@+id/back"
  			    android:text="返回"
  			    android:textColor="#ffffff"
  			    android:textSize="15sp"
  			   	android:layout_alignParentLeft="true"
        		android:layout_centerVertical="true"
  			    android:layout_width="80dp"
  			    android:layout_height="wrap_content"
  			    android:background="@drawable/title_btn_back"
  			    android:onClick="goBack"
  			    />  
      		<TextView
        		android:layout_width="wrap_content" 
        		android:layout_height="wrap_content" 
        		android:layout_centerInParent="true"
        		android:text="管理"
        		android:textSize="20sp"		
				android:textColor="#ffffff" />   
			<TextView
  			    android:id="@+id/userName"
  			    android:text="用户名"
  			    android:textColor="#ffffff"
  			    android:textSize="15sp"
  			   	android:layout_alignParentRight="true"
        		android:layout_centerInParent="true"
  			    android:layout_width="wrap_content"
  			    android:layout_height="wrap_content"
  			    android:background="@drawable/title_btn_right"
  			    />    
		</RelativeLayout>
		
      	<RelativeLayout  
      	    android:id="@+id/layout_socket_name"
      	    android:layout_below="@id/title"    				    
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="14dp"
            android:gravity="center_vertical"
            android:clickable="true"
            android:background="@drawable/preference_single_item" >
            <TextView
                android:id="@+id/socket_name"
        		android:layout_width="wrap_content" 
        		android:layout_height="wrap_content"
        		android:layout_centerHorizontal="true"
        		android:padding="8dp" 
        		android:text="无线插座"
        		android:textSize="17sp"		
				android:textColor="#000" /> 
									
      	</RelativeLayout>
		<RelativeLayout
		    android:layout_below="@id/layout_socket_name"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="14dp"
            android:gravity="center_horizontal"
            android:background="@drawable/preference_single_item" >
            			 
			<ImageView
				android:id="@+id/socket_iv0"
				android:layout_width="wrap_content"
				android:layout_height="wrap_content"
				android:paddingTop="8dp"
				android:paddingLeft="8dp"
				android:src="@drawable/jack0_close"
				android:clickable="true"
				android:onClick="Manage"
			/>
			<ImageView
				android:id="@+id/socket_iv2"
				android:layout_width="wrap_content"
				android:layout_height="wrap_content"
				android:layout_toRightOf="@id/socket_iv0"
				android:paddingTop="8dp"
			    android:paddingRight="8dp"
			    android:src="@drawable/jack2_close"
			    android:clickable="true"
			    android:onClick="Manage"
			/>
			<ImageView
			    android:id="@+id/socket_iv1"
			    android:layout_width="wrap_content"
			    android:layout_height="wrap_content"
			    android:layout_below="@id/socket_iv0"
			    android:paddingBottom="8dp"
			    android:paddingLeft="8dp"
			    android:src="@drawable/jack1_close"
			    android:clickable="true"
			    android:onClick="Manage"
			    />
			<ImageView
			    android:id="@+id/socket_iv3"
			    android:layout_width="wrap_content"
			    android:layout_height="wrap_content"
			    android:layout_below="@id/socket_iv2"
			    android:layout_toRightOf="@id/socket_iv1"
			    android:paddingBottom="8dp"
			    android:paddingRight="8dp"
			    android:src="@drawable/jack3_close"
			    android:clickable="true"
			    android:onClick="Manage"
			    />
											
      	</RelativeLayout>
      								
		<RelativeLayout      				    
   			android:layout_width="fill_parent"
   			android:layout_height="wrap_content"
   			android:layout_marginTop="14dp"
   			android:gravity="center_vertical"
   			android:clickable="true"
   			android:layout_alignParentBottom="true"
   			android:background="@drawable/preference_single_item" >
   			<TextView
   			    android:id="@+id/socket_id"
 				android:layout_width="wrap_content" 
 				android:layout_height="wrap_content"
 				android:layout_centerHorizontal="true"
 				android:padding="8dp" 
 				android:text="无线插座"
 				android:textSize="17sp"		
				android:textColor="#000" /> 
		
		</RelativeLayout>
   
</RelativeLayout>

布局效果图如下所示:

Android手机控制ZigBee板上LED_第2张图片

代码中用了Apache-Mina库文件,当然也可以不使用。MainActivity.java代码如下

package com.anobodykey.remotecontrol;

import java.io.IOException;
import java.net.InetSocketAddress;

import org.apache.mina.core.filterchain.DefaultIoFilterChainBuilder;
import org.apache.mina.core.session.IoSession;
import org.apache.mina.filter.codec.ProtocolCodecFilter;
import org.apache.mina.filter.codec.textline.TextLineCodecFactory;
import org.apache.mina.transport.socket.SocketAcceptor;
import org.apache.mina.transport.socket.nio.NioSocketAcceptor;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.os.Bundle;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.View;
import android.widget.ImageView;
import android.widget.Toast;

public class MainActivity extends Activity {
	
	private static final int JACK_NUMBER = 4;
	SocketAcceptor acceptor;
	private int[] jacks_id = 
		{
			R.id.socket_iv0, R.id.socket_iv1, 
			R.id.socket_iv2, R.id.socket_iv3,
		};//插孔控件id
	private int[] jacks_status = 
		{
			R.drawable.jack0_close, R.drawable.jack0_open,
			R.drawable.jack1_close, R.drawable.jack1_open,
			R.drawable.jack2_close, R.drawable.jack2_open,
			R.drawable.jack3_close, R.drawable.jack3_open,
		};//插孔状态图片资源
	private ImageView[] jackViews = null;
	static public int iterator = 0;	//插孔遍历器
	static public boolean[] status = null;//插座状态
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.remote_manager);
		
		jackViews = new ImageView[JACK_NUMBER];
		status = new boolean[JACK_NUMBER + 1];
		for(int i = 0; i < JACK_NUMBER; i++)
		{
			jackViews[i] = (ImageView)findViewById(jacks_id[i]);
			status[i] = false;
			if(status[i])
			{
				jackViews[i].setImageResource(jacks_status[2*i + 1]);
			}
			else
			{
				jackViews[i].setImageResource(jacks_status[2*i]);
			}
		}
		status[JACK_NUMBER] = false;
		acceptor = new NioSocketAcceptor();
		DefaultIoFilterChainBuilder chain = acceptor.getFilterChain();
		
		chain.addLast("mychain", new ProtocolCodecFilter(new TextLineCodecFactory()));
		acceptor.setHandler(new SimpleMinaServerHandler());
		int port = 5555;
		try 
		{
			acceptor.bind(new InetSocketAddress(port));
			Toast.makeText(MainActivity.this, "服务器启动完毕", Toast.LENGTH_SHORT).show();
		}
		catch (IOException e) 
		{
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		// Inflate the menu; this adds items to the action bar if it is present.
		getMenuInflater().inflate(R.menu.main, menu);
		return true;
	}
	
	public void Manage(View v)
	{
		for(iterator = 0; iterator < 4; iterator++)
		{
			if(jacks_id[iterator] == v.getId())
			{
				break;
			}
		}
		new AlertDialog.Builder(this)   
		.setTitle("确认对话框")  
		.setMessage("确定要修改该插孔状态吗?")  
		.setPositiveButton("是", new OnClickListener() 
		{
			
			public void onClick(DialogInterface dialog, int which) 
			{
				// TODO Auto-generated method stub
				if(iterator < 3)
				{
					if(status[iterator])
					{
						jackViews[iterator].setImageResource(jacks_status[2*iterator]);
					}
					else
					{
						jackViews[iterator].setImageResource(jacks_status[2*iterator + 1]);
					}
					
					status[iterator] = !status[iterator];
				}
				else if (iterator == 3)
				{
					if(status[iterator])
					{
						for(int i = 0; i <=iterator; i++)
						{
							jackViews[i].setImageResource(jacks_status[2*i]);
						}
					}
					else
					{
						for(int j = 0; j <=iterator; j++)
						{
							jackViews[j].setImageResource(jacks_status[2*j + 1]);
						}
					}
					for(int k = 0; k <=iterator; k++)
						status[k] = !status[k];
				}
				SendMessage();
			}
		})  
		.setNegativeButton("否", null)  
		.show();
	}
	public void SendMessage()
	{
		if(status[iterator])
		{
			SimpleMinaServerHandler.ioSession.write(iterator);
		}
		else
		{
			SimpleMinaServerHandler.ioSession.write(iterator+4);
		}
		
	}
	public void goBack(View v)
	{
		acceptor.unbind();
		acceptor.dispose();
		this.finish();
	}

	@Override
	public boolean onKeyDown(int keyCode, KeyEvent event) {
		// TODO Auto-generated method stub
		if(keyCode == KeyEvent.KEYCODE_BACK && event.getRepeatCount() == 0)
		{
			goBack(null);
		}
		return false;
	}
	
}

SimpleMinaServerHandler.java代码如下

package com.anobodykey.remotecontrol;

import org.apache.mina.core.service.IoHandlerAdapter;
import org.apache.mina.core.session.IdleStatus;
import org.apache.mina.core.session.IoSession;

public class SimpleMinaServerHandler extends IoHandlerAdapter
{
	static public IoSession ioSession; 
	@Override
	public void exceptionCaught(IoSession session, Throwable cause)
			throws Exception {
		// TODO Auto-generated method stub
		super.exceptionCaught(session, cause);
	}

	@Override
	public void messageReceived(IoSession session, Object message)
			throws Exception {
		// TODO Auto-generated method stub
		String s = (String)message;
		System.out.println("message:"+s);
	}

	@Override
	public void messageSent(IoSession session, Object message) throws Exception {
		// TODO Auto-generated method stub
		System.out.println("Sent");
	}

	@Override
	public void sessionClosed(IoSession session) throws Exception {
		// TODO Auto-generated method stub
		System.out.println("closed");;
	}

	@Override
	public void sessionCreated(IoSession session) throws Exception {
		// TODO Auto-generated method stub
		super.sessionCreated(session);
	}

	@Override
	public void sessionIdle(IoSession session, IdleStatus status)
			throws Exception {
		// TODO Auto-generated method stub
		super.sessionIdle(session, status);
	}

	@Override
	public void sessionOpened(IoSession session) throws Exception {
		// TODO Auto-generated method stub
		System.out.println("opend!");
		ioSession = session;
	}
	
}

此外,还需要一个TcpComm的工具,该工具可以将接收的TCP数据转换成串口数据发出,同时也可以将接收到的串口数据转换成TCP数据发出,我们用作中转,此时,就可以实现用手机来控制ZigBee板子上的LED资源啦。。。

PS:Android程序还有待完善,读者可自行设计。。。

你可能感兴趣的:(Android手机控制ZigBee板上LED)