Есть ли способ, чтобы сервер Arduino отправлял существующий файл .html клиенту Arduino? - PullRequest
0 голосов
/ 25 января 2019

Я создаю одностраничное приложение для Arduino.Он графически отображает аналоговые значения контактов на планшете, подключенном к Wi-Fi.

Я создал эскиз, но хочу его почистить.Я смог загрузить скетч в мое (Uno Wifi Rev 2) Arduino, инициализировать Wifi и подключиться к нему с помощью планшета.Я могу отправить статическую страницу "рамка" на планшет.Этот статический фрейм может запрашивать и получать значения аналоговых выводов Arduino, используя объект XMLHttpRequest.

Но отправка громоздкой статической страницы неуклюжа.Учебники делают такие вещи, как,

client.println("<html><body>");
client.println("Hello World!");
client.println("</body></html>");

Я пытался стать хитрым и создать заголовочный файл FileText.h:

#define constFileText=
"<html><body>"
"Hello World!"
"</body></html>";

и объединить это с:

#include "FileText.h"
client.println(constFileText);

Я хотел бы создать стандартный файл FileText.html:

Hello World!

И обработайте его следующим образом:

ifstream hFile ("FileText.html");
while (getline(hFile, strLine))
  client.println(strLine);

Это значительно упростит редактирование html-файла.Это исключило бы необходимость включения всех этих вызовов serial.println.Это также устранит ограничение максимальной длины для постоянных значений.

Есть ли способ предоставить текстовый файл компилятору Arduino и заставить сервер Arduino отправлять его клиенту Arduino?

Ответы [ 3 ]

0 голосов
/ 27 января 2019

C ++ имеет «необработанные строковые литералы». Вы можете поместить постоянную строку, без экранирования специальных символов, в исходный код между открывающим и закрывающим «тегом». Вы можете выбрать тег, который будет отсутствовать в необработанной строке. В следующем примере это тег =====.

const char* s1 = R"=====(Hello
"World")=====";

совпадает с

const char* s2 = "Hello\n\"World\"";

Таким образом, вы можете поместить ваши большие строки в отдельные файлы .h и включить их. На AVR используйте PROGMEM для экономии оперативной памяти.

0 голосов
/ 28 января 2019

Вооружившись форматом @jfowkes (но не @Juraj), я создал программу на Python. Работает как в Windows, так и в Linux.

Чтобы использовать его, поместите все текстовые файлы (для меня .html и .js) в подкаталог эскиза. Затем из папки эскизов запустите python TextEncode.py "SubdirectoryName". Добавьте линию #include "SubdirectoryName.h" в начале эскиза. Этот заголовочный файл включает в себя функцию void SendPage(WiFiClient hClient), которая отправляет содержимое файлов в подкаталоге клиенту; позвоните, когда это уместно.

(Он отправляет файлы в алфавитном порядке, поэтому я ставлю файлы перед такими номерами, как «F210». Я считаю файлы модулями. Имея много таких модулей, я могу отключать модули, выборочно комментируя код. На самом деле у меня есть два модуля разработки [.js и .html] и один производственный модуль [a .js], у меня есть копия функции SendPage в главном эскизе. Выборочно комментируя код, я могу выбирать, стоит ли Я хочу увидеть результаты вызовов функции XMLHttpRequest.)

Я знаю, что это намного сложнее, чем любое из предложенных решений, но это помогает циклу разработки: (1) Редактировать код html / js в моей любимой IDE (2) запустить программу python (3) compile эскиз.

Вот содержимое моего TextEncode.py:

# program to convert text files to file with constant array of ascii code of file characters
# converted file is to be used by Arduino compiler to efficiently send html/js code to Arduino
# Usage:
# 1) place files to be encoded into subfolder, "ClientHtml"
# 2) from console, 'python TextEncode.py "ClientHtml"'.
# 

import os
import sys
import binascii

c_nCharsPerLine = 16
strFolderIn = sys.argv[1]
astrPseudos = []                                        # array of file pseudonyms.  to be used to create inclusive [ClientHtml].h 
if len(sys.argv) > 2:
    strClientHandle = sys.argv[2]
else:
    strClientHandle = "hClient"

for strFileIn in os.listdir(strFolderIn):
# encode each file in subdirectory
# it is easier to re encode every file than it is to check timestamps to re encode only updated files
    strFilePseudo = strFileIn.replace (".", "_")        # to be used in name of encoded file and name of variable with contents of file.
    astrPseudos.append(strFilePseudo)
    strContents = "";                                   # contents read from file itself, in pairs of hex digits

    with open(strFolderIn + "/" + strFileIn, "r") as fileIn:
        nChar = 0;
        for strLineIn in fileIn:
            for chIn in strLineIn:
#               strContents = strContents + chIn.encode("hex") + ","        # works on Linux
                strContents = strContents + hex(ord(chIn)) + ","
                nChar += 1
                if nChar % c_nCharsPerLine == 0:
                    strContents += "\n"
    # truncate trailing \n, if it exists
    if nChar % c_nCharsPerLine == 0:
        strContents = strContents[:-1]
    strContents += "0\n"

    with open (strFilePseudo + ".h", "w") as fileOut:
        fileOut.write("const unsigned char c_" + strFilePseudo + "[] = {\n")
#       fileOut.write("unsigned char c_" + strFilePseudo + "[] = {\n")
        fileOut.write(strContents)
        fileOut.write("};\n")

with open (strFolderIn + ".h", "w") as fileOut:
    fileOut.write("// .h files with encoded files to be included:\n")
    astrPseudos.sort()
    for strFilePseudo in astrPseudos:
        fileOut.write("#include \"" + strFilePseudo + ".h\"\n")
    fileOut.write("/*\n")
    fileOut.write("// Arduino Compiler function to send encoded files to web client:\n")
    fileOut.write("// Comment these out if you don't want to use the functionality\n")
    fileOut.write("void SendPage(WiFiClient " + strClientHandle + ")\n")
    fileOut.write("{\n")
    fileOut.write(" String strData;\n")
    for strFilePseudo in astrPseudos:
        fileOut.write(" strData=c_" + strFilePseudo + ";\n")
        fileOut.write(" " + strClientHandle + ".println(strData);\n")
    fileOut.write("}\n")
    fileOut.write("*/\n")
0 голосов
/ 25 января 2019

Вы можете использовать инструмент xxd для генерации включаемого файла из вашего HTML.Например, дать файл test.html:

<html><body>
Hello World!
</body></html>

Использование xxd -i test.html > test_html.h приводит к test_html.h, содержащему:

unsigned char test_html[] = {
  0x3c, 0x68, 0x74, 0x6d, 0x6c, 0x3e, 0x3c, 0x62, 0x6f, 0x64, 0x79, 0x3e,
  0x0d, 0x0a, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x57, 0x6f, 0x72, 0x6c,
  0x64, 0x21, 0x0d, 0x0a, 0x3c, 0x2f, 0x62, 0x6f, 0x64, 0x79, 0x3e, 0x3c,
  0x2f, 0x68, 0x74, 0x6d, 0x6c, 0x3e
};
unsigned int test_html_len = 42;

Затем вы можете #include "test_html.h" в своем эскизе и передатьмассив до client.print().Это позволяет обойти ограничения на размер строки.К сожалению, вы теряете возможность циклически перебирать массив, поэтому вам придется написать функцию, которая сделает это самостоятельно, если потребуется.

xxd - инструмент * nix,но есть порты Windows , если вам нужен.

...