[IoT ๐ /Homebridge] - [JS] Homebridge ๋ฐ์คํฌํ ์๊ฒฉ ์ ์ ํ๋ฌ๊ทธ์ธ ์ ์
๊ณ์ Homebridge ํ๋ฌ๊ทธ์ธ ๊ฐ๋ฐ์ ํ๋ฉด์, ์ด์ ์ ๋ชฐ๋๋ ์ง์๋ค๋ ์๊ฒ ๋์๊ณ
๊ธฐ์กด ํ๋ฌ๊ทธ์ธ์์ ๊ฐ์ ํ ๋ถ๋ถ์ด ๋ณด์ด๊ธฐ ์์ํด์,
๊ทธ๋์ ์ ์ ํ๋ ํ๋ฌ๊ทธ์ธ๋ค์ ํ๋ํ๋ ๊ฐ์ ํด๋ณด๋ ค๊ณ ํ๋ค.
์ด์ ์ ๋ฐ์คํฌํ ์๊ฒฉ ์ ์ ๊ธฐ๋ฅ์ ๊ตฌํํ๊ณ ,
๋จ์ถ์ด๋ก ์ฌ์ฉํ๋ ๊ฒ์ Homebridge Plugin์ผ๋ก ๋ง๋ค์ด
๋ด ์ค๋งํธํ ์ํ๊ณ์ ์์ ํ ์ ์ฉ ์์ผฐ์๋ค.
๋จผ์ ํด๋น ํ๋ฌ๊ทธ์ธ์ ์ ์ธ์๋ฆฌ ๋น์ฃผ์ผ ์ ๋ฐ์ดํธ์,
์ ์ธ์๋ฆฌ์ PC ์ํ๋ฅผ ๋๊ธฐํ ํ ์ ์๊ฒ ์์ ํด๋ณด๋๋ก ํ๊ฒ ๋ค.
ํ๋ฌ๊ทธ์ธ ์์
๊ธฐ์กด์๋, ๋ชจ๋ํฐ ๋ชจ์์ TV ํ์ผ์ด ์ธ๋ถ ์ ์ธ์๋ฆฌ๋ก๋ง ๋ฑ๋ก์ด ๊ฐ๋ฅํ์ง ๋ชฐ๋์๋ค.
์ ๋ฒ์ Smartthings ์ฐ๋ ํ๋ฌ๊ทธ์ธ์ ์ง์ ๋ง๋ค์ด ๋ณด๋ฉด์ ์ฑ๊ณต์ ์ผ๋ก ๊ตฌํํ์ผ๋
์ด๋ฒ์๋ ์ ์ฉํด๋ณด๋๋ก ํ๊ฒ ๋ค.
๋จผ์ , ๊ธฐ์กด Switch ์ ์ธ์๋ฆฌ์์ TV ์ ์ธ์๋ฆฌ๋ก ๋ณ๊ฒฝํ๋ค.
์ด๋ฒ์๋ ์ ์ธ์๋ฆฌ์ ์ ์ ๊ธฐ๋ฅ๋ง ์์ผ๋ฉด ๋๋ฏ๋ก, ๊ฐ๋จํ๊ฒ ๊ธฐ๋ณธ ์ค์ ์ ํ๊ณ
publishExternalAccessories๋ก ์ธ๋ถ ์ ์ธ์๋ฆฌ๋ก ์ง์ ํด์ฃผ์๋ค.
publishTVAccessory() {
const uuid = UUID.generate(this.config.domain);
const acc = new this.api.platformAccessory(this.config.name, uuid);
acc.category = Categories.TELEVISION;
this.tvService = acc.addService(Service.Television, this.config.name);
this.tvService.setCharacteristic(Characteristic.ConfiguredName, this.config.name);
this.tvService.setCharacteristic(Characteristic.SleepDiscoveryMode, Characteristic.SleepDiscoveryMode.ALWAYS_DISCOVERABLE);
this.tvService.getCharacteristic(Characteristic.Active)
.onGet(() => this.isOnline ? Characteristic.Active.ACTIVE : Characteristic.Active.INACTIVE)
.onSet(async (value) => {
if (value === Characteristic.Active.ACTIVE) {
await this._powerOn();
this.isOnline = true;
} else {
await this._powerOff();
this.isOnline = false;
}
});
this.api.publishExternalAccessories('homebridge-wol-ssh', [acc]);
}
๊ทธ๋ฆฌ๊ณ PC์ ์ํ๋ฅผ ํ์ธํ๊ธฐ ์ํด, Port Check ๋ฐฉ์์ ์ด์ฉํ ๊ฒ์ด๋ค.
์ฒ์์ Ping์ ์ฃผ๊ธฐ์ ์ผ๋ก ์ฃผ๋ ๋ฐฉ์์ ๊ณ ๋ คํ์๋๋ฐ,
์๋ฌด๋๋ ์ข ๋ฃ ๋ช ๋ น์ด๋ฅผ SSH๋ก ์ฌ์ฉํ๊ณ ์์ผ๋ฏ๋ก
SSH ํฌํธ๊ฐ ์๋ตํ๋์ง ์ฌ๋ถ๋ฅผ ์ฒดํฌ ํ๋ ๋ฐฉ์์ด ๋ ํจ์จ์ ์ธ ๊ฒ ๊ฐ์์ ์ฑํํ๋ค.
PC๋ฅผ ์ํ๋ฅผ ์ฒดํฌํ๋ ํจ์ ๋ถ๋ถ์ด๋ค.
ํฌํธ๊ฐ ์ด๋ ค์์ผ๋ฉด connect ์ด๋ฒคํธ ๋ฐ์, ์ ์ธ์๋ฆฌ๋ฅผ ์จ๋ผ์ธ์ผ๋ก ๋๊ณ
ํ์์์์ด๋ ์๋ฌ ๋ฐ์์์๋ ์คํ๋ผ์ธ์ผ๋ก ๋๊ฒ ํ๋ค.
์์ผ ์ฐ๊ฒฐ์, on ๋ฉ์๋ ๋์ once ๋ฉ์๋๋ฅผ ์ด์ฉํด ๋ฉ๋ชจ๋ฆฌ ๋์๋ฅผ ๋ฐฉ์งํ๋ค.
checkPCStatus() {
const urlData = new URL(this.config.domain);
const hostname = urlData.hostname;
const port = this.config.sshPort || 22;
const socket = new net.Socket();
socket.setTimeout(2000);
socket.once('connect', () => {
this._updateState(true);
socket.destroy();
});
socket.once('timeout', () => {
this._updateState(false);
socket.destroy();
});
socket.once('error', () => {
this._updateState(false);
socket.destroy();
});
socket.connect(port, hostname);
}
์ค์ ์ ์ธ์๋ฆฌ ์ํ๋ฅผ ์ ์ด ํด์ฃผ๋ ๋ถ๋ถ์ด๋ค.
PC๊ฐ ์ด์ ์ํ์ ๋ค๋ฅผ ๊ฒฝ์ฐ์๋ง ์คํํ๊ฒ ํด๋์๋ค.
_updateState(newState) {
if (this.isOnline !== newState) {
this.isOnline = newState;
if (this.tvService) {
this.tvService.updateCharacteristic(
Characteristic.Active,
this.isOnline ? Characteristic.Active.ACTIVE : Characteristic.Active.INACTIVE
);
}
}
}
๋ง์ง๋ง์ผ๋ก 10์ด ์ฃผ๊ธฐ๋ก Polling ์ฒ๋ฆฌ๋ฅผ ํด์
์ํ ๊ฐ์ง๋ฅผ ์ฃผ๊ธฐ์ ์ผ๋ก ํ ์ ์๊ฒ ํด์ฃผ์๋ค.
api.on('didFinishLaunching', () => {
this.publishTVAccessory();
setInterval(() => this.checkPCStatus(), 10000);
});
์ฝ๋์์ ์ ์๋ฃํ์ผ๋ ํ๋ฌ๊ทธ์ธ์ ์ ๋ฐ์ดํธ ํด๋ณด์
ํ ์คํธ
์์ฑ๋ ํ๋ฌ๊ทธ์ธ์ ์ ์ฉํ๊ณ ๋ฑ๋กํด๋ณด๋
๋ชจ๋ํฐ ๋ชจ์์ TV ์ ์ธ์๋ฆฌ๋ก ์ ๋ฑ๋ก๋์๋ค.
์ ์๋, Toggle๋ฐฉ์์ผ๋ก ์๋์ผ๋ก ์ ์ธ์๋ฆฌ๊ฐ Off ๋๊ฒ ํ์๋ค๋ฉด
์ด์ ๋ ์ํ ๋๊ธฐํ๊ฐ ๋์ On ์ํ๋ก ์ ์ ์ง ๋๋ ๊ฒ์ ๋ณผ ์ ์๋ค.
(๋๋์ด ์ปดํจํฐ ์ ์ ์ํ๋ฅผ ๊ธฐ์ค์ผ๋ก ์กฐ๊ฑด์ ๊ฑธ ์ ์๊ฒ ๋๋ค!)

