{"id":404139,"date":"2024-06-29T17:32:10","date_gmt":"2024-06-29T17:32:10","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=404139"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=404139","title":{"rendered":"<span>Opensource \u0441\u0438\u0441\u0442\u0435\u043c\u0430 \u0443\u043c\u043d\u043e\u0433\u043e \u0434\u043e\u043c\u0430 \u043d\u0430 nodejs<\/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<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/3c1\/c52\/24f\/3c1c5224fb1677ee2f3fef1283b4f9be.png\" alt=\"\u0418\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u0433\u043b\u0430\u0432\u043d\u043e\u0433\u043e \u043c\u0435\u043d\u044e\" title=\"\u0418\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u0433\u043b\u0430\u0432\u043d\u043e\u0433\u043e \u043c\u0435\u043d\u044e\" width=\"1262\" height=\"941\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/3c1\/c52\/24f\/3c1c5224fb1677ee2f3fef1283b4f9be.png\"\/><figcaption>\u0418\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u0433\u043b\u0430\u0432\u043d\u043e\u0433\u043e \u043c\u0435\u043d\u044e<\/figcaption><\/figure>\n<p>\u041f\u0440\u0438\u0432\u0435\u0442, \u0425\u0430\u0431\u0440! \u0425\u043e\u0447\u0443 \u043f\u043e\u0434\u0435\u043b\u0438\u0442\u044c\u0441\u044f \u0441\u0432\u043e\u0438\u043c \u043f\u0440\u043e\u0435\u043a\u0442\u043e\u043c, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0440\u0430\u0437\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u043b \u043f\u043e\u0447\u0442\u0438 \u0433\u043e\u0434 &#8212; <a href=\"https:\/\/github.com\/andaran\/appex-system\" rel=\"noopener noreferrer nofollow\">appex-system<\/a>.<\/p>\n<p>\u0414\u0435\u043b\u043e \u043d\u0430\u0447\u0430\u043b\u043e\u0441\u044c \u0441 \u0442\u043e\u0433\u043e, \u0447\u0442\u043e \u044f \u0437\u0430\u043a\u043e\u043d\u0447\u0438\u043b \u0438\u0437\u0443\u0447\u0435\u043d\u0438\u0435 \u043d\u043e\u0434\u044b. \u041d\u0443\u0436\u043d\u043e \u0431\u044b\u043b\u043e \u0437\u0430\u043f\u0438\u043b\u0438\u0442\u044c \u043a\u0430\u043a\u043e\u0439-\u043d\u0438\u0431\u0443\u0434\u044c \u043f\u0440\u043e\u0435\u043a\u0442, \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u0442\u0440\u0435\u043d\u0438\u0440\u043e\u0432\u0430\u0442\u044c\u0441\u044f, \u0438 \u044f \u0440\u0435\u0448\u0438\u043b \u043e\u0431\u044a\u0435\u0434\u0438\u043d\u0438\u0442\u044c 2 \u043b\u044e\u0431\u0438\u043c\u044b\u0445 \u0434\u0435\u043b\u0430 &#8212; \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0438 \u0441\u0430\u043c\u043e\u0434\u0435\u043b\u043a\u0438. \u0418 \u0432\u043e\u0442 \u0447\u0442\u043e \u0438\u0437 \u044d\u0442\u043e\u0433\u043e \u043f\u043e\u043b\u0443\u0447\u0438\u043b\u043e\u0441\u044c.<\/p>\n<p>\u0423\u043c\u043d\u044b\u0439 \u0434\u043e\u043c \u0434\u0435\u043b\u0438\u0442\u0441\u044f \u043d\u0430 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430. \u0423\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u043e\u043c \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u043a\u0430\u043a \u043e\u0434\u043d\u0430 \u043f\u043b\u0430\u0442\u0430 (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 esp8266), \u0442\u0430\u043a \u0438 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e (\u043b\u044e\u0441\u0442\u0440\u0430, \u0441\u043e\u0441\u0442\u043e\u044f\u0449\u0430\u044f \u0438\u0437 4 \u0443\u043c\u043d\u044b\u0445 \u043b\u0430\u043c\u043f\u043e\u0447\u0435\u043a). \u0414\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430 \u043f\u0438\u0448\u0435\u0442\u0441\u044f \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u043d\u0430 js. \u0423\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u043e \u0432 \u043c\u0435\u0441\u0442\u0435 \u0441 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435\u043c \u043e\u0431\u044a\u0435\u0434\u0438\u043d\u044f\u044e\u0442\u0441\u044f \u0432 \u043a\u043e\u043c\u043d\u0430\u0442\u0443, \u043d\u0430\u043f\u043e\u0434\u043e\u0431\u0438\u0435 \u0433\u0440\u0443\u043f\u043f\u044b \u0432 \u0442\u0435\u043b\u0435\u0433\u0440\u0430\u043c, \u0433\u0434\u0435 \u0438 \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u0438\u0445 \u043e\u0431\u0449\u0435\u043d\u0438\u0435.<\/p>\n<p>\u0412 \u043a\u0430\u0436\u0434\u043e\u0439 \u043a\u043e\u043c\u043d\u0430\u0442\u0435 \u0438\u043c\u0435\u0435\u0442\u0441\u044f \u043e\u0431\u044a\u0435\u043a\u0442 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f. \u0412 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430\u0445 \u044d\u0442\u043e\u0433\u043e \u043e\u0431\u044a\u0435\u043a\u0442\u0430 \u0445\u0440\u0430\u043d\u044f\u0442\u0441\u044f \u0432\u0441\u0435 \u043d\u0443\u0436\u043d\u044b\u0435 \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0434\u0430\u043d\u043d\u044b\u0435 &#8212; \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 \u0441\u0442\u0430\u0442\u0443\u0441 \u043b\u0430\u043c\u043f\u043e\u0447\u043a\u0438. \u041e\u0431\u0449\u0435\u043d\u0438\u0435 \u043c\u0435\u0436\u0434\u0443 \u043f\u043b\u0430\u0442\u0430\u043c\u0438 \u0438 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435\u043c \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u043f\u043e \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b\u0443 web sockets. \u0415\u0441\u043b\u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c \u0441\u0435\u0440\u0432\u0435\u0440 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e, \u0442\u043e \u0430\u0440\u0434\u0443\u0438\u043d\u0430 \u043f\u043e\u043b\u0443\u0447\u0438\u0442 \u043a\u043e\u043c\u0430\u043d\u0434\u0443 \u0447\u0435\u0440\u0435\u0437 4 \u043c\u0438\u043b\u043b\u0438\u0441\u0435\u043a\u0443\u043d\u0434\u044b \u043f\u043e\u0441\u043b\u0435 \u043d\u0430\u0436\u0430\u0442\u0438\u044f \u043a\u043d\u043e\u043f\u043a\u0438 \u0432 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0438 &#8212; \u0432\u043f\u043e\u043b\u043d\u0435 \u043d\u0435 \u043f\u043b\u043e\u0445\u043e)<\/p>\n<h2>\u0414\u043b\u044f \u043f\u0440\u0438\u043c\u0435\u0440\u0430 \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u0441\u043e\u0431\u0435\u0440\u0435\u043c \u0443\u043c\u043d\u0443\u044e \u043b\u0430\u043c\u043f\u043e\u0447\u043a\u0443.<\/h2>\n<p>\u0427\u0442\u043e\u0431\u044b \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u0441\u0438\u0441\u0442\u0435\u043c\u0443, \u043c\u043e\u0436\u0435\u0442\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043c\u043e\u0439 <a href=\"https:\/\/www.appex-system.ru\/\" rel=\"noopener noreferrer nofollow\">\u0441\u0435\u0440\u0432\u0435\u0440<\/a>. \u0415\u0441\u043b\u0438 \u0445\u043e\u0442\u0438\u0442\u0435 \u043f\u043e\u0434\u043d\u044f\u0442\u044c \u0435\u0451 \u043d\u0430 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e\u0439 \u043c\u0430\u0448\u0438\u043d\u0435, \u0432\u043e\u0442 \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u0430\u044f \u0438\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u044f \u0434\u043b\u044f \u0412\u0430\u0441:<\/p>\n<details class=\"spoiler\">\n<summary>\u041b\u043e\u043a\u0430\u043b\u044c\u043d\u0430\u044f \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430<\/summary>\n<div class=\"spoiler__content\">\n<ol>\n<li>\n<p>\u0421\u0442\u0430\u0432\u0438\u043c \u0432\u0441\u0451 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0435. \u041f\u043e\u0434\u0440\u043e\u0431\u043d\u043e \u0437\u0430\u043e\u0441\u0442\u0440\u044f\u0442\u044c \u043d\u0430 \u044d\u0442\u043e\u043c \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435 \u043d\u0435 \u0431\u0443\u0434\u0443, \u0438\u043d\u0444\u044b \u043f\u043e\u043b\u043d\u043e \u0432 \u0438\u043d\u0442\u0435\u0440\u043d\u0435\u0442\u0435. \u041c\u043e\u0436\u043d\u043e \u043f\u043e\u0447\u0438\u0442\u0430\u0442\u044c \u044d\u0442\u0438 \u0433\u0430\u0439\u0434\u044b: <a href=\"https:\/\/www.digitalocean.com\/community\/tutorials\/how-to-install-mongodb-on-ubuntu-20-04-ru\" rel=\"noopener noreferrer nofollow\">\u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430 mongodb<\/a>, <a href=\"https:\/\/www.digitalocean.com\/community\/tutorials\/node-js-debian-9-ru\" rel=\"noopener noreferrer nofollow\">\u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430 nodejs<\/a>.<\/p>\n<\/li>\n<li>\n<p>\u041a\u043b\u043e\u043d\u0438\u0440\u0443\u0435\u043c \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0439.<code>git clone https:\/\/github.com\/andaran\/appex-system<\/code>.<\/p>\n<\/li>\n<li>\n<p>\u0421\u043a\u0430\u0447\u0438\u0432\u0430\u0435\u043c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0435 \u043f\u0430\u043a\u0435\u0442\u044b. <code>npm i<\/code><\/p>\n<\/li>\n<li>\n<p>\u0421\u043e\u0437\u0434\u0430\u0435\u043c \u043a\u043e\u043d\u0444\u0438\u0433 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f. \u041f\u0440\u043e\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u043c \u0442\u0443\u0434\u0430 \u043f\u0430\u0440\u043e\u043b\u0438 \u0434\u043b\u044f \u0441\u0435\u0441\u0441\u0438\u0439, \u0431\u0430\u0437\u0443 \u0434\u0430\u043d\u043d\u044b\u0445, \u043f\u043e\u0440\u0442, \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0434\u043b\u044f smtp \u043f\u043e\u0447\u0442\u044b.\u00a0<code>nano .env<\/code><\/p>\n<pre><code># .env  # application sessionSecretKey1=********** sessionSecretKey2=********** database=mongodb:\/\/127.0.0.1\/appex port=3001  # smtp mailer mailUser=appex.system@yandex.ru mailPass=********** mailPort=465 mailHost=smtp.yandex.ru<\/code><\/pre>\n<\/li>\n<li>\n<p>\u0421\u043e\u0431\u0438\u0440\u0430\u0435\u043c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435.\u00a0<code>npm run build<\/code><\/p>\n<\/li>\n<li>\n<p>\u0417\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c!\u00a0<code>node appex<\/code><\/p>\n<\/li>\n<\/ol>\n<p>\u0425\u043e\u0442\u0435\u043b\u043e\u0441\u044c \u0431\u044b \u043e\u0431\u0440\u0430\u0442\u0438\u0442\u044c \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435 \u043d\u0430 smtp. \u0422.\u043a. \u043f\u0440\u043e\u0435\u043a\u0442 \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u043b\u0441\u044f \u0434\u043b\u044f \u043f\u0443\u0431\u043b\u0438\u043a\u0430\u0446\u0438\u0438 \u0432 \u0438\u043d\u0442\u0435\u0440\u043d\u0435\u0442\u0435, \u0434\u043b\u044f \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u0438 \u043d\u0430 \u043f\u043e\u0447\u0442\u0443 \u043f\u0440\u0438\u0445\u043e\u0434\u0438\u0442 \u043a\u043e\u0434. \u0414\u043b\u044f \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0438 \u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e \u043e\u0431\u044b\u0447\u043d\u044b\u0439 \u0430\u043a\u043a\u0430\u0443\u043d\u0442 \u044f\u043d\u0434\u0435\u043a\u0441\u0430. \u0412 \u043a\u043e\u043d\u0444\u0438\u0433\u0435 \u043d\u0443\u0436\u043d\u043e \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u043b\u043e\u0433\u0438\u043d \u0438 \u043f\u0430\u0440\u043e\u043b\u044c \u043e\u0442 \u043d\u0435\u0433\u043e.<\/p>\n<p>\u041a\u043b\u044e\u0447\u0438 \u0434\u043b\u044f \u0441\u0435\u0441\u0441\u0438\u0439 \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0435\u043c \u0440\u0430\u043d\u0434\u043e\u043c\u043d\u044b\u0435 \u0438 \u0437\u0430\u0431\u044b\u0432\u0430\u0435\u043c.<\/p>\n<p>\u041d\u0430 \u044d\u0442\u043e\u043c \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430 \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0430.<\/p>\n<\/div>\n<\/details>\n<p>\u0414\u043b\u044f \u043d\u0430\u0447\u0430\u043b\u0430 \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u0443\u0435\u043c\u0441\u044f \u0432 \u0441\u0438\u0441\u0442\u0435\u043c\u0435. \u0414\u0443\u043c\u0430\u044e, \u0441 \u044d\u0442\u0438\u043c \u0431\u0435\u0437 \u043f\u0440\u043e\u0431\u043b\u0435\u043c \u0441\u043f\u0440\u0430\u0432\u0438\u0442\u0441\u044f \u043a\u0430\u0436\u0434\u044b\u0439. \u0414\u0430\u043b\u0435\u0435 \u0412\u0430\u043c \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u0435\u0434\u043b\u043e\u0436\u0435\u043d\u043e \u043f\u0440\u043e\u0439\u0442\u0438 \u043e\u0431\u0443\u0447\u0435\u043d\u0438\u0435. \u041f\u043e\u0441\u043b\u0435 \u0435\u0433\u043e \u043f\u0440\u043e\u0445\u043e\u0436\u0434\u0435\u043d\u0438\u044f \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u0438\u0441\u0442\u0443\u043f\u0430\u0442\u044c \u043a \u0440\u0430\u0431\u043e\u0442\u0435.<\/p>\n<figure class=\"float\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w780q1\/getpro\/habr\/upload_files\/ee6\/812\/0e5\/ee68120e5d3ff22c92ec910ea352f622.jpg\" alt=\"\u041c\u0435\u043d\u044e \u043f\u0440\u043e\u0435\u043a\u0442\u043e\u0432\" title=\"\u041c\u0435\u043d\u044e \u043f\u0440\u043e\u0435\u043a\u0442\u043e\u0432\" width=\"481\" height=\"699\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/ee6\/812\/0e5\/ee68120e5d3ff22c92ec910ea352f622.jpg\" data-blurred=\"true\"\/><figcaption>\u041c\u0435\u043d\u044e \u043f\u0440\u043e\u0435\u043a\u0442\u043e\u0432<\/figcaption><\/figure>\n<p>\u0414\u043b\u044f \u0412\u0430\u0441 \u0443\u0436\u0435 \u0441\u043e\u0437\u0434\u0430\u0434\u0443\u0442\u0441\u044f \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0438 \u043a\u043e\u043c\u043d\u0430\u0442\u0430 \u043a \u043d\u0435\u043c\u0443. \u0418\u0445 \u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c. \u0416\u043c\u0435\u043c \u043d\u0430 \u0437\u043d\u0430\u0447\u043e\u043a \u043b\u0430\u043c\u043f\u043e\u0447\u043a\u0438, \u0447\u0442\u043e\u0431\u044b \u043e\u0442\u043a\u0440\u044b\u0442\u044c \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440 \u043a\u043e\u0434\u0430. \u0412 \u043d\u0435\u043c \u0441\u0432\u0435\u0440\u0445\u0443 \u0435\u0441\u0442\u044c \u0441\u0442\u0440\u043e\u043a\u0430 &#171;\u041f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u0442\u044c\u0441\u044f \u043a \u043a\u043e\u043c\u043d\u0430\u0442\u0435&#187;. \u041f\u0440\u0438 \u043d\u0430\u0432\u0435\u0434\u0435\u043d\u0438\u0438 \u043d\u0430 \u043d\u0435\u0451 \u0432\u044b\u043b\u0435\u0437\u0435\u0442 \u043c\u0435\u043d\u044e, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u0443\u0436\u0435 \u0431\u0443\u0434\u0443\u0442 \u0432\u043f\u0438\u0441\u0430\u043d\u044b \u0434\u0430\u043d\u043d\u044b\u0435 \u0441\u043e\u0437\u0434\u0430\u043d\u043d\u043e\u0439 \u043a\u043e\u043c\u043d\u0430\u0442\u044b. \u041c\u043e\u0436\u043d\u043e \u043e\u0442\u043a\u0440\u044b\u0442\u044c \u044d\u043c\u0443\u043b\u044f\u0442\u043e\u0440, \u043f\u043e\u0436\u043c\u0430\u043a\u0430\u0442\u044c \u043d\u0430 \u043a\u043d\u043e\u043f\u043a\u0443 \u0438 \u0443\u0431\u0435\u0434\u0438\u0442\u044c\u0441\u044f, \u0447\u0442\u043e \u0432\u0441\u0451 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442.<\/p>\n<p> \u0422\u0435\u043f\u0435\u0440\u044c \u0437\u0430\u0439\u043c\u0435\u043c\u0441\u044f \u0434\u043e\u043f\u0438\u043b\u0438\u0432\u0430\u043d\u0438\u0435\u043c \u043a\u043e\u0434\u0430. \u0427\u0442\u043e\u0431\u044b \u0431\u044b\u043b\u043e \u0443\u0434\u043e\u0431\u043d\u0435\u0435 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c, \u043c\u043e\u0436\u0435\u0442\u0435 \u043d\u0430\u0436\u0430\u0442\u044c Alt + V. \u041a\u043e\u0434 \u043e\u0442\u043a\u0440\u043e\u0435\u0442\u0441\u044f \u043d\u0430 \u0432\u0435\u0441\u044c \u044d\u043a\u0440\u0430\u043d.<\/p>\n<p>\u0414\u043e\u043f\u043e\u043b\u043d\u0438\u043c \u0432\u0435\u0440\u0441\u0442\u043a\u0443 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f. \u0412 \u043f\u0440\u0430\u0432\u043e\u043c \u0432\u0435\u0440\u0445\u043d\u0435\u043c \u0443\u0433\u043b\u0443 \u044d\u043a\u0440\u0430\u043d\u0430 \u0431\u0443\u0434\u0435\u0442 \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u044c\u0441\u044f \u0438\u043d\u0434\u0438\u043a\u0430\u0442\u043e\u0440 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f \u043b\u0430\u043c\u043f\u044b \u043a \u0441\u0435\u0442\u0438 \u0438 \u0440\u0435\u0436\u0438\u043c \u043e\u0431\u044b\u0447\u043d\u043e\u0439 \u043b\u0430\u043c\u043f\u044b. \u0415\u0441\u043b\u0438 \u0432\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u044d\u0442\u043e\u0442 \u0440\u0435\u0436\u0438\u043c, \u0442\u043e \u043f\u043e\u0441\u043b\u0435 \u043f\u043e\u0434\u0430\u0447\u0438 \u044d\u043b\u0435\u043a\u0442\u0440\u0438\u0447\u0435\u0441\u0442\u0432\u0430 \u043d\u0430 \u043b\u0430\u043c\u043f\u0443 \u043e\u043d\u0430 \u0437\u0430\u0433\u043e\u0440\u0438\u0442\u0441\u044f \u043d\u0435 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e \u043e\u0442 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0432\u0438\u0440\u0442\u0443\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0432\u044b\u043a\u043b\u044e\u0447\u0430\u0442\u0435\u043b\u044f.<\/p>\n<p>\u0412 .app-wrap \u0432 \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u0435 data-theme \u0443\u043a\u0430\u0436\u0435\u043c \u0446\u0432\u0435\u0442 \u0441\u0442\u0430\u0442\u0443\u0441 \u0431\u0430\u0440\u0430 \u0442\u0435\u043b\u0435\u0444\u043e\u043d\u0430 \u043f\u0440\u0438 \u043e\u0442\u043a\u0440\u044b\u0442\u0438\u0438 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f. \u0415\u0449\u0451 \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u0433\u043e\u0442\u043e\u0432\u044b\u0439 \u043f\u0440\u0435\u0441\u0435\u0442 \u0432\u044b\u043a\u043b\u044e\u0447\u0430\u0442\u0435\u043b\u044f. \u041e \u043f\u0440\u0435\u0441\u0435\u0442\u0430\u0445 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u043e \u0432 <a href=\"https:\/\/www.appex-system.ru\/doc#presets\" rel=\"noopener noreferrer nofollow\">\u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438<\/a> \u043f\u0440\u043e\u0435\u043a\u0442\u0430.<\/p>\n<details class=\"spoiler\">\n<summary>HTML<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"xml\"> &lt;!-- \u043e\u0431\u0435\u0440\u0442\u043a\u0430 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f --> &lt;div class=\"app-wrap\"      data-role=\"config\"      data-theme=\"rgba(239, 239, 239)\">          &lt;div class=\"tools-wrap\">         &lt;div class=\"indicator\" id=\"indicator\">&lt;\/div>         [[Switch id=\"switch\"]]    &lt;\/div>          &lt;!-- ----------------- -->          &lt;div class=\"center-block\">                  &lt;!-- \u043a\u0440\u0443\u0436\u043e\u043a \u0437\u0430 \u043a\u043d\u043e\u043f\u043a\u043e\u0439 -->         &lt;div class=\"app-button-wrap\" id=\"app-button-wrap\">              &lt;!-- \u043a\u043d\u043e\u043f\u043a\u0430 -->             &lt;div class=\"app-button\" id=\"app-button\">                  &lt;!-- \u0438\u043a\u043e\u043d\u043a\u0430 -->                 [[Icon name=\"faPowerOff\"]]             &lt;\/div>         &lt;\/div>     &lt;\/div> &lt;\/div><\/code><\/pre>\n<\/div>\n<\/details>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043d\u0430\u043f\u0438\u0448\u0435\u043c \u0441\u0442\u0438\u043b\u0438. \u0422\u0443\u0442 \u043d\u0438\u0447\u0435\u0433\u043e \u043d\u0435\u043e\u0431\u044b\u0447\u043d\u043e\u0433\u043e.<\/p>\n<details class=\"spoiler\">\n<summary>CSS<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"css\"> \/* \u043e\u0431\u0435\u0440\u0442\u043a\u0430 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f *\/ .app-wrap {     height: 100vh;     display: flex;     justify-content: center;     align-items: center; }  \/* \u043a\u0440\u0443\u0436\u043e\u043a \u0437\u0430 \u043a\u043d\u043e\u043f\u043a\u043e\u0439 *\/ .app-button-wrap {     width: 120px;     height: 120px;     background: #c8d6e5;     border-radius: 50%;     display: flex;     justify-content: center;     align-items: center;     opacity: 0.8;     transition: .5s;     margin: auto; }  \/* \u043a\u043d\u043e\u043f\u043a\u0430 *\/ .app-button {     width: 110px;     height: 110px;     background: white;     border-radius: 50%;     color: #c8d6e5;     display: flex;     justify-content: center;     align-items: center;     font-size: 32px;     transition: .1s; }  \/* \u043a\u043d\u043e\u043f\u043a\u0430 \u043f\u0440\u0438 \u043a\u043b\u0438\u043a\u0435 *\/ .app-button:active {     transform: scale(.98); }  .center-block {     display: flex;     justify-content: center;     align-items: center; }  .indicator {     width: 24px;     height: 24px;      border-radius: 50%;     background: #ccc; }  #switch {     width: auto;     height: auto; }  .tools-wrap {     position: absolute;     top: 5px;     right: 5px;     display: flex;     align-items: center; }  .appex-preset-switch__handle {     width: 40px;     height: 24px; }  .appex-preset-switch__handle:after {     box-shadow: none;        height: 20px;     width: 20px;     margin-left: -16px; }  .appex-preset-switch__input:checked + .appex-preset-switch__handle {     background: #00d2d3; }      .appex-preset-switch__input:checked + .appex-preset-switch__handle:after {     margin-right: -16px; } <\/code><\/pre>\n<\/div>\n<\/details>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0441\u0430\u043c\u043e\u0435 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u043e\u0435 &#8212; js \u043a\u043e\u0434 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f. <\/p>\n<ol>\n<li>\n<p>\u0414\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u043e\u0431\u044a\u0435\u043a\u0442 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f \u0441 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f\u043c\u0438 \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e.<\/p>\n<pre><code class=\"javascript\">\/* \u043d\u0430\u0447\u0430\u043b\u044c\u043d\u043e\u0435 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 *\/ App.state = {   status: true,     isOnline: true,     autoEnable: false, }<\/code><\/pre>\n<\/li>\n<li>\n<p>\u041e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u043c \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438. <\/p>\n<pre><code class=\"javascript\">\/* \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 *\/ App.settings = {   awaitResponse: true, }<\/code><\/pre>\n<\/li>\n<li>\n<p>\u041d\u0430\u0445\u043e\u0434\u0438\u043c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0435 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u044b \u0438 \u0432\u0435\u0448\u0430\u0435\u043c \u043d\u0430 \u043d\u0438\u0445 \u0441\u043b\u0443\u0448\u0430\u0442\u0435\u043b\u0438 \u0441\u043e\u0431\u044b\u0442\u0438\u044f. \u041d\u043e\u0432\u043e\u0435 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043c\u0435\u0442\u043e\u0434\u0430 <code>App.send();<\/code><\/p>\n<pre><code class=\"javascript\">\/* \u0432\u0435\u0448\u0430\u0435\u043c \u0441\u043b\u0443\u0448\u0430\u0442\u0435\u043b\u0438 \u0441\u043e\u0431\u044b\u0442\u0438\u0439 *\/ button.addEventListener('click', () => { App.send({ status: !App.state.status });   window.navigator.vibrate(40); });  swtch.addEventListener('change', e => { App.send({ autoEnable: e.target.checked }); });<\/code><\/pre>\n<\/li>\n<li>\n<p>\u0414\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0443 \u043d\u0430 \u043e\u043d\u043b\u0430\u0439\u043d. \u041a\u0430\u0436\u0434\u044b\u0435 10 \u0441\u0435\u043a\u0443\u043d\u0434 \u043c\u0435\u043d\u044f\u0435\u043c \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u043e isOnline \u043d\u0430 false. \u0415\u0441\u043b\u0438 \u0432 \u0442\u0435\u0447\u0435\u043d\u0438\u0435 3 \u0441\u0435\u043a\u0443\u043d\u0434 \u043b\u0430\u043c\u043f\u0430 \u043d\u0435 \u043e\u043f\u0440\u043e\u0432\u0435\u0440\u0433\u0430\u0435\u0442 \u044d\u0442\u043e, \u0433\u0430\u0441\u0438\u043c \u0438\u043d\u0434\u0438\u043a\u0430\u0442\u043e\u0440 \u043e\u043d\u043b\u0430\u0439\u043d\u0430.<\/p>\n<pre><code class=\"javascript\">\/* \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u043d\u0430 \u043e\u043d\u043b\u0430\u0439\u043d *\/ setInterval(() => {     App.send({ isOnline: false });     setTimeout(() => {         if (!App.state.isOnline) {             indicator.style.backgroundColor = '#ccc';         }     }, 3000); }, 10000);<\/code><\/pre>\n<\/li>\n<li>\n<p>\u041f\u043e\u0434\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u043c\u0441\u044f \u043d\u0430 \u0441\u043e\u0431\u044b\u0442\u0438\u0435 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f. \u041f\u0440\u0438 \u043f\u0440\u0438\u0445\u043e\u0434\u0435 \u043d\u043e\u0432\u043e\u0433\u043e \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f \u043c\u0435\u043d\u044f\u0435\u043c \u0432\u043d\u0435\u0448\u043d\u0438\u0439 \u0432\u0438\u0434 \u0432\u0441\u0435\u0445 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u043d\u0430 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0439.<\/p>\n<pre><code class=\"javascript\">\/* \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f *\/ App.on('update', state => {   if (state.status) {     button.style.color = '#00d2d3';     wrap.style.backgroundColor = '#00d2d3';   } else {     button.style.color = '#c8d6e5';     wrap.style.backgroundColor = '#c8d6e5';   }        swtch.querySelector('input').checked = state.autoEnable;       if (state.isOnline) {     indicator.style.backgroundColor = '#00d2d3';   } });<\/code><\/pre>\n<\/li>\n<li>\n<p>\u0417\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435. \u041d\u0430 \u044d\u0442\u043e\u043c \u0441 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u0435\u043c \u043a\u043e\u0434\u0430 \u043f\u043e\u0434 \u043d\u0435\u0433\u043e \u043c\u044b \u0437\u0430\u043a\u043e\u043d\u0447\u0438\u043b\u0438.<\/p>\n<pre><code class=\"javascript\">\/* \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 *\/ App.start();<\/code><\/pre>\n<\/li>\n<\/ol>\n<details class=\"spoiler\">\n<summary>\u0421\u043a\u0440\u0438\u043d\u0448\u043e\u0442 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f<\/summary>\n<div class=\"spoiler__content\">\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w780q1\/getpro\/habr\/upload_files\/487\/807\/77c\/48780777c8f9a3564b2123cd9ba0d603.jpg\" width=\"576\" height=\"1280\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/487\/807\/77c\/48780777c8f9a3564b2123cd9ba0d603.jpg\" data-blurred=\"true\"\/><figcaption><\/figcaption><\/figure>\n<\/div>\n<\/details>\n<h2>\u041f\u0438\u0448\u0435\u043c \u043a\u043e\u0434 \u0434\u043b\u044f \u043c\u0438\u043a\u0440\u043e\u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u0430<\/h2>\n<p>\u0412 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u043c\u0438\u043a\u0440\u043e\u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u0430 \u0431\u044b\u043b \u0432\u0437\u044f\u0442 \u043f\u043e\u043f\u0443\u043b\u044f\u0440\u043d\u044b\u0439 esp-01. \u041a \u043d\u0435\u043c\u0443 \u0434\u043e\u043a\u0443\u043f\u0438\u043b \u0442\u0430\u043a\u0438\u0435 <a href=\"https:\/\/aliexpress.ru\/item\/1005001898935382.html?algo_pvid=4b9715ab-ad5b-417e-aac9-a2a0101d0357&amp;algo_expid=4b9715ab-ad5b-417e-aac9-a2a0101d0357-0&amp;btsid=0b8b034116274797812615512ef138&amp;ws_ab_test=searchweb0_0,searchweb201602_,searchweb201603_\" rel=\"noopener noreferrer nofollow\">\u0440\u0435\u043b\u0435<\/a> \u0438 <a href=\"https:\/\/aliexpress.ru\/item\/4001252926156.html?algo_pvid=63ffa007-5613-44f1-b1c9-ac4bbc732ef4&amp;algo_expid=63ffa007-5613-44f1-b1c9-ac4bbc732ef4-10&amp;btsid=0b8b034116274800357112148ef138&amp;ws_ab_test=searchweb0_0,searchweb201602_,searchweb201603_\" rel=\"noopener noreferrer nofollow\">\u0431\u043b\u043e\u043a \u043f\u0438\u0442\u0430\u043d\u0438\u044f<\/a>. <\/p>\n<p>\u041f\u0438\u043b\u0438\u043c \u043f\u0440\u043e\u0448\u0438\u0432\u043a\u0443 \u0438 \u0437\u0430\u043b\u0438\u0432\u0430\u0435\u043c \u0447\u0435\u0440\u0435\u0437 arduino ide.<\/p>\n<details class=\"spoiler\">\n<summary>\u041f\u0440\u043e\u0448\u0438\u0432\u043a\u0430<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"cpp\"> \/\/ \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0435 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 #include &lt;ESP8266WiFi.h> #include &lt;ArduinoJson.h> #include &lt;WebSocketsClient.h> #include &lt;SocketIOclient.h> #include &lt;string> #include &lt;unordered_map>  SocketIOclient socketIO;    \/*   ---==== \u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 ====---   *\/  #define ussid \"\"  \/\/ \u0418\u043c\u044f wifi #define pass \"\"  \/\/ \u041f\u0430\u0440\u043e\u043b\u044c wifi #define roomID \"\"  \/\/ ID \u043a\u043e\u043c\u043d\u0430\u0442\u044b #define roomPass \"\"  \/\/ \u041f\u0430\u0440\u043e\u043b\u044c \u043a\u043e\u043c\u043d\u0430\u0442\u044b  \/*   ------------------------   *\/  \/*    \u042f \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0434\u043e\u043b\u0433\u043e \u0438\u0441\u043a\u0430\u043b \u0441\u043f\u043e\u0441\u043e\u0431\u044b \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438 \u0432 c++,   \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0431\u0443\u0434\u0443\u0442 \u0431\u043e\u043b\u044c\u0448\u0435 \u0432\u0441\u0435\u0433\u043e \u043f\u043e\u0445\u043e\u0436\u0438 \u043d\u0430 \u043e\u0431\u044a\u0435\u043a\u0442 js (\u043c\u044b \u0432\u0435\u0434\u044c \u043f\u0430\u0440\u0441\u0438\u043c json).   std::unordered_map - \u0441\u0430\u043c\u044b\u0439 \u043f\u043e\u0434\u0445\u043e\u0434\u044f\u0449\u0438\u0439, \u0442.\u043a. \u0438\u0437 \u043d\u0435\u0433\u043e \u043c\u043e\u0436\u043d\u043e \u0432\u044b\u0442\u044f\u043d\u0443\u0442\u044c \u0438\u043b\u0438   \u0438\u0437\u043c\u0435\u043d\u0438\u0442\u044c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430, \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u043f\u0435\u0440\u0435\u0434\u0430\u043d\u043e \u0447\u0435\u0440\u0435\u0437 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u0443\u044e.   \u042d\u0442\u043e \u0434\u0430\u0435\u0442 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0432\u044b\u0431\u043e\u0440\u043e\u0447\u043d\u043e \u043e\u0431\u043d\u043e\u0432\u043b\u044f\u0442\u044c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0432\u043e \u0432\u0440\u0435\u043c\u044f    \u043f\u0430\u0440\u0441\u0438\u043d\u0433\u0430 json`\u0430.     [!!!] \u0414\u0430\u043d\u043d\u044b\u0439 \u0441\u043f\u0438\u0441\u043e\u043a \u0434\u043e\u043b\u0436\u0435\u043d \u043f\u043e\u043b\u043d\u043e\u0441\u0442\u044c\u044e \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0432\u043e\u0432\u0430\u0442\u044c          \u043e\u0431\u044a\u0435\u043a\u0442\u0443 App.state \u0432 \u043a\u043e\u0434\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f.         \u0422\u0430\u043a\u0436\u0435 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u043e \"lastChange\" - \u043e\u043d\u043e \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442         \u0432\u0440\u0435\u043c\u044f \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0435\u0433\u043e \u043e\u0431\u0440\u0430\u0449\u0435\u043d\u0438\u044f \u043a \u043a\u043e\u043c\u043d\u0430\u0442\u0435.    *\/  std::unordered_map&lt;std::string, std::string> receivedState = {   { \"status\", \"true\" },   { \"isOnline\", \"true\" },   { \"lastChange\", \"0\" },   { \"autoEnable\", \"false\" } };  bool light = LOW;    \/*   ---==== \u0424\u0443\u043d\u043a\u0446\u0438\u044f \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f ====---   *\/  void updateParams(String messageType) {    \/*          \u0418\u043c\u0435\u043d\u043d\u043e \u0432 \u044d\u0442\u043e\u0439 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u043d\u043e\u0432\u043e\u0435 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435.     \u041a \u0441\u043e\u0436\u0430\u043b\u0435\u043d\u0438\u044e, \u0432\u0441\u0435 \u0442\u0438\u043f\u044b \u0434\u0430\u043d\u043d\u044b\u0445 \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u0443\u044e\u0442\u0441\u044f \u0432 \u0441\u0442\u0440\u043e\u043a\u0438,     \u043d\u043e \u0437\u0430\u043f\u0430\u0440\u0441\u0438\u0442\u044c \u0447\u0438\u0441\u043b\u043e \u0438\u0437 \u0441\u0442\u0440\u043e\u043a\u0438 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u044e\u0442 \u0432\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u044b\u0435     \u0430\u0440\u0434\u0443\u0438\u043d\u043e\u0432\u0441\u043a\u0438\u0435 \u043c\u0435\u0442\u043e\u0434\u044b.         *\/    String status = receivedState.at(\"status\").c_str();   String online = receivedState.at(\"isOnline\").c_str();   String autoEnable = receivedState.at(\"autoEnable\").c_str();      \/* \u0432\u043a\u043b\u044e\u0447\u0430\u0435\u043c \u043b\u0430\u043c\u043f\u0443 *\/   if (status == \"true\" &amp;&amp; messageType != \"connectSuccess\") {     light = LOW;     Serial.println(\"RELAY ON\");   }       \/* \u0432\u044b\u043a\u043b\u044e\u0447\u0430\u0435\u043c \u043b\u0430\u043c\u043f\u0443 *\/   if (status == \"false\" &amp;&amp; messageType != \"connectSuccess\") {     light = HIGH;     Serial.println(\"RELAY OFF\");   }    \/* \u043f\u043e\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0430\u0435\u043c, \u0447\u0442\u043e \u043b\u0430\u043c\u043f\u0430 \u0432 \u0441\u0435\u0442\u0438 *\/   if (online == \"false\") {     DynamicJsonDocument doc(1024);     JsonObject sendState = doc.createNestedObject();     sendState[\"isOnline\"] = true;     message(\"updateState\", sendState);   }     \/* \u0432\u043a\u043b\u044e\u0447\u0430\u0435\u043c \u043b\u0430\u043c\u043f\u0443 \u043f\u0440\u0438 \u0440\u0435\u0436\u0438\u043c\u0435 \u0430\u0432\u0442\u043e\u0432\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f *\/   if (messageType == \"connectSuccess\" &amp;&amp; autoEnable == \"true\") {     DynamicJsonDocument doc(1024);     JsonObject sendState = doc.createNestedObject();     sendState[\"status\"] = true;     message(\"updateState\", sendState);   } }    \/*   ---==== \u0421\u043e\u0431\u044b\u0442\u0438\u044f ====---   *\/  void socketIOEvent(socketIOmessageType_t type, uint8_t * payload, size_t length) {   switch (type) {     case sIOtype_DISCONNECT: {         Serial.println(\"[IOc] \u041e\u0448\u0438\u0431\u043a\u0430 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f!\\n\");                } break;      case sIOtype_CONNECT: {         Serial.println(\"[IOc] \u041f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u043e!\");          \/\/ join default namespace (no auto join in Socket.IO V3)         socketIO.send(sIOtype_CONNECT, \"\/\");          \/*            \u0422\u0435\u043f\u0435\u0440\u044c \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0430\u0435\u043c\u0441\u044f \u043a \u043a\u043e\u043c\u043d\u0430\u0442\u0435.            \u042d\u0442\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u043a\u0430\u043a \u0433\u0440\u0443\u043f\u043f\u0430 \u0432 \u043a\u0430\u043a\u043e\u043c-\u043d\u0438\u0431\u0443\u0434\u044c \u043c\u0435\u0441\u0441\u0435\u043d\u0434\u0436\u0435\u0440\u0435 -            \u043a\u0430\u043a \u0442\u043e\u043b\u044c\u043a\u043e \u043e\u0434\u0438\u043d \u0443\u0447\u0430\u0441\u0442\u043d\u0438\u043a \u043d\u0430\u043f\u0438\u0448\u0435\u0442 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435            (\u043f\u0435\u0440\u0435\u0434\u0430\u0441\u0442 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435 \u0434\u043b\u044f \u043e\u0431\u044a\u0435\u043a\u0442\u0430 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f),           \u044d\u0442\u043e \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 \u0441\u0440\u0430\u0437\u0443 \u0436\u0435 \u043f\u043e\u043b\u0443\u0447\u0430\u0442 \u0432\u0441\u0435 \u0434\u0440\u0443\u0433\u0438\u0435 \u0443\u0447\u0430\u0441\u0442\u043d\u0438\u043a\u0438            (\u0442\u0435\u043b\u0435\u0444\u043e\u043d\u044b, \u043f\u043b\u0430\u0442\u044b esp, \u043c\u043e\u0436\u043d\u043e \u0438 \u043c\u0430\u043b\u0438\u043d\u0443 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u0442\u044c).                     *\/         connectToRoom();        } break;      case sIOtype_EVENT: {         char* json = (char*) payload;          \/\/ \u043f\u0430\u0440\u0441\u0438\u043c \u0441\u043e\u0431\u044b\u0442\u0438\u0435 \u0441 \u043d\u043e\u0432\u044b\u043c \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435\u043c         parseEvent(json);        } break;      default: {         Serial.println(\"[IOc] \u041f\u0440\u0438\u0448\u043b\u043e \u0447\u0442\u043e-\u0442\u043e \u043d\u0435\u043f\u043e\u043d\u044f\u0442\u043d\u043e\u0435 :(\");         hexdump(payload, length);        } break;   } }    \/*   ---==== \u0417\u0430\u043c\u0443\u0434\u0440\u0435\u043d\u0430\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u043f\u0430\u0440\u0441\u0438\u043d\u0433\u0430 \u043e\u0442\u0432\u0435\u0442\u0430 \u043e\u0442 \u0441\u0435\u0440\u0432\u0435\u0440\u0430 ====---   *\/  void parseEvent(char* json) {    \/* parse json *\/   String messageType = \"\";   String parsedParams = \"\";   char oldSimbool;   bool parseTypeFlag = false;   bool parseParamsFlag = false;    for (unsigned long i = 0; i &lt; strlen(json); i++) {     if (json[i] == '{') {       parseParamsFlag = true;       parsedParams = \"\";     }      if (json[i] == '\"') {       if (parseTypeFlag) {         parseTypeFlag = false;       } else if (messageType.length() == 0) {         parseTypeFlag = true;       }        if (parseTypeFlag) {         continue;       }     }      if (parseTypeFlag) {       messageType += json[i];     }     if (parseParamsFlag) {       parsedParams += json[i];     }      if (json[i] == '}') {       parseParamsFlag = false;     }     oldSimbool = json[i];   }    StaticJsonDocument&lt;200> doc;   DeserializationError error = deserializeJson(doc, parsedParams);      if (error) {     Serial.print(\"[ERR] \u041e\u0448\u0438\u0431\u043a\u0430 \u043f\u0430\u0440\u0441\u0438\u043d\u0433\u0430 json!\");   } else {          \/* count quantity of params and delete unnecessary symbols *\/     String prms = \"\";     int prmsQuant = 1;     for (unsigned long i = 1; i &lt; parsedParams.length() - 1; i++) {       if (parsedParams[i] == '\"') { continue; }       if (parsedParams[i] == ',') { prmsQuant++; }       prms += parsedParams[i];     }      \/* put params to array cells *\/     String namesAndValues[prmsQuant];     int numberOfParam = 0;     for (unsigned long i = 0; i &lt; prms.length(); i++) {       if (prms[i] == ',') {         numberOfParam++;         continue;       }       namesAndValues[numberOfParam] += prms[i];     }      \/* split params and values *\/     std::string prmName;     std::string prmValue;     char* values[prmsQuant];     bool typeFlag = false;     for (int i = 0; i &lt; prmsQuant; i++) {       typeFlag = false;       prmName = \"\";       prmValue = \"\";       for (int j = 0; j &lt; namesAndValues[i].length(); j++) {         if (namesAndValues[i][j] == ':') {           typeFlag = true;           continue;         }          if (typeFlag) {           prmValue += namesAndValues[i][j];         } else {           prmName += namesAndValues[i][j];         }       }        \/* save changes *\/       if (receivedState.count(prmName) != 0) {         receivedState.at(prmName) = prmValue;       } else {         Serial.print(\"[ERR] \u041d\u0435\u0438\u0437\u0432\u0435\u0441\u0442\u043d\u044b\u0439 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440 \\\"\");         Serial.print(prmName.c_str());         Serial.println(\"\\\"!\");       }     }      \/* call update function *\/     updateParams(messageType);   } }    \/*   ---==== \u041f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 \u043a \u043a\u043e\u043c\u043d\u0430\u0442\u0435 ====---   *\/  void connectToRoom() {    \/\/ \u0434\u0430\u043d\u043d\u044b\u0435 \u043e\u0442\u0441\u044b\u043b\u0430\u044e\u0442\u0441\u044f \u0432 json   DynamicJsonDocument doc(1024);   JsonArray array = doc.to&lt;JsonArray>();    \/\/ \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u0441\u043e\u0431\u044b\u0442\u0438\u044f, \u0432 \u0434\u0430\u043d\u043d\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 - \"connectToRoom\".   array.add(\"connectToRoom\");    \/\/ \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c id \u0438 \u043f\u0430\u0440\u043e\u043b\u044c \u043a\u043e\u043c\u043d\u0430\u0442\u044b \u0434\u043b\u044f \u043f\u0440\u043e\u0445\u043e\u0436\u0434\u0435\u043d\u0438\u044f \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438   JsonObject params = array.createNestedObject();   params[\"roomId\"] = roomID;   params[\"roomPass\"] = roomPass;    \/\/ \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u0443\u0435\u043c json \u0432 \u0441\u0442\u0440\u043e\u043a\u0443   String output;   serializeJson(doc, output);    \/\/ \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u043c \u0441\u043e\u0431\u044b\u0442\u0438\u0435 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f \u043a \u043a\u043e\u043c\u043d\u0430\u0442\u0435    socketIO.sendEVENT(output);    }    \/*   ---==== \u041e\u0442\u043f\u0440\u0430\u0432\u043a\u0430 \u0434\u0430\u043d\u043d\u044b\u0445 ====---   *\/  void message(String eventType, JsonObject sendState) {    \/\/ \u0434\u0430\u043d\u043d\u044b\u0435 \u043e\u0442\u0441\u044b\u043b\u0430\u044e\u0442\u0441\u044f \u0432 json   DynamicJsonDocument doc(1024);   JsonArray array = doc.to&lt;JsonArray>();    \/\/ \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u0441\u043e\u0431\u044b\u0442\u0438\u044f, \u043e\u0431\u044b\u0447\u043d\u043e \u044d\u0442\u043e 'update'   array.add(eventType);    \/\/ \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c id \u0438 \u043f\u0430\u0440\u043e\u043b\u044c \u043a\u043e\u043c\u043d\u0430\u0442\u044b \u0434\u043b\u044f \u043f\u0440\u043e\u0445\u043e\u0436\u0434\u0435\u043d\u0438\u044f \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438,   \/\/ \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435   JsonObject params = array.createNestedObject();   params[\"roomId\"] = roomID;   params[\"roomPass\"] = roomPass;   params[\"params\"] = sendState;    \/\/ \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u0443\u0435\u043c json \u0432 \u0441\u0442\u0440\u043e\u043a\u0443   String output;   serializeJson(doc, output);    \/\/ \u0448\u043b\u0435\u043c \u0441\u043e\u0431\u044b\u0442\u0438\u0435 \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440 appex   socketIO.sendEVENT(output);    }    \/*   ---==== Setup ====---   *\/  void setup() {    \/\/ \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c Serial \u043f\u043e\u0440\u0442   Serial.begin(9600);   Serial.setDebugOutput(false);    pinMode(RELAY, OUTPUT);    digitalWrite(RELAY, light);   Serial.println(\"RELAY ON\");    \/\/ \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0430\u0435\u043c\u0441\u044f \u043a WiFi   WiFi.begin(ussid, pass);   while (WiFi.status() != WL_CONNECTED) {     delay(300);     Serial.print(\".\");   }   Serial.println(\"\\n[LOG] Wifi connected!\\n\");    \/\/ ip \u0430\u0434\u0440\u0435\u0441 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430   String ip = WiFi.localIP().toString();   Serial.printf(\"[SETUP] IP adress: %s\\n\", ip.c_str());    \/\/ \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0430\u0435\u043c\u0441\u044f \u043a \u0441\u0435\u0440\u0432\u0435\u0440\u0443   socketIO.beginSSL(\"appex-system.ru\", 443, \"\/socket.io\/?EIO=4\");    \/\/ \u0435\u0441\u043b\u0438 \u043f\u0440\u0438\u0448\u0435\u043b \u0437\u0430\u043f\u0440\u043e\u0441   socketIO.onEvent(socketIOEvent);    }    \/*   ---==== Loop ====---   *\/  void loop() {    \/\/ \u0441\u043b\u0443\u0448\u0430\u0435\u043c \u0441\u0435\u0440\u0432\u0435\u0440   socketIO.loop();    digitalWrite(RELAY, light);  }<\/code><\/pre>\n<\/div>\n<\/details>\n<figure class=\"float full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w780q1\/getpro\/habr\/upload_files\/17e\/425\/5d4\/17e4255d49fa9569ef9c2386d06d670e.jpg\" width=\"1280\" height=\"958\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/17e\/425\/5d4\/17e4255d49fa9569ef9c2386d06d670e.jpg\" data-blurred=\"true\"\/><figcaption><\/figcaption><\/figure>\n<p>\u0422\u0430\u043a\u0430\u044f \u043b\u0430\u043c\u043f\u0430 \u043f\u043e\u043b\u0443\u0447\u0438\u043b\u0430\u0441\u044c. \u041d\u0438\u0436\u0435 \u043f\u0440\u0438\u0432\u0435\u0434\u0443 \u0432\u0438\u0434\u0435\u043e \u0441 \u0434\u0435\u043c\u043e\u043d\u0441\u0442\u0440\u0430\u0446\u0438\u0435\u0439.<\/p>\n<div class=\"tm-iframe_temp\" data-src=\"https:\/\/embedd.srv.habr.com\/iframe\/6101656a12b0d58fd6dde65e\" data-style=\"\" id=\"6101656a12b0d58fd6dde65e\" width=\"\"><\/div>\n<h2>\u0417\u0430\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435<\/h2>\n<p>\u0418\u0442\u0430\u043a, \u0434\u0430\u043d\u043d\u044b\u0439 \u043f\u0440\u043e\u0435\u043a\u0442 \u043f\u0440\u0435\u0434\u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d \u0434\u043b\u044f \u043b\u044e\u0434\u0435\u0439, \u043a\u043e\u0442\u043e\u0440\u044b\u043c \u043d\u0435 \u0445\u0432\u0430\u0442\u0430\u0435\u0442 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u0445 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043e\u0432 \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0434\u0440\u0443\u0433\u0438\u0445 \u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432 \u0434\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0433\u043e \u0443\u043c\u043d\u043e\u0433\u043e \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430.<br \/>\u0421 \u043f\u043e\u043c\u043e\u0449\u044c\u044e appex \u043c\u043e\u0436\u043d\u043e \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u043f\u0443\u043b\u044c\u0442 \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u043a \u0440\u043e\u0431\u043e\u0442\u0443, \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0434\u043b\u044f \u0441\u043b\u043e\u0436\u043d\u043e\u0433\u043e \u0430\u0432\u0442\u043e\u043f\u043e\u043b\u0438\u0432\u0430, \u0433\u0430\u0439\u0432\u0435\u0440-\u043b\u0430\u043c\u043f\u044b, \u0441\u0430\u043c\u043e\u0434\u0435\u043b\u044c\u043d\u044b\u0445 \u0447\u0430\u0441\u043e\u0432 \u0441 \u043a\u0443\u0447\u0435\u0439 \u0434\u0430\u0442\u0447\u0438\u043a\u043e\u0432 \u043d\u0430 \u0431\u043e\u0440\u0442\u0443 \u0438 \u0442.\u0434. <\/p>\n<p>\u042d\u0442\u043e \u043c\u043e\u044f \u043f\u0435\u0440\u0432\u0430\u044f \u043f\u0443\u0431\u043b\u0438\u043a\u0430\u0446\u0438\u044f. \u0415\u0441\u043b\u0438 \u043a\u043e\u043c\u0443 \u0437\u0430\u0439\u0434\u0435\u0442, \u043c\u043e\u0433\u0443 \u0437\u0430\u0431\u0430\u0446\u0430\u0442\u044c \u0435\u0449\u0451 \u0441\u0442\u0430\u0442\u0435\u0439\u043a\u0443 \u0432 \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0435\u043d\u0438\u0435 \u0442\u0435\u043c\u044b. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u043a\u0430\u043a \u044d\u0442\u0443 \u043b\u0430\u043c\u043f\u0443 \u043a \u044f\u043d\u0434\u0435\u043a\u0441 \u0410\u043b\u0438\u0441\u0435 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u0442\u044c.<\/p>\n<p>\u0412\u0441\u0435\u043c \u0445\u043e\u0440\u043e\u0448\u0435\u0433\u043e \u0434\u043d\u044f.<\/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\/570432\/\"> https:\/\/habr.com\/ru\/articles\/570432\/<\/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<figure class=\"full-width\"><figcaption>\u0418\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u0433\u043b\u0430\u0432\u043d\u043e\u0433\u043e \u043c\u0435\u043d\u044e<\/figcaption><\/figure>\n<p>\u041f\u0440\u0438\u0432\u0435\u0442, \u0425\u0430\u0431\u0440! \u0425\u043e\u0447\u0443 \u043f\u043e\u0434\u0435\u043b\u0438\u0442\u044c\u0441\u044f \u0441\u0432\u043e\u0438\u043c \u043f\u0440\u043e\u0435\u043a\u0442\u043e\u043c, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0440\u0430\u0437\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u043b \u043f\u043e\u0447\u0442\u0438 \u0433\u043e\u0434 &#8212; <a href=\"https:\/\/github.com\/andaran\/appex-system\" rel=\"noopener noreferrer nofollow\">appex-system<\/a>.<\/p>\n<p>\u0414\u0435\u043b\u043e \u043d\u0430\u0447\u0430\u043b\u043e\u0441\u044c \u0441 \u0442\u043e\u0433\u043e, \u0447\u0442\u043e \u044f \u0437\u0430\u043a\u043e\u043d\u0447\u0438\u043b \u0438\u0437\u0443\u0447\u0435\u043d\u0438\u0435 \u043d\u043e\u0434\u044b. \u041d\u0443\u0436\u043d\u043e \u0431\u044b\u043b\u043e \u0437\u0430\u043f\u0438\u043b\u0438\u0442\u044c \u043a\u0430\u043a\u043e\u0439-\u043d\u0438\u0431\u0443\u0434\u044c \u043f\u0440\u043e\u0435\u043a\u0442, \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u0442\u0440\u0435\u043d\u0438\u0440\u043e\u0432\u0430\u0442\u044c\u0441\u044f, \u0438 \u044f \u0440\u0435\u0448\u0438\u043b \u043e\u0431\u044a\u0435\u0434\u0438\u043d\u0438\u0442\u044c 2 \u043b\u044e\u0431\u0438\u043c\u044b\u0445 \u0434\u0435\u043b\u0430 &#8212; \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0438 \u0441\u0430\u043c\u043e\u0434\u0435\u043b\u043a\u0438. \u0418 \u0432\u043e\u0442 \u0447\u0442\u043e \u0438\u0437 \u044d\u0442\u043e\u0433\u043e \u043f\u043e\u043b\u0443\u0447\u0438\u043b\u043e\u0441\u044c.<\/p>\n<p>\u0423\u043c\u043d\u044b\u0439 \u0434\u043e\u043c \u0434\u0435\u043b\u0438\u0442\u0441\u044f \u043d\u0430 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430. \u0423\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u043e\u043c \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u043a\u0430\u043a \u043e\u0434\u043d\u0430 \u043f\u043b\u0430\u0442\u0430 (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 esp8266), \u0442\u0430\u043a \u0438 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e (\u043b\u044e\u0441\u0442\u0440\u0430, \u0441\u043e\u0441\u0442\u043e\u044f\u0449\u0430\u044f \u0438\u0437 4 \u0443\u043c\u043d\u044b\u0445 \u043b\u0430\u043c\u043f\u043e\u0447\u0435\u043a). \u0414\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430 \u043f\u0438\u0448\u0435\u0442\u0441\u044f \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u043d\u0430 js. \u0423\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u043e \u0432 \u043c\u0435\u0441\u0442\u0435 \u0441 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435\u043c \u043e\u0431\u044a\u0435\u0434\u0438\u043d\u044f\u044e\u0442\u0441\u044f \u0432 \u043a\u043e\u043c\u043d\u0430\u0442\u0443, \u043d\u0430\u043f\u043e\u0434\u043e\u0431\u0438\u0435 \u0433\u0440\u0443\u043f\u043f\u044b \u0432 \u0442\u0435\u043b\u0435\u0433\u0440\u0430\u043c, \u0433\u0434\u0435 \u0438 \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u0438\u0445 \u043e\u0431\u0449\u0435\u043d\u0438\u0435.<\/p>\n<p>\u0412 \u043a\u0430\u0436\u0434\u043e\u0439 \u043a\u043e\u043c\u043d\u0430\u0442\u0435 \u0438\u043c\u0435\u0435\u0442\u0441\u044f \u043e\u0431\u044a\u0435\u043a\u0442 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f. \u0412 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430\u0445 \u044d\u0442\u043e\u0433\u043e \u043e\u0431\u044a\u0435\u043a\u0442\u0430 \u0445\u0440\u0430\u043d\u044f\u0442\u0441\u044f \u0432\u0441\u0435 \u043d\u0443\u0436\u043d\u044b\u0435 \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0434\u0430\u043d\u043d\u044b\u0435 &#8212; \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 \u0441\u0442\u0430\u0442\u0443\u0441 \u043b\u0430\u043c\u043f\u043e\u0447\u043a\u0438. \u041e\u0431\u0449\u0435\u043d\u0438\u0435 \u043c\u0435\u0436\u0434\u0443 \u043f\u043b\u0430\u0442\u0430\u043c\u0438 \u0438 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435\u043c \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u043f\u043e \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b\u0443 web sockets. \u0415\u0441\u043b\u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c \u0441\u0435\u0440\u0432\u0435\u0440 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e, \u0442\u043e \u0430\u0440\u0434\u0443\u0438\u043d\u0430 \u043f\u043e\u043b\u0443\u0447\u0438\u0442 \u043a\u043e\u043c\u0430\u043d\u0434\u0443 \u0447\u0435\u0440\u0435\u0437 4 \u043c\u0438\u043b\u043b\u0438\u0441\u0435\u043a\u0443\u043d\u0434\u044b \u043f\u043e\u0441\u043b\u0435 \u043d\u0430\u0436\u0430\u0442\u0438\u044f \u043a\u043d\u043e\u043f\u043a\u0438 \u0432 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0438 &#8212; \u0432\u043f\u043e\u043b\u043d\u0435 \u043d\u0435 \u043f\u043b\u043e\u0445\u043e)<\/p>\n<h2>\u0414\u043b\u044f \u043f\u0440\u0438\u043c\u0435\u0440\u0430 \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u0441\u043e\u0431\u0435\u0440\u0435\u043c \u0443\u043c\u043d\u0443\u044e \u043b\u0430\u043c\u043f\u043e\u0447\u043a\u0443.<\/h2>\n<p>\u0427\u0442\u043e\u0431\u044b \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u0441\u0438\u0441\u0442\u0435\u043c\u0443, \u043c\u043e\u0436\u0435\u0442\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043c\u043e\u0439 <a href=\"https:\/\/www.appex-system.ru\/\" rel=\"noopener noreferrer nofollow\">\u0441\u0435\u0440\u0432\u0435\u0440<\/a>. \u0415\u0441\u043b\u0438 \u0445\u043e\u0442\u0438\u0442\u0435 \u043f\u043e\u0434\u043d\u044f\u0442\u044c \u0435\u0451 \u043d\u0430 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e\u0439 \u043c\u0430\u0448\u0438\u043d\u0435, \u0432\u043e\u0442 \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u0430\u044f \u0438\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u044f \u0434\u043b\u044f \u0412\u0430\u0441:<\/p>\n<details class=\"spoiler\">\n<summary>\u041b\u043e\u043a\u0430\u043b\u044c\u043d\u0430\u044f \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430<\/summary>\n<div class=\"spoiler__content\">\n<ol>\n<li>\n<p>\u0421\u0442\u0430\u0432\u0438\u043c \u0432\u0441\u0451 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0435. \u041f\u043e\u0434\u0440\u043e\u0431\u043d\u043e \u0437\u0430\u043e\u0441\u0442\u0440\u044f\u0442\u044c \u043d\u0430 \u044d\u0442\u043e\u043c \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435 \u043d\u0435 \u0431\u0443\u0434\u0443, \u0438\u043d\u0444\u044b \u043f\u043e\u043b\u043d\u043e \u0432 \u0438\u043d\u0442\u0435\u0440\u043d\u0435\u0442\u0435. \u041c\u043e\u0436\u043d\u043e \u043f\u043e\u0447\u0438\u0442\u0430\u0442\u044c \u044d\u0442\u0438 \u0433\u0430\u0439\u0434\u044b: <a href=\"https:\/\/www.digitalocean.com\/community\/tutorials\/how-to-install-mongodb-on-ubuntu-20-04-ru\" rel=\"noopener noreferrer nofollow\">\u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430 mongodb<\/a>, <a href=\"https:\/\/www.digitalocean.com\/community\/tutorials\/node-js-debian-9-ru\" rel=\"noopener noreferrer nofollow\">\u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430 nodejs<\/a>.<\/p>\n<\/li>\n<li>\n<p>\u041a\u043b\u043e\u043d\u0438\u0440\u0443\u0435\u043c \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0439.<code>git clone https:\/\/github.com\/andaran\/appex-system<\/code>.<\/p>\n<\/li>\n<li>\n<p>\u0421\u043a\u0430\u0447\u0438\u0432\u0430\u0435\u043c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0435 \u043f\u0430\u043a\u0435\u0442\u044b. <code>npm i<\/code><\/p>\n<\/li>\n<li>\n<p>\u0421\u043e\u0437\u0434\u0430\u0435\u043c \u043a\u043e\u043d\u0444\u0438\u0433 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f. \u041f\u0440\u043e\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u043c \u0442\u0443\u0434\u0430 \u043f\u0430\u0440\u043e\u043b\u0438 \u0434\u043b\u044f \u0441\u0435\u0441\u0441\u0438\u0439, \u0431\u0430\u0437\u0443 \u0434\u0430\u043d\u043d\u044b\u0445, \u043f\u043e\u0440\u0442, \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0434\u043b\u044f smtp \u043f\u043e\u0447\u0442\u044b.\u00a0<code>nano .env<\/code><\/p>\n<pre><code># .env  # application sessionSecretKey1=********** sessionSecretKey2=********** database=mongodb:\/\/127.0.0.1\/appex port=3001  # smtp mailer mailUser=appex.system@yandex.ru mailPass=********** mailPort=465 mailHost=smtp.yandex.ru<\/code><\/pre>\n<\/li>\n<li>\n<p>\u0421\u043e\u0431\u0438\u0440\u0430\u0435\u043c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435.\u00a0<code>npm run build<\/code><\/p>\n<\/li>\n<li>\n<p>\u0417\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c!\u00a0<code>node appex<\/code><\/p>\n<\/li>\n<\/ol>\n<p>\u0425\u043e\u0442\u0435\u043b\u043e\u0441\u044c \u0431\u044b \u043e\u0431\u0440\u0430\u0442\u0438\u0442\u044c \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435 \u043d\u0430 smtp. \u0422.\u043a. \u043f\u0440\u043e\u0435\u043a\u0442 \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u043b\u0441\u044f \u0434\u043b\u044f \u043f\u0443\u0431\u043b\u0438\u043a\u0430\u0446\u0438\u0438 \u0432 \u0438\u043d\u0442\u0435\u0440\u043d\u0435\u0442\u0435, \u0434\u043b\u044f \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u0438 \u043d\u0430 \u043f\u043e\u0447\u0442\u0443 \u043f\u0440\u0438\u0445\u043e\u0434\u0438\u0442 \u043a\u043e\u0434. \u0414\u043b\u044f \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0438 \u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e \u043e\u0431\u044b\u0447\u043d\u044b\u0439 \u0430\u043a\u043a\u0430\u0443\u043d\u0442 \u044f\u043d\u0434\u0435\u043a\u0441\u0430. \u0412 \u043a\u043e\u043d\u0444\u0438\u0433\u0435 \u043d\u0443\u0436\u043d\u043e \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u043b\u043e\u0433\u0438\u043d \u0438 \u043f\u0430\u0440\u043e\u043b\u044c \u043e\u0442 \u043d\u0435\u0433\u043e.<\/p>\n<p>\u041a\u043b\u044e\u0447\u0438 \u0434\u043b\u044f \u0441\u0435\u0441\u0441\u0438\u0439 \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0435\u043c \u0440\u0430\u043d\u0434\u043e\u043c\u043d\u044b\u0435 \u0438 \u0437\u0430\u0431\u044b\u0432\u0430\u0435\u043c.<\/p>\n<p>\u041d\u0430 \u044d\u0442\u043e\u043c \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430 \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0430.<\/p>\n<\/div>\n<\/details>\n<p>\u0414\u043b\u044f \u043d\u0430\u0447\u0430\u043b\u0430 \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u0443\u0435\u043c\u0441\u044f \u0432 \u0441\u0438\u0441\u0442\u0435\u043c\u0435. \u0414\u0443\u043c\u0430\u044e, \u0441 \u044d\u0442\u0438\u043c \u0431\u0435\u0437 \u043f\u0440\u043e\u0431\u043b\u0435\u043c \u0441\u043f\u0440\u0430\u0432\u0438\u0442\u0441\u044f \u043a\u0430\u0436\u0434\u044b\u0439. \u0414\u0430\u043b\u0435\u0435 \u0412\u0430\u043c \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u0435\u0434\u043b\u043e\u0436\u0435\u043d\u043e \u043f\u0440\u043e\u0439\u0442\u0438 \u043e\u0431\u0443\u0447\u0435\u043d\u0438\u0435. \u041f\u043e\u0441\u043b\u0435 \u0435\u0433\u043e \u043f\u0440\u043e\u0445\u043e\u0436\u0434\u0435\u043d\u0438\u044f \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u0438\u0441\u0442\u0443\u043f\u0430\u0442\u044c \u043a \u0440\u0430\u0431\u043e\u0442\u0435.<\/p>\n<figure class=\"float\"><figcaption>\u041c\u0435\u043d\u044e \u043f\u0440\u043e\u0435\u043a\u0442\u043e\u0432<\/figcaption><\/figure>\n<p>\u0414\u043b\u044f \u0412\u0430\u0441 \u0443\u0436\u0435 \u0441\u043e\u0437\u0434\u0430\u0434\u0443\u0442\u0441\u044f \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0438 \u043a\u043e\u043c\u043d\u0430\u0442\u0430 \u043a \u043d\u0435\u043c\u0443. \u0418\u0445 \u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c. \u0416\u043c\u0435\u043c \u043d\u0430 \u0437\u043d\u0430\u0447\u043e\u043a \u043b\u0430\u043c\u043f\u043e\u0447\u043a\u0438, \u0447\u0442\u043e\u0431\u044b \u043e\u0442\u043a\u0440\u044b\u0442\u044c \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440 \u043a\u043e\u0434\u0430. \u0412 \u043d\u0435\u043c \u0441\u0432\u0435\u0440\u0445\u0443 \u0435\u0441\u0442\u044c \u0441\u0442\u0440\u043e\u043a\u0430 &#171;\u041f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u0442\u044c\u0441\u044f \u043a \u043a\u043e\u043c\u043d\u0430\u0442\u0435&#187;. \u041f\u0440\u0438 \u043d\u0430\u0432\u0435\u0434\u0435\u043d\u0438\u0438 \u043d\u0430 \u043d\u0435\u0451 \u0432\u044b\u043b\u0435\u0437\u0435\u0442 \u043c\u0435\u043d\u044e, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u0443\u0436\u0435 \u0431\u0443\u0434\u0443\u0442 \u0432\u043f\u0438\u0441\u0430\u043d\u044b \u0434\u0430\u043d\u043d\u044b\u0435 \u0441\u043e\u0437\u0434\u0430\u043d\u043d\u043e\u0439 \u043a\u043e\u043c\u043d\u0430\u0442\u044b. \u041c\u043e\u0436\u043d\u043e \u043e\u0442\u043a\u0440\u044b\u0442\u044c \u044d\u043c\u0443\u043b\u044f\u0442\u043e\u0440, \u043f\u043e\u0436\u043c\u0430\u043a\u0430\u0442\u044c \u043d\u0430 \u043a\u043d\u043e\u043f\u043a\u0443 \u0438 \u0443\u0431\u0435\u0434\u0438\u0442\u044c\u0441\u044f, \u0447\u0442\u043e \u0432\u0441\u0451 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442.<\/p>\n<p> \u0422\u0435\u043f\u0435\u0440\u044c \u0437\u0430\u0439\u043c\u0435\u043c\u0441\u044f \u0434\u043e\u043f\u0438\u043b\u0438\u0432\u0430\u043d\u0438\u0435\u043c \u043a\u043e\u0434\u0430. \u0427\u0442\u043e\u0431\u044b \u0431\u044b\u043b\u043e \u0443\u0434\u043e\u0431\u043d\u0435\u0435 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c, \u043c\u043e\u0436\u0435\u0442\u0435 \u043d\u0430\u0436\u0430\u0442\u044c Alt + V. \u041a\u043e\u0434 \u043e\u0442\u043a\u0440\u043e\u0435\u0442\u0441\u044f \u043d\u0430 \u0432\u0435\u0441\u044c \u044d\u043a\u0440\u0430\u043d.<\/p>\n<p>\u0414\u043e\u043f\u043e\u043b\u043d\u0438\u043c \u0432\u0435\u0440\u0441\u0442\u043a\u0443 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f. \u0412 \u043f\u0440\u0430\u0432\u043e\u043c \u0432\u0435\u0440\u0445\u043d\u0435\u043c \u0443\u0433\u043b\u0443 \u044d\u043a\u0440\u0430\u043d\u0430 \u0431\u0443\u0434\u0435\u0442 \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u044c\u0441\u044f \u0438\u043d\u0434\u0438\u043a\u0430\u0442\u043e\u0440 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f \u043b\u0430\u043c\u043f\u044b \u043a \u0441\u0435\u0442\u0438 \u0438 \u0440\u0435\u0436\u0438\u043c \u043e\u0431\u044b\u0447\u043d\u043e\u0439 \u043b\u0430\u043c\u043f\u044b. \u0415\u0441\u043b\u0438 \u0432\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u044d\u0442\u043e\u0442 \u0440\u0435\u0436\u0438\u043c, \u0442\u043e \u043f\u043e\u0441\u043b\u0435 \u043f\u043e\u0434\u0430\u0447\u0438 \u044d\u043b\u0435\u043a\u0442\u0440\u0438\u0447\u0435\u0441\u0442\u0432\u0430 \u043d\u0430 \u043b\u0430\u043c\u043f\u0443 \u043e\u043d\u0430 \u0437\u0430\u0433\u043e\u0440\u0438\u0442\u0441\u044f \u043d\u0435 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e \u043e\u0442 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0432\u0438\u0440\u0442\u0443\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0432\u044b\u043a\u043b\u044e\u0447\u0430\u0442\u0435\u043b\u044f.<\/p>\n<p>\u0412 .app-wrap \u0432 \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u0435 data-theme \u0443\u043a\u0430\u0436\u0435\u043c \u0446\u0432\u0435\u0442 \u0441\u0442\u0430\u0442\u0443\u0441 \u0431\u0430\u0440\u0430 \u0442\u0435\u043b\u0435\u0444\u043e\u043d\u0430 \u043f\u0440\u0438 \u043e\u0442\u043a\u0440\u044b\u0442\u0438\u0438 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f. \u0415\u0449\u0451 \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u0433\u043e\u0442\u043e\u0432\u044b\u0439 \u043f\u0440\u0435\u0441\u0435\u0442 \u0432\u044b\u043a\u043b\u044e\u0447\u0430\u0442\u0435\u043b\u044f. \u041e \u043f\u0440\u0435\u0441\u0435\u0442\u0430\u0445 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u043e \u0432 <a href=\"https:\/\/www.appex-system.ru\/doc#presets\" rel=\"noopener noreferrer nofollow\">\u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438<\/a> \u043f\u0440\u043e\u0435\u043a\u0442\u0430.<\/p>\n<details class=\"spoiler\">\n<summary>HTML<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"xml\"> &lt;!-- \u043e\u0431\u0435\u0440\u0442\u043a\u0430 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f --> &lt;div class=\"app-wrap\"      data-role=\"config\"      data-theme=\"rgba(239, 239, 239)\">          &lt;div class=\"tools-wrap\">         &lt;div class=\"indicator\" id=\"indicator\">&lt;\/div>         [[Switch id=\"switch\"]]    &lt;\/div>          &lt;!-- ----------------- -->          &lt;div class=\"center-block\">                  &lt;!-- \u043a\u0440\u0443\u0436\u043e\u043a \u0437\u0430 \u043a\u043d\u043e\u043f\u043a\u043e\u0439 -->         &lt;div class=\"app-button-wrap\" id=\"app-button-wrap\">              &lt;!-- \u043a\u043d\u043e\u043f\u043a\u0430 -->             &lt;div class=\"app-button\" id=\"app-button\">                  &lt;!-- \u0438\u043a\u043e\u043d\u043a\u0430 -->                 [[Icon name=\"faPowerOff\"]]             &lt;\/div>         &lt;\/div>     &lt;\/div> &lt;\/div><\/code><\/pre>\n<\/div>\n<\/details>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043d\u0430\u043f\u0438\u0448\u0435\u043c \u0441\u0442\u0438\u043b\u0438. \u0422\u0443\u0442 \u043d\u0438\u0447\u0435\u0433\u043e \u043d\u0435\u043e\u0431\u044b\u0447\u043d\u043e\u0433\u043e.<\/p>\n<details class=\"spoiler\">\n<summary>CSS<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"css\"> \/* \u043e\u0431\u0435\u0440\u0442\u043a\u0430 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f *\/ .app-wrap {     height: 100vh;     display: flex;     justify-content: center;     align-items: center; }  \/* \u043a\u0440\u0443\u0436\u043e\u043a \u0437\u0430 \u043a\u043d\u043e\u043f\u043a\u043e\u0439 *\/ .app-button-wrap {     width: 120px;     height: 120px;     background: #c8d6e5;     border-radius: 50%;     display: flex;     justify-content: center;     align-items: center;     opacity: 0.8;     transition: .5s;     margin: auto; }  \/* \u043a\u043d\u043e\u043f\u043a\u0430 *\/ .app-button {     width: 110px;     height: 110px;     background: white;     border-radius: 50%;     color: #c8d6e5;     display: flex;     justify-content: center;     align-items: center;     font-size: 32px;     transition: .1s; }  \/* \u043a\u043d\u043e\u043f\u043a\u0430 \u043f\u0440\u0438 \u043a\u043b\u0438\u043a\u0435 *\/ .app-button:active {     transform: scale(.98); }  .center-block {     display: flex;     justify-content: center;     align-items: center; }  .indicator {     width: 24px;     height: 24px;      border-radius: 50%;     background: #ccc; }  #switch {     width: auto;     height: auto; }  .tools-wrap {     position: absolute;     top: 5px;     right: 5px;     display: flex;     align-items: center; }  .appex-preset-switch__handle {     width: 40px;     height: 24px; }  .appex-preset-switch__handle:after {     box-shadow: none;        height: 20px;     width: 20px;     margin-left: -16px; }  .appex-preset-switch__input:checked + .appex-preset-switch__handle {     background: #00d2d3; }      .appex-preset-switch__input:checked + .appex-preset-switch__handle:after {     margin-right: -16px; } <\/code><\/pre>\n<\/div>\n<\/details>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0441\u0430\u043c\u043e\u0435 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u043e\u0435 &#8212; js \u043a\u043e\u0434 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f. <\/p>\n<ol>\n<li>\n<p>\u0414\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u043e\u0431\u044a\u0435\u043a\u0442 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f \u0441 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f\u043c\u0438 \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e.<\/p>\n<pre><code class=\"javascript\">\/* \u043d\u0430\u0447\u0430\u043b\u044c\u043d\u043e\u0435 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 *\/ App.state = {   status: true,     isOnline: true,     autoEnable: false, }<\/code><\/pre>\n<\/li>\n<li>\n<p>\u041e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u043c \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438. <\/p>\n<pre><code class=\"javascript\">\/* \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 *\/ App.settings = {   awaitResponse: true, }<\/code><\/pre>\n<\/li>\n<li>\n<p>\u041d\u0430\u0445\u043e\u0434\u0438\u043c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0435 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u044b \u0438 \u0432\u0435\u0448\u0430\u0435\u043c \u043d\u0430 \u043d\u0438\u0445 \u0441\u043b\u0443\u0448\u0430\u0442\u0435\u043b\u0438 \u0441\u043e\u0431\u044b\u0442\u0438\u044f. \u041d\u043e\u0432\u043e\u0435 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043c\u0435\u0442\u043e\u0434\u0430 <code>App.send();<\/code><\/p>\n<pre><code class=\"javascript\">\/* \u0432\u0435\u0448\u0430\u0435\u043c \u0441\u043b\u0443\u0448\u0430\u0442\u0435\u043b\u0438 \u0441\u043e\u0431\u044b\u0442\u0438\u0439 *\/ button.addEventListener('click', () => { App.send({ status: !App.state.status });   window.navigator.vibrate(40); });  swtch.addEventListener('change', e => { App.send({ autoEnable: e.target.checked }); });<\/code><\/pre>\n<\/li>\n<li>\n<p>\u0414\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0443 \u043d\u0430 \u043e\u043d\u043b\u0430\u0439\u043d. \u041a\u0430\u0436\u0434\u044b\u0435 10 \u0441\u0435\u043a\u0443\u043d\u0434 \u043c\u0435\u043d\u044f\u0435\u043c \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u043e isOnline \u043d\u0430 false. \u0415\u0441\u043b\u0438 \u0432 \u0442\u0435\u0447\u0435\u043d\u0438\u0435 3 \u0441\u0435\u043a\u0443\u043d\u0434 \u043b\u0430\u043c\u043f\u0430 \u043d\u0435 \u043e\u043f\u0440\u043e\u0432\u0435\u0440\u0433\u0430\u0435\u0442 \u044d\u0442\u043e, \u0433\u0430\u0441\u0438\u043c \u0438\u043d\u0434\u0438\u043a\u0430\u0442\u043e\u0440 \u043e\u043d\u043b\u0430\u0439\u043d\u0430.<\/p>\n<pre><code class=\"javascript\">\/* \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u043d\u0430 \u043e\u043d\u043b\u0430\u0439\u043d *\/ setInterval(() => {     App.send({ isOnline: false });     setTimeout(() => {         if (!App.state.isOnline) {             indicator.style.backgroundColor = '#ccc';         }     }, 3000); }, 10000);<\/code><\/pre>\n<\/li>\n<li>\n<p>\u041f\u043e\u0434\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u043c\u0441\u044f \u043d\u0430 \u0441\u043e\u0431\u044b\u0442\u0438\u0435 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f. \u041f\u0440\u0438 \u043f\u0440\u0438\u0445\u043e\u0434\u0435 \u043d\u043e\u0432\u043e\u0433\u043e \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f \u043c\u0435\u043d\u044f\u0435\u043c \u0432\u043d\u0435\u0448\u043d\u0438\u0439 \u0432\u0438\u0434 \u0432\u0441\u0435\u0445 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u043d\u0430 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0439.<\/p>\n<pre><code class=\"javascript\">\/* \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f *\/ App.on('update', state => {   if (state.status) {     button.style.color = '#00d2d3';     wrap.style.backgroundColor = '#00d2d3';   } else {     button.style.color = '#c8d6e5';     wrap.style.backgroundColor = '#c8d6e5';   }        swtch.querySelector('input').checked = state.autoEnable;       if (state.isOnline) {     indicator.style.backgroundColor = '#00d2d3';   } });<\/code><\/pre>\n<\/li>\n<li>\n<p>\u0417\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435. \u041d\u0430 \u044d\u0442\u043e\u043c \u0441 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u0435\u043c \u043a\u043e\u0434\u0430 \u043f\u043e\u0434 \u043d\u0435\u0433\u043e \u043c\u044b \u0437\u0430\u043a\u043e\u043d\u0447\u0438\u043b\u0438.<\/p>\n<pre><code class=\"javascript\">\/* \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 *\/ App.start();<\/code><\/pre>\n<\/li>\n<\/ol>\n<details class=\"spoiler\">\n<summary>\u0421\u043a\u0440\u0438\u043d\u0448\u043e\u0442 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f<\/summary>\n<div class=\"spoiler__content\">\n<figure class=\"full-width\"><figcaption><\/figcaption><\/figure>\n<\/div>\n<\/details>\n<h2>\u041f\u0438\u0448\u0435\u043c \u043a\u043e\u0434 \u0434\u043b\u044f \u043c\u0438\u043a\u0440\u043e\u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u0430<\/h2>\n<p>\u0412 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u043c\u0438\u043a\u0440\u043e\u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u0430 \u0431\u044b\u043b \u0432\u0437\u044f\u0442 \u043f\u043e\u043f\u0443\u043b\u044f\u0440\u043d\u044b\u0439 esp-01. \u041a \u043d\u0435\u043c\u0443 \u0434\u043e\u043a\u0443\u043f\u0438\u043b \u0442\u0430\u043a\u0438\u0435 <a href=\"https:\/\/aliexpress.ru\/item\/1005001898935382.html?algo_pvid=4b9715ab-ad5b-417e-aac9-a2a0101d0357&amp;algo_expid=4b9715ab-ad5b-417e-aac9-a2a0101d0357-0&amp;btsid=0b8b034116274797812615512ef138&amp;ws_ab_test=searchweb0_0,searchweb201602_,searchweb201603_\" rel=\"noopener noreferrer nofollow\">\u0440\u0435\u043b\u0435<\/a> \u0438 <a href=\"https:\/\/aliexpress.ru\/item\/4001252926156.html?algo_pvid=63ffa007-5613-44f1-b1c9-ac4bbc732ef4&amp;algo_expid=63ffa007-5613-44f1-b1c9-ac4bbc732ef4-10&amp;btsid=0b8b034116274800357112148ef138&amp;ws_ab_test=searchweb0_0,searchweb201602_,searchweb201603_\" rel=\"noopener noreferrer nofollow\">\u0431\u043b\u043e\u043a \u043f\u0438\u0442\u0430\u043d\u0438\u044f<\/a>. <\/p>\n<p>\u041f\u0438\u043b\u0438\u043c \u043f\u0440\u043e\u0448\u0438\u0432\u043a\u0443 \u0438 \u0437\u0430\u043b\u0438\u0432\u0430\u0435\u043c \u0447\u0435\u0440\u0435\u0437 arduino ide.<\/p>\n<details class=\"spoiler\">\n<summary>\u041f\u0440\u043e\u0448\u0438\u0432\u043a\u0430<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"cpp\"> \/\/ \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0435 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 #include &lt;ESP8266WiFi.h> #include &lt;ArduinoJson.h> #include &lt;WebSocketsClient.h> #include &lt;SocketIOclient.h> #include &lt;string> #include &lt;unordered_map>  SocketIOclient socketIO;    \/*   ---==== \u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 ====---   *\/  #define ussid \"\"  \/\/ \u0418\u043c\u044f wifi #define pass \"\"  \/\/ \u041f\u0430\u0440\u043e\u043b\u044c wifi #define roomID \"\"  \/\/ ID \u043a\u043e\u043c\u043d\u0430\u0442\u044b #define roomPass \"\"  \/\/ \u041f\u0430\u0440\u043e\u043b\u044c \u043a\u043e\u043c\u043d\u0430\u0442\u044b  \/*   ------------------------   *\/  \/*    \u042f \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0434\u043e\u043b\u0433\u043e \u0438\u0441\u043a\u0430\u043b \u0441\u043f\u043e\u0441\u043e\u0431\u044b \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438 \u0432 c++,   \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0431\u0443\u0434\u0443\u0442 \u0431\u043e\u043b\u044c\u0448\u0435 \u0432\u0441\u0435\u0433\u043e \u043f\u043e\u0445\u043e\u0436\u0438 \u043d\u0430 \u043e\u0431\u044a\u0435\u043a\u0442 js (\u043c\u044b \u0432\u0435\u0434\u044c \u043f\u0430\u0440\u0441\u0438\u043c json).   std::unordered_map - \u0441\u0430\u043c\u044b\u0439 \u043f\u043e\u0434\u0445\u043e\u0434\u044f\u0449\u0438\u0439, \u0442.\u043a. \u0438\u0437 \u043d\u0435\u0433\u043e \u043c\u043e\u0436\u043d\u043e \u0432\u044b\u0442\u044f\u043d\u0443\u0442\u044c \u0438\u043b\u0438   \u0438\u0437\u043c\u0435\u043d\u0438\u0442\u044c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430, \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u043f\u0435\u0440\u0435\u0434\u0430\u043d\u043e \u0447\u0435\u0440\u0435\u0437 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u0443\u044e.   \u042d\u0442\u043e \u0434\u0430\u0435\u0442 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0432\u044b\u0431\u043e\u0440\u043e\u0447\u043d\u043e \u043e\u0431\u043d\u043e\u0432\u043b\u044f\u0442\u044c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0432\u043e \u0432\u0440\u0435\u043c\u044f    \u043f\u0430\u0440\u0441\u0438\u043d\u0433\u0430 json`\u0430.     [!!!] \u0414\u0430\u043d\u043d\u044b\u0439 \u0441\u043f\u0438\u0441\u043e\u043a \u0434\u043e\u043b\u0436\u0435\u043d \u043f\u043e\u043b\u043d\u043e\u0441\u0442\u044c\u044e \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0432\u043e\u0432\u0430\u0442\u044c          \u043e\u0431\u044a\u0435\u043a\u0442\u0443 App.state \u0432 \u043a\u043e\u0434\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f.         \u0422\u0430\u043a\u0436\u0435 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u043e \"lastChange\" - \u043e\u043d\u043e \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442         \u0432\u0440\u0435\u043c\u044f \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0435\u0433\u043e \u043e\u0431\u0440\u0430\u0449\u0435\u043d\u0438\u044f \u043a \u043a\u043e\u043c\u043d\u0430\u0442\u0435.    *\/  std::unordered_map&lt;std::string, std::string> receivedState = {   { \"status\", \"true\" },   { \"isOnline\", \"true\" },   { \"lastChange\", \"0\" },   { \"autoEnable\", \"false\" } };  bool light = LOW;    \/*   ---==== \u0424\u0443\u043d\u043a\u0446\u0438\u044f \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f ====---   *\/  void updateParams(String messageType) {    \/*          \u0418\u043c\u0435\u043d\u043d\u043e \u0432 \u044d\u0442\u043e\u0439 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u043d\u043e\u0432\u043e\u0435 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435.     \u041a \u0441\u043e\u0436\u0430\u043b\u0435\u043d\u0438\u044e, \u0432\u0441\u0435 \u0442\u0438\u043f\u044b \u0434\u0430\u043d\u043d\u044b\u0445 \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u0443\u044e\u0442\u0441\u044f \u0432 \u0441\u0442\u0440\u043e\u043a\u0438,     \u043d\u043e \u0437\u0430\u043f\u0430\u0440\u0441\u0438\u0442\u044c \u0447\u0438\u0441\u043b\u043e \u0438\u0437 \u0441\u0442\u0440\u043e\u043a\u0438 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u044e\u0442 \u0432\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u044b\u0435     \u0430\u0440\u0434\u0443\u0438\u043d\u043e\u0432\u0441\u043a\u0438\u0435 \u043c\u0435\u0442\u043e\u0434\u044b.         *\/    String status = receivedState.at(\"status\").c_str();   String online = receivedState.at(\"isOnline\").c_str();   String autoEnable = receivedState.at(\"autoEnable\").c_str();      \/* \u0432\u043a\u043b\u044e\u0447\u0430\u0435\u043c \u043b\u0430\u043c\u043f\u0443 *\/   if (status == \"true\" &amp;&amp; messageType != \"connectSuccess\") {     light = LOW;     Serial.println(\"RELAY ON\");   }       \/* \u0432\u044b\u043a\u043b\u044e\u0447\u0430\u0435\u043c \u043b\u0430\u043c\u043f\u0443 *\/   if (status == \"false\" &amp;&amp; messageType != \"connectSuccess\") {     light = HIGH;     Serial.println(\"RELAY OFF\");   }    \/* \u043f\u043e\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0430\u0435\u043c, \u0447\u0442\u043e \u043b\u0430\u043c\u043f\u0430 \u0432 \u0441\u0435\u0442\u0438 *\/   if (online == \"false\") {     DynamicJsonDocument doc(1024);     JsonObject sendState = doc.createNestedObject();     sendState[\"isOnline\"] = true;     message(\"updateState\", sendState);   }     \/* \u0432\u043a\u043b\u044e\u0447\u0430\u0435\u043c \u043b\u0430\u043c\u043f\u0443 \u043f\u0440\u0438 \u0440\u0435\u0436\u0438\u043c\u0435 \u0430\u0432\u0442\u043e\u0432\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f *\/   if (messageType == \"connectSuccess\" &amp;&amp; autoEnable == \"true\") {     DynamicJsonDocument doc(1024);     JsonObject sendState = doc.createNestedObject();     sendState[\"status\"] = true;     message(\"updateState\", sendState);   } }    \/*   ---==== \u0421\u043e\u0431\u044b\u0442\u0438\u044f ====---   *\/  void socketIOEvent(socketIOmessageType_t type, uint8_t * payload, size_t length) {   switch (type) {     case sIOtype_DISCONNECT: {         Serial.println(\"[IOc] \u041e\u0448\u0438\u0431\u043a\u0430 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f!\\n\");     <\/code><\/pre>\n<\/div>\n<\/details>\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-404139","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/404139","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=404139"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/404139\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=404139"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=404139"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=404139"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}