高さ調節可胜なデスクをIoTデスクに倉えた方法

この蚘事では、手動の高さのデスクを自動化されたIoTデスクに倉えた方法を玹介したす。モヌタヌのサむズ蚭定ず実行方法、およびHerokuをパブリックむンタヌフェむスずしお䜿甚しおIoTデバむスをGoogleに接続する方法に぀いお説明したす。



぀たり、このプロゞェクトには2぀の機胜がありたす。 1぀目テヌブルは音声コマンドを䜿甚しおGoogle Smart HomeからHerokuに接続され、2぀目H​​erokuずテヌブル自䜓はMQTT Internet ofThingsプロトコルを䜿甚しお通信したす。 MQTTは、Internet of Thingsにずっお、たた私たちが盎面しなければならない他のいく぀かの障害を克服するための優れた゜リュヌションです。



たず第䞀に、私はただ楜しみのためにこのプロゞェクトをしたず蚀いたす。この蚘事がおもしろくお、時間をかけお自分のこずをやる気にさせおくれるこずを願っおいたす。



同じテヌブル




ハヌドりェア郚分



仕事の最初の、そしおおそらく最も難しい郚分は、テヌブルの再蚭蚈です。過去の人生では、テヌブルには取り倖し可胜なハンドルがあり、テヌブルトップの端にありたした。最初は、テヌブルのデザむンを邪魔するこずなく、ハンドルの穎に䜕かを取り付けるこずを考えたした。モヌタヌをテヌブルに取り付ける方法を理解するためにいく぀かのドラむブを賌入したしたが、圹に立ちたせんでした。それからアむデアが浮かびたした。テヌブル党䜓の長さに沿っお走るロッドで、脚を接続しお同時に䞊䞋するようにしたす。ロッドに合うドラむブを取り付けるず、ベルトを䜿っおロッドをモヌタヌに接続できたす。蚭蚈にあたり干枉するこずなく、テヌブルにモヌタヌを装備するこずも可胜です。



トルクの重芁性



適切なドラむブずベルトを泚文した埌、私はアマゟンで高トルクモヌタヌを探し始めたした。そしお-ああ、奇跡 -私は倚くの適切な゚ンゞンを芋぀けたしたずいうか 小さなモヌタヌを買っお、䞭囜からの到着を玄1ヶ月埅ちたした。モヌタヌが぀いに到着したずき、私はずおも興奮したした週末がようやくすべおをたずめお、電動デスクを手に入れるのが埅ちきれたせんでした。



物事は蚈画通りに進たなかった。私はテヌブルの金属パネルにロッド甚の穎を開けるのに䞀日を費やしたした。圓時はハンドツヌルしか持っおいなかったので、思ったより時間がかかりたした。䞀日の終わりに、私はテヌブルの組み立おを終え、それを詊す準備ができたした。



モヌタヌをオンにし、デスクトップ電源の電圧をオンにしたしたが...䜕も起こりたせんでした。数分埌、モヌタヌが回転し始め、取埗したベルトの歯がガタガタ鳎りたした。これから2぀の教蚓を孊びたした。ベルトが明らかに機胜しおいないこずず、「高トルクのモヌタヌ」ずいう蚀葉は「䜕でも持ち䞊げるこずができる」ずいう意味ではありたせん。2番目のレッスンは、モヌタヌが指ず比べおどれだけ倧きいかを確認するこずです。私のは小さいこずが刀明したした







写真の巊偎はモヌタヌずベルトです。右䞊はテヌブルに取り付けられたモヌタヌですこれに぀いおは埌で詳しく説明したす。右䞋では、モヌタヌはテヌブルの所定の䜍眮にありたす。



適切なモヌタヌ



適切なモヌタヌを遞択するには、卓䞊を持ち䞊げるのに必芁なトルクを蚈算する必芁がありたした。これがいかに簡単かずいうこずに驚きたした。







T=F∗r







トルクは、力にレバヌアヌムの長さを掛けたものです。



さお、私はレバヌアヌムこれはテヌブルハンドルですを持っおいたした、レバヌアヌムを簡単に回す力を蚈算するこずだけが必芁でした。ミルクゞャグをハンドルに結び付けおテヌブルにロヌドし、レバヌが回転し始めるたでゞャグに埐々に氎を远加したした。氎差しがいっぱいになった状態でハンドルを䞊に回すこずで、おもりがハンドルを回しやすいようにしたした。レバヌアヌムの長さは11cmで、必芁な力は4ポンドであるこずがわかりたした。これらの数倀を匏に代入するず、モヌタヌは少なくずも19.95 kg / cmのトルクを生成する必芁があるこずがわかりたした。そしお私は圌を探し始めたした。



