• Система автоматизации с открытым исходным кодом на базе esp8266/esp32 микроконтроллеров и приложения IoT Manager. Наша группа в Telegram

Отправляем GET запросы на страницы сайта

Кирилл

New member
Продолжаю ковыряться с ESP8266.
Получилось подключиться к Wi-Fi
и стал вопрос в отправки запросов на интернет страницу. https://site.my/home/in.php
Пока не представляю как это сделать...
Хотелось бы отправить запрос, так, что бы страница отправила полученные данные в БД.
Насколько я понимаю мне надо сделать страницу с публичной переменной, в которую я буду записывать полученный пакет.

С GET запросами пока вообще не знаком, поэтому плохо представляю что к чему, помогите составить запрос на отправку в переменную:

Код:
function sendData()
print("Sending data to https://site.my/home/in.php")
conn=net.createConnection(net.TCP, 1) -- TCP>>отправка, 1>>ssl
 

conn:on("site.my", function(conn, payload) print(payload) end)
-- https://site.my/home/in.php 111.111.111.111
conn:connect(443,'111.111.111.111') 
conn:send("GET site.my/home/" .. t1 .. " HTTP/1.1\r\n Host: 111.111.111.111:443\r\n")
conn:send("GET /in.php?key=YOURAPIKEY&field1="..t.." HTTP/1.1\r\n")
conn:send("Host: site.my\r\n")
conn:send("Accept: */*\r\n")
conn:send("User-Agent: Mozilla/4.0 (compatible; esp8266 Lua; Windows NT 5.1)\r\n")
conn:send("\r\n")
conn:on("sent",function(conn)
                      print("Closing connection")
                      conn:close()
                  end)
conn:on("disconnection", function(conn)
                                print("Got disconnection...")
  end)
end
Как написать это правильно ?

t - переменная которая передаем
YOURAPIKEY - имя переменной в php файле
 

JustACat

Moderator
Команда форума
Кирилл, еще можете локальный сервер на ПК прямо поднять: http://www.denwer.ru/
Там можно будет что угодно создавать и отлаживать.
Например, можно будет создать на вашем локальном сервере тот самый файл in.php, например, с таким содержимым:
PHP:
<?
file_put_contents($_SERVER["DOCUMENT_ROOT"]."/_get-".date("H-i-s").".txt", print_r($_GET,true));
file_put_contents($_SERVER["DOCUMENT_ROOT"]."/_post-".date("H-i-s").".txt", print_r($_POST,true));
file_put_contents($_SERVER["DOCUMENT_ROOT"]."/_request-".date("H-i-s").".txt", print_r($_REQUEST,true));
file_put_contents($_SERVER["DOCUMENT_ROOT"]."/_globals-".date("H-i-s").".txt", print_r($GLOBALS,true));
print 'OK: '.date("H-i-s");
?>
И дальше к нему обращаться с вашей ESP, и в файлах генерируемых видеть, что прилетает.

PS: справочник по всем функциям php: http://php.net/manual/ru/index.php
 

Кирилл

New member
и в файлах генерируемых видеть, что прилетает.
Пошел более простым способом https://www.hurl.it/
написал страничку и принял в нее переменную (длинный набор переменных в одну строку) типа
Код:
data1=1&data2=2&data3=3&data4=4&data45=5&data6=6&
накатал в PHP страничку которая ловит это и записывает в БД
но не просто а с помощью формул и запросов, а вот теперь думаю,
может ли модуль считать квадратный корень и выполнять округление дробных чисел, конечно подразумеваю деление, умножение и вычитание со сложением?

Я думаю на основе сложного расчета выводить ключ который будет рассчитываться на сервере и на модуле, а затем сравниваться, так сказать защита от подбора, что бы хакером не докопаться до истины. Это всего лишь одна из защит сделав в которой ошибку сервер считает до 3-5 ошибок и блокирует пользователя по IP.
справочник по всем функциям php
Я в курсе этого хорошего ресурса, но у меня более глобально, пока я на пишу на основе Wordpress с отдельно БД, что бы не изобретать защиту, как новый велосипед.
еще можете локальный сервер на ПК прямо поднять
Сервер тоже реальны, показалось так проще, ведь домене с SSL
 

lsat

New member
conn=net.createConnection(net.TCP, 1)
У вас нормально проходят соединения через https? Я перепробовал разные прошивки: 0.9.5, 0.9.6, но у меня не проходит. С помощью wireshark вижу, что проблема в Failure handshake.
NodeMCU использует TLSv1.1, который включён на сервере. Есть предположения в чём ошибка?
 

jmms

