{"id":465188,"date":"2025-06-30T15:00:18","date_gmt":"2025-06-30T15:00:18","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=465188"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=465188","title":{"rendered":"<span>\u0423\u043d\u0438\u0432\u0435\u0440\u0441\u0430\u043b\u044c\u043d\u044b\u0439 \u0431\u043e\u043a\u0441 \u0434\u043b\u044f \u0434\u0440\u043e\u043d\u0430<\/span>"},"content":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<p><strong>\u041f\u0440\u0435\u0434\u0438\u0441\u043b\u043e\u0432\u0438\u0435<\/strong><\/p>\n<p>\u0414\u0430\u043d\u043d\u0430\u044f \u0441\u0442\u0430\u0442\u044c\u044f \u044d\u0442\u043e \u0440\u0430\u0441\u0441\u043a\u0430\u0437 \u043e\u0431 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u0439 \u0447\u0430\u0441\u0442\u0438 \u043c\u043e\u0435\u0433\u043e \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u043f\u043e \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044e \u0441\u0438\u0441\u0442\u0435\u043c\u044b \u0434\u043e\u0441\u0442\u0430\u0432\u043a\u0438 \u0434\u0440\u043e\u043d\u0430\u043c\u0438. \u0421\u0438\u0441\u0442\u0435\u043c\u0430 \u0441\u043e\u0432\u0441\u0435\u043c \u0432 \u0440\u0430\u043d\u043d\u0435\u0439 \u0441\u0442\u0430\u0434\u0438\u0438 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438. \u041d\u043e \u0432 \u043f\u0440\u0438\u043d\u0446\u0438\u043f\u0435 \u044d\u0442\u0430 \u0447\u0430\u0441\u0442\u044c \u0433\u043e\u0442\u043e\u0432\u0430 \u0438 \u0435\u0441\u043b\u0438 \u043a\u043e\u043c\u0443 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u043e \u043c\u043e\u0436\u0435\u0442 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0432 \u0441\u0432\u043e\u0438\u0445 \u043f\u0440\u043e\u0435\u043a\u0442\u043e\u0432. \u0415\u0441\u043b\u0438 \u0431\u0443\u0434\u0435\u0442 \u0437\u0430\u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043e\u0432\u0430\u043d\u043d\u043e\u0441\u0442\u044c \u043c\u043e\u0433\u0443 \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0438\u0442\u044c \u043f\u0443\u0431\u043b\u0438\u043a\u043e\u0432\u0430\u0442\u044c \u0447\u0435\u0440\u0442\u0435\u0436\u0438, \u0441\u0445\u0435\u043c\u044b \u0438 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u043d\u044b\u0439 \u043a\u043e\u0434.<\/p>\n<h4>\u0412\u0432\u0435\u0434\u0435\u043d\u0438\u0435<\/h4>\n<p>\u0421 \u0440\u043e\u0441\u0442\u043e\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u0434\u0440\u043e\u043d\u043e\u0432 \u0432 \u043b\u043e\u0433\u0438\u0441\u0442\u0438\u043a\u0435 \u0438 \u0442\u0435\u0445\u043d\u0438\u0447\u0435\u0441\u043a\u043e\u043c \u043e\u0431\u0441\u043b\u0443\u0436\u0438\u0432\u0430\u043d\u0438\u0438 \u0440\u0430\u0441\u0442\u0435\u0442 \u043f\u043e\u0442\u0440\u0435\u0431\u043d\u043e\u0441\u0442\u044c \u0432 \u0443\u043d\u0438\u0432\u0435\u0440\u0441\u0430\u043b\u044c\u043d\u044b\u0445 \u043c\u043e\u0434\u0443\u043b\u044f\u0445 \u0434\u043b\u044f \u043f\u0435\u0440\u0435\u0432\u043e\u0437\u043a\u0438 \u0433\u0440\u0443\u0437\u043e\u0432 \u0438 \u0441\u043c\u0435\u043d\u043d\u044b\u0445 \u0430\u043a\u043a\u0443\u043c\u0443\u043b\u044f\u0442\u043e\u0440\u043e\u0432. \u0414\u043b\u044f \u0440\u0435\u0448\u0435\u043d\u0438\u044f \u044d\u0442\u043e\u0439 \u0437\u0430\u0434\u0430\u0447\u0438 \u0431\u044b\u043b \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0430\u043d\u00a0<strong>\u0438\u043d\u0442\u0435\u043b\u043b\u0435\u043a\u0442\u0443\u0430\u043b\u044c\u043d\u044b\u0439 \u0431\u043e\u043a\u0441<\/strong>, \u0443\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u043c\u044b\u0439 \u0443\u0434\u0430\u043b\u0451\u043d\u043d\u043e \u0447\u0435\u0440\u0435\u0437 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440 \u043d\u0430 \u0431\u0430\u0437\u0435\u00a0<strong>ESP8266<\/strong>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0441\u043f\u043e\u0441\u043e\u0431\u0435\u043d:<\/p>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/0c1\/ae8\/994\/0c1ae8994a7a6421b469541df2ae76a3.png\" alt=\"\u041e\u0431\u0449\u0430\u044f \u0441\u0445\u0435\u043c\u0430. \u0424\u043b\u0430\u0448\u043a\u0438 \u0444\u0438\u043a\u0441\u0430\u0446\u0438\u0438 \u0431\u0443\u0434\u0443\u0442 \u0441 \u043e\u0431\u043e\u0438\u0445 \u0441\u0442\u043e\u0440\u043e\u043d \u0438 \u0441\u0435\u0440\u0432\u043e\u043f\u0440\u0438\u0432\u043e\u0434 \u0431\u0443\u0434\u0435\u0442 \u043f\u043e\u0441\u0435\u0440\u0435\u0434\u0438\u043d\u0435. \u0422\u0430\u043a \u0436\u0435 \u043d\u0435 \u043f\u043e\u043a\u0430\u0437\u0430\u043d\u043d\u044b \u043a\u043e\u043d\u0446\u0435\u0432\u0438\u043a\u0438.\" width=\"911\" height=\"859\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/0c1\/ae8\/994\/0c1ae8994a7a6421b469541df2ae76a3.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/0c1\/ae8\/994\/0c1ae8994a7a6421b469541df2ae76a3.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption>\u041e\u0431\u0449\u0430\u044f \u0441\u0445\u0435\u043c\u0430. \u0424\u043b\u0430\u0448\u043a\u0438 \u0444\u0438\u043a\u0441\u0430\u0446\u0438\u0438 \u0431\u0443\u0434\u0443\u0442 \u0441 \u043e\u0431\u043e\u0438\u0445 \u0441\u0442\u043e\u0440\u043e\u043d \u0438 \u0441\u0435\u0440\u0432\u043e\u043f\u0440\u0438\u0432\u043e\u0434 \u0431\u0443\u0434\u0435\u0442 \u043f\u043e\u0441\u0435\u0440\u0435\u0434\u0438\u043d\u0435. \u0422\u0430\u043a \u0436\u0435 \u043d\u0435 \u043f\u043e\u043a\u0430\u0437\u0430\u043d\u043d\u044b \u043a\u043e\u043d\u0446\u0435\u0432\u0438\u043a\u0438.<\/figcaption><\/div>\n<\/figure>\n<ul>\n<li>\n<p>\ud83d\udce6 \u043e\u0442\u043a\u0440\u044b\u0432\u0430\u0442\u044c \u0438 \u0437\u0430\u043a\u0440\u044b\u0432\u0430\u0442\u044c \u043e\u0442\u0441\u0435\u043a \u0434\u043b\u044f \u0433\u0440\u0443\u0437\u0430;<\/p>\n<\/li>\n<li>\n<p>\ud83d\udd0b \u043e\u0442\u043a\u0440\u044b\u0432\u0430\u0442\u044c \u0438 \u0437\u0430\u043a\u0440\u044b\u0432\u0430\u0442\u044c \u043e\u0442\u0441\u0435\u043a \u0434\u043b\u044f \u0441\u043c\u0435\u043d\u043d\u043e\u0433\u043e \u0430\u043a\u043a\u0443\u043c\u0443\u043b\u044f\u0442\u043e\u0440\u0430;<\/p>\n<\/li>\n<li>\n<p>\ud83d\udce1 \u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u0442\u044c \u0442\u0435\u043b\u0435\u043c\u0435\u0442\u0440\u0438\u044e \u043e \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0438 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430;<\/p>\n<\/li>\n<li>\n<p>\u2705 \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0442\u044c \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u0447\u0435\u0440\u0435\u0437 WebSocket-\u0441\u0435\u0440\u0432\u0435\u0440.<\/p>\n<\/li>\n<\/ul>\n<h4>\u0410\u043f\u043f\u0430\u0440\u0430\u0442\u043d\u0430\u044f \u0447\u0430\u0441\u0442\u044c<\/h4>\n<p>\u0423\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u043e \u043f\u043e\u0441\u0442\u0440\u043e\u0435\u043d\u043e \u043d\u0430 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u0435\u00a0<strong>ESP8266<\/strong>\u00a0(\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, ESP-01 \u0438\u043b\u0438 NodeMCU) \u0438 \u0432\u043a\u043b\u044e\u0447\u0430\u0435\u0442 \u0432 \u0441\u0435\u0431\u044f:<\/p>\n<ul>\n<li>\n<p><strong>2 \u0441\u0435\u0440\u0432\u043e\u043f\u0440\u0438\u0432\u043e\u0434\u0430<\/strong>:<br \/>Servo1 \u2014 \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u043a\u0440\u044b\u0448\u043a\u043e\u0439 \u0433\u0440\u0443\u0437\u043e\u0432\u043e\u0433\u043e \u043e\u0442\u0441\u0435\u043a\u0430.<br \/>Servo2 \u2014 \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u043a\u0440\u044b\u0448\u043a\u043e\u0439 \u043e\u0442\u0441\u0435\u043a\u0430 \u0430\u043a\u043a\u0443\u043c\u0443\u043b\u044f\u0442\u043e\u0440\u0430.<\/p>\n<\/li>\n<li>\n<p><strong>2 \u043a\u043e\u043d\u0446\u0435\u0432\u044b\u0445 \u043f\u0435\u0440\u0435\u043a\u043b\u044e\u0447\u0430\u0442\u0435\u043b\u044f<\/strong>:<br \/>Button1 \u2014 \u043d\u0430\u043b\u0438\u0447\u0438\u0435 \u0433\u0440\u0443\u0437\u0430 \u0432 \u0431\u043e\u043a\u0441\u0435.<br \/>Button2 \u2014 \u043d\u0430\u043b\u0438\u0447\u0438\u0435 \u0430\u043a\u043a\u0443\u043c\u0443\u043b\u044f\u0442\u043e\u0440\u0430.<\/p>\n<\/li>\n<li>\n<p><strong>\u0421\u0432\u0435\u0442\u043e\u0434\u0438\u043e\u0434<\/strong>: \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0434\u043b\u044f \u0438\u043d\u0434\u0438\u043a\u0430\u0446\u0438\u0438 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f.<\/p>\n<\/li>\n<\/ul>\n<h4>\u0421\u0435\u0442\u044c \u0438 \u0441\u0432\u044f\u0437\u044c<\/h4>\n<p>\u041a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0430\u0435\u0442\u0441\u044f \u043a \u0437\u0430\u0434\u0430\u043d\u043d\u043e\u0439 Wi-Fi-\u0441\u0435\u0442\u0438 \u0438 \u0443\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u0442 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0435 \u0441\u00a0<strong>WebSocket-\u0441\u0435\u0440\u0432\u0435\u0440\u043e\u043c<\/strong>. \u042d\u0442\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u0443 \u0434\u0440\u043e\u043d\u0430 \u0438\u043b\u0438 \u043b\u043e\u0433\u0438\u0441\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u0439 \u0441\u0438\u0441\u0442\u0435\u043c\u0435 \u0443\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c \u0431\u043e\u043a\u0441\u043e\u043c \u0432 \u0440\u0435\u0436\u0438\u043c\u0435 \u0440\u0435\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u0438.<\/p>\n<p><strong>\u0421\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f<\/strong>\u00a0\u0432\u0438\u0437\u0443\u0430\u043b\u0438\u0437\u0438\u0440\u0443\u044e\u0442\u0441\u044f \u0447\u0435\u0440\u0435\u0437 \u0432\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u044b\u0439 \u0441\u0432\u0435\u0442\u043e\u0434\u0438\u043e\u0434:<\/p>\n<ul>\n<li>\n<p>\u2734\ufe0f \u0411\u044b\u0441\u0442\u0440\u043e \u043c\u0438\u0433\u0430\u0435\u0442 \u2014 \u043d\u0435\u0442 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f \u043a Wi-Fi.<\/p>\n<\/li>\n<li>\n<p>\u23f3 \u041c\u0435\u0434\u043b\u0435\u043d\u043d\u043e \u043c\u0438\u0433\u0430\u0435\u0442 \u2014 Wi-Fi \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d, WebSocket \u043d\u0435\u0442.<\/p>\n<\/li>\n<li>\n<p>\u2705 \u041f\u043e\u0441\u0442\u043e\u044f\u043d\u043d\u043e \u0433\u043e\u0440\u0438\u0442 \u2014 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0435 WebSocket \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u043e.<\/p>\n<\/li>\n<\/ul>\n<h4>\u041f\u0440\u0438\u043d\u0446\u0438\u043f \u0440\u0430\u0431\u043e\u0442\u044b<\/h4>\n<p>\u041f\u043e\u0441\u043b\u0435 \u0432\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u043e:<\/p>\n<ol>\n<li>\n<p>\u041f\u043e\u0434\u043a\u043b\u044e\u0447\u0430\u0435\u0442\u0441\u044f \u043a Wi-Fi.<\/p>\n<\/li>\n<li>\n<p>\u041f\u0435\u0440\u0438\u043e\u0434\u0438\u0447\u0435\u0441\u043a\u0438 \u043f\u044b\u0442\u0430\u0435\u0442\u0441\u044f \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c WebSocket-\u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0435.<\/p>\n<\/li>\n<li>\n<p>\u041f\u043e\u0441\u043b\u0435 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442 \u0434\u0430\u043d\u043d\u044b\u0435 \u043e\u0431 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0435 (\u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440 \u0438 \u043f\u0430\u0440\u043e\u043b\u044c).<\/p>\n<\/li>\n<li>\n<p>\u041e\u0436\u0438\u0434\u0430\u0435\u0442 \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u043e\u0442 \u0441\u0435\u0440\u0432\u0435\u0440\u0430 \u0438 \u0440\u0435\u0430\u0433\u0438\u0440\u0443\u0435\u0442 \u043d\u0430 \u043d\u0438\u0445.<\/p>\n<\/li>\n<\/ol>\n<h4>\u041e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u043a\u043e\u043c\u0430\u043d\u0434<\/h4>\n<p>\u041f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u044e\u0442\u0441\u044f \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u043a\u043e\u043c\u0430\u043d\u0434\u044b:<\/p>\n<ul>\n<li>\n<p>&#171;servo1&#187; \u2014 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u0443\u0433\u043e\u043b \u043e\u0442\u043a\u0440\u044b\u0442\u0438\u044f \u0433\u0440\u0443\u0437\u043e\u0432\u043e\u0433\u043e \u043e\u0442\u0441\u0435\u043a\u0430.<\/p>\n<\/li>\n<li>\n<p>&#171;servo2&#187; \u2014 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u0443\u0433\u043e\u043b \u043e\u0442\u043a\u0440\u044b\u0442\u0438\u044f \u0430\u043a\u043a\u0443\u043c\u0443\u043b\u044f\u0442\u043e\u0440\u043d\u043e\u0433\u043e \u043e\u0442\u0441\u0435\u043a\u0430.<\/p>\n<\/li>\n<li>\n<p>&#171;reboot&#187; \u2014 \u043f\u0435\u0440\u0435\u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0430 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430.<\/p>\n<\/li>\n<\/ul>\n<h4>\u0422\u0435\u043b\u0435\u043c\u0435\u0442\u0440\u0438\u044f<\/h4>\n<p>\u0423\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u043e \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442 \u0442\u0435\u043b\u0435\u043c\u0435\u0442\u0440\u0438\u044e \u043f\u043e \u043a\u043e\u043c\u0430\u043d\u0434\u0435 &#171;PING&#187;:<\/p>\n<ul>\n<li>\n<p>\u0421\u0442\u0430\u0442\u0443\u0441 &#171;\u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442&#187;,<\/p>\n<\/li>\n<li>\n<p>\u0423\u0433\u043b\u044b \u043e\u0431\u043e\u0438\u0445 \u0441\u0435\u0440\u0432\u043e\u043f\u0440\u0438\u0432\u043e\u0434\u043e\u0432,<\/p>\n<\/li>\n<li>\n<p>\u0421\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u043e\u0431\u043e\u0438\u0445 \u043a\u043e\u043d\u0446\u0435\u0432\u0438\u043a\u043e\u0432 (&#171;pressed&#187; \u0438\u043b\u0438 &#171;released&#187;).<\/p>\n<\/li>\n<\/ul>\n<h4>\u041a\u043d\u043e\u043f\u043a\u0438 (\u043a\u043e\u043d\u0446\u0435\u0432\u0438\u043a\u0438)<\/h4>\n<p>\u041a\u043e\u043d\u0446\u0435\u0432\u0438\u043a\u0438 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u044b \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u043d\u043e\u0433\u043e \u043a\u043b\u0430\u0441\u0441\u0430 Button. \u0421\u0438\u0441\u0442\u0435\u043c\u0430 \u043e\u0442\u0441\u043b\u0435\u0436\u0438\u0432\u0430\u0435\u0442 \u0438\u0445 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f \u0438 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f \u043f\u0440\u0438 \u043d\u0430\u0436\u0430\u0442\u0438\u0438 \u0438\u043b\u0438 \u043f\u043e \u0442\u0430\u0439\u043c\u0435\u0440\u0443 (\u0440\u0430\u0437 \u0432 \u0441\u0435\u043a\u0443\u043d\u0434\u0443), \u0435\u0441\u043b\u0438 WebSocket-\u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0435 \u0430\u043a\u0442\u0438\u0432\u043d\u043e.<\/p>\n<h4>\u041f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u043d\u0430\u044f \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0430<\/h4>\n<p>\u041a\u043b\u044e\u0447\u0435\u0432\u044b\u0435 \u0442\u0435\u0445\u043d\u043e\u043b\u043e\u0433\u0438\u0438:<\/p>\n<ul>\n<li>\n<p><strong>ESP8266WiFi<\/strong>\u00a0\u2014 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 \u043a \u0441\u0435\u0442\u0438.<\/p>\n<\/li>\n<li>\n<p><strong>WebSocketsClient<\/strong>\u00a0\u2014 \u0434\u0432\u0443\u0441\u0442\u043e\u0440\u043e\u043d\u043d\u044f\u044f \u0441\u0432\u044f\u0437\u044c \u0441 \u0441\u0435\u0440\u0432\u0435\u0440\u043e\u043c.<\/p>\n<\/li>\n<li>\n<p><strong>ArduinoJson<\/strong>\u00a0\u2014 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430 JSON-\u043a\u043e\u043c\u0430\u043d\u0434 \u0438 \u0442\u0435\u043b\u0435\u043c\u0435\u0442\u0440\u0438\u0438.<\/p>\n<\/li>\n<li>\n<p><strong>Servo<\/strong>\u00a0\u2014 \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0441\u0435\u0440\u0432\u043e\u043f\u0440\u0438\u0432\u043e\u0434\u0430\u043c\u0438.<\/p>\n<\/li>\n<li>\n<p><strong>\u041a\u0430\u0441\u0442\u043e\u043c\u043d\u044b\u0439 \u043a\u043b\u0430\u0441\u0441 Button<\/strong>\u00a0\u2014 \u043f\u0440\u043e\u0441\u0442\u0430\u044f \u043b\u043e\u0433\u0438\u043a\u0430 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0439 \u043a\u043d\u043e\u043f\u043e\u043a.<\/p>\n<\/li>\n<\/ul>\n<h4>\u041f\u0440\u0438\u043c\u0435\u043d\u0435\u043d\u0438\u0435<\/h4>\n<p>\u0422\u0430\u043a\u0430\u044f \u0441\u0438\u0441\u0442\u0435\u043c\u0430 \u043c\u043e\u0436\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0432 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0445 \u0441\u043b\u0443\u0447\u0430\u044f\u0445:<\/p>\n<ul>\n<li>\n<p>\ud83d\udce6\u00a0<strong>\u0414\u043e\u0441\u0442\u0430\u0432\u043a\u0430 \u043c\u0430\u043b\u044b\u0445 \u0433\u0440\u0443\u0437\u043e\u0432<\/strong>: \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u043e\u0442\u043a\u0440\u044b\u0442\u044c \u043e\u0442\u0441\u0435\u043a \u0434\u043b\u044f \u0432\u044b\u0433\u0440\u0443\u0437\u043a\u0438.<\/p>\n<\/li>\n<li>\n<p>\ud83d\udd0b\u00a0<strong>\u041e\u0431\u0441\u043b\u0443\u0436\u0438\u0432\u0430\u043d\u0438\u0435 \u0434\u0440\u043e\u043d\u043e\u0432<\/strong>: \u0431\u044b\u0441\u0442\u0440\u043e\u0435 \u0438\u0437\u0432\u043b\u0435\u0447\u0435\u043d\u0438\u0435 \u0438 \u0437\u0430\u043c\u0435\u043d\u0430 \u0430\u043a\u043a\u0443\u043c\u0443\u043b\u044f\u0442\u043e\u0440\u043e\u0432.<\/p>\n<\/li>\n<li>\n<p>\ud83d\udce1\u00a0<strong>\u041c\u043e\u043d\u0438\u0442\u043e\u0440\u0438\u043d\u0433 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f<\/strong>: \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440 \u0432\u0441\u0435\u0433\u0434\u0430 \u0437\u043d\u0430\u0435\u0442, \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u043b\u0438 \u0433\u0440\u0443\u0437 \u0438\u043b\u0438 \u0430\u043a\u043a\u0443\u043c\u0443\u043b\u044f\u0442\u043e\u0440 \u0432 \u0431\u043e\u043a\u0441\u0435.<\/p>\n<\/li>\n<\/ul>\n<p>\u0422\u0430\u043a \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 \u043d\u0430 \u043f\u0440\u0430\u043a\u0442\u0438\u043a\u0435 <\/p>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/ba4\/39d\/b97\/ba439db979f569c1d599411dbc047bb3.png\" width=\"960\" height=\"1280\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/ba4\/39d\/b97\/ba439db979f569c1d599411dbc047bb3.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/ba4\/39d\/b97\/ba439db979f569c1d599411dbc047bb3.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<p>\u041a\u0443\u0434\u0430 \u0447\u0442\u043e \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0430\u0442\u044c \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u043d\u044f\u0442\u044c \u0438\u0437 \u043f\u0440\u043e\u0448\u0438\u0432\u043a\u0438. <\/p>\n<h4>\u041a\u043e\u0434 \u0434\u043b\u044f \u043f\u0440\u043e\u0448\u0438\u0432\u043a\u0438.<\/h4>\n<p>#include &lt;ESP8266WiFi.h&gt;<br \/>#include &lt;WebSocketsClient.h&gt;<br \/>#include &lt;ArduinoJson.h&gt;<br \/>#include &lt;Servo.h&gt;<br \/>#include &#171;Button.h&#187; \/\/ \u041f\u043e\u0434\u043a\u043b\u044e\u0447\u0430\u0435\u043c \u043d\u0430\u0448 \u043a\u043b\u0430\u0441\u0441 Button<\/p>\n<p>const char* ssid = &#171;&#8212;-&#171;;<br \/>const char* password = &#171;&#8212;&#8212;&#171;;<\/p>\n<p>WebSocketsClient webSocket;<\/p>\n<p>const char* deviceName = &#171;esp01&#187;;<br \/>const char* devicePassword = &#171;1234&#187;;<\/p>\n<p>const int LED_PIN = LED_BUILTIN;<br \/>const int BUTTON1_PIN = 14; \/\/ GPIO14 (D5 \u043d\u0430 NodeMCU)<br \/>const int BUTTON2_PIN = 4; \/\/ GPIO4 (D2 \u043d\u0430 NodeMCU)<br \/>const int SERVO1_PIN = 12; \/\/ \u041f\u0438\u043d \u043f\u0435\u0440\u0432\u043e\u0433\u043e \u0441\u0435\u0440\u0432\u043e\u043f\u0440\u0438\u0432\u043e\u0434\u0430 (D6)<br \/>const int SERVO2_PIN = 13; \/\/ \u041f\u0438\u043d \u0432\u0442\u043e\u0440\u043e\u0433\u043e \u0441\u0435\u0440\u0432\u043e\u043f\u0440\u0438\u0432\u043e\u0434\u0430 (D7)<br \/>Button button1(BUTTON1_PIN);<br \/>Button button2(BUTTON2_PIN);<\/p>\n<p>Servo servo1;<br \/>Servo servo2;<\/p>\n<p>unsigned long previousMillis = 0;<br \/>unsigned long lastConnectionAttempt = 0;<br \/>const long connectionInterval = 10000; \/\/ 10 \u0441\u0435\u043a\u0443\u043d\u0434 \u043c\u0435\u0436\u0434\u0443 \u043f\u043e\u043f\u044b\u0442\u043a\u0430\u043c\u0438 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f<\/p>\n<p>int ledState = LOW;<br \/>int connectionState = 0; \/\/ 0 &#8212; \u043d\u0435\u0442 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f, 1 &#8212; WiFi \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d, 2 &#8212; WebSocket \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d<br \/>int servo1Pos = 90; \/\/ \u0422\u0435\u043a\u0443\u0449\u0435\u0435 \u043f\u043e\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0441\u0435\u0440\u0432\u043e\u043f\u0440\u0438\u0432\u043e\u0434\u0430 1 (0-180)<br \/>int servo2Pos = 90; \/\/ \u0422\u0435\u043a\u0443\u0449\u0435\u0435 \u043f\u043e\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0441\u0435\u0440\u0432\u043e\u043f\u0440\u0438\u0432\u043e\u0434\u0430 2 (0-180)<\/p>\n<p>void updateLed() {<br \/>unsigned long currentMillis = millis();<br \/>unsigned long interval;<\/p>\n<p>switch(connectionState) {<br \/>case 0: \/\/ \u041d\u0435\u0442 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f &#8212; \u0431\u044b\u0441\u0442\u0440\u043e\u0435 \u043c\u0438\u0433\u0430\u043d\u0438\u0435 (500ms)<br \/>interval = 500;<br \/>break;<br \/>case 1: \/\/ WiFi \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d &#8212; \u043c\u0435\u0434\u043b\u0435\u043d\u043d\u043e\u0435 \u043c\u0438\u0433\u0430\u043d\u0438\u0435 (1000ms)<br \/>interval = 1000;<br \/>break;<br \/>case 2: \/\/ WebSocket \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d &#8212; \u043f\u043e\u0441\u0442\u043e\u044f\u043d\u043d\u043e \u0432\u043a\u043b\u044e\u0447\u0435\u043d<br \/>digitalWrite(LED_PIN, LOW);<br \/>return;<br \/>}<\/p>\n<p>if (currentMillis &#8212; previousMillis &gt;= interval) {<br \/>previousMillis = currentMillis;<br \/>ledState = (ledState == LOW) ? HIGH : LOW;<br \/>digitalWrite(LED_PIN, ledState);<br \/>}<br \/>}<\/p>\n<p>void handleCommand(const char* cmd, const char* value) {<br \/>Serial.printf(&#171;Received command: %s, value: %s\\n&#187;, cmd, value);<\/p>\n<p>if (strcmp(cmd, &#171;servo1&#187;) == 0) {<br \/>int pos = atoi(value);<br \/>if (pos &gt;= 0 &amp;&amp; pos &lt;= 360) {<br \/>servo1Pos = pos;<br \/>servo1.write(servo1Pos);<br \/>Serial.printf(&#171;Servo1 set to %d\\n&#187;, servo1Pos);<br \/>}<br \/>}<br \/>else if (strcmp(cmd, &#171;servo2&#187;) == 0) {<br \/>int pos = atoi(value);<br \/>if (pos &gt;= 0 &amp;&amp; pos &lt;= 360) {<br \/>servo2Pos = pos;<br \/>servo2.write(servo2Pos);<br \/>Serial.printf(&#171;Servo2 set to %d\\n&#187;, servo2Pos);<br \/>}<br \/>}<br \/>else if (strcmp(cmd, &#171;reboot&#187;) == 0) {<br \/>Serial.println(&#171;Rebooting&#8230;&#187;);<br \/>ESP.restart();<br \/>}<br \/>}<\/p>\n<p>void webSocketEvent(WStype_t type, uint8_t* payload, size_t length) {<br \/>switch (type) {<br \/>case WStype_CONNECTED:<br \/>Serial.println(&#171;[WS] Connected&#187;);<br \/>connectionState = 2; \/\/ WebSocket \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d<br \/>updateLed();<\/p>\n<p>\/\/ \u041e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u043c \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043e\u0431 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0435 \u043f\u0440\u0438 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0438<br \/>{<br \/>StaticJsonDocument&lt;256&gt; doc;<br \/>doc[&#171;type&#187;] = &#171;auth&#187;;<br \/>doc[&#171;name&#187;] = deviceName;<br \/>doc[&#171;password&#187;] = devicePassword;<br \/>String json;<br \/>serializeJson(doc, json);<br \/>webSocket.sendTXT(json);<br \/>}<br \/>break;<\/p>\n<p>case WStype_DISCONNECTED:<br \/>Serial.println(&#171;[WS] Disconnected&#187;);<br \/>connectionState = (WiFi.status() == WL_CONNECTED) ? 1 : 0;<br \/>break;<\/p>\n<p>case WStype_TEXT:<br \/>Serial.printf(&#171;[WS] Received: %s\\n&#187;, payload);<br \/>\/\/Serial.printf(&#171;-%s-\\n&#187;, payload);<\/p>\n<p>\/\/ \u041e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430 PING<br \/>\/\/if (strstr((char*)payload, &#171;\\&#187;command\\&#187;:\\&#187;PING\\&#187;&#187;) != NULL) {<br \/>if (strstr((char*)payload, &#171;\\&#187;command\\&#187;: \\&#187;PING\\&#187;&#187;) != NULL) {<\/p>\n<p>Serial.println(&#171;Processing PING command&#187;);<br \/>StaticJsonDocument&lt;512&gt; doc;<br \/>doc[&#171;type&#187;] = &#171;telemetry&#187;;<br \/>doc[&#171;status&#187;] = &#171;\u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442&#187;;<br \/>doc[&#171;servo1&#187;] = servo1Pos;<br \/>doc[&#171;servo2&#187;] = servo2Pos;<br \/>doc[&#171;button1&#187;] = button1.isPressed() ? &#171;pressed&#187; : &#171;released&#187;;<br \/>doc[&#171;button2&#187;] = button2.isPressed() ? &#171;pressed&#187; : &#171;released&#187;;<br \/>String json;<br \/>serializeJson(doc, json);<br \/>webSocket.sendTXT(json);<br \/>Serial.println(&#171;\u0422\u0435\u043b\u0435\u043c\u0435\u0442\u0440\u0438\u044f \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0430&#187;);<br \/>}<br \/>\/\/ \u041e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u043a\u043e\u043c\u0430\u043d\u0434<br \/>else {<br \/>StaticJsonDocument&lt;256&gt; doc;<br \/>DeserializationError error = deserializeJson(doc, payload);<\/p>\n<p>Serial.print(&#171;Deserialization error: &#171;);<br \/>Serial.println(error.c_str()); \/\/ \u0412\u044b\u0432\u0435\u0434\u0435\u0442 &#171;Ok&#187; \u0435\u0441\u043b\u0438 \u043e\u0448\u0438\u0431\u043e\u043a \u043d\u0435\u0442<\/p>\n<p>\/\/ \u0412\u044b\u0432\u043e\u0434\u0438\u043c \u0441\u044b\u0440\u043e\u0439 payload \u0434\u043b\u044f \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438<br \/>Serial.print(&#171;Raw payload: &#171;);<br \/>Serial.println((char*)payload);<\/p>\n<p>\/\/ \u0412\u044b\u0432\u043e\u0434\u0438\u043c \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u0435 doc \u0432 Serial<br \/>Serial.println(&#171;Parsed JSON content:&#187;);<br \/>serializeJsonPretty(doc, Serial); \/\/ \u041a\u0440\u0430\u0441\u0438\u0432\u044b\u0439 \u0432\u044b\u0432\u043e\u0434 \u0441 \u043e\u0442\u0441\u0442\u0443\u043f\u0430\u043c\u0438<br \/>Serial.println(&#171;\\n&#8212;&#171;);<\/p>\n<p>if (!error &amp;&amp; doc.containsKey(&#171;command&#187;) &amp;&amp; doc.containsKey(&#171;value&#187;)) {<br \/>const char* cmd = doc[&#171;command&#187;];<br \/>const char* value = doc[&#171;value&#187;];<br \/>handleCommand(cmd, value);<\/p>\n<p>\/\/ \u041e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u043c \u043f\u043e\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043d\u0438\u0435<br \/>doc[&#171;type&#187;] = &#171;command_ack&#187;;<br \/>doc[&#171;status&#187;] = &#171;ok&#187;;<br \/>String json;<br \/>serializeJson(doc, json);<br \/>webSocket.sendTXT(json);<br \/>Serial.println(&#171;&#187;);<br \/>}<br \/>}<br \/>break;<br \/>}<br \/>}<\/p>\n<p>void setup() {<br \/>pinMode(LED_PIN, OUTPUT);<br \/>digitalWrite(LED_PIN, HIGH);<\/p>\n<p>pinMode(BUTTON1_PIN, INPUT_PULLUP);<br \/>pinMode(BUTTON2_PIN, INPUT_PULLUP);<\/p>\n<p>servo1.attach(SERVO1_PIN);<br \/>servo2.attach(SERVO2_PIN);<br \/>servo1.write(servo1Pos);<br \/>servo2.write(servo2Pos);<\/p>\n<p>Serial.begin(115200);<br \/>WiFi.begin(ssid, password);<\/p>\n<p>\/\/ \u041d\u0430\u0447\u0430\u043b\u044c\u043d\u043e\u0435 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 &#8212; \u043d\u0435\u0442 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f<br \/>connectionState = 0;<br \/>}<\/p>\n<p>void handleButtons() {<br \/>static unsigned long lastSend = 0;<\/p>\n<p>\/\/ \u041f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c \u043d\u0430\u0436\u0430\u0442\u0438\u044f<br \/>if (button1.click() <span class=\"habrahidden\"> button2.click() <\/span> millis() &#8212; lastSend &gt; 1000) {<br \/>if (webSocket.isConnected()) {<br \/>sendButtonStates();<br \/>lastSend = millis();<br \/>}<br \/>}<br \/>}<br \/>void sendButtonStates() {<br \/>StaticJsonDocument&lt;200&gt; doc;<br \/>doc[&#171;type&#187;] = &#171;button_state&#187;;<br \/>doc[&#171;button1&#187;] = button1.isPressed() ? &#171;pressed&#187; : &#171;released&#187;;<br \/>doc[&#171;button2&#187;] = button2.isPressed() ? &#171;pressed&#187; : &#171;released&#187;;<\/p>\n<p>String json;<br \/>serializeJson(doc, json);<br \/>webSocket.sendTXT(json);<br \/>}<\/p>\n<p>void loop() {<br \/>unsigned long currentMillis = millis();<\/p>\n<p>\/\/ \u041e\u0431\u043d\u043e\u0432\u043b\u044f\u0435\u043c \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f WiFi<br \/>if (WiFi.status() != WL_CONNECTED) {<br \/>connectionState = 0;<br \/>if (currentMillis &#8212; lastConnectionAttempt &gt;= connectionInterval) {<br \/>Serial.println(&#171;Connecting to WiFi&#8230;&#187;);<br \/>WiFi.begin(ssid, password);<br \/>lastConnectionAttempt = currentMillis;<br \/>}<br \/>}<br \/>else if (connectionState == 0) {<br \/>connectionState = 1;<br \/>Serial.println(&#171;\\nWiFi connected&#187;);<br \/>Serial.print(&#171;IP address: &#171;);<br \/>Serial.println(WiFi.localIP());<br \/>}<\/p>\n<p>updateLed();<br \/>handleButtons();<br \/>webSocket.loop();<\/p>\n<p>\/\/ \u0415\u0441\u043b\u0438 WiFi \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d, \u043d\u043e WebSocket \u0435\u0449\u0435 \u043d\u0435\u0442 &#8212; \u043f\u044b\u0442\u0430\u0435\u043c\u0441\u044f \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u0442\u044c\u0441\u044f<br \/>if (WiFi.status() == WL_CONNECTED &amp;&amp; !webSocket.isConnected() &amp;&amp;<br \/>currentMillis &#8212; lastConnectionAttempt &gt;= connectionInterval) {<br \/>connectionState = 1;<br \/>Serial.println(&#171;Connecting to WebSocket server&#8230;&#187;);<br \/>webSocket.begin(&#171;192.168.1.10&#187;, 8765, &#171;\/&#187;);<br \/>webSocket.onEvent(webSocketEvent);<br \/>webSocket.setReconnectInterval(5000);<br \/>lastConnectionAttempt = currentMillis;<br \/>}<\/p>\n<p>delay(10); \/\/ \u041d\u0435\u0431\u043e\u043b\u044c\u0448\u0430\u044f \u0437\u0430\u0434\u0435\u0440\u0436\u043a\u0430 \u0434\u043b\u044f \u0441\u0442\u0430\u0431\u0438\u043b\u044c\u043d\u043e\u0441\u0442\u0438<\/p>\n<h4>\u0411\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 button.h<\/h4>\n<p>#ifndef Button_h<br \/> #define Button_h<br \/> #include<br \/> class Button {<br \/> public:<br \/> Button(byte pin) : pin(pin), lastState(HIGH), lastDebounceTime(0), flag(false) {<br \/> pinMode(_pin, INPUT_PULLUP);<br \/> }<br \/> bool click() {<br \/> bool currentState = digitalRead(_pin);<br \/> bool result = false;<br \/> if (currentState != <em>lastState) {<br \/> <\/em>lastDebounceTime = millis();<br \/> }<br \/> if ((millis() &#8212; lastDebounceTime) &gt; DEBOUNCEDELAY) {<br \/> if (!currentState &amp;&amp; !_flag) {<br \/> <em>flag = true;<br \/> result = true;<br \/> }<br \/> if (currentState &amp;&amp; <\/em>flag) {<br \/> <em>flag = false;<br \/> }<br \/> }<br \/> <\/em>lastState = currentState;<br \/> return result;<br \/> }<br \/> bool isPressed() {<br \/> return (digitalRead(_pin) == LOW);<br \/> }<br \/> private:<br \/> static const uint32_t DEBOUNCE_DELAY = 50;<br \/> byte <em>pin;<br \/> bool <\/em>lastState;<br \/> uint32_t <em>lastDebounceTime;<br \/> bool <\/em>flag;<br \/> };<\/p>\n<p>\u041a\u043e\u0434 \u0441\u0435\u0440\u0432\u0435\u0440\u0430 \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u0442 \u0443\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u043c \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u043e\u043c \u044f \u043f\u0440\u0438\u0432\u0435\u0434\u0443 \u0432 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u0435\u0441\u043b\u0438 \u0431\u0443\u0434\u0435\u0442 \u043a\u043e\u043c\u0443 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u043e. <\/p>\n<h4>\u0417\u0430\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435<\/h4>\n<p>\u0420\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0430\u043d\u043d\u044b\u0439 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u043d\u044b\u0439 \u043c\u043e\u0434\u0443\u043b\u044c \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0441\u043e\u0431\u043e\u0439\u00a0<strong>\u043d\u0430\u0434\u0451\u0436\u043d\u0443\u044e \u0438 \u0433\u0438\u0431\u043a\u0443\u044e \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0443<\/strong>\u00a0\u0434\u043b\u044f \u0443\u0434\u0430\u043b\u0435\u043d\u043d\u043e\u0433\u043e \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0434\u0440\u043e\u043d\u043e\u0432\u044b\u043c \u043e\u0431\u043e\u0440\u0443\u0434\u043e\u0432\u0430\u043d\u0438\u0435\u043c. \u0411\u043b\u0430\u0433\u043e\u0434\u0430\u0440\u044f WebSocket-\u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044e \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u0432\u044b\u0441\u043e\u043a\u0430\u044f \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u044c \u043e\u0442\u043a\u043b\u0438\u043a\u0430, \u0430 \u043d\u0430\u043b\u0438\u0447\u0438\u0435 \u0442\u0435\u043b\u0435\u043c\u0435\u0442\u0440\u0438\u0438 \u0438 \u0432\u0438\u0437\u0443\u0430\u043b\u044c\u043d\u043e\u0439 \u0438\u043d\u0434\u0438\u043a\u0430\u0446\u0438\u0438 \u0434\u0435\u043b\u0430\u0435\u0442 \u044d\u043a\u0441\u043f\u043b\u0443\u0430\u0442\u0430\u0446\u0438\u044e \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u0439 \u0438 \u043f\u0440\u0435\u0434\u0441\u043a\u0430\u0437\u0443\u0435\u043c\u043e\u0439. \u0414\u0430\u043d\u043d\u044b\u0439 \u043f\u043e\u0434\u0445\u043e\u0434 \u043b\u0435\u0433\u043a\u043e \u043c\u0430\u0441\u0448\u0442\u0430\u0431\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u0438 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0430\u0434\u0430\u043f\u0442\u0438\u0440\u043e\u0432\u0430\u043d \u043f\u043e\u0434 \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0435 \u0442\u0438\u043f\u044b \u0434\u0440\u043e\u043d\u043e\u0432 \u0438 \u0437\u0430\u0434\u0430\u0447.<\/p>\n<\/div>\n<\/div>\n<\/div>\n<p><!----><!----><\/div>\n<p><!----><!----><br \/> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/articles\/923262\/\"> https:\/\/habr.com\/ru\/articles\/923262\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<p><strong>\u041f\u0440\u0435\u0434\u0438\u0441\u043b\u043e\u0432\u0438\u0435<\/strong><\/p>\n<p>\u0414\u0430\u043d\u043d\u0430\u044f \u0441\u0442\u0430\u0442\u044c\u044f \u044d\u0442\u043e \u0440\u0430\u0441\u0441\u043a\u0430\u0437 \u043e\u0431 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u0439 \u0447\u0430\u0441\u0442\u0438 \u043c\u043e\u0435\u0433\u043e \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u043f\u043e \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044e \u0441\u0438\u0441\u0442\u0435\u043c\u044b \u0434\u043e\u0441\u0442\u0430\u0432\u043a\u0438 \u0434\u0440\u043e\u043d\u0430\u043c\u0438. \u0421\u0438\u0441\u0442\u0435\u043c\u0430 \u0441\u043e\u0432\u0441\u0435\u043c \u0432 \u0440\u0430\u043d\u043d\u0435\u0439 \u0441\u0442\u0430\u0434\u0438\u0438 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438. \u041d\u043e \u0432 \u043f\u0440\u0438\u043d\u0446\u0438\u043f\u0435 \u044d\u0442\u0430 \u0447\u0430\u0441\u0442\u044c \u0433\u043e\u0442\u043e\u0432\u0430 \u0438 \u0435\u0441\u043b\u0438 \u043a\u043e\u043c\u0443 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u043e \u043c\u043e\u0436\u0435\u0442 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0432 \u0441\u0432\u043e\u0438\u0445 \u043f\u0440\u043e\u0435\u043a\u0442\u043e\u0432. \u0415\u0441\u043b\u0438 \u0431\u0443\u0434\u0435\u0442 \u0437\u0430\u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043e\u0432\u0430\u043d\u043d\u043e\u0441\u0442\u044c \u043c\u043e\u0433\u0443 \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0438\u0442\u044c \u043f\u0443\u0431\u043b\u0438\u043a\u043e\u0432\u0430\u0442\u044c \u0447\u0435\u0440\u0442\u0435\u0436\u0438, \u0441\u0445\u0435\u043c\u044b \u0438 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u043d\u044b\u0439 \u043a\u043e\u0434.<\/p>\n<h4>\u0412\u0432\u0435\u0434\u0435\u043d\u0438\u0435<\/h4>\n<p>\u0421 \u0440\u043e\u0441\u0442\u043e\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u0434\u0440\u043e\u043d\u043e\u0432 \u0432 \u043b\u043e\u0433\u0438\u0441\u0442\u0438\u043a\u0435 \u0438 \u0442\u0435\u0445\u043d\u0438\u0447\u0435\u0441\u043a\u043e\u043c \u043e\u0431\u0441\u043b\u0443\u0436\u0438\u0432\u0430\u043d\u0438\u0438 \u0440\u0430\u0441\u0442\u0435\u0442 \u043f\u043e\u0442\u0440\u0435\u0431\u043d\u043e\u0441\u0442\u044c \u0432 \u0443\u043d\u0438\u0432\u0435\u0440\u0441\u0430\u043b\u044c\u043d\u044b\u0445 \u043c\u043e\u0434\u0443\u043b\u044f\u0445 \u0434\u043b\u044f \u043f\u0435\u0440\u0435\u0432\u043e\u0437\u043a\u0438 \u0433\u0440\u0443\u0437\u043e\u0432 \u0438 \u0441\u043c\u0435\u043d\u043d\u044b\u0445 \u0430\u043a\u043a\u0443\u043c\u0443\u043b\u044f\u0442\u043e\u0440\u043e\u0432. \u0414\u043b\u044f \u0440\u0435\u0448\u0435\u043d\u0438\u044f \u044d\u0442\u043e\u0439 \u0437\u0430\u0434\u0430\u0447\u0438 \u0431\u044b\u043b \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0430\u043d\u00a0<strong>\u0438\u043d\u0442\u0435\u043b\u043b\u0435\u043a\u0442\u0443\u0430\u043b\u044c\u043d\u044b\u0439 \u0431\u043e\u043a\u0441<\/strong>, \u0443\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u043c\u044b\u0439 \u0443\u0434\u0430\u043b\u0451\u043d\u043d\u043e \u0447\u0435\u0440\u0435\u0437 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440 \u043d\u0430 \u0431\u0430\u0437\u0435\u00a0<strong>ESP8266<\/strong>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0441\u043f\u043e\u0441\u043e\u0431\u0435\u043d:<\/p>\n<figure class=\"full-width\">\n<div><figcaption>\u041e\u0431\u0449\u0430\u044f \u0441\u0445\u0435\u043c\u0430. \u0424\u043b\u0430\u0448\u043a\u0438 \u0444\u0438\u043a\u0441\u0430\u0446\u0438\u0438 \u0431\u0443\u0434\u0443\u0442 \u0441 \u043e\u0431\u043e\u0438\u0445 \u0441\u0442\u043e\u0440\u043e\u043d \u0438 \u0441\u0435\u0440\u0432\u043e\u043f\u0440\u0438\u0432\u043e\u0434 \u0431\u0443\u0434\u0435\u0442 \u043f\u043e\u0441\u0435\u0440\u0435\u0434\u0438\u043d\u0435. \u0422\u0430\u043a \u0436\u0435 \u043d\u0435 \u043f\u043e\u043a\u0430\u0437\u0430\u043d\u043d\u044b \u043a\u043e\u043d\u0446\u0435\u0432\u0438\u043a\u0438.<\/figcaption><\/div>\n<\/figure>\n<ul>\n<li>\n<p>\ud83d\udce6 \u043e\u0442\u043a\u0440\u044b\u0432\u0430\u0442\u044c \u0438 \u0437\u0430\u043a\u0440\u044b\u0432\u0430\u0442\u044c \u043e\u0442\u0441\u0435\u043a \u0434\u043b\u044f \u0433\u0440\u0443\u0437\u0430;<\/p>\n<\/li>\n<li>\n<p>\ud83d\udd0b \u043e\u0442\u043a\u0440\u044b\u0432\u0430\u0442\u044c \u0438 \u0437\u0430\u043a\u0440\u044b\u0432\u0430\u0442\u044c \u043e\u0442\u0441\u0435\u043a \u0434\u043b\u044f \u0441\u043c\u0435\u043d\u043d\u043e\u0433\u043e \u0430\u043a\u043a\u0443\u043c\u0443\u043b\u044f\u0442\u043e\u0440\u0430;<\/p>\n<\/li>\n<li>\n<p>\ud83d\udce1 \u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u0442\u044c \u0442\u0435\u043b\u0435\u043c\u0435\u0442\u0440\u0438\u044e \u043e \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0438 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430;<\/p>\n<\/li>\n<li>\n<p>\u2705 \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0442\u044c \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u0447\u0435\u0440\u0435\u0437 WebSocket-\u0441\u0435\u0440\u0432\u0435\u0440.<\/p>\n<\/li>\n<\/ul>\n<h4>\u0410\u043f\u043f\u0430\u0440\u0430\u0442\u043d\u0430\u044f \u0447\u0430\u0441\u0442\u044c<\/h4>\n<p>\u0423\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u043e \u043f\u043e\u0441\u0442\u0440\u043e\u0435\u043d\u043e \u043d\u0430 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u0435\u00a0<strong>ESP8266<\/strong>\u00a0(\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, ESP-01 \u0438\u043b\u0438 NodeMCU) \u0438 \u0432\u043a\u043b\u044e\u0447\u0430\u0435\u0442 \u0432 \u0441\u0435\u0431\u044f:<\/p>\n<ul>\n<li>\n<p><strong>2 \u0441\u0435\u0440\u0432\u043e\u043f\u0440\u0438\u0432\u043e\u0434\u0430<\/strong>:<br \/>Servo1 \u2014 \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u043a\u0440\u044b\u0448\u043a\u043e\u0439 \u0433\u0440\u0443\u0437\u043e\u0432\u043e\u0433\u043e \u043e\u0442\u0441\u0435\u043a\u0430.<br \/>Servo2 \u2014 \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u043a\u0440\u044b\u0448\u043a\u043e\u0439 \u043e\u0442\u0441\u0435\u043a\u0430 \u0430\u043a\u043a\u0443\u043c\u0443\u043b\u044f\u0442\u043e\u0440\u0430.<\/p>\n<\/li>\n<li>\n<p><strong>2 \u043a\u043e\u043d\u0446\u0435\u0432\u044b\u0445 \u043f\u0435\u0440\u0435\u043a\u043b\u044e\u0447\u0430\u0442\u0435\u043b\u044f<\/strong>:<br \/>Button1 \u2014 \u043d\u0430\u043b\u0438\u0447\u0438\u0435 \u0433\u0440\u0443\u0437\u0430 \u0432 \u0431\u043e\u043a\u0441\u0435.<br \/>Button2 \u2014 \u043d\u0430\u043b\u0438\u0447\u0438\u0435 \u0430\u043a\u043a\u0443\u043c\u0443\u043b\u044f\u0442\u043e\u0440\u0430.<\/p>\n<\/li>\n<li>\n<p><strong>\u0421\u0432\u0435\u0442\u043e\u0434\u0438\u043e\u0434<\/strong>: \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0434\u043b\u044f \u0438\u043d\u0434\u0438\u043a\u0430\u0446\u0438\u0438 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f.<\/p>\n<\/li>\n<\/ul>\n<h4>\u0421\u0435\u0442\u044c \u0438 \u0441\u0432\u044f\u0437\u044c<\/h4>\n<p>\u041a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0430\u0435\u0442\u0441\u044f \u043a \u0437\u0430\u0434\u0430\u043d\u043d\u043e\u0439 Wi-Fi-\u0441\u0435\u0442\u0438 \u0438 \u0443\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u0442 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0435 \u0441\u00a0<strong>WebSocket-\u0441\u0435\u0440\u0432\u0435\u0440\u043e\u043c<\/strong>. \u042d\u0442\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u0443 \u0434\u0440\u043e\u043d\u0430 \u0438\u043b\u0438 \u043b\u043e\u0433\u0438\u0441\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u0439 \u0441\u0438\u0441\u0442\u0435\u043c\u0435 \u0443\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c \u0431\u043e\u043a\u0441\u043e\u043c \u0432 \u0440\u0435\u0436\u0438\u043c\u0435 \u0440\u0435\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u0438.<\/p>\n<p><strong>\u0421\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f<\/strong>\u00a0\u0432\u0438\u0437\u0443\u0430\u043b\u0438\u0437\u0438\u0440\u0443\u044e\u0442\u0441\u044f \u0447\u0435\u0440\u0435\u0437 \u0432\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u044b\u0439 \u0441\u0432\u0435\u0442\u043e\u0434\u0438\u043e\u0434:<\/p>\n<ul>\n<li>\n<p>\u2734\ufe0f \u0411\u044b\u0441\u0442\u0440\u043e \u043c\u0438\u0433\u0430\u0435\u0442 \u2014 \u043d\u0435\u0442 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f \u043a Wi-Fi.<\/p>\n<\/li>\n<li>\n<p>\u23f3 \u041c\u0435\u0434\u043b\u0435\u043d\u043d\u043e \u043c\u0438\u0433\u0430\u0435\u0442 \u2014 Wi-Fi \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d, WebSocket \u043d\u0435\u0442.<\/p>\n<\/li>\n<li>\n<p>\u2705 \u041f\u043e\u0441\u0442\u043e\u044f\u043d\u043d\u043e \u0433\u043e\u0440\u0438\u0442 \u2014 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0435 WebSocket \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u043e.<\/p>\n<\/li>\n<\/ul>\n<h4>\u041f\u0440\u0438\u043d\u0446\u0438\u043f \u0440\u0430\u0431\u043e\u0442\u044b<\/h4>\n<p>\u041f\u043e\u0441\u043b\u0435 \u0432\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u043e:<\/p>\n<ol>\n<li>\n<p>\u041f\u043e\u0434\u043a\u043b\u044e\u0447\u0430\u0435\u0442\u0441\u044f \u043a Wi-Fi.<\/p>\n<\/li>\n<li>\n<p>\u041f\u0435\u0440\u0438\u043e\u0434\u0438\u0447\u0435\u0441\u043a\u0438 \u043f\u044b\u0442\u0430\u0435\u0442\u0441\u044f \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c WebSocket-\u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0435.<\/p>\n<\/li>\n<li>\n<p>\u041f\u043e\u0441\u043b\u0435 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442 \u0434\u0430\u043d\u043d\u044b\u0435 \u043e\u0431 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0435 (\u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440 \u0438 \u043f\u0430\u0440\u043e\u043b\u044c).<\/p>\n<\/li>\n<li>\n<p>\u041e\u0436\u0438\u0434\u0430\u0435\u0442 \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u043e\u0442 \u0441\u0435\u0440\u0432\u0435\u0440\u0430 \u0438 \u0440\u0435\u0430\u0433\u0438\u0440\u0443\u0435\u0442 \u043d\u0430 \u043d\u0438\u0445.<\/p>\n<\/li>\n<\/ol>\n<h4>\u041e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u043a\u043e\u043c\u0430\u043d\u0434<\/h4>\n<p>\u041f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u044e\u0442\u0441\u044f \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u043a\u043e\u043c\u0430\u043d\u0434\u044b:<\/p>\n<ul>\n<li>\n<p>&#171;servo1&#187; \u2014 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u0443\u0433\u043e\u043b \u043e\u0442\u043a\u0440\u044b\u0442\u0438\u044f \u0433\u0440\u0443\u0437\u043e\u0432\u043e\u0433\u043e \u043e\u0442\u0441\u0435\u043a\u0430.<\/p>\n<\/li>\n<li>\n<p>&#171;servo2&#187; \u2014 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u0443\u0433\u043e\u043b \u043e\u0442\u043a\u0440\u044b\u0442\u0438\u044f \u0430\u043a\u043a\u0443\u043c\u0443\u043b\u044f\u0442\u043e\u0440\u043d\u043e\u0433\u043e \u043e\u0442\u0441\u0435\u043a\u0430.<\/p>\n<\/li>\n<li>\n<p>&#171;reboot&#187; \u2014 \u043f\u0435\u0440\u0435\u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0430 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430.<\/p>\n<\/li>\n<\/ul>\n<h4>\u0422\u0435\u043b\u0435\u043c\u0435\u0442\u0440\u0438\u044f<\/h4>\n<p>\u0423\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u043e \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442 \u0442\u0435\u043b\u0435\u043c\u0435\u0442\u0440\u0438\u044e \u043f\u043e \u043a\u043e\u043c\u0430\u043d\u0434\u0435 &#171;PING&#187;:<\/p>\n<ul>\n<li>\n<p>\u0421\u0442\u0430\u0442\u0443\u0441 &#171;\u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442&#187;,<\/p>\n<\/li>\n<li>\n<p>\u0423\u0433\u043b\u044b \u043e\u0431\u043e\u0438\u0445 \u0441\u0435\u0440\u0432\u043e\u043f\u0440\u0438\u0432\u043e\u0434\u043e\u0432,<\/p>\n<\/li>\n<li>\n<p>\u0421\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u043e\u0431\u043e\u0438\u0445 \u043a\u043e\u043d\u0446\u0435\u0432\u0438\u043a\u043e\u0432 (&#171;pressed&#187; \u0438\u043b\u0438 &#171;released&#187;).<\/p>\n<\/li>\n<\/ul>\n<h4>\u041a\u043d\u043e\u043f\u043a\u0438 (\u043a\u043e\u043d\u0446\u0435\u0432\u0438\u043a\u0438)<\/h4>\n<p>\u041a\u043e\u043d\u0446\u0435\u0432\u0438\u043a\u0438 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u044b \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u043d\u043e\u0433\u043e \u043a\u043b\u0430\u0441\u0441\u0430 Button. \u0421\u0438\u0441\u0442\u0435\u043c\u0430 \u043e\u0442\u0441\u043b\u0435\u0436\u0438\u0432\u0430\u0435\u0442 \u0438\u0445 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f \u0438 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f \u043f\u0440\u0438 \u043d\u0430\u0436\u0430\u0442\u0438\u0438 \u0438\u043b\u0438 \u043f\u043e \u0442\u0430\u0439\u043c\u0435\u0440\u0443 (\u0440\u0430\u0437 \u0432 \u0441\u0435\u043a\u0443\u043d\u0434\u0443), \u0435\u0441\u043b\u0438 WebSocket-\u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0435 \u0430\u043a\u0442\u0438\u0432\u043d\u043e.<\/p>\n<h4>\u041f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u043d\u0430\u044f \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0430<\/h4>\n<p>\u041a\u043b\u044e\u0447\u0435\u0432\u044b\u0435 \u0442\u0435\u0445\u043d\u043e\u043b\u043e\u0433\u0438\u0438:<\/p>\n<ul>\n<li>\n<p><strong>ESP8266WiFi<\/strong>\u00a0\u2014 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 \u043a \u0441\u0435\u0442\u0438.<\/p>\n<\/li>\n<li>\n<p><strong>WebSocketsClient<\/strong>\u00a0\u2014 \u0434\u0432\u0443\u0441\u0442\u043e\u0440\u043e\u043d\u043d\u044f\u044f \u0441\u0432\u044f\u0437\u044c \u0441 \u0441\u0435\u0440\u0432\u0435\u0440\u043e\u043c.<\/p>\n<\/li>\n<li>\n<p><strong>ArduinoJson<\/strong>\u00a0\u2014 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430 JSON-\u043a\u043e\u043c\u0430\u043d\u0434 \u0438 \u0442\u0435\u043b\u0435\u043c\u0435\u0442\u0440\u0438\u0438.<\/p>\n<\/li>\n<li>\n<p><strong>Servo<\/strong>\u00a0\u2014 \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0441\u0435\u0440\u0432\u043e\u043f\u0440\u0438\u0432\u043e\u0434\u0430\u043c\u0438.<\/p>\n<\/li>\n<li>\n<p><strong>\u041a\u0430\u0441\u0442\u043e\u043c\u043d\u044b\u0439 \u043a\u043b\u0430\u0441\u0441 Button<\/strong>\u00a0\u2014 \u043f\u0440\u043e\u0441\u0442\u0430\u044f \u043b\u043e\u0433\u0438\u043a\u0430 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0439 \u043a\u043d\u043e\u043f\u043e\u043a.<\/p>\n<\/li>\n<\/ul>\n<h4>\u041f\u0440\u0438\u043c\u0435\u043d\u0435\u043d\u0438\u0435<\/h4>\n<p>\u0422\u0430\u043a\u0430\u044f \u0441\u0438\u0441\u0442\u0435\u043c\u0430 \u043c\u043e\u0436\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0432 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0445 \u0441\u043b\u0443\u0447\u0430\u044f\u0445:<\/p>\n<ul>\n<li>\n<p>\ud83d\udce6\u00a0<strong>\u0414\u043e\u0441\u0442\u0430\u0432\u043a\u0430 \u043c\u0430\u043b\u044b\u0445 \u0433\u0440\u0443\u0437\u043e\u0432<\/strong>: \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u043e\u0442\u043a\u0440\u044b\u0442\u044c \u043e\u0442\u0441\u0435\u043a \u0434\u043b\u044f \u0432\u044b\u0433\u0440\u0443\u0437\u043a\u0438.<\/p>\n<\/li>\n<li>\n<p>\ud83d\udd0b\u00a0<strong>\u041e\u0431\u0441\u043b\u0443\u0436\u0438\u0432\u0430\u043d\u0438\u0435 \u0434\u0440\u043e\u043d\u043e\u0432<\/strong>: \u0431\u044b\u0441\u0442\u0440\u043e\u0435 \u0438\u0437\u0432\u043b\u0435\u0447\u0435\u043d\u0438\u0435 \u0438 \u0437\u0430\u043c\u0435\u043d\u0430 \u0430\u043a\u043a\u0443\u043c\u0443\u043b\u044f\u0442\u043e\u0440\u043e\u0432.<\/p>\n<\/li>\n<li>\n<p>\ud83d\udce1\u00a0<strong>\u041c\u043e\u043d\u0438\u0442\u043e\u0440\u0438\u043d\u0433 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f<\/strong>: \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440 \u0432\u0441\u0435\u0433\u0434\u0430 \u0437\u043d\u0430\u0435\u0442, \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u043b\u0438 \u0433\u0440\u0443\u0437 \u0438\u043b\u0438 \u0430\u043a\u043a\u0443\u043c\u0443\u043b\u044f\u0442\u043e\u0440 \u0432 \u0431\u043e\u043a\u0441\u0435.<\/p>\n<\/li>\n<\/ul>\n<p>\u0422\u0430\u043a \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 \u043d\u0430 \u043f\u0440\u0430\u043a\u0442\u0438\u043a\u0435 <\/p>\n<figure class=\"full-width\"><\/figure>\n<p>\u041a\u0443\u0434\u0430 \u0447\u0442\u043e \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0430\u0442\u044c \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u043d\u044f\u0442\u044c \u0438\u0437 \u043f\u0440\u043e\u0448\u0438\u0432\u043a\u0438. <\/p>\n<h4>\u041a\u043e\u0434 \u0434\u043b\u044f \u043f\u0440\u043e\u0448\u0438\u0432\u043a\u0438.<\/h4>\n<p>#include &lt;ESP8266WiFi.h&gt;<br \/>#include &lt;WebSocketsClient.h&gt;<br \/>#include &lt;ArduinoJson.h&gt;<br \/>#include &lt;Servo.h&gt;<br \/>#include &#171;Button.h&#187; \/\/ \u041f\u043e\u0434\u043a\u043b\u044e\u0447\u0430\u0435\u043c \u043d\u0430\u0448 \u043a\u043b\u0430\u0441\u0441 Button<\/p>\n<p>const char* ssid = &#171;&#8212;-&#171;;<br \/>const char* password = &#171;&#8212;&#8212;&#171;;<\/p>\n<p>WebSocketsClient webSocket;<\/p>\n<p>const char* deviceName = &#171;esp01&#187;;<br \/>const char* devicePassword = &#171;1234&#187;;<\/p>\n<p>const int LED_PIN = LED_BUILTIN;<br \/>const int BUTTON1_PIN = 14; \/\/ GPIO14 (D5 \u043d\u0430 NodeMCU)<br \/>const int BUTTON2_PIN = 4; \/\/ GPIO4 (D2 \u043d\u0430 NodeMCU)<br \/>const int SERVO1_PIN = 12; \/\/ \u041f\u0438\u043d \u043f\u0435\u0440\u0432\u043e\u0433\u043e \u0441\u0435\u0440\u0432\u043e\u043f\u0440\u0438\u0432\u043e\u0434\u0430 (D6)<br \/>const int SERVO2_PIN = 13; \/\/ \u041f\u0438\u043d \u0432\u0442\u043e\u0440\u043e\u0433\u043e \u0441\u0435\u0440\u0432\u043e\u043f\u0440\u0438\u0432\u043e\u0434\u0430 (D7)<br \/>Button button1(BUTTON1_PIN);<br \/>Button button2(BUTTON2_PIN);<\/p>\n<p>Servo servo1;<br \/>Servo servo2;<\/p>\n<p>unsigned long previousMillis = 0;<br \/>unsigned long lastConnectionAttempt = 0;<br \/>const long connectionInterval = 10000; \/\/ 10 \u0441\u0435\u043a\u0443\u043d\u0434 \u043c\u0435\u0436\u0434\u0443 \u043f\u043e\u043f\u044b\u0442\u043a\u0430\u043c\u0438 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f<\/p>\n<p>int ledState = LOW;<br \/>int connectionState = 0; \/\/ 0 &#8212; \u043d\u0435\u0442 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f, 1 &#8212; WiFi \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d, 2 &#8212; WebSocket \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d<br \/>int servo1Pos = 90; \/\/ \u0422\u0435\u043a\u0443\u0449\u0435\u0435 \u043f\u043e\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0441\u0435\u0440\u0432\u043e\u043f\u0440\u0438\u0432\u043e\u0434\u0430 1 (0-180)<br \/>int servo2Pos = 90; \/\/ \u0422\u0435\u043a\u0443\u0449\u0435\u0435 \u043f\u043e\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0441\u0435\u0440\u0432\u043e\u043f\u0440\u0438\u0432\u043e\u0434\u0430 2 (0-180)<\/p>\n<p>void updateLed() {<br \/>unsigned long currentMillis = millis();<br \/>unsigned long interval;<\/p>\n<p>switch(connectionState) {<br \/>case 0: \/\/ \u041d\u0435\u0442 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f &#8212; \u0431\u044b\u0441\u0442\u0440\u043e\u0435 \u043c\u0438\u0433\u0430\u043d\u0438\u0435 (500ms)<br \/>interval = 500;<br \/>break;<br \/>case 1: \/\/ WiFi \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d &#8212; \u043c\u0435\u0434\u043b\u0435\u043d\u043d\u043e\u0435 \u043c\u0438\u0433\u0430\u043d\u0438\u0435 (1000ms)<br \/>interval = 1000;<br \/>break;<br \/>case 2: \/\/ WebSocket \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d &#8212; \u043f\u043e\u0441\u0442\u043e\u044f\u043d\u043d\u043e \u0432\u043a\u043b\u044e\u0447\u0435\u043d<br \/>digitalWrite(LED_PIN, LOW);<br \/>return;<br \/>}<\/p>\n<p>if (currentMillis &#8212; previousMillis &gt;= interval) {<br \/>previousMillis = currentMillis;<br \/>ledState = (ledState == LOW) ? HIGH : LOW;<br \/>digitalWrite(LED_PIN, ledState);<br \/>}<br \/>}<\/p>\n<p>void handleCommand(const char* cmd, const char* value) {<br \/>Serial.printf(&#171;Received command: %s, value: %s\\n&#187;, cmd, value);<\/p>\n<p>if (strcmp(cmd, &#171;servo1&#187;) == 0) {<br \/>int pos = atoi(value);<br \/>if (pos &gt;= 0 &amp;&amp; pos &lt;= 360) {<br \/>servo1Pos = pos;<br \/>servo1.write(servo1Pos);<br \/>Serial.printf(&#171;Servo1 set to %d\\n&#187;, servo1Pos);<br \/>}<br \/>}<br \/>else if (strcmp(cmd, &#171;servo2&#187;) == 0) {<br \/>int pos = atoi(value);<br \/>if (pos &gt;= 0 &amp;&amp; pos &lt;= 360) {<br \/>servo2Pos = pos;<br \/>servo2.write(servo2Pos);<br \/>Serial.printf(&#171;Servo2 set to %d\\n&#187;, servo2Pos);<br \/>}<br \/>}<br \/>else if (strcmp(cmd, &#171;reboot&#187;) == 0) {<br \/>Serial.println(&#171;Rebooting&#8230;&#187;);<br \/>ESP.restart();<br \/>}<br \/>}<\/p>\n<p>void webSocketEvent(WStype_t type, uint8_t* payload, size_t length) {<br \/>switch (type) {<br \/>case WStype_CONNECTED:<br \/>Serial.println(&#171;[WS] Connected&#187;);<br \/>connectionState = 2; \/\/ WebSocket \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d<br \/>updateLed();<\/p>\n<p>\/\/ \u041e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u043c \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043e\u0431 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0435 \u043f\u0440\u0438 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0438<br \/>{<br \/>StaticJsonDocument&lt;256&gt; doc;<br \/>doc[&#171;type&#187;] = &#171;auth&#187;;<br \/>doc[&#171;name&#187;] = deviceName;<br \/>doc[&#171;password&#187;] = devicePassword;<br \/>String json;<br \/>serializeJson(doc, json);<br \/>webSocket.sendTXT(json);<br \/>}<br \/>break;<\/p>\n<p>case WStype_DISCONNECTED:<br \/>Serial.println(&#171;[WS] Disconnected&#187;);<br \/>connectionState = (WiFi.status() == WL_CONNECTED) ? 1 : 0;<br \/>break;<\/p>\n<p>case WStype_TEXT:<br \/>Serial.printf(&#171;[WS] Received: %s\\n&#187;, payload);<br \/>\/\/Serial.printf(&#171;-%s-\\n&#187;, payload);<\/p>\n<p>\/\/ \u041e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430 PING<br \/>\/\/if (strstr((char*)payload, &#171;\\&#187;command\\&#187;:\\&#187;PING\\&#187;&#187;) != NULL) {<br \/>if (strstr((char*)payload, &#171;\\&#187;command\\&#187;: \\&#187;PING\\&#187;&#187;) != NULL) {<\/p>\n<p>Serial.println(&#171;Processing PING command&#187;);<br \/>StaticJsonDocument&lt;512&gt; doc;<br \/>doc[&#171;type&#187;] = &#171;telemetry&#187;;<br \/>doc[&#171;status&#187;] = &#171;\u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442&#187;;<br \/>doc[&#171;servo1&#187;] = servo1Pos;<br \/>doc[&#171;servo2&#187;] = servo2Pos;<br \/>doc[&#171;button1&#187;] = button1.isPressed() ? &#171;pressed&#187; : &#171;released&#187;;<br \/>doc[&#171;button2&#187;] = button2.isPressed() ? &#171;pressed&#187; : &#171;released&#187;;<br \/>String json;<br \/>serializeJson(doc, json);<br \/>webSocket.sendTXT(json);<br \/>Serial.println(&#171;\u0422\u0435\u043b\u0435\u043c\u0435\u0442\u0440\u0438\u044f \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0430&#187;);<br \/>}<br \/>\/\/ \u041e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u043a\u043e\u043c\u0430\u043d\u0434<br \/>else {<br \/>StaticJsonDocument&lt;256&gt; doc;<br \/>DeserializationError error = deserializeJson(doc, payload);<\/p>\n<p>Serial.print(&#171;Deserialization error: &#171;);<br \/>Serial.println(error.c_str()); \/\/ \u0412\u044b\u0432\u0435\u0434\u0435\u0442 &#171;Ok&#187; \u0435\u0441\u043b\u0438 \u043e\u0448\u0438\u0431\u043e\u043a \u043d\u0435\u0442<\/p>\n<p>\/\/ \u0412\u044b\u0432\u043e\u0434\u0438\u043c \u0441\u044b\u0440\u043e\u0439 payload \u0434\u043b\u044f \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438<br \/>Serial.print(&#171;Raw payload: &#171;);<br \/>Serial.println((char*)payload);<\/p>\n<p>\/\/ \u0412\u044b\u0432\u043e\u0434\u0438\u043c \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u0435 doc \u0432 Serial<br \/>Serial.println(&#171;Parsed JSON content:&#187;);<br \/>serializeJsonPretty(doc, Serial); \/\/ \u041a\u0440\u0430\u0441\u0438\u0432\u044b\u0439 \u0432\u044b\u0432\u043e\u0434 \u0441 \u043e\u0442\u0441\u0442\u0443\u043f\u0430\u043c\u0438<br \/>Serial.println(&#171;\\n&#8212;&#171;);<\/p>\n<p>if (!error &amp;&amp; doc.containsKey(&#171;command&#187;) &amp;&amp; doc.containsKey(&#171;value&#187;)) {<br \/>const char* cmd = doc[&#171;command&#187;];<br \/>const char* value = doc[&#171;value&#187;];<br \/>handleCommand(cmd, value);<\/p>\n<p>\/\/ \u041e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u043c \u043f\u043e\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043d\u0438\u0435<br \/>doc[&#171;type&#187;] = &#171;command_ack&#187;;<br \/>doc[&#171;status&#187;] = &#171;ok&#187;;<br \/>String json;<br \/>serializeJson(doc, json);<br \/>webSocket.sendTXT(json);<br \/>Serial.println(&#171;&#187;);<br \/>}<br \/>}<br \/>break;<br \/>}<br \/>}<\/p>\n<p>void setup() {<br \/>pinMode(LED_PIN, OUTPUT);<br \/>digitalWrite(LED_PIN, HIGH);<\/p>\n<p>pinMode(BUTTON1_PIN, INPUT_PULLUP);<br \/>pinMode(BUTTON2_PIN, INPUT_PULLUP);<\/p>\n<p>servo1.attach(SERVO1_PIN);<br \/>servo2.attach(SERVO2_PIN);<br \/>servo1.write(servo1Pos);<br \/>servo2.write(servo2Pos);<\/p>\n<p>Serial.begin(115200);<br \/>WiFi.begin(ssid, password);<\/p>\n<p>\/\/ \u041d\u0430\u0447\u0430\u043b\u044c\u043d\u043e\u0435 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 &#8212; \u043d\u0435\u0442 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f<br \/>connectionState = 0;<br \/>}<\/p>\n<p>void handleButtons() {<br \/>static unsigned long lastSend = 0;<\/p>\n<p>\/\/ \u041f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c \u043d\u0430\u0436\u0430\u0442\u0438\u044f<br \/>if (button1.click() <span class=\"habrahidden\"> button2.click() <\/span> millis() &#8212; lastSend &gt; 1000) {<br \/>if (webSocket.isConnected()) {<br \/>sendButtonStates();<br \/>lastSend = millis();<br \/>}<br \/>}<br \/>}<br \/>void sendButtonStates() {<br \/>StaticJsonDocument&lt;200&gt; doc;<br \/>doc[&#171;type&#187;] = &#171;button_state&#187;;<br \/>doc[&#171;button1&#187;] = button1.isPressed() ? &#171;pressed&#187; : &#171;released&#187;;<br \/>doc[&#171;button2&#187;] = button2.isPressed() ? &#171;pressed&#187; : &#171;released&#187;;<\/p>\n<p>String json;<br \/>serializeJson(doc, json);<br \/>webSocket.sendTXT(json);<br \/>}<\/p>\n<p>void loop() {<br \/>unsigned long currentMillis = millis();<\/p>\n<p>\/\/ \u041e\u0431\u043d\u043e\u0432\u043b\u044f\u0435\u043c \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f WiFi<br \/>if (WiFi.status() != WL_CONNECTED) {<br \/>connectionState = 0;<br \/>if (currentMillis &#8212; lastConnectionAttempt &gt;= connectionInterval) {<br \/>Serial.println(&#171;Connecting to WiFi&#8230;&#187;);<br \/>WiFi.begin(ssid, password);<br \/>lastConnectionAttempt = currentMillis;<br \/>}<br \/>}<br \/>else if (connectionState == 0) {<br \/>connectionState = 1;<br \/>Serial.println(&#171;\\nWiFi connected&#187;);<br \/>Serial.print(&#171;IP address: &#171;);<br \/>Serial.println(WiFi.localIP());<br \/>}<\/p>\n<p>updateLed();<br \/>handleButtons();<br \/>webSocket.loop();<\/p>\n<p>\/\/ \u0415\u0441\u043b\u0438 WiFi \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d, \u043d\u043e WebSocket \u0435\u0449\u0435 \u043d\u0435\u0442 &#8212; \u043f\u044b\u0442\u0430\u0435\u043c\u0441\u044f \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u0442\u044c\u0441\u044f<br \/>if (WiFi.status() == WL_CONNECTED &amp;&amp; !webSocket.isConnected() &amp;&amp;<br \/>currentMillis &#8212; lastConnectionAttempt &gt;= connectionInterval) {<br \/>connectionState = 1;<br \/>Serial.println(&#171;Connecting to WebSocket server&#8230;&#187;);<br \/>webSocket.begin(&#171;192.168.1.10&#187;, 8765, &#171;\/&#187;);<br \/>webSocket.onEvent(webSocketEvent);<br \/>webSocket.setReconnectInterval(5000);<br \/>lastConnectionAttempt = currentMillis;<br \/>}<\/p>\n<p>delay(10); \/\/ \u041d\u0435\u0431\u043e\u043b\u044c\u0448\u0430\u044f \u0437\u0430\u0434\u0435\u0440\u0436\u043a\u0430 \u0434\u043b\u044f \u0441\u0442\u0430\u0431\u0438\u043b\u044c\u043d\u043e\u0441\u0442\u0438<\/p>\n<h4>\u0411\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 button.h<\/h4>\n<p>#ifndef Button_h<br \/> #define Button_h<br \/> #include<br \/> class Button {<br \/> public:<br \/> Button(byte pin) : pin(pin), lastState(HIGH), lastDebounceTime(0), flag(false) {<br \/> pinMode(_pin, INPUT_PULLUP);<br \/> }<br \/> bool click() {<br \/> bool currentState = digitalRead(_pin);<br \/> bool result = false;<br \/> if (currentState != <em>lastState) {<br \/> <\/em>lastDebounceTime = millis();<br \/> }<br \/> if ((millis() &#8212; lastDebounceTime) &gt; DEBOUNCEDELAY) {<br \/> if (!currentState &amp;&amp; !_flag) {<br \/> <em>flag = true;<br \/> result = true;<br \/> }<br \/> if (currentState &amp;&amp; <\/em>flag) {<br \/> <em>flag = false;<br \/> }<br \/> }<br \/> <\/em>lastState = currentState;<br \/> return result;<br \/> }<br \/> bool isPressed() {<br \/> return (digitalRead(_pin) == LOW);<br \/> }<br \/> private:<br \/> static const uint32_t DEBOUNCE_DELAY = 50;<br \/> byte <em>pin;<br \/> bool <\/em>lastState;<br \/> uint32_t <em>lastDebounceTime;<br \/> bool <\/em>flag;<br \/> };<\/p>\n<p>\u041a\u043e\u0434 \u0441\u0435\u0440\u0432\u0435\u0440\u0430 \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u0442 \u0443\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u043c \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u043e\u043c \u044f \u043f\u0440\u0438\u0432\u0435\u0434\u0443 \u0432 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u0435\u0441\u043b\u0438 \u0431\u0443\u0434\u0435\u0442 \u043a\u043e\u043c\u0443 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u043e. <\/p>\n<h4>\u0417\u0430\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435<\/h4>\n<p>\u0420\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0430\u043d\u043d\u044b\u0439 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u043d\u044b\u0439 \u043c\u043e\u0434\u0443\u043b\u044c \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0441\u043e\u0431\u043e\u0439\u00a0<strong>\u043d\u0430\u0434\u0451\u0436\u043d\u0443\u044e \u0438 \u0433\u0438\u0431\u043a\u0443\u044e \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0443<\/strong><\/p>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-465188","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/465188","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=465188"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/465188\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=465188"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=465188"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=465188"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}