私はテヌブルを䞍可逆的に䜜り盎すこずにしたした。テヌブルの真ん䞭を通るロッドが䞭空であるこずを私は知っおいたした。ツむンシャフトモヌタヌを探した埌、ロッドをカットしお、モヌタヌを真ん䞭に眮いお組み立お盎すこずができたした。 20 kg / cmのトルクで2぀のモヌタヌを賌入するこずで、テヌブルを持ち䞊げるのに十分なトルクがあるこずを確認したした。



別の矎しい土曜日に、私はテヌブルを4぀に分解し、ロッドを組み立おるずきに䜿甚できるようにモヌタヌシャフトを切断したした。モヌタヌに合うように金属にさらに穎を開けたした。今回はベルトがありたせんでした。モヌタヌはロッドに盎接接続されおいお、穎はかなり倧きかったです。倕方になるず、机を組み立お盎しお事務甚品を積み蟌みたした。





䞊の2぀の写真は、テヌブルに完党に取り付けられたモヌタヌです。䞋の2぀の写真は、モヌタヌの助けを借りおテヌブルの長さに沿っお走る䞀䜓型のロッドです。



モヌタヌを接続しお電源に接続したした。電源を入れるず、テヌブルが動くのが芋えたした今回はモヌタヌのサむズを正しく蚭定したので、自信が぀きたした。確かに゚ンゞンのパワヌを2倍にしたしたが、゚ンゞンが動くのを芋るのは玠晎らしかったです



ただし、テヌブルが遅いこずを明確にしおおきたす。私は友人にテヌブルの仕組みを瀺すためにビデオを撮圱したしたが、テヌブルがテヌブルの䞊の䜍眮を倉えるので5分間芋ないように、圌はビデオの時間加速をオンにする必芁がありたした。



売䞊高は重芁です。最終版



぀いに私はそれがすべおトルクず回転の2぀に垰着するこずに気づきたした。既知のトルクで十分な回転数のモヌタヌを芋぀ける必芁がありたした。



それほど難しくはありたせんでした。ツむンシャフトモヌタヌは芋぀かりたせんでしたが、シングルシャフトモヌタヌをツむンシャフトモヌタヌに倉える長方圢のギアボックスを芋぀けたした 。



芁するに、翌月は䞭囜からのギアボックスを埅぀月であり、埅った埌の次の土曜日は、適切な速床でテヌブルを動かしおいたした。





最埌のモヌタヌ自䜓が巊偎にあり、取り付けられおいるモヌタヌが右偎にありたす。小さなハヌドりェアずたくさんの゜フトりェア。



卓䞊の高さを制埡するためだけに暪たわっおいる、机の䞊の巚倧な電源に満足しおいたせんでした。たた、テヌブルの䜍眮を前埌に倉えるために、ワむダヌを亀換したした。小さな問題ですが、プロゞェクトは理想的にはボタンを抌すだけで、耇数の高さのプリセットを持぀ように行われたした。



ブルヌトゥヌス



最初の解決策は、Bluetoothをテヌブルに远加するこずでした。結局のずころ、家の䞭のほがすべおのデバむスにNluetoothが搭茉されおいるように芋え、電話は私の机のようなものにずっお䟿利な制埡むンタヌフェヌスのようです。



だから今、私はモヌタヌコントロヌラヌボヌド、北欧のNRF52ブルヌトゥヌスボヌド、距離センサヌを手に入れ、コントロヌラヌのファヌムりェアをいじり始めたした。



蚘事の終わりに、私がプロゞェクトのために曞いた゜フトりェアずファヌムりェアぞのリンクを残したす。コヌドに぀いおお気軜にコメントしおください。私はプロのファヌムりェア開発者ではないので、ガむダンスを受け取りたいず思いたす。



簡単な玹介ずしおESP32は、Arduinoラむブラリを䜿甚しおC ++で蚘述され、電話のBLEタヌミナルアプリず察話したす。 BLEのむンストヌルず構成は非垞に耇雑です。たず、BLEを介しお制埡したい倀のすべおの特性を䜜成する必芁がありたす。特性をコヌド内の倉数ず考えおください。 BLEは、倉数を耇数のハンドラヌでラップしお、その倉数の倀を取埗および蚭定したす。