Moderator
Команда форума
Пошел более простым способом https://www.hurl.it/
написал страничку и принял в нее переменную (длинный набор переменных в одну строку) типа
Код:
data1=1&data2=2&data3=3&data4=4&data45=5&data6=6&
накатал в PHP страничку которая ловит это и записывает в БД
но не просто а с помощью формул и запросов, а вот теперь думаю,
может ли модуль считать квадратный корень и выполнять округление дробных чисел, конечно подразумеваю деление, умножение и вычитание со сложением?

Я думаю на основе сложного расчета выводить ключ который будет рассчитываться на сервере и на модуле, а затем сравниваться, так сказать защита от подбора, что бы хакером не докопаться до истины. Это всего лишь одна из защит сделав в которой ошибку сервер считает до 3-5 ошибок и блокирует пользователя по IP.

Я в курсе этого хорошего ресурса, но у меня более глобально, пока я на пишу на основе Wordpress с отдельно БД, что бы не изобретать защиту, как новый велосипед.

Сервер тоже реальны, показалось так проще, ведь домене с SSL
А о какой защите идет речь? Если я правильно понял, то ESP таки может гонять трафик по защищенным протоколам, здесь отпадает вариант перехвата данных по пути следования.

Тогда другой вопрос: где необходима защита, если на PHP странице, тогда достаточно API-ключа чтобы отбрасывать данные от "левых" людей (клиентов).

Какие еще есть варианты защиты? Мне просто это тоже интересно. Я склоняюсь, что все данные должны ходить по защищенному протоколу, а доморощенные методы шифрования, хоть и эффективны, но действительно зачем изобретать велосипед?
 

pvvx

Активный участник сообщества
У вас нормально проходят соединения через https? Я перепробовал разные прошивки: 0.9.5, 0.9.6, но у меня не проходит. С помощью wireshark вижу, что проблема в Failure handshake.
NodeMCU использует TLSv1.1, который включён на сервере. Есть предположения в чём ошибка?
В версии SDK 1.1.1 ещё есть ошибки с SSL, а что уж говорить о SDK 0.9.5, на которой базируется NodeMCU. В каждом новом SDK всегда приписано, что исправлена очередная ошибка работы espconn, через которую и происходит связь в NodeMCU.
Тем более как работать с инет, если буфер у NodeMCU меньше размера MSS инет-пакета TCP/UDP ?
Да и проект NodeMCU заброшен - никаких обновлений, кроме выпуска под шумиху модулей с чипом...
 

jmms

Moderator
Команда форума
В версии SDK 1.1.1 ещё есть ошибки с SSL, а что уж говорить о SDK 0.9.5, на которой базируется NodeMCU. В каждом новом SDK всегда приписано, что исправлена очередная ошибка работы espconn, через которую и происходит связь в NodeMCU.
Тем более как работать с инет, если буфер у NodeMCU меньше размера MSS инет-пакета TCP/UDP ?
Да и проект NodeMCU заброшен - никаких обновлений, кроме выпуска под шумиху модулей с чипом...
Как обстоят дела при разработке прошивок на C++, каким образом можно реализовать защищенный протокол общения устройство-сервер в таком случае? Очень интересует данный вопрос.
 

pvvx

Активный участник сообщества
Как обстоят дела при разработке прошивок на C++, каким образом можно реализовать защищенный протокол общения устройство-сервер в таком случае? Очень интересует данный вопрос.
Очень просто - через подключение ssl либы к собственному интерфейсу работы с Lwip. Данные либы - open-source и ошибок не имеют.
Поспрашивайте в темах "Дурино" может там уже реализовали. Дурины не работают через китай-глюк-espconn которая является прослойкой между пользовательским приложением и LwIP в китай-SDK. АрДурины работают напрямую с LwIP.
 
Последнее редактирование:
  • Like
Реакции: jmms

artmasterpro

New member
Пытаюсь выполнить 2 действия, подключится к сети и отправить GET запрос
Код:
wifi.setmode(wifi.STATION)

wifi.sta.config("xxx","xxx")

wifi.sta.connect();
print (wifi.sta.getip())

tmr.delay(5000)

tmr.alarm(1,5000, 1, function()
    if wifi.sta.getip()== nil then
        print("IP unavaiable, Waiting...")
        print (wifi.sta.getip())
         collectgarbage();
    else
        tmr.stop(1)
        
       --  collectgarbage();
        print("Config done, IP is "..wifi.sta.getip())
    
        --dofile ("get.lua")

  conn=net.createConnection(net.TCP, false)
conn:on("receive", function(conn, pl) print(pl) end)
conn:connect(80,'xxx.com')
conn:send("GET /zap.php?key=button1 HTTP/1.1\r\n")
conn:send("Host: xxx.com\r\n")
conn:send("Accept: */*\r\n")
conn:send("User-Agent: Mozilla/4.0 (compatible; esp8266 Lua; Windows NT 5.1)\r\n")
conn:send("\r\n")

         wifi.sta.disconnect()
    end
end)
Как следствие на выходе GET запрос или вообще не отправляется, или выдает вот такую ошибку
DNS retry 1!
DNS retry 2!
DNS retry 3!
DNS retry 4!
DNS Fail!

