동생 녀석 이 장치 달 때부터 표정이 매우 매우 매우 매우 좋지 않았는데 가족 블로그에 아래의 글을 작성해서 올렸다.
ㅋㅋㅋ 성공인가 싶다 ㅋㅋㅋ
아버지 하우스 개폐기를 만들면서 업로드 하려고 포트를 너무 많이 꼽았다 빼면서 Esp32포트가 망가져 부러졌다....
그때, 임시방편으로 Vcc GND에 케이블을 잘라 +/-를 납땜하여 놓고 왔었는데 오프라인용 비상 스위치를 만들면서 바꾸려고 일단 그대로 사용중이다.
그래서!
이번에는 수정할 때에 OTA를 이용하여 업로드 하기로 했다 ( * 원래 코드가 길어지는게 싫어 하지 않았다.)
원래 계획은
1. 5v sb 가져다가 Esp32에 공급하고
- 트랜지스터로 스위치랑 병렬로 연결하여 만들고 컴퓨터를 끄기도하고 켜기도 하도록 만들고
- 켜지면 3v3에 전원이 공급될 테니 그 전기로 켜졌는지 꺼졌는지 판단하려 했다
----> 메인보드에 들어가는 전기를 건들기는 불안하니까 포기
----> 컴퓨터가 오류가 나서 안켜져서 트렌지스터 잘라 넴..
----> 그러면 컴퓨터가 꺼졌는지 아닌지 알기 위해 전기를 USB로 부터 가져와
컴퓨터가 켜지면 전기를 공급받고 메세지를 보내도록함.
>>>>>>>>>>>>> 결국 선은 USB-A로 부터 공급받는 전기선만 남음....
이거 하기 전에 OTA 업로드를 위한 코드를 업로드 해야한다.
아두이노 코드
이 예제를 바탕으로 Mqtt를 추가하고 코드를 작성!
#전체 코드
#include <WiFi.h>
#include <WiFiClient.h>
#include <WebServer.h>
#include <ESPmDNS.h>
#include <Update.h>
#include <PubSubClient.h>
const char* host = "esp32";
const char *ssid = "olleh_WiFi_BA83";
const char *password = "0000002583";
const char* ID = "Child_Pc_Control"; // Name of our device, must be unique
const char* TOPIC = "room/pc/state";
const char* mqttUser = "XXXXXXXX";
const char* mqttPassword = "XXXXXXXXXX";
const char* broker = "172.30.1.48";
WebServer server(80);
WiFiClient wclient;
PubSubClient client(wclient);
char messages[50];
/*
* Login page
*/
const char* loginIndex =
"<form name='loginForm'>"
"<table width='20%' bgcolor='A09F9F' align='center'>"
"<tr>"
"<td colspan=2>"
"<center><font size=4><b>ESP32 Login Page</b></font></center>"
"<br>"
"</td>"
"<br>"
"<br>"
"</tr>"
"<tr>"
"<td>Username:</td>"
"<td><input type='text' size=25 name='userid'><br></td>"
"</tr>"
"<br>"
"<br>"
"<tr>"
"<td>Password:</td>"
"<td><input type='Password' size=25 name='pwd'><br></td>"
"<br>"
"<br>"
"</tr>"
"<tr>"
"<td><input type='submit' onclick='check(this.form)' value='Login'></td>"
"</tr>"
"</table>"
"</form>"
"<script>"
"function check(form)"
"{"
"if(form.userid.value=='admin' && form.pwd.value=='admin')"
"{"
"window.open('/serverIndex')"
"}"
"else"
"{"
" alert('Error Password or Username')/*displays error message*/"
"}"
"}"
"</script>";
/*
* Server Index Page
*/
const char* serverIndex =
"<script src='https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js'></script>"
"<form method='POST' action='#' enctype='multipart/form-data' id='upload_form'>"
"<input type='file' name='update'>"
"<input type='submit' value='Update'>"
"</form>"
"<div id='prg'>progress: 0%</div>"
"<script>"
"$('form').submit(function(e){"
"e.preventDefault();"
"var form = $('#upload_form')[0];"
"var data = new FormData(form);"
" $.ajax({"
"url: '/update',"
"type: 'POST',"
"data: data,"
"contentType: false,"
"processData:false,"
"xhr: function() {"
"var xhr = new window.XMLHttpRequest();"
"xhr.upload.addEventListener('progress', function(evt) {"
"if (evt.lengthComputable) {"
"var per = evt.loaded / evt.total;"
"$('#prg').html('progress: ' + Math.round(per*100) + '%');"
"}"
"}, false);"
"return xhr;"
"},"
"success:function(d, s) {"
"console.log('success!')"
"},"
"error: function (a, b, c) {"
"}"
"});"
"});"
"</script>";
/*
* setup function
*/
void reconnect() {
// Loop until we're reconnected
while (!client.connected()) {
Serial.print("Attempting MQTT connection...");
// Attempt to connect
if (client.connect(ID, mqttUser, mqttPassword)) {
Serial.println("connected");
Serial.print("Publishing to: ");
Serial.println(TOPIC);
Serial.println('\n');
} else {
Serial.print("failed, rc=");
Serial.print(client.state());
Serial.println("\n try again in 5 seconds");
// Wait 5 seconds before retrying
delay(5000);
}
}
}
void setup(void) {
Serial.begin(115200);
// Connect to WiFi network
WiFi.begin(ssid, password);
Serial.println("");
// Wait for connection
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.print("Connected to ");
Serial.println(ssid);
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
/*use mdns for host name resolution*/
if (!MDNS.begin(host)) { //http://esp32.local
Serial.println("Error setting up MDNS responder!");
while (1) {
delay(1000);
}
}
Serial.println("mDNS responder started");
/*return index page which is stored in serverIndex */
server.on("/", HTTP_GET, []() {
server.sendHeader("Connection", "close");
server.send(200, "text/html", loginIndex);
});
server.on("/serverIndex", HTTP_GET, []() {
server.sendHeader("Connection", "close");
server.send(200, "text/html", serverIndex);
});
/*handling uploading firmware file */
server.on("/update", HTTP_POST, []() {
server.sendHeader("Connection", "close");
server.send(200, "text/plain", (Update.hasError()) ? "FAIL" : "OK");
ESP.restart();
}, []() {
HTTPUpload& upload = server.upload();
if (upload.status == UPLOAD_FILE_START) {
Serial.printf("Update: %s\n", upload.filename.c_str());
if (!Update.begin(UPDATE_SIZE_UNKNOWN)) { //start with max available size
Update.printError(Serial);
}
} else if (upload.status == UPLOAD_FILE_WRITE) {
/* flashing firmware to ESP*/
if (Update.write(upload.buf, upload.currentSize) != upload.currentSize) {
Update.printError(Serial);
}
} else if (upload.status == UPLOAD_FILE_END) {
if (Update.end(true)) { //true to set the size to the current progress
Serial.printf("Update Success: %u\nRebooting...\n", upload.totalSize);
} else {
Update.printError(Serial);
}
}
});
server.begin();
client.setServer(broker, 1883);
pinMode(4, OUTPUT);
pinMode(18, INPUT);
}
void loop(void) {
if (WiFi.status() != WL_CONNECTED) {
ESP.restart();
}
server.handleClient();
delay(1);
if (!client.connected()){
reconnect();
}
client.loop();
snprintf(messages, 75, "%s", "online");
client.publish(TOPIC, messages);
delay(1000);
}
# 부분 코드(OTAWebUpdater 코드는 잘모르니 제외)
const char *ssid = "olleh_WiFi_BA83"; //와이파이 SSID
const char *password = "0000002583"; // 와이파이 비밀번호
const char* ID = "Child_Pc_Control"; // Mqtt 브로커에 전달하는 이름으로 유닉해야함.
const char* TOPIC = "room/pc/state"; // Mqtt에 전달할 토픽
const char* mqttUser = "XXXXXXXX"; // Mqtt 브로커 로그인을 위한 유저
const char* mqttPassword = "XXXXXXXXXX"; // Mqtt 브로커 로그인 패스워드
const char* broker = "172.30.1.48"; // Mqtt 서버 주소
char messages[50]; // 버퍼가 담길 변수
// Mqtt 재 연결
void reconnect() {
// Loop until we're reconnected
while (!client.connected()) {
Serial.print("Attempting MQTT connection...");
// Attempt to connect
if (client.connect(ID, mqttUser, mqttPassword)) {
Serial.println("connected");
Serial.print("Publishing to: ");
Serial.println(TOPIC);
Serial.println('\n');
} else {
Serial.print("failed, rc=");
Serial.print(client.state());
Serial.println("\n try again in 5 seconds");
// Wait 5 seconds before retrying
delay(5000);
}
}
}
void setup(void) {
client.setServer(broker, 1883); //Mqtt 접속 코드 void seup(void) 함수에 추가
}
void loop(void) {
if (WiFi.status() != WL_CONNECTED) { // 와이파이 연결 안되면 Esp 보드 새로 시작(실 사용중 이런 와이파이 연결 안되서 센서 값이 안들어 오는 경우가 있어서 추가함)
ESP.restart();
}
if (!client.connected()){ //Mqtt 재연결
reconnect();
}
client.loop();
snprintf(messages, 75, "%s", "online"); // 컴이 켜지면 켜짐의 메세지(online)를 버퍼로 바꾸는 코드
client.publish(TOPIC, messages); //Mqtt에 메시지 전달
delay(1000);
}
홈어시스턴트(Home Assistant) 코드
File Editor - configuration.yaml에 코드 추가
switch:
- platform: wake_on_lan # hassio wol 스위치
mac: "D8:BB:C1:15:62:A6" # pc mac 주소
name: PcWol
host: 172.30.1.41 # pc 주소
sensor:
- platform: mqtt
name: "컴 상태" # 센서 이름
state_topic: "room/pc/state" # 토픽
expire_after: 10 # 10 초 내에 센서 값이 안 오면 Unavailable 전시
저장후 서버 재시작한 뒤
전 글에서 처럼 엔티티 아이콘을 변경(나는 mdi:microsoft-windows)
File Editor - ui-lovelace.yaml에 코드 추가
- type: horizontal-stack
cards:
- type: 'custom:button-card'
entity: sensor.keom_sangtae
show_entity_picture: true
aspect_ratio: '1/1'
size: 80%
name: "Pc Status"
state:
- value: 'online'
icon: 'mdi:microsoft-windows'
styles:
card:
- background: rgba(255, 255, 255, 0.3)
icon:
- color: rgba(0, 173, 239, 0.8)
show_state: true
tap_action: #클릭시 wol을 통한 pc 시작
action: 'call-service'
service: switch.turn_on
service_data:
entity_id: switch.pcwol
hold_action: # 꾹 누르면 히스토리 나오도록
action: 'more-info'
styles:
card:
- background: rgba(0, 0, 0, 0.5)
border-radius: 10%
padding: 10%
text-align: center
grid:
- grid-template-areas: '"i" "n" "s"'
- grid-template-columns: 1fr
- grid-template-rows: 1fr min-content min-content
img_cell:
- align-self: start
- text-align: start
name:
- justify-self: start
- color: white
- font-weight: bold
- text-shadow: 0px 0px 5px black
state:
- justify-self: start
- padding-left: 0px
kt 공유기 Wake On Lan 설정은 구글링 ㄱ 다른 분들이 잘 해두심 ㅋ
윈도우, 공유기, 메인보드 모두 wol 설정함
끄는건 안됨...
대신 크롬에서 원격 데스크톱 설정해서 크롬으로 되도록함.
홈어시스턴트로 킨다음
이걸루 끌수 있음 ㅋ
크롬 원격 데스크톱 영상도 은근히 잘 돌아가더라 ㅋ
이제 이후에 코드를 수정할 일이 있으면 OTA로 하면 되는데 나의 경우 KT공유기를 이용함으로 그걸 바탕으로 하겠다.
공유기에 접속!(http://172.30.1.254) - 로그인(ktuser/homehub/보안코드) - 유무선 단말 정보에서 경과시간을 바탕으로 Esp32의 아이피를 찾는다. 컴을 처음에 킨 다음 새로고침하면 몇초만 경과한 녀석의 MAC주소를 바탕으로 찾으면 된다. 나의 경우 172.30.1.26 이다.
해당아이피를 인터넷 브라우저에 넣고 엔터를 치면! 아래와 같은 화면이 나오는데 설정을 바꾸지 않았다면 기본적으로 admin/admin이다.
로그인을 하면 아래와 같은 화면이 나오는데 여기서
파일선택에서 아까 아두이노 스케치 폴더에 만들어진 bin 파일을 선택한 뒤 업데이트한 뒤 Progress가 100%가 되면 반영이 된거다 ㅋㅋ
'스마트 홈 > 홈어시스턴트(Home Assistant)' 카테고리의 다른 글
아빠 비닐하우스 개폐기 더이상 손 안 댈 정도로 끝 - 블라인드로 같은 방식으로 하면된다. (1) | 2022.02.24 |
---|---|
홈어시스턴트(Home Assistant) 코로나 확진자수 스크랩(크롤링)(2) (0) | 2022.02.03 |
홈어시스턴트(Home Assistant) button-card (0) | 2021.07.08 |
홈어시스턴트 lovelace 커스텀 카드 추가하기 (0) | 2021.07.06 |
홈어시스턴트(Home Assistant) 아이콘 추가하기 (0) | 2021.07.06 |