次に、特性は独自のUUIDを持぀サヌビスにパッケヌゞ化されたす。これにより、サヌビスが䞀意になり、アプリケヌションから識別できるようになりたす。最埌に、このサヌビスを広告ペむロヌドに远加しお、デバむスがサヌビスを怜出できるようにする必芁がありたす。リモヌトデバむスがサヌビスに接続し、仕様を介しおデヌタを送信するず、テヌブルは、ナヌザヌが高さを別のプリセットに調敎するこずを望んでいるこずを認識し、移動を開始したす。



高さ調敎のために、ワヌクトップには珟圚の高さを怜出するTFMini-SLiDARセンサヌがありたす。これは楜しいセンサヌです。実際にはレヌザヌである堎合、LiDARず呌ばれたす。光孊系ずLEDを䜿甚しお、赀倖線の飛行時間を決定したす。䜕らかの方法で、センサヌはテヌブルの高さを決定したす。次に、制埡盀は珟圚の高床ず芁求された高床の差を怜出し、モヌタヌを始動したす。モヌタヌは目的の方向に回転したす。コヌドの䞻芁郚分の䞀郚を以䞋に瀺したすが、ファむル党䜓をここで確認でき たす。



void setup()
{
   Serial.begin(115200);
   Serial2.begin(TFMINIS_BAUDRATE);
   EEPROM.begin(3); // used for saving the height presets between reboots

   tfminis.begin(&Serial2);
   tfminis.setFrameRate(0);

   ledcSetup(UP_PWM_CHANNEL, PWM_FREQUENCY, PWM_RESOLUTION);
   ledcAttachPin(UP_PWM_PIN, UP_PWM_CHANNEL);

   ledcSetup(DOWN_PWM_CHANNEL, PWM_FREQUENCY, PWM_RESOLUTION);
   ledcAttachPin(DOWN_PWM_PIN, DOWN_PWM_CHANNEL);

   state_machine = new StateMachine();
   state_machine->begin(*t_desk_height, UP_PWM_CHANNEL, DOWN_PWM_CHANNEL);

   BLEDevice::init("ESP32_Desk");
  ...

   BLEServer *p_server = BLEDevice::createServer();
   BLEService *p_service = p_server->createService(BLEUUID(SERVICE_UUID), 20);

   /* ------------------- SET HEIGHT TO PRESET CHARACTERISTIC -------------------------------------- */
   BLECharacteristic *p_set_height_to_preset_characteristic = p_service->createCharacteristic(...);
   p_set_height_to_preset_characteristic->setCallbacks(new SetHeightToPresetCallbacks());
   /* ------------------- MOVE DESK UP CHARACTERISTIC ---------------------------------------------- */
   BLECharacteristic *p_move_desk_up_characteristic = p_service->createCharacteristic(...);
   p_move_desk_up_characteristic->setCallbacks(new MoveDeskUpCallbacks());
   /* ------------------- MOVE DESK UP CHARACTERISTIC ---------------------------------------------- */
   BLECharacteristic *p_move_desk_down_characteristic = p_service->createCharacteristic(...);
   p_move_desk_down_characteristic->setCallbacks(new MoveDeskDownCallbacks());
   /* ------------------- GET/SET HEIGHT 1 CHARACTERISTIC ------------------------------------------ */
   BLECharacteristic *p_get_height_1_characteristic = p_service->createCharacteristic(...);
   p_get_height_1_characteristic->setValue(state_machine->getHeightPreset1(), 1);
   BLECharacteristic *p_save_current_height_as_height_1_characteristic = p_service->createCharacteristic(...);
   p_save_current_height_as_height_1_characteristic->setCallbacks(new SaveCurrentHeightAsHeight1Callbacks());
   /* ------------------- GET/SET HEIGHT 2 CHARACTERISTIC ------------------------------------------ */
  ...
   /* ------------------- GET/SET HEIGHT 3 CHARACTERISTIC ------------------------------------------ */
  ...
   /* ------------------- END CHARACTERISTIC DEFINITIONS ------------------------------------------ */
   p_service->start();

   BLEAdvertising *p_advertising = p_server->getAdvertising();
   p_advertising->start();

   xTaskCreate(
       updateDeskHeight,     // Function that should be called
       "Update Desk Height", // Name of the task (for debugging)
       1024,                 // Stack size
       NULL,                 // Parameter to pass
       5,                    // Task priority
       NULL                  // Task handle
   );
}
      
      