์๋์ผ๋ก ์ข ๋ฃ์์๋, ์๋์ผ๋ก ์ ์ธ์๋ฆฌ๊ฐ ๋๊ธฐํ ๋๋ ๋ชจ์ต
์ด๋ ๊ฒ, ๊ธฐ์กด ์ ์ํ๋ ํ๋ฌ๊ทธ์ธ์ ๊ฐ์ ํ๊ณ ์ ๊ทธ๋ ์ด๋ ํ๋ ์์ ์ ํด๋ณด์๋ค.
์ด์ ์ผ ์์ฑ๋ ํ๋ฌ๊ทธ์ธ์ด ๋ ๊ฒ ๊ฐ์์ ๋ฟ๋ฏํ๋ค.
์์ผ๋ก๋, ๋ถํธํ ์ ์ด ๋ณด์ด๋ฉด ๋ฐ๋ก๋ฐ๋ก ๊ณ ์ณ์ ์จ๋ด์ผ๊ฒ ๋ค.
์๋ณธ ๊ฒ์๊ธ
[JS] Homebridge ๋ฐ์คํฌํ ์๊ฒฉ ์ ์ ํ๋ฌ๊ทธ์ธ ๊ฐ์
๊ณ์ Homebridge ํ๋ฌ๊ทธ์ธ ๊ฐ๋ฐ์ ํ๋ฉด์, ์ด์ ์ ๋ชฐ๋๋ ์ง์๋ค๋ ์๊ฒ ๋์๊ณ ๊ธฐ์กด ํ๋ฌ๊ทธ์ธ์์ ๊ฐ์ ํ ...
blog.naver.com