- 概述
- 课程实训概述
主要是完成通过移动端APP控制智云物联实验平台上的传感器,本次实训实现对灯光传感器的控制或实现对自有电路板上某一元器件的控制。
-
- 主要内容
本次实训报告的主要内容包括以下几点:
(1)智云物联实验平台简介。
(2)配置智云物联实验平台硬件。
(3)基本功能的实现,美化软件界面,提高用户输入操作性和界面显示友好性。
(4)思考总结开发过程中的问题和想法。
- 智云物联平台简介
- 智云物联平台项目系统模型
用户通过注册模块,获取到一个账号权限。通过账号登录到开关控制界面,通过拨动按钮来控制灯的开关。
-
- ZXBee通信协议
ZXBee是一套基于JSON格式的轻量级物联网通信协议。
ZXBee协议旨在描述传感器节点与应用间的“对话”。通信协议数据格式: {[参数]=[值],{[参数]=[值],……},每条数据以“{}”作为起始字符,“{}”内参数多个条目以“,”分隔。
-
- 智云物联软件框架
通过移动端连接光照传感器,设置用户账户,用户密钥,服务器地址,光敏传感器MAC地址。
-
- 主要功能设计
(1)布局文件
页面有2个:登录注册页面、和控制页面。其中本节点主要讲解布局设计。界面使用FrameLayout布局,页面下方是一个文字输入框和一个发送按钮,如图2-1所示。
图2-1 界面布局
(2)主配置文件
由于这个应用需要调用平台的信息,所以需要特别在AndroidManifest.xml文件中注册应用访问网络的权限,如下所示:
<uses-permission android:name="android.permission.INTERNET"/>
-
- 通讯设计
public class ZApplication extends Application implements WSNRTConnectListener { public WSNRTConnect wRTConnect;//创建 WSNRTConnect实例 public WSNHistory wHistory;//创建 WSNHistory实例 public WSNRTConnect getWSNRConnect(){ if(wRTConnect==null){ wRTConnect = new WSNRTConnect();//初始化WSNRTConnect实例 } return wRTConnect; } public WSNHistory getWSNHistory(){ if(wHistory==null){ wHistory = new WSNHistory();//初始化WSNHistory实例 } return wHistory; } public void onCreate(){ super.onCreate(); wRTConnect=getWSNRConnect(); wRTConnect.setRTConnectListener(this);//设置WSNRTConnectListener监听 } //消息到达时会自动调用该方法 public void onMessageArrive(String mac,byte[] data){ if(data[0]=='{'&& data[data.length-1]=='}'){ String sData =new String(data,1,data.length-2); String[] pDatas = sData.split(","); for(String pData:pDatas){ String[] tagVal = pData.split("="); if(tagVal.length==2){ for(IOnWSNDataListener li:mIOnWSNDataListeners){ //实现了IOWSNDataListener传感器数据监听接口的类都会自动调用onMessageArrive()方法 li.onMessageArrive(mac,tagVal[0],tagVal[1]); } } } } } //连接失败 public void onConnectLost(Throwable arg0){ Toast.makeText(ZApplication.this,"断开连接",Toast.LENGTH_SHORT).show(); for(IOnWSNDataListener li:mIOnWSNDataListeners){ //实现了IOWSNDataListener传感器数据监听接口的类都会自动调用onConnectLost()方法 li.onConnectLost(); } } //连接成功 @Override public void onConnect() { Toast.makeText(ZApplication.this,"连接网关成功",Toast.LENGTH_SHORT).show(); for(IOnWSNDataListener li:mIOnWSNDataListeners){ //实现了IOWSNDataListener传感器数据监听接口的类都会自动调用onConnect()方法 li.onConnect(); } } //传感器数据监听器数组 public ArrayList<IOnWSNDataListener>mIOnWSNDataListeners = new ArrayList<>(); //注册传感器数据监听器 public void registerOnWSNDataListener(IOnWSNDataListener li){mIOnWSNDataListeners.add(li);} //取消注册传感器数据监听器 public void unregisterOnWSNDataListener(IOnWSNDataListener li){ mIOnWSNDataListeners.remove(li); } } |
- 系统实现
- 系统界面
- 系统程序实现
- Android客户端程序实现
(1)项目整体框架
(2)Register中的登录按钮点击事件
public class Register extends AppCompatActivity {
private SQlite mSQlite;
private EditText username;
private EditText userpassword;
private Button reday;
private Button back;
String name;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.start);
reday = findViewById(R.id.reday);
back = findViewById(R.id.back);
username = findViewById(R.id.userName);
userpassword =findViewById( R.id.userpassword);
reday.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
name = username.getText().toString().trim();
String password = userpassword.getText().toString().trim();
if(!TextUtils.isEmpty(name)&&!TextUtils.isEmpty(password)){
mSQlite.add(name,password);
Intent intent1 = new Intent(Register.this,MainActivity.class);
startActivity(intent1);
finish();
Toast.makeText(Register.this,"注册成功",Toast.LENGTH_SHORT).show();
}else {Toast.makeText(Register.this,"信息不完备,注册失败",Toast.LENGTH_SHORT).show();}
}
});
mSQlite = new SQlite(Register.this);
back.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String name = username.getText().toString().trim();
String password = userpassword.getText().toString().trim();
try {
// 当用户按下发送按钮后,将用户输入的数据封装成
//Message
// 然后发送给子线程的 Handler
// 清空 input 文本框
// input.setText("");
} catch (Exception e) {
e.printStackTrace();
}
if (!TextUtils.isEmpty( name ) && !TextUtils.isEmpty( password )) {
ArrayList<User> data = mSQlite.getAllDATA();
boolean user = false;
for (int i = 0; i < data.size(); i++) {
User userdata = data.get( i ); //可存储账号数量
if (name.equals( userdata.getName() ) && password.equals( userdata.getPassword() )) {
user = true;
break;
} else {
user = false;
}
}
if (user) {
baocun.name= username.getText().toString();
baocun.password= userpassword.getText().toString();
Toast.makeText( Register.this, "登录成功", Toast.LENGTH_SHORT ).show();
Intent intent = new Intent( Register.this, MainActivity.class );
intent.putExtra( "username", name );
intent.putExtra( "password", password ); //展示账号密码功能
startActivity( intent );
finish();
} else {
Toast.makeText( Register.this, "用户名或密码不正确", Toast.LENGTH_SHORT ).show();
}
} else {
Toast.makeText( Register.this, "用户名或密码不能为空", Toast.LENGTH_SHORT ).show();
}
}
});
}
}
(3)MainActivity中的发送按钮点击事件
public class MainActivity extends AppCompatActivity implements IOnWSNDataListener{
private ZApplication mApplication;//创建 ZApplication实例
private WSNRTConnect wRTConnect;//创建WSNRTConnect实例
//配置信息
private String ID = "837958346782";//用户账户
private String KEY = "CQUEAAwOBwUABAgKQxFBWFlRV11CFQISCQoCDAYKBwUDDhQSGl1WVFAaCRQUT01IUEoVRA8";//用户密钥
private String server = "zhiyun360.com";//服务器地址
private String mMac = "00:12:4b:00:07:5E:23:D2";//光敏传感器IEEE地址
private TextView tv1;
private TextView tv2;
private ImageView btn;
int[] ic=new int[]{R.mipmap.btn0,R.mipmap.btn1};
private int setCount = 0;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mApplication = (ZApplication) getApplication();
wRTConnect = mApplication.getWSNRConnect();
wRTConnect.setIdKey(ID, KEY);//设置ID,KEY
wRTConnect.setServerAddr(server);//设置服务器地址
mApplication.registerOnWSNDataListener((IOnWSNDataListener) MainActivity.this);
wRTConnect.connect();//建立实时连接
tv1 = findViewById(R.id.textView1);
tv2 = findViewById(R.id.textView1);
btn = findViewById(R.id.button1);
btn.setOnClickListener(new View.OnClickListener() {
public void onClick(View x) {
if (setCount % 2 == 1) {
setCount++;
new Thread(new Runnable() {
@Override
public void run() {
wRTConnect.sendMessage(mMac, "{OD1=3,D1=1}".getBytes());//查询关照强度值
tv1.setText("智能LED灯状态:关闭");
}
}).start();
btn.setImageResource(R.drawable.btn0);
Toast.makeText(MainActivity.this, "{OD1=3,D1=1}", Toast.LENGTH_SHORT).show();
} else {
setCount++;
new Thread(new Runnable() {
@Override
public void run() {
wRTConnect.sendMessage(mMac, "{CD1=1,D1=1}".getBytes());//查询关照强度
tv1.setText("智能LED灯状态:开启");
}
}).start();
btn.setImageResource(R.drawable.btn1);
Toast.makeText(MainActivity.this, "{OD1=1,D1=1}", Toast.LENGTH_SHORT).show();
}
}
});
}
@Override
public void onMessageArrive(String mac, String tag, String val) {
}
public void onConnectLost() {//连接失败
tv2.setText("数据连接掉线!");
}
public void onConnect() {//连接成功
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
try {
Looper.prepare();
wRTConnect.sendMessage(mMac, "D1=?".getBytes());
Toast.makeText(MainActivity.this, "D1=?", Toast.LENGTH_SHORT).show();
runOnUiThread(new Runnable() {
@Override
public void run() {
tv2.setText("数据服务连接成功");
}
});
Looper.loop();
} catch (Exception e) {
e.printStackTrace();
}
}
});
thread.start();
}
protected void onDestory()
{
wRTConnect.disconnect();//断开连接
}
}
- 系统测试
- 登录功能测试
表4-1 登录功能测试用例
测试项目 | 登录功能 | 测试编号 | 01 | ||
测试目的 | 登录信息的验证及容错处理 | ||||
序号 | 测试内容 | 测试结果 | 测试结果是否合格 | ||
1 | 不输入任何内容 | 提示:请输入账号或密码 | 合格 | ||
2 | 只输入账号、不输入密码 | 提示:请输入账号或密码 | 合格 | ||
3 | 输入错误的账号密码 | 提示:账号或密码错误 | 合格 | ||
4 | 输入正确的账号密码 | 成功登录到聊天界面 | 合格 | ||
5 | 输入中文账号和密码 | 成功登录到聊天界面 | 合格 | ||
-
- 注册功能测试
表4-2 注册功能测试用例
测试项目 | 注册功能 | 测试编号 | 02 | ||
测试目的 | 注册信息的验证及容错处理 | ||||
序号 | 测试内容 | 测试结果 | 测试结果是否合格 | ||
1 | 不输入任何内容 | 提示:请输入完整信息! | 合格 | ||
2 | 只输入账号 | 提示:请输入完整信息! | 合格 | ||
3 | 两次密码输入不一致 | 提示:两次密码不一致! | 合格 | ||
4 | 注册已有账号 | 提示:请勿重复注册! | 合格 | ||
5 | 注册新账号 | 提示:注册成功! | 合格 | ||
-
- 控制功能测试
表4-3 控制功能测试用例
测试项目 | 控制功能 | 测试编号 | 03 | ||
测试目的 | 拨动按钮能否开关灯 | ||||
序号 | 测试内容 | 测试结果 | 测试结果是否合格 | ||
1 | 拨动一次按钮 | 软件无异常,正常显示 | 合格 | ||
2 | 拨动两次按钮 | 软件无异常,正常显示 | 合格 | ||
3 | 拨动三次按钮 | 软件无异常,正常显示 | 合格 | ||
4 | 拨动四次按钮 | 软件无异常,正常显示 | 合格 | ||
- 项目总结
项目总结: 1、 btn.setImageResource(R.drawable.btn0); Toast.makeText(MainActivity.this, "{OD1=3,D1=1}", Toast.LENGTH_SHORT).show(); 要写在}}).start();的下一行,不能写在if里面,不然会出现闪退的情况。 2、setCount++;是实现判断灯光是开启还是关闭的全局变量,通过setCount++来自加一,判断setCount是偶数还是奇数来决策开关灯。一开始我是放在if之前进行setCount++,但是这会出现只能开关一次,第三次就不能进行控制了,之后放在if和else里面第一句,就可以解决这个问题了。 Application常见的用途如下: 初始化资源,App启动时会在Application的onCreate()方法中初始化一些全局资源,系统配置,三方sdk等。 此处需要注意一点,App可能会有多个进程:主进程、三方sdk的一些进程,初始sdk的时候需要注意在相应的进程中去初始化,避免浪费资源。 数据共享,由于Application对象是全局唯一的,所以可以用来缓存一些全局变量,这些变量在任何地方都可以调用,达到共享目的。 监听App所处状态。 实时连接(WSNRTConnect) new WSNRTConnect(myZCloudID, myZCloudKey); 建立实时数据实例,并初始化智云ID及密钥 connect();建立实时数据服务连接 sendMessage(mac, dat); 发送消息 mac:传感器的MAC地址,dat:发送的消息内容 本次的移动平台应用程序设计课程报告基本完成了智能灯的功能开发,同时也得到了很多启示。 这个智能灯只是一个最基础的版本,没有实现更多的可交互和深入挖掘的功能,还有很大的改进空间。比如:可以在移动端设置光照传感器的MAC,不需要在电脑上线设置好配置信息了。 |