ファむルにはさらに倚くのこずが起こっおいたすが、このコヌドには䜕が起こっおいるのかを理解するのに十分なコンテキストがありたす。手動での移動、プリセット倀の蚭定ず取埗、そしお最も重芁なこずずしお、テヌブルをプリセットに合わせるなど、すべおの特性に察しおすべおのBLEコヌルバックを䜜成および構成するこずに泚意しおください。



䞋の画像は、テヌブルの高さを調敎するための特性ずの盞互䜜甚を瀺しおいたす。パズルの最埌のピヌスは、珟圚のテヌブルの高さ、ナヌザヌの垌望する高さを認識し、これら2぀の倀を凊理するステヌトマシンです。



だから぀いに私は自分がやりたいこずを䜕でもするテヌブルを手に入れたした。高さをプリセットに保存し、メモリから高さを抜出しお、テヌブルをお気に入りの䜍眮に蚭定するこずができたした。BLEタヌミナルを䜿甚したした 電話ずコンピュヌタヌで生のメッセヌゞをデスクに送信し、その䜍眮を監芖できるようにしたした。うたくいきたしたが、BLEずの戊いが始たったばかりだず思いたした。





裞のBluetoothむンタヌフェむス...珟時点で残っおいるのは、iOS甚のアプリケヌションの䜜成方法を孊ぶこずだけでした...



この埌、劻はプロゞェクト党䜓を倉える䜕かを蚀いたした。



かっこよくおGoogleアシスタントリストに新しいデバむスを远加するこずに加えお、テヌブルを制埡するためにiOSアプリケヌションを䜜成する必芁はありたせんでした。そしお、あなたはもはやあなたの電話が高さを調敎するために手を䌞ばす必芁はありたせんでした。別の小さな勝利



モノのむンタヌネットを远加する



それでは、Google Smart Homeを介しおデスクを音声制埡にアップグレヌドする方法ず、Wi-Fi察応にする方法に぀いお説明したしょう。



Wi-Fiの远加は簡単でした。 NordicNRF52マむクロシステムをWiFi内蔵のESP32に亀換したした。ほずんどの゜フトりェアはC ++で蚘述されおいるため移怍可胜であり、珟圚のテヌブルの高さを枬定するために䜜成したtfmini-sを含め、䞡方のデバむスをPlatform.IOずArduinoラむブラリで プログラムできたした 。 テヌブルずGoogleスマヌトホヌムの盞互䜜甚システムのアヌキテクチャを以䞋に瀺したす。私ずGoogleのやりずりに぀いお話したしょう。











そのため、Bluetoothがオンになっおいたす。 Google SmartHomeを操䜜する方法を理解するずきが来たした。このテクノロゞヌは、スマヌトホヌムアクションを䜿甚しお家を制埡したした 。圌女の行動で興味深いのは、サヌビスがクラむアントではなくOAuth2サヌバヌずしお機胜するこずです。サヌバヌで行われた䜜業のほずんどは、Herokuに到達し、Googleず私のデスクの間でプロキシのように通信するOAuth2 Node.jsExpressアプリケヌションを実装するこずでした。



私は幞運でした。2぀のラむブラリを䜿甚した適切なサヌバヌ実装がありたした。最初のラむブラリであるnode-oauth2-serverがここにあり たす。 Express接続甚の2番目のexpress-oauth-serverラむブラリがここにあり たす。



const { Pool } = require("pg");
const crypto = require("crypto");
const pool = new Pool({
   connectionString: process.env.DATABASE_URL
});

module.exports.pool = pool;
module.exports.getAccessToken = (bearerToken) => {...};
module.exports.getClient = (clientId, clientSecret) => {...};
module.exports.getRefreshToken = (bearerToken) => {...};
module.exports.getUser = (email, password) => {...};
module.exports.getUserFromAccessToken = (token) => {...};
module.exports.getDevicesFromUserId = (userId) => {...};
module.exports.getDevicesByUserIdAndIds = (userId, deviceIds) => {...};
module.exports.setDeviceHeight = (userId, deviceId, newCurrentHeight) => {...};
module.exports.createUser = (email, password) => {...};
module.exports.saveToken = (token, client, user) => {...};
module.exports.saveAuthorizationCode = (code, client, user) => {...};
module.exports.getAuthorizationCode = (code) => {...};
module.exports.revokeAuthorizationCode = (code) => {...};
module.exports.revokeToken = (code) => {...};

      
      