Причем если запрос отправлять GET запрос отдельно из ESPlorer
тогда все работает как нужно. Если собираю все в один скрипт. не работает.
Подскажите пожалуйста, что не так делаю?
 

r0va

New member
попробуйте вместо xxx.com указать IP сервера, тогда обращения к DNS не будет.
 

mishgan

Member
Как отправлять запросы на сервер понятно, а вот как получить то что сервер ответил? Дайте пожалуйста ссылочку на пример
 

hash

New member
Mishgan, лови...
Код:
pages = {}

pages["/logo.png"] = function(request)
    file.open("logo.png")
     X = file.read()
     file.close()
     return X , "image/png"
    end

pages["/err.gif"] = function(request)
    file.open("err.gif")
     X = file.read()
     file.close()
     return X , "image/gif"
    end

pages["/ok.gif"] = function(request)
    file.open("ok.gif")
     X = file.read()
     file.close()
     return X , "image/gif"
    end

pages["/help.htm"] = function(request)
    file.open("help.htm")
     X = file.read()
     file.close()
     return X
    end

parseRequest = function(request)
    _, _, method, url = string.find(request, "(%a+)%s([^%s]+)")
    _, _, path, queryString = string.find(url, "([^%s]+)%?([^%s]+)")
    if queryString then
      query = {}
      for name, value in string.gfind(queryString, "([^&=]+)=([^&=]+)") do
        query[name] = value
      end
    else
      path = url
      query = nil
    end
    return {method = method, url = url, path = path, query = query, queryString = queryString}
end


srv=net.createServer(net.TCP)
srv:listen(80,function(conn)
    conn:on("receive",function(conn,payload)
        request = parseRequest(payload)
        print(request.method, request.url)

      if pages[request.path] then
        local response = pages[request.path](request)
        headers = "HTTP/1.1 200 OK\r\nConnection: keep-alive\r\nCache-Control: private, no-store\r\nContent-Length: " .. string.len(response) .. "\r\n\r\n"
        conn:send(headers .. response)
      else
        conn:send("HTTP/1.1 200 OK\r\n")
        conn:send("Connection: close\r\n\r\n")
        conn:send("<html><head><body>")

        file.open("body.htm","r")
        conn:send(file.read())
        file.close()

        conn:send("</body></head></html>\r\n")
      end
        conn:close() collectgarbage("collect") end)
    end)
строка из браузера : http://xxx.xxx.xxx.xxx/uart?cfg.baud=9600&cfg.bits=8&cfg.parity=0&cfg.stops=1
Код:
ucfg={}
ucfg.baud = 115200
ucfg.bits = 8
ucfg.parity = 0
ucfg.stops = 1

srv=net.createServer(net.TCP)
srv:listen(80,function(conn)
    conn:on("receive",function(conn,request)
        local conf_page = ""
        conf_page = ""..string.sub(request,string.find(request,"GET")+5,string.find(request,"GET")+8)
        local _, _, method, path, vars = string.find(request, "([A-Z]+) (.+)?(.+) HTTP");
        if(method == nil)then
            _, _, method, path = string.find(request, "([A-Z]+) (.+) HTTP");
        end
        local _GET = {}
        --print("cmd:"..conf_page)
        if (vars ~= nil)then
            for k, v in string.gmatch(vars, "(%w+)=(%w+)&*") do
                _GET[k] = v
                --print("param: "..k..", value: ".._GET[k])
            end
        end

        if (conf_page == "uart")then
            ucfg.baud = _GET.baud
            ucfg.bits = _GET.bits
            ucfg.parity = _GET.parity
            ucfg.stops = _GET.stops
        end
     
        conn:send("HTTP/1.1 200 OK\r\n")
        conn:send("Connection: close\r\n\r\n")
        conn:send("<html><head><body>")

        conn:send("<form action='uart'>")
        conn:send("<table border='1' width='300'><tr><th colspan='2'><p style='color: #333399'>UART Settings</p></th></tr>")
        conn:send("<tr><td>Baud Rate<td><center><input type='text' name=cfg.baud' size='20' value='"..ucfg.baud.."'></tr>")
        conn:send("<tr><td>Data Bits<td><center><input type='text' name='cfg.bits' size='20' value='"..ucfg.bits.."'></tr>")
        conn:send("<tr><td>Parity<td><center><input type='text' name='cfg.parity' size='20' value='"..ucfg.parity.."'></tr>")
        conn:send("<tr><td>Stop Bits<td><center><input type='text' name='cfg.stops' size='20' value='"..ucfg.stops.."'></tr>")
        conn:send("<tr><td colspan='2'><p style='text-align: center'><button type='submit'>Save</button></tr>")
        conn:send("</table></form>")
        conn:send("</body></head></html>\r\n")

     conn:close() collectgarbage("collect") end)
end)

