쨍쨍
#5. Al Smart Home_HomeActivty 본문
[ Home 화면 및 기능 ]
1 | 기상청 API를 사용하여 받아온 실외 온도와 습도, 미세먼지 값을 서버에서 받아와서 출력한다. |
2 | - 사용자 설정 Switch를 활성화하면 아두이노 온습도로 측정한 현재 실내온도와 비교하여 사용자가 원하는 실내온도를 설정할 수 있다. 설정 온도와 현재 온도를 비교하여 현재 온도보다 설정 온도가 더 높으면 히터가 작동되고, 현재 온도보다 설정 온도가 더 낮으면 에어컨이 작동한다. - 추천온도 Switch를 활성화하면 실외온도, 현재 온도, 그리고 사용자가 설정한 온도를 데이터로 수집하여 딥러닝 모델이 학습한다. 이를 통해 사용자가 선호하는 특정 온도를 자동으로 설정할 수 있다. |
3 | Switch를 통해서 집 안의 조명, 에어컨, 히터, 공기청정기를 제어할 수 있다. 실제 가전제품과 연결하기에는 예산 상 제약으로 인한 어려움이 있었으나, 비슷한 기능을 제공하는 대체 센서(팬모터, LED 조명)을 활용하여 구현을 진행하였다. |
[ activity_home.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:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".HomeActivity">
<ImageView
android:id="@+id/voice"
android:layout_width="320dp"
android:layout_height="80dp"
android:layout_gravity="center"
android:layout_marginTop="5dp"
android:background="@drawable/home1"/>
<LinearLayout
android:layout_width="350dp"
android:layout_height="150dp"
android:layout_gravity="center"
android:layout_marginTop="5dp"
android:layout_marginBottom="5dp"
android:background="@drawable/edge"
android:orientation="vertical">
<LinearLayout
android:layout_width="350dp"
android:layout_height="50dp"
android:orientation="horizontal">
<TextView
android:layout_width="100dp"
android:layout_height="40dp"
android:layout_gravity="center"
android:layout_marginStart="5dp"
android:gravity="center"
android:text="실외온도"
android:textColor="@color/black"
android:textSize="24sp" />
<TextView
android:id="@+id/out_temp"
android:layout_width="95dp"
android:layout_height="40dp"
android:layout_gravity="center"
android:layout_marginStart="150dp"
android:gravity="center"
android:text=" "
android:textColor="@color/black"
android:textSize="24sp" />
</LinearLayout>
<LinearLayout
android:layout_width="350dp"
android:layout_height="50dp"
android:orientation="horizontal">
<TextView
android:layout_width="100dp"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginStart="5dp"
android:gravity="center"
android:text="실외습도"
android:textColor="@color/black"
android:textSize="24sp" />
<TextView
android:id="@+id/out_humid"
android:layout_width="95dp"
android:layout_height="40dp"
android:layout_gravity="center"
android:layout_marginStart="150dp"
android:gravity="center"
android:text=" "
android:textColor="@color/black"
android:textSize="24sp" />
</LinearLayout>
<LinearLayout
android:layout_width="350dp"
android:layout_height="50dp"
android:orientation="horizontal">
<TextView
android:layout_width="100dp"
android:layout_height="40dp"
android:layout_gravity="center"
android:layout_marginStart="5dp"
android:gravity="center"
android:text="미세먼지"
android:textColor="@color/black"
android:textSize="24sp" />
<TextView
android:id="@+id/microdust"
android:layout_width="95dp"
android:layout_height="40dp"
android:layout_gravity="center"
android:layout_marginStart="150dp"
android:gravity="center"
android:text=" "
android:textColor="@color/black"
android:textSize="24sp" />
</LinearLayout>
</LinearLayout>
<LinearLayout
android:layout_width="350dp"
android:layout_height="180dp"
android:layout_gravity="center"
android:layout_marginBottom="5dp"
android:background="@drawable/edge"
android:orientation="vertical">
<LinearLayout
android:layout_width="350dp"
android:layout_height="45dp"
android:background="@drawable/edge"
android:orientation="horizontal">
<TextView
android:layout_width="100dp"
android:layout_height="40dp"
android:layout_gravity="center"
android:layout_marginStart="5dp"
android:gravity="center"
android:text="추천온도"
android:textColor="@color/black"
android:textSize="24sp" />
<androidx.appcompat.widget.SwitchCompat
android:id="@+id/TEMP_switch"
android:layout_width="55dp"
android:layout_height="40dp"
android:layout_gravity="center"
android:layout_marginStart="180dp" />
</LinearLayout>
<LinearLayout
android:layout_width="350dp"
android:layout_height="40dp"
android:layout_marginTop="5dp"
android:orientation="horizontal">
<TextView
android:layout_width="130dp"
android:layout_height="40dp"
android:layout_gravity="center"
android:gravity="center"
android:text="사용자 설정"
android:textColor="@color/black"
android:textSize="24sp" />
<androidx.appcompat.widget.SwitchCompat
android:id="@+id/set_switch"
android:layout_width="55dp"
android:layout_height="40dp"
android:layout_gravity="center"
android:layout_marginStart="155dp" />
</LinearLayout>
<LinearLayout
android:layout_width="350dp"
android:layout_height="40dp"
android:orientation="horizontal"
android:layout_marginTop="5dp">
<TextView
android:layout_width="100dp"
android:layout_height="40dp"
android:layout_gravity="center"
android:layout_marginStart="80dp"
android:gravity="center"
android:text="현재 온도"
android:textColor="@color/black"
android:textSize="24sp" />
<TextView
android:layout_width="100dp"
android:layout_height="match_parent"
android:layout_gravity="center"
android:layout_marginStart="20dp"
android:gravity="center"
android:text="설정 온도"
android:textColor="@color/black"
android:textSize="24sp" />
</LinearLayout>
<LinearLayout
android:layout_width="350dp"
android:layout_height="40dp"
android:orientation="horizontal">
<TextView
android:layout_width="80dp"
android:layout_height="40dp"
android:layout_gravity="center"
android:gravity="center"
android:text="온도"
android:textColor="@color/black"
android:textSize="24sp" />
<TextView
android:id="@+id/living_temp"
android:layout_width="100dp"
android:layout_height="40dp"
android:layout_gravity="center"
android:gravity="center"
android:text=" "
android:textColor="@color/black"
android:textSize="24sp" />
<EditText
android:id="@+id/liv_con_temp"
android:layout_width="100dp"
android:layout_height="45dp"
android:layout_gravity="center"
android:layout_marginStart="20dp"
android:gravity="center"
android:hint="온도 입력"
android:inputType="numberDecimal"
android:maxLength="2"
android:text=""
android:textColor="@color/black"
android:textSize="20sp" />
<Button
android:id="@+id/set_but"
android:layout_width="50dp"
android:layout_height="40dp"
android:text="입력"
/>
</LinearLayout>
</LinearLayout>
<LinearLayout
android:layout_width="350dp"
android:layout_height="200dp"
android:layout_gravity="center"
android:layout_marginBottom="10dp"
android:background="@drawable/edge"
android:orientation="vertical">
<LinearLayout
android:layout_width="350dp"
android:layout_height="50dp"
android:orientation="horizontal">
<TextView
android:layout_width="100dp"
android:layout_height="40dp"
android:layout_gravity="center"
android:gravity="center"
android:text="조명"
android:textColor="@color/black"
android:textSize="24sp" />
<androidx.appcompat.widget.SwitchCompat
android:id="@+id/LED_switch"
android:layout_width="55dp"
android:layout_height="40dp"
android:layout_gravity="center"
android:layout_marginStart="185dp" />
</LinearLayout>
<LinearLayout
android:layout_width="350dp"
android:layout_height="50dp"
android:orientation="horizontal">
<TextView
android:layout_width="100dp"
android:layout_height="40dp"
android:layout_gravity="center"
android:gravity="center"
android:text="에어컨"
android:textColor="@color/black"
android:textSize="24sp" />
<androidx.appcompat.widget.SwitchCompat
android:id="@+id/AC_switch"
android:layout_width="55dp"
android:layout_height="40dp"
android:layout_gravity="center"
android:layout_marginStart="185dp" />
</LinearLayout>
<LinearLayout
android:layout_width="350dp"
android:layout_height="50dp"
android:orientation="horizontal">
<TextView
android:layout_width="100dp"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:gravity="center"
android:text="히터"
android:textColor="@color/black"
android:textSize="24sp" />
<androidx.appcompat.widget.SwitchCompat
android:id="@+id/HEATER_switch"
android:layout_width="55dp"
android:layout_height="40dp"
android:layout_gravity="center"
android:layout_marginStart="185dp" />
</LinearLayout>
<LinearLayout
android:layout_width="350dp"
android:layout_height="50dp"
android:orientation="horizontal">
<TextView
android:layout_width="120dp"
android:layout_height="40dp"
android:layout_gravity="center"
android:gravity="center"
android:layout_marginStart="5dp"
android:text="공기청정기"
android:textColor="@color/black"
android:textSize="24sp" />
<androidx.appcompat.widget.SwitchCompat
android:id="@+id/AIR_switch"
android:layout_width="55dp"
android:layout_height="40dp"
android:layout_gravity="center"
android:layout_marginStart="160dp" />
</LinearLayout>
</LinearLayout>
</LinearLayout>
[ HomeActivity.java ]
import android.annotation.SuppressLint;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.SwitchCompat;
public class HomeActivity extends AppCompatActivity implements SocketActivity.OnDataReceivedListener {
private static final String TAG = "HomeActivity";
private TextView tempTextView, rehTextView, microTextView, livingtempView;
private Handler uiHandler;
private EditText livConTemp;
private SwitchCompat ledSwitch,acSwitch, airSwitch, heaterSwitch, tempSwitch, setSwitch; // LED 스위치 추가
private SocketActivity socketActivity;
private Button setBut;
private boolean isSetSwitchOn = false; // 스위치 상태를 저장하는 변수
@SuppressLint("MissingInflatedId")
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_home);
// UI 요소 초기화
// findViewById로 레이아웃 XML의 UI 요소를 참조.
tempTextView = findViewById(R.id.out_temp); // 실외 온도
rehTextView = findViewById(R.id.out_humid); // 실외 습도
microTextView = findViewById(R.id.microdust); // 실외 미세먼지
livingtempView = findViewById(R.id.living_temp);
livConTemp = findViewById(R.id.liv_con_temp);
ledSwitch = findViewById(R.id.LED_switch); // LED 스위치 초기화
acSwitch = findViewById(R.id.AC_switch); // AC 스위치 초기화
airSwitch = findViewById(R.id.AIR_switch); // LED 스위치 초기화
heaterSwitch = findViewById(R.id.HEATER_switch); // AC 스위치 초기화
tempSwitch = findViewById(R.id.TEMP_switch); // 자동 온도 추천
setSwitch = findViewById(R.id.set_switch);
setBut = findViewById(R.id.set_but); // 설정온도입력 완료 버튼
uiHandler = new Handler(Looper.getMainLooper());
// SocketActivity 인스턴스를 가져와서 서버 연결 시작
// SocketActivity 객체를 통해 서버 연결.
socketActivity = SocketActivity.getInstance();
socketActivity.connectToServer(this); // 서버 연결 및 데이터 수신
// LED 스위치 리스너 설정
// 스위치 상태에 따라 서버에 "LED_ON" 또는 "LED_OFF" 신호 전송.
ledSwitch.setOnCheckedChangeListener((buttonView, isChecked) -> {
if (isChecked) {
sendLedSignal("LED_ON");
} else {
sendLedSignal("LED_OFF");
}
});
// 에어컨 스위치 리스너 설정
acSwitch.setOnCheckedChangeListener((buttonView, isChecked) -> {
if (isChecked) {
sendLedSignal("AC_ON");
} else {
sendLedSignal("AC_OFF");
}
});
// 공기청정기 스위치 리스너 설정
airSwitch.setOnCheckedChangeListener((buttonView, isChecked) -> {
if (isChecked) {
sendLedSignal("PFAN_ON");
} else {
sendLedSignal("PFAN_OFF");
}
});
// 히터 스위치 리스너 설정
heaterSwitch.setOnCheckedChangeListener((buttonView, isChecked) -> {
if (isChecked) {
sendLedSignal("HFAN_ON");
} else {
sendLedSignal("HFAN_OFF");
}
});
// 온도 추천 스위치 리스너 설정
tempSwitch.setOnCheckedChangeListener((buttonView, isChecked) -> {
if (isChecked) {
sendLedSignal("Recommend_ON");
} else {
sendLedSignal("Recommend_OFF");
}
});
// set_switch 스위치 리스너 설정
setSwitch.setOnCheckedChangeListener((buttonView, isChecked) -> {
isSetSwitchOn = isChecked; // 스위치 상태 저장
if (!isChecked) {
// 스위치가 왼쪽으로 갔을 때 No_Signal, HFAN_OFF, AC_OFF 전송
sendLedSignal("No_Signal");
sendLedSignal("HFAN_OFF");
sendLedSignal("AC_OFF");
}
});
// set_but 버튼 클릭 리스너 설정
setBut.setOnClickListener(v -> {
if (isSetSwitchOn) {
// 스위치가 오른쪽으로 켜져 있을 때만 compareAndSendSignal 호출
compareAndSendSignal();
}
});
}
// 서버에 LED 신호를 전송하는 메서드
private void sendLedSignal(String signal) {
if (socketActivity != null) {
socketActivity.sendData(signal);
Log.d(TAG, "Sent LED signal: " + signal); // 신호 전송 시 로그 작성
} else {
Log.e(TAG, "SocketActivity is null, cannot send signal.");
}
}
// 서버에서 데이터 수신 시 호출되는 메서드
// parseAndSetData(data)로 데이터를 분석 및 UI 업데이트, 데이터가 "BTN_ON"이면 팝업창 표시.
@Override
public void onDataReceived(String data) {
Log.d(TAG, "Received: " + data); // 수신 데이터 로그 출력
parseAndSetData(data);
if (data.equals("BTN_ON")) {
runOnUiThread(this::showAlertForBtnOn); // UI 스레드에서 팝업 실행
}
}
// 비상버튼 팝업창
private void showAlertForBtnOn() {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
// 커스텀 레이아웃 인플레이션
LayoutInflater inflater = getLayoutInflater();
View dialogView = inflater.inflate(R.layout.emergency, null);
// AlertDialog에 커스텀 레이아웃 설정
builder.setView(dialogView)
.setTitle("알림")
.setPositiveButton("확인", (dialog, which) -> dialog.dismiss())
.show();
}
// 데이터를 파싱하고 UI에 설정하는 메서드
private void parseAndSetData(String data) {
Log.d(TAG, "Parsing Data: " + data); // 전체 데이터 확인
if (data.startsWith("OUTTEMP:") && data.length() > "OUTTEMP:".length()) { // 실외 온도 데이터
String OUTTEMP = data.substring("OUTTEMP:".length()).trim();
tempTextView.setText(OUTTEMP + " °C"); // 온도 설정
} else if (data.startsWith("REH:") && data.length() > "REH:".length()) { // 실외 습도 데이터
String reh = data.substring("REH:".length()).trim();
rehTextView.setText(reh + " %"); // 습도 설정
} else if (data.startsWith("MICRO:") && data.length() > "MICRO:".length()) { // 미세먼지 데이터
String micro = data.substring("MICRO:".length()).trim();
try {
int microValue = Integer.parseInt(micro);
updateMicroStatus(microValue); // 미세먼지 상태 설정
} catch (NumberFormatException e) {
Log.e(TAG, "Invalid micro data: " + micro);
microTextView.setText("데이터 없음");
}
} else if (data.startsWith("INTEMP:") && data.length() > "INTEMP:".length()) { // 실내 온도 데이터
String INTEMP = data.substring("INTEMP:".length()).trim();
livingtempView.setText(INTEMP + " °C"); // 실내 온도 설정
}
}
// 온도 비교 후 신호 전송하는 메서드
private void compareAndSendSignal() {
try {
String livingTempText = livingtempView.getText().toString().replace(" °C", "").trim();
String targetTempText = livConTemp.getText().toString().trim();
if (!livingTempText.isEmpty() && !targetTempText.isEmpty()) {
float livingTemp = Float.parseFloat(livingTempText);
float targetTemp = Float.parseFloat(targetTempText);
if (livingTemp > targetTemp) {
sendLedSignal("AC_ON");
sendLedSignal("HFAN_OFF");
sendLedSignal("usersettemp, " + targetTemp);
} else if (livingTemp < targetTemp) {
sendLedSignal("HFAN_ON");
sendLedSignal("AC_OFF");
sendLedSignal("usersettemp, " + targetTemp);
} else {
sendLedSignal("No_Signal");
}
}
} catch (NumberFormatException e) {
Log.e(TAG, "Invalid temperature input", e);
}
}
// 미세먼지 상태를 업데이트하는 메서드
private void updateMicroStatus(int microValue) {
String status;
if (microValue <= 30) {
status = "좋음"; // 미세먼지 상태가 좋음
} else if (microValue <= 80) {
status = "보통"; // 미세먼지 상태가 보통
} else if (microValue <= 150) {
status = "나쁨"; // 미세먼지 상태가 나쁨
} else {
status = "매우 나쁨"; // 미세먼지 상태가 매우 나쁨
}
microTextView.setText(status); // 텍스트 뷰에 설정
}
@Override
protected void onDestroy() {
super.onDestroy();
// 액티비티 종료 시 서버 연결 해제
if (socketActivity != null) {
socketActivity.disconnect();
}
}
}
'프로그래밍 코드 > Android Studio' 카테고리의 다른 글
#7. AI Smart Home_ModeActivity (0) | 2024.12.17 |
---|---|
#6. Al Smart Home_TipActivity (1) | 2024.12.17 |
#4. AI Smart Home_SocketActivity (3) | 2024.12.17 |
AI 심리 분석 프로그램 도담이 (1) | 2024.07.22 |
#3. AI Smart Home_MainActivity (0) | 2024.03.13 |