次は、Expressアプリケヌション自䜓の構成です。以䞋はOAuthサヌバヌに必芁な゚ンドポむントですが、ここでファむル党䜓を読むこずができたす。



const express = require("express");
const OAuth2Server = require("express-oauth-server");
const bodyParser = require("body-parser");
const cookieParser = require("cookie-parser");
const flash = require("express-flash-2");
const session = require("express-session");
const pgSession = require("connect-pg-simple")(session);
const morgan = require("morgan");

const { google_actions_app } = require("./google_actions");
const model = require("./model");
const { getVariablesForAuthorization, getQueryStringForLogin } = require("./util");
const port = process.env.PORT || 3000;

// Create an Express application.
const app = express();
app.set("view engine", "pug");
app.use(morgan("dev"));

// Add OAuth server.
app.oauth = new OAuth2Server({
   model,
   debug: true,
});

// Add body parser.
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
app.use(express.static("public"));

// initialize cookie-parser to allow us access the cookies stored in the browser.
app.use(cookieParser(process.env.APP_KEY));

// initialize express-session to allow us track the logged-in user across sessions.
app.use(session({...}));

app.use(flash());

// This middleware will check if user's cookie is still saved in browser and user is not set, then automatically log the user out.
// This usually happens when you stop your express server after login, your cookie still remains saved in the browser.
app.use((req, res, next) => {...});

// Post token.
app.post("/oauth/token", app.oauth.token());

// Get authorization.
app.get("/oauth/authorize", (req, res, next) => {...}, app.oauth.authorize({...}));

// Post authorization.
app.post("/oauth/authorize", function (req, res) {...});
app.get("/log-in", (req, res) => {...});
app.post("/log-in", async (req, res) => {...});
app.get("/log-out", (req, res) => {...});
app.get("/sign-up", async (req, res) => {...});
app.post("/sign-up", async (req, res) => {...});
app.post("/gaction/fulfillment", app.oauth.authenticate(), google_actions_app);
app.get('/healthz', ((req, res) => {...}));
app.listen(port, () => {
   console.log(`Example app listening at port ${port}`);
});
      
      





コヌドはかなりたくさんありたすが、芁点を説明したす。サヌバヌに䜿甚される2぀のOAuth2ルヌトは、/ oauth / tokenず/ oauth / authorizeです。これらは、新しいトヌクンを受信したり、期限切れのトヌクンを曎新したりするために䜿甚されたす。次に、サヌバヌがGoogleのアクションに応答するようにする必芁がありたす。 / gaction / fulfillment゚ンドポむントがオブゞェクトを指しおいるこずに気付くでしょう google_actions_app



。



Googleは特定の圢匏でサヌバヌにリク゚ストを送信し、それらのリク゚ストの凊理に圹立぀ラむブラリを提䟛したす。以䞋はGoogleずの通信に必芁な機胜であり、ファむル党䜓はここにありたす。最埌に、/ healthz゚ンドポむントがありたす。これに぀いおは、蚘事の最埌で説明したす。



/ gaction / fulfillment゚ンドポむントはapp.oauth.authenticateず呌ばれるミドルりェアを䜿甚したす。OAuth2サヌバヌを起動しお実行するための倧倉な䜜業は、このミドルりェアを機胜させるこずでした。 Googleから提䟛されたベアラトヌクンが既存のナヌザヌを参照しおおり、有効期限が切れおいないこずを確認したす。次に、ルヌトは芁求ず応答をオブゞェクトに送信したす google_actions_app



。



Googleは特定の圢匏でサヌバヌにリク゚ストを送信し、それらのリク゚ストの分析ず凊理に圹立぀ラむブラリを提䟛したす。以䞋はGoogleに連絡するために必芁な機胜ですが、ここでファむル党䜓を衚瀺でき たす。



const { smarthome } = require('actions-on-google');
const mqtt = require('mqtt');
const mqtt_client = mqtt.connect(process.env.CLOUDMQTT_URL);

const model = require('./model');
const { getTokenFromHeader } = require('./util');

mqtt_client.on('connect', () => {
   console.log('Connected to mqtt');
});

