环境: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; } }
此时已经完成了一半。
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>
代码中用了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; } }
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程序还有待完善,读者可自行设计。。。