Добавил: код для версии 0.9.5
 
Последнее редактирование:

Nurmukhamed

New member
Добрый день.
я собрал свой термометр, пытаюсь отправить данные thingspeak, но не работает отсылка данных на сервер.
начал изучать информацию по проблеме, пишут, что нет возможности отправлять запрос размером больше, чем 512 байт. рекомендуют отправлять по порядку. помогите, у кого есть рабочий скрипт отправки данных на сервер thingspeak.

Код:
print('init.lua ver 1.2')
wifi.setmode(wifi.STATION)
print('set mode=STATION (mode='..wifi.getmode()..')')
print('MAC: ',wifi.sta.getmac())
print('chip: ',node.chipid())
print('heap: ',node.heap())
-- wifi config start
wifi.sta.config("wifi","XXXXXXXX")
-- wifi config end
tmr.alarm(1, 1000, 1, function()
        if wifi.sta.getip()== nil then
                print("IP unavaiable, Waiting...")
        else
                tmr.stop(1)
        print("ESP8266 mode is: " .. wifi.getmode())
        print("The module MAC address is: " .. wifi.ap.getmac())
        print("Config done, IP is "..wifi.sta.getip())
        end
end)
-- GPIO pin connected to data on DHT22
pin = 2
-- Source in secrets.lua, if present
l = file.list()
if l['secrets.lua'] then
  dofile('secrets.lua')
end
function getTemp() --[[
     Input: <none>
     Output: temperature (celcius), humidity
     Notes:
      - uses nodemcu dht library
      - retries until status is OK (checksum is correct)
      - when using FLOAT firmware, _decimal variables are not needed
     --]]
    temp = -5000
    humi = -5000
    status,temp,humi,temp_decimial,humi_decimial = dht.readxx(pin)
    ---[[ Print out values for debugging
    print (string.format("Temperature: %.2fC", temp))
    print (string.format("Humidity: %.2f", humi))
    --]]
    if (status ~= dht.OK) then
      print('error reading DHTxx, will retry in 5s')
    end
  return temp,humi
end
function thingspeakPost(temp, humi) --[[
    Input: temperature, humidity
    Output: <none>
    Notes:
      - ensure that TS_KEY is a valid thingspeak API key!
    --]]
  -- conecting to thingspeak.com
  print("Sending data to thingspeak.com")
  conn = nil
  conn=net.createConnection(net.TCP, 0)
  conn:on("receive", function(conn, payload)
        if (string.find(payload, "Status: 200 OK") ~= nil ) then
                print("Posted OK");
        end
        print(payload)
  end)
  conn:on("connection", function (conn, payload)
        print("Posting...")
        conn:send(string.format('GET /update?key=XXXXXXXXXXXXXXXX&field3=%.2f&field4=%.2f HTTP/1.1\r\n',temp,umi))
        conn.send('Host: api.thingspeak.com\r\n')
        conn.send('Accept: */*\r\n')
        conn.send('User-Agent: Mozilla/4.0 (compatible; esp8266 Lua; Windows NT 5.1)\r\n')
        conn.send('\r\n')
  end)
--  conn:on("sent",function(conn)
--                        print("Closing connection")
--                        conn:close()
--                      collectgarbage()
--                    end)
  conn:on("disconnection", function(conn)
                        print("Got disconnection...")
                        conn:close()
                        collectgarbage()
    end)
  -- api.thingspeak.com 184.106.153.149
  conn:connect(80,'api.thingspeak.com')
end
--- Get temp and send data to thingspeak.com
function sendData()
  -- get data from the DHT22
  temp, humi = getTemp()
  thingspeakPost(temp, humi)
end

function readADC_avg()                 -- read 10 consecutive values and calculate average.
    ad1 = 0
    i=0
    while (i<10) do
        ad1=ad1+adc.read(0)*4/978 --calibrate based on your voltage divider AND Vref!
        print(ad1)
        i=i+1
    end
    ad1 = ad1/10
    print(ad1)
    return ad1