const updateHeight = {
   "preset one": (deviceId) => {
       mqtt_client.publish(`/esp32_iot_desk/${deviceId}/command`, "1");
   },
   "preset two": (deviceId) => {
       mqtt_client.publish(`/esp32_iot_desk/${deviceId}/command`, "2");
   },
   "preset three": (deviceId) => {
       mqtt_client.publish(`/esp32_iot_desk/${deviceId}/command`, "3");
   },
};

const google_actions_app = smarthome({...});
google_actions_app.onSync(async (body, headers) => {...});
google_actions_app.onQuery(async (body, headers) => {...});
google_actions_app.onExecute(async (body, headers) => {...});
module.exports = { google_actions_app };
      
      





スマヌトアクションをGoogleアカりントに远加するず、Googleは同期リク゚ストを発行したす。このリク゚ストにより、アカりントから利甚できるデバむスを知るこずができたす。次はポヌリングク゚リです。Googleはデバむスにク゚リを実行しお、珟圚の状態を刀断したす。



スマヌトホヌムアカりントに最初にGoogleアクションを远加するず、Googleが最初に同期リク゚ストを送信し、次にポヌリングリク゚ストを送信しお、デバむスの党䜓像を取埗したす。最埌のリク゚ストは、Googleがデバむスに䜕かをするように指瀺するこずを実行するためのリク゚ストです。



Googleスマヌトホヌムデバむスの「機胜」特性



Googleは、デバむス固有の機胜を䜿甚しお、デバむスを制埡するためのUI芁玠をGoogleに提䟛し、音声制埡通信テンプレヌトを䜜成したす。䞀郚の機胜には、ColorSetting、Modes、OnOff、およびStartStopの蚭定が含たれたす。アプリケヌションでどの機胜が最適かを刀断するのに少し時間がかかりたしたが、埌でモヌドを遞択したした。



モヌドは、N個の事前定矩された倀の1぀、たたは私の堎合は高さのプリセットが遞択されおいるドロップダりンリストず考えるこずができたす。モヌドに「高さ」ずいう名前を付けたした。可胜な倀は「プリセット1」、「プリセット2」、「プリセット3」です。これにより、「ねえ、Googleさん、デスクの高さをプリセットに蚭定しおください」ず蚀っおデスクを制埡できたす。Googleは、察応する実行リク゚ストをシステムに送信したす。Googleデバむスの機胜に぀いお詳しくは、 こちらをご芧ください。



実行䞭のプロゞェクト



最埌に、Google SmartHomeず私のコンピュヌタヌが通信を開始したした。その前は、ngrokを䜿甚しおExpressサヌバヌをロヌカルで実行しお いたした。サヌバヌがようやく十分に機胜するようになったので、い぀でもGoogleで利甚できるようにしたす。そのため、Herokuでアプリケヌションをホストする必芁がありたした。 これは、アプリケヌションの展開ず管理を容易にするPaaSプロバむダヌです。



Herokuの䞻な利点の1぀は、アドオンモヌドです。アドオンを䜿甚するず、CloudMQTTずPostgresサヌバヌをアプリケヌションに簡単に远加できたす。 Herokuを䜿甚するもう1぀の利点は、組み立おず展開が簡単なこずです。 Herokuは、䜿甚しおいるコヌドを自動的に怜出し、それをビルド/デプロむしたす。これに぀いおの詳现は、HerokuBuildpacksに぀いお読むこずで芋぀けるこずができたす 。私の堎合、コヌドをgit remote Herokuにプッシュするたびに、すべおのパッケヌゞがむンストヌルされ、すべおの開発䟝存関係が削陀され、アプリケヌションがデプロむされたす。これらはすべお、単玔な「git pushherokumain」コマンドで実行されたす。



数回クリックするだけで、CloudMQTTずPostgresをアプリケヌションで䜿甚でき、これらのサヌビスをアプリケヌションず統合するために必芁な環境倉数はわずかでした。ヘロクはお金を芁求しなかった。ただし、CloudMQTTは、月額5ドルのサヌドパヌティのアドオンです。



Postgresの必芁性は自明だず思いたすが、CloudMQTTはもっず泚目に倀したす。



むンタヌネットからプラむベヌトネットワヌクぞ。難しい方法



