В этой статье я покажу, как я превратил свой стол с ручной регулировкой высоты в автоматизированный стол с Интернетом вещей. Я расскажу, как подобрать размеры и запустить моторы, а также как подключить ваше устройство IoT к Google при помощи Heroku в качестве публичного интерфейса. Если коротко, у этого проекта две особенности. Первое: стол подключается из Google Smart Home к Heroku с помощью голосовых команд, и второе: Heroku и собственно стол общаются по протоколу Интернета вещей MQTT. MQTT — хорошее решение для Интернета вещей, а также для преодоления некоторых других препятствий, с которыми нам придётся столкнуться.
Прежде всего скажу, что я делал этот проект, просто чтобы поразвлечься. Надеюсь, вы найдёте статью занимательной и она послужит вам мотивацией, чтобы найти время и сделать что-то своё.
Тот самый столик
Аппаратная часть
Первая и, вероятно, самая трудная часть работы — переделать стол. В прошлой жизни у стола была отсоединяемая ручка, она располагалась у края столешницы. Сначала я подумал о том, чтобы прикрепить что-то к отверстию ручки, не пришлось бы вмешиваться в конструкцию стола. Я приобрёл несколько приводов, чтобы понять, как к столу прикрепить мотор, но безрезультатно. Затем появилась идея: стержень, работающий по длине всего стола, который соединял бы его ножки так, что они опускались и поднимались бы одновременно. Если закрепить подходящий к стержню привод, тогда я смогу использовать ремень для соединения стержня и мотора. Также можно было бы оснастить стол мотором, не сильно вмешиваясь в его конструкцию.
Изготовление столика на балкон своими руками
Если готовые изделия не устраивают по габаритам, внешнему виду или стоимости, всегда есть возможность собрать откидное сооружение самостоятельно. Тем более, что особых сложностей процесс не вызывает.
Для изготовления конструкции необходимо запастись материалом, петлями и крепежом. Столешницу можно вырезать из мебельного щита, толстой фанеры, плиты ЛДСП или МДФ.
Чем отличается МДФ от ЛДСП
Если используются плиты, рекомендуется обработать торцы кромкой, подходящей по цвету. Для этого понадобятся утюг и острый нож для срезки излишков. При установке столика в помещении, которое отделано деревом, гармоничнее будет смотреться деревянная крышка стола.
Предлагается вариант производства простейшей конструкции откидного стола из мебельного щита для балкона.
В качестве опор будут использованы две детали из ЛДСП (можно сделать также из дерева, но использовалось то, что было под рукой). Опору можно сделать одну, но стол получается довольно большим, поэтому для прочности конструкции лучше установить два опорных элемента, складывающиеся в разные стороны. Также понадобятся два бруска. Один — для крепления столешницы, второй — для фиксации опор.
Таблица. Материалы и приспособления для изготовления стола.
Потребуется | Иллюстрация |
Мебельный щит размером 1000 х 500 мм | |
Бруски 40 х 50 мм длиной 600 мм (2 шт.) | |
ЛДСП размером 450 х 450 мм | |
Петли универсальные (2 шт.) | |
Петли мебельные (2 шт.) | |
Саморезы |
Шаг 1.
Мебельный щит покрывается лаком и высушивается.
Мебельный щит
При необходимости столешницу можно отполировать (до нанесения лакокрасочного покрытия)
Шаг 2.
На стену наносится разметка для крепления бруска. Он будет установлен на высоте 700 мм от пола. При проведении работ необходимо использовать уровень.
Шаг 3.
При помощи четырех саморезов брусок фиксируется к стене.
Шаг 4.
На расстоянии 30 мм от краев к нему крепятся две дверные петли.
Шаг 5.
Из куска ЛДСП выпиливаются две треугольные детали (либо треугольники собираются из бруса), которые будут служить опорами.
Сборка треугольной опоры из брусков
Бруски скреплены саморезами и перфорированным уголком. Для надежности все места соединения проклеены столярным клеем
Шаг 6.
Вертикально прикладываются обе опорные ножки. Делаются отметки для крепления рояльных (мебельных) петель.
Шаг 7.
Мебельные петли крепятся саморезами к ножкам и стене.
Уголки держатся на рояльных петлях
Так выглядят опоры в сложенном виде
Шаг 8.
На внутреннюю сторону столешницы крепится брусок (параллельно первому). Расстояние от наружного края — 200 мм.
Шаг 10. Крышка стола укладывается сверху на закрепленный к стене брусок с петлями. С внутренней стороны она саморезами крепится к свободной створке петли.
Столешница держится на двух коротких петлях, расположенных горизонтально. Под столешницей закреплен брус
Стол в сложенном виде
Функциональное и надежное сооружение, не занимающее лишнего места на балконе готово. При необходимости крышка стола поднимается, ножки сдвигаются под углом к центру и надежно удерживают конструкцию.
Приобретенные у изготовителя или собранные своими руками компактные конструкции, отличающиеся бюджетностью и функциональностью, в ряде случаев являются незаменимыми предметами интерьера.
Важность крутящего момента
Заказав нужные привод и ремень, я начал искать на Amazon мотор с высоким крутящим моментом. И — о, чудо! — я нашёл много подходящих двигателей! Или мне так показалось… Купив маленький моторчик, около месяца я ждал его прибытия из Китая. Я был так взволнован, когда моторчик, наконец, приехал! Не мог дождаться выходных, чтобы, наконец, собрать всё воедино и получить мой моторизованный стол.
Всё пошло не по плану. Я провёл день, вырезая дыру для стержня в металлической обшивке стола. В тот момент у меня были только ручные инструменты, поэтому процесс занял больше времени, чем я рассчитывал. Ближе к концу дня я закончил сборку стола и был готов его опробовать.
Я включил моторчик, напряжение на своём настольном источнике питания и… ничего не произошло. Несколькими мгновениями позже мотор начал вращаться и скрежетать зубцами приобретённого ремня. Из этого я извлёк два урока: ремень, очевидно, не справляется со своей работой, а надпись «Мотор с высоким крутящим моментом» не означает «Я могу поднять всё на свете». Второй урок: надо смотреть, какого размера моторчик в сравнении с пальцами. Мой оказался крошечным!
Слева на фото мотор и ремень. Вверху справа — прикреплённый к столу мотор (позже вы увидите больше о происходящем). Внизу справа мотор в положении на столе.
Типы компьютерных столов
Модели столов отличаются по своей форме. Мастер выбирает форму изделия, исходя из размеров комнаты, расположения других деталей интерьера, дизайнерского стиля, назначения стола. Выделяют следующие типы конструкций:
Подходящий мотор
Чтобы выбрать подходящий мотор, нужно было рассчитать, какой крутящий момент требуется для поднятия столешницы. Я был удивлён тем, насколько просто сделать это. Крутящий момент — это сила, умноженная на длину плеча рычага.
Что ж, плечо рычага у меня было (это рукоятка стола), нужно было только рассчитать силу, которая легко повернула бы плечо рычага. Я нагрузил стол, привязав к ручке кувшин для молока и постепенно добавлял в кувшин воду, пока рычаг не начал вращаться. Повернув ручку кверху с наполненным кувшином я убедился, что вес легко поворачивает ручку. Я выяснил, что длина плеча рычага составляет 11 см, а требуемая сила — 4 фунта. Подставив эти цифры в формулу, я выяснил, что мотор должен выдавать крутящий момент не менее 19,95 кгс.см. И начал искать его.
Я решил переделать стол необратимым образом. Мне было известно, что проходящий через середину стола стержень полый. Поискав двухвальный мотор, я мог разрезать стержень и пересобрать его с мотором в середине. Купив два мотора с крутящим моментом 20 кгс.см, я гарантировал, что крутящего момента для поднятия стола достаточно.
В очередную прекрасную субботу я разобрал свой стол на четыре части, подпилив валы двигателей так, чтобы их можно было использовать при сборке стержня. Я проделал больше дырок в металле, чтобы поместить в них моторы. Ремня в этот раз не было: моторы соединялись напрямую со стержнем, дыры были достаточно большими. Пока наступал вечер, я пересобрал стол и загрузил его офисными принадлежностями.
Два верхних фото — полностью установленные на стол моторы. Два нижних фото —- интегрированный стержень, с помощью моторов проходящий по длине стола.
Я подключил моторы и соединил их с источником питания. Включив питание, я увидел движение стола! На этот раз я был увереннее, потому что правильно подобрал размеры моторов. Я удвоил мощность двигателей ради уверенности, но потрясающе было видеть их движение!
Однако позвольте уточнить, что стол был медленным. Я снял видео, чтобы показать другу, как работает стол, но ему пришлось включить ускорение времени на видео, чтобы не смотреть 5 минут, как стол меняет положение столешницы.
Вариант 1. Инструкция по изготовлению стола для ручного фрезера
Материалы для изготовления фрезерного стола
Для сооружения фрезерного стола понадобиться:
- 4 бруска квадратного сечения;
- обрезки ДСП и фанеры, размеры которых определяются при построении чертежа стола;
- метизы (гайки, болты, саморезы, петли и пр.);
- домкрат;
- металлический профиль;
- шестимиллиметровая стальная пластина;
- алюминиевые направляющие;
- подвижная каретка-упор (направляющая от пилы);
- ручной фрезер.
Чертеж самодельного фрезерного стола (вариант 1)
В любом случае, перед тем как начать делать любой такой стол, чертеж нужно выполнить с обозначением всех размеров и определением расположения рабочих элементов относительно друг друга.
Пошаговая сборка
Рассмотрим подробно каждый шаг по изготовлению и креплению каждого элемента самодельного фрезерного стола.
1-й шаг. Для изготовления стационарной основы для стола потребуются бруски и обрезки ДСП, из которых скручиваем опоры-ножки, дополнительно усиливаем жесткость с помощью горизонтальных соединительных панелей из фанеры. В правой боковой части вырезаем отверстие под кнопку пуска, которая будет подсоединена к ручному фрезеру.
2-й шаг. Столешницу стола выполняем из ДСП. Делаем ее подъемной вместе с фрезером, для чего устанавливаем петли и изготавливаем дополнительную основу-опору из 15-тимиллиметровой фанеры.
3-й шаг. Чтобы ровно перемещать обрабатываемую заготовку вдоль стола, например, чтобы прорезать в ней паз, применяется двигающаяся каретка-упор. В столешнице вырезаем канавку под направляющие подвижного упора и устанавливаем в нее металлический профиль. В качестве каретки-упора можно использовать направляющую от старой пилы.
4-й шаг. Продольный упор также выполняем из ДСП и делаем его подвижным для регулирования вокруг фрезы зазоров. Для обеспечения подвижности вырезаем в верхней части упора перпендикулярные пазы и крепим упор к столешнице фиксаторами. Посередине вырезаем небольшой паз для высасывания стружки и прочих отходов фрезерования.
5-й шаг. Из тонкой фанеры мастерим короб с отверстием для подсоединения шланга пылесоса, который будет удалять образовавшуюся в процессе фрезеровки пыль и стружку. Крепим короб сзади перпендикулярного упора.
6-й шаг. Берем шестимиллиметровую стальную пластину и прикручиваем ее к столешнице вровень с поверхностью. В процессе крепления следим, чтобы ее края не выступали над столешницей, иначе обрабатываемые детали будут за них цепляться. К пластине снизу будет крепиться ручной фрезер.
7-й шаг. Прикрепляем фрезер за алюминиевую подошву к низу пластины с помощью болтов, но не забываем предварительно просверлить в подошве отверстия под болты. Крепление ручного инструмента к съемной пластине, а не непосредственно к столу, обеспечивает экономию глубины фрезерования и позволяет легко заменять фрезу.
8-й шаг. Сооружаем лифт фрезера. Для этого используем автомобильный домкрат, позволяющий изменять высоту фрезы с максимальной точностью.
9-й шаг. Снимаем с фрезера ручки и вместо них прикручиваем алюминиевые направляющие, которые соединяем с механизмом домкрата.
Конструкция и видео самодельного фрезерного стола для ручного фрезера
Прежде чем приступить к изготовлению фрезерного стола необходимо точно определится с его конструктивными особенностями. Данная статья предоставляет инструкцию, согласно которой изготавливается простой фрезерный стол. Другие первого варианта сборки подробности смотрите на видео ниже.
Проверяем надежность крепления всех элементов – и фрезерный стол своими руками готов!
Предлагаем на ваш вкус еще несколько моделей фрезерный станков по дереву, сделанных своими руками.
Обороты важны. Окончательная версия
Наконец я понял, что всё сводится к двум вещам: крутящему моменту и оборотам. Нужно было найти мотор с достаточным количеством оборотов при уже известном крутящем моменте.
Это было не так сложно. Хотя я не нашёл двухвалового мотора, зато нашёл прямоугольный редуктор, который превращает мотор с одним валом в двухвальный мотор.
Короче говоря, следующий месяц был месяцем ожидания коробки передач из Китая, а следующей после ожиданий субботой у меня был стол, который двигался с нужной скоростью.
Последний мотор сам по себе слева, а установленный — справа. Немного аппаратного обеспечения и много программного обеспечения.
Я не был доволен огромным блоком питания на моем столе, лежащем только ради того, чтобы управлять высотой столешницы. Кроме того, чтобы изменять положение стола от одного к другому и обратно, я менял местами провода. Небольшая проблема, но проект делался, чтобы в идеале просто нажимать кнопку и иметь несколько предустановок высоты.
Письменный стол с регулируемой высотой: преимущества и недостатки
К основным преимуществам рассматриваемых конструкций стоит отнести:
- Возможность чередовать положение тела во время длительной «сидячей» работы.
- Хорошая адаптивность. Несложно подобрать высоту для каждого индивидуально.
- Современный подход к организации рабочего места. В некоторых случаях это может быть важно.
- Большой поднимаемый вес (более 100кг.). Для моделей с электроприводом.
- Широкий ассортимент. Практически всегда удастся подобрать модель, максимально соответствующую выдвигаемым требованиям.
Механический механизм является самым надежным в виду своей простоты.
При этом недостатки также имеются и довольно серьезные:
- Неудобство механического способа регулировки.
- Дешевые конструкции отличаются своеобразным «тремором» – в поднятом состоянии поверхность стола может качаться или дрожать во время работы.
- Модели с автоподъемником зависят от электричества и требуют дополнительного ухода. Для компьютерных столов не всегда получится организовать кабель-менеджмент подручными средствами. Как следствие – непредвиденные расходы.
- Высокая стоимость.
Столешницы также могут быть регулируемыми и настраиваться под определенным углом.
Bluetooth
Первым решением было добавить к столу Bluetooth. В конце концов, похоже на то, что почти каждое устройство в доме имеет Bluetooth, а телефон представляется удобным интерфейсом управления чего-то подобного моему столу.
Итак, теперь я приобрёл плату контроллера мотора, плату для Bluetooth Nordic NRF52, сенсоры для измерения расстояния и начал возиться с прошивкой контроллера.
В конце статьи я оставлю ссылки на софт и прошивку, которые написал для проекта. Не стесняйтесь комментировать код: я не занимаюсь прошивками профессионально и хотел бы получить какие-то указания.
В качестве краткого введения: ESP32 написана на C++ с помощью библиотек Arduino для взаимодействия с приложением BLE Terminal на телефоне. Установка и конфигурирование BLE довольно сложны. Для начала нужно создать все характеристики для значений, которые вы хотели бы контролировать через BLE. Думайте о характеристике, как о переменной в вашем коде. BLE оборачивает переменную во множество обработчиков для получения и установки значения этой переменной.
Затем характеристики упаковываются в сервис с собственным UUID, который делает сервис уникальным и идентифицируемым из приложения. Наконец, вы должны добавить этот сервис к полезной нагрузке объявления, чтобы ваш сервис мог быть обнаружен устройством. Когда удалённое устройство соединяется с вашим сервисом и отправляет данные через характеристики, стол распознаёт, что пользователь хочет отрегулировать высоту до другой предустановки и начинает движение.
Для регулировки высоты столешница имеет определяющий текущую высоту встроенный в нижнюю часть сенсор TFMini-S LiDAR. Это забавный сенсор: он называется LiDAR, хотя на самом деле это лазер. Он использует оптику и светодиод, чтобы определить время полёта ИК-излучения. Так или иначе, сенсор определяет высоту стола. Затем контрольная плата определяет разницу между текущей высотой и запрашиваемой высотой и запускает мотор, который вращается в нужном направлении. Некоторые основные части кода приведены ниже, но вы можете увидеть весь файл здесь.
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 для всех характеристик, включая ручное движение, установку и получение значений пресета и, самое важное, выравнивает стол согласно предустановке.
Изображение ниже показывает взаимодействие с характеристиками для регулировки высоты стола. Последний элемент головоломки — машина состояний, которой известна текущая высота стола, требуема пользователем высота, и работает с этими двумя значениями.
Итак, наконец у меня был стол, который делал всё, что я хотел. Я мог сохранить высоту в пресеты и извлечь высоты из памяти, чтобы установить стол в мои любимые положения. Я применял BLE Terminal на моём телефоне и компьютере, так я мог посылать сообщения в сыром виде моему столу и контролировать его позицию. Это работало, но я знал, что битва с BLE только начинается.
Голый интерфейс bluetooth… Всё, что оставалось на данный момент, — научиться писать приложения под iOS…
После всего этого моя жена сказала кое-что, что изменило весь проект: «А что, если сделать управление твоим голосом?».
Кроме крутости и добавления нового устройства к списку Google Assistant отпала необходимость писать приложение под iOS, чтобы управлять столом. И больше не нужно было доставать телефон, чтобы отрегулировать высоту. Ещё одна маленькая победа!
Как выбирать
Прежде чем идти в магазин следует задаться вопросом, а какой, собственно, нужен стол регулируемый по высоте? В первую очередь нужно исходить из задач, решение которых будет оправдывать целесообразность такой покупки. Вторым немаловажным фактором является размер. Такие столы отличаются довольно большими габаритами, поэтому имеет смысл заранее сделать замеры того места, где он должен стоять.
Такая мебель подстраивается под рост и эргономику человека, что позволяет ему не сутулиться во время работы.
В общем случае рекомендуется обращать внимание на следующее:
- Конструктивная схема. Механический подъем или при помощи электроприводов.
- Материал. Если предполагается большая нагрузка (монитор, принтер, системный блок), лучше выбирать модели с каркасом из металла и массивной столешницей. Модели для бумажной работы могут быть попроще.
- Количество опор. Опять же, все зависит от нагрузки.
- Максимальная высота подъема.
- Частота использования. С какой периодичностью предполагается регулировать высоту.
Обратите внимание! В некоторых столах с механической системой подъема, процесс регулировки осуществляется при помощи закладного штифта в соответствующее отверстие на опоре. Это значит, что со столешницы придется убирать все предметы, которые могут упасть во время этой процедуры, что крайне неудобно, если такое действие нужно производить постоянно.
Регулируемая мебель является отличной профилактикой различных заболеваний позвоночного столба.
Добавление Интернета вещей
Теперь поговорим об апгрейде стола до управления голосом через Google Smart Home и как подружить его с Wi-Fi.
Добавить Wi-Fi было достаточно просто. Я заменил микроконтроллер Nordic NRF52 на ESP32 со встроенным WiFi. Большая часть софта была переносимой, потому что была написана на C++, а оба устройства могли программироваться с помощью Platform.IO и библиотек Arduino, включая tfmini-s, написанную мной для измерения текущей высоты стола.
Ниже показана архитектура системы взаимодействия стола с Google Smart Home. Давайте поговорим о взаимодействии между мной и Гуглом.
Итак, Bluetooth был включён. Пришло время выяснить, как взаимодействовать с Google Smart Home. Эта технология контролировала дом с помощью Smart Home Actions. В её действиях интересно то, что сервис действует как сервер OAuth2, а не как клиент. Большая часть проделанной с сервером работы была связана с реализацией приложения OAuth2 Node.js Express, которое добирается до Heroku и взаимодействует как прокси между Google и моим столом.
Мне повезло: была достойная реализация сервера с помощью двух библиотек. Первая библиотека — node-oauth2-server, была найдена здесь. Вторая библиотека express-oauth-server для подключения Express была найдена здесь.
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}`); }); Кода довольно много, но я объясню основные моменты. Два используемых для сервера маршрута 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 в свой аккаунт Smart Home, вы заметите, что Google сначала отправляет запрос синхронизации, а затем опрашивающий запрос, чтобы получить целостное представление о ваших устройствах. Последний — запрос это запрос на выполнение, который Google сообщает вашим устройствам, чтобы они что-то делали.
Популярные конструкции
В зависимости от размера помещения, от того, сколько человек будет использовать стол, выбирают его форму и размеры. Существуют несколько вариаций по типу конструкции:
- Т-образный – подходит для больших прямоугольных помещений. Стандартный размер – 80 х 160 см. Письменный стол обладает именно такими габаритами. Если столешница будет использоваться для праздников, то изделие будет особенно удобным – именинник может сесть во главе, у него есть возможность видеть всех остальных. Если места во главе стола окажутся незанятыми, то эта часть – идеальное место для украшения. Легко подойти с любой стороны, что упрощает сервировку.
- П-образная – подойдет для помещений любого размера. Подходит для кофейных, кабинетных и кухонных столов. Один из наиболее популярных вариантов.
- Е-образная – используется в просторных помещениях. Подходит для проведения массовых торжеств.
- Овальный или круглый стол. Не подходят для малогабаритных помещений. За овальными столами свободно размещаются 4 персоны, за круглыми – не более 5.
Т-образный
П-образный
Е-образный
Овальный
Круглый
Большой стол подойдет для торжеств и праздников, на которых много гостей. Изделия небольшого размера идеальны для маленькой семьи. Стандартные размеры столешниц таковы:
- 4 человека – от 80 х 120 до 100 х 150;
- 6 человек – от 80 х 180 до 100 х 200;
- 8 человек – от 80 х 240 до 100 х 260;
- 12 человек – от 80 х 300 – 100 х 320.
Стандартные размеры столешниц
По назначению столы разделяются на такие разновидности:
- офисный или компьютерный;
- кухонный;
- низкий журнальный;
- туалетный со встроенным зеркалом;
- обеденный стол;
- для телевизора.
Офисный
Кухонный
Низкий журнальный
Туалетный со встроенным зеркалом
Обеденный
Для телевизора
По форме основания различают столы:
- С 4 ножками. Классика, модель оправдана разнообразием материалов, комфортом при сидении.
- С 2 ножками. Есть варианты с двумя Х-образными ножками или прочными, изготовленными из массива с перемычкой снизу.
- Дизайнерские конструкции. Встречаются столики с 3 ножками, стилизованные под барокко. Варианты с одной опорой имеют круглую или овальную форму, за таким столом может разместиться большая компания.
С 4 ножками
С 2 ножками
Дизайнерский
Изделия выполняют из множества материалов. Выбор определяется целью и условиями эксплуатации:
- Древесно-стружечная плита – бюджетное сырье. Невысокая стоимость конструкции отражается на износоустойчивости. Такие столешницы служат недолго.
- Древесноволокнистая плита. Более дорогой и надежный вариант. Высокая влагостойкость, долгий срок эксплуатации.
- Массив дерева. Изделия характеризуются долговечностью, надежностью. Эстетично выглядят, могут легко сочетаться с любым дизайнерским решением. Натуральный материал высокого качества дорого стоит.
- Стекло. Стеклянные столешницы легко очищаются от загрязнений, визуально расширяют пространство.
- Камень. Для того чтобы изготовить каменный стол, используют натуральное и искусственное сырье. Конструкция из камня отличается большим весом и высокой плотностью.
- Мозаика. Мозаичные элементы могут быть керамическими стеклянными или акриловыми. Из подручных материалов подойдут яичная скорлупа, ракушки, камешки, деревянные спилы.
- Доски. Такое изделие легче всего изготовить самостоятельно. Для увеличения срока эксплуатации мебели используют шпунтованные доски.
По конструкции столы бывают стационарными и складными. Первые характеризуются массивностью и высокой ценой. Складные варианты легко сложить, переместить в необходимое место, они компактные и удобные. Этот вариант особенно удобен для небольшой кухни.
Древесно-стружечная плита
Древесноволокнистая плита
Массив дерева
Стекло
Камень
Мозаика
Доски
«Особенности» (trait) устройства Google Smart Home
Google использует особенности устройства для предоставления элементов пользовательского интерфейса управления вашими устройствами в Google, а также для создания коммуникационных шаблонов голосового управления. Некоторые из особенностей включают в себя следующие настройки: ColorSetting, Modes, OnOff, and StartStop. Мне потребовалось некоторое время, чтобы решить, какая особенность будет лучше всего работать в моём приложения, но позже я выбрал режимы.
Вы можете думать о режимах как о выпадающем списке, где выбирается одно из N предопределённых значений или, в моём случае, предустановки высоты. Я назвал свой режим «высота», а возможные значения — «предустановка один», «предустановка два» и «предустановка три». Это позволяет мне управлять своим столом, говоря: «Эй, Google, установите высоту моего стола в предустановку один», — и Google отправит соответствующий запрос на выполнение в мою систему. Вы можете прочитать больше об особенностях устройств Google здесь.
Материалы и инструменты для работы
Мастеру необходимо приготовить следующий набор:
- Электрический лобзик.
- Дрель.
- Крепежные детали (саморезы, шурупы, гвозди, металлические уголки).
- Составы для пропитки древесины.
- Морилка, акриловый лак для декорирования поверхностей.
- Строительный карандаш.
- Рулетка, уровень.
Для выдвижных систем и полок необходимо подобрать дополнительную фурнитуру (пазы, ролики для выдвижной панели).
Проект в деле
Наконец, Google Smart Home и мой компьютер начали общаться. До этого для локального запуска сервера Express я использовал ngrok. Теперь, когда мой сервер наконец заработал достаточно хорошо, пришло время сделать его доступным для Google в любое время. Значит, нужно было разместить приложение на Heroku — это поставщик PaaS, упрощающий развёртывание и управление приложениями.
Одно из главных преимуществ Heroku — режим дополнений. С дополнениями очень просто добавить CloudMQTT и сервер Postgres для приложения. Ещё одно преимущество использования Heroku — простота сборки и развёртывания. Heroku автоматически определяет, какой код вы используете, и создаёт/развёртывает его для вас. Вы можете найти более подробную информацию об этом, прочитав о Heroku Buildpacks. В моём случае всякий раз, когда я отправляю код в git remote Heroku, он устанавливает все мои пакеты, удаляет все зависимости разработки и развёртывает приложение, и это всё простой командой «git push heroku main».
Всего в несколько кликов CloudMQTT и Postgres стали доступны моему приложению, и мне нужно было использовать только несколько переменных среды, чтобы интегрировать эти сервисы с моим приложением. Heroku не потребовал денег. Однако CloudMQTT — сторонним дополнение за $5 в месяц.
Я считаю, что необходимость в Postgres не нуждается в комментариях, но CloudMQTT заслуживает больше внимания.
Существующие разновидности
Принципиально все подобные столы одинаковы: основание, ножки с функцией регулировки по высоте и столешница. Тем не менее различий довольно много и некоторые весьма значимые.
Удобство достигается прежде всего соответствием параметров мебели характеристикам телосложения человека. Добиться этого помогает регулируемый стол.
Существует ряд критериев, по которым можно определить разновидность стола:
- Способ регулировки. Механический или при помощи электромотора.
- Материал столешницы. Стекло, пластик, дерево.
- Форма. Прямоугольный, круглый, угловой.
- Предназначение. Детский, письменный, компьютерный, офисный.
- Опции. Крепления для монитора, кабель-менеджмент, пульт, наличие розеток.
Дополнительная информация! Наиболее простым (и дешевым) является стол с ручным изменением высоты. Наличие автоматического подъемника в разы удорожает конструкцию, поэтому следует тщательно все взвесить, прежде чем отправляться в магазин!
Внешне трансформер представляет из себя регулируемое основание и различные по форме, дизайну и цвету столешницы.
Из Интернета в частную сеть. Сложный способ
Есть несколько способов предоставить доступ к приложению или, в моём случае, устройству Интернета вещей. Первый — открыть порт в моей домашней сети, чтобы вывести устройство в Интернет. В этом случае моё приложение Heroku Express отправит запрос на моё устройство, используя публичный IP-адрес. Это потребовало бы от меня иметь публичный статический IP-адрес, а также статический IP-адрес для ESP32. ESP32 также должен был бы действовать как HTTP-сервер и всё время слушать инструкции от Heroku. Это большие накладные расходы для устройства, получающего инструкции несколько раз в день.
Второй способ называется «дырокол». С ним вы можете задействовать сторонний внешний сервер для доступа устройства в Интернет без необходимости переадресации портов. Ваше устройство в основном подключается к серверу, который устанавливает открытый порт. Затем другая служба может подключиться непосредственно к вашему внутреннему устройству, получив открытый порт от внешнего сервера. Наконец, он подключается непосредственно к устройству, используя этот открытый порт. Подход может быть правильным или не совсем правильным: я прочитал о нём только часть статьи.
Внутри «дырокола» происходит многое, и я не до конца понимаю происходящее. Однако, если вам интересно, есть несколько интересных статей, объясняющих больше. Вот две статьи, которые я прочитал, чтобы лучше понять «дырокол»: Википедия и статья из MIT, написанная Брайаном Фордом и другими.
Из Интернета в частную сеть через IoT
Я не был очень доволен этими решениями. Я подключил много смарт-устройств в дом, и мне никогда не приходилось открывать порт на маршрутизаторе, так что переадресации портов не было. Кроме того, пробивка дыр кажется гораздо более сложной, чем то, что я ищу, и лучше подходит для сетей P2P. В результате дальнейших исследований я обнаружил MQTT и узнал, что это протокол для IoT. Он обладает некоторыми преимуществами, такими как низкое энергопотребление, настраиваемая отказоустойчивость, и не требует переадресации портов. MQTT — протокол типа издатель/подписчик, это означает, что стол — подписчик определённого топика, а приложение Heroku — издатель этого топика.
Таким образом, Google связывается с Heroku, этот запрос анализируется, чтобы определить запрошенное устройство и его новое состояние или режим. Затем приложение Heroku публикует сообщение на сервере CloudMQTT, развёрнутом как надстройка на Heroku, с указанием столу перейти к новой предустановке. Наконец, стол подписывается на топик и получает сообщение, опубликованное приложением Heroku, наконец, стол настраивает свою высоту в соответствии с запросом! В файле googleactionsapp вы заметите, что есть функция updateHeight, которая публикует один номер в топике MQTT для определённого идентификатора устройства. Вот так приложение 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
; } 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 для получения команд!
Рекомендации по выбору
Поскольку ассортимент угловых рабочих столов достаточно широк, покупатель может попросту растеряться. Поэтому, чтобы сделать правильный выбор и приобрести действительно качественную вещь, которая будет удобна в эксплуатации и подойдет к интерьеру, нужно следовать некоторым правилам.
1. Внешний вид стола играет не последнюю роль, но все же при выборе в первую очередь следует обращать внимание на качество его материалов. Самыми прочными и долговечными считаются изделия из массива дерева, но их стоимость довольно высока. Наиболее доступные и практичные столы из ДСП или МДФ, к тому же они выглядят не хуже моделей из натуральной древесины. Важно, чтобы поверхность имела защитное покрытие, все торцы должны быть обработаны специальной лентой, а крепежные элементы надежно привинчены и не болтаться.
2. Определить надежность мебели всегда можно по качеству фурнитуры и подвижных элементов. Добросовестные производители таким аспектам уделяют особое внимание, поскольку от них зависит не только внешний вид стола, но и его функциональность. Фурнитура должна быть тщательно подобрана, прочно закреплена, выполнена в одинаковом стиле и цветовой гамме. Подвижные элементы ящиков и полочек должны работать плавно и бесшумно, без заеданий и прикладывания больших усилий.
3. Прежде чем выбирать угловой письменный стол, необходимо произвести замеры помещения. В противном случае он будет мешать свободному передвижению по комнате либо вовсе не поместится на отведенной ему площади. Рекомендуется замерять угол для стола с небольшим припуском.
4. Дизайн мебели может быть любым. Довольно популярны столы с плавными закругленными формами, поскольку они выглядят более изящно, в отличие от моделей с прямыми строгими линиями. Цвет изделия следует выбирать в зависимости от палитры общего интерьера помещения. Универсальным вариантом является светлое дерево или его имитация.
Помимо всего прочего, угловой письменный стол должен быть удобным, поэтому перед покупкой рекомендуется сесть за него, чтобы убедиться в его комфортабельности. Все параметры предмета мебели, а именно высота, длина, ширина и количество полок, должны подходить для человека, который будет постоянно им пользоваться.
Последние заметки
Последняя конечная точка, о которой я не упоминал, — конечная точка / healthz. Это связано с тем, что Google ожидает, довольно быстрого ответа, и загрузка приложения Heroku при каждом запросе в моём случае не работает. Я установил службу ping для проверки связи с конечной точкой /healthz каждую минуту, чтобы служба оставалась работоспособной и была готова ответить. Если вы планируете сделать что-то подобное, помните, что на это будут израсходованы все бесплатные часы на стенде. Сейчас всё нормально: это единственное используемое на Heroku приложение. Кроме того, за 7 долларов в месяц вы можете перейти на тарифный план Heroku’s Hobby с поддержкой постоянной работы приложения.
Создание устройства IoT связано с большими накладными расходами в начале. Я сконструировал оборудование, построил схему управления, настроил сервер MQTT, написал сервер Express OAuth2 и научился взаимодействовать с Google Smart Home через действия. Первоначальные накладные расходы были огромными, но я чувствую, что многого добился! Не говоря уже о том, что сервер MQTT, сервер приложений Express OAuth2 и Google Smart Home Actions можно использовать для другого проекта. Умные дома мне интересны, и я могу попытаться расширить свой репертуар IoT-устройств, включив в него датчики, отслеживающие происходящее вокруг моего дома и сообщающее об этом через MQTT. Датчики для мониторинга почвы, температуры и датчики света будет очень интересно мониторить и анализировать.
Что дальше?
Высота столешницы сейчас измеряется в лучшем случае ненадёжно. Я использую в целом работающим инфракрасным датчиком расстояния TFMini-S. Замечено, что высота стола немного меняется в течение дня, когда меняется окружающее освещение в комнате. Я заказал датчик угла поворота, чтобы подсчитать обороты стержня, проходящего через стол. Это должно дать мне движения точнее в любое время дня. У меня также есть доступ к серверу, который я размещаю в подвале. На нём я могу исследовать собственный сервер Mosquitto MQTT, Node-RED и Express-приложения OAuth2, если захочу хостить что-то сам. Наконец, сейчас вся электроника лежит прямо на моём столе. Я планирую организовать устройства так, чтобы все было красиво и аккуратно!
Спасибо, что прочитали статью! Для удобства даю все ссылки.
- Torque Calculator
- 90 degree right angle gear box
- BLE Terminal
- Platform.IO
- TFMini-S Arduino Driver
- Google Smart Home Actions
- Node OAuth2 Server
- Express OAuth2 Server
- ESP32 IoT Desk Server model.js
- ESP32 IoT Desk Server index.js
- ESP32 IoT Desk Server google_actions.js
- Google Smart Home Device Traits
- NGROK
- ESP32 IoT Desk Firmware
- Node-RED
- Heroku
- Heroku Hobby Plan
- Heroku Buildpacks
- Wikipedia Hole Punching
- MIT Paper on Hole Punching by Bryan Ford et al.
- C++ разработчик
Eще курсы
- Обучение профессии Data Science
- Обучение профессии Data Analyst
- Профессия Этичный хакер
- Frontend-разработчик
- Профессия Веб-разработчик
- Курс «Python для веб-разработки»
- Продвинутый курс «Machine Learning Pro + Deep Learning»
- Курс по Machine Learning
- Курс «Математика и Machine Learning для Data Science»
- Разработчик игр на Unity
- Курс по JavaScript
- Профессия Java-разработчик
- Курс по аналитике данных
- Курс по DevOps
- Профессия iOS-разработчик с нуля
- Профессия Android-разработчик с нуля