end
------ MAIN ------
-- send data every X ms to thing speak
tmr.alarm(1, 60000, 1, function() sendData() end)
 

mishgan

Member
Mishgan, лови...
Код:
pages = {}

pages["/logo.png"] = function(request)
    file.open("logo.png")
     X = file.read()
     file.close()
     return X , "image/png"
    end

pages["/err.gif"] = function(request)
    file.open("err.gif")
     X = file.read()
     file.close()
     return X , "image/gif"
    end

pages["/ok.gif"] = function(request)
    file.open("ok.gif")
     X = file.read()
     file.close()
     return X , "image/gif"
    end

pages["/help.htm"] = function(request)
    file.open("help.htm")
     X = file.read()
     file.close()
     return X
    end

parseRequest = function(request)
    _, _, method, url = string.find(request, "(%a+)%s([^%s]+)")
    _, _, path, queryString = string.find(url, "([^%s]+)%?([^%s]+)")
    if queryString then
      query = {}
      for name, value in string.gfind(queryString, "([^&=]+)=([^&=]+)") do
        query[name] = value
      end
    else
      path = url
      query = nil
    end
    return {method = method, url = url, path = path, query = query, queryString = queryString}
end


srv=net.createServer(net.TCP)
srv:listen(80,function(conn)
    conn:on("receive",function(conn,payload)
        request = parseRequest(payload)
        print(request.method, request.url)

      if pages[request.path] then
        local response = pages[request.path](request)
        headers = "HTTP/1.1 200 OK\r\nConnection: keep-alive\r\nCache-Control: private, no-store\r\nContent-Length: " .. string.len(response) .. "\r\n\r\n"
        conn:send(headers .. response)
      else
        conn:send("HTTP/1.1 200 OK\r\n")
        conn:send("Connection: close\r\n\r\n")
        conn:send("<html><head><body>")

        file.open("body.htm","r")
        conn:send(file.read())
        file.close()

        conn:send("</body></head></html>\r\n")
      end
        conn:close() collectgarbage("collect") end)
    end)
строка из браузера : http://xxx.xxx.xxx.xxx/uart?cfg.baud=9600&cfg.bits=8&cfg.parity=0&cfg.stops=1
Код:
ucfg={}
ucfg.baud = 115200
ucfg.bits = 8
ucfg.parity = 0
ucfg.stops = 1

srv=net.createServer(net.TCP)
srv:listen(80,function(conn)
    conn:on("receive",function(conn,request)
        local conf_page = ""
        conf_page = ""..string.sub(request,string.find(request,"GET")+5,string.find(request,"GET")+8)
        local _, _, method, path, vars = string.find(request, "([A-Z]+) (.+)?(.+) HTTP");
        if(method == nil)then
            _, _, method, path = string.find(request, "([A-Z]+) (.+) HTTP");
        end
        local _GET = {}
        --print("cmd:"..conf_page)
        if (vars ~= nil)then
            for k, v in string.gmatch(vars, "(%w+)=(%w+)&*") do
                _GET[k] = v
                --print("param: "..k..", value: ".._GET[k])
            end
        end

        if (conf_page == "uart")then
            ucfg.baud = _GET.baud
            ucfg.bits = _GET.bits
            ucfg.parity = _GET.parity
            ucfg.stops = _GET.stops
        end
    
        conn:send("HTTP/1.1 200 OK\r\n")
        conn:send("Connection: close\r\n\r\n")
        conn:send("<html><head><body>")

        conn:send("<form action='uart'>")
        conn:send("<table border='1' width='300'><tr><th colspan='2'><p style='color: #333399'>UART Settings</p></th></tr>")
        conn:send("<tr><td>Baud Rate<td><center><input type='text' name=cfg.baud' size='20' value='"..ucfg.baud.."'></tr>")
        conn:send("<tr><td>Data Bits<td><center><input type='text' name='cfg.bits' size='20' value='"..ucfg.bits.."'></tr>")
        conn:send("<tr><td>Parity<td><center><input type='text' name='cfg.parity' size='20' value='"..ucfg.parity.."'></tr>")
        conn:send("<tr><td>Stop Bits<td><center><input type='text' name='cfg.stops' size='20' value='"..ucfg.stops.."'></tr>")
        conn:send("<tr><td colspan='2'><p style='text-align: center'><button type='submit'>Save</button></tr>")
        conn:send("</table></form>")
        conn:send("</body></head></html>\r\n")

     conn:close() collectgarbage("collect") end)
end)

Добавил: код для версии 0.9.5
Не совсем понял где тут отправка запросов на сервер
 
Сверху Снизу