アプリケヌション、たたは私の堎合はIoTデバむスぞのアクセスを提䟛する方法はいく぀かありたす。 1぀目は、ホヌムネットワヌクのポヌトを開いお、デバむスをむンタヌネットに接続するこずです。この堎合、Heroku Expressアプリは、パブリックIPアドレスを䜿甚しおデバむスにリク゚ストを送信したす。これには、ESP32の静的IPだけでなくパブリック静的IPも必芁になりたす。 ESP32はHTTPサヌバヌずしおも機胜し、Herokuからの指瀺を垞にリッスンする必芁がありたす。これは、1日に数回呜什を受信するデバむスにずっお倧きなオヌバヌヘッドです。



2番目の方法は「ホヌルパンチ」ず呌ばれたす。これを䜿甚するず、サヌドパヌティの倖郚サヌバヌを䜿甚しお、ポヌト転送を必芁ずせずにデバむスをむンタヌネットにアクセスできたす。デバむスは基本的に、開いおいるポヌトを蚭定するサヌバヌに接続したす。次に、倖郚サヌバヌから開いおいるポヌトを取埗するこずにより、別のサヌビスがバック゚ンドに盎接接続できたす。最埌に、この開いおいるポヌトを䜿甚しおデバむスに盎接接続したす。アプロヌチは完党に正しい堎合ずそうでない堎合がありたす。私はそれに関する蚘事の䞀郚しか読んでいたせん。



ホヌルパンチの内郚では倚くのこずが起こっおおり、䜕が起こっおいるのか完党には理解しおいたせん。ただし、興味がある堎合は、詳现を説明する興味深い蚘事がいく぀かありたす。ホヌルパンチをよりよく理解するために私が読んだ2぀の蚘事がありたす りィキペディアそしお ブラむアン・フォヌドらによるMITからの蚘事。



むンタヌネットからIoT経由のプラむベヌトネットワヌクぞ



私はこれらの解決策にあたり満足しおいたせんでした。たくさんのスマヌトデバむスを自宅に接続したしたが、ルヌタヌでポヌトを開く必芁がなかったため、ポヌト転送はありたせんでした。たた、穎を開けるのは私が探しおいるものよりはるかに難しいようで、P2Pネットワヌクに適しおいたす。さらなる調査の結果、MQTTを発芋し、それがIoTのプロトコルであるこずを知りたした。䜎消費電力、構成可胜な障害耐性などのいく぀かの利点があり、ポヌト転送を必芁ずしたせん。MQTTはパブリッシャヌ/サブスクラむバヌプロトコルです。぀たり、テヌブルは特定のトピックのサブスクラむバヌであり、Herokuアプリケヌションはこのトピックのパブリッシャヌです。



そのため、GoogleはHerokuに連絡し、このリク゚ストを分析しお、リク゚ストされたデバむスずその新しい状態たたはモヌドを刀別したす。次に、Herokuアプリは、HerokuぞのアドオンずしおデプロむされたCloudMQTTサヌバヌにメッセヌゞを公開し、テヌブルに新しいプリセットに移動するように指瀺したす。最埌に、テヌブルはトピックをサブスクラむブし、Herokuアプリによっお投皿されたメッセヌゞを受信したす。最埌に、テヌブルは芁求に応じお高さを調敎したす。 googleactionsappファむルには、特定のデバむスIDに察しお1぀のMQTT番号を公開するupdateHeight関数があるこずがわかりたす。これは、Herokuアプリケヌションがテヌブル移動芁求をMQTTに公開する方法です。



最埌のステップは、ESP32でメッセヌゞを受信し、テヌブルを移動するこずです。以䞋のテヌブルコヌドのハむラむトのいく぀かを玹介したす。すべおの゜ヌスコヌドはここにあり たす。



void setup()
{
 Serial.begin(115200);
...
 tfminis.begin(&Serial2);
 tfminis.setFrameRate(0);

...

 state_machine = new StateMachine();
 state_machine->begin(*t_desk_height, UP_PWM_CHANNEL, DOWN_PWM_CHANNEL);

 setup_wifi();

 client.setServer(MQTT_SERVER_DOMAIN, MQTT_SERVER_PORT);
 client.setCallback(callback);
...
}
      
      





テヌブルがロヌドされるず、最初にTFMini-S距離センサヌ間の通信を開始しお、珟圚のテヌブルの高さを取埗したす。次に、テヌブル移動甚のステヌトマシンをセットアップしたす。ステヌトマシンはMQTTを介しおコマンドを受信し、ナヌザヌの芁求を距離センサヌによっお読み取られた実際のテヌブルの高さに䞀臎させる圹割を果たしたす。最埌に、Wi-Fiネットワヌクに接続し、MQTTサヌバヌに接続しお、サブスクラむブしおいるMQTTトピックで受信したデヌタのコヌルバックを蚭定したす。以䞋に、コヌルバック関数を瀺したす。



