智能家電的介紹與使用方法:
本文章所需工具在文章末尾,請君自取。
家居模擬器程序介紹 本程序實現了客廳、臥室、廚房三個房間的智能設備,包括:光亮傳感器、LED燈、溫度傳感器、風扇等。
本程序模擬現在比較流程的智能設備,能夠自動接入WIFI。通過手機、平板等安裝的APP,自動發現這些智能設備。智能設備既可以自主廣播數據(定時或者自身狀態改變),也可以根據請求返回設備的狀態。例如:光亮傳感器,當光線亮度發生變化時會自動廣播自己的當前狀態。而溫度傳感器,則會每隔10秒鐘自動廣播自己的當前狀態。而風扇和LED燈,既可以通過模擬程序控制,也可以通過手機和平板控制。
程序的使用: 運行程序後,點擊“啓動設備”按鈕,啓動TCP服務器。 手機、平板通過TCP連接到模擬程序,即可進行通信。 通信協議:
(1)通信協議採用JSON格式。
(2)模擬程序廣播的數據格式:[{“Device”: “D0001”, “Value”: “50”,
“Value2”: “xx”},> …]。其中,Device爲設備編號,D001代表光亮傳感器,D0002代表LED燈,D0003代表溫度傳感器,D0004代表風扇。Value、Value1表示設備狀態值。
(3)模擬程序接收的數據格式:[{“Device”: “D0001”, “Value”: “50”}, {“Device”:
“D0001”},
…]。如果存在Value、Value1屬性,則表示設置指定的設備狀態。如果不存在Value、Value1屬性,則表示獲取指定設備的狀態。
(4)發現設備的數據格式:[]。即可返回智能設備的信息。
此處的智能設備有燈光,廚房的風扇,還有光線傳感器,溫度
點擊啓動設備即可啓動,現在智能家居等待着客戶端的連接,連接成功就會顯示接收到某個客戶端以及受到客戶端發來的消息
客戶端測試工具:
此客戶端的協議類型默認爲:TCP Client
遠程主機默認爲分配給智能家電的ip地址,或者用本地ip也可,即127.0.0.1
連接的智能家電的端口爲1981,然後點擊連接,發送[]\r\n
上面的智能家電顯示客戶端發送 “[]” 即可返回智能家電的設備信息
\r\n代表的是換行的意思,此客戶端也默認發送消息換行
Device代表的是id號碼
type代表設備的類型
value代表的是設備的狀態,比如風扇的開關,空調的溫度,
valuel代表的是輔助狀態,因爲空調可以具有溫度也可以具有溼度,所以只能家居具有多種狀態
下面在eclipse中採用socket的方式建立與智能家電的連接
實現代碼(步驟中有有正確的解釋):
i
```java
mport java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.Socket;
public class TcpClient {
public static void main(String[] args) {
try {
// 採用socket建立鏈接,連接的IP爲本地連接
// 用localhost或者127.0.0.1的本地IP地址,端口號爲1981
Socket socket = new Socket("127.0.0.1",1981);
// 讀取智能家電傳送來的json信息
BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
// 將信息寫入到智能家電
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
// 採用線程休眠,在讀取之後休眠3秒鐘
Thread.sleep(3000);
// 智能家電提示用[]\r\n與其建立連接,此處將其寫入
writer.write("[]\r\n");
// 採用每次的寫入進行一次刷新
writer.flush();
// 刷新一次休眠0.5秒鐘
Thread.sleep(500);
// 將數據的每一行讀取出來放到控制檯進行顯示
String line = reader.readLine();
System.out.println(line);
} catch (Exception e) {
e.printStackTrace();
}
}
}
舉個列子,控制燈泡的打開;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.net.Socket;
public class TcpClient {
public static void main(String[] args) {
try {
// 採用socket建立鏈接,連接的IP爲本地連接
// 用localhost或者127.0.0.1的本地IP地址,端口號爲1981
Socket socket = new Socket("127.0.0.1",1981);
// 讀取智能家電傳送來的json信息
BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
// 將信息寫入到智能家電
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
// 採用線程休眠,在讀取之後休眠3秒鐘
Thread.sleep(3000);
// 向智能家電傳入json數據來控制燈的開啓(on:開啓;off:關閉;)
writer.write("[{\"Device\":\"D0002\",\"Value\":\"on\"}]\r\n");
writer.flush();
} catch (Exception e) {
e.printStackTrace();
}
}
}
接下來是在Android studio中畫開關的圖紙,佈局採用的是線性佈局
實現代碼:
在xml中:
首先修改xml文件中的Activity標籤,將主頁的設置爲另外的Activity文件(如果此處新建Activity,否則不需要下面的步驟),然後申請網絡權限,因爲連接網絡不是危險權限,所以不需要動態申請(此處很重要)
在java文件中的實現代碼:
i
import androidx.appcompat.app.AppCompatActivity;
import android.gesture.GestureUtils;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.Socket;
public class DeciceTestActivity extends AppCompatActivity implements View.OnClickListener {
// 聲明連接按鈕的變量與輸入輸出流的變量
private Button connectButton;
private BufferedReader reader;
private BufferedWriter writer;
private Socket socket;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_decice_test);
// 綁定事件
findViewById(R.id.connect_button).setOnClickListener(this);
findViewById(R.id.disconnect_button).setOnClickListener(this);
findViewById(R.id.find_device_button).setOnClickListener(this);
findViewById(R.id.led_on_button).setOnClickListener(this);
findViewById(R.id.led_off_button).setOnClickListener(this);
findViewById(R.id.low_button).setOnClickListener(this);
findViewById(R.id.middle_button).setOnClickListener(this);
findViewById(R.id.height_button).setOnClickListener(this);
findViewById(R.id.stop_space).setOnClickListener(this);
}
@Override
public void onClick(View v) {
if (v.getId() == R.id.connect_button) {
// 連接服務器
connectToServer();
} else if (v.getId() == R.id.disconnect_button) {
// 斷開服務器
disconnectFromServer();
} else if (v.getId() == R.id.find_device_button) {
// 查詢設備
findDevices();
} else if (v.getId() == R.id.led_on_button) {
// 開燈
ledTurn("on");
} else if (v.getId() == R.id.led_off_button) {
// 關燈
ledTurn("off");
}else if(v.getId() == R.id.low_button){
lowspace();
}else if(v.getId() == R.id.middle_button){
midelespace();
}else if(v.getId() == R.id.height_button){
heighspace();
}else if (v.getId() == R.id.stop_space){
stopspace();
}
}
// 連接到服務器
private void connectToServer() {
if (socket != null) {
Toast.makeText(this, "已經連接到服務器", Toast.LENGTH_LONG).show();
return;
}
new Thread(new Runnable() {
@Override
public void run() {
try {
Socket socket = new Socket("192.168.1.9", 1981);
reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
writer = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
new Thread(new Runnable() {
@Override
public void run() {
String line;
try {
while ((line = reader.readLine()) != null) {
Log.d("TEST", line);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
} catch (IOException e) {
e.printStackTrace();
Log.d("TEST", "連接服務器錯誤");
}
}
}).start();
}
// 斷開連接
private void disconnectFromServer() {
if (socket == null) {
Toast.makeText(this, "請連接服務器", Toast.LENGTH_LONG).show();
return;
}
if (writer != null) {
try {
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (reader != null) {
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (socket != null) {
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
// 查詢智能設備
private void findDevices() {
new Thread(new Runnable() {
@Override
public void run() {
try {
writer.write("[]\r\n");
writer.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
}
/**
* 設置LED開或者關
*/
private void ledTurn(String status) {
if (socket != null){
Toast.makeText(this,"還未連接服務器",Toast.LENGTH_LONG).show();
return;
}
final String message = "[{\"Device\":\"D0002\",\"Value\":\""+ status +"\"}]\r\n";
new Thread(new Runnable() {
@Override
public void run() {
try {
writer.write(message);
writer.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
}
// 風扇低速
private void lowspace(){
if (socket != null){
Toast.makeText(this,"還未連接服務器",Toast.LENGTH_LONG).show();
return;
}
final String message = "[{\"Device\":\"D0004\",\"Type\":null,\"Value\":\"low\",\"Value1\":null}]\r\n";
new Thread(new Runnable() {
@Override
public void run() {
try {
writer.write(message);
writer.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
}
// 風扇中速
private void midelespace(){
if (socket != null){
Toast.makeText(this,"還未連接服務器",Toast.LENGTH_LONG).show();
return;
}
final String message = "[{\"Device\":\"D0004\",\"Type\":null,\"Value\":\"middle\",\"Value1\":null}]\r\n";
new Thread(new Runnable() {
@Override
public void run() {
try {
writer.write(message);
writer.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
}
// 風扇高速
private void heighspace(){
if (socket != null){
Toast.makeText(this,"還未連接服務器",Toast.LENGTH_LONG).show();
return;
}
final String message = "[{\"Device\":\"D0004\",\"Type\":null,\"Value\":\"high\",\"Value1\":null}]\r\n";
new Thread(new Runnable() {
@Override
public void run() {
try {
writer.write(message);
writer.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
}
// 停止風扇
private void stopspace(){
if (socket != null){
Toast.makeText(this,"還未連接服務器",Toast.LENGTH_LONG).show();
}
final String message = "[{\"Device\":\"D0004\",\"Type\":null,\"Value\":\"off\",\"Value1\":null}]\r\n";
new Thread(new Runnable() {
@Override
public void run() {
try {
writer.write(message);
writer.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
}
}
最後曬兩張運行圖: