Есть Iskra JS и WiFi (Troyka-модуль). Решил сделать устройство, которое можно настроить перед использованием. Для тех, кто не в курсе, что такое Captive portal - это, пока устройство не знает к какой точке доступа цепляться, оно создает свою и ждет, что ты к ней подключишься и настроишь нужные параметры. При этом хочется, чтобы при подключении к точке доступа устройства ты сразу попадал на страницу настройки без перехода в браузер и прочих неудобств. На форуме Амперки нашел тему с кодом для Arduino. Есть обсуждение на esp8266.ru. Еще есть хорошая статья Амперкота. Из них я понял, что надо перехватывать DNS-запросы. Пошел искать дальше. На гитхабе нашел решение под Espruino с продолжениями (обсуждение, решение 1, решение 2, решение 3, описание 3) на ту же тему. Судя по скринам, они даже когда-то работали. Правда, там подключались с iOS. Решение 3 у меня не взлетело, поскольку использует функции, которых уже нет в эспруиновском модуле "Wifi" (сам модуль тоже переименовался). Решение 2 отличается от первого двумя необязательными наворотами, поэтому я решил попробовать решение 1. После небольшой доработки получил следующий результат. Точка доступа создается, вешается web-сервер на 80-й порт и UDP-сокет на 53-й порт. (Правда, почему-то UDP-сокет сразу закрывается. Если Web-сервер не создавать, то не закрывается.) К точке доступа подключаюсь, но открытия страницы с "Hello World" не происходит. Пробовал с андроида и с винды. Судя по логам, DNS не отрабатывает переадресацию. Логи при запуске Искры: Код (Text): Wifi setup successfull AP created HTTP init DNS init Socket bound - {"type":2,"opt":{},"port":53,"sckt":6,"conn":true} Socket closed - no error Socket closed - no error При подключении с винды ничего не происходит. При подключении с андроида пишет следующее: Код (Text): HTTP request - { "type":1, "res":{ "sckt":1, "headers":{"Connection":"close"} }, "svr":{ "type":1, "port":80, "sckt":6 }, "sckt":1, "hdrs":true, "dRcv":"", "headers":{ "Connection":"close", "User-Agent":"Dalvik/2.1.0 (Linux; U; Android 14; SM-A525F Build/UP1A.231005.007)", "Host":"192.168.4.1", "Accept-Encoding":"gzip" }, "cRcv":0, "method":"GET", "url":"/" } HTTP response HTTP response - { "sckt":1, "headers":{"Connection":"close"}, "dSnd":"HTTP/1.1 200 OK\r\nServer: Espruino 2v13.5586\r\nConnection: close\r\nContent-Type: text/html\r\n\r\n<html><body><H1>Hello World</H1></body></html>", "cls":true } Пробовал комментировать startDNSServer(), результат тот же. Кто понимает, в чем может быть проблема? Подскажите, плз. Ниже доработанный мною код. Код (Javascript): // Captive Portal PrimarySerial.setup(115200); var Wifi = require('@amperka/wifi'); var http = require('http'); var dgram = require('dgram'); var socketUDP = dgram.createSocket('udp4'); var SSID = 'CaptivePortalTest'; var authMode = 'wpa2_psk'; var password = '1234567890'; var portHTTP = 80; var portDNS = 53; var dnsIPStr = '192.168.4.1'; var dnsIP = dnsIPStr.split('.').map(n => String.fromCharCode(parseInt(n, 10))).join(''); var page = '<html><body><H1>Hello World</H1></body></html>'; // get Query name out of message // offset = 12 // end \x00 function dnsQname(msg) { var i = 12; var qname = ''; while ( msg[i] !== '\x00' ) { qname += msg[i]; i++; } return qname + '\x00'; } /* 1. line header 2. line query 3. line resource */ function dnsResponse(msg,dns_ip){ return msg[0]+msg[1] + '\x81\x80'+'\x00\x01'+'\x00\x01'+'\x00\x00\x00\x00' + dnsQname(msg) + '\x00\x01' + '\x00\x01' + '\xc0\x0c'+'\x00\x01'+'\x00\x01'+'\x00\x00\x00\xf9'+'\x00\x04' + dns_ip ; } function startDNSServer(port){ socketUDP.on('error', (err) => { console.log('Socket error - ' + err); socketUDP.close(); }); socketUDP.on('close', (had_err) => { console.log('Socket closed - ' + (had_err ? 'with error' : 'no error')); }); socketUDP.on('message', (msg, info) => { console.log('DNS request'); // we only serve ip4 if ( msg[msg.length-3] === '\x01') { console.log('DNS response'); socketUDP.send(dnsResponse(msg,dnsIP),info.port,info.address); } }); console.log('DNS init'); socketUDP.bind(port, (res) => { console.log('Socket bound - ' + JSON.stringify(res)); }); } // start http server function startHttpServer(port){ var webServer = http.createServer(function (req, res) { console.log('HTTP request - ' + JSON.stringify(req)); accept = req.headers.Accept || ''; if (accept !== '*\/*') { console.log('HTTP response'); res.writeHead(200, {'Content-Type': 'text/html'}); res.end(page); } else { // redirect to the Setup page console.log('HTTP redirect'); res.writeHead(302, {'Location': 'http://192.168.4.1', 'Content-Type': 'text/plain'}); res.end(); } console.log('HTTP response - ' + JSON.stringify(res)); }); console.log('HTTP init'); webServer.listen(port); } // start beeing a access point function startAccessPoint(ssid,authMode, password, callback){ //Wifi.startAP(ssid,{authMode: authMode, password: password}, callback); var wifi = Wifi.setup(PrimarySerial, function(err) { if (err) print('Wifi setup error: ' + err); else print('Wifi setup successfull'); wifi.createAP(ssid, password, 1, authMode, callback); }); } function start(){ startAccessPoint(SSID,authMode,password,function(err) { if (err) console.log('AP creating error - ' + err); else { console.log('AP created'); startHttpServer(portHTTP); startDNSServer(portDNS); } }); } setTimeout(start,1000);
Унас тоже падает udp soscket, не сразу, но мин через 15.Там в прошивее от амперки кривпя библиотека с сокетами. Мы ее ручками правили. У амперки оф прошивка на сайте 2.13, она уже сильно устарела. У гордона в текущих версиях которве ощутимо новее пофиксен этот баг. Но раз в некотороевремя в райне15 мин отваливается. Одновременно поднимается websocket и mqtt publishers/resder. Подключается к AP на Raspberry. Разбираемся в чем причина и на чьей стороне. Кстати и в WebSocket юиблиотеки был косяк, в новых вроде тоже исправлнно.