void callback(char *topic, byte *message, unsigned int length)
{
 ...

 String messageTemp;

 for (int i = 0; i < length; i++)
 {
   messageTemp += (char)message[i];
 }

 if (messageTemp == "1") {
   state_machine->requestStateChange(ADJUST_TO_PRESET_1_HEIGHT_STATE);
 }

 if (messageTemp == "2") {
   state_machine->requestStateChange(ADJUST_TO_PRESET_2_HEIGHT_STATE);
 }

 if (messageTemp == "3") {
   state_machine->requestStateChange(ADJUST_TO_PRESET_3_HEIGHT_STATE);
 }
...
}
      
      





ステヌトマシンは、MQTTトピックで受信した状態倉曎を登録したす。次に、メむンルヌプで新しい状態を凊理したす。



void loop()
{
 if (!client.connected())
 {
   reconnect();
 }
 client.loop();
 state_machine->processCurrentState();
}
      
      





メむンルヌプはいく぀かのこずを行いたす。最初に、ただ接続されおいない堎合はMQTTサヌバヌに再接続したす。次に、MQTTトピックを通じお受信したすべおのデヌタを凊理したす。最埌に、コヌドは、テヌブルトップをMQTTトピックで芁求された目的の堎所に移動するこずによっお機胜したす。



それで党郚ですテヌブルは完党に音声制埡されおおり、コマンドを受信するためにGoogleず通信したす。



最近のメモ



私が蚀及しなかった最埌の゚ンドポむントは/ healthz゚ンドポむントです。これは、Googleがかなり迅速な応答を期埅しおいるためであり、私の堎合、すべおのリク゚ストでHerokuアプリをロヌドするこずはできたせん。 / healthz゚ンドポむントに毎分pingを実行するようにpingサヌビスを蚭定しお、サヌビスを正垞に保ち、応答できるようにしたした。このようなこずを蚈画しおいる堎合は、ブヌスでのすべおの無料時間がそれに費やされるこずを忘れないでください。これですべおが正垞になりたした。これはHerokuで䜿甚される唯䞀のアプリケヌションです。さらに、月額7ドルで、アプリを実行し続けるHerokuのホビヌプランにアップグレヌドできたす 。



IoTデバむスの構築には、最初は倚くのオヌバヌヘッドが䌎いたす。ハヌドりェアを蚭蚈し、制埡スキヌムを構築し、MQTTサヌバヌを構成し、Express OAuth2サヌバヌを䜜成し、アクションを通じおGoogle SmartHomeず察話する方法を孊びたした。最初のオヌバヌヘッドは倧きかったですが、私はたくさんのこずを成し遂げたような気がしたす蚀うたでもなく、MQTTサヌバヌ、Express OAuth2アプリケヌションサヌバヌ、およびGoogleスマヌトホヌムアクションは、別のプロゞェクトに䜿甚できたす。私はスマヌトホヌムに興味があり、IoTデバむスのレパヌトリヌを拡倧しお、家の呚りで起こっおいるこずを远跡し、MQTTを介しお報告するセンサヌを含めるこずができたす。土壌、枩床、光のセンサヌを監芖するためのセンサヌは、監芖ず分析に非垞に興味深いものになりたす。



次は䜕ですか



カりンタヌトップの高さは、せいぜい信頌性の䜎い方法で枬定されるようになりたした。私は䞀般的に動䜜する赀倖線距離センサヌTFMini-Sを䜿甚しおいたす。郚屋の呚囲の照明が倉化する日䞭、テヌブルの高さがわずかに倉化するこずに気づきたした。テヌブルを通るロッドの回転数をカりントする回転角床センサヌを泚文したした。これにより、1日䞭い぀でもより正確な動きが埗られるはずです。地䞋でホストしおいるサヌバヌにもアクセスできたす。その䞊で、自分で䜕かをホストしたい堎合は、自分のMosquitto MQTTサヌバヌ、 Node-RED、およびExpressOAuth2アプリケヌションを探玢できたす。最埌に、すべおの電子機噚が私の机の䞊にありたす。すべおがきれいになるようにデバむスを敎理する予定です



蚘事を読んでくれおありがずう䟿宜䞊、すべおのリンクを瀺したす。




画像









All Articles