一、手机APP程序
1、AndroidManifest.xml文件
添加应用访问网络和WIFI权限:因为手机端要连接XR806发出来的热点,需要用到WIFI。
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.administrator.xr806">
<!-- 允许应用程序改变网络状态 -->
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
<!-- 允许应用程序改变WIFI连接状态 -->
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<!-- 允许应用程序访问有关的网络信息 -->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<!-- 允许应用程序访问WIFI网卡的网络信息 -->
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<!-- 允许应用程序完全使用网络 -->
<uses-permission android:name="android.permission.INTERNET" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
2、activity_main.xml布局文件
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#00bfff"
tools:context=".MainActivity">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:gravity="center"
android:layout_weight="1"
android:text="IP地址:"
android:textSize="25sp" />
<EditText
android:id="@+id/ip"
android:layout_width="200dp"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:gravity="center_horizontal"
android:hint="192.168.1.1"
android:layout_weight="3"
android:maxLines="5" />
</LinearLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:gravity="center"
android:layout_weight="1"
android:text="端口号:"
android:textSize="25sp" />
<EditText
android:id="@+id/port"
android:layout_width="200dp"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:gravity="center_horizontal"
android:hint="80"
android:layout_weight="3"
android:maxLines="5" />
</LinearLayout>
<Button
android:id="@+id/connect"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="连接"
android:layout_gravity="center_horizontal"
android:textColor="#0000ff"
android:textSize="20sp" />
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<Button
android:id="@+id/turnOn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="开灯"
android:layout_gravity="left"
android:textColor="#000000"
android:textSize="20sp" />
<Button
android:id="@+id/turnOff"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="关灯"
android:layout_gravity="left"
android:textColor="#ff0000"
android:textSize="20sp" />
</LinearLayout>
<Switch
android:id="@+id/switch1"
android:layout_width="50dp"
android:layout_height="wrap_content"
android:text="" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:gravity="center"
android:text="亮度调节"
android:textSize="25sp" />
<SeekBar
android:id="@+id/PWM"
style="@style/Widget.AppCompat.SeekBar"
android:layout_width="match_parent"
android:layout_height="40dp"
android:layout_marginTop="20dp"
android:background="@android:color/background_light"
android:max="100"
android:progress="0" />
</LinearLayout>
实现后的效果
3、MainActivity.java文件
实现TCP客户端发送数据给XR806。
package com.example.administrator.xr806;
import android.annotation.SuppressLint;
import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.SeekBar;
import android.widget.Toast;
import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;
public class MainActivity extends AppCompatActivity implements View.OnClickListener,SeekBar.OnSeekBarChangeListener{
private static final String TAG = "MainActivity";
private Socket socket=null;
private OutputStream out=null;
private EditText ip;
private EditText port;
private String ipStr="192.168.51.1";
private int portInt=80;
private SeekBar pwm;
private int pwmInt=0;
public short TYPE = 0xAA;
public short MAJOR = 0x00;
public short FIRST = 0x00;
public short SECOND = 0x00;
public short THRID = 0x00;
public short CHECKSUM = 0x00;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ip=(EditText)findViewById(R.id.ip);
port=(EditText)findViewById(R.id.port);
pwm=(SeekBar)findViewById(R.id.PWM);
Button connect=(Button)findViewById(R.id.connect);
Button turnOn=(Button)findViewById(R.id.turnOn);
Button turnOff=(Button)findViewById(R.id.turnOff);
connect.setOnClickListener(this); //实现按键连接的接口
turnOn.setOnClickListener(this);
turnOff.setOnClickListener(this);
pwm.setOnSeekBarChangeListener(this);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.connect:
new Thread(new Runnable() {
@Override
public void run() {
phHandler.sendEmptyMessage(10);//获取输入的IP地址和端口号
startClient(); //执行连接WIFI
}
}).start();
break;
case R.id.turnOn:
sendData((short) 0x01);//开灯
Log.e(TAG, "开灯");
break;
case R.id.turnOff:
sendData((short)0x02);//关灯
Log.e(TAG, "关灯");
break;
default:
break;
}
}
public void startClient() {
try {
socket = new Socket(ipStr, portInt);
if(socket==null){
socket.isConnected(); //连接XR806
Log.e(TAG, "正在连接XR806: ");
}
Log.e(TAG, "连接成功: ");
phHandler.sendEmptyMessage(20);
out = socket.getOutputStream(); //获取输出的数据
} catch (Exception e) { //捕获输出数据是否有异常
e.printStackTrace();
}
}
@SuppressLint("HandlerLeak")
public Handler phHandler = new Handler() {
public void handleMessage(Message msg) {
if (msg.what == 10) {
String portStr="80";
ipStr=ip.getText().toString();
portStr=port.getText().toString();
if (port.getText().toString().equals(""))
portStr="80";
if (ipStr.equals(""))
ipStr="192.168.51.1";
portInt=Integer.parseInt(portStr);
Log.e(TAG, "IP地址: "+ipStr +" 端口号:"+portInt);
}
if (msg.what==20){
Toast.makeText(MainActivity.this,"连接成功",Toast.LENGTH_LONG).show();
}
if (msg.what==30){
Toast.makeText(MainActivity.this,"连接失败",Toast.LENGTH_LONG).show();
}
}
};
public void sendData(final short data){
new Thread(new Runnable() {
@Override
public void run() {
try {
FIRST=data;
CHECKSUM=(short) ((FIRST+SECOND+THRID)%256);
final byte[] sbyte = {0x55, (byte) TYPE,(byte) FIRST, (byte) SECOND, (byte) THRID, (byte) CHECKSUM, (byte) 0xBB};
Log.e(TAG, "发送数据"+Integer.toHexString(sbyte[0])+" "+Integer.toHexString(sbyte[1])+" "
+Integer.toHexString(sbyte[2])+" "+Integer.toHexString(sbyte[3])
+" "+Integer.toHexString(sbyte[4])+" "+Integer.toHexString(sbyte[5])
+" "+Integer.toHexString(sbyte[6]));
out.write(sbyte,0,sbyte.length); //输出数据
out.flush();
} catch (IOException e) { //捕获一下(Input/Output)的异常
e.printStackTrace();
}
}
}).start();
}
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
switch (seekBar.getId()) {
case R.id.PWM:
if (fromUser) {
pwmInt= progress;
SECOND=0x03;
sendData((short) pwmInt);
Log.e(TAG, "PWM:"+pwmInt);
}
break;
default:
break;
}
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
Log.e(TAG, "开始滑动时触发该事件");
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
Log.e(TAG, "结束滑动时触发该事件");
SECOND=0x00;
}
}
二、XR806程序编写
1、BUILD.gn文件
添加头文件路径和.c文件路径
import("//device/xradio/xr806/liteos_m/config.gni")
static_library("app_tcp") {
configs = []
sources = [
"main.c",
]
cflags = board_cflags
include_dirs = board_include_dirs
include_dirs += [
".",
"//base/iot_hardware/peripheral/interfaces/kits",
"//utils/native/lite/include",
"//foundation/communication/wifi_lite/interfaces/wifiservice",
]
}
2、main.c文件
大部分是参考例程和其它大佬的程序,就大体就三个部分,第一就是XR806发射出WIFI热点,第二就是设置TCP 服务端,第三就是传输过来的数据处理和LED的亮灭和亮度调节(PWM)。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "wifi_hotspot.h"
#include "wifi_device.h"
#include "ohos_init.h"
#include "kernel/os/os.h"
#include "wifi_device.h"
#include "lwip/sockets.h"
#include "iot_gpio.h"
#define GPIO_ID_PA21 21
#define WIFI_HOSTAP_SSID "WIFI_DEVICE_AP_TEST"
#define WIFI_HOSTAP_PSK "12345678"
int tcp_server_init(int port);
int tcp_server_accept(int sfd);
void wifi_device_ap_test();
void LED_Handler(char *recv_buf);
static OS_Thread_t g_main_thread;
static void MainThread(void *arg)
{
int sfd = 0;
int cfd = 0;
char recv_buf[7] = {0};
wifi_device_ap_test();
sfd=tcp_server_init(80);
cfd=tcp_server_accept(sfd);
while (1) {
if(-1!=recv(cfd, recv_buf, sizeof(recv_buf), 0))
{
LED_Handler(recv_buf);
for (int i = 0; i < 7; i++)
{
printf(" recv_buf[%d] : %x\r\n", i,recv_buf[i]);
recv_buf[i]=0;
}
printf("HELLO World\r\n");
send(cfd,"good", 5,0);
}
}
}
void LED_Handler(char *recv_buf)
{
char CHECKSUM=((recv_buf[2]+recv_buf[3]+recv_buf[4])%256);
if (recv_buf[0]==0x55&&recv_buf[1]==0xAA&&CHECKSUM==recv_buf[5]&&recv_buf[6]==0xBB)
{
if (recv_buf[2]==0x01&&recv_buf[3]!=0x03)
{
printf("Turn On LED\r\n");
IoTGpioInit(GPIO_ID_PA21);
IoTGpioSetDir(GPIO_ID_PA21, IOT_GPIO_DIR_OUT);
IoTGpioSetOutputVal(GPIO_ID_PA21,1);
}
if (recv_buf[2]==0x02&&recv_buf[3]!=0x03)
{
printf("Turn Off LED\r\n");
IoTGpioInit(GPIO_ID_PA21);
IoTGpioSetDir(GPIO_ID_PA21, IOT_GPIO_DIR_OUT);
IoTGpioSetOutputVal(GPIO_ID_PA21,0);
}
if (recv_buf[3]==0x03)
{
printf("PWM LED Light:%d\r\n",recv_buf[2]);
IoTPwmInit(2);
IoTPwmStart(2, recv_buf[2], 2000);
}
}
}
void WifiTestMain(void)
{
printf("Wifi Connect Start\n");
if (OS_ThreadCreate(&g_main_thread, "MainThread", MainThread, NULL,
OS_THREAD_PRIO_APP, 4 * 1024) != OS_OK) {
printf("[ERR] Create MainThread Failed\n");
}
}
SYS_RUN(WifiTestMain);
int tcp_server_init(int port)
{
int sfd = 0;
struct sockaddr_in saddr;
sfd = socket(AF_INET,SOCK_STREAM,0);
memset(&saddr, 0, sizeof(saddr));
saddr.sin_family = AF_INET;
saddr.sin_port = htons(port);
saddr.sin_addr.s_addr = htonl(INADDR_ANY);
bind(sfd, (struct sockaddr*)&saddr, sizeof(saddr));
listen(sfd,1);
return sfd;
}
int tcp_server_accept(int sfd)
{
int cfd = 0;
struct sockaddr_in caddr;
memset(&caddr, 0, sizeof(struct sockaddr_in));
int addrl = sizeof(struct sockaddr_in);
cfd = accept(sfd , (struct sockaddr*)&caddr , &addrl);
return cfd;
}
WifiEvent ap_event;
static void printf_mac_address(unsigned char *mac_address)
{
for (int i = 0; i < WIFI_MAC_LEN - 1; i++) {
printf("%02X:", mac_address[i]);
}
printf("%02X\n", mac_address[WIFI_MAC_LEN - 1]);
}
static void Ap_started_deal(int state)
{
if (state == WIFI_STATE_AVALIABLE) {
printf("=====> Callback: ap is started\n");
}
}
static void Ap_sta_join(StationInfo *info)
{
printf("=====> Callback: station join, the mac address: ");
printf_mac_address(info->macAddress);
}
static void Ap_sta_leave(StationInfo *info)
{
printf("=====> Callback: station leave, the mac address: ");
printf_mac_address(info->macAddress);
}
void wifi_device_ap_test()
{
printf("\n=========== Hotspot(AP) Test Start ===========\n");
ap_event.OnWifiConnectionChanged = NULL;
ap_event.OnWifiScanStateChanged = NULL;
ap_event.OnHotspotStateChanged = Ap_started_deal;
ap_event.OnHotspotStaJoin = Ap_sta_join;
ap_event.OnHotspotStaLeave = Ap_sta_leave;
if (WIFI_SUCCESS != RegisterWifiEvent(&ap_event)) {
printf("Error: RegisterWifiEvent fail\n");
return;
}
printf("RegisterWifiEvent Success\n");
HotspotConfig ap_config = { .ssid = WIFI_HOSTAP_SSID,
.securityType = WIFI_SEC_TYPE_PSK,
.band = HOTSPOT_BAND_TYPE_2G,
.channelNum = 6,
.preSharedKey = WIFI_HOSTAP_PSK };
if (WIFI_SUCCESS != SetHotspotConfig(&ap_config)) {
printf("Error: SetHotspotConfig Fail\n");
return;
}
printf("SetHotspotConfig Success\n");
if (WIFI_SUCCESS != EnableHotspot()) {
printf("Error: EnableHotspot Fail\n");
return;
}
printf("EnableHotspot Success, Use your phone to connect it:\n");
printf("SSID:%s\n", WIFI_HOSTAP_SSID);
printf("PSK:%s\n", WIFI_HOSTAP_PSK);
if (WIFI_HOTSPOT_ACTIVE == IsHotspotActive()) {
printf("Wifi is active\n");
} else {
printf("Wifi isn't active\n");
}
printf("\n=========== Hotspot(AP) Test End ===========\n");
}
三、实现效果
https://www.bilibili.com/vide...
四、总结
首先感谢极术社区送的开发板,因为之前没搞过移植系统编译固件这些东西,所以搭环境的时候很费劲,但是参考了一些文章之后就感觉好像还可以,后面有时间在用这块开发板做其它的东西吧。